Skip to content

feat: add Firestore storage backend for OAuth 2.1 state persistence#721

Open
peekabo0jackson wants to merge 1 commit into
taylorwilsdon:mainfrom
peekabo0jackson:firestore-storage-backend
Open

feat: add Firestore storage backend for OAuth 2.1 state persistence#721
peekabo0jackson wants to merge 1 commit into
taylorwilsdon:mainfrom
peekabo0jackson:firestore-storage-backend

Conversation

@peekabo0jackson
Copy link
Copy Markdown

@peekabo0jackson peekabo0jackson commented Apr 23, 2026

Summary

  • Adds a firestore branch to the existing WORKSPACE_MCP_OAUTH_PROXY_STORAGE_BACKEND switch alongside valkey, disk, and memory.
  • Uses py-key-value-aio[firestore] (FirestoreStore), wrapped in the same FernetEncryptionWrapper pattern as the valkey and disk backends.
  • Updates Dockerfile to install the firestore extra and regenerates uv.lock to pull google-cloud-firestore and transitive deps.

Motivation

OAuth 2.1 state (JTI mappings, upstream tokens, DCR client registrations, authorization codes, refresh token metadata) is stored in process memory by default. When the server is deployed to a platform like Google Cloud Run that scales to zero between idle periods, a cold start wipes this state, causing 401s on the next request from clients whose JWTs were issued before the restart. The user-visible symptom is "Connection issue - This connector has a server configuration issue" in Claude Desktop.

See #449 where this behavior is documented as in-memory-by-design with a recommendation to use valkey or disk for persistence. For GCP deployments, Firestore is the natural fit: native to the platform, free tier covers the workload comfortably (1 GiB storage, 50k reads/day, 20k writes/day, 20k deletes/day), no new infrastructure to provision.

Configuration

New environment variables:

  • WORKSPACE_MCP_OAUTH_PROXY_STORAGE_BACKEND=firestore — activates the backend
  • WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_PROJECT_ID — optional; defaults to ADC / GOOGLE_CLOUD_PROJECT
  • WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_DATABASE — optional; defaults to (default). Note: if deploying to a project with a named default database (not literally (default)), set this explicitly.
  • WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_COLLECTION_PREFIX — optional; defaults to fastmcp-oauth. Use per-service prefixes if multiple Cloud Run services share one Firestore database.

Authentication uses Application Default Credentials — on Cloud Run, grant the runtime service account roles/datastore.user.

Test plan

  • Existing tests pass (785 on current upstream main)
  • Deployed across 7 Cloud Run services in production
  • Verified persistence across forced container restart on 3 services
  • Confirmed no regressions in non-Firestore backends

Summary by CodeRabbit

  • New Features

    • Added Firestore as a new storage backend option for OAuth proxy state handling with serverless-safe persistence capabilities.
    • Firestore storage now includes built-in encryption alongside existing Disk and Valkey backends.
  • Documentation

    • Added comprehensive Firestore configuration documentation including required dependencies, authentication flow details, and environment variable setup.

Cloud Run services scale to zero between requests. When the process
restarts, any in-memory or local-disk OAuth 2.1 state is gone, causing
401s on the next auth flow. Firestore persists state across scale-to-zero
at no cost under the free tier, and is already available in every GCP
project without provisioning additional infrastructure.

This adds a `firestore` branch to the storage_backend switch alongside
the existing `valkey`, `disk`, and `memory` options. State is encrypted
with the same Fernet/derive_jwt_key pattern used by the Valkey and disk
backends before writing to Firestore. The collection prefix env var
lets multiple Cloud Run services share one Firestore database without
key collisions.

New env vars:
- WORKSPACE_MCP_OAUTH_PROXY_STORAGE_BACKEND=firestore
- WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_PROJECT_ID (optional; inferred from ADC)
- WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_DATABASE (optional; defaults to "(default)")
- WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_COLLECTION_PREFIX (optional; defaults to "fastmcp-oauth")

Dockerfile updated to install --extra firestore alongside --extra disk.
uv.lock regenerated to include google-cloud-firestore and transitive deps
(google-cloud-core, grpcio, grpcio-status, protobuf).

Install: pip install workspace-mcp[firestore]

Verified in production across 7 Cloud Run services. State persists
correctly across forced container restarts. No regressions in existing
752 tests.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 23, 2026

📝 Walkthrough

Walkthrough

The changes add support for Firestore as an OAuth proxy storage backend. Documentation is updated to describe Firestore configuration and encryption handling. Dependencies are added via pyproject.toml, Docker build configuration is updated to install the Firestore extra, and server initialization logic is modified to recognize and configure the Firestore backend with encryption wrapping and error handling.

Changes

Cohort / File(s) Summary
Documentation
.env.oauth21
Adds Firestore section documenting serverless-safe persistence, required dependency, GCP authentication flow, and optional environment variables. Updates encryption documentation to include Firestore alongside Disk and Valkey storage.
Dependency & Build Configuration
pyproject.toml, Dockerfile
Adds firestore extra with py-key-value-aio[firestore]>=0.3.0 dependency. Updates Docker build step to install both disk and firestore extras during uv sync.
Feature Implementation
core/server.py
Adds Firestore backend recognition in OAuth proxy storage selection. Implements dynamic import of FirestoreStore, configuration building from environment variables, encryption wrapping with FernetEncryptionWrapper, and targeted error-handling paths with fallback to default storage on dependency or validation failures.

Sequence Diagram

sequenceDiagram
    participant Server as Server Init
    participant Config as Configuration
    participant Firestore as FirestoreStore
    participant Encryption as Encryption Wrapper
    participant Storage as OAuth Storage
    
    Server->>Config: Read WORKSPACE_MCP_OAUTH_PROXY_STORAGE_BACKEND
    Config-->>Server: "firestore" mode detected
    Server->>Firestore: Dynamically import (with error handling)
    alt Dependencies available
        Firestore-->>Server: Module loaded
        Server->>Config: Extract project, database, collection prefix
        Server->>Firestore: Build store with Firestore config
        Firestore-->>Server: Store instance created
        Server->>Encryption: Derive key from JWT signing key
        Server->>Encryption: Wrap FirestoreStore with FernetEncryption
        Encryption-->>Storage: Encrypted storage ready
    else Dependencies missing or config invalid
        Server->>Server: Log warning, fallback to default storage
        Server-->>Storage: Default storage ready
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A Firestore backend hops into view,
With encryption wrapped snug, secure and true,
Configuration flows like carrots in spring,
OAuth states stored—oh what a thing!
Our proxy now soars with serverless delight,
✨🔐

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main change: adding Firestore as a new storage backend for OAuth 2.1 state persistence, which is the primary objective of the pull request.
Description check ✅ Passed The description provides comprehensive coverage of the change: motivation, technical implementation, configuration details, and a thorough test plan. While it doesn't strictly follow the template sections, it contains all substantive required information and goes beyond the minimum.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.env.oauth21 (1)

21-24: ⚠️ Potential issue | 🟡 Minor

Options legend doesn't list firestore.

The summary line still reads memory, disk, valkey / memory|disk|valkey, even though a full Firestore section is added below. Users scanning the top of the storage section will miss it.

📝 Proposed doc fix
-# Storage backend for OAuth proxy state. Options: memory, disk, valkey
+# Storage backend for OAuth proxy state. Options: memory, disk, valkey, firestore
 # Default: FastMCP's built-in default (disk on Mac/Windows, memory on Linux)
 #
-# WORKSPACE_MCP_OAUTH_PROXY_STORAGE_BACKEND=memory|disk|valkey
+# WORKSPACE_MCP_OAUTH_PROXY_STORAGE_BACKEND=memory|disk|valkey|firestore
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.env.oauth21 around lines 21 - 24, Update the options legend for the OAuth
proxy storage backend to include "firestore" so it matches the detailed
Firestore section: change the summary line and the example value for
WORKSPACE_MCP_OAUTH_PROXY_STORAGE_BACKEND (the symbol to edit) to list memory,
disk, valkey, firestore (e.g., memory|disk|valkey|firestore) so users scanning
the top see Firestore as an option.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@core/server.py`:
- Around line 458-469: The env var
WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_COLLECTION_PREFIX is misnamed and misleading
because its value is passed into FirestoreStore(..., default_collection=...)
which is only a fallback, not a prefix; update the code to either (A) rename the
env var and related logging to
WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_DEFAULT_COLLECTION and keep passing it to
FirestoreStore(default_collection=...) to match semantics, or (B) implement a
wrapper around FirestoreStore (e.g., a small helper that prepends the intended
prefix to any collection argument before delegating to
FirestoreStore.put/get/delete) so the original prefix intent is honored; adjust
use of FirestoreStore, the variable firestore_collection_prefix, and the log
message to reflect the chosen fix.
- Around line 444-469: The FirestoreStore instantiation is using wrong kwargs
and omits required credentials
(firestore_project_id/firestore_database/firestore_collection_prefix passed as
project/database/default_collection) which will raise TypeError in
FirestoreStore; fix by constructing FirestoreStore with a proper credentials
object (e.g., load service account or ADC into google_credentials and call
FirestoreStore(credentials=google_credentials, database=firestore_database) and
remove unsupported kwargs like project= and default_collection=), and also
update the surrounding exception handling in configure_server_for_http (the
Firestore import/initialization try/except) to catch TypeError or Exception so
initialization failures fall back gracefully instead of propagating.

---

Outside diff comments:
In @.env.oauth21:
- Around line 21-24: Update the options legend for the OAuth proxy storage
backend to include "firestore" so it matches the detailed Firestore section:
change the summary line and the example value for
WORKSPACE_MCP_OAUTH_PROXY_STORAGE_BACKEND (the symbol to edit) to list memory,
disk, valkey, firestore (e.g., memory|disk|valkey|firestore) so users scanning
the top see Firestore as an option.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ef1ad9ce-526a-4de8-90b3-8a546f3752f7

📥 Commits

Reviewing files that changed from the base of the PR and between 9c0e8d1 and e711c77.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • .env.oauth21
  • Dockerfile
  • core/server.py
  • pyproject.toml

Comment thread core/server.py
Comment on lines +444 to +469
from key_value.aio.stores.firestore import FirestoreStore

firestore_project_id = (
os.getenv(
"WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_PROJECT_ID", ""
).strip()
or None
)
firestore_database = (
os.getenv(
"WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_DATABASE", ""
).strip()
or None
)
firestore_collection_prefix = (
os.getenv(
"WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_COLLECTION_PREFIX", ""
).strip()
or "fastmcp-oauth"
)

client_storage = FirestoreStore(
project=firestore_project_id,
database=firestore_database,
default_collection=firestore_collection_prefix,
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm the FirestoreStore constructor signature in the installed version
pip download --no-deps --no-binary=:all: "py-key-value-aio[firestore]>=0.3.0" -d /tmp/pkv 2>/dev/null
fd -e tar.gz . /tmp/pkv -x tar -xzf {} -C /tmp/pkv
fd -t f 'firestore.py|__init__.py' /tmp/pkv --full-path | xargs rg -nP -C2 'class FirestoreStore|def __init__' 2>/dev/null | head -100

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 164


🏁 Script executed:

# First, look at the core/server.py file structure around lines 444-469
fd -t f 'server.py' . | head -5

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 189


🏁 Script executed:

# Read core/server.py to see the exception handling context
cat -n core/server.py | sed -n '430,480p'

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 2616


🏁 Script executed:

# Search for FirestoreStore usage in the codebase to find other examples
rg -n 'FirestoreStore' --type py

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 411


🏁 Script executed:

# Find the exception handlers for the Firestore block
cat -n core/server.py | sed -n '442,570p'

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 7274


🏁 Script executed:

# Search for py-key-value package documentation or source in the repo
rg -n 'py-key-value|FirestoreStore' --type py -B2 -A2

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 2095


🏁 Script executed:

# Check if there's a requirements file or setup.py that specifies the version
fd -t f '(requirements|setup|pyproject|poetry)' . | head -10

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 94


🏁 Script executed:

# Read pyproject.toml to find py-key-value-aio version
cat pyproject.toml | grep -A5 -B5 'py-key-value\|firestore'

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 986


🌐 Web query:

py-key-value-aio FirestoreStore constructor signature 0.3.0

💡 Result:

The FirestoreStore constructor signature in py-key-value-aio version 0.3.0 is FirestoreStore(credentials, database). This is shown in the official documentation example: from key_value.aio.stores.firestore import FirestoreStore store = FirestoreStore(credentials=google_credentials, database="firestore-db") Note that FirestoreStore was added in version 0.4.0 (PR #249), but the documentation reflects the current signature, which is likely the same or similar for 0.3.0 if backported or available. Version 0.3.0 was released 2025-11-17 per piwheels. Official docs at https://strawgate.github.io/py-key-value/stores/ provide the usage. GitHub repo: https://github.com/strawgate/py-key-value. No explicit source code snippet for init found, but example indicates keyword arguments credentials (Google credentials object) and database (str, Firestore database ID).

Citations:


🏁 Script executed:

# Search for any other usages or tests of FirestoreStore to find the correct kwargs
rg -n 'FirestoreStore(' --type py -B2 -A5

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 158


🌐 Web query:

py-key-value-aio FirestoreStore project_id credentials database 0.4.0

💡 Result:

py-key-value-aio is an async Python library providing a pluggable interface for key-value stores, supporting multiple backends including Firestore via FirestoreStore (added in v0.4.0). Install with pip install "py-key-value-aio[firestore]". Usage example from official docs: from key_value.aio.stores.firestore import FirestoreStore store = FirestoreStore(credentials=google_credentials, database="firestore-db") FirestoreStore initialization requires: - credentials: Google Cloud credentials object (e.g., from service account JSON via google.oauth2.service_account.Credentials.from_service_account_file or similar). - database: Firestore database ID (e.g., "(default)" or custom name like "firestore-db"). The project_id is typically specified within the credentials object (loaded from service account key file containing "project_id") or via default application credentials. It is not shown as a direct parameter in the documented constructor, but standard Google Cloud clients infer it from credentials. For non-default databases, specify the database parameter explicitly. Version 0.4.0 (released 2026-02-10) introduced Firestore support among other backends. Current latest is v0.4.4.

Citations:


🏁 Script executed:

# Escape the parenthesis properly for rg
rg -n 'FirestoreStore\(' --type py -B2 -A5

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 507


🌐 Web query:

site:github.com strawgate py-key-value FirestoreStore __init__ source code

💡 Result:

The FirestoreStore class is part of the strawgate/py-key-value library (specifically the py-key-value-aio package), which provides a pluggable async key-value store interface supporting multiple backends including Firestore (added in v0.4.0 via PR #249). Import and initialization example from official docs: from key_value.aio.stores.firestore import FirestoreStore store = FirestoreStore(credentials=google_credentials, database="firestore-db") Install with: pip install py-key-value-aio[firestore] The full source code for the FirestoreStore.init method is in the repository at https://github.com/strawgate/py-key-value, likely under key-value-aio/src/key_value/aio/stores/firestore/store.py (following the pattern of other stores like MemoryStore). The repo structure indicates stores are in src/key_value/aio/stores/[backend]/store.py. Exact init parameters likely include Firestore client credentials and database ID, plus common store options like sanitization_strategy as per library architecture (stores no longer sanitize by default; must specify SanitizationStrategy on init). No snippet of the exact init code was found in searched pages, but docs confirm the usage above. Repository: https://github.com/strawgate/py-key-value

Citations:


🌐 Web query:

"FirestoreStore" "def __init__" py-key-value credentials database project

💡 Result:

FirestoreStore is a class from the py-key-value library (also available as py-key-value-aio), which provides a key-value store abstraction supporting multiple backends including Google Cloud Firestore. It is used to interface with Firestore as a key-value store. The init method initializes the store with Google Cloud credentials and a database name: from key_value.aio.stores.firestore import FirestoreStore store = FirestoreStore(credentials=google_credentials, database="firestore-db") This matches the query terms: FirestoreStore, def init, py-key-value, credentials, database, project (project is part of the credentials setup for Firestore access). To use it: - Install: pip install py-key-value-aio[firestore] - Requires google-cloud-firestore and authentication via service account credentials (JSON key file path set via GOOGLE_APPLICATION_CREDENTIALS or passed explicitly). - The library supports async operations for distributed storage like Firestore. - Documentation: https://strawgate.github.io/py-key-value/stores/ - GitHub: https://github.com/strawgate/py-key-value

Citations:


🏁 Script executed:

# Check if there are any comments or other clues in the code about credentials handling
cat -n core/server.py | sed -n '400,550p' | grep -i 'credential\|project\|adc'

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 521


Fix FirestoreStore constructor: missing credentials parameter and incorrect kwargs.

The documented FirestoreStore signature (py-key-value-aio ≥0.3.0) is FirestoreStore(credentials=google_credentials, database="firestore-db"). The code passes project=, database=, and default_collection= instead. This will fail with TypeError at runtime:

  • Missing credentials=: The constructor requires a Google Cloud credentials object (e.g., from service account JSON or Application Default Credentials). The code does not pass this at all.
  • Incorrect project=: The project ID is embedded in the credentials object, not a separate parameter.
  • Unsupported default_collection=: Not shown in official examples and likely unsupported.

The exception handler (lines 493–504) catches only ImportError and ValueError, not TypeError. This means initialization errors will not be caught in the Firestore block and will bubble to the outer except Exception on line 570, crashing configure_server_for_http() instead of falling back gracefully.

Fix: Either pass valid credentials (e.g., via Application Default Credentials or service account key) and remove the unsupported kwargs, or widen the Firestore exception handler to catch TypeError (or all Exception types) to fail gracefully.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/server.py` around lines 444 - 469, The FirestoreStore instantiation is
using wrong kwargs and omits required credentials
(firestore_project_id/firestore_database/firestore_collection_prefix passed as
project/database/default_collection) which will raise TypeError in
FirestoreStore; fix by constructing FirestoreStore with a proper credentials
object (e.g., load service account or ADC into google_credentials and call
FirestoreStore(credentials=google_credentials, database=firestore_database) and
remove unsupported kwargs like project= and default_collection=), and also
update the surrounding exception handling in configure_server_for_http (the
Firestore import/initialization try/except) to catch TypeError or Exception so
initialization failures fall back gracefully instead of propagating.

Comment thread core/server.py
Comment on lines +458 to +469
firestore_collection_prefix = (
os.getenv(
"WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_COLLECTION_PREFIX", ""
).strip()
or "fastmcp-oauth"
)

client_storage = FirestoreStore(
project=firestore_project_id,
database=firestore_database,
default_collection=firestore_collection_prefix,
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In py-key-value-aio 0.3.0, does the FirestoreStore default_collectionconstructor argument act as a prefix applied to all collection names, or is it only used when the caller omits thecollection argument on put/get/delete?

💡 Result:

In py-key-value-aio 0.3.0, the FirestoreStore default_collection constructor argument is only used when the caller omits the collection argument on put/get/delete operations. It does not act as a prefix applied to all collection names.

Citations:


🏁 Script executed:

# Search for client_storage usage in core/server.py
rg "client_storage" core/server.py -A 3 -B 1

# Also check if there are any other FirestoreStore instantiations
rg "FirestoreStore" . --type py

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 5069


🏁 Script executed:

# Find FastMCP imports and usage
rg "fastmcp" . --type py -i -A 2 | head -100

# Check what method is called on client_storage in the OAuth setup
rg "client_storage" . --type py | grep -E "(put|get|delete|set)" -i

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 6198


🏁 Script executed:

# Find GoogleProvider imports and usage
rg "GoogleProvider" . --type py -B 2 -A 5

# Also check auth module structure
fd "auth" --type d | head -10

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 10513


🏁 Script executed:

# Look for any FastMCP-related documentation or comments about client_storage usage
rg "client_storage" . --type py -B 5 -A 5 | grep -E "(collection|GoogleProvider|client_storage)" -i

# Check if there are any comments or docs about the OAuth flow
rg "OAuth 2.1" core/server.py -B 2 -A 10 | head -80

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 5977


🏁 Script executed:

# Search for any FastMCP documentation or examples in the repo
find . -type f \( -name "*.md" -o -name "*.txt" -o -name "*.rst" \) | xargs grep -l "client_storage\|GoogleProvider" 2>/dev/null | head -5

# Check if there's a requirements or pyproject file that specifies FastMCP version
fd -e txt -e toml -e cfg -e ini | xargs grep -l "fastmcp" 2>/dev/null

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 104


🏁 Script executed:

# Check pyproject.toml for FastMCP version and documentation
cat pyproject.toml | grep -A 10 -B 2 fastmcp

# Check README for any relevant details
grep -A 20 -B 5 "client_storage\|GoogleProvider" ./README.md | head -80

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 2315


🏁 Script executed:

# Search web for FastMCP GoogleProvider documentation about client_storage
# First, let's check if there are any inline comments or usage examples in the codebase
rg "GoogleProvider" . --type py -A 15 | grep -A 15 "client_storage"

Repository: taylorwilsdon/google_workspace_mcp

Length of output: 1166


Env var named COLLECTION_PREFIX but wired to default_collection — semantic mismatch.

The default_collection parameter on py-key-value-aio's FirestoreStore is confirmed to be a fallback used only when the caller omits the collection= argument on put/get/delete; it does not act as a prefix applied to all collection names. This contradicts the env var name WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_COLLECTION_PREFIX, which implies prefix semantics. The log message at line ~478 even calls it collection_prefix despite passing it to default_collection, reinforcing the confusion.

If FastMCP's GoogleProvider ever explicitly specifies a collection= argument when using client_storage, your "prefix" will be silently ignored, and two services sharing one Firestore DB will collide despite different COLLECTION_PREFIX values.

Recommendation: Rename the env var to WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_DEFAULT_COLLECTION to match the actual semantics, or implement a wrapper that enforces the prefix intent regardless of caller-supplied collection arguments. The current naming creates a false sense of isolation that may not exist depending on FastMCP's internal behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/server.py` around lines 458 - 469, The env var
WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_COLLECTION_PREFIX is misnamed and misleading
because its value is passed into FirestoreStore(..., default_collection=...)
which is only a fallback, not a prefix; update the code to either (A) rename the
env var and related logging to
WORKSPACE_MCP_OAUTH_PROXY_FIRESTORE_DEFAULT_COLLECTION and keep passing it to
FirestoreStore(default_collection=...) to match semantics, or (B) implement a
wrapper around FirestoreStore (e.g., a small helper that prepends the intended
prefix to any collection argument before delegating to
FirestoreStore.put/get/delete) so the original prefix intent is honored; adjust
use of FirestoreStore, the variable firestore_collection_prefix, and the log
message to reflect the chosen fix.

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.

1 participant