How to Create an MCP Server

Build Model Context Protocol (MCP) servers to expose tools and resources to AI agents.

Prerequisites

Quick Start (TypeScript)

1. Initialize Project

1
2
3
4
mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk
npm install -D typescript @types/node

2. Create Server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// src/index.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new Server({
  name: "my-mcp-server",
  version: "1.0.0",
});

// Define a tool
server.setRequestHandler("tools/list", async () => ({
  tools: [
    {
      name: "greet",
      description: "Greet a user by name",
      inputSchema: {
        type: "object",
        properties: {
          name: { type: "string", description: "Name to greet" }
        },
        required: ["name"]
      }
    }
  ]
}));

// Handle tool calls
server.setRequestHandler("tools/call", async (request) => {
  if (request.params.name === "greet") {
    const name = request.params.arguments.name;
    return { content: [{ type: "text", text: `Hello, ${name}!` }] };
  }
  throw new Error(`Unknown tool: ${request.params.name}`);
});

// Start server
const transport = new StdioServerTransport();
await server.connect(transport);

3. Configure TypeScript

1
2
3
4
5
6
7
8
9
10
11
// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "./dist",
    "strict": true
  },
  "include": ["src/**/*"]
}

4. Build and Run

1
2
npx tsc
node dist/index.js

Quick Start (Python)

1. Initialize Project

1
2
3
4
mkdir my-mcp-server && cd my-mcp-server
python -m venv .venv
source .venv/bin/activate
pip install mcp

2. Create Server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# server.py
from mcp.server import Server
from mcp.server.stdio import stdio_server

server = Server("my-mcp-server")

@server.tool()
async def greet(name: str) -> str:
    """Greet a user by name."""
    return f"Hello, {name}!"

async def main():
    async with stdio_server() as (read_stream, write_stream):
        await server.run(read_stream, write_stream)

if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

3. Run

1
python server.py

Testing with Evaluation

Use the MCP evaluation harness:

1
2
3
4
5
python .github/skills/mcp-builder/scripts/evaluation.py \
  -t stdio \
  -c python \
  -a server.py \
  eval.xml

Create eval.xml with test cases:

1
2
3
4
5
6
<evaluations>
  <qa_pair>
    <question>Greet Alice</question>
    <answer>Hello, Alice!</answer>
  </qa_pair>
</evaluations>

Best Practices

  1. Descriptive tool names - Use verb-noun format (get_user, create_order)
  2. Clear descriptions - Help the agent understand when to use each tool
  3. Validate inputs - Use JSON Schema for input validation
  4. Meaningful errors - Return actionable error messages
  5. Limit output size - Avoid returning megabytes of data