MCP Development Guides

Learn how to build MCP servers and clients, develop powerful AI integration applications

Quick Start

Python SDK

Official Python SDK, easy to use

Node.js SDK

TypeScript/JavaScript support

Other Languages

Go, Rust, Java, etc.

Python MCP Server Development

1. Install Python SDK

bash
pip install mcp

2. Create Basic Server

python
import asyncio
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationOptions
from mcp.server.stdio import stdio_server
from mcp.types import (
    Resource,
    Tool,
    TextContent,
    ImageContent,
    EmbeddedResource,
    LoggingLevel
)

# Create MCP server instance
server = Server("my-mcp-server")

# Register resources
@server.list_resources()
async def handle_list_resources() -> list[Resource]:
    """Return list of available resources"""
    return [
        Resource(
            uri="config://app.json",
            name="App Configuration",
            description="Application configuration file",
            mimeType="application/json",
        )
    ]

# Read resources
@server.read_resource()
async def handle_read_resource(uri: str) -> str:
    """Read resource content"""
    if uri == "config://app.json":
        return json.dumps({
            "app_name": "MCP Server",
            "version": "1.0.0",
            "debug": True
        })
    else:
        raise ValueError(f"Unknown resource: {uri}")

# Register tools
@server.list_tools()
async def handle_list_tools() -> list[Tool]:
    """Return list of available tools"""
    return [
        Tool(
            name="echo",
            description="Echo input text",
            inputSchema={
                "type": "object",
                "properties": {
                    "text": {"type": "string", "description": "Text to echo"}
                },
                "required": ["text"]
            },
        ),
        Tool(
            name="get_weather",
            description="Get weather information",
            inputSchema={
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "City name"}
                },
                "required": ["location"]
            },
        )
    ]

# Call tools
@server.call_tool()
async def handle_call_tool(name: str, arguments: dict) -> list[TextContent]:
    """Handle tool calls"""
    if name == "echo":
        return [TextContent(type="text", text=arguments["text"])]
    elif name == "get_weather":
        location = arguments["location"]
        # Here should call real weather API
        weather_data = {
            "location": location,
            "temperature": "22°C",
            "description": "Sunny",
            "humidity": "65%"
        }
        return [TextContent(
            type="text", 
            text=f"Weather info - {location}: {weather_data['temperature']}, {weather_data['description']}"
        )]
    else:
        raise ValueError(f"Unknown tool: {name}")

# Run server
async def main():
    # Use stdio transport
    async with stdio_server() as (read_stream, write_stream):
        await server.run(
            read_stream,
            write_stream,
            InitializationOptions(
                server_name="my-mcp-server",
                server_version="1.0.0",
                capabilities=server.get_capabilities(
                    notification_options=NotificationOptions(),
                    experimental_capabilities={},
                ),
            ),
        )

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

3. Advanced Features Example

python
# Add prompts (Prompts)
@server.list_prompts()
async def handle_list_prompts() -> list[Prompt]:
    return [
        Prompt(
            name="summarize",
            description="Summarize text content",
            arguments=[
                PromptArgument(
                    name="text",
                    description="Text to summarize",
                    required=True
                )
            ]
        )
    ]

@server.get_prompt()
async def handle_get_prompt(name: str, arguments: dict) -> GetPromptResult:
    if name == "summarize":
        text = arguments["text"]
        prompt = f"Please summarize the following text:\n\n{text}\n\nSummary:"
        return GetPromptResult(
            description="Text summarization prompt",
            messages=[
                PromptMessage(
                    role="user",
                    content=TextContent(type="text", text=prompt)
                )
            ]
        )

# Handle notifications
@server.notification()
async def handle_notification(notification):
    """Handle notifications from client"""
    print(f"Received notification: {notification}")

# Error handling
@server.error()
async def handle_error(error):
    """Handle errors"""
    print(f"Error occurred: {error}")
    return {"error": str(error)}

TypeScript MCP Server Development

1. Install Dependencies

bash
npm install @modelcontextprotocol/sdk
npm install -D typescript @types/node

2. Create TypeScript Server

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

// Create server instance
const server = new Server(
  {
    name: 'my-typescript-mcp-server',
    version: '1.0.0',
  },
  {
    capabilities: {
      tools: {},
      resources: {},
    },
  }
);

// Register tool list handler
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: 'calculate',
        description: 'Perform mathematical calculations',
        inputSchema: {
          type: 'object',
          properties: {
            expression: {
              type: 'string',
              description: 'Mathematical expression (e.g., "2 + 3 * 4")',
            },
          },
          required: ['expression'],
        },
      },
      {
        name: 'get_time',
        description: 'Get current time',
        inputSchema: {
          type: 'object',
          properties: {},
        },
      },
    ] as Tool[],
  };
});

// Register tool call handler
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  switch (name) {
    case 'calculate':
      try {
        const expression = args.expression as string;
        // Simple math calculation (production should use safe expression parser)
        const result = eval(expression);
        return {
          content: [
            {
              type: 'text',
              text: `Calculation result: ${expression} = ${result}`,
            } as TextContent,
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: 'text',
              text: `Calculation error: ${error.message}`,
            } as TextContent,
          ],
        };
      }

    case 'get_time':
      const now = new Date();
      return {
        content: [
          {
            type: 'text',
            text: `Current time: ${now.toLocaleString('en-US')}`,
          } as TextContent,
        ],
      };

    default:
      throw new Error(`Unknown tool: ${name}`);
  }
});

// Start server
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  
  console.error('MCP server started');
}

main().catch((error) => {
  console.error('Server startup failed:', error);
  process.exit(1);
});

Deployment and Configuration

Claude Desktop Configuration

Configure your MCP server in Claude Desktop:

json
{
  "mcpServers": {
    "my-mcp-server": {
      "command": "python",
      "args": ["path/to/your/server.py"],
      "env": {
        "API_KEY": "your-api-key"
      }
    }
  }
}

Environment Variables Configuration

bash
# .env file
DATABASE_URL=postgresql://user:password@localhost/dbname
API_KEY=your-api-key
LOG_LEVEL=info
DEBUG=true

Docker Deployment

dockerfile
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["python", "server.py"]

Best Practices and Resources

Development Best Practices

  • Use type annotations and input validation
  • Implement proper error handling
  • Add detailed tool descriptions
  • Support asynchronous operations
  • Use environment variables for configuration management