feat(runtime/codex): execute agent MCP/function tools via the shim#641
Merged
Conversation
yaozheng-fang
force-pushed
the
feat/codex-mcp-passthrough
branch
from
July 7, 2026 02:33
4103f22 to
412f8bf
Compare
Codex presents MCP/function tools to the model as a namespace tool that Ark rejects, and it won't route a plain function_call back to a namespaced tool. So instead of configuring tools on the Codex side, the Responses shim now advertises the agent's ADK tools to the backend as plain function tools and executes them itself in a bounded tool loop, invisibly to Codex. - New tools_bridge builds (flat function specs, executors) from the agent's tools, reusing ADK end to end: BaseToolset.get_tools (incl. MCP), BaseTool._get_declaration + _function_declaration_to_tool_param for the schema, and BaseTool.run_async for execution. - proxy runs the agent's tools in a shim-internal loop (registered per turn via set_agent_tools); the tool-less path is unchanged. Codex's own non-function tools (e.g. its hosted web_search, whose schema Ark rejects) are dropped, so Codex web search is disabled by default on a chat backend. - runtime bridges the agent's tools onto the shim and closes MCP sessions when the turn ends. Note: this also removes the opt-in web-search restoration added in fix/codex-runtime-longtask (the CODEX_SHIM_MAX_TOOL_ITERS shim web loop), keeping Codex web search off by default. The retry/timeout knobs from that change are retained. Validated end to end: an Agent(runtime=codex) with an MCPToolset pointing at a live MCP server calls the tool and answers from its result, on the bundled Codex binary (no namespace, no config flag, no binary bump).
yaozheng-fang
force-pushed
the
feat/codex-mcp-passthrough
branch
from
July 7, 2026 02:34
412f8bf to
4f0eb0c
Compare
zakahan
approved these changes
Jul 7, 2026
…rough # Conflicts: # veadk/runtime/codex/runtime.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Makes an agent's MCP and function tools usable on
runtime="codex"(against a chat backend like Ark).Why not just configure the MCP server on the Codex side?
Codex can connect to an MCP server, but it presents the tools to the model as a
type:"namespace"object, and it won't route a plainfunction_callback to a namespaced tool. On Ark that's a dead end (verified directly against/responses):/responsesfunctionnamespaceunknown tool type: namespaceNo Codex config/version reconciles this —
create_tool_spechardcodes MCP tools tonamespace, and Ark rejects that type.Approach
Don't hand the tools to Codex. The Responses shim (which already mediates every model call) advertises the agent's ADK tools to the backend as plain
functiontools and executes them itself in a bounded loop — feeding results back until the model stops calling them and returning only the final turn to Codex. Codex never sees these tools, so thenamespacepath is never taken.Changes (3 files)
tools_bridge.py(new): builds(flat function specs, executors)fromagent.tools, reusing ADK end to end —BaseToolset.get_tools(incl. MCP),BaseTool._get_declaration+ ADK's own_function_declaration_to_tool_paramfor the schema, andBaseTool.run_asyncfor execution. No schema or dispatch is reimplemented.proxy.py: runs the agent's tools in a shim-internal loop (registered per turn viaset_agent_tools); addsget_shim. The tool-less path is unchanged.runtime.py: bridges the agent's tools onto the shim; closes MCP sessions when the turn ends.Validation
End to end through the real
CodexRuntimeon the bundled Codex binary (no version bump, no config flag): anAgent(runtime="codex")with anMCPToolsetpointing at a live MCP server (get_launch_code) — the model calls the tool and answers with the secret only obtainable via the tool:FunctionTools go through the same
BaseToolpath.Notes
functiontools (its hostedweb_search, whoseexternal_web_accessfield Ark rejects) are dropped. This PR also removes the opt-in web-search restoration added infix/codex-runtime-longtask(theCODEX_SHIM_MAX_TOOL_ITERSshim web loop); the retry/timeout knobs from that change are kept.🤖 Generated with Claude Code