An MCP server is a small program that exposes tools, resources, or prompts. You can write one in under 100 lines of TypeScript or Python. Most of the work is thinking about what to expose and how.
Anthropic maintains official MCP SDKs in:
@modelcontextprotocol/sdkmcpCommunity SDKs exist for Go, Rust, Java, and more. The protocol is simple enough to implement from scratch if needed.
Every MCP server handles six message types:
initialize, client says hi, negotiates protocol version and capabilitieslist_tools / list_resources / list_prompts, client asks what's availablecall_tool, client executes a toolread_resource, client reads a resourceget_prompt, client fetches a filled promptshutdown, client is disconnectingimport { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server(
{ name: "hello-mcp", version: "0.1.0" },
{ capabilities: { tools: {} } }
);
server.setRequestHandler("tools/list", async () => ({
tools: [{
name: "say_hello",
description: "Returns a greeting",
inputSchema: {
type: "object",
properties: { name: { type: "string" } },
required: ["name"]
}
}]
}));
server.setRequestHandler("tools/call", async (req) => {
const { name, arguments: args } = req.params;
if (name === "say_hello") {
return {
content: [{ type: "text", text: `Hello, ${args.name}!` }]
};
}
throw new Error("Unknown tool");
});
await server.connect(new StdioServerTransport());
Most MCP servers just wrap an HTTP API (GitHub, Notion, Stripe). Each tool corresponds to one API endpoint. Thin wrappers are the most common and usually best, they're easy to maintain and update.
Sometimes a single tool should hit multiple systems, e.g, a "find person" tool that searches LinkedIn, your CRM, and your email. Useful but harder to maintain.
For data-heavy servers (document stores, databases), resources are the right primitive. Model the data as addressable URIs, let the client pin specific items into context.
The official SDKs ship with an inspector tool (@modelcontextprotocol/inspector). It connects to your server, lists tools, lets you call them manually, and shows raw protocol traffic. Use it before connecting your server to a real agent.
If your MCP is generally useful, publish it to npm (TypeScript) or PyPI (Python). Add an entry to your README showing how to install and configure. See the Directory for inspiration.