MCP: One Server, Three Different AI Agents
The architecture is straightforward: the MCP server acts as the provider, and the agents act as clients. They communicate via JSON over stdio. A critical technical detail for anyone building these: since stdout is the communication channel, you cannot use print() for debugging in your server code—you must log to stderr, or you'll break the protocol.
Deployment Structure
The project layout looks like this:
nb2lite-agent-claude/
├── MCP/
│ └── server.py # The MCP server (Gemini wrapper)
├── python/
│ └── agent.py # Consumer 1: Google ADK agent
├── rust/
│ └── main.rs # Consumer 2: Rust CLI client
└── .mcp.json # Consumer 3: Config for Claude CodeImplementation Deep Dive
I used FastMCP from the official mcp Python package. It simplifies tool creation by using decorators; the function's docstring and type hints actually become the documentation the LLM uses to understand when to call the tool.
Here is the basic implementation of the image generation tool:
from mcp.server.fastmcp import FastMCPmcp = FastMCP("NB2Lite Agent")
@mcp.tool()
def generate_image(
prompt: str, aspect_ratio: str = "1:1", thinking_level: str = "low"
) -> str:
"""Generates a new image from a text prompt."""
# Gemini API logic goes here
...
The server provides four specific tools:
By centralizing the logic in server.py, I only have to maintain the Gemini API integration in one place, regardless of which agent is triggering the request. It's a much cleaner AI workflow than hard-coding tool logic into every individual agent.