Release v1.22.2
A maintenance release focused on ending the hourly OAuth 2.1 re-auth loop, returning complete data from Sheets and Gmail, and adding optional OpenTelemetry tracing. Also includes a security dependency bump and new Google Docs table header controls.
Authentication
Fixed: OAuth 2.1 proxy sessions no longer force a re-auth every hour (#942, fixes #886 and #775)
When running behind the FastMCP OAuth proxy, the server was building Google credentials without an upstream refresh token, so every session died when Google's ~1 hour access token expired and clients were bounced back through the full auth flow.
The session store now walks FastMCP 3.x's real token chain — the inbound reference JWT's jti → _jti_mapping_store → _upstream_token_store — to recover the upstream access and refresh tokens, producing credentials that refresh transparently. ensure_session_from_access_token() is now async (it awaits the proxy's key-value stores); callers in auth_info_middleware and service_decorator were updated accordingly. Requires fastmcp>=3.4.4.
Google Sheets
read_sheet_valuesno longer stops at 50 rows (#955) — the tool fetched everything inrange_namebut silently truncated the rendered output to the first 50 rows with an "... and N more rows" footer. It now returns every row it fetched; callers bound the volume withrange_name(defaultA1:Z1000).- Reject cell references passed as column letters (#964, thanks @syf2211) —
_column_to_indexaccepted inputs likeA1and quietly computed a garbage index from the digits. Column parsing is now strict (^[A-Za-z]+$), and A1 range/sheet-title parsing switched from.match()to.fullmatch()so trailing junk raises a clearUserInputErrorinstead of being ignored.
Gmail
- Untruncated message export (#939, thanks @123andy) —
get_gmail_message_contentgained afull: boolparameter that returns the complete message with no truncation limit. Over HTTP the body is written to attachment storage and handed back as a download URL; over stdio you get the file path; in stateless mode (no storage) it's inlined and explicitly labeled as complete. Works with all threebody_formatvalues, includingraw, which saves the byte-exact RFC 5322 message as.eml. Encoding and file writes run on a worker thread so large exports don't block the event loop. get_gmail_thread_contentnow includes To/Cc (#970, fixes #693) — recipient headers were dropped from thread output, making it impossible to tell who was on a message. Thread formatting now goes through_extract_headersand always printsTo:/Cc:, marking them[not present in Gmail response]when Gmail genuinely omits them rather than leaving the reader guessing. RepeatedTo/Ccheaders are merged instead of last-one-wins, and thread ownership analysis matches header names case-insensitively (Gmail does not guarantee casing).
Google Docs
Table header row support (#947, thanks @pmgagne) — two new batch_update_doc operations:
pin_table_header_rows— repeat the leading N rows of a table after every page break (0unpins). This is the writable Docs API request for the header state thatTableRowStyle.tableHeaderonly reports; sendingtableHeaderonupdateTableRowStylereturns a 400.update_table_row_style— setmin_row_heightfor specific rows.
create_table_with_data also accepts header_rows to pin headers at creation time, and now reports PARTIAL SUCCESS (with the effective index) when the table is created but a follow-up styling step doesn't fully apply.
Telemetry
Optional OpenTelemetry tracing (#938, thanks @DrFaust92) — FastMCP is already instrumented, but its spans are no-ops without a configured TracerProvider. The new core/telemetry.py wires one up from the standard OTEL_* environment variables so tool-call spans export to an OTLP collector.
pip install "workspace-mcp[otel]" # already in the Docker image
export OTEL_EXPORTER_OTLP_ENDPOINT="http://otel-collector:4317"
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc" # or "http/protobuf"Strictly opt-in and off by default: with no endpoint set nothing is configured, a provider installed by auto-instrumentation is left alone, and a missing SDK logs a hint instead of failing startup. The README's security and licensing sections were updated to reflect that tracing exports only to an endpoint you configure yourself.
Dependencies
- Security bumps (#956) —
mcp1.28.1,pyasn10.6.4,pypdf6.14.2. fastmcpraised to>=3.4.4(required by the OAuth fix above).httplib20.31.2 → 0.32.0 (#969, @dependabot).
Docs
Upgrade notes
ensure_session_from_access_token()is now a coroutine. If you import it fromauth.oauth21_session_storein your own code, addawait.read_sheet_valuesoutput can be much larger than before. If you relied on the implicit 50-row cap, narrowrange_nameexplicitly.
New Contributors
As always, thanks to our new contributors!
- @pmgagne made their first contribution in #947
- @chrstphe made their first contribution in #965
- @syf2211 made their first contribution in #964
- @123andy made their first contribution in #939
Full Changelog: v1.22.1...v1.22.2