Summary
This follows #259. The question that
issue left open is now settled from source: Wassette sends
notifications/tools/list_changed correctly. Codex CLI receives, deserializes,
and dispatches it, but does not connect the notification to its model-facing
tool catalogue and therefore never sends another tools/list.
This issue tracks the interoperability impact for Wassette until an upstream
Codex release fixes the client and can be verified against Wassette's dynamic
load-component flow. It is not asking Wassette to work around the client bug
in the protocol implementation.
Why track this here
Loading a component at runtime and immediately exposing its tools is a core
Wassette path. The server is conforming, but users experience the feature as
broken when their MCP client ignores the catalogue change. Keeping a focused
compatibility issue here:
- gives Wassette maintainers and users visibility into the affected client;
- gives the Codex reports independent signal that a real MCP server and workflow
hit the bug;
- records why a server-side workaround would be the wrong layer; and
- provides a place to verify the first Codex release that claims a fix.
Confirmed client-side root cause
In Codex CLI 0.149.1:
- RMCP 3.1.2 parses the message as
ServerNotification::ToolListChangedNotification.
- RMCP invalidates its own cached
tools/list response.
- RMCP dispatches the notification to Codex's
LoggingClientHandler::on_tool_list_changed.
- That handler only logs
MCP server tool list changed and returns.
- Nothing informs
codex-mcp, whose ManagedClient.tools remains the vector
captured by the startup tools/list.
- The model-facing immutable
McpBinding stays cached at the same
tool_catalog_revision.
RMCP cache invalidation is passive: it permits a fresh response if the client
later asks for tools/list; it does not send that request itself. Codex never
asks, so the loaded component remains absent from the model's tool catalogue.
The notification is therefore not lost by stdio parsing, protocol negotiation,
a subscription receiver, Plugin Runtime event routing, or app-server
indirection.
Cross-client evidence
The same Wassette binary was driven against three clients in the same harness
run:
| Client |
Protocol |
After tools/list_changed |
| Copilot CLI |
server/discover, 2026-07-28 |
re-listed after about 9 ms |
| Claude Code 2.1.241 |
initialize, 2025-11-25 |
re-listed after about 2 ms |
| Codex CLI 0.149.1 |
initialize, 2025-06-18 |
sent no subsequent tools/list |
A fresh run on 2026-08-29 reproduced the Codex result. Its only tools/list
occurred about 21 seconds before Wassette sent the notification. The session
continued afterward, ruling out a closed connection or timing race.
Codex upstream reports
The primary report, which describes the same cache-disconnection root cause, is:
Related open reports show the same behavior through other paths and versions:
The disconnect remained present in Codex 0.150.1 and in openai/codex main at
commit 0ae94fdd49b05ee7faa4d984d06a68492cb32b54 on 2026-08-28.
An unmerged community implementation exists at:
Its focused refresh test passes, but it predates Codex's current immutable
binding/catalogue-revision architecture and is not directly cherry-pickable.
A current fix must also increment tool_catalog_revision so the cached
McpBinding is replaced.
Proposed scope for this follow-up
The desired upstream fix belongs in Codex. The useful Wassette action is to
retain a clear compatibility record and independently verify the repaired
client against the server behavior that exposed it.
Summary
This follows #259. The question that
issue left open is now settled from source: Wassette sends
notifications/tools/list_changedcorrectly. Codex CLI receives, deserializes,and dispatches it, but does not connect the notification to its model-facing
tool catalogue and therefore never sends another
tools/list.This issue tracks the interoperability impact for Wassette until an upstream
Codex release fixes the client and can be verified against Wassette's dynamic
load-componentflow. It is not asking Wassette to work around the client bugin the protocol implementation.
Why track this here
Loading a component at runtime and immediately exposing its tools is a core
Wassette path. The server is conforming, but users experience the feature as
broken when their MCP client ignores the catalogue change. Keeping a focused
compatibility issue here:
hit the bug;
Confirmed client-side root cause
In Codex CLI 0.149.1:
ServerNotification::ToolListChangedNotification.tools/listresponse.LoggingClientHandler::on_tool_list_changed.MCP server tool list changedand returns.codex-mcp, whoseManagedClient.toolsremains the vectorcaptured by the startup
tools/list.McpBindingstays cached at the sametool_catalog_revision.RMCP cache invalidation is passive: it permits a fresh response if the client
later asks for
tools/list; it does not send that request itself. Codex neverasks, so the loaded component remains absent from the model's tool catalogue.
The notification is therefore not lost by stdio parsing, protocol negotiation,
a subscription receiver, Plugin Runtime event routing, or app-server
indirection.
Cross-client evidence
The same Wassette binary was driven against three clients in the same harness
run:
tools/list_changedserver/discover,2026-07-28initialize,2025-11-25initialize,2025-06-18tools/listA fresh run on 2026-08-29 reproduced the Codex result. Its only
tools/listoccurred about 21 seconds before Wassette sent the notification. The session
continued afterward, ruling out a closed connection or timing race.
Codex upstream reports
The primary report, which describes the same cache-disconnection root cause, is:
MCP tools/list_changed notification does not invalidate deferred tool cache or refetch tools/listRelated open reports show the same behavior through other paths and versions:
notifications/tools/list_changedopenai/codex#10105 — supportnotifications/tools/list_changedserver restart
MCP tools after
notifications/tools/list_changedThe disconnect remained present in Codex 0.150.1 and in
openai/codexmain atcommit
0ae94fdd49b05ee7faa4d984d06a68492cb32b54on 2026-08-28.An unmerged community implementation exists at:
Its focused refresh test passes, but it predates Codex's current immutable
binding/catalogue-revision architecture and is not directly cherry-pickable.
A current fix must also increment
tool_catalog_revisionso the cachedMcpBindingis replaced.Proposed scope for this follow-up
server-side protocol workaround is required.
user visibility and upstream signal.
dynamic
load-component, if that is appropriate for current Wassettedocumentation.
claims a fix.
refresh before closing this compatibility issue.
The desired upstream fix belongs in Codex. The useful Wassette action is to
retain a clear compatibility record and independently verify the repaired
client against the server behavior that exposed it.