mcp-simulator
by huafua
README.md
# MCP Simulator (Node.js MCP Server)
`mcp simulator` 是一個基於 Node.js 構建的輕量級 **MCP 伺服器 (Model Context Protocol Server)**。本專案採用零外部依賴設計(僅使用原生 `http` 模組),透過模組化的 `McpServer` 與 `McpRegistry` 提供動態的工具註冊與 HTTP 遠端調用(RPC)能力。
---
## 🚀 核心特性
- **零外部依賴**:完全依賴 Node.js 原生的 `http` 模組,無需 `express` 等框架。
- **全新 MCP 核心架構**:
- `McpRegistry`:負責維護工具清單與執行邏輯(支援同步與非同步 `async` 方法)。
- `McpServer`:提供基於 HTTP POST 的執行入口與統一的 JSON 回應封裝。
- **簡潔的 API 註冊設計**:提供支援鏈式調用的 `register()` 介面,僅需提供「工具定義」與「執行回呼」兩個參數即可輕鬆註冊。
- **內建工具與反射機制**:
- 內建 `tool/list` 動態查詢所有已註冊的工具。
- 提供同步計算、文字處理以及非同步 (`async`) 模擬 API 請求(`fetch-posts`)等完整示範。
---
## 📁 檔案結構
```text
mcp-simulator/
├── mcp.core.js # 伺服器核心引擎(定義 McpServer 與 McpRegistry 類別)
├── index.js # 專案主入口(載入核心引擎並註冊具體工具)
├── index.http # HTTP API 測試腳本(搭配 VS Code REST Client 使用)
├── package.json # 專案配置文件
└── README.md # 本專案說明文件
```
---
## ⚙️ 快速開始
### 啟動伺服器
請在專案根目錄執行以下指令:
```bash
node index.js
```
伺服器預設會監聽 `8889` 端口(或讀取環境變數 `PORT`)。啟動後控制台將顯示:
```text
Server running at 8889
```
---
## 🔌 API 協議規範
所有的 API 調用均透過單一入口點進行。
- **請求方法**:`POST`
- **伺服器位址**:`http://localhost:8889`
- **請求標頭 (Header)**:`Content-Type: application/json`
- **請求體格式 (Payload)**:
```json
{
"name": "要調用的工具名稱",
"args": {
"參數鍵": "參數值"
}
}
```
### 統一回應結構 (Response)
所有請求成功處理後,伺服器將回傳統一封裝的 JSON 結構:
```json
{
"code": 200,
"message": "success",
"data": {
/* 工具回傳的原始結果 */
}
}
```
#### 伺服器錯誤狀態一覽
| HTTP 狀態碼 | 情境說明 | 回應內容 (JSON) |
| :---------: | :----------------------------------------- | :-------------------------------------------------------------------- |
| **200** | **Header 錯誤**(未指定 application/json) | `{"code": 406, "message": "Content-type must be 'application/json'"}` |
| **200** | **JSON 格式錯誤**(無法被解析) | `{"code": 500, "message": "Request body is not valid format"}` |
| **200** | **未提供工具名稱**(缺少 name 欄位) | `{"code": 406, "message": "Name must be provided"}` |
| **200** | **呼叫未註冊的工具** | `{"code": 200, "message": "success", "data": null}` |
---
## 🛠️ 內建方法調用示例
以下是以 `localhost:8889` 為例的實際調用資料:
### 1. 獲取可用工具清單 (`tool/list`)
列出伺服器中已註冊的所有工具定義。
- **請求 Payload**:`{"name": "tool/list", "args": {}}`
- **回應範例**:
```json
{
"code": 200,
"message": "success",
"data": [
{ "name": "info", "description": "..." },
{
"name": "hello",
"description": "just say hello to someone",
"args": { "username": "string" }
},
{
"name": "calculate",
"description": "calculate sum of two numbers",
"args": { "a": "number", "b": "number" }
},
{
"name": "fetch-posts",
"description": "fetch posts from https://jsonplaceholder.typicode.com/posts"
}
]
}
```
### 2. 計算兩數之和 (`calculate`)
- **請求 Payload**:`{"name": "calculate", "args": {"a": 20, "b": 30}}`
- **回應範例**:
```json
{
"code": 200,
"message": "success",
"data": { "result": 50 }
}
```
### 3. 非同步請求測試 (`fetch-posts`)
示範 `async` 回呼函數的用法,返回一組使用者的假資料(陣列)。
- **請求 Payload**:`{"name": "fetch-posts"}`
- **回應範例**:
```json
{
"code": 200,
"message": "success",
"data": [
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz"
// ... (其他資料略)
}
]
}
```
---
## 📝 開發與擴充自定義工具
您可以修改 `index.js`,透過鏈式調用 `.register()` 新增您的工具。
### API 簽名
```javascript
server.register(toolDefinition, callback);
```
- **`toolDefinition`** (Object): 必須包含 `name`,並可選提供 `description` 與 `args`(參數定義)。
- **`callback`** (Function / Async Function): 當接收到請求時執行的回呼。接收一個來自 `req.params.args` 的**單一物件參數**。
### 註冊範例
```javascript
const { McpServer } = require("./mcp.core");
new McpServer(8889)
// 註冊一個需要參數的非同步工具
.register(
{
name: "get_user",
description: "獲取特定使用者資料",
args: { userId: "number" },
},
async ({ userId }) => {
// ⚠️ 必須使用物件解構讀取參數
const user = await database.find(userId);
return { result: user };
},
)
.start();
```
> **💡 開發重點提醒:**
>
> 1. **參數接收**:因為客戶端傳來的 `args` 會被當作**單一物件**傳遞給回呼函數,所以若工具定義了多個參數,請務必在回呼函數使用 `{ param1, param2 }` 進行**物件解構**。
> 2. **非同步支援**:`McpRegistry` 內部使用 `await` 執行工具,您可以放心在回呼函數中使用 `async/await` 進行資料庫查詢或發送網路請求。
---
## 📄 授權協議
本專案採用 [MIT License](LICENSE) 條款進行開源。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues