# Creating an MCP Server

This guide explains how to create a custom MCP server that can be used with the MCP toolkit.

## Overview

An MCP server is a process that implements the Model Context Protocol and exposes:

1. **Resources**: Data and content that clients can read
2. **Tools**: Functions that clients can execute
3. **Prompts**: Reusable prompt templates (optional)

## Basic Server Structure

Here's a simple example of an MCP server using Node.js:

```javascript
// server.js
import { createServer } from '@modelcontextprotocol/server';

// Create the server
const server = createServer({
  name: 'my-custom-server',
  version: '1.0.0',
  description: 'A custom MCP server'
});

// Register a tool
server.registerTool({
  name: 'greet',
  description: 'Generates a greeting message',
  parameters: {
    type: 'object',
    properties: {
      name: {
        type: 'string',
        description: 'The name to greet'
      }
    },
    required: ['name']
  },
  returns: {
    type: 'object',
    properties: {
      greeting: {
        type: 'string',
        description: 'The greeting message'
      }
    }
  },
  handler: async (params) => {
    return {
      greeting: `Hello, ${params.name}!`
    };
  }
});

// Register a resource
server.registerResource({
  uri: '/info',
  description: 'Server information',
  handler: async () => {
    return {
      contentType: 'application/json',
      content: JSON.stringify({
        serverName: 'my-custom-server',
        timestamp: new Date().toISOString(),
        status: 'running'
      })
    };
  }
});

// Start the server
server.start();
```

## Server Implementation Guidelines

### Resources

Resources are data or content exposed by the server. To register a resource:

```javascript
server.registerResource({
  uri: '/path/to/resource',
  description: 'Description of the resource',
  handler: async () => {
    // Fetch or generate the resource content
    return {
      contentType: 'application/json', // MIME type
      content: JSON.stringify({ /* content */ })
    };
  }
});
```

### Tools

Tools are functions that can be executed by clients. To register a tool:

```javascript
server.registerTool({
  name: 'tool_name',
  description: 'Description of the tool',
  parameters: {
    // JSON Schema for parameters
    type: 'object',
    properties: {
      param1: {
        type: 'string',
        description: 'Description of param1'
      }
    },
    required: ['param1']
  },
  returns: {
    // JSON Schema for return value
    type: 'object',
    properties: {
      result: {
        type: 'string',
        description: 'Description of result'
      }
    }
  },
  handler: async (params) => {
    // Tool implementation
    return {
      result: `Processed: ${params.param1}`
    };
  }
});
```

### Prompts

Prompts are reusable templates for LLM interactions. To register a prompt:

```javascript
server.registerPrompt({
  name: 'prompt_name',
  description: 'Description of the prompt',
  parameters: {
    // JSON Schema for parameters
    type: 'object',
    properties: {
      param1: {
        type: 'string',
        description: 'Description of param1'
      }
    }
  },
  template: 'This is a prompt template with {{param1}} as a parameter.',
  handler: async (params) => {
    // Generate the prompt content
    return {
      content: `This is a prompt with ${params.param1} as a parameter.`
    };
  }
});
```

## Dynamic Updates

MCP servers can send notifications about resource updates:

```javascript
// Update a resource
server.updateResource('/path/to/resource', {
  contentType: 'application/json',
  content: JSON.stringify({ /* updated content */ })
});
```

## Error Handling

Proper error handling is important for MCP servers:

```javascript
server.registerTool({
  name: 'risky_tool',
  // ... other properties ...
  handler: async (params) => {
    try {
      // Tool implementation
      return { result: 'Success' };
    } catch (error) {
      // Convert errors to MCP error format
      throw {
        code: 'tool_execution_error',
        message: error.message,
        data: {
          details: error.stack
        }
      };
    }
  }
});
```

## Testing Your Server

You can use the MCP toolkit to test your server:

```javascript
import { McpClient, StdioClientTransport } from '@modelcontextprotocol/toolkit';

async function testServer() {
  const client = new McpClient();
  
  const transport = new StdioClientTransport({
    command: 'node',
    args: ['path/to/your/server.js']
  });
  
  await client.connect(transport);
  
  // Test tool execution
  const result = await client.callTool('greet', { name: 'World' });
  console.log('Tool result:', result);
  
  // Test resource reading
  const resource = await client.readResource('mcp://my-custom-server/info');
  console.log('Resource content:', resource);
  
  await client.close();
}

testServer();
```

## Advanced Server Features

### Authentication

For servers requiring authentication:

```javascript
server.requireAuthentication((headers) => {
  const token = headers['authorization'];
  if (!token || !validateToken(token)) {
    throw new Error('Unauthorized');
  }
  return { userId: getUserIdFromToken(token) };
});
```

### Persistent State

Servers might need to maintain state between requests:

```javascript
const state = new Map();

server.registerTool({
  name: 'store_value',
  // ... other properties ...
  handler: async (params, context) => {
    state.set(params.key, params.value);
    return { success: true };
  }
});

server.registerTool({
  name: 'get_value',
  // ... other properties ...
  handler: async (params, context) => {
    return { value: state.get(params.key) };
  }
});
```

## Server Security Considerations

- Validate all input parameters
- Implement proper authentication and authorization
- Limit resource sizes and tool execution times
- Avoid exposing sensitive information
- Implement rate limiting for tools and resources
- Log all access and tool executions

## Deploying an MCP Server

MCP servers can be deployed in various ways:

1. **Local Process**: Run the server as a child process from the client application
2. **HTTP Server**: Expose the MCP server over HTTP for remote access
3. **Containerized**: Deploy in Docker or other containerization solutions
4. **Serverless**: Deploy as serverless functions (with some limitations)

## Examples

For more examples of MCP servers, see:

- [Echo Server](../src/tools/echo-server.js) - A simple example server included in this toolkit
- [Weather Server](https://github.com/modelcontextprotocol/server-weather) - A sample weather data server
- [GitHub Server](https://github.com/modelcontextprotocol/server-github) - A GitHub API integration server