What official SDKs exist for building MCP servers, and how do they structure a minimal server?
Quick Answer
Anthropic and the MCP community maintain official SDKs in several languages, including Python (mcp, with a high-level FastMCP API), TypeScript/JavaScript (@modelcontextprotocol/sdk), Java, Kotlin, and C#, all published under the modelcontextprotocol GitHub organization. Each SDK handles the JSON-RPC framing, lifecycle handshake, and transport plumbing for you, so building a server mostly means registering tools/resources/prompts through decorators or builder methods and writing their handler logic — you rarely touch raw JSON-RPC messages directly unless you need something the high-level API doesn't expose.
Detailed Answer
The SDKs exist precisely so implementers don't have to hand-roll JSON-RPC framing, the initialize handshake, or pagination cursors themselves.
Python (FastMCP-style high-level API)
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("demo-server")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
if __name__ == "__main__":
mcp.run(transport="stdio")
TypeScript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({ name: "demo-server", version: "1.0.0" });
server.tool("add", "Add two numbers", { a: z.number(), b: z.number() },
async ({ a, b }) => ({ content: [{ type: "text", text: String(a + b) }] })
);
await server.connect(new StdioServerTransport());
What the SDK handles for you
Hand-implementing the protocol is a reasonable learning exercise, but for a real server it means re-solving problems the SDK already handles correctly and keeps updated as the spec evolves:
- Deriving
inputSchemafrom typed function signatures (Python type hints, Zod schemas in TypeScript) instead of hand-writing JSON Schema. - The full
initialize/initializedhandshake and capability negotiation. - Transport wiring — swapping
stdioforstreamable-httpis usually a one-line change, as covered in the transports section. - Pagination cursor handling for
*/listmethods, if your catalog is large enough to need it.