Other formats agents might prefer:
markdownjsonllms.txt

Agent? You probably want markdown or json, or Pod over MCP.

Reported issues for ms-graph-mcp

Pod holds 16 of 21 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.

Back to ms-graph-mcp.

Most discussed

Consolidate onto a single HTTP stack (httpx vs httpx2)

MCP SDK 2.0 depends on httpx2, a distribution separate from httpx. Both are currently installed: the SDK uses httpx2, client.py uses httpx.

Deliberately left out of the SDK 2.0 migration — an HTTP-stack swap and a protocol migration are two failure domains and did not belong in one change.

Spike first: confirm the httpx2 API surface covers what client.py uses (streaming reads, timeouts, verify=, Retry-After handling) before committing to the move.

Read the thread · 2026-08-05 · open · 1 comment

Dockerfile and GHCR publishing

Multi-stage build (uv build stage -> slim runtime), non-root user, HEALTHCHECK against /health, resource-limit guidance.

Add the ghcr job to release.yml, which currently ends with a comment explaining why it is absent: referencing a Dockerfile that does not exist would fail the first tagged release.

Note GitHub Packages has no Python registry — GHCR is the container registry, and PyPI remains the only place the wheel can live.

Read the thread · 2026-08-05 · closed · 1 comment

Client configuration documentation

docs/clients.md, one section per client, all pointing at the same server:

  • VS Code.vscode/mcp.json, both tiers. Local: type: "stdio" with uvx. Hosted: type: "http" with an oauth block carrying clientId, using the inputs array and ${input:...} substitution so no secret is ever hardcoded.
  • Claude Codeclaude mcp add, plus the Entra DCR caveat for the hosted tier
  • Claude Desktopclaude_desktop_config.json, stdio
  • MCP Inspector — as the neutral c

Read the thread · 2026-08-05 · closed · 1 comment

Testing and debugging documentation

docs/testing.md — the existing pytest patterns (contract tests, the entra/ RS256 fixtures, asyncio_mode=auto, the in-process mcp.Client conformance suite) plus MCP Inspector, the reference tool. Node 22.19+, three clients behind one binary: web, --cli, --tui. Include an Inspector CLI tools/list smoke check for CI — it exercises a real client and catches protocol regressions pytest cannot.

docs/debugging.md — reading [Graph] client logs, the OTEL spans, the structured error

Read the thread · 2026-08-05 · closed · 1 comment

Consolidate meetings.py onto client.py (14 raw httpx clients)

meetings.py holds 14 hand-rolled httpx.AsyncClient instances — by far the largest concentration left. Every one bypasses the OTEL span, the [Graph] error logging and the TLS toggle, so transcript retrieval is the least observable part of the server despite being its most-used feature.

graph_post_no_content and graph_post_raw have already removed the legitimate reasons for an inline client. Anything genuinely not expressible through client.py earns a helper there instead.

Being hand

Read the thread · 2026-08-05 · closed · 1 comment

OAuth resource server: PRM, WWW-Authenticate, audience binding

Implement the MCP authorization spec so any conforming client can authenticate without client-specific configuration — not just one client's convention.

  • GET /.well-known/oauth-protected-resource (RFC 9728) — unauthenticated, like /health
  • 401 with WWW-Authenticate: Bearer resource_metadata="...", scope="...". Today auth.py returns a bare JSON error, which gives a client nothing to discover from. This one header is what lets a spec-compliant client self-configure.
  • **403 wi

Read the thread · 2026-08-05 · closed · 1 comment

Contacts tools

The user's personal address book is not reachable.

  • people_list_contactsGET /me/contacts (READ)
  • people_search_contacts (READ)
  • people_create_contactPOST /me/contacts (WRITE)

Not a duplicate of people_search, and the descriptions must say so. /me/people is the relevance-ranked People API over colleagues the user interacts with. /me/contacts is the user's saved address book, and it includes external contacts who are not in the tenant directory at all — invisible to

Read the thread · 2026-08-05 · closed · 1 comment

OneNote page read tools

The server can write a OneNote page but cannot read one back — notes_create_page exists with no counterpart.

  • notes_list_pagesGET /me/onenote/sections/{id}/pages (READ)
  • notes_get_page_contentGET /me/onenote/pages/{id}/content (READ)

Page content is HTML, not JSON, so it uses client.py:graph_get_text — the same helper the transcript VTT path already uses. Requires Notes.Read.

Read the thread · 2026-08-05 · closed · 1 comment

Most recent

Make the HTTP transport a spec-conformant OAuth resource server (agent → MCP → Graph OBO)

Summary

Make the HTTP transport a spec-conformant OAuth 2.1 resource server, so an agent acting for a signed-in user can call this server and the server mints its own Microsoft Graph token via on-behalf-of. The user's Graph token is never handed around.

Most of this flow already exists behind GRAPH_MCP_DOES_OBO=true. It is off by default, and the default posture is the problem.

The problem

With GRAPH_MCP_DOES_OBO=false (today's default) the server accepts a token whose aud is

Read the thread · 2026-08-05 · open · 0 comments

Replace X-Write-Scope with a 403 insufficient_scope challenge

Split out of #20, which delivered the discovery half (RFC 9728 metadata + WWW-Authenticate on 401). This is the remaining piece, deliberately deferred because it is a breaking change to a working gate and had no business riding along with the change that introduced discovery.

What

The write tier is currently opted into with X-Write-Scope: true. A custom header only works for a client that has been told about it, which is the opposite of the point of #20 — a spec-compliant client should

Read the thread · 2026-08-05 · open · 0 comments

Toolset profiles: startup default with per-connection narrowing

Deferred by decision until the tool surface is complete, then decided on measured evidence rather than a guess.

Design already settled:

  • GRAPH_MCP_TOOLSETS selects namespaces at startup; an X-Toolsets header or ?toolsets= query parameter may narrow further but never widen — the startup value is the ceiling
  • Namespaces follow permission-scope families, which the Phase B renames already established, so filtering is a prefix match
  • Tool visibility is a context-efficiency lever, no

Read the thread · 2026-08-05 · closed · 0 comments

Unified search tool over POST /search/query

One endpoint searches messages, events, driveItems, lists, listItems, sites and people, plus Copilot-connector external data that nothing else in Graph reaches. Highest coverage per tool available.

  • search_query — entity types selectable by the caller
  • search_sharepoint_content — narrowed to driveItem / listItem / site

Note chat_search_messages already calls /search/query for chatMessage, so this generalises an existing pattern rather than introducing one.

Read the thread · 2026-08-05 · closed · 1 comment

Teams chat tools: 1:1 and group chats

Teams coverage looks complete but is channel-shaped. 1:1 and group chats — where most Teams conversation actually happens — are entirely absent.

  • chat_listGET /me/chats (READ)
  • chat_list_messagesGET /chats/{id}/messages (READ)
  • chat_send_messagePOST /chats/{id}/messages (WRITE)
  • chat_list_membersGET /chats/{id}/members (READ)

Chat.Read and ChatMessage.Send are already in the permission set, so this is purely unimplemented.

Gotcha: Microsoft imposes a on

Read the thread · 2026-08-05 · closed · 1 comment

Mail action tools: reply, reply-all, forward, mark read

mail_send exists but reply does not, which is backwards for an assistant — replying in-thread is both more common and safer than composing a new message to addresses the model chose.

  • mail_reply, mail_reply_all, mail_forward (WRITE, Mail.Send)
  • mail_mark_read (WRITE, Mail.ReadWrite)

All four are action endpoints returning 202 with an empty body, so they use client.py:graph_post_no_content.

Read the thread · 2026-08-05 · closed · 1 comment

Task write tools: To Do and Planner

"Mark it done" is the most-used task verb and is missing on both platforms.

  • tasks_complete_todo, tasks_update_todo
  • tasks_create_planner, tasks_update_planner, tasks_complete_planner

Planner writes are the fiddly part. Every POST/PATCH/DELETE requires If-Match carrying the current @odata.etag and returns 409/412 on conflict, so each tool is read-then-write with a retry. client.py:graph_patch already accepts extra_headers, and errors.py:conflict() is the respons

Read the thread · 2026-08-05 · closed · 0 comments

Calendar write and scheduling tools

Booking is the largest functional hole in the surface — the calendar is readable but nothing can be scheduled.

  • calendar_create_event (WRITE) — POST /me/events
  • calendar_update_event (WRITE) — PATCH /me/events/{id}
  • calendar_cancel_event (WRITE, destructiveHint: true) — notifies attendees
  • calendar_respond_to_event (WRITE) — accept / decline / tentative
  • calendar_find_meeting_times (READ) — POST /me/findMeetingTimes
  • calendar_get_free_busy (READ) — `POST /me/ca

Read the thread · 2026-08-05 · closed · 0 comments

The remaining reports are on the project's issue tracker.