Skip to main content
You bring an openapi.json. Gecko comprehends the API’s surface, turns every endpoint into a question-shaped, first-call-correct tool with a JSON schema, and hands your agent a one-line “add me” string. No client to hand-write, no guessing whether the agent is calling it right.

Try it in 10 seconds — no install

Give your agent a live, Gecko-comprehended surface and watch it call correctly — no pip, no spec, no key:
claude mcp add --transport http gecko-txline https://mcp.geckovision.tech/txline/mcp
That’s the TxODDS TxLINE World Cup API — 18 first-call-correct tools over an API with a two-token on-chain paywall a coding agent does not one-shot. It’s served recorded ($0/offline, responses synthesized from the schema), so you explore the real surface without a subscription; point it at your own TxLINE session for live data.
claude mcp add and /plugin are Claude-Code-only. In Cursor (~/.cursor/mcp.json), VS Code, or any other MCP client, add the same endpoint to your mcp.json:
{ "mcpServers": { "gecko-txline": { "type": "http", "url": "https://mcp.geckovision.tech/txline/mcp" } } }
The transport is MCP Streamable HTTP (protocol 2025-11-25), not SSE. From the Python MCP SDK use mcp.client.streamable_http.streamablehttp_client(url) — an sse_client returns 400.

In Claude Code — install the plugin

The plugin bundles the skills + commands and wires that live demo surface, so one install gives your agent working tools and the workflow to make your own API agent-ready:
/plugin marketplace add GeckoVision/gecko-surf
/plugin install gecko-surf@geckovision
Then /make-agent-ready <openapi-url> comprehends your API and serves it over MCP; you also get /setup-x402 and the anti-poisoning guard.

Bring your own API — run the CLI

No install needed — run it straight from PyPI with uvx (the npx equivalent for Python):
uvx --from "gecko-surf[serve]" gecko <openapi-url>
Prefer a persistent install, or a zero-Python binary?
uv tool install "gecko-surf[serve]"                          # or: pip install "gecko-surf[serve]"
curl -fsSL https://get.geckovision.tech/install.sh | bash    # prebuilt binary, no Python prereq
The package is gecko-surf; the CLI is gecko; the SDK is from gecko import …. The gecko CLI has three verbs — serve (this page), test (first-call-correctness checks), and from-docs (comprehend an API that has no OpenAPI). Bare gecko <url> is shorthand for gecko serve <url>.

Bundled examples & your keys (the fastest path)

Two ready-to-run surfaces ship in the package — no spec file needed:
uvx --from "gecko-surf[serve]" jupiter-mcp        # Jupiter Swap — keyless (free tier)
uvx --from "gecko-surf[serve]" colosseum-mcp      # Colosseum Copilot — needs your key (below)
For a keyed API, store the key once in your OS keychain; Gecko injects it at call time, hidden from the agent, and it never leaves your machine:
gecko auth set colosseum      # hidden prompt — paste the PAT (arena.colosseum.org/copilot)
gecko auth list               # names only, never values
Local vs hosted. An API that needs your key runs locally — the key stays on your machine. The hosted mcp.geckovision.tech serves only the public surfaces (Gecko never holds a user’s key), so it can’t serve a keyed API like Colosseum.
“Connected” but 0 tools? Try these first — a tunnel is usually not needed:
  1. Wait ~20 s and re-check. Tool discovery can lag right after the client connects; the tools often appear on their own with no change.
  2. Server up + add in a second terminal. Leave the server running in terminal 1; run claude mcp add … in terminal 2 (the server only prints that line, it doesn’t run it), then reconnect the agent session.
  3. Clear a stale registration. An old local-scope entry can silently shadow a new user-scope one — claude mcp remove colosseum, re-add, then claude mcp list to confirm a single Connected entry.
Only if it still shows 0 tools is your client genuinely network-isolated from 127.0.0.1 (a sandboxed or remote client). Then expose the server on a real URL:
brew install cloudflared                                       # once
# stop the server (Ctrl+C), then in terminal A:
cloudflared tunnel --url http://127.0.0.1:8000                 # prints https://<name>.trycloudflare.com
# terminal B — re-run advertising that URL so Gecko trusts the host:
uvx --from "gecko-surf[serve]" colosseum-mcp --public-url https://<name>.trycloudflare.com
claude mcp add --transport http colosseum https://<name>.trycloudflare.com/mcp

1. Serve any API to your agent (the one-minute path)

gecko serve <openapi-url> SSRF-validates the spec, comprehends it, prints the MCP URL + a one-click “add” string for Claude Code / Cursor / VS Code, then serves the API over Streamable-HTTP MCP.
# straight from PyPI, no clone:
uvx --from "gecko-surf[serve]" gecko https://api.example.com/openapi.json
gecko comprehends an API and prints the MCP URL + one-click add strings Paste the printed claude mcp add … line (or open the Cursor / VS Code deeplink) and your agent can call the API — first try, right params: An agent asks in plain language, calls the right tool, and gets 200 on the first try
Auth-gated operations are hidden from the agent unless the session can satisfy them. The CLI defaults to --mode recorded ($0, synthesized) — pass --mode live for real upstream calls. Exposing it to a remote agent? Add --public-url https://<your-tunnel>.

2. Embed the SDK

Building your own app or agent loop? Skip the server and import the engine — no extras needed. AgentApiClient is the one object that makes an API agent-usable: point it at a spec, search for a capability, call it.
from gecko import AgentApiClient, public_session

# spec = a URL, a path, or a parsed dict. public_session() = no auth.
client = AgentApiClient(spec, session=public_session())

# intent → ranked endpoints
hits = client.search("get the latest live odds for a fixture")

# call the top hit in recorded mode ($0, offline)
result = client.call(hits[0]["name"], {"fixtureId": 123}, mode="recorded")
print(result["method"], result["request"], result["status"])
print(result["data"])   # schema-shaped sample
search() returns ranked entries (name, summary, path, method). call() returns {status, request, method, data, mode}. With a no-auth session, any operation that requires auth is automatically hidden from the agent — it can’t satisfy it, so it never tries. For a paywalled API, pass a Session whose auth_headers() returns your credentials (BYOK) — the key is injected at call time and never reaches the agent. A complete forkable example — an app on any API in ~20 lines — lives in examples/_starter/; for a full LLM agent (Telegram + a tool-use loop), see examples/sos_vzla_bot/.

3. Falsify it offline first — $0 recorded mode

mode="recorded" runs the same code path as live, but synthesizes the response from the API’s own response schema instead of hitting the network. No keys, no subscription, no spend — so you can prove the agent picks the right call and builds a well-formed request before you go live. $0 recorded mode — intent → the right capability → a first-call-correct request, proven offline
git clone https://github.com/GeckoVision/gecko-surf
cd gecko-surf && uv sync
uv run pytest                       # 857 passing
uv run python -m gecko.demo         # E2E: goal → discover → correct call → data (recorded, $0)
Recorded mode and the test suite need no API keys and no subscription. The recorded response is synthesized from the spec’s response schema, so it proves the agent picked the right call and built a well-formed request — not that the upstream returned that exact data.
Recorded vs live — what unlocks live. python -m gecko.demo (and gecko serve) run recorded ($0) by default, and auto-switch to live the moment a real session or credential is present — no flag to remember. The demo goes live when it finds a TxODDS session (~/.gecko/txodds-session.json, or TXODDS_API_TOKEN + TXODDS_JWT); a served API goes live once you’ve stored its key (gecko auth set <api>). So a recorded run means everything is wired correctly — you just haven’t supplied a live credential yet. Live data for a paid/gated API also needs that provider’s real session (e.g. TxODDS’s on-chain subscription), which is separate from Gecko.

Prove it’s correct — gecko test

Generate and run first-call-correctness checks for every usable tool, offline:
gecko test https://api.example.com/openapi.json     # exits non-zero if any check fails
gecko test <url> -o test_api_firstcall.py           # also writes a pytest module to commit
Each tool gets two checks — a well-formed first call (synthesized from the schema) and a required-field guard (dropping a required field is caught locally, not fired live). Wire it into CI to catch drift the moment the API changes.

No OpenAPI? Comprehend the docs — gecko from-docs

Not every painful API ships a spec. Point Gecko at the doc site and it recovers a draft OpenAPI, then comprehends it into agent tools:
gecko from-docs https://docs.some-api.com
See From docs for how the on-ramp works — and the honest review notes it emits for anything it couldn’t pin down.

Going live

Recorded mode needs nothing. For live data you pass a real Session; the call uses the same code path, differing only at the transport edge:
from gecko import AgentApiClient

client = AgentApiClient(spec, base_url="https://...", session=my_session)
client.call(tool_name, args, mode="live")   # same path as recorded
See Access & auth for how a session is established and how the two-token handshake works.