# MCP Server Demo

这是一个支持多种传输方式的 MCP (Model Context Protocol) Server演示项目，使用 TypeScript 和 Nodejs 构建，支持 STDIO、SSE 和 StreamableHttp 三种传输方式。

## 功能特性

- **STDIO 传输**: 标准输入输出传输，适合命令行工具集成
- **SSE 传输**: Server-Sent Events 传输，适合 Web 应用实时通信
- **StreamableHttp 传输**: 可流式传输的 HTTP 传输，适合 Web API 集成
- **工具支持**: 内置加法工具演示
- **命令行界面**: 使用 Commander.js 提供友好的命令行界面
- **健康检查**: 内置健康检查和服务信息端点
- **CORS 支持**: 内置跨域请求支持
- **优雅关闭**: 优雅关闭服务器

## 安装依赖

```bash
pnpm install
```

## 构建项目

```bash
pnpm run build
```

## 使用方法

### 查看帮助

```bash
node build/index.js --help
```

输出：
```
Usage: mcp-server-demo [options] [command]

A demo MCP server

Options:
  -V, --version      display version number
  -h, --help         display help for command

Commands:
  stdio              Start MCP server with STDIO transport
  sse [options]      Start MCP server with SSE transport
  http|streamable    Start MCP server with StreamableHttp transport
  help [command]     display help for command
```

### 1. STDIO 传输

```bash
node build/index.js stdio
```

这是标准的 MCP 传输方式，适合与 Claude Desktop、Cursor 等客户端集成。

### 2. SSE 传输

```bash
node build/index.js sse
# 或指定端口
node build/index.js sse --port 3000
```

启动后可以访问：
- **SSE 端点**: `http://localhost:3000/sse`
- **消息端点**: `http://localhost:3000/message`
- **健康检查**: `http://localhost:3000/health`
- **服务信息**: `http://localhost:3000/info`

### 3. StreamableHttp 传输

```bash
node build/index.js http
# 或者使用别名
node build/index.js streamable --port 3000
```

启动后可以访问：
- **MCP 端点**: `http://localhost:3000/mcp`
- **健康检查**: `http://localhost:3000/health`
- **服务信息**: `http://localhost:3000/info`

## API 端点

### 健康检查

```bash
curl http://localhost:3000/health
```

响应：
```json
{
  "status": "ok",
  "transport": "sse",
  "timestamp": "2024-01-01T00:00:00.000Z"
}
```

### 服务信息

```bash
curl http://localhost:3000/info
```

响应：
```json
{
  "name": "mcp-server-demo",
  "version": "0.0.1",
  "description": "A demo MCP server",
  "transport": "sse",
  "endpoints": {
    "health": "/health",
    "info": "/info",
    "sse": "/sse"
  },
  "timestamp": "2024-01-01T00:00:00.000Z"
}
```

### SSE 连接

使用 JavaScript 连接 SSE：

```javascript
const eventSource = new EventSource('http://localhost:3000/sse');

eventSource.onmessage = function(event) {
  const data = JSON.parse(event.data);
  console.log('Received:', data);
};

eventSource.onerror = function(error) {
  console.error('SSE error:', error);
};
```

### 发送消息到 SSE

```bash
curl -X POST http://localhost:3000/message?sessionId=<session-id> \
  -H "Content-Type: application/json" \
  -d '{"method": "tools/list"}'
```

## 工具演示

项目内置了一个加法工具，演示 MCP 工具的使用：

```typescript
// 位于 src/tools/add.ts
export function registerAddTool(server: McpServer) {
  server.registerTool("add", {
    title: "Addition Tool",
    description: "Add two numbers",
    inputSchema: { a: z.number(), b: z.number() }
  }, async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b) }]
  }));
}
```

## 开发说明

### 项目结构

```
src/
├── index.ts        # 主服务器文件
└── tools/
    └── add.ts      # 加法工具实现
```

### 技术栈

- **TypeScript**: 类型安全的 JavaScript
- **Commander**: 命令行参数解析
- **Node.js HTTP**: 内置 HTTP 服务器
- **MCP SDK**: Model Context Protocol 实现
- **Zod**: 类型验证库

### 添加新工具

1. 在 `src/tools/` 目录下创建新的工具文件
2. 在 `src/index.ts` 中的 `createMcpServer` 函数中注册新工具

示例：
```typescript
// src/tools/multiply.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

export function registerMultiplyTool(server: McpServer) {
  server.registerTool("multiply", {
    title: "Multiplication Tool",
    description: "Multiply two numbers",
    inputSchema: { a: z.number(), b: z.number() }
  }, async ({ a, b }) => ({
    content: [{ type: "text", text: String(a * b) }]
  }));
}
```

然后在 `src/index.ts` 中注册：
```typescript
import { registerMultiplyTool } from "./tools/multiply.js";

function createMcpServer(): McpServer {
  const server = new McpServer({
    name: MCP_INFO.name,
    version: MCP_INFO.version
  });
  registerAddTool(server);
  registerMultiplyTool(server); // 添加这行
  return server;
}
```

## 脚本命令

```bash
# 开发模式（构建并运行）
pnpm run dev

# 构建项目
pnpm run build

# 运行构建后的项目
pnpm run start

# 使用 MCP Inspector 调试
pnpm run inspector

# 发布到 npm
pnpm run publish:patch   # 小版本更新
pnpm run publish:minor   # 次版本更新
pnpm run publish:major   # 主版本更新
```

## 部署说明

### 使用 PM2 部署

```bash
# 全局安装 PM2
npm install -g pm2

# 启动应用
pm2 start build/index.js --name mcp-server-sse -- sse --port 3000
pm2 start build/index.js --name mcp-server-http -- http --port 3000

# 查看状态
pm2 status

# 查看日志
pm2 logs mcp-server-sse
```

### 使用 Docker 部署

创建 `Dockerfile`:

```dockerfile
FROM node:18-alpine

WORKDIR /app

COPY package*.json ./
RUN npm ci --only=production

COPY build ./build

EXPOSE 3000

CMD ["node", "build/index.js", "sse"]
```

构建和运行：
```bash
docker build -t mcp-server-demo .
docker run -p 3000:3000 mcp-server-demo
```

## 与 Claude Desktop、Cursor 等集成

### STDIO 传输集成

在 Claude Desktop、Cursor 等产品的MCP配置文件中添加：

```json
{
  "mcpServers": {
    "mcp-server-demo": {
      "command": "node",
      "args": ["/path/to/your/build/index.js", "stdio"]
    }
  }
}
```

### SSE 传输集成

对于支持SSE传输的客户端，可以使用HTTP配置：

```json
{
  "mcpServers": {
    "mcp-server-demo-sse": {
      "url": "http://localhost:3000/sse",
      "type": "sse"
    }
  }
}
```

或者通过环境变量启动：

```bash
# 先启动SSE服务器
node build/index.js sse --port 3000

# 然后配置客户端连接到 http://localhost:3000/sse
```

### StreamableHttp 传输集成

对于支持StreamableHttp传输的客户端：

```json
{
  "mcpServers": {
    "mcp-server-demo-http": {
      "url": "http://localhost:3000/mcp",
      "type": "streamable"
    }
  }
}
```

或者通过环境变量启动：

```bash
# 先启动StreamableHttp服务器
node build/index.js http --port 3000

# 然后配置客户端连接到 http://localhost:3000/mcp
```

### 传输方式选择指南

- **STDIO**: 适合本地开发和桌面应用集成，最稳定
- **SSE**: 适合Web应用和实时通信场景，支持服务端推送
- **StreamableHttp**: 适合REST API风格的集成，支持流式响应

### 客户端集成示例

#### JavaScript/TypeScript 客户端

```typescript
// SSE 连接示例
const eventSource = new EventSource('http://localhost:3000/sse');

eventSource.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log('MCP Message:', data);
};

// 发送消息到服务器
const sendMessage = async (message: any, sessionId: string) => {
  const response = await fetch(`http://localhost:3000/message?sessionId=${sessionId}`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(message),
  });
  return response.json();
};
```

#### Python 客户端

```python
import requests
import json

# StreamableHttp 连接示例
class MCPClient:
    def __init__(self, base_url="http://localhost:3000"):
        self.base_url = base_url
    
    def call_tool(self, tool_name, arguments):
        response = requests.post(f"{self.base_url}/mcp", json={
            "method": "tools/call",
            "params": {
                "name": tool_name,
                "arguments": arguments
            }
        })
        return response.json()
    
    def list_tools(self):
        response = requests.post(f"{self.base_url}/mcp", json={
            "method": "tools/list"
        })
        return response.json()

# 使用示例
client = MCPClient()
result = client.call_tool("add", {"a": 5, "b": 3})
print(result)
```

## 故障排除

### 常见问题

1. **端口已被占用**
   ```bash
   # 查找占用端口的进程
   lsof -i :3000
   # 杀死进程
   kill -9 <PID>
   ```

2. **构建失败**
   ```bash
   # 清除 node_modules 重新安装
   rm -rf node_modules
   pnpm install
   ```

3. **SSE 连接失败**
   - 检查 CORS 配置
   - 确保防火墙允许端口访问
   - 查看服务器日志

### 日志查看

运行时日志会显示：
- 🚀 服务启动成功
- 📡 SSE 客户端连接/断开
- 🔍 健康检查访问
- 📋 服务信息查询
- 🛑 优雅关闭信号

## 配置说明

主要配置在 `src/index.ts` 中：

```typescript
const MCP_INFO = {
  name: "mcp-server-demo",
  version: "0.0.1",
  description: "A demo MCP server"
};

const DEFAULT_PORT = 3000;
```

## 贡献指南

1. Fork 项目
2. 创建功能分支 (`git checkout -b feature/amazing-feature`)
3. 提交更改 (`git commit -m 'Add some amazing feature'`)
4. 推送到分支 (`git push origin feature/amazing-feature`)
5. 发起 Pull Request

## 许可证

[MIT License](./LICENSE)

## 作者

isboyjc 