Skip to content

v0.10.0 — meeting transcripts reachable end to end

Latest

Choose a tag to compare

@JustStas JustStas released this 20 Aug 12:26
47add7e

Meeting transcripts were unreachable end to end. Two independent defects compounded, so a transcript that exists in Teams was reported as one that does not.

Breaking change

graph_get_meeting_transcript_content → graph_get_transcript_content.

The old name is 36 characters, which is 65 with the mcp__plugin_graph-mcp_graph__ prefix a plugin install adds — one over the 64-character limit on a prefixed tool name. The client rewrites an over-length name to a truncated hashed alias that does not route, so the only tool returning transcript text answered No such tool available. Standalone installs, prefixed with only mcp__graph__, were unaffected, which is why it survived.

Standalone MCP installs must update. No alias is kept: a second registration at 65 characters would still be unreachable in plugin installs, so it would only mislead.

Fixed

  • Every join-URL meeting lookup was broken. graph_list_online_meetings embedded the join URL as encodeURIComponent(join_url) inside its OData literal, and the HTTP layer percent-encoded the query string again, so Graph compared JoinWebUrl against a doubly encoded string that can never match. Every lookup failed with 404 3004: Specified meeting is not found — an error that reads as "no such meeting" rather than "the client built the filter wrong". The value now goes in verbatim, with only transport encoding. The '' apostrophe escaping that keeps a hostile join URL inside one OData literal is unchanged.
  • graph_list_online_meetings no longer claims an empty join_url "returns recent meetings". Graph has no unfiltered listing and answers 400: One of the required parameters to lookup meeting by QueryOptions is null or empty, so a missing or ambiguous lookup is now reported without spending a request.

Added

  • graph_get_meeting_id resolves the ID the six meeting tools require, from a calendar event, a Teams join URL, or a meeting chat thread. It prefers the join-URL lookup Graph documents and, when that finds nothing, derives base64("1*<organizer object ID>*0**<thread ID>") from the join URL's path segment and context.Oid. That composite is what Graph reports as onlineMeeting.id; it previously had to be assembled by hand outside the tool surface from two unrelated calls plus a shell base64. Single- and double-encoded join URLs both parse.
  • join_meeting_id on graph_list_online_meetings — the numeric meeting ID printed in every invite, spaces tolerated. The only lookup that works for short teams.microsoft.com/meet/<code> links, which carry no thread ID.
  • A contract test fails if any tool name exceeds the prefixed 64-character limit, so the next long name breaks the build instead of silently vanishing at runtime. Next longest is graph_get_channel_message_replies at 62.

Tool count

126 → 127.

Verification

npm run verify passes on a pristine checkout of the release commit: 1672 tests across 31 files, plus lint, typecheck, build, and the version, package, and lockfile validators. Both installed plugins expose exactly 127 tools.

Confirmed against live Microsoft Graph: the verbatim filter returns the meeting while the previous filter returns 404 3004; the failure reproduced on a meeting organized by the signed-in user, so it was never specific to Microsoft Bookings or shared mailboxes; a hand-derived composite ID is byte-identical to the ID the API reports; and the built bundle resolves a calendar event to that ID, lists its transcripts, and returns VTT.

Full details in CHANGELOG.md and #26.