Skip to main content
Glama
luwaup
by luwaup

Microsoft To Do MCP Bridge

中文说明 · Security · Data handling

A self-hosted remote MCP server for personal Microsoft To Do accounts. Connect an OAuth-capable client such as ChatGPT to read lists, create tasks, change due dates and mark tasks complete.

This is an independent community project, not an official Microsoft, OpenAI or Cloudflare integration. v0.1.2 is a pre-release for individual deployments, not a reviewed multi-user hosting service.

Deploy to your own account

Deploy to Cloudflare

The button is an optional Cloudflare deployment entry point. Its full onboarding flow has not been verified. It does not configure Microsoft OAuth or bypass consent. Use the guided setup below for the tested deployment approach.

Requirements: Node.js 22+, your own Cloudflare account, a personal Microsoft account, and an Entra directory in which you can register an application. A Microsoft account by itself may not have that directory; obtain access through Microsoft's supported Azure or Microsoft 365 onboarding first. Keep the same To Do account and tasks.

git clone https://github.com/luwaup/microsoft-todo-mcp-bridge.git
cd microsoft-todo-mcp-bridge
npm ci
npm run check
npm run setup

The wizard creates a dedicated KV namespace, deploys the Worker, asks for its public URL, and stores the application's client ID and secret using Wrangler's secret prompt. Cloudflare login or Microsoft registration may require you to complete browser verification.

  1. Register an Entra application with a neutral name, for example Personal To Do Bridge. Microsoft-branded app names and callback hostnames can be rejected.

  2. Choose Personal Microsoft accounts only. The server uses the Microsoft /consumers authority.

  3. Add a Web redirect URI matching your deployment exactly: https://personal-todo-bridge.your-subdomain.workers.dev/callback.

  4. Add Microsoft Graph delegated permissions User.Read and Tasks.ReadWrite. The sign-in request also asks for offline_access to refresh authorization.

  5. Create a client secret. Save its value, not the secret ID, directly to Wrangler or Cloudflare Secrets as MS_CLIENT_SECRET. Save the application's client ID, not the tenant ID, as MS_CLIENT_ID.

  6. Complete Microsoft sign-in and consent when connecting an MCP client. A configured: true health response checks only that settings exist; it does not prove their validity or task access.

Do not put secrets into chat, GitHub issues, source code, screenshots or a public deployment form. Each deployer must supply their own credentials.

Connect ChatGPT or another client

Open ChatGPT Plugins, choose Add → Add custom MCP server, select OAuth, and enter:

https://personal-todo-bridge.your-subdomain.workers.dev/mcp

The server advertises CIMD and dynamic registration. ChatGPT can discover OAuth settings automatically; its OAuth client is separate from your Microsoft application. Follow the bridge consent page, check the client callback domain, then authorize on Microsoft's sign-in pages. Availability depends on your account and workspace.

Example requests:

  • Show my To Do lists.

  • Add “Buy groceries” to my Tasks list, due tomorrow.

  • Re-read this task and move its due date to next Friday.

  • Mark this task complete.

Resolve opaque list and task IDs with read tools before making changes. Due dates are calendar dates, not reminder times. due_date: null clears the due date. Destructive changes require the host's approval; deleting one task additionally requires confirm: true.

Manual deployment

npm ci
npx wrangler login
npx wrangler kv namespace create OAUTH_KV
# Put only your namespace ID into your local wrangler.jsonc.
npx wrangler deploy
# Register the exact /callback URL in Entra, then:
npx wrangler secret put MS_CLIENT_ID
npx wrangler secret put MS_CLIENT_SECRET
npx wrangler deploy

Set PUBLIC_BASE_URL to the exact Worker origin in local deployment configuration. The guided setup sets it for you. Do not commit the locally edited deployment file: the release privacy check rejects personal namespace IDs or account configuration. Keep personal configurations in the ignored .personal/ directory when maintaining a fork.

GET /health is a no-task-data check. Unauthenticated /mcp must return 401. Local development uses the ignored .dev.vars file, a separate development app, and http://localhost:8787/callback.

Related MCP server: microsoft-todo-mcp-server

Tools

Read

Write

list_task_lists

create_task_list, rename_task_list

list_tasks, get_task

create_task, update_task

list_checklist_items

complete_task, reopen_task

add_checklist_item, delete_task

Bounded list responses return { items, truncated }. This project makes live Graph requests; it has no background synchronization or independent reminder scheduler.

Security model

Microsoft credentials are stored as Cloudflare Secrets. Per-user access and refresh tokens are held in encrypted OAuth grant properties managed by Cloudflare's OAuth provider and KV. Task content is returned only through authorized tool calls; the bridge has no separate task-content database.

The MCP side uses PKCE, state, browser-bound upstream transactions, validated callbacks and resource-bound OAuth tokens. Graph requests are restricted to Microsoft To Do paths and pagination stays in the original collection. Writes are not automatically retried. Microsoft error bodies are not echoed. Invocation logging is disabled by default because callback URLs can contain authorization codes.

MCP clients and Microsoft still process data under their own policies. The Cloudflare account owner controls the deployment and storage. See PRIVACY.md for boundaries and revocation steps. Do not expose a shared multi-user service without a separate security review, rate limiting and operational controls.

Validation and limits

  • TypeScript checks, 19 protocol/unit tests and a complete local Worker OAuth scenario passed. OAuth integration tests use mocked Microsoft responses, including refresh and two-account isolation.

  • A personal live deployment completed ChatGPT CIMD authorization and discovered all 12 tools. Creating a test list/task, changing its title and completing it were independently confirmed in the Microsoft To Do web UI.

  • The ChatGPT test reply had a rendering failure. Actual task changes were confirmed separately; raw reply/tool-result transcripts are not published. If a client reply fails, read back before retrying a write.

  • Long-running real refresh, all remaining live tools, two real-account isolation and the deployment-button onboarding are not fully verified. No independent penetration test has been performed.

  • There are no transactional bulk updates or automatic ETag conflict resolution. Re-read before editing tasks that other devices may change.

Development and release hygiene

npm run check          # Typecheck, protocol tests, build, Worker OAuth scenario
npm run security:check # Check tracked public files without printing matched secrets
npm audit --omit=dev
npm run release:pack -- v0.1.2

The packer accepts a clean Git checkout, packages committed public files only, adds a SHA-256 manifest, and verifies ZIP contents against Git. It never packages .personal, local logs or deployment evidence. The scanner is a defense against accidental publication, not proof that every possible secret is detectable.

CI runs without Microsoft or Cloudflare credentials. Dependency versions are pinned in package-lock.json; GitHub Actions are pinned to commit SHAs with read-only repository permissions.

References

MIT licensed. See LICENSE.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers