🚀 模型上下文協議(MCP)服務器 + Microsoft Entra ID OAuth + 待辦事項管理
本項目是一個支持遠程 MCP 連接的 模型上下文協議(MCP) 服務器,內置 Microsoft Entra ID(前身為 Azure AD)OAuth 功能,並且具備全面的 Microsoft To Do 任務管理能力。
你可以將其部署到自己的 Cloudflare 賬戶中。創建自己的 Azure AD OAuth 應用程序後,你將擁有一個功能完備的遠程 MCP 服務器,可在此基礎上進行開發。用戶能夠使用他們的 Microsoft 賬戶登錄並連接到你的 MCP 服務器,管理待辦事項列表、創建任務、設置提醒等。
你可以將此項目作為參考示例,學習如何使用 workers-oauth-provider 庫,將其他 OAuth 提供商與部署到 Cloudflare 的 MCP 服務器集成。
MCP 服務器(由 Cloudflare Workers 提供支持):
- 作為 OAuth 服務器 為 MCP 客戶端提供服務。
- 作為 OAuth 客戶端 連接到真正的 OAuth 服務器(在本例中為 Microsoft Entra ID)。
🚀 快速開始
克隆倉庫並安裝依賴:
npm install
生產環境部署
創建新的 Azure AD 應用程序
-
訪問 Azure 門戶 → Azure Active Directory → 應用註冊。
-
點擊 新建註冊。
-
進行如下配置:
- 名稱:
MCP Entra OAuth Todo Server
- 支持的賬戶類型:
- 若要支持 多租戶(推薦):選擇 “任何組織目錄中的賬戶(任何 Azure AD 目錄 - 多租戶)和個人 Microsoft 賬戶”。
- 若僅支持單個組織:選擇 “僅此組織目錄中的賬戶”。
- 重定向 URI:
- 類型:
Web
- URI:
https://remote-mcp-entra-oauth-todo.<your-subdomain>.workers.dev/callback
- 同時添加:
http://localhost:8789/callback(開發環境)
-
註冊完成後,記錄以下信息:
-
創建客戶端密鑰:
- 訪問 證書和密鑰 → 新建客戶端密鑰。
- 立即複製密鑰值(之後將無法再次查看)。
-
配置 API 權限:
- 訪問 API 權限 → 添加權限 → Microsoft Graph → 委託權限。
- 添加:
User.Read(登錄並讀取用戶個人資料)
Tasks.ReadWrite(讀取和寫入用戶的任務)
- 為你的組織點擊 授予管理員同意。
💡 專業提示:代碼使用 https://graph.microsoft.com/.default 範圍,該範圍會動態請求所有預先同意的權限。要添加新工具或權限,只需在 Azure 門戶中添加並授予同意,無需更改代碼!
-
通過 Wrangler 設置密鑰:
wrangler secret put ENTRA_CLIENT_ID
wrangler secret put ENTRA_CLIENT_SECRET
wrangler secret put ENTRA_TENANT_ID
wrangler secret put COOKIE_ENCRYPTION_KEY
wrangler secret put DEFAULT_TIMEZONE
⚠️ 重要提示
多租戶配置:設置 ENTRA_TENANT_ID 時:
- 使用
common:允許工作/學校賬戶和個人 Microsoft 賬戶(多租戶推薦)。
- 使用
organizations:僅允許工作/學校賬戶(Azure AD),不允許個人賬戶。
- 使用
consumers:僅允許個人 Microsoft 賬戶。
- 使用特定租戶 ID:僅允許該特定租戶的用戶。
對於多租戶應用,使用 common 可確保在用戶的主租戶上下文中頒發令牌,即使他們是其他租戶的來賓用戶,也能訪問其個人資源(如待辦事項列表)。
⚠️ 重要提示
創建第一個密鑰時,Wrangler 會詢問是否創建新的 Worker。輸入 "Y" 創建新的 Worker 並保存密鑰。
設置時區
- 設置
DEFAULT_TIMEZONE 為你首選的時區(例如 Asia/Tokyo、America/New_York、Europe/London)。
- 除非另有指定,否則所有任務的截止日期和提醒都將使用該時區。
- 用戶仍可根據需要為每個任務指定不同的時區。
- 如果未設置,默認為
Europe/London。
設置 KV 命名空間
wrangler kv namespace create "OAUTH_KV"
部署和測試
將 MCP 服務器部署到你的 workers.dev 域名:
wrangler deploy
使用 Inspector 測試遠程服務器:
npx @modelcontextprotocol/inspector@latest
輸入 https://remote-mcp-entra-oauth-todo.<your-subdomain>.workers.dev/mcp 並點擊連接。完成身份驗證流程後,你將看到工具可用。
現在你已成功部署遠程 MCP 服務器!
從 Claude Desktop 訪問遠程 MCP 服務器
打開 Claude Desktop,導航到設置 -> 開發者 -> 編輯配置。這將打開控制 Claude 可訪問的 MCP 服務器的配置文件。
將內容替換為以下配置。重啟 Claude Desktop 後,將打開一個瀏覽器窗口顯示 OAuth 登錄頁面。完成身份驗證流程,授予 Claude 訪問你的 MCP 服務器的權限。授予訪問權限後,工具將可供使用。
{
"mcpServers": {
"entra-todo": {
"command": "npx",
"args": [
"mcp-remote",
"https://remote-mcp-entra-oauth-todo.<your-subdomain>.workers.dev/mcp"
]
}
}
}
當界面中出現工具(在 🔨 下方)時,你可以要求 Claude 使用它們。例如:
- "能否從 Microsoft Graph 獲取我的用戶個人資料?"
- "顯示我所有的待辦事項列表"
- "在我的工作列表中創建一個截止日期為下週五的新任務"
- "我本週有哪些任務到期?"
本地開發
如果你想迭代和測試 MCP 服務器,可以在本地開發環境中進行。這需要在 Azure AD 中創建另一個 OAuth 應用程序:
- 主頁 URL 指定為
http://localhost:8789。
- 授權回調 URL 指定為
http://localhost:8789/callback。
- 記錄客戶端 ID 並生成客戶端密鑰。
- 在項目根目錄創建
.dev.vars 文件,內容如下:
ENTRA_CLIENT_ID=your_development_azure_ad_client_id
ENTRA_CLIENT_SECRET=your_development_azure_ad_client_secret
ENTRA_TENANT_ID=common # 多租戶使用 'common',或使用特定租戶 ID
COOKIE_ENCRYPTION_KEY=any_random_string_here
DEFAULT_TIMEZONE=Europe/London
開發和測試
在本地運行服務器,使其在 http://localhost:8789 可用:
wrangler dev
要測試本地服務器,在 Inspector 中輸入 http://localhost:8789/mcp 並點擊連接。按照提示操作後,你將能夠 “列出工具”。
使用 Claude 和其他 MCP 客戶端
使用 Claude 連接到遠程 MCP 服務器時,可能會看到一些錯誤消息。這是因為 Claude Desktop 尚未支持遠程 MCP 服務器,所以有時會出現混淆。要驗證 MCP 服務器是否已連接,將鼠標懸停在 Claude 界面右下角的 🔨 圖標上,你應該會看到可用的工具。
使用 Cursor 和其他 MCP 客戶端
要將 Cursor 與 MCP 服務器連接,選擇 類型:“命令”,並在 命令 字段中將命令和參數字段合併為一個(例如 npx mcp-remote https://<your-worker-name>.<your-subdomain>.workers.dev/mcp)。
請注意,雖然 Cursor 支持 HTTP+SSE 服務器,但不支持身份驗證,因此仍需使用 mcp-remote(並使用 STDIO 服務器,而不是 HTTP 服務器)。
你可以通過打開其他 MCP 客戶端(如 Windsurf)的配置文件,添加與 Claude 設置相同的 JSON 內容,然後重啟 MCP 客戶端,將 MCP 服務器連接到這些客戶端。
🔧 工作原理
OAuth 提供商
OAuth 提供商庫是 Cloudflare Workers 的完整 OAuth 2.1 服務器實現。它處理 OAuth 流程的複雜性,包括令牌頒發、驗證和管理。在本項目中,它扮演以下雙重角色:
- 對連接到服務器的 MCP 客戶端進行身份驗證。
- 管理與 Microsoft Entra ID 的 OAuth 服務的連接。
- 在 KV 存儲中安全地存儲令牌和身份驗證狀態。
持久化 MCP
持久化 MCP 通過 Cloudflare 的 Durable Objects 擴展了基本 MCP 功能,提供:
- MCP 服務器的持久狀態管理。
- 請求之間身份驗證上下文的安全存儲。
- 通過
this.props 訪問經過身份驗證的用戶信息。
- 根據用戶身份支持有條件的工具可用性。
MCP 遠程
MCP 遠程庫使服務器能夠公開可由 Inspector 等 MCP 客戶端調用的工具。它:
- 定義客戶端與服務器之間的通信協議。
- 提供定義工具的結構化方式。
- 處理請求和響應的序列化和反序列化。
- 支持流式 HTTP(推薦)和服務器發送事件(SSE)協議進行客戶端通信。
🚧 傳輸協議遷移
此示例已更新為支持新的 流式 HTTP 傳輸協議,該協議取代了已棄用的服務器發送事件(SSE)協議。服務器現在公開兩個端點:
/mcp - 推薦:使用新的流式 HTTP 協議。
/sse - 已棄用:舊的 SSE 協議(為向後兼容性保留)。
所有新集成應使用 /mcp 端點。SSE 端點將在未來版本中移除。
🛠️ 可用工具
用戶個人資料
getUserProfile - 獲取經過身份驗證的用戶的 Microsoft Graph 個人資料。
待辦事項列表管理
listTodoLists - 獲取經過身份驗證的用戶的所有待辦事項列表。
createTodoList - 創建一個具有指定名稱的新任務列表。
updateTodoList - 更新現有任務列表的名稱。
deleteTodoList - 刪除一個任務列表。
任務管理
listTasks - 從特定的待辦事項列表中獲取所有任務。
getTask - 獲取特定任務的詳細信息。
createTask - 創建一個具有可選屬性的新任務:
- 標題(必需)
- 正文/描述
- 截止日期和時間
- 提醒日期和時間
- 重要性級別(低、正常、高)
- 類別/標籤
- 日期的時區
updateTask - 更新任務的任何屬性:
- 標題
- 正文/描述
- 狀態(未開始、進行中、已完成、等待他人、推遲)
- 重要性級別
- 截止日期和時間
- 提醒設置
- 類別
deleteTask - 從列表中刪除一個任務。
簡單測試工具
add - 相加兩個數字(用於測試 MCP 連接)。
💻 使用示例
要求 Claude 幫助你完成以下任務:
- "顯示我所有的待辦事項列表"
- "創建一個名為 '購物' 的新列表"
- "在我的購物列表中添加一個任務 '購買雜貨',截止日期為明天下午 5 點"
- "我的工作列表中有哪些任務?"
- "將任務 '致電客戶' 更新為高重要性,截止日期為週五"
- "將 '提交報告' 任務標記為已完成"
- "為我的 '團隊會議準備' 任務設置明天上午 9 點的提醒"
- "從我的個人列表中刪除所有已完成的任務"
➕ 添加新工具
由於 OAuth 流程中使用了 .default 範圍,添加新工具非常簡單:
- 在 Azure 門戶中添加權限:
- 訪問你的應用 → API 權限。
Tasks.ReadWrite 權限已包含在待辦事項功能中。
- 如果尚未授予管理員同意,請進行授予。
- 在代碼中添加工具():
this.server.tool(
"getTodoTaskList",
"Get details of a specific todo task list",
{
listId: z.string().describe("The ID of the todo list to retrieve"),
},
async ({ listId }) => {
const client = Client.init({
authProvider: (done) => {
done(null, this.props!.accessToken);
},
});
try {
const taskList = await client
.api(`/me/todo/lists/${listId}`)
.get();
return {
content: [{ text: JSON.stringify(taskList, null, 2), type: "text" }],
};
} catch (error) {
return {
content: [{
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
type: "text"
}],
isError: true,
};
}
}
);
- 部署:
npm run deploy
就是這麼簡單!由於 .default 範圍會動態請求所有預先同意的權限,因此無需更改 OAuth 流程中的範圍。
🔒 安全說明
- ✅ 客戶端密鑰存儲為 Cloudflare Workers 密鑰(不會向客戶端公開)。
- ✅ OAuth 狀態參數可防止 CSRF 攻擊。
- ✅ HMAC 簽名的 cookie 用於批准對話框的持久化。
- ✅ 訪問令牌在 MCP 會話令牌中加密。
- ✅ 所有通信均通過 HTTPS 進行。
- ✅ 批准對話框在授權前顯示客戶端信息。
🐞 故障排除
"獲取訪問令牌失敗"
- 檢查 Azure 門戶中的客戶端密鑰是否正確且未過期。
- 驗證重定向 URI 是否完全匹配(包括協議和端口)。
- 確保
ENTRA_TENANT_ID 正確。
"Tasks.ReadWrite 權限被拒絕"
- 確保在 Azure 門戶中授予了管理員同意。
- 檢查用戶在 Azure AD 中是否具有適當的權限。
- 驗證權限是否作為 委託權限 添加,而不是應用程序權限。
"無效的租戶"
- 驗證密鑰中的
ENTRA_TENANT_ID 是否正確。
- 對於多租戶應用,使用
common 作為租戶 ID 以支持工作/學校和個人賬戶。
- 僅支持工作/學校賬戶使用
organizations,僅支持個人賬戶使用 consumers。
- 如果使用特定租戶,請確保租戶 ID 與 Azure 門戶中顯示的一致。
- 來賓用戶注意事項:如果用戶是租戶的來賓用戶,但試圖訪問其個人資源(如待辦事項),必須使用
common,以便在其主租戶上下文中頒發令牌。
Claude Desktop 連接問題
- 更新配置後重啟 Claude Desktop。
- 檢查 Worker URL 是否正確且可訪問。
- 使用
wrangler secret list 驗證所有密鑰是否設置正確。
任務時區問題
- 驗證密鑰中的
DEFAULT_TIMEZONE 是否設置正確。
- 使用標準時區名稱(例如
America/New_York,而不是 EST)。
- 可以通過在工具參數中指定時區來覆蓋默認時區。
🏗️ 架構
此實現遵循標準的 OAuth 2.0 授權碼流程:
- 用戶打開 MCP 客戶端 → 客戶端嘗試連接到 MCP 服務器。
- 服務器啟動 OAuth → 顯示包含客戶端信息的批准對話框。
- 用戶批准 → 重定向到 Microsoft 登錄頁面。
- 用戶進行身份驗證 → Microsoft 使用授權碼重定向回服務器。
- 服務器交換代碼 → 使用客戶端密鑰從 Microsoft 獲取訪問令牌。
- 服務器獲取用戶信息 → 調用 Microsoft Graph 獲取用戶個人資料。
- 頒發令牌 → MCP 客戶端接收包含用戶上下文的加密令牌。
- 工具可用 → 客戶端現在可以使用委託權限調用 Microsoft Graph 工具。
Cloudflare Worker 充當 機密客戶端(服務器端應用程序),它:
- 安全地存儲客戶端密鑰。
- 處理完整的 OAuth 流程。
- 將授權碼交換為訪問令牌。
- 代表經過身份驗證的用戶進行 Microsoft Graph API 調用。
📄 許可證
本項目採用 MIT 許可證。