Skip to content

feat(google-gemini): add Google Gemini MCP with full LLM binding support#222

Open
viktormarinho wants to merge 3 commits intomainfrom
feat/google-gemini-mcp
Open

feat(google-gemini): add Google Gemini MCP with full LLM binding support#222
viktormarinho wants to merge 3 commits intomainfrom
feat/google-gemini-mcp

Conversation

@viktormarinho
Copy link
Contributor

@viktormarinho viktormarinho commented Feb 6, 2026

Summary

  • Adds a new google-gemini MCP that provides direct access to Google's Gemini models via the Google Generative AI API
  • Implements the same 7 tools as the OpenRouter and Deco AI Gateway MCPs with identical binding schemas (@decocms/bindings/llm), enabling seamless interchangeability
  • Accepts a Google AI API key via the authorization header for simple, no-OAuth authentication

Tools

Tool Description
COLLECTION_LLM_LIST List Gemini models with filtering and pagination
COLLECTION_LLM_GET Get a single model by ID
LLM_METADATA Model capabilities and supported media types
LLM_DO_STREAM Streaming generation via @ai-sdk/google
LLM_DO_GENERATE Non-streaming generation via @ai-sdk/google
COMPARE_MODELS Side-by-side model comparison
RECOMMEND_MODEL Task-based model recommendations

Implementation details

  • Model listing: Calls the Gemini REST API (generativelanguage.googleapis.com/v1beta/models) directly, with pagination and 5-minute cache
  • Pricing: Hardcoded pricing table since the Gemini API doesn't expose cost data
  • Generation: Uses @ai-sdk/google (createGoogleGenerativeAI) which provides the same doStream()/doGenerate() interface as the OpenRouter provider
  • Model IDs: Stripped of the models/ prefix (e.g., gemini-2.5-pro instead of models/gemini-2.5-pro)

Test plan

  • Verify bun run check passes (TypeScript compilation)
  • Verify bun run fmt and bun run lint pass
  • Test model listing with a valid Gemini API key
  • Test streaming and non-streaming generation
  • Verify model comparison and recommendation tools work

Made with Cursor


Summary by cubic

Adds a new Google Gemini MCP with full LLM binding parity, enabling direct access to Gemini models. Drop-in compatible with existing bindings, with streaming and non-streaming generation.

  • New Features

    • Implements LLM tools: list, get, metadata, stream, generate; plus compare and recommend.
    • Uses @ai-sdk/google for doStream/doGenerate with @decocms/bindings/llm schemas.
    • Lists models via Gemini REST with pagination and a 5-minute cache; includes a maintained pricing table.
    • Orders well-known models first and exposes multimodal support via LLM_METADATA.
  • Migration

    • Pass a Google AI API key in the Authorization header only; “Bearer” prefix is accepted and stripped. No OAuth or env var fallback.
    • Model IDs omit the "models/" prefix (e.g., gemini-2.5-pro).
    • Can replace existing OpenRouter/Deco Gateway MCPs without code changes.

Written for commit c36e575. Summary will update on new commits.

Implements a new MCP for direct access to Google's Gemini API, satisfying
the same LLM binding interface as the OpenRouter and Deco AI Gateway MCPs.

Tools implemented (7 total):
- COLLECTION_LLM_LIST: List models with filtering/pagination
- COLLECTION_LLM_GET: Get single model by ID
- LLM_METADATA: Model capabilities and supported URL patterns
- LLM_DO_STREAM: Streaming generation via @ai-sdk/google
- LLM_DO_GENERATE: Non-streaming generation via @ai-sdk/google
- COMPARE_MODELS: Side-by-side model comparison
- RECOMMEND_MODEL: Task-based model recommendations

Key design decisions:
- Uses @ai-sdk/google provider for doStream/doGenerate
- Calls Gemini REST API directly for model listing
- Hardcoded pricing table (Gemini API doesn't expose pricing)
- Simple API key auth (no OAuth needed)
- 5-minute model cache for performance

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions
Copy link

github-actions bot commented Feb 6, 2026

🚀 Preview Deployments Ready!

Your changes have been deployed to preview environments:

📦 google-gemini

🔗 View Preview

These previews will be automatically updated with new commits to this PR.


Deployed from commit: a73c87f

MESH_REQUEST_CONTEXT.authorization includes the "Bearer " prefix,
but both the Gemini REST API (query param) and @ai-sdk/google
(x-goog-api-key header) expect a raw API key.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 20 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="google-gemini/README.md">

<violation number="1" location="google-gemini/README.md:10">
P2: The README instructs users to add the MCP to `deploy.json`, but deployment is automatic in this repo. This new step conflicts with the documented workflow and will mislead users.</violation>
</file>

<file name="google-gemini/server/tools/llm-binding.ts">

<violation number="1" location="google-gemini/server/tools/llm-binding.ts:421">
P1: The `flush()` implementation doesn't match its documented intent. `usage.promise.catch(() => {})` only adds an empty catch handler—it doesn't reject the promise. If the stream ends without a "finish" chunk, the promise hangs forever. Should call `usage.reject(new Error("Stream ended without finish chunk"))` instead.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

flush() {
// If stream finishes without a "finish" chunk, reject the promise
// so callers don't hang forever.
usage.promise.catch(() => {});
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 6, 2026

Choose a reason for hiding this comment

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

P1: The flush() implementation doesn't match its documented intent. usage.promise.catch(() => {}) only adds an empty catch handler—it doesn't reject the promise. If the stream ends without a "finish" chunk, the promise hangs forever. Should call usage.reject(new Error("Stream ended without finish chunk")) instead.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At google-gemini/server/tools/llm-binding.ts, line 421:

<comment>The `flush()` implementation doesn't match its documented intent. `usage.promise.catch(() => {})` only adds an empty catch handler—it doesn't reject the promise. If the stream ends without a "finish" chunk, the promise hangs forever. Should call `usage.reject(new Error("Stream ended without finish chunk"))` instead.</comment>

<file context>
@@ -0,0 +1,664 @@
+    flush() {
+      // If stream finishes without a "finish" chunk, reject the promise
+      // so callers don't hang forever.
+      usage.promise.catch(() => {});
+    },
+  });
</file context>
Fix with Cubic

1. Configure your MCP in `server/types/env.ts`
2. Implement tools in `server/tools/`
3. Rename `app.json.example` to `app.json` and customize
4. Add to `deploy.json` for deployment
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 6, 2026

Choose a reason for hiding this comment

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

P2: The README instructs users to add the MCP to deploy.json, but deployment is automatic in this repo. This new step conflicts with the documented workflow and will mislead users.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At google-gemini/README.md, line 10:

<comment>The README instructs users to add the MCP to `deploy.json`, but deployment is automatic in this repo. This new step conflicts with the documented workflow and will mislead users.</comment>

<file context>
@@ -0,0 +1,13 @@
+1. Configure your MCP in `server/types/env.ts`
+2. Implement tools in `server/tools/`
+3. Rename `app.json.example` to `app.json` and customize
+4. Add to `deploy.json` for deployment
+5. Test with `bun run dev`
+
</file context>
Fix with Cubic

…API keys

This MCP acts as a proxy -- users must pass their own Google AI key
via the authorization header. No env var fallback needed.

Co-authored-by: Cursor <cursoragent@cursor.com>
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