Skip to main content

Build an MCP server

Get started building a server you can use in Claude Desktop, Cursor, VS Code and other MCP clients.

Adapted from the official Build an MCP server tutorial. The upstream page includes full TypeScript, Python, and other language walkthroughs — use it for copy-paste examples; this page captures the architecture decisions and enterprise checklist.

Weather alerts example from the official server tutorial — Source: MCP docs

Reference weather server scenario used in official tutorials. Source: modelcontextprotocol/docs (weather-alerts.png).

Choose your path

GoalRecommendation
Fastest start on NodeTypeScript SDK (Tier 1)
Data / ML teamsPython SDK (Tier 1)
.NET estatesC# SDK (Tier 1)
Guided AI codingBuild with Agent Skills

Full language matrix: SDKs.

What you will build

A typical first server (weather / filesystem tutorials):

  1. Declare server identity and capabilities.
  2. Register tools with JSON Schema inputs.
  3. Optionally register resources and prompts.
  4. Connect a stdio transport for local hosts.
  5. Test with MCP Inspector.
  6. Add the server to host config (Claude Desktop, Cursor, …).

Conceptual TypeScript shape

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: "weather",
version: "1.0.0",
});

server.tool(
"get_alerts",
{
state: z.string().length(2).describe("US state code, e.g. CA"),
},
async ({ state }) => {
// Call upstream API, handle errors, return structured content
return {
content: [{ type: "text", text: `Alerts for ${state}` }],
};
},
);

async function main(): Promise<void> {
const transport = new StdioServerTransport();
await server.connect(transport);
}

main().catch((error: unknown) => {
console.error(error);
process.exit(1);
});

Exact imports and APIs evolve — follow the current SDK README and the official build-server guide.

Design checklist

Decision checklist

  • Each tool has one clear responsibility and typed inputs
  • Errors return protocol-friendly messages (no raw stack traces to the model)
  • Side-effecting tools are documented; hosts can require approval
  • Secrets come from environment variables, never from tool arguments by default
  • Stdio servers log to stderr only (stdout is the protocol channel)
  • Inspector can list and call every tool successfully
  • Absolute paths used in host config examples

Negative cases

FailureMitigation
Logging JSON to stdout on stdioBreaks the protocol — use stderr
Unbounded network timeoutsSet timeouts; return timed-out tool errors
Tool accepts free-form shell commandsReject or tightly allow-list
Missing input validationSchema + runtime validation; treat invalid input as tool error
Crash on upstream 5xxCatch, return error content, keep process alive

After the first server

  1. Connect to local hosts
  2. Connect remote servers when you need shared multi-user access
  3. Add authorization before exposing sensitive tools
  4. Publish metadata to the Registry when public

Approval dialog for tool execution — Source: MCP docs

Hosts should prompt before side effects. Source: modelcontextprotocol/docs (quickstart-approve.png).

Discussion

Comments

Share feedback or questions about this page. No account required.

Loading comments…