Skip to content
Back to skills

Scaffold Mcp Server

ASecurity

Scaffold a new MCP server from tool specifications using the official SDK (TypeScript or Python), including transport configuration, tool handlers, and test harness. Use when you have a tool specification and need a working server, when starting a new MCP server project and want correct structure from the start, when migrating an existing tool integration to the MCP protocol, or when prototyping a tool surface to test with Claude Code before full implementation.

  • 31 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 3, 2026
ai-agentstypescriptpythongobashnodedockerapi

Works with

  • claude code
  • claude desktop
  • cli
  • api
  • mcp

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned September 3, 2026

npx -y skills add pjt222/agent-almanac --skill scaffold-mcp-server --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Scaffold Mcp Server?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Scaffold Mcp Server
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/pjt222-scaffold-mcp-server-5841cf05/badge)](https://www.skillsdirectory.com/skills/pjt222-scaffold-mcp-server-5841cf05)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: scaffold-mcp-server
locale: wenyan-lite
source_locale: en
source_commit: 82c77053
fence_basis_commit: 82c77053
translator: "Julius Brussee homage — caveman"
translation_date: "2026-05-03"
description: >
  Scaffold a new MCP server from tool specifications using the official SDK
  (TypeScript or Python), including transport configuration, tool handlers,
  and test harness. Use when you have a tool specification and need a working
  server, when starting a new MCP server project and want correct structure
  from the start, when migrating an existing tool integration to the MCP
  protocol, or when prototyping a tool surface to test with Claude Code before
  full implementation.
license: MIT
allowed-tools: Read Write Edit Bash Grep Glob
metadata:
  author: Philipp Thoss
  version: "1.0"
  domain: mcp-integration
  complexity: intermediate
  language: multi
  tags: mcp, scaffold, sdk, typescript, python, server
---

# 構建 MCP 伺服器腳手架

依工具規格文件以官方 MCP SDK(TypeScript 或 Python)產生完整、可執行之 MCP 伺服器項目。

## 適用時機

- 已有工具規格(來自 `analyze-codebase-for-mcp` 或手寫)並需可運行之伺服器
- 新建 MCP 伺服器項目並欲從一開始有正確結構
- 將既有工具整合遷移至 MCP 協議
- 於完整實作前以工具表面原型測試 Claude Code
- 同時需伺服器骨架與 CI 之測試框架

## 輸入

- **必要**:工具規格文件(YAML 或 JSON,含工具名、參數、回傳類型)
- **必要**:目標語言(`typescript` 或 `python`)
- **必要**:傳輸類型(`stdio` 或 `sse`)
- **選擇性**:輸出目錄(預設:當前目錄)
- **選擇性**:套件名與版本
- **選擇性**:認證方式(`none`、`bearer-token`、`api-key`)
- **選擇性**:Docker 打包(`true` 或 `false`,預設:`false`)

## 步驟

### 步驟一:選擇 SDK 語言與傳輸

1.1. 依項目情境選擇實作語言:
   - **TypeScript**:適合 Node.js 生態、近 web 工具、JSON 重之工作負載
   - **Python**:適合資料科學、ML 與科學計算工具表面

1.2. 選擇傳輸機制:
   - **stdio**:本地工具執行之預設。Claude Code 將伺服器作為子程序啟動。
   - **SSE(Server-Sent Events)**:用於遠端/共享伺服器。需 HTTP 託管。

1.3. 決定認證需求:
   - **none**:本地 stdio 伺服器(程序級信任)
   - **bearer-token**:遠端 SSE 伺服器,靜態 token
   - **api-key**:遠端伺服器,每客戶之鑰匙

**預期:** 語言、傳輸與認證選擇已書面記錄。

**失敗時:** 若需求不明,預設 TypeScript + stdio + 無認證以最快達成可運行之伺服器。

### 步驟二:初始化項目結構

2.1. 建立項目目錄並初始化:

**TypeScript:**

```bash
mkdir -p $PROJECT_NAME && cd $PROJECT_NAME
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node tsx
npx tsc --init --target ES2022 --module nodenext --moduleResolution nodenext --outDir dist
```

**Python:**

```bash
mkdir -p $PROJECT_NAME && cd $PROJECT_NAME
python -m venv .venv
source .venv/bin/activate
pip install mcp pydantic
```

2.2. 建立標準目錄結構:

```text
$PROJECT_NAME/
├── src/
│   ├── index.ts|main.py      # Server entry point
│   ├── tools/                 # One file per tool category
│   │   ├── index.ts|__init__.py
│   │   └── [category].ts|.py
│   └── utils/                 # Shared utilities
│       └── validation.ts|.py
├── test/
│   ├── harness.ts|.py         # MCP test harness
│   └── tools/
│       └── [category].test.ts|.py
├── package.json|pyproject.toml
├── tsconfig.json              # TypeScript only
├── Dockerfile                 # If Docker requested
└── README.md
```

2.3. 為 npm(TypeScript)加 bin 入口或為 Python 加入口點:

**TypeScript package.json:**

```json
{
  "name": "$PACKAGE_NAME",
  "version": "1.0.0",
  "type": "module",
  "bin": { "$PACKAGE_NAME": "./dist/index.js" },
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js",
    "dev": "tsx src/index.ts",
    "test": "tsx test/harness.ts"
  }
}
```

**預期:** 可建構之項目骨架,所有依賴皆已安裝。

**失敗時:** 若 npm/pip 安裝失敗,檢查網路連線與註冊表存取。TypeScript 需 Node.js >= 18。Python 需 Python >= 3.10。

### 步驟三:依規格實作工具處理器

3.1. 解析工具規格文件,並為每工具產生處理器:

**TypeScript 處理器範本:**

```typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

export function registerTools(server: McpServer): void {
  server.tool(
    "tool_name",
    "Tool description from spec",
    {
      param1: z.string().describe("Parameter description"),
      param2: z.number().optional().default(10).describe("Optional param"),
    },
    async ({ param1, param2 }) => {
      try {
        // TODO: Implement tool logic
        const result = await performAction(param1, param2);
        return {
          content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
        };
      } catch (error) {
        return {
          content: [{ type: "text", text: `Error: ${(error as Error).message}` }],
          isError: true,
        };
      }
    }
  );
}
```

**Python 處理器範本:**

```python
from mcp.server import Server
from mcp.types import Tool, TextContent
from pydantic import BaseModel

class ToolNameParams(BaseModel):
    param1: str
    param2: int = 10

async def handle_tool_name(params: ToolNameParams) -> list[TextContent]:
    try:
        result = await perform_action(params.param1, params.param2)
        return [TextContent(type="text", text=json.dumps(result, indent=2))]
    except Exception as e:
        return [TextContent(type="text", text=f"Error: {e}")]
```

3.2. 由規格為每工具類別產生一處理器文件。

3.3. 於類型檢查之外加入輸入驗證:
   - 字串長度限制
   - 數值範圍邊界
   - 列舉值約束
   - 必填欄位強制

3.4. 為所有預期之失敗模式加入結構化錯誤回應。

**預期:** 每類別一處理器文件,附類型化參數與錯誤處理。

**失敗時:** 若規格含模糊類型,預設 `string` 並加 TODO 註解供手動細修。

### 步驟四:配置傳輸

4.1. 以所選傳輸建立伺服器入口點:

**stdio(TypeScript):**

```typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { registerTools } from "./tools/index.js";

const server = new McpServer({
  name: "$PACKAGE_NAME",
  version: "1.0.0",
});

registerTools(server);

const transport = new StdioServerTransport();
await server.connect(transport);
```

**SSE(TypeScript):**

```typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import { registerTools } from "./tools/index.js";

const server = new McpServer({
  name: "$PACKAGE_NAME",
  version: "1.0.0",
});

registerTools(server);

const transport = new SSEServerTransport("/messages", response);
await server.connect(transport);
```

4.2. 若需認證,加入中介層:
   - Bearer token:驗證 `Authorization` 標頭
   - API key:驗證 `X-API-Key` 標頭

4.3. 為 stdio 伺服器加 shebang 行以啟用直接執行:

```typescript
#!/usr/bin/env node
```

**預期:** 可運作之入口點於配置之傳輸啟動 MCP 伺服器。

**失敗時:** 若 SDK 版本與引入路徑不符,檢查 `@modelcontextprotocol/sdk` 版本並調整引入。SDK 於版本間重整路徑。

### 步驟五:建立測試框架

5.1. 建構測試框架以驗證每工具:

```typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";

async function runTests(): Promise<void> {
  const server = createServer();
  const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();

  await server.connect(serverTransport);
  const client = new Client({ name: "test-client", version: "1.0.0" });
  await client.connect(clientTransport);

  // Test: tools/list returns all expected tools
  const tools = await client.listTools();
  console.assert(tools.tools.length === EXPECTED_TOOL_COUNT);

  // Test: each tool with valid input
  for (const tool of tools.tools) {
    const result = await client.callTool({
      name: tool.name,
      arguments: getTestInput(tool.name),
    });
    console.assert(!result.isError, `${tool.name} failed`);
  }

  // Test: each tool with invalid input returns isError
  for (const tool of tools.tools) {
    const result = await client.callTool({
      name: tool.name,
      arguments: getInvalidInput(tool.name),
    });
    console.assert(result.isError, `${tool.name} should reject invalid input`);
  }

  console.log("All tests passed");
}
```

5.2. 為每工具建立測試夾具:有效輸入、無效輸入與邊緣案例。

5.3. 加 `test` 腳本至 `package.json` 或 `pyproject.toml`。

**預期:** 測試框架以有效與無效輸入皆運用每工具。

**失敗時:** 若 SDK 版本中無 `InMemoryTransport`,退回將伺服器作為子程序啟動並透過 stdio 管道通訊。

### 步驟六:產生文件與配置

6.1. 產生 `README.md`,含:
   - 項目描述
   - 安裝指引
   - Claude Code 配置命令
   - Claude Desktop JSON 配置片段
   - 工具列表附描述與參數架構
   - 開發與測試指引

6.2. 產生 Claude Code 註冊命令:

```bash
# stdio transport
claude mcp add $PACKAGE_NAME stdio "node" "dist/index.js"

# SSE transport
claude mcp add $PACKAGE_NAME -e API_KEY=your_key -- mcp-remote http://localhost:3000/mcp
```

6.3. 產生 Claude Desktop 配置片段:

```json
{
  "mcpServers": {
    "$PACKAGE_NAME": {
      "command": "node",
      "args": ["path/to/dist/index.js"]
    }
  }
}
```

6.4. 若已要求 Docker,產生 `Dockerfile`:

```dockerfile
FROM node:20-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-slim
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/package.json .
ENTRYPOINT ["node", "dist/index.js"]
```

**預期:** 完整文件與配置文件可立即使用。

**失敗時:** 若產生之 README 含佔位值,搜尋項目以代換實際值。若 Docker 建構失敗,驗證基底映像符合所用之 Node.js/Python 版本。

## 驗證

- [ ] 項目無錯誤建構(`npm run build` 或等效)
- [ ] 伺服器啟動並回應 `tools/list` JSON-RPC 請求
- [ ] 規格中每工具皆已註冊且可發現
- [ ] 測試框架以有效輸入對所有工具通過
- [ ] 測試框架對無效輸入確認錯誤回應
- [ ] Claude Code 可經 `claude mcp add` 命令連接
- [ ] README 含可運作之安裝與配置指引
- [ ] 所有產生之代碼通過 linting(若已配置)

## 常見陷阱

- **SDK 引入路徑變化**:`@modelcontextprotocol/sdk` 套件於版本間重整其匯出。應始終檢查已安裝版本之實際匯出路徑。
- **遺忘 shebang**:直接呼叫之 stdio 伺服器需 `#!/usr/bin/env node` 作首行以可執行。
- **阻塞事件迴圈**:TypeScript 之工具處理器須為 `async`。同步操作阻塞伺服器上所有其他工具呼叫。
- **package.json 中遺漏 `type: "module"`**:MCP SDK 用 ESM 引入。無 `"type": "module"`,Node.js 將文件視為 CommonJS 而引入失敗。
- **Zod 架構漂移**:若工具規格演進而 Zod 架構未更新,驗證不匹配引發靜默失敗。應由單一真實源產生架構。
- **stdout 污染**:stdio 傳輸用 stdout 作 JSON-RPC。工具處理器中任何 `console.log` 將腐蝕協議流。應改用 `console.error` 或文件記錄器。

## 相關技能

- `analyze-codebase-for-mcp` - 產生此技能消費之工具規格
- `build-custom-mcp-server` - 複雜情況之手動伺服器實作
- `configure-mcp-server` - 將腳手架伺服器連至 Claude Code/Desktop
- `troubleshoot-mcp-connection` - 部署後除錯連線問題
- `containerize-mcp-server` - 將伺服器以 Docker 打包用於分發

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…