multi-agent-lab / src /tools /mcp_server.py
agharsallah
feat: official MCP SDK as an optional tool transport
24b5ffb
Raw
History Blame Contribute Delete
2.02 kB
"""MCP server exposing the built-in tools over the Model Context Protocol.
This is the *server* half of the optional MCP transport (ADR-0017). It wraps the
same in-process tool functions (`src/tools/builtins.py`) as MCP tools using the
official SDK's FastMCP, so a tool's behaviour is identical whether an agent
reaches it in-process or over MCP. ``oracle`` is exposed first; adding a tool is
one `@mcp.tool` decorator that delegates to the shared implementation.
Run as a stdio server::
python -m src.tools.mcp_server
The capability check still lives on the *client* side, behind the registry
(ADR-0012): this server is pure transport and trusts the registry to have already
authorised the call. ``mcp`` is a top-level import here because this module is
only ever imported when the server is being run — the package and the app import
cleanly without it (see ``src/tools/mcp_client.py`` for the lazy client side).
"""
from __future__ import annotations
from mcp.server.fastmcp import FastMCP
from src.tools.builtins import oracle as _oracle
#: Stable server name advertised to clients; also used by the client config gate.
SERVER_NAME = "multi-agent-land-tools"
def build_server() -> FastMCP:
"""Construct the FastMCP server with every exposed built-in tool registered.
Return types are annotated as ``dict[str, str]`` so FastMCP emits structured
content the client can read back without re-parsing prose; the client also
tolerates plain text JSON for robustness.
"""
mcp = FastMCP(SERVER_NAME)
@mcp.tool(
name="oracle",
description="Draw a single cryptic omen for the current scene. Params: {seed: str}.",
)
def oracle(seed: str = "") -> dict[str, str]:
"""Deterministic omen — delegates to the shared in-process implementation."""
return _oracle(seed=seed)
return mcp
def main() -> None:
"""Entry point: serve the tools over stdio JSON-RPC."""
build_server().run("stdio")
if __name__ == "__main__":
main()