mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 15:19:10 +02:00
* code mode * update uv.lock for monty optional dep 🤖 Generated with Claude Code * retry CI * Address PR review comments on CodeMode transform 🤖 Generated with Claude Code Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix ty unresolved-attribute error on search_helper 🤖 Generated with Claude Code Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * more idiomacy * harden * fix docs * harden * fix red CI * Refactor CodeMode to use CatalogTransform base class Removes the duplicate ContextVar bypass pattern in favor of the shared CatalogTransform machinery. Also fixes a pre-existing bug where `from __future__ import annotations` caused NameError for Annotated in nested function scopes at runtime. * Remove redundant _get_visible_tools wrapper in CodeMode * Rewrite CodeMode docs with proper motivation and structure * Fix type narrowing in collision test * Stop unwrapping tool results in CodeMode's call_tool call_tool() inside execute blocks now returns structured content as-is, preserving the {"result": value} wrapping. This means the output schema shown in search results accurately describes what call_tool() returns, so LLMs can trust the schema when writing code. Also adds examples/code_mode/ with a server and narrated client demo. * Simplify call_tool return type: dict | str * Fix example client to unwrap structured results * Let server resolve tool versions instead of pinning first match * Rewrite CodeMode docs to match current behavior * Rename optional extra from monty to code-mode --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Jeremiah Lowin <153965+jlowin@users.noreply.github.com>
84 lines
1.9 KiB
Python
84 lines
1.9 KiB
Python
"""Example: CodeMode transform — search and execute tools via code.
|
|
|
|
CodeMode replaces the entire tool catalog with two meta-tools: `search`
|
|
(keyword-based tool discovery) and `execute` (run Python code that chains
|
|
tool calls in a sandbox). This dramatically reduces round-trips and
|
|
context window usage when an LLM needs to orchestrate many tools.
|
|
|
|
Requires pydantic-monty for the sandbox:
|
|
pip install "fastmcp[code-mode]"
|
|
|
|
Run with:
|
|
uv run python examples/code_mode/server.py
|
|
"""
|
|
|
|
from fastmcp import FastMCP
|
|
from fastmcp.experimental.transforms import CodeMode
|
|
|
|
mcp = FastMCP("CodeMode Demo")
|
|
|
|
|
|
@mcp.tool
|
|
def add(a: int, b: int) -> int:
|
|
"""Add two numbers together."""
|
|
return a + b
|
|
|
|
|
|
@mcp.tool
|
|
def multiply(x: float, y: float) -> float:
|
|
"""Multiply two numbers."""
|
|
return x * y
|
|
|
|
|
|
@mcp.tool
|
|
def fibonacci(n: int) -> list[int]:
|
|
"""Generate the first n Fibonacci numbers."""
|
|
if n <= 0:
|
|
return []
|
|
seq = [0, 1]
|
|
while len(seq) < n:
|
|
seq.append(seq[-1] + seq[-2])
|
|
return seq[:n]
|
|
|
|
|
|
@mcp.tool
|
|
def reverse_string(text: str) -> str:
|
|
"""Reverse a string."""
|
|
return text[::-1]
|
|
|
|
|
|
@mcp.tool
|
|
def word_count(text: str) -> int:
|
|
"""Count the number of words in a text."""
|
|
return len(text.split())
|
|
|
|
|
|
@mcp.tool
|
|
def to_uppercase(text: str) -> str:
|
|
"""Convert text to uppercase."""
|
|
return text.upper()
|
|
|
|
|
|
@mcp.tool
|
|
def list_files(directory: str) -> list[str]:
|
|
"""List files in a directory."""
|
|
import os
|
|
|
|
return os.listdir(directory)
|
|
|
|
|
|
@mcp.tool
|
|
def read_file(path: str) -> str:
|
|
"""Read the contents of a file."""
|
|
with open(path) as f:
|
|
return f.read()
|
|
|
|
|
|
# CodeMode collapses all 8 tools into just `search` + `execute`.
|
|
# The LLM discovers tools via keyword search, then writes Python
|
|
# scripts that chain multiple tool calls in a single round-trip.
|
|
mcp.add_transform(CodeMode())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
mcp.run()
|