Chapter 2: Development Environment Setup

Haiyue
19min

Chapter 2: Development Environment Setup

Learning Objectives
  • Install and configure Node.js development environment
  • Understand MCP SDK and related tools
  • Set up your first MCP Server project
  • Configure development debugging tools and test environment
  • Understand the basic project structure of MCP Server

Knowledge Summary

Environment Requirements

  • Node.js >= 18.0.0 (LTS version recommended)
  • npm or yarn package manager
  • TypeScript support (recommended)
  • Git version control tool
  • VS Code or other IDE with TypeScript support

MCP SDK Core Packages

Package NamePurposeDescription
@modelcontextprotocol/sdkMCP Core SDKProvides basic protocol implementation and type definitions
@modelcontextprotocol/serverMCP Server FrameworkHigh-level framework to simplify Server development
@modelcontextprotocol/clientMCP Client ToolFor testing and debugging MCP Server
@types/nodeNode.js Type DefinitionsRequired for TypeScript development

Project Structure Standards

mcp-server-example/
├── src/
│   ├── index.ts          # Server entry file
│   ├── tools/            # Tool implementations
│   ├── resources/        # Resource providers
│   ├── prompts/          # Prompt templates
│   └── types/            # Type definitions
├── dist/                 # Compilation output directory
├── package.json          # Project configuration
├── tsconfig.json         # TypeScript configuration
├── .gitignore           # Git ignore configuration
└── README.md            # Project documentation

Environment Setup Steps

1. Install Node.js Environment

# Python script demonstrating environment check
import subprocess
import sys
import json

def check_node_version():
    """Check Node.js version"""
    try:
        result = subprocess.run(['node', '--version'],
                              capture_output=True, text=True)
        if result.returncode == 0:
            version = result.stdout.strip()
            print(f"✅ Node.js installed: {version}")

            # Check if version meets requirements
            major_version = int(version[1:].split('.')[0])
            if major_version >= 18:
                print("✅ Node.js version meets requirements (>=18.0.0)")
                return True
            else:
                print("❌ Node.js version too old, requires >=18.0.0")
                return False
        else:
            print("❌ Node.js not installed")
            return False
    except FileNotFoundError:
        print("❌ Node.js not installed")
        return False

def check_npm_version():
    """Check npm version"""
    try:
        result = subprocess.run(['npm', '--version'],
                              capture_output=True, text=True)
        if result.returncode == 0:
            version = result.stdout.strip()
            print(f"✅ npm installed: {version}")
            return True
        else:
            print("❌ npm not installed")
            return False
    except FileNotFoundError:
        print("❌ npm not installed")
        return False

# Environment check
print("🔍 Checking development environment...")
node_ok = check_node_version()
npm_ok = check_npm_version()

if node_ok and npm_ok:
    print("\n✅ Environment check passed, ready to start MCP development!")
else:
    print("\n❌ Environment check failed, please install required tools")

2. Create MCP Server Project

# Simulate project initialization process
import os
import json
from pathlib import Path

def create_mcp_project(project_name):
    """Create MCP Server project structure"""

    # Create project directory structure
    dirs = [
        f"{project_name}",
        f"{project_name}/src",
        f"{project_name}/src/tools",
        f"{project_name}/src/resources",
        f"{project_name}/src/prompts",
        f"{project_name}/src/types",
        f"{project_name}/dist"
    ]

    for dir_path in dirs:
        Path(dir_path).mkdir(parents=True, exist_ok=True)
        print(f"📁 Created directory: {dir_path}")

    # Generate package.json
    package_json = {
        "name": project_name,
        "version": "1.0.0",
        "description": "MCP Server example",
        "main": "dist/index.js",
        "scripts": {
            "build": "tsc",
            "start": "node dist/index.js",
            "dev": "tsx src/index.ts",
            "watch": "tsx watch src/index.ts"
        },
        "dependencies": {
            "@modelcontextprotocol/sdk": "^1.0.0",
            "@modelcontextprotocol/server": "^1.0.0"
        },
        "devDependencies": {
            "@types/node": "^20.0.0",
            "typescript": "^5.0.0",
            "tsx": "^4.0.0"
        }
    }

    # Generate tsconfig.json
    tsconfig = {
        "compilerOptions": {
            "target": "ES2022",
            "module": "CommonJS",
            "moduleResolution": "node",
            "outDir": "./dist",
            "rootDir": "./src",
            "strict": True,
            "esModuleInterop": True,
            "skipLibCheck": True,
            "forceConsistentCasingInFileNames": True,
            "declaration": True,
            "declarationMap": True,
            "sourceMap": True
        },
        "include": ["src/**/*"],
        "exclude": ["node_modules", "dist"]
    }

    # Write configuration files
    with open(f"{project_name}/package.json", "w", encoding="utf-8") as f:
        json.dump(package_json, f, indent=2, ensure_ascii=False)

    with open(f"{project_name}/tsconfig.json", "w", encoding="utf-8") as f:
        json.dump(tsconfig, f, indent=2, ensure_ascii=False)

    print(f"📝 Created configuration files: package.json, tsconfig.json")

    return f"{project_name}"

# Create sample project
project_path = create_mcp_project("my-mcp-server")
print(f"\n✅ Project '{project_path}' created successfully!")

3. Hello World MCP Server

# Generate basic MCP Server code structure
hello_world_server = '''
import { Server } from '@modelcontextprotocol/server';
import { StdioTransport } from '@modelcontextprotocol/server/stdio';

class HelloWorldMCPServer {
    private server: Server;

    constructor() {
        // Create MCP Server instance
        this.server = new Server(
            {
                name: "hello-world-server",
                version: "1.0.0"
            },
            {
                capabilities: {
                    tools: {},
                    resources: {},
                    prompts: {}
                }
            }
        );

        this.setupTools();
        this.setupResources();
        this.setupPrompts();
    }

    private setupTools() {
        // Register Hello World tool
        this.server.setRequestHandler('tools/list', async () => {
            return {
                tools: [
                    {
                        name: "say_hello",
                        description: "A tool that says Hello",
                        inputSchema: {
                            type: "object",
                            properties: {
                                name: {
                                    type: "string",
                                    description: "Name to greet"
                                }
                            },
                            required: ["name"]
                        }
                    }
                ]
            };
        });

        // Handle tool calls
        this.server.setRequestHandler('tools/call', async (request) => {
            const { name, arguments: args } = request.params;

            if (name === "say_hello") {
                const userName = args.name || "World";
                return {
                    content: [
                        {
                            type: "text",
                            text: `Hello, ${userName}! Welcome to MCP Server!`
                        }
                    ]
                };
            }

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

    private setupResources() {
        // Register resource list
        this.server.setRequestHandler('resources/list', async () => {
            return {
                resources: [
                    {
                        uri: "hello://info",
                        name: "Server Information",
                        description: "Get basic information about the Hello World server",
                        mimeType: "text/plain"
                    }
                ]
            };
        });

        // Handle resource reading
        this.server.setRequestHandler('resources/read', async (request) => {
            const uri = request.params.uri;

            if (uri === "hello://info") {
                return {
                    contents: [
                        {
                            uri: uri,
                            mimeType: "text/plain",
                            text: "This is a Hello World MCP Server example\\nVersion: 1.0.0\\nFeatures: Demonstrates basic MCP protocol usage"
                        }
                    ]
                };
            }

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

    private setupPrompts() {
        // Register prompt templates
        this.server.setRequestHandler('prompts/list', async () => {
            return {
                prompts: [
                    {
                        name: "greeting_template",
                        description: "Friendly greeting template",
                        arguments: [
                            {
                                name: "user_name",
                                description: "User name",
                                required: true
                            }
                        ]
                    }
                ]
            };
        });

        // Handle prompt template retrieval
        this.server.setRequestHandler('prompts/get', async (request) => {
            const { name, arguments: args } = request.params;

            if (name === "greeting_template") {
                const userName = args?.user_name || "friend";
                return {
                    description: "Generate a friendly greeting message",
                    messages: [
                        {
                            role: "user",
                            content: {
                                type: "text",
                                text: `Please greet ${userName} in a friendly manner and introduce the advantages of the MCP protocol.`
                            }
                        }
                    ]
                };
            }

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

    public async start() {
        // Use standard input/output transport
        const transport = new StdioTransport();
        await this.server.connect(transport);
        console.error("Hello World MCP Server started!");
    }
}

// Start server
const server = new HelloWorldMCPServer();
server.start().catch((error) => {
    console.error("Server startup failed:", error);
    process.exit(1);
});
'''

print("📄 Basic MCP Server code template:")
print("=" * 50)
print(hello_world_server)
print("=" * 50)

Development Tools Configuration

VS Code Configuration

# VS Code configuration example
import json

def create_vscode_config():
    """Generate VS Code development configuration"""

    # launch.json - Debug configuration
    launch_config = {
        "version": "0.2.0",
        "configurations": [
            {
                "name": "Start MCP Server",
                "type": "node",
                "request": "launch",
                "program": "${workspaceFolder}/src/index.ts",
                "outFiles": ["${workspaceFolder}/dist/**/*.js"],
                "console": "integratedTerminal",
                "envFile": "${workspaceFolder}/.env"
            },
            {
                "name": "Debug MCP Server",
                "type": "node",
                "request": "launch",
                "program": "${workspaceFolder}/node_modules/tsx/cli.js",
                "args": ["${workspaceFolder}/src/index.ts"],
                "console": "integratedTerminal",
                "envFile": "${workspaceFolder}/.env"
            }
        ]
    }

    # settings.json - Workspace settings
    settings_config = {
        "typescript.preferences.importModuleSpecifier": "relative",
        "editor.codeActionsOnSave": {
            "source.organizeImports": True
        },
        "files.exclude": {
            "**/node_modules": True,
            "**/dist": True,
            "**/.git": True
        }
    }

    # extensions.json - Recommended extensions
    extensions_config = {
        "recommendations": [
            "ms-vscode.vscode-typescript-next",
            "esbenp.prettier-vscode",
            "ms-vscode.vscode-json",
            "bradlc.vscode-tailwindcss"
        ]
    }

    print("VS Code configuration files:")
    print("\n.vscode/launch.json:")
    print(json.dumps(launch_config, indent=2, ensure_ascii=False))

    print("\n.vscode/settings.json:")
    print(json.dumps(settings_config, indent=2, ensure_ascii=False))

    print("\n.vscode/extensions.json:")
    print(json.dumps(extensions_config, indent=2, ensure_ascii=False))

create_vscode_config()

Testing and Debugging Tools

Testing Tools

MCP Inspector - MCP protocol debugging tool

  • Provides visual interface to test MCP Server
  • Real-time view of message passing process
  • Supports tool invocation and resource access testing

MCP Client CLI - Command-line testing tool

  • Quick testing of MCP Server functionality
  • Automated testing script support
  • Performance and load testing
# Test script example
def create_test_script():
    """Generate MCP Server test script"""

    test_script = '''
import asyncio
import json
from typing import Any, Dict

class MCPServerTester:
    def __init__(self, server_command: str):
        self.server_command = server_command
        self.process = None

    async def start_server(self):
        """Start MCP Server process"""
        import subprocess
        self.process = await asyncio.create_subprocess_exec(
            *self.server_command.split(),
            stdin=asyncio.subprocess.PIPE,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE
        )
        print("📡 MCP Server started")

    async def send_request(self, method: str, params: Dict[str, Any] = None):
        """Send MCP request"""
        if not self.process:
            raise RuntimeError("Server not started")

        request = {
            "jsonrpc": "2.0",
            "id": 1,
            "method": method,
            "params": params or {}
        }

        # Send request
        request_data = json.dumps(request) + "\\n"
        self.process.stdin.write(request_data.encode())
        await self.process.stdin.drain()

        # Read response
        response_line = await self.process.stdout.readline()
        response = json.loads(response_line.decode())

        return response

    async def test_tools(self):
        """Test tools functionality"""
        print("🔧 Testing Tools functionality...")

        # Get tools list
        tools_response = await self.send_request("tools/list")
        print(f"Available tools: {tools_response}")

        # Call say_hello tool
        call_response = await self.send_request("tools/call", {
            "name": "say_hello",
            "arguments": {"name": "Test User"}
        })
        print(f"Tool call result: {call_response}")

    async def test_resources(self):
        """Test resources functionality"""
        print("📚 Testing Resources functionality...")

        # Get resources list
        resources_response = await self.send_request("resources/list")
        print(f"Available resources: {resources_response}")

        # Read resource content
        read_response = await self.send_request("resources/read", {
            "uri": "hello://info"
        })
        print(f"Resource content: {read_response}")

    async def test_prompts(self):
        """Test prompts functionality"""
        print("💬 Testing Prompts functionality...")

        # Get prompt templates list
        prompts_response = await self.send_request("prompts/list")
        print(f"Available templates: {prompts_response}")

        # Get prompt template
        get_response = await self.send_request("prompts/get", {
            "name": "greeting_template",
            "arguments": {"user_name": "Developer"}
        })
        print(f"Template content: {get_response}")

    async def run_all_tests(self):
        """Run all tests"""
        await self.start_server()
        try:
            await self.test_tools()
            await self.test_resources()
            await self.test_prompts()
            print("\\n✅ All tests passed!")
        finally:
            if self.process:
                self.process.terminate()
                await self.process.wait()

# Usage example
async def main():
    tester = MCPServerTester("node dist/index.js")
    await tester.run_all_tests()

# Run tests
# asyncio.run(main())
print("Test script ready")
    '''

    print("🧪 MCP Server test script:")
    print(test_script)

create_test_script()

Project Management Best Practices

Git Configuration

# .gitignore file content
gitignore_content = '''
# Node.js
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# TypeScript
dist/
*.tsbuildinfo

# Environment variables
.env
.env.local
.env.production

# IDE
.vscode/settings.json
.idea/

# Operating system
.DS_Store
Thumbs.db

# Log files
logs/
*.log

# Temporary files
tmp/
temp/
'''

print("📄 .gitignore configuration:")
print(gitignore_content)

Development Workflow

Development Workflow
  1. Project Initialization - Use scaffolding tools to quickly create project structure
  2. Dependency Installation - Install MCP SDK and development dependencies
  3. Code Development - Develop MCP Server using TypeScript
  4. Local Testing - Test functionality using MCP Client tools
  5. Build and Package - Compile TypeScript to JavaScript
  6. Integration Testing - Test in real AI clients
  7. Deployment and Release - Publish to npm or private repository

Through this chapter, we have successfully set up a complete MCP Server development environment, created our first Hello World project, and configured necessary development and testing tools. This lays a solid foundation for in-depth learning of MCP protocol implementation.