Skip to content

[REF] mcp: move to 2.x - #195

Merged
beorngb merged 3 commits into
mainfrom
refactor/ms365-fastmcp
Aug 28, 2026
Merged

[REF] mcp: move to 2.x#195
beorngb merged 3 commits into
mainfrom
refactor/ms365-fastmcp

Conversation

@beorngb

@beorngb beorngb commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Closes #190.

mcp has been pinned below 2.0.0 since that release took every stdio server
down. This moves to 2.x and unpins.

How the servers move

The ergonomic server API is FastMCP on mcp 1.x and MCPServer on 2.x, and the
two are identical for the way these files use them — same @tool parameters,
same run_stdio_async, same emitted schema, checked by running one file under
both. Importing whichever is present means the same code runs on either major
and the version is chosen in pyproject alone, so trying 2.x cost one line and
would have rolled back in one line.

ms365 keeps _call_tool_impl as its dispatch, so no Graph logic moved and the
existing 53 tests still cover it. Its eighteen schemas are now derived from typed
wrappers rather than hand-written JSON, and the wrappers omit arguments left
unset so the defaults inside the implementation still apply.

Two things this turned up

  • Tool calls read isError off the result object, which 2.0 renamed the same
    way it renamed inputSchema. Servers connected and then failed on every call
    until the circuit breaker opened. Both reads now resolve fields by their
    protocol alias, which the spec fixes and both majors keep.
  • mcp-google-sheets imports mcp.server.fastmcp and has no 2.x-compatible
    release — the newest predates 2.0. It is a separate process, but it shared the
    application's site-packages, so our SDK version decided a third-party server's.
    The image now builds it a private virtualenv holding mcp 1.x.

The round-trip test had the blind spot it was built to remove

It called the session directly, so it passed while the gateway's own wrapper was
broken. It now also routes a call through call_tool; that case fails without
the isError fix and passes with it.

Verified

  • ms365 tool surface before and after: same eighteen names, descriptions,
    required arguments and per-argument descriptions — zero diffs.
  • 711 unit tests on mcp 2.1.1, including the stdio round trip.
  • Container rebuilt: ten stdio servers connect, no failures, google-sheets
    starts again.
  • Exercised through a live agent against real data, matching the result from
    before the move.

The pin has been at <2.0.0 since 2.0.0 removed the decorators every server
here was built on. Servers now use the ergonomic API, which is FastMCP on 1.x
and MCPServer on 2.x and identical for this usage, so both majors run the same
code and the version is chosen in pyproject alone.

ms365 keeps _call_tool_impl as its dispatch, so no tool logic moved and the
existing tests still cover it; the eighteen schemas are now derived from typed
wrappers instead of hand-written JSON. Wrappers omit arguments left unset so
the defaults inside the implementation still apply.

Surface verified against the live server before and after: same eighteen names,
descriptions, required arguments and per-argument descriptions, zero diffs. The
stdio round-trip test passes on 2.1.1 — the case that broke last time.
Tool calls raised AttributeError on mcp 2.x because the gateway read isError
off the result object, which 2.0 renamed to is_error. Listing was already
fixed; calling was not, so servers connected and then failed on every call.

The reads now go through a helper that resolves a field by its protocol alias,
which the spec fixes and both majors keep, rather than by attribute.

The round-trip test called the session directly and so passed while the wrapper
around it was broken — the exact blind spot it existed to remove. It now also
routes a call through the gateway, and that case fails without this fix.
mcp-google-sheets imports mcp.server.fastmcp, which mcp 2.x removed, and no
release supports 2.x — the newest predates it. Sharing the application's
site-packages meant our SDK version decided a third-party server's, and it
stopped starting the moment we moved.

It runs as its own process, so the image now builds it a private virtualenv
holding mcp 1.x. The provider points at that binary and falls back to PATH
where the venv is absent.
@beorngb
beorngb merged commit 57f3250 into main Aug 28, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate to mcp 2.x (Tool.inputSchema renamed to input_schema)

1 participant