Back to .md Directory

PR #37 Review Guide

Documents a pull request that adds graceful degradation, fixes a sandbox argument mutation bug, and upgrades FastMCP to 3.2.4.

May 2, 2026
0 downloads
1 views
ai llm mcp gemini
View source

What this file does

Documents a pull request that adds graceful degradation, fixes a sandbox argument mutation bug, and upgrades FastMCP to 3.2.4.

When to use it

  • Reviewing PR #37 in dipseth/google_workspace_fastmcp2
  • Understanding how to implement degraded mode for MCP servers
  • Checking for stale argument leakage in sandbox sessions
  • Aligning tool documentation with optional parameter defaults

Assumes this stack

PythonFastMCPQdrantRuffGoogle Workspace APIs

PR #37 Review Guide

Overview

This PR brings the reaserch_trm_mw branch into main via pr/migrate-to-public. It spans TRM research, module wrapper improvements, and server hardening work across multiple sessions.

Key Changes to Review

1. Graceful Degradation (High Impact)

Files: adapters/module_wrapper/__init__.py, qdrant_mixin.py, embedding_mixin.py, search_mixin/_base.py, lifespans/server_lifespans.py

Server now starts with all 96 tools even when Qdrant/embeddings are down. ModuleWrapper enters degraded mode — in-memory introspection works, vector search returns empty results, lazy reconnection recovers when services come back.

Validated: Server starts with Qdrant unreachable, card/email tools register and work with in-memory fallbacks, normal mode unchanged.

2. Stale Sandbox Argument Fix (Bug Fix)

File: middleware/sampling_middleware.py

The argument recovery middleware was mutating context.message.arguments in-place (.clear()/.update()), causing args from prior tool calls to leak into subsequent calls within the same sandbox session. Changed to dict reassignment.

Validated: Sequential search_gmail_messagessend_dynamic_cardcompose_dynamic_email calls in sandbox — no arg leakage.

3. Tool Docs Alignment (Developer Experience)

Files: gchat/card_tools.py, skills/server_skill_generator.py, gchat/wrapper_setup.py, gmail/email_wrapper_setup.py

  • send_dynamic_card now uses UserGoogleEmail = None (middleware auto-injects, LLMs don't need to pass it)
  • All hardcoded Unicode symbols in skill templates/examples converted to dynamic functions pulling from wrapper.symbol_mapping
  • Parameter tables updated with user_google_email, email content separation guidance

4. FastMCP 3.2.4 Upgrade

File: uv.lock

Security fixes (FileUpload validation, header forwarding), task auth scoping, Gemini compatibility.

5. Supporting Fixes

  • middleware/tag_based_resource_middleware.py — Forms resource list_tool set to None (requires form_id)
  • Lint: all E741/E731 errors fixed across research and diagnostic-ui code
  • Format: entire codebase formatted with ruff format

What's NOT Changed

  • Google API tool behavior (Gmail, Drive, Docs, Sheets, Calendar, etc.) — unchanged
  • Authentication flows — unchanged
  • Payment middleware — unchanged
  • DSL parser — unchanged

Test Results

SuiteResult
Module unit tests480 passed, 28 skipped, 0 failed
Client tests21 passed, 1 pre-existing failure (test_list_tools count assertion in code mode)
Live server validationsend_dynamic_card and compose_dynamic_email both succeed
Degraded modeServer starts and tools register with Qdrant down
Lintruff check passes clean
Formatruff format --check passes clean

Merge Checklist

  • CI passes (lint + format + tests)
  • No breaking changes to tool signatures (UserGoogleEmail is Optional with default=None)
  • Graceful degradation tested in both degraded and normal modes
  • Stale arg fix validated with sequential sandbox calls
  • All 96 tools register on server startup
  • Live tool calls succeed (card sent to Testing space, email drafted)

What's inside

Overview, 5 key change sections, test results table, and a 6-item merge checklist.

Change this for your project

  • Replace dipseth/google_workspace_fastmcp2 with your repository name
  • Replace pr/migrate-to-public with your target branch name
  • Replace reaserch_trm_mw with your source branch name

Where it goes

Keep it in your repository where the agent or team that needs it will read it.

Worth borrowing

  • Degraded mode pattern: server starts with all tools even when dependencies are down
  • Argument recovery fix: reassign dict instead of mutating in-place to prevent cross-call leaks

Related Documents