mcp-server-building

📁 yonatangross/orchestkit 📅 Jan 22, 2026
19
总安装量
19
周安装量
#18901
全站排名
安装命令
npx skills add https://github.com/yonatangross/orchestkit --skill mcp-server-building

Agent 安装分布

claude-code 14
gemini-cli 14
opencode 12
codex 11
github-copilot 10

Skill 文档

MCP Server Building

Build custom MCP servers to extend Claude with tools, resources, and prompts.

Architecture

+-------------+     JSON-RPC      +-------------+
|   Claude    |<----------------->| MCP Server  |
|   (Host)    |   stdio/SSE/WS    |  (Tools)    |
+-------------+                   +-------------+

Three Primitives:

  • Tools: Functions Claude can call (with user approval)
  • Resources: Data Claude can read (files, API responses)
  • Prompts: Pre-defined prompt templates

Quick Start

Minimal Python Server (stdio)

from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent

server = Server("my-tools")

@server.list_tools()
async def list_tools() -> list[Tool]:
    return [
        Tool(
            name="greet",
            description="Greet a user by name",
            inputSchema={
                "type": "object",
                "properties": {
                    "name": {"type": "string", "description": "Name to greet"}
                },
                "required": ["name"]
            }
        )
    ]

@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
    if name == "greet":
        return [TextContent(type="text", text=f"Hello, {arguments['name']}!")]
    raise ValueError(f"Unknown tool: {name}")

async def main():
    async with stdio_server() as (read, write):
        await server.run(read, write, server.create_initialization_options())

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

TypeScript Server (production)

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

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

server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [{
    name: "fetch_url",
    description: "Fetch content from a URL",
    inputSchema: {
      type: "object",
      properties: { url: { type: "string" } },
      required: ["url"],
    },
  }],
}));

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  if (request.params.name === "fetch_url") {
    const { url } = request.params.arguments as { url: string };
    const response = await fetch(url);
    return { content: [{ type: "text", text: await response.text() }] };
  }
  throw new Error("Unknown tool");
});

await server.connect(new StdioServerTransport());

Detailed Guides

Key Decisions

Decision Choice Rationale
Transport stdio for CLI, SSE for web stdio simplest, SSE for browsers
Language TypeScript for production Better SDK support, type safety
Error handling Return errors as text Claude can interpret and retry

Anti-Patterns

  1. Stateful tools without cleanup – Always clean up connections
  2. Blocking synchronous code – Use asyncio.to_thread()
  3. Missing input validation – Validate before processing
  4. Secrets in tool output – Never return credentials
  5. Unbounded responses – Limit response sizes

Related Skills

  • function-calling – LLM function calling patterns
  • agent-loops – Agentic patterns using MCP tools
  • input-validation – Input validation for arguments

Resources