2025 自建 MCP Server | 打造你的 C++ AI 代理編程助手


MCP Server — 雖然聽起來很技術性,但它正在悄悄改變我們與 AI 的互動方式。
回想你第一次使用 AI 編程助手的經驗:它可以寫出優雅的程式碼,解釋複雜的概念,但當你問:「這段程式碼能真正運行嗎?」時,得到的總是:「請您自行編譯測試。」

MCP Server 正好彌補了這個空缺。它將 AI 從一個靜態的知識來源,轉變為能夠實際行動的智能夥伴——可以編譯程式碼、運行測試、分析數據,甚至從網路上獲取資訊。
它不只是一個協議,而是讓 AI 真正與現實世界互動的橋樑。

MCP Server

什麼是 MCP Server?

MCP Server 是基於 Model Context Protocol(MCP) 的伺服器服務,
它可以讓 AI 助手(如 ChatGPT、Claude 或 Gemini)安全地與外部工具、本地檔案和系統環境互動。

簡單來說,它是 AI 與現實世界之間的橋樑
透過 MCP 伺服器,AI 不再只是依據訓練資料生成文字,而是可以真正「動手」操作,例如:

  • 讀取或修改專案檔案
  • 執行系統指令或編譯程式碼
  • 查詢資料庫或 API
  • 運行測試並分析結果

換句話說,MCP 伺服器 將 AI 從靜態的「知識庫」轉變為 能夠積極參與工作流程的智能夥伴

MCP 伺服器核心運作模式

MCP Server 的運作模式本質上是 一個 AI 與外部工具之間的橋樑,其核心流程可以分為以下幾個步驟:

  • 註冊工具(Tool Registration)
  • 建立通訊通道(Transport Layer)
  • 接收 AI 請求(Request Handling)
  • 執行工具(Tool Execution)
  • 回傳結果給 AI(Response Delivery)
  • 安全與權限控制(Optional Security Layer)

為什麼 C++ 開發者需要自建 MCP Server?

對 C++ 開發者來說,MCP Server 的好處非常明顯:

功能傳統 AI 助手MCP Server 加持後
讀取專案代碼❌ 需手動貼上代碼✅ 自動讀取指定資料夾
編譯測試❌ 無法執行指令✅ 可呼叫 g++cmake
單元測試❌ 無法執行✅ 直接跑測試並回報結果
錯誤分析❌ 僅語法推測✅ 根據實際錯誤訊息分析
自動修正❌ 被動建議✅ 主動修改並重新編譯

開發環境

在開始自建 MCP 伺服器前,需要先準備好 本地 C++ 編譯器(如 g++cmake,並確保在系統 PATH 中),以及 開發工具(建議使用 VS Code,可安裝 Continue 插件,提供語法補全、程式碼導航與編輯便利)。

接下來,建立 MCP 伺服器專案的基本步驟如下:

  • 安裝 Node.js

Node.js 是 MCP 伺服器運行的核心環境,建議安裝 LTS(Long Term Support)版本,以確保穩定性。

官方下載:Node

安裝 Node.js 後,在終端輸入:

node -v
npm -v
npx -v

若三者都能正常顯示版本號(例如 v18.x.x、v10.x.x 等),代表 Node.js、npm、npx 都已成功安裝。

  • 建立專案資料夾

建議建立獨立資料夾管理專案,例如:cpp-mcp,方便組織代碼與依賴。

mkdir cpp-mcp
cd cpp-mcp
  • 初始化 Node 專案
npm init -y

這個指令會生成 package.json 文件,用於管理專案依賴、版本與腳本。

  • 安裝 MCP SDK
install @modelcontextprotocol/sdk

實戰開始:打造你的 C++ MCP 伺服器

  • 在專案目錄中建立 server.js
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import fs from "fs";
import path from "path";
import { execSync } from "child_process";

console.error("🚀 Starting C++ MCP Server...");

// Define available tools
const tools = [
  {
    name: "write_file_proxy",
    description: "Write content to file",
    inputSchema: {
      type: "object",
      properties: {
        path: { type: "string" },
        content: { type: "string" },
        mode: { 
          type: "string", 
          enum: ["overwrite", "append", "error"],
          default: "overwrite" 
        },
      },
      required: ["path", "content"],
    },
  },
  {
    name: "compile_and_run",
    description: "Compile and run a C++ file",
    inputSchema: {
      type: "object",
      properties: {
        path: { type: "string" },
      },
      required: ["path"],
    },
  }
];

// Create MCP server instance
const server = new Server(
  {
    name: "cpp-ai-proxy",
    version: "1.0.0",
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

// Handle tool listing requests
server.setRequestHandler(ListToolsRequestSchema, async () => {
  console.error("📋 Listing tools...");
  return {
    tools: tools
  };
});

// Handle tool execution requests
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  console.error(`🔧 Tool called: ${request.params.name}`);
  const { name, arguments: args } = request.params;
  
  if (name === "write_file_proxy") {
    const { path: filePath, content, mode = "overwrite" } = args;
    const absPath = path.resolve(filePath);
    
    try {
      // Check if file exists and handle based on mode
      if (fs.existsSync(absPath) && mode === "error") {
        return {
          content: [{ type: "text", text: `❌ File exists: ${absPath}` }]
        };
      }
      
      // Create directory if it doesn't exist
      const dir = path.dirname(absPath);
      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir, { recursive: true });
      }
      
      // Write or append content based on mode
      if (fs.existsSync(absPath) && mode === "append") {
        fs.appendFileSync(absPath, content, "utf8");
      } else {
        fs.writeFileSync(absPath, content, "utf8");
      }
      
      return {
        content: [{ type: "text", text: `✅ File written: ${absPath}` }]
      };
    } catch (error) {
      return {
        content: [{ type: "text", text: `❌ Error: ${error.message}` }]
      };
    }
  }
  
  if (name === "compile_and_run") {
    const { path: filePath } = args;
    const absPath = path.resolve(filePath);
    
    try {
      // Check if source file exists
      if (!fs.existsSync(absPath)) {
        return {
          content: [{ type: "text", text: `❌ File not found: ${absPath}` }]
        };
      }
      
      // Compile C++ code
      const exePath = absPath.replace(/\.cpp$/, "");
      console.error(`🛠️ Compiling: ${absPath}`);
      execSync(`g++ "${absPath}" -o "${exePath}"`, { stdio: 'pipe' });
      
      // Execute the compiled program
      console.error(`🚀 Running: ${exePath}`);
      const output = execSync(`"${exePath}"`, { encoding: "utf8", stdio: 'pipe' });
      
      return {
        content: [{ type: "text", text: `✅ Output:\n${output}` }]
      };
    } catch (error) {
      // Extract meaningful error information
      const errorOutput = error.stderr ? error.stderr.toString() : error.message;
      return {
        content: [{ type: "text", text: `❌ Compilation or execution failed:\n${errorOutput}` }]
      };
    }
  }
  
  // Handle unknown tools
  throw new Error(`Unknown tool: ${name}`);
});

// Global error handler for the server
server.onerror = (error) => {
  console.error('❌ Server error:', error);
};

// Connection close handler
server.onclose = () => {
  console.error('🔌 Server connection closed');
};

// Main server startup function
async function main() {
  try {
    console.error("📡 Connecting to transport...");
    const transport = new StdioServerTransport();
    await server.connect(transport);
    console.error("✅ C++ MCP Server running and connected!");
  } catch (error) {
    console.error('💥 Failed to start server:', error);
    process.exit(1);
  }
}

// Start the server
main().catch(console.error);
  • 配置 VSCode 與 Continue 插件

在創建的目錄中如 cpp-mcp/.continue/mcpServers 新建 new-mcp-server.yaml

name: New MCP server
version: 0.0.1
schema: v1
mcpServers:
  - name: New MCP server
    command: npx
    args:
      - -y
      - node
      - Your/cpp-mcp/server.js

專案結構

C++ MCP Server 專案結構:

cpp-mcp/
├── .continue/          # VSCode Continue 插件配置目錄
├── node_modules/       # Node.js 依賴包(自動生成)
├── package.json        # 專案配置和依賴定義
├── package-lock.json   # 依賴版本鎖定文件
├── server.js           # MCP 伺服器主程式
├── test                # 編譯後的可執行文件
└── test.cpp           # C++ 測試源碼文件

測試 C++ MCP

  • 啟動伺服器
node server.js
  • 在 VSCode 中測試

打開 Continue 聊天面板,嘗試以下指令:

請幫我創建一個簡單的 Hello World C++ 程序,然後編譯並運行它
  • AI 將會:
1. 自動創建 C++ 源碼文件
2. 調用 compile_cpp 工具進行編譯
3. 使用 run_executable 工具運行程序
4. 返回完整的執行結果

說明 server.js

一個讓 AI 能夠實際操作文件和運行 C++ 代碼的橋樑程式。

兩個主要功能:

  • 寫檔案工具
write_file_proxy({
    path: "test.cpp",
    content: "C++ code",
    mode: "overwrite" // overwrite/append/error
})

創建或修改文件,自動建立資料夾。

  • 編譯執行工具
compile_and_run({
    path: "test.cpp"
})

自動編譯 C++ 並運行,返回執行結果。

// AI 可以這樣使用我:
1. "請創建一個 hello.cpp 文件,內容是 Hello World 程序"
   → 調用 write_file_proxy 工具

2. "請編譯並運行 hello.cpp"
   → 調用 compile_and_run 工具

3. 獲得結果:"✅ Output: Hello World!"

結論

MCP Server 的出現,讓 AI 不再只是被動的代碼生成器,而是真正能「參與」開發流程的智能夥伴。對 C++ 開發者而言,它不僅能理解程式語意,更能實際操作編譯器、執行測試、分析錯誤,讓開發從對話走向行動。

透過自建 MCP 伺服器並整合 VS Code 的 Continue 插件,AI 助手終於能直接與你的專案環境互動。從編譯、調試到分析錯誤,全程自動化與即時回饋,讓開發體驗更流暢、更貼近真實工程場景。

這只是開始。未來你可以擴充 MCP 伺服器,整合更多工具如單元測試、靜態分析或性能監控,
讓 AI 成為團隊開發中的核心助力,一位永不疲倦的 C++ 夥伴。