Support `resources/subscribe` for MCP resources as a client (resource notification subscriptions)

Open 💬 3 comments Opened Mar 29, 2026 by alejandro5042

What variant of Codex are you using?

CLI, Desktop App, IDE Extensions

What feature would you like to see?

Feature: Codex should support subscribing to MCP resources (resources/subscribe) as an MCP client

Problem

Codex currently implements listing and reading MCP resources as a client (resources/list, resources/read, and resources/templates/list) but does not support subscribing to resource notifications via resources/subscribe or resources/unsubscribe or handling notifications/resources/updated and related events as a client.

This means:

  • Resource caches in Codex can get stale with no way to keep them up to date when MCP servers change or publish new resources.
  • Live update scenarios relying on the MCP spec for resource change invalidation (see MCP spec "Server Resources" section) aren't functional -- even though the underlying SDK provides the wire format.
  • There's no extension point for users to auto-inject dynamic context into messages[] without modifying codex-rs source. MCP resource subscriptions would naturally fill this gap.
Current state

(This was AI-assisted.)

| MCP Capability | Codex Support | Location |
|---|---|---|
| resources/list | ✅ via list_mcp_resources tool | mcp_resource.rs, mcp_connection_manager.rs |
| resources/read | ✅ via read_mcp_resource tool | mcp_resource.rs |
| resources/templates/list | ✅ via list_mcp_resource_templates tool | mcp_resource.rs |
| resources/subscribe | ❌ Not implemented | -- |
| resources/unsubscribe | ❌ Not implemented | -- |
| notifications/resources/updated | ⚠️ Received but only logged | logging_client_handler.rs:71-77 |
| notifications/resources/list_changed | ⚠️ Received but only logged | logging_client_handler.rs:79-81 |

Implementation plan

(This was AI-assisted.)

Phase 1: Wire up subscription lifecycle

  1. Give LoggingClientHandler (or a replacement) an event channel so on_resource_updated and on_resource_list_changed forward events to McpConnectionManager instead of just logging them.
  2. Add resources/subscribe and resources/unsubscribe client methods on McpConnectionManager using the existing rmcp wire types (SubscribeRequestParams, UnsubscribeRequestParams).
  3. During McpConnectionManager::new(), after a server reaches Ready, check if it advertises capabilities.resources.subscribe == true. If so, enumerate resources via resources/list and subscribe to all of them.

Phase 2: Resource cache invalidation

  1. Add a per-server resource cache (HashMap<String, HashMap<String, CachedResource>>) to McpConnectionManager. Populate on first list/read, invalidate entries on ResourceEvent::Updated.
  2. On ResourceEvent::ListChanged, re-issue resources/list, diff against the cached list, subscribe to new resources, unsubscribe from removed ones.

Phase 3: Auto-inject into messages[]

This is the key payoff -- subscriptions become an extension point for the model context pipeline:

  1. Add an mcp_resource_context field to TurnContextItem (URI -> content snapshot).
  2. Populate it in make_turn_context() / to_turn_context_item() from the cached subscribed resources.
  3. Add a build_mcp_resource_update_item() diff function in context_manager/updates.rs alongside the existing build_permissions_update_item, build_collaboration_mode_update_item, etc. Wire it into build_settings_update_items().
  4. Optionally, on mid-turn ResourceEvent::Updated, queue updated content via queue_response_items_for_next_turn() for immediate injection.

Phase 4: Configuration

Allow users to control subscription behavior in config.toml:

[mcp_resources]
auto_subscribe = true          # subscribe to all resources from all servers
auto_inject = true             # inject subscribed resource content into model context
max_inject_size = 8192         # cap total injected resource content (bytes)
References
Impact
  • Enables Codex agents to keep MCP resource state in sync with underlying MCP servers
  • Creates a first-class extension point for injecting dynamic context into the model -- users can write an MCP server that exposes a resource, and Codex will auto-inject updates into messages[] without any source changes
  • Reduces stale data risk and aligns Codex with MCP spec and other major clients
  • Fixes a gap identified in the closure of #4956 / PR #5239 -- subscription support was scoped out despite being part of the original design

Additional information

The initial implementation in #5239 and tracking in #4956 covered listing/reading resources, but not subscribing or notification flow in the client. See those as context for demand and scope. Current state: Codex logs resource notifications but does not act on them, and never issues subscribe/unsubscribe requests as a client.

This is about the Codex client role, not MCP server implementation.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗