Chapter 2: Development Environment Setup

Haiyue
28min

Chapter 2: Development Environment Setup

Learning Objectives

  1. Install and configure Node.js development environment
  2. Understand MCP SDK and related tools
  3. Set up your first MCP Server project
  4. Configure development debugging tools and test environment
  5. Understand the basic project structure of MCP Server

2.1 Environment Preparation

Node.js Environment Installation

# Recommended to use Node.js 18+ version
# Method 1: Direct download and installation
# Visit https://nodejs.org/ to download LTS version

# Method 2: Use nvm to manage multiple Node.js versions
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
source ~/.bashrc

# Install and use Node.js 20
nvm install 20
nvm use 20
nvm alias default 20

# Verify installation
node --version
npm --version

TypeScript Development Environment

# Install TypeScript globally
npm install -g typescript ts-node nodemon

# Verify TypeScript installation
tsc --version
ts-node --version

Development Tools Recommendations

// VS Code extensions recommendations (.vscode/extensions.json)
{
  "recommendations": [
    "ms-vscode.vscode-typescript-next",
    "bradlc.vscode-tailwindcss",
    "esbenp.prettier-vscode",
    "ms-vscode.vscode-json",
    "redhat.vscode-yaml"
  ]
}

2.2 MCP SDK Installation and Configuration

Installing MCP SDK

# Create new project directory
mkdir my-mcp-server
cd my-mcp-server

# Initialize npm project
npm init -y

# Install MCP SDK
npm install @modelcontextprotocol/sdk

# Install dev dependencies
npm install -D typescript @types/node ts-node nodemon prettier

Project Structure Setup

my-mcp-server/
├── package.json
├── tsconfig.json
├── .gitignore
├── .prettierrc
├── README.md
├── src/
│   ├── index.ts
│   ├── server.ts
│   ├── tools/
│   │   ├── index.ts
│   │   └── example.ts
│   ├── resources/
│   │   ├── index.ts
│   │   └── static.ts
│   ├── prompts/
│   │   ├── index.ts
│   │   └── templates.ts
│   └── types/
│       └── index.ts
├── dist/
├── tests/
│   ├── integration/
│   └── unit/
└── docs/

Basic Configuration Files

// package.json
{
  "name": "my-mcp-server",
  "version": "1.0.0",
  "description": "My first MCP Server",
  "main": "dist/index.js",
  "type": "module",
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js",
    "dev": "nodemon --exec ts-node src/index.ts",
    "test": "jest",
    "lint": "prettier --check src/",
    "lint:fix": "prettier --write src/",
    "clean": "rm -rf dist/"
  },
  "keywords": ["mcp", "ai", "tools"],
  "author": "Your Name",
  "license": "MIT",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.0.0"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "typescript": "^5.0.0",
    "ts-node": "^10.9.0",
    "nodemon": "^3.0.0",
    "prettier": "^3.0.0",
    "jest": "^29.0.0",
    "@types/jest": "^29.0.0"
  }
}
// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2022"],
    "module": "ESNext",
    "moduleResolution": "Node",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "removeComments": false,
    "noImplicitAny": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "allowSyntheticDefaultImports": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "tests"]
}
// .prettierrc
{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false
}
# .gitignore
node_modules/
dist/
.env
.env.local
*.log
.DS_Store
coverage/
.nyc_output/

2.3 Creating Your First MCP Server

Basic Server Structure

// src/types/index.ts
export interface ServerConfig {
  name: string;
  version: string;
  description?: string;
  author?: string;
  capabilities: {
    tools?: boolean;
    resources?: boolean;
    prompts?: boolean;
    logging?: boolean;
  };
}

export interface ToolDefinition {
  name: string;
  description: string;
  inputSchema: {
    type: 'object';
    properties: Record<string, any>;
    required?: string[];
  };
  handler: (args: any) => Promise<any>;
}

export interface ResourceDefinition {
  uri: string;
  name: string;
  description?: string;
  mimeType?: string;
  handler: () => Promise<{ content: any; mimeType?: string }>;
}

export interface PromptDefinition {
  name: string;
  description?: string;
  arguments?: Array<{
    name: string;
    description: string;
    required?: boolean;
  }>;
  handler: (args: any) => Promise<{
    messages: Array<{
      role: 'user' | 'assistant' | 'system';
      content: {
        type: 'text' | 'image';
        text?: string;
        data?: string;
      };
    }>;
  }>;
}
// src/server.ts
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
  ListResourcesRequestSchema,
  ReadResourceRequestSchema,
  ListPromptsRequestSchema,
  GetPromptRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';

import type { ServerConfig, ToolDefinition, ResourceDefinition, PromptDefinition } from './types/index.js';

export class MCPServer {
  private server: Server;
  private config: ServerConfig;
  private tools: Map<string, ToolDefinition> = new Map();
  private resources: Map<string, ResourceDefinition> = new Map();
  private prompts: Map<string, PromptDefinition> = new Map();

  constructor(config: ServerConfig) {
    this.config = config;
    this.server = new Server(
      {
        name: config.name,
        version: config.version,
      },
      {
        capabilities: {
          tools: config.capabilities.tools ? {} : undefined,
          resources: config.capabilities.resources ? { subscribe: false } : undefined,
          prompts: config.capabilities.prompts ? {} : undefined,
        },
      }
    );

    this.setupHandlers();
  }

  private setupHandlers(): void {
    // Tool-related handlers
    if (this.config.capabilities.tools) {
      this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
        tools: Array.from(this.tools.values()).map(tool => ({
          name: tool.name,
          description: tool.description,
          inputSchema: tool.inputSchema,
        })),
      }));

      this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
        const { name, arguments: args } = request.params;
        const tool = this.tools.get(name);

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

        try {
          const result = await tool.handler(args || {});
          return {
            content: [
              {
                type: 'text',
                text: typeof result === 'string' ? result : JSON.stringify(result, null, 2),
              },
            ],
          };
        } catch (error) {
          throw new Error(`Tool execution failed: ${error.message}`);
        }
      });
    }

    // Resource-related handlers
    if (this.config.capabilities.resources) {
      this.server.setRequestHandler(ListResourcesRequestSchema, async () => ({
        resources: Array.from(this.resources.values()).map(resource => ({
          uri: resource.uri,
          name: resource.name,
          description: resource.description,
          mimeType: resource.mimeType,
        })),
      }));

      this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
        const { uri } = request.params;
        const resource = this.resources.get(uri);

        if (!resource) {
          throw new Error(`Unknown resource: ${uri}`);
        }

        try {
          const result = await resource.handler();
          return {
            contents: [
              {
                uri: resource.uri,
                mimeType: result.mimeType || resource.mimeType || 'text/plain',
                text: typeof result.content === 'string' ? result.content : JSON.stringify(result.content),
              },
            ],
          };
        } catch (error) {
          throw new Error(`Resource read failed: ${error.message}`);
        }
      });
    }

    // Prompt template-related handlers
    if (this.config.capabilities.prompts) {
      this.server.setRequestHandler(ListPromptsRequestSchema, async () => ({
        prompts: Array.from(this.prompts.values()).map(prompt => ({
          name: prompt.name,
          description: prompt.description,
          arguments: prompt.arguments,
        })),
      }));

      this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
        const { name, arguments: args } = request.params;
        const prompt = this.prompts.get(name);

        if (!prompt) {
          throw new Error(`Unknown prompt: ${name}`);
        }

        try {
          const result = await prompt.handler(args || {});
          return result;
        } catch (error) {
          throw new Error(`Prompt generation failed: ${error.message}`);
        }
      });
    }
  }

  // Register tool
  addTool(tool: ToolDefinition): void {
    if (!this.config.capabilities.tools) {
      throw new Error('Tools capability is not enabled');
    }
    this.tools.set(tool.name, tool);
  }

  // Register resource
  addResource(resource: ResourceDefinition): void {
    if (!this.config.capabilities.resources) {
      throw new Error('Resources capability is not enabled');
    }
    this.resources.set(resource.uri, resource);
  }

  // Register prompt template
  addPrompt(prompt: PromptDefinition): void {
    if (!this.config.capabilities.prompts) {
      throw new Error('Prompts capability is not enabled');
    }
    this.prompts.set(prompt.name, prompt);
  }

  // Start server
  async start(): Promise<void> {
    const transport = new StdioServerTransport();
    await this.server.connect(transport);

    console.error(`${this.config.name} v${this.config.version} started successfully`);
    console.error(`Capabilities: ${JSON.stringify(this.server.getCapabilities())}`);
  }
}

Example Tool Implementation

// src/tools/example.ts
import type { ToolDefinition } from '../types/index.js';

// Hello World tool
export const helloTool: ToolDefinition = {
  name: 'hello',
  description: 'Say hello to a specified person',
  inputSchema: {
    type: 'object',
    properties: {
      name: {
        type: 'string',
        description: 'Name of the person to greet',
      },
      greeting: {
        type: 'string',
        description: 'Greeting message, defaults to "Hello"',
        default: 'Hello',
      },
    },
    required: ['name'],
  },
  handler: async (args) => {
    const { name, greeting = 'Hello' } = args;
    return `${greeting}, ${name}! Welcome to MCP Server!`;
  },
};

// Calculate tool
export const calculateTool: ToolDefinition = {
  name: 'calculate',
  description: 'Perform basic mathematical calculations',
  inputSchema: {
    type: 'object',
    properties: {
      expression: {
        type: 'string',
        description: 'Mathematical expression, e.g., "2 + 3 * 4"',
      },
    },
    required: ['expression'],
  },
  handler: async (args) => {
    const { expression } = args;

    // Simple mathematical expression evaluation (supports basic operations only)
    const sanitized = expression.replace(/[^0-9+\-*/().]/g, '');

    try {
      // Note: In production, use a safer expression evaluator
      const result = Function(`"use strict"; return (${sanitized})`)();

      return {
        expression: expression,
        result: result,
        sanitized: sanitized,
      };
    } catch (error) {
      throw new Error(`Invalid expression: ${expression}`);
    }
  },
};

// Get current time tool
export const currentTimeTool: ToolDefinition = {
  name: 'current_time',
  description: 'Get current time',
  inputSchema: {
    type: 'object',
    properties: {
      format: {
        type: 'string',
        description: 'Time format: "iso" or "readable"',
        enum: ['iso', 'readable'],
        default: 'iso',
      },
      timezone: {
        type: 'string',
        description: 'Timezone, e.g., "Asia/Shanghai"',
      },
    },
  },
  handler: async (args) => {
    const { format = 'iso', timezone } = args;
    const now = new Date();

    let result: string;

    if (format === 'readable') {
      result = timezone
        ? now.toLocaleString('en-US', { timeZone: timezone })
        : now.toLocaleString('en-US');
    } else {
      result = now.toISOString();
    }

    return {
      timestamp: result,
      format: format,
      timezone: timezone || 'local',
    };
  },
};
// src/tools/index.ts
export { helloTool, calculateTool, currentTimeTool } from './example.js';

Example Resource Implementation

// src/resources/static.ts
import type { ResourceDefinition } from '../types/index.js';

// System information resource
export const systemInfoResource: ResourceDefinition = {
  uri: 'system://info',
  name: 'System Information',
  description: 'Basic system information',
  mimeType: 'application/json',
  handler: async () => {
    const info = {
      platform: process.platform,
      arch: process.arch,
      nodeVersion: process.version,
      memory: process.memoryUsage(),
      uptime: process.uptime(),
      timestamp: new Date().toISOString(),
    };

    return {
      content: info,
      mimeType: 'application/json',
    };
  },
};

// Configuration resource
export const configResource: ResourceDefinition = {
  uri: 'config://app',
  name: 'Application Configuration',
  description: 'Application configuration information',
  mimeType: 'application/json',
  handler: async () => {
    const config = {
      name: 'My MCP Server',
      version: '1.0.0',
      features: ['tools', 'resources', 'prompts'],
      debug: process.env.NODE_ENV === 'development',
      capabilities: {
        maxConcurrentRequests: 10,
        timeout: 30000,
      },
    };

    return {
      content: config,
      mimeType: 'application/json',
    };
  },
};

// Help documentation resource
export const helpResource: ResourceDefinition = {
  uri: 'help://usage',
  name: 'Usage Help',
  description: 'Usage help documentation',
  mimeType: 'text/markdown',
  handler: async () => {
    const helpContent = `
# MCP Server Usage Help

## Available Tools

### hello
Say hello to a specified person
- **Parameters**: name (required), greeting (optional)
- **Example**: {"name": "World", "greeting": "Hi"}

### calculate
Perform basic mathematical calculations
- **Parameters**: expression (required)
- **Example**: {"expression": "2 + 3 * 4"}

### current_time
Get current time
- **Parameters**: format (optional), timezone (optional)
- **Example**: {"format": "readable", "timezone": "Asia/Shanghai"}

## Available Resources

- **system://info**: System information
- **config://app**: Application configuration
- **help://usage**: Usage help

## Getting Started

Connect to this server using an MCP client, then you can call tools and read resources.
    `.trim();

    return {
      content: helpContent,
      mimeType: 'text/markdown',
    };
  },
};
// src/resources/index.ts
export { systemInfoResource, configResource, helpResource } from './static.js';

Example Prompt Template Implementation

// src/prompts/templates.ts
import type { PromptDefinition } from '../types/index.js';

// Code review prompt template
export const codeReviewPrompt: PromptDefinition = {
  name: 'code_review',
  description: 'Code review prompt template',
  arguments: [
    {
      name: 'code',
      description: 'Code to review',
      required: true,
    },
    {
      name: 'language',
      description: 'Programming language',
      required: false,
    },
  ],
  handler: async (args) => {
    const { code, language = 'unknown' } = args;

    return {
      messages: [
        {
          role: 'system',
          content: {
            type: 'text',
            text: `You are an experienced code review expert. Please carefully review the following ${language} code, focusing on:
1. Code quality and readability
2. Potential bugs and security issues
3. Performance optimization suggestions
4. Best practice compliance

Please provide specific improvement suggestions and example code.`,
          },
        },
        {
          role: 'user',
          content: {
            type: 'text',
            text: `Please review the following code:

\`\`\`${language}
${code}
\`\`\``,
          },
        },
      ],
    };
  },
};

// Technical documentation generation prompt template
export const docGenerationPrompt: PromptDefinition = {
  name: 'generate_docs',
  description: 'Prompt template for generating technical documentation',
  arguments: [
    {
      name: 'topic',
      description: 'Documentation topic',
      required: true,
    },
    {
      name: 'audience',
      description: 'Target audience (beginner/intermediate/advanced)',
      required: false,
    },
    {
      name: 'format',
      description: 'Documentation format (markdown/html/plain)',
      required: false,
    },
  ],
  handler: async (args) => {
    const { topic, audience = 'intermediate', format = 'markdown' } = args;

    return {
      messages: [
        {
          role: 'system',
          content: {
            type: 'text',
            text: `You are a technical writing expert. Please generate ${format} format technical documentation about "${topic}" for ${audience}-level readers.

The documentation should include:
1. Overview and objectives
2. Core concept explanations
3. Practical examples and code
4. Best practices
5. Common questions and solutions

Please ensure the content is clear, accurate, and practical.`,
          },
        },
        {
          role: 'user',
          content: {
            type: 'text',
            text: `Please generate technical documentation about "${topic}".`,
          },
        },
      ],
    };
  },
};
// src/prompts/index.ts
export { codeReviewPrompt, docGenerationPrompt } from './templates.js';

Main Entry File

// src/index.ts
import { MCPServer } from './server.js';
import { helloTool, calculateTool, currentTimeTool } from './tools/index.js';
import { systemInfoResource, configResource, helpResource } from './resources/index.js';
import { codeReviewPrompt, docGenerationPrompt } from './prompts/index.js';

async function main() {
  // Create MCP server
  const server = new MCPServer({
    name: 'my-mcp-server',
    version: '1.0.0',
    description: 'My first MCP Server with examples',
    author: 'Your Name',
    capabilities: {
      tools: true,
      resources: true,
      prompts: true,
      logging: true,
    },
  });

  // Register tools
  server.addTool(helloTool);
  server.addTool(calculateTool);
  server.addTool(currentTimeTool);

  // Register resources
  server.addResource(systemInfoResource);
  server.addResource(configResource);
  server.addResource(helpResource);

  // Register prompt templates
  server.addPrompt(codeReviewPrompt);
  server.addPrompt(docGenerationPrompt);

  // Start server
  await server.start();
}

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

2.4 Development and Debugging Tools

Development Scripts Configuration

// package.json - scripts section
{
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js",
    "dev": "nodemon --exec ts-node src/index.ts",
    "dev:debug": "nodemon --exec 'node --inspect=0.0.0.0:9229 -r ts-node/register src/index.ts'",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage",
    "lint": "prettier --check src/ && eslint src/",
    "lint:fix": "prettier --write src/ && eslint src/ --fix",
    "clean": "rm -rf dist/",
    "check-types": "tsc --noEmit"
  }
}

Debugging Configuration

// .vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug MCP Server",
      "type": "node",
      "request": "launch",
      "program": "${workspaceFolder}/src/index.ts",
      "runtimeArgs": ["-r", "ts-node/register"],
      "env": {
        "NODE_ENV": "development"
      },
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen"
    },
    {
      "name": "Attach to Process",
      "type": "node",
      "request": "attach",
      "port": 9229,
      "restart": true,
      "localRoot": "${workspaceFolder}",
      "remoteRoot": "."
    }
  ]
}

MCP Debugging Tools

// src/utils/debug.ts
export class MCPDebugger {
  private static instance: MCPDebugger;
  private debugEnabled: boolean;

  private constructor() {
    this.debugEnabled = process.env.NODE_ENV === 'development' || process.env.MCP_DEBUG === 'true';
  }

  static getInstance(): MCPDebugger {
    if (!MCPDebugger.instance) {
      MCPDebugger.instance = new MCPDebugger();
    }
    return MCPDebugger.instance;
  }

  log(message: string, data?: any): void {
    if (!this.debugEnabled) return;

    const timestamp = new Date().toISOString();
    console.error(`[DEBUG ${timestamp}] ${message}`);

    if (data) {
      console.error(JSON.stringify(data, null, 2));
    }
  }

  logRequest(method: string, params: any): void {
    this.log(`Request: ${method}`, params);
  }

  logResponse(method: string, response: any): void {
    this.log(`Response: ${method}`, response);
  }

  logError(error: Error, context?: string): void {
    const timestamp = new Date().toISOString();
    console.error(`[ERROR ${timestamp}] ${context || 'Unknown'}: ${error.message}`);
    if (this.debugEnabled) {
      console.error(error.stack);
    }
  }
}

// Usage example
const debugger = MCPDebugger.getInstance();
debugger.log('Server starting...');

2.5 Test Environment Configuration

Jest Test Configuration

// jest.config.js
export default {
  preset: 'ts-jest/presets/default-esm',
  extensionsToTreatAsEsm: ['.ts'],
  testEnvironment: 'node',
  roots: ['<rootDir>/src', '<rootDir>/tests'],
  testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
  transform: {
    '^.+\\.ts$': ['ts-jest', {
      useESM: true
    }]
  },
  collectCoverageFrom: [
    'src/**/*.ts',
    '!src/**/*.d.ts',
    '!src/**/__tests__/**',
    '!src/**/*.spec.ts',
    '!src/**/*.test.ts'
  ],
  coverageDirectory: 'coverage',
  coverageReporters: ['text', 'lcov', 'html']
};

Example Test File

// tests/unit/tools.test.ts
import { helloTool, calculateTool, currentTimeTool } from '../../src/tools/example.js';

describe('Example Tools', () => {
  describe('helloTool', () => {
    it('should greet with default message', async () => {
      const result = await helloTool.handler({ name: 'World' });
      expect(result).toBe('Hello, World! Welcome to MCP Server!');
    });

    it('should greet with custom message', async () => {
      const result = await helloTool.handler({ name: 'Alice', greeting: 'Hi' });
      expect(result).toBe('Hi, Alice! Welcome to MCP Server!');
    });
  });

  describe('calculateTool', () => {
    it('should calculate simple expressions', async () => {
      const result = await calculateTool.handler({ expression: '2 + 3' });
      expect(result.result).toBe(5);
      expect(result.expression).toBe('2 + 3');
    });

    it('should handle complex expressions', async () => {
      const result = await calculateTool.handler({ expression: '2 + 3 * 4' });
      expect(result.result).toBe(14);
    });

    it('should throw error for invalid expressions', async () => {
      await expect(calculateTool.handler({ expression: 'invalid' }))
        .rejects.toThrow('Invalid expression');
    });
  });

  describe('currentTimeTool', () => {
    it('should return ISO format by default', async () => {
      const result = await currentTimeTool.handler({});
      expect(result.format).toBe('iso');
      expect(typeof result.timestamp).toBe('string');
    });

    it('should return readable format', async () => {
      const result = await currentTimeTool.handler({ format: 'readable' });
      expect(result.format).toBe('readable');
    });
  });
});

Integration Tests

// tests/integration/server.test.ts
import { MCPServer } from '../../src/server.js';
import { helloTool } from '../../src/tools/example.js';

describe('MCPServer Integration', () => {
  let server: MCPServer;

  beforeEach(() => {
    server = new MCPServer({
      name: 'test-server',
      version: '1.0.0',
      capabilities: {
        tools: true,
        resources: false,
        prompts: false,
      },
    });
  });

  it('should register and execute tools', async () => {
    server.addTool(helloTool);

    // Test tool registration
    const hasHelloTool = server['tools'].has('hello');
    expect(hasHelloTool).toBe(true);

    // Test tool execution
    const tool = server['tools'].get('hello');
    const result = await tool!.handler({ name: 'Test' });
    expect(result).toContain('Hello, Test!');
  });

  it('should throw error for invalid tool capabilities', () => {
    const serverWithoutTools = new MCPServer({
      name: 'test-server',
      version: '1.0.0',
      capabilities: { tools: false },
    });

    expect(() => {
      serverWithoutTools.addTool(helloTool);
    }).toThrow('Tools capability is not enabled');
  });
});

2.6 Build and Run

Building the Project

# Install dependencies
npm install

# Type checking
npm run check-types

# Build project
npm run build

# Run tests
npm test

# Code formatting
npm run lint:fix

Running Development Server

# Development mode
npm run dev

# Debug mode
npm run dev:debug

# Production mode
npm run build && npm start

Verifying MCP Server

# Test using stdio transport
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}' | node dist/index.js

# Expected response should include server capability information

Summary

Through this chapter, we have established a complete MCP Server development environment:

  1. Environment Configuration: Node.js, TypeScript, development tools
  2. Project Structure: Standard MCP Server project organization
  3. Core Framework: Reusable MCPServer class
  4. Example Implementations: Complete examples of tools, resources, and prompt templates
  5. Development Tools: Debugging, testing, and build scripts
  6. Best Practices: Type safety, error handling, modular design

Next, we will dive into the MCP protocol technical specifications to understand message formats and communication mechanisms.

Extended Exercises

  1. Add a new tool to implement file reading functionality
  2. Create an environment variable resource providing system environment information
  3. Write a JSON formatting prompt template
  4. Add more unit tests for existing tools
  5. Implement a simple logging functionality