Skip to content

Add experimental CodeMode transform#3297

Open
aaazzam wants to merge 10 commits intomainfrom
code-mode
Open

Add experimental CodeMode transform#3297
aaazzam wants to merge 10 commits intomainfrom
code-mode

Conversation

@aaazzam
Copy link
Collaborator

@aaazzam aaazzam commented Feb 25, 2026

Closes #3296

Summary

Adds CodeMode, an experimental transform inspired by Cloudflare's Code Mode that collapses a large tool surface into two meta-tools: search (inspect tool metadata via Python) and execute (chain call_tool(...) invocations in Python). Useful when LLMs need to plan multi-step workflows against many tools without listing them all in context.

Changes

  • New fastmcp.experimental.transforms.CodeMode transform with pluggable SandboxProvider protocol
  • Default MontySandboxProvider backed by pydantic-monty (new fastmcp[monty] optional dep)
  • Supports custom tool names/descriptions, default arguments, search helpers, and respects disabled/auth-gated tools
  • Documentation at docs/servers/transforms/code-mode.mdx
  • 10 test cases with an in-process sandbox provider

Design notes

Placed under fastmcp.experimental.transforms since this is an experimental API. The sandbox provider is a protocol so third-party runtimes (remote sandboxes, WASM, etc.) can plug in without changes to the transform itself.

@marvin-context-protocol marvin-context-protocol bot added feature Major new functionality. Reserved for 2-4 significant PRs per release. Not for issues. server Related to FastMCP server implementation or server-side functionality. labels Feb 25, 2026
🤖 Generated with Claude Code
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 73cd76babc

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@marvin-context-protocol
Copy link
Contributor

marvin-context-protocol bot commented Feb 25, 2026

Test Failure Analysis

Summary: The ty (type checker) static analysis step failed with one type error in the new code_mode.py file: tool.version is str | None but call_tool's version parameter expects VersionSpec | None.

Root Cause: In src/fastmcp/experimental/transforms/code_mode.py:359, the code passes tool.version (a str | None) directly to ctx.fastmcp.call_tool(..., version=tool.version). However, call_tool's version parameter has type VersionSpec | None (defined in src/fastmcp/utilities/versions.py). These types are incompatible.

Suggested Solution:

In src/fastmcp/experimental/transforms/code_mode.py:

  1. Import VersionSpec:
from fastmcp.utilities.versions import VersionSpec
  1. Wrap tool.version in a VersionSpec at line 359:
# Before
result = await ctx.fastmcp.call_tool(
    tool.name, merged, version=tool.version
)

# After
result = await ctx.fastmcp.call_tool(
    tool.name, merged, version=VersionSpec(eq=tool.version) if tool.version is not None else None
)
Detailed Analysis

Failed step: ty check in the Run prek step of the static_analysis job.

Log excerpt:

error[invalid-argument-type]: Argument to bound method `call_tool` is incorrect
   --> src/fastmcp/experimental/transforms/code_mode.py:359:40
    |
358 |                 result = await ctx.fastmcp.call_tool(
359 |                     tool.name, merged, version=tool.version
    |                                        ^^^^^^^^^^^^^^^^^^^^ Expected `VersionSpec | None`, found `str | None`
360 |                 )
    |
info: Element `str` of this union is not assignable to `VersionSpec | None`

call_tool signature (from src/fastmcp/server/server.py:897):

async def call_tool(
    self,
    name: str,
    arguments: dict[str, Any] | None = None,
    *,
    version: VersionSpec | None = None,  # <-- expects VersionSpec, not str
    run_middleware: bool = True,
    task_meta: None = None,
) -> ...

VersionSpec (from src/fastmcp/utilities/versions.py:28):

@dataclass
class VersionSpec:
    gte: str | None = None
    lt: str | None = None
    eq: str | None = None  # exact version match

The loq (file size) violations shown in the log are not enforced and pre-exist across the repository — they are not the cause of the failure.

Related Files
  • src/fastmcp/experimental/transforms/code_mode.py:359 — where the type mismatch occurs (needs fix)
  • src/fastmcp/server/server.py:892-897call_tool overload definition showing version: VersionSpec | None
  • src/fastmcp/utilities/versions.py:28VersionSpec dataclass definition

🤖 Automated triage via Claude Code · edited to reflect latest analysis

aaazzam and others added 5 commits February 25, 2026 15:18
🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Major new functionality. Reserved for 2-4 significant PRs per release. Not for issues. server Related to FastMCP server implementation or server-side functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add experimental CodeMode transform

1 participant