Summary
buildRunToolSet takes allowAmbiguousMcpToolNamesWithoutIdentity, which defaults to false. The chat path leaves it at the default; the OpenAI-compatible and Responses paths pass true and never wire resolveMcpServerName / stampMcpServerIdentities. Tool calls persisted on those paths therefore carry no mcpServerName, and continuing the same conversation in the chat UI can drop those turns from context.
Flagged by a static analyzer on a downstream merge; verified by reading the call sites, not reproduced.
The asymmetry
packages/api/src/agents/tools.ts:
allowAmbiguousMcpToolNamesWithoutIdentity = false,
api/server/controllers/agents/client.js (chat) passes four arguments, so the flag stays false:
const toolSet = buildRunToolSet(
this.options.agent,
this.agentConfigs?.values(),
this.options.subagentTasks == null ? undefined : [Constants.CHECK_BACKGROUND_TASK],
payload,
);
api/server/controllers/agents/openai.js (~809) passes a fifth positional true:
const toolSet = buildRunToolSet(
primaryConfig,
handoffAgentConfigs.values(),
undefined,
openaiMessages,
true,
);
responses.js (~1007) does the same.
Separately, stampMcpServerIdentities and resolveMcpServerName appear only in client.js and callbacks.js. Neither openai.js nor responses.js references them.
Consequence
A run through the OpenAI-compatible or Responses endpoint persists MCP tool calls without an identity stamp. That is self-consistent while the flag is on, but the chat path reads the same history with the flag off, so delimiter-bearing historical MCP names cannot be resolved unambiguously and formatAgentMessages can strip those turns.
The visible effect would be a conversation started via API losing MCP tool-call history when continued in the UI — which reads as context loss rather than a tool-naming problem, so it seems worth an explicit decision either way.
Questions
- Is the permissive flag on the API paths deliberate, on the grounds that those runs never round-trip into the chat UI? If so a comment stating that would help, since the flag's default and these two overrides now disagree.
- If they can round-trip, wiring
resolveMcpServerName / stampMcpServerIdentities on both API paths would make the persisted history readable by the chat path.
Caveat
Static read of the three call sites and the flag default. Not reproduced against a live API-then-UI continuation.
Summary
buildRunToolSettakesallowAmbiguousMcpToolNamesWithoutIdentity, which defaults tofalse. The chat path leaves it at the default; the OpenAI-compatible and Responses paths passtrueand never wireresolveMcpServerName/stampMcpServerIdentities. Tool calls persisted on those paths therefore carry nomcpServerName, and continuing the same conversation in the chat UI can drop those turns from context.Flagged by a static analyzer on a downstream merge; verified by reading the call sites, not reproduced.
The asymmetry
packages/api/src/agents/tools.ts:api/server/controllers/agents/client.js(chat) passes four arguments, so the flag staysfalse:api/server/controllers/agents/openai.js(~809) passes a fifth positionaltrue:responses.js(~1007) does the same.Separately,
stampMcpServerIdentitiesandresolveMcpServerNameappear only inclient.jsandcallbacks.js. Neitheropenai.jsnorresponses.jsreferences them.Consequence
A run through the OpenAI-compatible or Responses endpoint persists MCP tool calls without an identity stamp. That is self-consistent while the flag is on, but the chat path reads the same history with the flag off, so delimiter-bearing historical MCP names cannot be resolved unambiguously and
formatAgentMessagescan strip those turns.The visible effect would be a conversation started via API losing MCP tool-call history when continued in the UI — which reads as context loss rather than a tool-naming problem, so it seems worth an explicit decision either way.
Questions
resolveMcpServerName/stampMcpServerIdentitieson both API paths would make the persisted history readable by the chat path.Caveat
Static read of the three call sites and the flag default. Not reproduced against a live API-then-UI continuation.