建議在我的部落格中 https://blog.ray-realms.com/article/73b7d4c5-fc5e-49e2-a7df-c675c4703300 閱讀此文章,以獲取更好的閱讀體驗
你是一位熱愛學習的工程師,這些年累積了超過 1000 篇個人筆記,散落在本地資料夾裡。涵蓋前端框架、後端架構、演算法、系統設計⋯⋯每一篇都是你花時間整理的寶貴知識。
某天,你想問 ChatGPT:「幫我找所有關於 React Hooks 的筆記,並整理出我還沒掌握的進階用法。」
這個需求聽起來很合理,對吧?但實際上,要讓 AI 助手做到這件事,困難重重。

讓我們快速看幾個現有的處理方式:
手動複製貼上? 效率極差,每次都要重複,而且 AI 只能看到你貼的部分,無法主動探索更多相關筆記。
批次上傳檔案? 跟剛剛一樣的問題,你得先猜哪些檔案相關,容易遺漏,而且每個新問題都要重新上傳。

用 Claude Code 或 Cursor? 它們的能力被綁死在特定工具裡,而且這些工具就是很會 Coding,不太會討論、發想創意。更重要的是,缺乏標準化 —— 每個工具都自己搞一套。

寫個 REST API? 這是最接近的方案,但有個致命問題:REST API 是為「程式」設計的,不是為「LLM」設計的。 LLM 不知道你有哪些 API,需要每次對話都重新被告知規格,還得自己猜該呼叫哪個 endpoint。
這就是 MCP 要解決的問題。
不知道你有沒有看過 Cyberpunk 2077?
在這個世界觀上,大部分的人都會安裝一推超酷的義肢,更強壯的手臂、更壯的機械腿...,但這些義肢要能正常運作,有個前提:義肢的接口必須符合標準規格。如果每個義肢廠商都自己搞一套接口,那你的手臂根本裝不上去。
MCP 就像是一本「AI 義肢製作手冊」。
ChatGPT、Claude 這些 AI 會根據這本手冊打造對應的「安裝槽」,而任何人都可以根據這份手冊,設計給 AI 使用的「義肢」,然後直接裝上去。
重點來了:MCP 只是一本製作手冊,用嚴謹的話來講就是:
它只決定「接口的部分長怎樣」,確保你做出來的義肢可以順利裝到其他 AI 身上。至於這個義肢有什麼功能?讀檔案、查資料庫、發 email、控制你的智慧家居⋯⋯隨便你,完全自由。
MCP 是為 LLM 設計的標準化協定,讓 AI 能夠自動發現和使用你的工具。
關鍵差異:
| 特性 | REST API | MCP | 
|---|---|---|
| 設計對象 | 給「開發者」用 | 給「LLM」用 | 
| 發現機制 | 需要讀文件 | AI 自動發現工具 | 
| 使用方式 | 需要寫程式呼叫 | AI 自動選擇並呼叫 | 
| 參數格式 | 需要查文件 | 設計 MCP 時,都會定義好 | 

這裡快速釐清一下概念。
AI(嚴格來說是 LLM)就是一個只會思考、無法行動的大腦。 對,他只是一顆大腦,沒手沒腳,無法行動。他可以思考得很深入、很精彩,但你問他「幫我查一下天氣」,他只能回答「抱歉我查不了」。
那什麼是 Agent 呢 簡單說,Agent = AI 大腦 + 能力(工具)。給 AI 裝上「手」(查天氣的工具)、「腳」(控制智慧家居的工具),他就從一顆只會想的大腦,變成一個能實際做事的 Agent。
MCP 就是定義「怎麼給 AI 裝義肢」的標準。
如果你對 AI Agent 的概念想要更深入了解,推薦閱讀我之前撰寫的書籍《從零開始,打造一個生成式 AI 平台》https://www.books.com.tw/products/0011029234 ,裡頭有更完整的講解。
如果說 AI 的大腦是語言模型,那麼 Tools 就是 AI 的義肢。
沒有義肢,大腦再聰明也只能思考,無法行動。有了 Tools,AI 才能:
這是 Tools 最重要的特性。你不需要明確指示「請呼叫 XXX 工具」,AI 會根據對話情境自己判斷。 AI 自己決定:
Tools 就是一個 Function,他執行完後的結果,會送回給 LLM 就像下面這三個 Function
list_notes()→ 返回:[note1.md, note2.md, note3.md]read_note(path: "note1.md")→ 返回:筆記的完整內容search_notes(query: "React")→ 返回:包含 "React" 的筆記列表和摘要每個 Tool 的呼叫都會產生結果,AI 會根據結果決定下一步動作。 這就像是你問助理「幫我查一下檔案」,他真的會去翻檔案櫃。
每個 Tool 都有清楚的說明書,你必須替每一個工具定義好以下參數
基本上還是剛剛提到的,Tool 的本質就是一個 Function,只是你必須詳細交代 LLM 該怎麼用、什麼時會去用這個 Function
❓ 練習題
你正在開發一個「個人知識庫」的 MCP Server。下列哪個功能「不應該」設計成 Tool?
A) 搜尋筆記內容(根據關鍵字找出相關筆記)
B) 筆記分類規則(說明你如何組織筆記的 markdown 文件)
C) 建立新筆記(在指定目錄建立 .md 檔案)
D) 統計筆記數量(計算各分類有多少筆記)正確答案: B) 筆記分類規則(說明你如何組織筆記的 markdown 文件)
工具是一個 Function,是一個可以被執行的行為 筆記分類規則 ,其實就是很單純的文字、命令告訴 LLM 該怎麼做
在 https://blog.ray-realms.com/article/73b7d4c5-fc5e-49e2-a7df-c675c4703300 閱讀此文章,以獲取更好的學習體驗
我的部落格透過 滾動視差 設計,如同我本人一步一步與你講解、教學每一段程式碼
我們要解決什麼問題? 現在我們要讓 AI 能夠「看到」你電腦裡有哪些筆記檔案。 這個工具很簡單:
🎯 學習目標:
- 初始化 Node.js 專案並安裝必要套件
- 建立 Express 伺服器並設定基本路由
- 配置 TypeScript 環境以支援 MCP 開發
# 首先,創建一個資料夾當作專案資料夾
# 我這邊就叫做「my-notes-mcp-server」
mkdir my-notes-mcp-server
cd my-notes-mcp-server

npm init -y
npm install @modelcontextprotocol/sdk express zod
npm install -D @types/express @types/node tsx typescript

import express from 'express';
// 1. 建立 Express 應用程式
const app = express();
app.use(express.json());
// 2. 設定路由
// 健康檢查 endpoint
app.get('/health', (req, res) => {
  res.json({ 
    status: 'ok',
    message: 'Server is running!' 
  });
});
// 3. 啟動伺服器
const port = 8080;
app.listen(port, () => {
  console.log(`🚀 伺服器運行中:http://localhost:${port}`);
  console.log(`📍 健康檢查:http://localhost:${port}/health`);
});

{
  "name": "my-notes-mcp-server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "tsx watch index.ts", // [新增] 開發模式,支援熱重載,讓程式碼修改後自動重啟
    "start": "tsx index.ts", // [新增] 生產模式啟動
    "build": "tsc", // [新增] 編譯 TypeScript 為 JavaScript
    "serve": "node dist/index.js" // [新增] 執行編譯後的 JavaScript
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "commonjs",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.20.2",
    "express": "^5.1.0",
    "zod": "^3.25.76"
  },
  "devDependencies": {
    "@types/express": "^5.0.4",
    "@types/node": "^24.9.1",
    "tsx": "^4.20.6",
    "typescript": "^5.9.3"
  }
}

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "esModuleInterop": true,
    "strict": true,
    "skipLibCheck": true,
    "outDir": "./dist"
  },
  "include": ["*.ts"]
}

npm run dev
在瀏覽器中打開 http://localhost:8080/health ,應該可以看到健康檢查回應。

🎯 學習目標:
- 導入 MCP SDK 並建立 McpServer 實例
- 註冊第一個 Tool 並定義其規格
- 實現 Tool 的執行邏輯與回傳格式
- 設定 MCP HTTP 端點以接收請求
import express from 'express';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; // [新增] 導入 MCP Server 類別,這是 MCP 協定的核心實現
const app = express();
app.use(express.json());
// 建立 MCP Server // [新增] 建立 MCP Server 實例
const server = new McpServer({ // [新增] 配置 MCP Server,定義名稱和版本,這些資訊會被客戶端顯示
  name: 'my-notes-server', // [新增] 伺服器名稱,用於識別此 MCP 服務
  version: '1.0.0' // [新增] 版本號,用於追蹤更新和相容性
}); // [新增] MCP Server 建立完成,負責處理連接、工具註冊和訊息路由
app.get('/health', (req, res) => {
  res.json({ 
    status: 'ok',
    message: 'Server is running!' 
  });
});
const port = 8080;
app.listen(port, () => {
  console.log(`🚀 伺服器運行中:http://localhost:${port}`);
  console.log(`📍 健康檢查:http://localhost:${port}/health`);
});
import express from 'express';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
const app = express();
app.use(express.json());
// 建立 MCP Server
const server = new McpServer({
  name: 'my-notes-server',
  version: '1.0.0'
});
server.registerTool( // [新增] 註冊工具,這是讓 AI 發現並使用此功能的關鍵方法
  'list_files' // 工具名稱 // [新增] 工具的唯一識別名稱,應該簡潔且能讓 LLM 理解其功能(例如:列出檔案)
); // [新增] 工具註冊完成,現在 MCP Server 知道有一個名為 list_files 的工具可用
app.get('/health', (req, res) => {
  res.json({ 
    status: 'ok',
    message: 'Server is running!' 
  });
});
const port = 8080;
app.listen(port, () => {
  console.log(`🚀 伺服器運行中:http://localhost:${port}`);
  console.log(`📍 健康檢查:http://localhost:${port}/health`);
});
import express from 'express';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod'; // [新增] 導入 Zod,用於定義輸入輸出 schema,確保資料驗證和類型安全
const app = express();
app.use(express.json());
// 建立 MCP Server
const server = new McpServer({
  name: 'my-notes-server',
  version: '1.0.0'
});
server.registerTool(
  'list_files',
  { // [新增] Tool 的規格定義,這是給 LLM 的「說明書」,告訴 AI 這個工具怎麼用
    title: '列出檔案', // [新增] 工具的顯示名稱,人性化描述
    description: '列出所有 Markdown 檔案', // [新增] 工具的功能說明,讓 AI 知道何時該使用此工具
    inputSchema: {}, // 這裡不需要傳入任何參數 // [新增] 輸入 schema,定義工具需要的參數(此例為空,表示無參數)
    outputSchema: { // [新增] 輸出 schema,定義工具回傳的資料結構
      files: z.array(z.string()) // [新增] 預期輸出為一個字串陣列,代表檔案清單
    } // [新增] Schema 定義完成,確保輸入輸出格式一致
  },
);
app.get('/health', (req, res) => {
  res.json({ 
    status: 'ok',
    message: 'Server is running!' 
  });
});
const port = 8080;
app.listen(port, () => {
  console.log(`🚀 伺服器運行中:http://localhost:${port}`);
  console.log(`📍 健康檢查:http://localhost:${port}/health`);
});
import express from 'express';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
const app = express();
app.use(express.json());
// 建立 MCP Server
const server = new McpServer({
  name: 'my-notes-server',
  version: '1.0.0'
});
server.registerTool(
  'list_files',
  {
    title: '列出檔案',
    description: '列出所有 Markdown 檔案',
    inputSchema: {}, // 這裡不需要傳入任何參數 
    outputSchema: {
      files: z.array(z.string())
    }
  },
  async () => { // [新增] Tool 的執行函數,當 AI 呼叫此工具時會執行此 async function
    return { // [新增] 回傳物件,必須符合 MCP 協定格式
      content: [                               // ← 必須是陣列 // [新增] content 陣列,包含回傳給 AI 的資料項目
        { // [新增] 每個 content 項目定義類型和內容
          type: 'text',                        // ← 內容類型 // [新增] 內容類型,目前支援 text、image 等
          text: '目前還沒有檔案'                // ← 實際內容 // [新增] 文字內容,AI 會直接「閱讀」此內容
        } // [新增] 預設回傳,模擬無檔案狀態
      ] // [新增] 回傳格式確保 AI 能正確解析結果
    }; // [新增] 執行函數完成,回傳值會直接傳送給呼叫的 LLM
  } // [新增] Tool 註冊完整,現在 AI 可以呼叫並獲得回應
);
app.get('/health', (req, res) => {
  res.json({ 
    status: 'ok',
    message: 'Server is running!' 
  });
});
const port = 8080;
app.listen(port, () => {
  console.log(`🚀 伺服器運行中:http://localhost:${port}`);
  console.log(`📍 健康檢查:http://localhost:${port}/health`);
});
import express from "express";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
const app = express();
app.use(express.json());
// 建立 MCP Server
const server = new McpServer({
  name: "my-notes-server",
  version: "1.0.0",
});
server.registerTool(
  "list_files",
  {
    title: "列出檔案",
    description: "列出所有 Markdown 檔案",
    inputSchema: {}, // 這裡不需要傳入任何參數
    outputSchema: {
      files: z.array(z.string()),
    },
  },
  async () => {
    return {
      content: [
        {
          type: "text",
          text: "目前還沒有檔案",
        },
        {// 簡單展示一下如果要回傳圖片該怎麼做 // [新增] 示範如何在回傳中加入圖片,擴展工具的豐富度
          type: "image",// [新增] 設定內容類型為圖片,讓 AI 能處理視覺資料
          data: "base64 編碼的圖片",// [新增] 圖片資料,使用 base64 編碼傳輸
          mimeType: "image/png",// [新增] MIME 類型,指定圖片格式
        },// [新增] 多媒體支援讓工具更強大,可回傳圖表、截圖等
      ],
    };
  }
);
app.get("/health", (req, res) => {
  res.json({
    status: "ok",
    message: "Server is running!",
  });
});
const port = 8080;
app.listen(port, () => {
  console.log(`🚀 伺服器運行中:http://localhost:${port}`);
  console.log(`📍 健康檢查:http://localhost:${port}/health`);
});
(右側程式碼僅為舉例)
import express from "express";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
const app = express();
app.use(express.json());
// 建立 MCP Server
const server = new McpServer({
  name: "my-notes-server",
  version: "1.0.0",
});
server.registerTool(
  "list_files",
  {
    title: "列出檔案",
    description: "列出所有 Markdown 檔案",
    inputSchema: {}, // 這裡不需要傳入任何參數
    outputSchema: {
      files: z.array(z.string()),
    },
  },
  async () => {
    const output = { files: [] };              // ← 先用空陣列 // [新增] 準備結構化輸出,符合 outputSchema 定義
    return {
      content: [
        {
          type: "text",
          text: JSON.stringify(output, null, 2),// [新增] 將結構化資料轉為格式化 JSON 字串,讓 AI 能「閱讀」易懂的文字
        }
      ],
      structuredContent: output                // 同時提供結構化資料 // [新增] 結構化內容,供程式端解析,與 content 內容同步但格式更嚴謹
    };
  }
);
app.get("/health", (req, res) => {
  res.json({
    status: "ok",
    message: "Server is running!",
  });
});
const port = 8080;
app.listen(port, () => {
  console.log(`🚀 伺服器運行中:http://localhost:${port}`);
  console.log(`📍 健康檢查:http://localhost:${port}/health`);
});
import express from 'express';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; // [新增] 導入 HTTP 傳輸層,處理 MCP 協定訊息
import { z } from 'zod';
const app = express();
app.use(express.json());
const server = new McpServer({
  name: 'my-notes-server',
  version: '1.0.0'
});
server.registerTool(
  'list_files',
  {
    title: '列出檔案',
    description: '列出所有 Markdown 檔案',
    inputSchema: {},
    outputSchema: { files: z.array(z.string()) }
  },
  async () => {
    const output = { files: [] };
    return {
      content: [
        {
          type: "text",
          text: JSON.stringify(output, null, 2),
        }
      ],
      structuredContent: output 
    };
  }
);
// MCP endpoint // [新增] 建立 MCP 專用端點,接收來自 AI 客戶端的請求
app.post('/mcp', async (req, res) => { // [新增] POST 路由處理 MCP 訊息,使用 streamable HTTP 傳輸
  try { // [新增] 錯誤處理包裝,確保伺服器穩定
    const transport = new StreamableHTTPServerTransport({ // [新增] 建立 HTTP 傳輸實例,支援 JSON 回應和會話管理
      sessionIdGenerator: undefined, // [新增] 預設會話 ID 生成器
      enableJsonResponse: true // [新增] 啟用 JSON 回應格式,方便調試
    }); // [新增] 傳輸層建立完成,負責 MCP 協定封裝
    /* @cat-caption */
    res.on('close', () => transport.close()); // [新增] 處理 HTTP 連接關閉,清理資源避免記憶體洩漏
    
    await server.connect(transport); // [新增] 連接 MCP Server 與傳輸層,讓伺服器能透過 HTTP 接收請求
    await transport.handleRequest(req, res, req.body); // [新增] 處理實際請求,將請求 body 傳遞給 MCP 協定層解析
  } catch (error) { // [新增] 捕獲所有錯誤,提供標準化錯誤回應
    console.error('MCP 請求錯誤:', error); // [新增] 記錄錯誤日誌
    if (!res.headersSent) { // [新增] 確保回應尚未發送,避免重複錯誤
      res.status(500).json({ // [新增] 回傳標準 JSON-RPC 錯誤格式,符合 MCP 協定
        jsonrpc: '2.0', // [新增] JSON-RPC 版本
        error: { code: -32603, message: 'Internal server error' }, // [新增] 標準錯誤碼和訊息
        id: null // [新增] 請求 ID,通常為 null 在錯誤時
      }); // [新增] 錯誤回應完成,確保客戶端能正確處理
    } // [新增] 錯誤處理確保 API 穩定性
  } // [新增] MCP 端點設定完成,現在外部 AI 可以透過 HTTP 連接此伺服器
}); // [新增] 端點暴露,MCP 服務正式可用
app.get('/health', (req, res) => {
  res.json({ status: 'ok' });
});
const port = 8080;
app.listen(port, () => {
  console.log(`🚀 伺服器運行中:http://localhost:${port}`);
  console.log(`📍 MCP endpoint:http://localhost:${port}/mcp`);
});
🎯 學習目標:
- 使用官方 MCP Inspector 工具測試連接
- 驗證 Tool 註冊與執行功能
- 確認 MCP 端點正常回應
npx @modelcontextprotocol/inspector http://localhost:8080/mcp

輸入完成後,他會開啟一個網站。

確保 Transport Type 是 Streamable HTTP。

確保 URL 是 http://localhost:8080/mcp 。

按下 Connect。

你應該可以看到連接成功,你可以點擊中間的 List Tools。

應該可以看到我們創建的工具「list files」。

我們來把 list_files 的功能給實際做出來 由於本教學的重點是 MCP,我會用很快的速度帶過去,就不特別提細節了
🎯 學習目標:
- 整合 Node.js fs 模組讀取本地檔案
- 過濾並處理 Markdown 檔案清單
- 實現錯誤處理與使用者友善回應
為了方便測試,我建議在專案資料夾中建立一個 notes 資料夾 我們的 mcp 工具會把該資料夾當作我們的筆記目錄。

import express from 'express';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { z } from 'zod';
import fs from 'fs/promises'; /* @cat-caption */ // [新增] 導入檔案系統模組(Promise 版本),用於非同步讀取目錄和檔案
import path from 'path';/* @cat-caption */ // [新增] 導入路徑處理模組,處理檔案路徑和副檔名
const app = express();
app.use(express.json());
// 筆記目錄/* @cat-caption */ // [新增] 定義筆記檔案的根目錄路徑,讓工具知道從哪裡讀取檔案
const NOTES_DIR = './notes';/* @cat-caption */ // [新增] 相對路徑指向專案中的 notes 資料夾
const server = new McpServer({
  name: 'my-notes-server',
  version: '1.0.0'
});
server.registerTool(
  'list_files',
  {
    title: '列出檔案',
    description: '列出所有 Markdown 檔案',
    inputSchema: {},
    outputSchema: { files: z.array(z.string()) }
  },
  async () => {
    try {/* @cat-caption */ // [新增] 使用 try-catch 包裝檔案操作,處理可能發生的 I/O 錯誤
      const entries = await fs.readdir(NOTES_DIR, { withFileTypes: true });/* @cat-caption */ // [新增] 非同步讀取目錄,返回檔案和子目錄的詳細資訊
      const files = entries/* @cat-caption */ // [新增] 過濾出只有檔案(非目錄)且副檔名為 .md 的項目
        .filter(entry => entry.isFile() && entry.name.endsWith('.md'))/* @cat-caption */ // [新增] 雙重過濾:確認是檔案且是 Markdown 格式
        .map(entry => entry.name);/* @cat-caption */ // [新增] 提取檔案名稱,形成乾淨的字串陣列
      /* @cat-caption */
      const output = { files };/* @cat-caption */ // [新增] 封裝輸出物件,符合預定義的 schema 結構
      /* @cat-caption */
      return {/* @cat-caption */ // [新增] 成功回傳,包含文字內容和結構化資料
        content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],/* @cat-caption */ // [新增] 將輸出轉為格式化 JSON,讓 AI 易讀
        structuredContent: output/* @cat-caption */ // [新增] 提供結構化版本,供後續處理使用
      };/* @cat-caption */
    } catch (error) {/* @cat-caption */ // [新增] 捕獲讀取錯誤(如目錄不存在、權限問題)
      return {/* @cat-caption */ // [新增] 錯誤回傳,標記為錯誤狀態並提供使用者友善訊息
        content: [{ type: 'text', text: `錯誤:${(error as Error).message}` }],/* @cat-caption */ // [新增] 將錯誤訊息轉為文字,讓 AI 能理解問題
        isError: true/* @cat-caption */ // [新增] 明確標記錯誤,讓 MCP 協定能特殊處理
      };/* @cat-caption */
    }/* @cat-caption */ // [新增] 錯誤處理確保工具穩定,即使檔案系統出問題也能優雅降級
  }
);
app.post('/mcp', async (req, res) => {
  try {
    const transport = new StreamableHTTPServerTransport({
      sessionIdGenerator: undefined,
      enableJsonResponse: true
    });
    res.on('close', () => transport.close());
    await server.connect(transport);
    await transport.handleRequest(req, res, req.body);
  } catch (error) {
    console.error('MCP 請求錯誤:', error);
    if (!res.headersSent) {
      res.status(500).json({
        jsonrpc: '2.0',
        error: { code: -32603, message: 'Internal server error' },
        id: null
      });
    }
  }
});
app.get('/health', (req, res) => {
  res.json({ status: 'ok' });
});
const port = 8080;
app.listen(port, () => {
  console.log(`🚀 伺服器運行中:http://localhost:${port}`);
  console.log(`📍 MCP endpoint:http://localhost:${port}/mcp`);
  console.log(`📂 筆記目錄:${NOTES_DIR}`);
});

在 /notes 資料夾中,放一些檔案方便測試。
回到剛剛提到的 mcp 測試網站(來自 第三步,測試看看 MCP 伺服器有沒有建立成功)
你可以執行看看 list_files 工具 應該可以看到所有檔案。

恭喜你!現在我們的 MCP Server 已經跑起來了,但有個問題:ChatGPT 在雲端,怎麼連到你電腦上的 localhost:3000?
(不知道為什麼讓我想到這個工程師老梗

外部的電腦是沒辦法連線到我 localhost 的網站,該怎麼辦呢? 難道只能部署到雲端嗎?
這邊推薦給大家一個超讚的免費服務 ngrok 他可以開了一個「臨時的公開網址」,外面的人可以把信件寄到這公開網址,而 ngrok 會把收到的信再轉交給你家裡的電腦。
這樣就可以讓 ChatGPT、Claude 直接連到你的電腦的 MCP 伺服器了
🎯 學習目標:
- 安裝並配置 Ngrok 服務
- 建立本地伺服器到公開網址的隧道
- 獲取臨時公開 URL 用於 AI 整合
首先,打開 ngrok 的服務 https://ngrok.com/ 並且登入。

造著他的方式安裝他,以 macos homebrew 為例
打開終端機 - 先輸入 brew install ngrok 安裝整個程式碼 - 然後輸入ngrok config add-authtoken XXX 登入你的帳號
這樣就完成安裝了。

ngrok http 8080

Ok! 他接下來會生成一個網址 恭喜你,這就是你 MCP 的網址,把它複製下來 終端機不要關掉,一但關掉這個網址會失效
任何針對這個網址的請求,都會直接送到你電腦中的 localhost:8080。

請注意!ChatGPT 的 MCP 功能需要訂閱(每個月 20 美金方案以上)才可以使用
🎯 學習目標:
- 在 ChatGPT 中啟用開發者模式
- 建立自訂 MCP 連接器
- 配置 Ngrok URL 並驗證連接
打開你的 ChatGPT,並點擊左下角。

選擇「設定」。

選擇「應用程式和連接器」。

滑到最底下,選擇「進階設定」。

開啟「開發者模式」,並回到上一步。

點擊「建立」。

輸入這個 MCP 伺服器的名稱。

重點來了! 貼上 ngrok 的網址 記得!!最後要加上 /mcp。

把「驗證」改成「無驗證」。

點擊「我了解並繼續」,最後選擇建立。

順利的話,就可以看到我們的 MCP 服務。

到這邊就可以直接跟 ChatGPT 聊天,順利的話,恭喜成功串接 MCP 到 ChatGPT 上頭!

請注意!Claude 的 MCP 功能需要訂閱(每個月 20 美金方案以上)才可以使用
Claude 的邏輯跟 ChatGPT 很像,
🎯 學習目標:
- 在 Claude 中新增自訂連接器
- 配置相同 Ngrok URL
- 驗證跨平台 MCP 相容性
打開你的 Claude,並點擊左下角。

選擇「Settings」。

選擇「Connectors」並點擊「Add custom connector」。

輸入這個 MCP 伺服器的名稱。

重點來了! 貼上 ngrok 的網址 記得!!最後要加上 /mcp 最後按下 Add。

順利的話,就可以看到我們的 MCP 服務。

到這邊就可以直接跟 ChatGPT 聊天,順利的話,恭喜成功串接 MCP 到 Claude 上頭!

理解 MCP 解決的核心問題
掌握 Tools 的設計哲學
建立第一個實用的 MCP Server
整合到真實的 AI 應用
你現在擁有了一個可運作的 MCP Server,但它還很基礎。 下一篇則會更深入 MCP 的精髓,講解 Resources 和 Prompts 的功能 我會分享很多開發 MCP 必定會遇到大問題以及解法,好比身份驗證、很多必須避開的坑
在 AI 時代,重點不是寫多少 code,而是理解問題、設計方案、驗證效果。Code 可以讓 AI 幫你寫,思考無法委託。 準備好了嗎?讓我們在下篇繼續深入 MCP 的世界!