Quickstart
Instrument a Python MCP server with spanly in one line.
This walks through wiring spanly into a Python MCP server. The same
pattern applies whether your server uses the high-level MCPServer from
the mcp package or the low-level Server class.
1. Install
pip install spanly2. Add monitoring
from spanly import SpanlyClientspanly_client = SpanlyClient( api_key=os.environ["SPANLY_API_KEY"],)# server = MCPServer("your-mcp-server-name", version="1.0.0")# Monitor your MCP server (one line!)spanly_client.monitor(server)# server.run()That's it – all MCP traffic on server is now reported to your Spanly
project.
SpanlyClient.monitor() patches the server's run() method to wrap the
underlying read/write streams. Call it before server.run() so the
initialize handshake is captured.
3. Set the API key
export SPANLY_API_KEY=spanly_us_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxSpanlyClient() reads SPANLY_API_KEY automatically. The region is
encoded in the key prefix and auto-detected.
Full example – stdio MCP server
import asyncio
import os
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import TextContent, Tool
from spanly import SpanlyClient
server = Server("demo-server")
@server.list_tools()
async def list_tools() -> list[Tool]:
return [Tool(name="echo", description="Echo input back", inputSchema={
"type": "object",
"properties": {"input": {"type": "string"}},
"required": ["input"],
})]
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
return [TextContent(type="text", text=arguments.get("input", ""))]
async def main() -> None:
spanly = SpanlyClient(api_key=os.environ["SPANLY_API_KEY"])
spanly.monitor(server)
async with stdio_server() as (read, write):
await server.run(read, write, server.create_initialization_options())
if __name__ == "__main__":
asyncio.run(main())Full example – high-level MCPServer
import asyncio
import os
from mcp.server.fastmcp import FastMCP
from spanly import SpanlyClient
mcp = FastMCP("demo-fastmcp")
@mcp.tool()
async def echo(input: str) -> str:
return input
spanly = SpanlyClient(api_key=os.environ["SPANLY_API_KEY"])
spanly.monitor(mcp)
if __name__ == "__main__":
mcp.run() # stdio by defaultThe SDK detects both MCPServer / FastMCP (which expose a
_lowlevel_server attribute) and the low-level Server class directly,
so the same monitor(server) call works in both cases.
Next steps
- The API reference covers the full
SpanlyClientAPI andMonitorOptions. - Examples cover async context, multi-tenant
tagging, and integration with
httpx/ FastAPI hosts. - If you'd rather not change code, the CLI wraps the same server with the same capture behavior.