Skip to content

Releases: taylorwilsdon/google_workspace_mcp

v1.26.0

Choose a tag to compare

@taylorwilsdon taylorwilsdon released this 06 Sep 21:13

Release v1.26.0

Feature release. Calendar finally paginates and can carry attachments, Chat can edit a message it already sent, Gmail labels take colors, Docs gains tab-scoped reads and anchors that survive an index shift, Sheets can manage its tabs, and deployments can cap how much any download is allowed to buffer into memory. Special thank you to @DrFaust92 who didn't get a credit here but did the leg work on one of these.

What's Changed

  • auth/OAuth: the OAuth 2.1 protocol path now falls back to the client secrets file instead of insisting on GOOGLE_OAUTH_CLIENT_ID/GOOGLE_OAUTH_CLIENT_SECRET, so a deployment configured only with GOOGLE_CLIENT_SECRET_PATH no longer dies at startup on OAuth 2.1 requires GOOGLE_OAUTH_CLIENT_SECRET; env vars still win per value, and a path that is set but missing or malformed raises a clear error instead of falling through by @gnomed in #1076
  • gmail: manage_gmail_label takes optional background_color and text_color hex strings on create and update, validated up front against Gmail's fixed palette so a bad value names the offending field rather than coming back as a bare 400 (#351) by @ConnorMoss02 in #1083
  • core: new WORKSPACE_MCP_MAX_FILE_BYTES bounds how many bytes Drive, Gmail, Chat, and Docs downloads may buffer into process memory; unset or 0 keeps today's uncapped behavior, and an oversized download returns a Drive link and alternative tools instead of OOMing the server by @SlayerBirden in #996
  • gchat: send_message accepts an optional message_name and patches that message in place instead of only ever creating, so a typo, a stale link, or a post pitched at the wrong room can be reworded; left unset, the create path is byte for byte unchanged and the tool count stays the same by @TidyMaze in #1092
  • gcalendar: get_events and list_calendars are paginated. gcalendar was the last package still dropping nextPageToken, so the 25-event default returned 25 events with nothing to indicate a 26th existed; callers who pass neither parameter send the same request as before (#1089) by @ConnorMoss02 in #1090
  • gdocs: inspect_doc_structure reports paragraph layout stats in both modes: empty-paragraph counts, up to 100 paragraph ranges with a truncation flag, and the last paragraph's list and empty status, with list membership and object anchors in detailed output. Object anchors do not count as empty, and ranges can cover protected newlines, so the docs spell out the cleanup constraints by @kryan007 in #1080
  • gdocs/gsheets/gcalendar/gslides/auth: the document-index and delegation batch, closing #1084, #1052, #1085 and #1086 by @taylorwilsdon in #1098
    • gdocs: get_doc_content, get_doc_as_markdown and inspect_doc_structure take a tab_id, so the read tools can finally target the tab the write tools already accepted
    • gdocs: inspect_doc_structure takes preview_chars (0 or None for untruncated text), so the index workflow its own docstring describes can actually be completed past the old 100-character cap
    • gdocs: insert operations accept after_heading, before_heading, or anchor_text plus anchor_position in place of a raw index, resolved against the document at execution time, which removes the class of bug where a shifted index lands an edit on unrelated content without failing
    • gsheets: new manage_sheet_tab renames, deletes, hides, unhides, and reorders tabs within a spreadsheet
    • gcalendar: create_event and modify_event take attachments as Drive file IDs or URLs; on modify_event the list replaces the event's existing attachments rather than appending to them
    • gslides: get_presentation and get_page take include_geometry to report each element's placement
    • auth: service-account mode substitutes the full Drive scope for drive.file, which under domain-wide delegation can never reach a pre-existing file because a DWD service account never passes through the Drive picker; authorize it in the Admin console DWD scope list
    • gmail: send_gmail_message states plainly that Gmail's REST API has no send-time parameter, so an agent stops telling users a message was scheduled when it was sent immediately

New Contributors

Full Changelog: v1.25.2...v1.26.0

A very gracious thank you to those who have sponsored,
@rajivpant + @123andy being a solo maintainer in open source can be a thankless job and your thank you's mean the world!

v1.25.2

Choose a tag to compare

@taylorwilsdon taylorwilsdon released this 28 Aug 00:47

Release v1.25.2

Fixes Gmail reply threading and label handling, adds recurring-event series support to Calendar, hardens Drive's inline base64 uploads with integrity checks and zip-bomb protection, and improves Word document text extraction fidelity.

What's Changed

  • gappsscript: list_deployments now surfaces the bound versionNumber and reads descriptions from deploymentConfig, so deployment state is verifiable from the API (#922) by @WIZARD221 in #1063
  • gdrive: inline base64 uploads are validated before hitting the Drive API, with SHA-256 integrity checks, a 100 MB payload ceiling, and zip-bomb / malformed-container rejection for Office and ODF files by @taylorwilsdon in #1066
  • gmail: replies and reply drafts now target the latest non-draft, non-trash message in a thread by default, fixing cases where replies landed on an older message or an existing draft by @floriangaldo in #1065
  • gmail: the add_labels / remove_labels schema is corrected so MCP clients render a proper array input instead of a broken text field by @Tethys0 in #1058
  • gcalendar: get_events gains a single_events parameter, letting callers view recurring events as a collapsed series or as individual occurrences, with correct handling of exceptions, cancellations, and events that started in the past by @taylorwilsdon in #1067
  • gdrive: Word document text extraction now joins runs without spurious spaces, separates paragraphs with newlines, and reads headers, footers, footnotes, and endnotes by @taylorwilsdon in #1071
  • gmail: list_gmail_labels adds prefix, compact, and include_system parameters for efficient label-tree filtering (a 355-label account's 72 KB response drops to under 1 KB with a prefix filter) by @erikholz in #1041
  • auth: OAuthProxy token-expiry thresholds are now configurable via WORKSPACE_MCP_OAUTH_PROXY_TOKEN_EXPIRY_THRESHOLD_SECONDS and WORKSPACE_MCP_OAUTH_PROXY_ACCESS_TOKEN_EXPIRY_SECONDS, reducing invalid_grant errors from refresh-token rotation races by @DrFaust92 in #1061
  • auth: external OAuth token validation now runs off the event loop via asyncio.to_thread, preventing a slow Google userinfo call from blocking the entire server by @pavel-at-stacks in #1046

New Contributors

Full Changelog: v1.25.1...v1.25.2

v1.25.1

Choose a tag to compare

@taylorwilsdon taylorwilsdon released this 25 Aug 04:15

Release v1.25.1

Bug-fix release improving Gmail accuracy, Calendar timezone handling, Drive shortcut safety, and log hygiene across all services.

What's Changed

  • feat(calendar): report and author event boundaries in their own timezones - start and end times can now carry different IANA zones, and unresolvable or empty timezone values are rejected early instead of being forwarded to Google (#1044) by @seidnerj in #1044
  • fix(gmail): stop reporting batch label changes that Gmail never made - batch_modify_labels now returns honest results instead of echoing back the requested changes when the API silently no-ops (#1047) by @123andy in #1047
  • fix(logging): keep user free-text out of INFO/ERROR logs - queries, find/replace text, subjects, titles, file names, and request URIs are scrubbed from INFO and ERROR entries across all seven search tools, import/create paths, and the Gmail attach path; DEBUG remains reachable for local troubleshooting (#1037) by @123andy in #1037
  • fix(drive): preserve shortcuts for metadata updates - update_file_metadata now targets the shortcut itself rather than resolving through to the underlying file, so renaming or moving a shortcut no longer silently renames the target (#1051) by @lukaszliniewicz in #1051
  • fix(gmail): use default Send-As identity for drafts - create_draft now picks the account's configured default Send-As address instead of leaving the From header unset, which caused drafts to appear with a bare email rather than the user's display name (#1054) by @floriangaldo in #1054
  • fix(gmail): include Reply-To in message and thread header output - get_message and get_thread now surface the Reply-To header so agents can reply to the address the sender actually intended (#1042) by @mickey-mikey in #1042

New Contributors

Full Changelog: v1.25.0...v1.25.1

v1.25.0

Choose a tag to compare

@taylorwilsdon taylorwilsdon released this 18 Aug 14:13

Release v1.25.0

Large Drive downloads no longer buffer in RAM, stored attachments stop surviving forever across restarts, calendar event times carry an unambiguous weekday, and tools now accept camelCase argument names from clients that mirror Google's API field names.

What's Changed

  • enh(gdrive/gmail/core): stream Drive downloads to a temp file in 8 MB chunks and adopt them into attachment storage with the new save_attachment_from_path() (a shutil.move, so it stays memory-safe across filesystems) instead of buffering the whole payload. A multi-gigabyte download now costs one chunk of RAM rather than a full copy (#994). Stored files also keep the full UUID in their name, closing a case where a truncated 8-char prefix let two attachments silently overwrite each other, and HTML sends now build their text/plain alternative with html_to_text_preserving_breaks() so non-HTML clients see real paragraph breaks instead of First paragraph.Second paragraph. by @taylorwilsdon in #1022
  • fix(attachments): sweep the storage directory by file mtime, on get_attachment_storage() and as part of cleanup_expired(), so attachments written before a restart actually expire. Expiry previously lived only in the in-memory metadata dict, which meant a restart orphaned every file already on disk with nothing left to ever delete it by @justadityaraj in #1028
  • fix(calendar): annotate get_events start/end boundaries with the offset-local weekday (2026-08-18T09:00:00-04:00 [weekday: Tuesday; ISO weekday: 2]) and mark all-day ends as exclusive, so a model reading the response stops deriving the wrong day from a raw RFC 3339 string. Values that don't match RFC 3339 (or Google's all-day YYYY-MM-DD) pass through untouched by @TheMachineAiden in #1025
  • fix(core): add CamelCaseArgumentsMiddleware, which renames camelCase tool arguments (calendarId, timeMin, maxResults, ...) onto their snake_case parameters. Every tool declares additionalProperties: false, so callers echoing Google's field names used to fail schema validation before the request ever reached Google (#918). A key is only renamed when it isn't itself a declared parameter, its snake_case form is, and the caller didn't also pass the snake_case key, so existing callers and genuinely invalid arguments behave exactly as before by @Bortlesboat in #921

New Contributors

Full Changelog: v1.24.1...v1.25.0

v1.24.1

Choose a tag to compare

@taylorwilsdon taylorwilsdon released this 13 Aug 18:36

Release v1.24.1

Bug-fix release focused on OAuth 2.1: the ChatGPT connector can complete its token exchange again, and OAuth 2.1 mode now fails fast with an actionable message instead of dying at the last step of the browser flow. Also adds a per-tool block list for trimming individual tools out of any tier.

What's Changed

  • fix(oauth21): require GOOGLE_OAUTH_CLIENT_SECRET in OAuth 2.1 mode and fail at startup with an actionable error instead of letting the browser flow die on invalid_request: client_secret is missing at /oauth2callback. Google enforces the secret on the authorization code exchange even for public clients sending a valid PKCE code_verifier, so the documented "secretless" launch block could never complete end to end. MCP clients still connect with PKCE and no secret — the secret is only used by this server for its own upstream exchange with Google, and it doubles as the JWT signing key material, so FASTMCP_SERVER_AUTH_GOOGLE_JWT_SIGNING_KEY is no longer needed. Deployments where a separate IdP performs the code exchange are exempt via EXTERNAL_OAUTH21_PROVIDER=true. Fixes #1008 by @taylorwilsdon in #1019
  • fix(deps): bump fastmcp to >=3.4.7 to restore the ChatGPT connector (developer mode), which authenticates via CIMD with private_key_jwt client assertions. FastMCP 3.4.4's OAuthProxy validated those assertions against a doubled-slash audience (https://host//token) when the server is deployed at a bare origin, rejecting ChatGPT's correctly signed aud: https://host/token with invalid_client: Invalid JWT assertion — sign-in and consent completed, then the token exchange failed with a generic "There was a problem connecting". Fixes #1015 by @taylorwilsdon in #1018
  • enh(tools): add --disabled-tools <name> ... and WORKSPACE_MCP_DISABLED_TOOLS (comma-separated) to block individual tools by name. Every other filter is an allowlist; this one is subtractive, so it composes with --tools, --tool-tier, --read-only, and --permissions, and block wins over allow — you can drop send_gmail_message while still running --tool-tier core. Unmatched names log a warning rather than failing startup, since a name is legitimately absent when its service isn't loaded. Works for plugin users who can't pass CLI args, and the resolved block list is shown in the startup configuration banner by @taylorwilsdon in #990

Upgrade notes

If you were running OAuth 2.1 in the README's old secretless configuration, the server will now refuse to start until you set GOOGLE_OAUTH_CLIENT_SECRET (use a Web application client). That flow never actually completed against Google, so this converts a confusing mid-flow 500 into a startup error that tells you what to set. FASTMCP_SERVER_AUTH_GOOGLE_JWT_SIGNING_KEY becomes optional once the secret is set — the JWT key is derived from it — but an explicit key is still honored if you'd rather set one.

Note that --disabled-tools doesn't narrow the OAuth scopes requested at consent; scopes are derived from the loaded services, not from individual tools. Use --read-only or --permissions when the goal is scope reduction rather than a smaller tool list.

Full Changelog: v1.24.0...v1.24.1

v1.24.0

Choose a tag to compare

@taylorwilsdon taylorwilsdon released this 12 Aug 23:30

Release v1.24.0

Gmail's send path finally gets the reply machinery the draft path already had, Drive file-content updates become first-class (append/prepend, no forced Docs conversion), and Slides speaker notes are readable and editable. Rounded out with reliability fixes across Gmail batching, Drive uploads and Docs styling.

Gmail

  • feat(gmail): send_gmail_message can now build a reply the way draft_gmail_message already could — In-Reply-To/References derived from thread_id, opt-in reply_all recipients (excluding your own address and Send As alias), and quote_original history, all off a single thread fetch; to becomes optional when reply_all can derive it, and a non-reply send still fetches nothing (#898) by @vyakunin in #1004
  • gmail: opt-in include_headers on search_gmail_messages puts Subject, From and Date on each result row via format="metadata", so triaging hits no longer needs a second content call — default output is byte-identical to before by @erikholz in #1017
  • fix(gmail): batch fetches retry rate-limited 429/5xx sub-requests instead of quietly returning fewer messages than you asked for by @lukaszliniewicz in #1010
  • fix(gmail): attachments nested under multipart/signed now resolve their real filename rather than the enclosing part's by @bcelary in #1013
  • fix(gmail): draft_gmail_message reply handling — fixes the reply-threading crash, actually attaches threadId so drafted replies land in the original conversation, and stops signature line breaks from collapsing by @erikholz in #917

Drive

  • gdrive: file-content updates gain replace/append/prepend modes, keep non-Google targets (.md, .txt, .pdf) in their original format instead of forcing a Docs conversion, accept text-like JSON/XML payloads, and serialize concurrent updates to the same file behind a per-file lock; downloads also fixed for shared-drive files by @taylorwilsdon in #1016
  • fix(gdrive): resumable uploads treat 308 Resume Incomplete as the continuation signal it is instead of failing the upload by @jdowning10 in #1000
  • fix(gdrive): Shared Drive permissions are read through permissions.list, so files on a shared drive report their actual sharing state by @drew-miraxis in #1002

Docs & Slides

  • slides: speaker notes are now first class — retrieve the notes text plus its editable shape ID, and replace, append or clear notes through presentation updates, with slides that have no notes handled cleanly by @taylorwilsdon in #1003
  • fix(gdocs): fixes the styling payload bugs behind #998 and adds per-edge border control for table cells and paragraphs by @ssbn in #999

Auth & Docs

  • fix(auth): new WORKSPACE_MCP_ALLOW_NULL_ORIGIN_CONSENT flag lets reverse-proxy deployments accept the Origin: null consent POST some setups produce; off by default, and CSRF protection still rides on the SameSite=Lax MCP_CONSENT_STATE cookie by @enthouan in #925

New Contributors

Full Changelog: v1.23.1...v1.24.0

v1.23.1

Choose a tag to compare

@taylorwilsdon taylorwilsdon released this 02 Aug 20:45

Release v1.23.1

Bug-fix release focused on multi-user auth correctness and CLI argument handling.

What's Changed

  • Auth identity no longer leaks between requestsAuthInfoMiddleware re-derives the caller's identity on every request instead of relying on FastMCP's session store, so clients that open a new session per tool call always get the right user. Thanks @SlayerBirden in #992
  • Quieter, clearer logs on streamable-HTTP with legacy auth — no more noisy warnings when running the older auth path. by @taylorwilsdon in #991
  • workspace-cli stops eating your quotes — a value like query='"exact phrase"' was parsed as JSON and silently unquoted, breaking Gmail phrase searches. Values are now only JSON-decoded when they actually look like JSON (3, [["a"]], true); everything else is passed through verbatim. by @CapitalX in #983

New Contributors

Full Changelog: v1.23.0...v1.23.1

v1.23.0 - Gateway Auth, Tool Enhancements, Apps Script Overhaul

Choose a tag to compare

@taylorwilsdon taylorwilsdon released this 31 Jul 13:07

Release v1.23.0

Adds a trusted-gateway auth mode for deployments behind a reverse proxy, plus fixes for tools that were returning the wrong thing: trashed files in Drive search, empty structure for tabbed Docs, missing metadata on ranged calendar events, and Apps Script pushes that deleted files you didn't touch.

Per-user identity behind a reverse proxy

The big addition is TRUST_GATEWAY_IDENTITY (#981, #891 - huge thanks @123andy for the original implementation), a new auth mode for anyone running the server behind an MCP-aware proxy like Pomerium, Cloudflare Access, oauth2-proxy, or Traefik ForwardAuth.

Previously, running behind a gateway meant the proxy and the MCP server both wanted to own the OAuth handshake. Now the server can verify the proxy's signed identity assertion (JWT, checked against its JWKS) and use the asserted email as the per-request principal - real per-user isolation without terminating MCP OAuth itself.

The mode is deliberately fail-closed:

  • Assertions are verified cryptographically, with the algorithm pinned to block none/alg-confusion, and aud always checked so a token minted for another route can't be replayed.
  • A missing or invalid assertion rejects the request. There's no fallback to bearer tokens or transport-session identity.
  • Like OAuth 2.1 mode, user_google_email is hidden from tool schemas and auto-filled from the verified principal, so a caller can't act as another account by passing one. A configured USER_GOOGLE_EMAIL default is ignored - the principal always wins.
  • The Google consent flow binds its OAuth state to that principal, and /oauth2callback rejects a callback where the account that actually consented doesn't match.

Setup and the full env var reference live in docs/trusted-gateway-identity.md.

Alongside it, external OAuth metadata now aligns with the MCP mount path (#972 by @sebastianrosch) - protected-resource metadata is derived from where FastMCP actually mounts the endpoint, so discovery and the WWW-Authenticate challenge agree instead of advertising a resource URL that doesn't match.

Tools that return what you asked for

Four fixes in the same spirit - each one a case where a tool's output didn't match a reasonable reading of the request:

  • Drive search no longer surfaces trashed files (#978 by @martiant). search_drive_files now appends trashed=false by default, matching list_drive_items and the Drive web UI. An explicit trashed clause in your own query still wins, quoted literals aren't mistaken for one, and include_trashed=True opts back in.
  • inspect_doc_structure works on tabbed Docs without a tab_id (#976 by @Ofori01). It was reading headers and footers from the first tab but leaving body pointed at the empty top-level document, so structure inspection came back blank. Body and named ranges now come from the same tab.
  • Both get_events paths emit identical metadata (#980 by @wdrwilson). The single-event lookup returned colorId, recurrence, creator, and organizer while the ranged listing didn't. Shared formatting in calendar_helpers now drives both branches, with tests asserting parity - and eventType/status are omitted at their API defaults so ordinary meetings stay compact.
  • read_sheet_values clamps oversized reads (#986 by @SlayerBirden). Open-ended or huge A1 ranges are trimmed to 1000 rows before the Sheets request, bounding memory instead of pulling an entire sheet into the response.

Apps Script updates stop being destructive by default

update_script_content used to replace the project's entire file set with whatever you passed, so pushing one file deleted the rest. It now merges by default (#982 by @syf2211, addressing #923): your files overlay the existing project, keyed by (name, type) since Script API names exclude the extension and one project can hold both Code.gs and Code.html.

Ambiguity is rejected rather than guessed - an update missing type only resolves when exactly one existing file carries that name - and file types and the appsscript manifest name are validated up front. Per-script locks serialize concurrent merges within a process. Pass merge=False for the old full-replacement behavior.

Telemetry and startup polish

  • Opt-in user.email span attribute (#974 by @DrFaust92). Tool-call traces can now be attributed to a person rather than only the opaque enduser.id FastMCP derives from the token. It's PII, so it's strictly off unless the operator sets WORKSPACE_MCP_OTEL_USER_EMAIL, and it no-ops cleanly when OpenTelemetry isn't installed.
  • Reworked startup output. A new core/startup_ui.py centralizes the ANSI palette, section rules, and column alignment that were scattered through main.py, so the startup screen reads as one coherent block. Emphasis uses SGR attributes instead of hardcoded greys, keeping it legible on light, dark, and tinted terminals, and everything renders through a caller-supplied emit so the stdout-stays-clean-for-JSON-RPC rule lives in one place.

New Contributors

Full Changelog: v1.22.2...v1.23.0

v1.22.2

Choose a tag to compare

@taylorwilsdon taylorwilsdon released this 26 Jul 22:27

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_values no longer stops at 50 rows (#955) — the tool fetched everything in range_name but 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 with range_name (default A1:Z1000).
  • Reject cell references passed as column letters (#964, thanks @syf2211) — _column_to_index accepted inputs like A1 and 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 clear UserInputError instead of being ignored.

Gmail

  • Untruncated message export (#939, thanks @123andy) — get_gmail_message_content gained a full: bool parameter 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 three body_format values, including raw, 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_content now 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_headers and always prints To:/Cc:, marking them [not present in Gmail response] when Gmail genuinely omits them rather than leaving the reader guessing. Repeated To/Cc headers 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 (0 unpins). This is the writable Docs API request for the header state that TableRowStyle.tableHeader only reports; sending tableHeader on updateTableRowStyle returns a 400.
  • update_table_row_style — set min_row_height for 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) — mcp 1.28.1, pyasn1 0.6.4, pypdf 6.14.2.
  • fastmcp raised to >=3.4.4 (required by the OAuth fix above).
  • httplib2 0.31.2 → 0.32.0 (#969, @dependabot).

Docs

  • MCP Toplist rank badge added to the README (#965, thanks @chrstphe).

Upgrade notes

  • ensure_session_from_access_token() is now a coroutine. If you import it from auth.oauth21_session_store in your own code, add await.
  • read_sheet_values output can be much larger than before. If you relied on the implicit 50-row cap, narrow range_name explicitly.

New Contributors

As always, thanks to our new contributors!

Full Changelog: v1.22.1...v1.22.2

v1.22.1

Choose a tag to compare

@taylorwilsdon taylorwilsdon released this 22 Jul 22:17

Release v1.22.1

Bug-fix release focused on Apps Script deployments, Slides page inspection, Gmail reply threading, and a concurrency-safe startup path.

What's Changed

  • fix(gappsscript): wrap the deployment update body in deploymentConfig (with scriptId) so projects.deployments.update no longer rejects it with 400 Unknown name "description"; also adds an optional version_number to repoint a deployment at a new script version (#836) by @asif786ka in #894
  • slides: get_page now surfaces sheetsChart, image, video, and wordArt elements instead of collapsing them to "Type: Unknown" — linked charts expose their source spreadsheetId/chartId, making it possible to find the backing sheet and refresh the chart by @CharlesMcquade in #904
  • fix(core): make the credentials-dir permission check concurrency-safe — use makedirs(exist_ok=True) and a unique temp-file probe (no shared probe file, no rmdir) so personal and work servers starting together can no longer race and crash startup by @seidnerj in #879
  • fix(gmail): attach reply drafts to their existing thread via message.threadId so drafted replies appear inline in the original conversation instead of spawning a new thread by @kenjimax in #889
  • fix(gmail): preserve <br> boundaries in _HTMLTextExtractor so multi-line signatures no longer run together when extracting plain text by @sebastianlungu in #902
  • test(forms): align the set_publish_settings updateMask assertion with the shipped publishState mask, fixing the red main branch that was failing every open PR's pytest check by @ameet-rajababa in #883
  • chore(deps): bump joserfc from 1.6.4 to 1.6.8 in the uv group by @dependabot[bot] in #906

New Contributors

Full Changelog: v1.22.0...v1.22.1