我建立了一個自訂 MCP 伺服器來自動發布我的部落格

為什麼我開始這件事

我最近一直在深入準備 AI 工程 — 部署了幾個全端 AI 專案,微調了一個開源權重 LLM,還在為了就業機會而努力準備 DSA。在這一切的過程中,我對 MCP(Model Context Protocol)產生了好奇,決定實際用它來建立一些東西,而不只是閱讀相關資料。

想法很簡單:如果 Claude 可以讀取我電腦上的草稿部落格文章,清理內容,然後直接發布到 Dev.to — 完全不用我碰 Dev.to 的使用者介面,會怎麼樣?

結果發現,這正是 MCP 的用途。

什麼是 MCP,簡介

MCP 是一種協定,讓像 Claude 這樣的 AI 模型可以呼叫你定義的工具 — 讀取檔案、呼叫 API、執行腳本 — 而不是只生成文字。你寫一個小型伺服器來暴露「工具」(帶有說明字串的普通 Python 函式),將其插入 Claude Desktop 的設定中,突然間 Claude 就能「行動」,而不僅僅是「說話」。

我為此設定了兩個伺服器:

  1. filesystem — 一個官方 MCP 伺服器,讓 Claude 可以讀取/寫入我允許的資料夾中的檔案
  2. devto — 我建立的自訂伺服器,暴露一個 publish_blog_to_devto 工具,包裝 Dev.to API

設定環境

我首先使用 uv 進行 Python 套件管理 — 比普通的 pip/venv 快得多。

第一個小問題:安裝後,PowerShell 找不到 uv,因為我的終端機工作階段在安裝程式更新 PATH 之前就已經開啟了。關閉並重新開啟終端機立即解決了這個問題。這是小事,但如果你不知道原因,很容易驚慌失措。

第二個小問題更有趣。我建立了一個新的 venv 並嘗試 uv add "mcp[cli]",但它一直無法解決相依性 — 因為我的 pyproject.tomlrequires-python = ">=3.9",這是從專案最初針對系統 Python 3.9 建立時留下的,但實際的 MCP SDK 需要 3.10+。我透過明確設定來修復它:

uv python pin 3.12
uv venv --python 3.12

進入全螢幕模式 退出全螢幕模式

然後我在 pyproject.toml 中將 requires-python 編輯為 >=3.10,安裝就順利完成了。

套件名稱陷阱

這就是實際讓我困住一陣子的問題。在 supposedly 成功的安裝之後,匯入 fastmcp 一直拋出 ModuleNotFoundError: No module named 'mcp.server.fastmcp' — 即使 import mcp 正常運作,而且資料夾中明顯有 server 目錄。

原來 uv pip show mcp 顯示安裝的套件版本是 2.0.0,其相依性如 httpx2mcp-typespyjwtpywin32 — 這些都不屬於真正的 MCP SDK。在 PyPI 上有一個無關的套件佔用了 mcp 這個名稱,被拉進來而不是真正的 modelcontextprotocol SDK。

修復方法是明確設定版本範圍:

uv remove mcp
uv add "mcp[cli]>=1.2.0,<2.0.0"

進入全螢幕模式 退出全螢幕模式

這拉進了真正的 SDK(當時是 1.29.0),from mcp.server.fastmcp import FastMCP 終於可以運作了。

教訓:如果 uv add somepackage 「成功」但之後一切都不合理,請檢查 uv pip show — 不要假設 PyPI 上的名稱就是你認為的專案。

連接到 Claude Desktop

Claude Desktop 從 claude_desktop_config.json 讀取其 MCP 伺服器清單,在頂層的 mcpServers 鍵下。這個檔案現在有其他無關的應用程式偏好設定,所以很容易意外將你的伺服器新增為 mcpServers 的同級,而不是巢狀在裡面 — 這樣會默默地什麼都不做。我從艱苦的經驗中學到了這一點,盯著設定 → 開發者 → 本機 MCP 伺服器,想知道為什麼只有 filesystem 顯示出來。

正確的結構:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "C:\\Technical\\mcp-code"]
    },
    "devto": {
      "command": "C:\\Users\\vdine\\.local\\bin\\uv.exe",
      "args": ["--directory", "C:\\Technical\\custom-mcp\\devto-mcp-server", "run", "dev-server.py"]
    }
  }
}

進入全螢幕模式 退出全螢幕模式

另一個 Windows 特有的問題:Claude Desktop 不一定會繼承你的 shell 的 PATH,所以單獨使用 "command": "uv" 有時無法啟動。使用從 where.exe uv 取得的完整路徑永久解決了這個問題。

在完全退出並重新開啟 Claude Desktop 之後(不只是關閉視窗 — 它會留在系統匣中),兩個伺服器都顯示為執行中

使用 MCP Inspector 進行測試

在將任何東西連接到 Claude Desktop 之前,我使用以下方式獨立測試了伺服器:

uv run mcp dev src/mcp_server_demo/__init__.py

進入全螢幕模式 退出全螢幕模式

這會啟動 MCP Inspector — 一個本機網頁 UI,你可以在這裡直接呼叫你的工具並查看原始請求/回應有效負載,完全不需要 Claude 參與。對於在透過聊天介面除錯之前及早發現錯誤非常有用。

發布部落格

在兩個伺服器都連接後,實際的發布步驟幾乎是反高潮 — 我只是正常地與 Claude 交談:

「我在 [資料夾] 中有一個 blog.txt 檔案,請精煉其內容,然後以相關標籤作為草稿發布到 Dev.to。」

Claude 自己鏈接工具:

  1. 呼叫 read_text_file(filesystem 伺服器)來提取原始草稿
  2. 即時重寫和清理內容
  3. 使用標題、markdown 正文和標籤呼叫 publish_blog_to_devto(我的自訂伺服器)

不用複製貼上到 Dev.to 的編輯器,不用手動格式化。我首先設定 published: false 以作為草稿審查,然後再發布 — 這是防止發布半成品的廉價保險。

這實際上教會了我什麼

這裡真正的學習大部分不是關於 MCP 協定 — 而是標準的環境除錯:PATH 問題、Python 版本設定、被佔用的套件名稱,以及 JSON 巢狀錯誤。一旦環境正常,MCP 本身可能只是帶有說明字串的 20 行 Python。

這可能是被低估的教訓:代理工具只有在其下方的無聊管線可靠時才可靠。讓 venv、套件版本和設定結構正確,「AI 做有趣的部分」就會自己處理。

接下來,我計劃在同一個伺服器中新增更多工具 — 也許是一個拉取我的 GitHub 提交歷史記錄的工具,以幫助自動起草「本週我建立了什麼」的文章。