# Gemina MCP Server

One hosted server, 13 tools for business documents. Sign in with OAuth 2.1 or send an API key. The FileTag tools are free up to 1,500 calls/month — no credit card.

- HTML version: https://www.gemina.co/docs/mcp
- Product page and config snippets for every host: https://www.gemina.co/product/agents#install
- MCP manifest: https://www.gemina.co/.well-known/mcp.json
- FileTag REST API (markdown): https://www.gemina.co/docs/filetag.md
- Gemina REST API (markdown): https://www.gemina.co/docs.md

## Overview

The Gemina MCP server speaks Streamable HTTP. Mount it as a tool source in any compatible host — Claude Code, claude.ai, Claude Desktop, Cursor, VS Code, Codex CLI, Gemini CLI, Grok, Windsurf, ChatGPT, n8n, Copilot Studio, Zapier, Cline, OpenClaw, Hermes-Agent — or drive it from a script.

- **MCP endpoint:** `https://api.gemina.co/api/v1/mcp/` (keep the trailing slash — the slashless form is rewritten, but some hosts treat the redirect as a failed connection)
- **Transport:** Streamable HTTP
- **Discovery (no credentials):** `https://api.gemina.co/api/v1/mcp/public/` — answers `tools/list` anonymously
- **Manifest:** https://www.gemina.co/.well-known/mcp.json

## Authentication

Tool execution needs a credential. The anonymous discovery mount answers `tools/list` without one.

### OAuth 2.1 — sign in from your app

Register the server without a header. The host discovers the authorization server, opens a browser, and you sign in to Gemina and approve the connection. Each connected app gets its own key; revoke it any time under **Connected apps** in the console. The token carries the `mcp` scope.

```bash
# Claude Code
claude mcp add --transport http gemina https://api.gemina.co/api/v1/mcp/
# then run /mcp inside Claude Code and sign in
```

claude.ai and Claude Desktop: Customize → Connectors → Add → Add custom connector → Paste the URL → Sign in. URL: `https://api.gemina.co/api/v1/mcp/`

Most hosts need nothing beyond the URL: they register themselves on the first 401 and open your browser. Three need an explicit second step. One can't sign in at all:

| Host | What to run | Why |
|---|---|---|
| Codex CLI | `codex mcp add gemina --url https://api.gemina.co/api/v1/mcp/` then `codex mcp login gemina` | A bare `[mcp_servers.gemina]` block in `config.toml` connects unauthenticated |
| OpenClaw | `openclaw mcp set gemina '{"url":"https://api.gemina.co/api/v1/mcp/","transport":"streamable-http","auth":"oauth"}'` then `openclaw mcp login gemina` | The `auth: "oauth"` key and the `login` command are both required — no 401-triggered sign-in |
| Hermes-Agent | `auth: oauth` in `~/.hermes/config.yaml`, then `hermes mcp login gemina` | OAuth is an explicit opt-in; run the login from a fresh terminal, the in-session reload times out first |
| Cline | API key only | No documented OAuth path for remote servers as of 27 August 2026 |

Discovery documents:

- `https://api.gemina.co/.well-known/oauth-protected-resource/api/v1/mcp` — protected resource metadata (RFC 9728)
- `https://api.gemina.co/.well-known/oauth-authorization-server/api/v1/mcp` — authorization server metadata (RFC 8414)

### API key — headless and scripted

Send a Gemina API key on every request, as `Authorization: Bearer` or `X-API-Key`. Same server, same tools; the key you use for the REST API works here unchanged.

- **Get an API key:** https://console.gemina.co/registration/create-account

## Tools

13 tools in 3 groups. Names and descriptions are read from the published manifest at build time.

### FileTag (3 tools, free tier)

Tag, rename, and enrich any PDF or image. Free tier, no credit card.

- `files_create_upload` — Reserve a pre-signed PUT slot for a file the agent holds locally, then follow the returned next_tool_call recipe into tag_file. Bytes go straight from the agent host to storage and never traverse the LLM context.
- `tag_file` — Run the FileTag pipeline against a previously uploaded slot. Returns extracted metadata, a suggested filename, six filename patterns, and a short-lived signed URL to an enriched copy with the metadata embedded in document properties or EXIF.
- `tag_url` — Fetch a public HTTPS URL server-side under strict SSRF guards and run the FileTag pipeline on it. Same result shape as tag_file; the bytes never traverse the LLM context.

### Extraction (7 tools, plan credits)

Typed extraction over invoices, Hebrew documents, line items, raw OCR, and custom templates.

- `files_create_extraction_upload` — Reserve a pre-signed PUT slot for Core-OCR extraction. Distinct from the FileTag upload flow — follow the returned recipe into extract_document with one or more extraction_types.
- `extract_document` — Run typed extraction on an uploaded slot. Choose extraction_types: ocr, invoice_headers, invoice_line_items, document_details_hebrew, document_line_items_hebrew, or custom_template. Asynchronous — returns the result directly or a correlationId to poll. Model selection and thinking, evaluation, correction, and coordinate toggles mirror the REST API.
- `get_extraction_result` — Poll for the result of an asynchronous extract_document call using its correlationId. Returns the completed extraction, or an in-process status to poll again.
- `list_extractions` — List past extractions, newest first. Filter by external_id, end_user_id, or an ISO date window, and paginate with skip and limit.
- `get_extraction` — Fetch one extraction by id, including the full extracted data.
- `get_document` — Fetch one document by id, including all of its extractions.
- `submit_extraction_feedback` — Submit verified or corrected field values for a completed extraction and get back a per-field comparison summary. Each extraction accepts feedback once.

### Document Intelligence (3 tools, plan credits)

Search the tenant's indexed documents and compute exact totals over them.

- `query_documents` — Search the tenant's indexed documents in structured mode (exact field filters), semantic mode (natural-language similarity), or hybrid mode (keyword and semantic fused with Reciprocal Rank Fusion). Returns matched documents with their extracted fields and scores.
- `aggregate_documents` — Compute sums, averages, minimums, maximums, and counts over indexed documents, grouped by vendor, currency, document type, expense type, payment method, end user, month, or year. Money metrics are always split per currency unless a currency filter is given, so totals are never mixed.
- `index_document` — Manually (re)index one document into the searchable index — after corrections, or to backfill a document processed before indexing was enabled. Indexing otherwise happens automatically on every extraction once the tenant enables it.

Chat is deliberately not a tool: a conversation carries state between turns and an MCP call is stateless. Agents compose a conversational answer from `query_documents` and `aggregate_documents` instead.

## Errors

Transport-level failures use HTTP status codes; tool failures come back as the standard Gemina error envelope inside the JSON-RPC result. Branch on `error_code`, not on the message.

| Status | `error_code` | Meaning |
|---|---|---|
| `401` | `UNAUTHORIZED_ERROR` | No credential was sent — an OAuth host reads the `WWW-Authenticate` challenge and starts the sign-in |
| `403` | `ACCESS_DENIED_ERROR` | The key is unknown, revoked or expired — re-sending it will not help |
| `403` | `insufficient_scope` | The OAuth token does not carry the `mcp` scope — reconnect the app |
| `429` | `FILETAG_RATE_LIMIT_EXCEEDED` | Burst limit — wait the `Retry-After` header and retry |
| `429` | `FILETAG_QUOTA_EXHAUSTED` | Monthly free allowance spent — `Retry-After` counts down to the reset |
| `429` | `CREDIT_EXHAUSTED`, `INSUFFICIENT_CREDITS`, `SPEND_LIMIT_EXCEEDED` | Extraction and Document Intelligence run on plan credits — retrying will not help until the reset or a plan change |

Full status-code table: https://www.gemina.co/docs#errors

## Headless session with curl

Open a session with `initialize`, then list the tools. The same headers work for `tools/call`.

```bash
curl -X POST https://api.gemina.co/api/v1/mcp/ \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'
```

```bash
curl -X POST https://api.gemina.co/api/v1/mcp/ \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
```

## Limits

- Files up to 50 MB
- ~10 calls/second burst per key
- 1,500 FileTag calls/month on the free tier; extraction and Document Intelligence run on plan credits (see https://www.gemina.co/pricing)

## Links

- Config snippets for every host: https://www.gemina.co/product/agents#install
- gemina-mcp on GitHub: https://github.com/tommyil/gemina-mcp
- Agent-ready install guide: https://raw.githubusercontent.com/tommyil/gemina-mcp/main/llms-install.md
- FileTag REST API: https://www.gemina.co/docs/filetag
- Gemina REST API: https://www.gemina.co/docs
- Free API key: https://console.gemina.co/registration/create-account
