Skip to content

mcp: investigate FastMCP native Pydantic-typed tool registration to delete generation layer #209

@bokelley

Description

@bokelley

Context

Today src/adcp/server/mcp_tools.py maintains a list of 57 tool dicts + a runtime _generate_pydantic_schemas() pass that maps each tool name to its <ToolName>Request Pydantic model and calls .model_json_schema() at import. This works, but it reinvents what FastMCP already does when you register a tool function with Pydantic-typed parameters.

If FastMCP's native registration can express everything we need — descriptions, annotations (RO / MUT / DEST / IDEMP), nested Pydantic models, and the ADCPHandler delegation pattern — we could delete the generation layer entirely and the drift surface goes to zero.

What to investigate

  1. Can FastMCP's @mcp.tool decorator accept a pydantic-typed params argument directly? What does the resulting schema look like vs. our current output?
  2. How do we preserve the hand-written tool descriptions and annotations (readOnlyHint, destructiveHint, etc.) through the native path?
  3. How does this interact with ADCPHandler being a subclass hook — tools need to route to handler.<tool_name>(params, context), which is what _register_tool in src/adcp/server/serve.py does today.
  4. Compare startup cost: current design runs .model_json_schema() for all 57 tools at import (~100ms). Native registration may defer or batch this.

Acceptance

  • A short writeup (docs/design/mcp-native-registration.md or issue comment) that picks: stay with generation layer, or migrate. If migrate, follow-up PR deletes ADCP_TOOL_DEFINITIONS + _generate_pydantic_schemas() and uses FastMCP native registration.

Priority

4.1+. Architectural cleanup, not a user-visible bug.

Surfaced from: #205

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions