# Access & auth
Source: https://docs.geckovision.tech/access-and-auth
The whole engine/adapter seam is one function — Session.auth_headers(). How Gecko handles auth and paywalls invisibly to the agent.
Auth is invisible to the agent. The agent describes intent; Gecko injects
credentials at call time.
The entire engine/adapter seam is **one function**:
```python theme={null}
class AuthSession(Protocol):
def auth_headers(self) -> dict[str, str]: ...
```
Any object with `auth_headers() -> dict[str, str]` is a valid session. A paywalled API
returns its tokens; a public API returns an empty dict. This is the design that keeps
the engine **API-agnostic** — adding an API is data (the spec) plus, at most, this one
adapter.
## Sessions you get out of the box
A two-token authenticated session (JWT + API token). Returned by the access
handshake.
For public, no-auth APIs — `auth_headers()` returns an empty dict.
A non-live session for recorded demos: auth headers are present but not real.
## Store your keys safely — the credential resolver
You don't have to hand-write a `Session`. Gecko ships a credential resolver that keeps
provider secrets in your **OS keychain** and injects them at call time — the key never
enters the agent's context, shell history, a dotfile, or a log, and **it never leaves
your machine**.
```bash theme={null}
gecko auth set colosseum # hidden prompt — paste the key; it goes to your OS keychain
gecko auth list # names only, never values
gecko auth test colosseum # reports which backend answered — never the value
gecko auth rm colosseum # remove
```
The resolver tries, in order: your **OS keychain** → an external secret-manager command
(`op` / `vault` / `pass`) → an environment variable (CI/headless). For CI, just
`export COLOSSEUM_COPILOT_PAT=...`.
**Local vs hosted.** Because the key stays on *your* machine, an API that needs *your*
key runs **locally** (`gecko auth set …` then serve it). The hosted
`mcp.geckovision.tech` serves only the **public** surfaces — Gecko never holds a user's
key, so a keyed, per-person API can't be a shared hosted surface.
## How auth gating works
When a session returns an **empty** auth-header dict, Gecko treats it as "this
session can't satisfy auth-gated operations" and **hides those operations from the
agent** — it could only mis-call them. A session *with* auth surfaces everything,
unchanged. If an auth-gated tool is forced anyway, `prepare()` raises a typed error
rather than firing a request that can't succeed.
```python theme={null}
from gecko.access import public_session
from gecko.client import AgentApiClient
client = AgentApiClient(spec, session=public_session())
client.list_tools() # auth-gated operations are not in this list
client.prepare("some_auth_only_op", {}) # raises CallError — correctly refused
```
## The two-token handshake (worked example)
The live reference integration (the TxODDS World Cup API) uses a flow the agent never
has to learn. Gecko encodes it so the agent only ever describes intent:
```
guest JWT → on-chain subscribe (txSig) → sign(txSig:leagues:jwt) → activate → apiToken
```
producing a two-token session:
```
Authorization: Bearer (httpAuth)
X-Api-Token: (apiKeyAuth)
```
Transport and signer are **injected**, so the whole flow is unit-testable with no
network and no keys:
```python theme={null}
from gecko.access import establish_session
session = establish_session(base_url, tx_sig, leagues, signer=my_signer)
session.auth_headers()
# {"Authorization": "Bearer ...", "X-Api-Token": "..."}
```
## The on-chain step
The `subscribe` transaction itself is a wallet-signing, network-specific step that
lives outside the access layer (in `scripts/`). The access layer takes the resulting
`txSig` plus a signer and finishes the session.
**Mainnet boundary.** The subscribe transaction is **founder-run only**. The tooling
*simulates* by default (no spend) and hands over the exact command; a human broadcasts
it. Gecko does not sign or broadcast mainnet transactions on its own.
## Short-lived tokens & OAuth — auto-refresh
Most production APIs hand you a **short-lived access token plus a refresh token**
(the OAuth pattern). Gecko manages that lifecycle for you, behind the same
`auth_headers()` seam — the agent never sees an expiry:
* **Proactive refresh** — when the token is within a leeway window of expiry, the
session refreshes it *before* returning headers.
* **Reactive self-heal** — if a live call still comes back `401`, Gecko re-authenticates
and retries the identical call **once** (bounded — a second failure raises a typed,
redacted error, never an infinite loop).
You do the one-time interactive login yourself (Gecko can't complete a human's 2FA);
after that, Gecko takes over. `OAuth2Lifecycle` refreshes via a `refresh_token` grant,
and adapters like `oauth2_from_dpo2u()` read a local token file and refresh on their own.
```python theme={null}
from gecko.access import oauth2_from_dpo2u # reads ~/.dpo2u/oauth.json, refreshes at the token endpoint
session = oauth2_from_dpo2u()
session.auth_headers() # a valid Bearer token — refreshed transparently as it nears expiry
```
The refresh token (a secret) resolves through the credential resolver in your local
runner; the short-lived access token lives in memory only. Nothing about the token is
persisted by Gecko's control plane.
## What Gecko never does with credentials
* It never exposes auth headers in the agent-facing tool definitions.
* It never logs tokens or keys — secrets are redacted before any error is raised.
* Its **control plane** never stores or transmits your secret: the credential resolver
reads it from your local OS keychain (or env) and injects it at call time, on your
machine. Gecko only ever sends it toward the API's own host — never anywhere else.
See [Architecture](/architecture) for how this fits the control-plane model.
# Architecture
Source: https://docs.geckovision.tech/architecture
Gecko is a control plane, not a data plane. The invariants, the module map, and the single API-agnostic seam.
Gecko is a **control plane, not a data plane.** It holds the API's *surface*, the
generated tool defs, and *correctness metadata* — and never the data flowing through.
That single invariant is what makes the rest of the design coherent.
## The flow
The agent calls the real API **directly** for data. Gecko injects credentials and
stays out of the data path.
## Invariants
Stores the API surface, tool defs, and correctness metadata only — never response
payloads, user data, or secrets.
Everything API-specific reduces to data (the spec) plus one adapter seam,
`Session.auth_headers()`. Adding an API doesn't touch ingest/catalog/tools/caller.
`recorded` and `live` differ only at the transport edge. The free offline
simulation comes first; live smoke is the final check.
Tool defs never expose auth headers. The agent describes intent; Gecko injects
credentials at call time.
## Module map
The comprehension logic is the product and lives in the package; the MCP server, the
client, and the scripts are thin transport.
| Module | Responsibility |
| --------------------- | --------------------------------------------------------------------------------------- |
| `gecko/ingest.py` | OpenAPI 3.x → normalized `Operation` / `Param` (`$ref` resolution, cycle/depth guarded) |
| `gecko/catalog.py` | Lexical capability search (intent → endpoint) |
| `gecko/tools.py` | `Operation` → question-shaped agent tool defs (**auth hidden**) |
| `gecko/caller.py` | tool + args → correct `PreparedRequest` (stdlib `urllib`) |
| `gecko/access.py` | `Session.auth_headers()` — the engine/adapter seam; two-token session |
| `gecko/sample.py` | deterministic schema → example (powers \$0 recorded mode) |
| `gecko/client.py` | `AgentApiClient` — `search` / `list_tools` / `prepare` / `call` |
| `gecko/mcp_server.py` | `McpSurface` — the agent-facing MCP surface |
| `gecko/validator.py` | replay + first-call-correct check + JSONL outcome log (metadata only) |
| `gecko/evaluate.py` | task-based first-call-correct scorecard (top-1 / top-5 / well-formed) |
| `gecko/demo.py` | `run()` (recorded, \$0) + `live_demo()` |
## The one seam that matters
Adding a new API should not require touching ingest, catalog, tools, or the caller. The
only API-specific code is, at most, an auth adapter — an object that implements:
```python theme={null}
def auth_headers(self) -> dict[str, str]: ...
```
A public API uses the built-in no-auth adapter (returns `{}`); a paywalled API supplies
a session that returns its tokens. See [Access & auth](/access-and-auth).
## Outcome logging (control-plane safe)
The validator and the evaluation harness append **outcome metadata only** — tool name,
rank, ok/reason — to a JSONL log. They never write response payloads. Turning that
metadata into a richer, multi-API correctness signal is V2 work and is **not live
today**; see [Status](/status).
## Security posture
* Ingested spec/doc content is treated as **untrusted input**.
* URLs are validated before fetching (no SSRF — private/loopback/link-local ranges and
non-http schemes blocked).
* Secrets come from the environment/session and are never logged or persisted; errors
redact tokens before they're raised.
* Stdlib-first networking (`urllib`); minimal dependencies, so the engine ports
anywhere.
# Cloud
Source: https://docs.geckovision.tech/cloud
The free gecko-surf engine makes any API agent-usable and stays free forever. Cloud is the hosted, always-correct layer API providers pay for — and you pay only when it scales.
**The engine is free and stays free.** Everything that makes an agent call an API
correctly the first time is in the open-source `gecko-surf` you run yourself — no
account, telemetry off by default. **Cloud** is what we're **building on top**: the
hosted, continuously-correct, cross-customer layer. This page describes what it's
becoming — honestly, it's incoming, not shipped.
## Who pays, and why
One sentence: **the engine is free forever for builders; API providers pay a flat
per-API subscription for hosted, drift-watched, agent-ready surfaces.**
The free engine is the **funnel**: any developer points it at any painful API and gets
first-call-correct tools, forever, on their own machine — builders never pay. **Cloud is
where API providers pay** — to make *their* API the one agents call correctly, keep it
correct as it drifts, and turn more correct calls into more usage (and, wired to their
payment rail, more revenue). A provider starts free and steps up **as their API scales
with agents** — the tiers below are performance and reach, not a builder meter. If you
own an API, start at [For API providers](/for-providers).
## What Cloud adds over the free engine
* Comprehend any OpenAPI → **first-call-correct** tools · auth hidden
* `$0` recorded mode · the MCP surface + one-click add — you host it
* Anti-poisoning defenses + agent-native artifacts
* Local eval + your own telemetry — **on your disk, we see nothing**
* No account. Telemetry ships **disabled**.
* **Hosted MCP** — always-on endpoint, nothing to run or scale
* **Drift-watch** — re-comprehend when your API changes, alert *before* your integrators break
* **Access analytics** — first-call-correct rate, dark ops, failed→settled
* **Correctness corpus** — day-one-correct on a new API, from across the fleet
* **Team** — shared surfaces, roles, audit, deploy-to-your-domain
**Control-plane holds in the cloud.** We store the API **surface**, the generated
**tool definitions**, and **correctness metadata** — never your response payloads,
user data, or secrets. No lock-in: you can go back to fully self-hosted anytime.
## Plans — you pay when you scale
The tier is what scales — performance and reach, not the core capability (that's free).
The open-source engine + a free hosted tier to try — **shared throughput, best-effort
latency.** Point it at your API and see the agent-native surface today.
**Low latency, dedicated throughput, faster drift-watch, analytics, longer retention.**
For an API that's becoming load-bearing for agents.
**SLA, high throughput, white-label private discoverability, onboarding.** For an API
that's a real part of the agent economy.
We price the **value** — keeping your surface correct through drift and turning failed
agent calls into settled ones — **not the compute**, and **never a cut of what agents pay
you.** The model we're building toward is a **flat per-API subscription** that steps up
with performance/scale (Free → Pro → Scale), the Pro tier illustratively in the low
hundreds/month per API, deliberately below the coding-agent seat you already pay for.
Prices are **illustrative**, not committed — they land when Cloud ships. We'd rather
show you the shape honestly now than quote a number we haven't earned the right to charge.
## Payments — you keep 100%
We collect **our own flat fee** over whatever rail fits you — **x402 / USDC** (or **PayAI**
for recurring), or **card / fiat** via **Privy**, **abacatepay**, or Stripe. It's an injected,
neutral seam, so the rail is a config choice, not a rewrite.
And when it comes to *your* API getting paid by agents, we **compose** your rail — we point
the tools at your x402 endpoint (**PayAI, Metera, or pay.sh**) as part of the setup. You keep
every cent; **Gecko is never the payment rail and never a marketplace.**
## How we make money, plainly
A flat monthly subscription per API we keep agent-correct and drift-watched — collected as
our own fee, **never a cut of what agents pay you.** The engine developers use is free and
open source; the compounding **correctness corpus** is the moat. Metera meters it; Gecko
multiplies it.
## Come build it with us
Cloud is being built alongside the API providers who feel it most. If agents keep calling
your API wrong — or you want it to be the one they call *right* — that's exactly the surface
we want to make agent-ready.
Join the Discord — we build in the open and figure out which API to make agent-ready next.
`uvx --from "gecko-surf[serve]" gecko ` runs the whole engine on your machine today.
# How comprehension works
Source: https://docs.geckovision.tech/comprehension
Ingest, catalog, and the question-shaped tool generator — the path from an OpenAPI surface to first-call-correct agent tools, tied to the real engine.
Comprehension is the product. It is the path from a raw API surface to tools an agent
calls correctly the first time. Three stages, each a small focused module.
## 1. Ingest the surface
Gecko parses an **OpenAPI 3.x** document (YAML or JSON) into a normalized list of
operations. It resolves local `$ref`s with **cycle and depth guards** — on a cycle or
when the depth cap is hit, the `$ref` is left in place rather than expanded, so callers
still get a usable (if shallow) schema. Path-level parameters are merged into each
operation's own parameters.
Each `Operation` carries: method, path, `operation_id`, summary, description, tags,
parameters, request body, responses, and security. Each `Param` carries: name,
location, required, schema, description.
Ingest reads the **surface only** — method, path, params, request/response schemas.
It never reads or stores response data. The ingestor is stdlib + PyYAML by design, so
it runs anywhere with zero heavy dependencies.
Ingested spec content is treated as **untrusted input**, and any URL fetched to load a
remote spec is validated first.
## 2. Catalog — intent to endpoint
The catalog lets an agent go from a natural-language goal to the right endpoint. It
scores each operation by lexical overlap between the query and the operation's surface
text — summary, description, path, tags, and id — with **summary matches weighted
double** (it's the most intent-bearing field). Results are ranked and returned.
```python theme={null}
catalog.search("get live odds for a fixture", limit=5)
# → ranked CatalogEntry list, highest score first
```
It can also group capabilities by tag and emit a human/agent-readable capability map.
This is **lexical, not vector** search: at tens of endpoints it is more accurate and
far simpler than vector RAG. Vectorization is a deliberately deferred multi-API / large-API
concern, not part of V1.
## 3. Comprehend — the question-shaped tool
Each operation becomes an MCP-compatible tool definition: a name, a **question-shaped
description**, and a JSON-Schema input. Two decisions make this more than a raw OpenAPI
dump:
**Hide the plumbing.** Auth headers (`Authorization`, `X-Api-Token`, and similar) are
stripped from the agent-facing input. The agent reasons only about decision-relevant
inputs; the [access layer](/access-and-auth) injects credentials at call time.
**Carry invocation metadata.** The tool keeps an internal `_invoke` block — method,
path, and the location of each parameter — so the caller can build the real HTTP
request without re-parsing the spec.
A generated tool looks like:
```json theme={null}
{
"name": "get_odds_snapshot_fixtureId",
"description": "Live odds snapshot for a fixture. Required: fixtureId.",
"inputSchema": {
"type": "object",
"properties": { "fixtureId": { "type": "integer" } },
"required": ["fixtureId"]
},
"requires_auth": true,
"auth_schemes": ["apiKeyAuth", "httpAuth"]
}
```
`requires_auth` is true only when *every* way to call the operation needs auth (an
OpenAPI `security` requirement of `{}` means "no-auth is also acceptable", which keeps
it optional). The client uses `requires_auth` + the session to **hide operations a
no-auth session could never satisfy**, so the agent never wastes a call on them.
## 4. Build the correct request
When the agent calls a tool, the caller places each argument by its location, injects
the hidden auth headers, and assembles the request. Crucially, it **catches the silent
first-call failure** — for example a missing required path parameter raises a typed
`CallError` instead of firing a malformed request the agent can't diagnose.
## Measuring first-call-correct
Gecko ships a falsifiable scorecard. Given a client and a list of
`{goal, expect_op, args}` tasks, it measures whether the comprehension layer retrieves
the right operation (top-1 / top-5) and builds a well-formed request for it — recorded
and offline, recording **only outcome metadata** (tool, rank, ok/reason), never
payloads.
```python theme={null}
from gecko.evaluate import evaluate_tasks
card = evaluate_tasks(client, tasks)
print(card["top1_rate"], card["top5_rate"], card["well_formed_rate"])
```
This is the same harness used to score a **second public API** end-to-end (see the
`scripts/pegana_eval.py` worked example in the repo, which ingests a public peg-state
API with a no-auth session and scores first-call-correctness, including correctly
**refusing** to fire an auth-gated operation on a public read). It's evidence the
engine is API-agnostic, not a claim that Gecko one-shots every API.
# Concepts
Source: https://docs.geckovision.tech/concepts
The vocabulary behind Gecko — surface, operation, question-shaped tool, session, and the two run modes.
A small, precise vocabulary runs through the whole system. Learn these and the rest of
the docs read cleanly.
## Surface
The *surface* of an API is everything that describes how to call it: methods, paths,
parameters, request/response **schemas**, auth schemes. It is **not** the data the API
returns. Gecko ingests the surface and nothing more — this is the basis of the
[control-plane](/architecture) promise.
## Operation
A single callable endpoint, normalized from the spec into a typed record: method,
path, `operation_id`, summary/description, tags, parameters, request body, responses,
and security. Local `$ref`s are resolved (with cycle and depth guards) so each
operation is self-contained.
## Parameter
A normalized input to an operation, carrying its `name`, `location`
(`path` / `query` / `header` / `cookie`), whether it's `required`, and its schema. The
location is what lets the caller place each agent-supplied value in the right spot.
## Catalog
The "find the right endpoint" layer. It does lexical search over each operation's
surface text (summary, description, path, tags, id), with summary matches weighted
highest. At the scale of tens of endpoints this is more accurate and far simpler than
vector search — vectorization is a deliberately deferred multi-API concern.
## Question-shaped tool
The comprehension payload: an operation rendered as an agent-reasonable tool
definition — a name, a question-shaped description, and a JSON-Schema input. Two
decisions separate it from a raw OpenAPI dump:
* **Auth is hidden.** Authorization-style headers are removed from the agent-facing
input. The agent only sees decision-relevant inputs.
* **Invocation metadata travels with the tool.** The method, path, and per-parameter
locations ride along so the caller can build a real request without re-parsing the
spec.
Each tool also carries `requires_auth` and the `auth_schemes` it references, so a
session with no credentials can hide operations it could never satisfy.
## Session
The access/auth seam. Any object with `auth_headers() -> dict[str, str]` is a valid
session. A paywalled API returns its tokens; a public API returns an empty dict. The
agent never sees these headers — Gecko injects them at call time. See
[Access & auth](/access-and-auth).
## Caller
Turns a question-shaped tool plus the agent's arguments into a correct HTTP request:
it places each value in the right location (path / query / header), injects the hidden
auth headers, and **catches the failure the agent can't see** — like a missing
required path parameter — instead of firing a malformed call.
## Modes: recorded vs live
Gecko runs one code path in two modes:
| Mode | Network | Cost | What you get |
| ---------- | ------- | ----------- | ------------------------------------------------------------------- |
| `recorded` | none | \$0 | response synthesized from the response schema — falsifiable offline |
| `live` | yes | per the API | the real upstream response |
They differ **only at the transport edge**. See [Recorded mode](/recorded-mode).
## First-call-correct
The bar Gecko holds itself to: given a natural-language goal, retrieve the right
operation and build a **well-formed** request for it on the first try — no trial calls,
no malformed requests the agent can't diagnose. A built-in evaluation scores retrieval
(top-1 / top-5) and request well-formedness against a task set.
# Agent discoverability
Source: https://docs.geckovision.tech/discoverability
Gecko exists to make an API discoverable to agents — question-shaped tools, intent-to-endpoint search, hidden auth, and an llms.txt for the API itself.
Gecko's whole reason to exist is **discoverability for agents**. A human can read
docs, infer the right call, and guess at parameters. An agent shouldn't have to. These
are the mechanisms that make an ingested API discoverable.
## Intent, not endpoints
An agent describes *what it wants* — not which path to hit. The catalog turns that
intent into a ranked list of candidate operations, and the `search_capabilities` tool
on the [MCP surface](/mcp-surface) exposes it directly:
```python theme={null}
client.search("what fixtures are coming up?")
# → [{ "name": ..., "summary": ..., "path": ..., "method": ... }, ...]
```
## Question-shaped descriptions
Every tool's description is written as the question it answers, with required and
optional inputs called out. The agent picks the right tool from the description alone —
no API docs in front of it. See [How comprehension works](/comprehension).
## Auth is out of the way
Auth headers never appear in the agent-facing tool input, and operations the current
session can't authenticate are hidden entirely. The agent's surface is exactly the set
of calls it can actually make — nothing it would only fail at. See
[Access & auth](/access-and-auth).
## Only the calls that will work
When a [session](/access-and-auth) can't satisfy an operation's auth, that operation is
removed from `list_tools()` and `search()`. Discoverability means surfacing the *usable*
surface, not the whole spec — an agent should never discover a call it can't complete.
## An llms.txt for the API
Gecko can emit an agent/human-readable capability map grouped by tag — the
machine-facing equivalent of a table of contents for the API:
```python theme={null}
print(client.catalog.describe())
# ## fixtures
# - GET /api/fixtures/snapshot — upcoming fixtures
# ## odds
# - GET /api/odds/snapshot/{fixtureId} — live odds for a fixture
```
This docs site itself ships an [`llms.txt`](/llms.txt) — a discoverability map for
these docs, in the same spirit. If you're an agent, start there.
## The agent-native layer — and we dogfood it
Docs are a human handoff. An `llms.txt` or an MDX page is something an agent has to
*read and trust*; the agent-native contract is a **structured tool it calls**. Gecko's
job is to turn the human-shaped surface into that tool — so an agent finds and uses the
right call without reading prose.
Gecko projects one comprehended surface three ways, for three moments:
* **`llms.txt`** — a breadcrumb for an agent that lands on the docs: the capability map
plus a pointer to the live MCP and `search_capabilities`. (These docs ship one —
[read it](/llms.txt).)
* **OpenAPI + `x-gecko`** — the spec an OpenAPI-native tool already ingests, enriched in
place with question-shaped intents, prerequisites, and worked examples. Unknown `x-`
keys degrade gracefully, so a non-Gecko consumer just ignores them.
* **`/.well-known/gecko.json`** — the machine-precise manifest `search_capabilities`
navigates: the capability graph (which call produces the id another call needs), worked
examples, and first-call-correct stats.
All three cross-link, so an agent landing on any one reaches the callable tool. This docs
site is the reference implementation — our own surface is exposed through the same layer
we generate for any API.
## Everything an agent can fetch
This docs site publishes the same agent-native surface Gecko generates for any API —
point your agent at any of these:
* [`llms.txt`](https://docs.geckovision.tech/llms.txt) — the curated index of these docs
* [`llms-full.txt`](https://docs.geckovision.tech/llms-full.txt) — the whole docs as one Markdown file
* [`gecko.json`](https://docs.geckovision.tech/gecko.json) — the machine-readable manifest for this site
* [`/.well-known/gecko.json`](https://docs.geckovision.tech/.well-known/gecko.json) — the manifest at the discovery-convention path
* **Any page as Markdown** — append `.md` to its URL (e.g. [`/discoverability.md`](https://docs.geckovision.tech/discoverability.md))
* [Hosted MCP endpoint](https://mcp.geckovision.tech/mcp) — the live Gecko MCP (Streamable-HTTP), one-click add to Claude or Cursor
* [Product manifest (canonical)](https://geckovision.tech/gecko.json) — the source-of-truth manifest on the landing
Shipped today: the MCP surface, `search_capabilities`, hidden auth, a usable-only
surface, and this site's own agent-native artifacts — `llms.txt`, `gecko.json`, and
`/.well-known/gecko.json` (discovery level). Rolling out (see [Roadmap](/roadmap)): the
`x-gecko` OpenAPI enrichment and the richer `/.well-known/gecko.json` **capability graph**
(which call produces the id another call needs), `search_capabilities` returning the full
call recipe inline (prerequisites + a worked example), and access-quality measurement —
did the agent find and correctly use the call. We build these against our own docs first.
## Honest scope
Discoverability is real today on an ingested **OpenAPI 3.x** surface. Gecko does not
crawl arbitrary human-only docs yet, does not auto-discover APIs across the internet,
and does not verify the data an API returns. It makes a *known* API surface
agent-usable. See [Status](/status).
# For API providers
Source: https://docs.geckovision.tech/for-providers
Agents are becoming a consumer of your API — and they fail it silently. Make yours the API agents find, call correctly on the first try, and keep calling as you ship.
## The problem you can't see from your side
Your docs are written for humans — and they work for humans. But a growing share of your
integrations are now attempted by **AI agents**, and for them the experience is different:
* **Agents mis-call you.** Wrong parameter, wrong endpoint, an auth scheme inferred
incorrectly from prose. On your side that's malformed requests, retry storms,
rate-limit pressure, and support tickets that read "your API doesn't work" — when
really, the agent guessed wrong.
* **Agents can't find you.** An agent picks the API it can *discover and call correctly
today*. If that's your competitor, the traffic — and the integration — goes there. You
never see the loss; it just never arrives.
* **Your own changes break your integrators.** A renamed field that no human would
miss silently breaks every downstream agent. Their 2am incident becomes your support
ticket and, eventually, your churn.
* **A hand-rolled MCP server goes stale.** Teams that ship their own agent surface cover
a handful of endpoints, then drift out of date the next time the API ships.
None of this shows up in your analytics, because failed and never-attempted agent calls
are invisible by definition. That's the trap: the pain is real, and it's unmeasured.
## What Gecko does about it
Gecko is the **API comprehension layer for agents**. Point it at your OpenAPI (or your
docs — [no spec needed](/from-docs)) and your **whole surface** becomes question-shaped,
first-call-correct agent tools: auth handled invisibly, operations an agent can't
satisfy hidden, everything provable offline first.
## Bringing your API onboard — five moves
Some moves are self-serve and free today; one is a deliberate manual handshake (we don't
want your credentials flowing through a form); a couple are still hands-on while we build
them toward self-serve. Each is labeled with what's real right now.
Paste your OpenAPI URL — or [your docs](/from-docs), no spec needed — and get
question-shaped, first-call-correct tools back, provable offline before a single live
call. Run it yourself: `uvx --from "gecko-surf[serve]" gecko `. You
see your own API comprehended in one session, no account, no cost.
Most real APIs are auth-gated, so this is the step that needs a human exchange: hand
us a **sandbox key** and agree the **safe scope** — which operations agents may call;
anything that moves money is excluded or step-up-gated, not handed to an arbitrary
agent. Gecko stores the credential as an *opaque reference* and injects it at call
time — the agent never sees a token. See [Access & auth](/access-and-auth).
Your comprehended surface is hosted at `/{you}/mcp` with the agent-native breadcrumbs
— `llms.txt`, `gecko.json`, `/.well-known/gecko.json`, `/.well-known/x402.json` — so
agents *discover* you, not just call you ([Agent discoverability](/discoverability)).
Your own MCP, if you have one, keeps running untouched; Gecko sits **beside** it. You
get one line to hand your developers: `claude mcp add --transport http you https://mcp.geckovision.tech/you/mcp`.
Charge agents per call by wiring the generated tools to **your own** x402 endpoint
(PayAI, Metera, or pay.sh). The 402 challenge, the funds, and the settlement are
yours; Gecko composes the rail, holds nothing, signs nothing, and **takes no cut.**
You see the full challenge→settle handshake offline first (`X402_MODE=stub`) before
any real money moves; on-chain settlement is proven on devnet, and any mainnet
transaction is run by you, never by us.
Drift-watch re-comprehends your API when you ship and regenerates the tools, so your
next release doesn't silently break downstream agents — the alert fires **before their
prod does.** The surface fingerprint that makes this tractable exists today; the
auto-update loop and the adoption dashboard are **designed for V2, not yet shipped**
([Stay correct](/stay-correct)).
## What we need from you
To take a real API from comprehended to a live, measured surface:
* **A sandbox / test API key** (+ the sandbox base URL) — unlocks the gated operations
and keeps calls off production.
* **Your current OpenAPI spec** (or confirmation the docs URL is current) — so the
surface reflects today's API, and drift is measured against a real baseline.
* **The safe scope** — which operations agents may call; what to exclude or
step-up-gate (anything that moves money).
* **Distribution** — put the add-command in front of your developers. Gecko *measures*
the funnel (who connected, called, came back); it doesn't *create* the traffic.
That's the whole ask. **No production credentials, no build work on your side, no money
changing hands to start, no exclusivity.**
## Who pays, in one sentence
> **The engine is free forever for builders; API providers pay a flat per-API
> subscription for hosted, drift-watched, agent-ready surfaces.**
Flat fee. Never a percentage of your revenue, never a cut of what agents pay you, never
a public catalog listing you didn't ask for. Illustrative shape on the
[Cloud page](/cloud) — prices land when Cloud ships.
## Why this is measurable (unlike docs spend)
Human-docs spend is famously unattributable. Agent comprehension isn't: a
first-call-correct fix turns a **failed** call into a **completed** one — and if your
API is x402-metered, into a **settled** one. The delta is visible per API revision.
That's the difference between a cost center and an ROI line.
## Honest status
The comprehension engine, the scorecard, discoverability artifacts, and the free
self-serve flow are **live today**. Drift-watch, access analytics, and the hosted
provider plane are **building** — with the first design partners, now. See
[Status](/status) and [Roadmap](/roadmap) for the exact line.
## Bring your API
Join the Discord and drop your OpenAPI URL — we'll run the comprehension scorecard
on your API and show you what agents see.
Run the open-source engine against your own spec today — comprehend, serve over
MCP, emit your agent-native surface.
# From docs
Source: https://docs.geckovision.tech/from-docs
No OpenAPI? Point `gecko from-docs` at an API's doc site and it recovers a draft OpenAPI, then comprehends it into agent tools — with honest review notes for anything it couldn't pin down.
Not every painful API ships a spec. The long-tail, paywalled, human-documented ones — the
exact APIs an agent *can't* one-shot — often have **only a doc site**. `gecko from-docs` is
the on-ramp: it reads the docs and hands the comprehension engine a *draft* OpenAPI.
```bash theme={null}
gecko from-docs https://docs.some-api.com
gecko from-docs ./api-docs.html # a local file, for dev
gecko from-docs -o draft.json # also write the draft spec
```
## What it does
1. **Fetch** the doc page — SSRF-validated (private / loopback / link-local ranges and
non-HTTP schemes are refused, every redirect re-checked). The bytes are parsed and
**discarded**: Gecko is control-plane only, it never stores the doc.
2. **Recover** candidate operations from the page's structure — headings, code blocks, and
parameter tables, in document order — into a draft OpenAPI 3.1. JSON-RPC methods are
modeled honestly (one operation per method; the envelope carried on `x-jsonrpc-*`).
3. **Comprehend** the draft through the *same* engine as any spec → question-shaped,
first-call-correct agent tools.
```text theme={null}
Gecko from-docs — recover a draft API from human docs
========================================================
source: https://docs.some-api.com
recovered 3 candidate operation(s):
- sendBundle [POST /api/v1/bundles] (jsonrpc, high)
- getTipAccounts [POST /api/v1/bundles] (jsonrpc, high)
- getTipFloor [GET /api/v1/bundles/tip_floor] (rest, medium)
honesty: 2 x-review note(s), 2 low/medium-confidence field(s) to confirm.
optional auth recovered: x-tip-auth header (injected by the access layer, invisible to the agent).
comprehended draft -> 3 agent tools.
```
## It's an assistive draft, not zero-touch
`from-docs` is honest about its uncertainty. Every field it couldn't pin down from the docs
is flagged with `x-review` and a confidence level in the draft spec — so a human (or an
agent) confirms those before going live. It gets the **surface and shape** right; you confirm
the ambiguous edges, then run [`gecko test `](/quickstart) to prove the calls before
you ship.
## JS-heavy doc sites
Static docs work out of the box with the built-in reader — no extra dependencies. For doc
sites that render their navigation with JavaScript, `from-docs` tells you when it recovered
only a few operations and points you at the agent-browser driver in
[`spikes/docs_reader`](https://github.com/GeckoVision/gecko-surf/tree/main/spikes/docs_reader),
which renders the JS nav before extracting.
## Why this matters
This is the painful-API wedge, made concrete. A coding agent can one-shot a popular,
well-specified API — it can't one-shot the **Nth painful one** with no OpenAPI. `from-docs`
turns that API's docs into agent-usable tools without you hand-writing a client or a spec.
# Introduction
Source: https://docs.geckovision.tech/introduction
Gecko is the API comprehension layer for agents — point it at an API and the agent finds the right call, makes it correctly the first time, and runs.
## What Gecko is
Docs and endpoints are built for humans. **Gecko is the API comprehension layer for
agents — the layer that translates an API's surface for agents.** Point an agent at an
API — even one behind human-shaped docs and a paywall — and it finds the right call,
makes it correctly the first time, and runs. No client to hand-write, no guessing
whether the agent is calling it right.
The brand is **Gecko**. The PyPI package is **`gecko-surf`** (`pip install gecko-surf`),
the import is **`gecko`** (`from gecko import …`), and the CLI is **`gecko`**.
Today a builder reads the docs, hand-writes a client, and **still can't tell if the
agent is calling the API correctly.** Gecko removes that step. It ingests an API's
*surface* (OpenAPI today), turns it into question-shaped, first-call-correct agent
tools, drives the access/auth handshake, and lets the agent call the **real API
directly** for data.
## Where Gecko sits — three verbs, three layers
There are three distinct jobs in the agentic economy. Gecko does exactly one.
| Layer | What it does | Examples |
| -------------------------- | ------------------------------- | ------------------- |
| APIs get **PAID** | billing / settlement rail | x402, payment rails |
| skills get **DISTRIBUTED** | marketplace / discovery | skill marketplaces |
| **APIs get USED** | **comprehension / consumption** | **Gecko** |
Gecko **composes on top of** x402 / MCP / payment catalogs — it *consumes* them as
input. It is **not** a payment rail and **not** a marketplace. It is the layer that
makes an API actually *usable* by an agent.
## What it does, in one path
Parse an OpenAPI 3.x document into normalized operations and parameters — the
*surface only* (method, path, params, schemas). Never the response data.
Build a capability list so an agent can go from natural-language intent to the
right endpoint. Lexical at this scale; no vectors.
Turn each operation into a question-shaped tool an agent picks correctly with no
API docs in front of it. Auth headers are hidden from the agent.
Drive the access/subscription handshake. The whole engine/adapter seam is one
function: `Session.auth_headers()`.
The agent calls the real API directly; Gecko injects credentials and stays out
of the data path.
## Control plane, never data plane
Gecko holds the API's *surface*, the generated tool defs, and *correctness
metadata*. It **never** stores response payloads, user data, or secrets. That
invariant is what lets it ingest an API's surface unilaterally — and it is a hard
boundary, not a setting.
## Honest status
V1 — the comprehension path — is **live end-to-end against one real, painful API**
(the TxODDS World Cup API, on Solana mainnet, 857 tests passing), with a **\$0
recorded mode** that runs the whole path offline. Ingest is **OpenAPI 3.x today**.
The multi-API correctness work is **V2 and not yet live**. Gecko does **not**
claim to work on *any* API yet, and it does **not** verify or vouch for the data an
API returns. See [Status](/status) for the full picture.
## Next
Run the \$0 recorded demo — goal to correct call to data, no keys, no spend.
The vocabulary: surface, operation, question-shaped tool, session, modes.
Ingest, catalog, and the question-shaped tool generator, tied to the real code.
The MCP surface an agent installs, and how Gecko makes an API discoverable.
# The MCP surface
Source: https://docs.geckovision.tech/mcp-surface
What an agent installs — a framework-agnostic MCP surface over any ingested API, plus a synthetic search_capabilities tool for intent-to-endpoint discovery.
Gecko exposes an ingested API to an agent through the **Model Context Protocol
(MCP)**. The surface is framework-agnostic and fully testable: it's a thin view over
the client with two methods — `list_tools` and `call_tool`.
Want to see it without installing anything? Add a live, hosted surface to your agent:
```bash theme={null}
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, served recorded/\$0).
In Claude Code you can instead `/plugin install gecko-surf@geckovision` — it wires that
surface **and** the make-agent-ready workflow. See the [Quickstart](/quickstart).
## Connect it in one step
The fastest way to give an agent an API: run the CLI and paste the printed line. It
comprehends the spec, serves it over **Streamable-HTTP MCP**, and prints a one-click
"add" string for each host app.
```bash theme={null}
uvx --from "gecko-surf[serve]" gecko https://api.example.com/openapi.json
```
```text theme={null}
MCP URL (Streamable HTTP): http://127.0.0.1:8000/mcp
Add it to an agent (one step):
Claude Code: claude mcp add --transport http your-api http://127.0.0.1:8000/mcp
Cursor: cursor://…/mcp/install?name=your-api&config=…
VS Code: vscode:mcp/install?…
```
* **Claude Code** — paste the printed `claude mcp add …` line.
* **Cursor / VS Code** — open the printed deeplink (click it, or paste it into the address bar).
Serving to a *remote* agent? Add `--public-url https://` so the add strings and
the DNS-rebinding `Host`/`Origin` guard use your public URL. (For an embedded, in-process
server there's also a stdio variant — see [Using it in code](#using-it-in-code) below.)
## What the agent sees
The surface lists every usable, question-shaped tool for the API **plus one synthetic
tool**, `search_capabilities`, so the agent can go from plain-language intent to the
right endpoint and then call it.
```json theme={null}
{
"name": "search_capabilities",
"description": "Find which endpoint/tool fits a natural-language intent. Returns ranked tool names you can then call.",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string", "description": "What you want to do, in plain language." }
},
"required": ["query"]
}
}
```
Each real tool is listed with only `name`, `description`, and `inputSchema` — auth
plumbing and invocation metadata stay internal. Operations the current
[session](/access-and-auth) can't satisfy are not listed at all.
## The agent loop
Call `search_capabilities` with the goal in plain language → ranked tool names.
Read the question-shaped `description` and `inputSchema` of the top tool.
Call the tool by name with the inputs. Gecko builds the correct request,
injects auth, and returns the result.
## Using it in code
`McpSurface` wraps an `AgentApiClient` and is testable without any MCP SDK installed:
```python theme={null}
from gecko.client import AgentApiClient
from gecko.mcp_server import McpSurface
surface = McpSurface(AgentApiClient(spec), mode="recorded")
surface.list_tools() # search_capabilities + the API's tools
surface.call_tool("search_capabilities", {"query": "live odds for a fixture"})
surface.call_tool("get_odds_snapshot_fixtureId", {"fixtureId": 123})
```
## Running a real stdio server
For a live MCP server, `serve_stdio` wraps the surface with the `mcp` SDK. It is
import-guarded, so the surface and its tests work without the SDK installed.
```bash theme={null}
uv add mcp
```
```python theme={null}
from gecko.mcp_server import serve_stdio
serve_stdio("path/to/openapi.yaml", base_url="https://...", mode="recorded")
```
The MCP server is **thin transport**. All comprehension logic lives in the engine; the
server just parses input, calls the package, and formats output. Run it in `recorded`
mode for a \$0 surface, or `live` once a session is in place.
# Quickstart
Source: https://docs.geckovision.tech/quickstart
Make any API agent-usable in minutes — serve it over MCP, or embed the SDK. $0 recorded mode lets you prove every call offline first.
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:
```bash theme={null}
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`:
```jsonc theme={null}
{ "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 ` 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):
```bash theme={null}
uvx --from "gecko-surf[serve]" gecko
```
Prefer a persistent install, or a zero-Python binary?
```bash theme={null}
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 `
is shorthand for `gecko serve `.
## Bundled examples & your keys (the fastest path)
Two ready-to-run surfaces ship in the package — no spec file needed:
```bash theme={null}
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:
```bash theme={null}
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:
```bash theme={null}
brew install cloudflared # once
# stop the server (Ctrl+C), then in terminal A:
cloudflared tunnel --url http://127.0.0.1:8000 # prints https://.trycloudflare.com
# terminal B — re-run advertising that URL so Gecko trusts the host:
uvx --from "gecko-surf[serve]" colosseum-mcp --public-url https://.trycloudflare.com
claude mcp add --transport http colosseum https://.trycloudflare.com/mcp
```
## 1. Serve any API to your agent (the one-minute path)
`gecko serve ` 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.
```bash theme={null}
# straight from PyPI, no clone:
uvx --from "gecko-surf[serve]" gecko https://api.example.com/openapi.json
```
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:
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://`.
## 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.
```python theme={null}
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/`](https://github.com/GeckoVision/gecko-surf/tree/main/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.
```bash theme={null}
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 `). 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:
```bash theme={null}
gecko test https://api.example.com/openapi.json # exits non-zero if any check fails
gecko test -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:
```bash theme={null}
gecko from-docs https://docs.some-api.com
```
See [From docs](/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:
```python theme={null}
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](/access-and-auth) for how a session is established and how the
two-token handshake works.
# Recorded mode ($0)
Source: https://docs.geckovision.tech/recorded-mode
One code path, two modes. Recorded mode synthesizes responses from the spec so you can prove the comprehension offline, for free, before going live.
Gecko runs **one code path in two modes**. `recorded` and `live` differ *only at
the transport edge* — same discovery, same tool selection, same request building. The
only difference is where the response comes from.
| Mode | Network | Cost | Response source |
| ---------- | ------- | ----------- | ------------------------------------------------ |
| `recorded` | none | \$0 | synthesized from the operation's response schema |
| `live` | yes | per the API | the real upstream API |
## Why recorded mode exists
The first deliverable for any wire integration is a **free local simulation that can
falsify it offline**. Live smoke is the final check, never the primary debugger. If
the agent picks the wrong endpoint or builds a malformed request, recorded mode catches
it before a single network call — or a single cent — is spent.
Recorded mode proves the agent **selected the right call and built a well-formed
request**. It does not prove the upstream returns that exact data — for that, run
`live`. Recorded responses are schema-shaped samples, not real data.
## How the sample is built
For each operation, Gecko finds the success response schema (`200` / `201` /
`default`, JSON content) and synthesizes a minimal valid instance from it. The
generator is **deterministic** — the same schema always yields the same sample — and
walks the schema sensibly:
* honors `example`, then `default`, then the first `enum` value
* follows `anyOf` / `oneOf` (first branch) and merges `allOf`
* builds objects from `properties`, arrays from `items`
* emits typed placeholders for primitives (e.g. an ISO timestamp for a
`date-time` string), with a bounded recursion depth
This is what powers the `$0` demo: many real specs ship almost no response examples, so
to demo and validate without live calls, Gecko synthesizes from the schema.
## Running it
```bash theme={null}
uv run python -m gecko.demo # E2E recorded demo, $0
```
Or programmatically:
```python theme={null}
result = client.call(tool_name, args, mode="recorded")
# {
# "status": 200,
# "request": "https://.../api/odds/snapshot/123",
# "method": "GET",
# "data": { ... schema-shaped sample ... },
# "mode": "recorded"
# }
```
Switching to live is a one-word change once you have a [session](/access-and-auth):
```python theme={null}
result = client.call(tool_name, args, mode="live")
```
Because the path is identical, a green recorded run is a strong signal the live call
will be well-formed too — the remaining unknowns are purely network and credentials.
# Roadmap
Source: https://docs.geckovision.tech/roadmap
What's live, what's coming, and what we'll never build. We label everything — no vaporware on this page.
We label everything. **Live** = run it today. **Building** = designed and in progress.
**Exploring** = we want your input before we commit. No vaporware on this page.
## Live today — V1, comprehension
* **Ingest any OpenAPI → first-call-correct MCP tools** (`gecko `). Run it now.
* **`gecko from-docs`** — an API with no OpenAPI? Point it at the doc site → a draft spec → agent tools. See [From docs](/from-docs).
* **Invisible auth** — the credential is injected at call time, never in the tool defs, never seen by the agent.
* **`$0` recorded mode** — falsify every call offline, from the schema, before you spend a token.
* **Hosted MCP** — one-click add to Claude Code / Cursor / VS Code.
* **Control-plane correctness corpus + replay** — call-outcome *metadata* (never payloads) that proves first-call-correctness.
## Building — V2, continuous correctness
Designed, in progress. The primitives ship today; the scheduled pieces are being built.
* **Stay-correct watcher** — notice when an API drifts, diff what moved, regenerate the tool defs, and tell you — *before* your agent breaks in prod. See [Stay correct](/stay-correct).
* **The correctness corpus as a compounding asset** — every call teaches how to call an API right, so a new painful API is more first-call-correct because someone already paid the tax.
* **Poisoning / tampering monitoring** — we treat every ingested spec and doc as **untrusted**. When a stable surface silently shifts — a moved auth location, a changed host, a dropped required field — we quarantine it and alert, instead of letting the agent fire a poisoned call.
* **Vectorized semantic catalog · multi-API scale.**
## Exploring — V3, trust + Cloud
Unbuilt. If one of these is the reason you'd adopt, tell us below — it moves up.
* **Trust & verification** — *"is this the **right** call, is this response **sane**?"*
* **Cloud** — hosted always-on watcher jobs, drift + poisoning alerts, team entitlements, and the shared correctness corpus that makes an API you've never called **day-one-correct**.
## Free vs Cloud
The **`gecko-surf` engine is free and open-source, forever** — ingest, comprehend, first-call-correct
tools, recorded mode, run it yourself. **Cloud** (hosted) adds what you don't want to operate: the
always-on stay-correct watcher, drift + poisoning alerts, team entitlements, and the managed
cross-customer corpus. Who pays, in one sentence: **the engine is free forever for builders; API
providers pay a flat per-API subscription for hosted, drift-watched, agent-ready surfaces** — and
nobody ever pays us a cut of an API call ([For API providers](/for-providers)).
## What we'll never build
So the labels above stay credible:
* **No browsable provider marketplace.** Point us at the OpenAPI URL — the flow is identical for every API.
* **No payment rail, no custody** of your funds or your provider keys. We compose x402 / pay.sh; the provider charges you directly.
* **No storage of your API responses, request values, or secrets.** The correctness corpus is metadata-only *by construction* — a fail-closed allowlist, not a policy you have to trust.
## Tell us what to comprehend next
The Nth painful, paywalled, poorly-documented API — the one your agent *can't* one-shot. Open an issue and tell us. Public 👍s rank what we comprehend next.
# Status
Source: https://docs.geckovision.tech/status
An honest read on what is live, what is early, and what is deliberately deferred.
Gecko is early and we keep the status honest. Here is exactly what is real.
## What is live (V1 — comprehension)
The comprehension path is **live end-to-end against one real, painful API** — the
TxODDS World Cup API:
* ingest → catalog → question-shaped tools → access (a two-token on-chain subscribe) →
first-call-correct request → real data, proven on **Solana mainnet**
* a **\$0 recorded mode** that runs the entire path offline, no subscription, no keys
* **857 tests passing**
* a falsifiable first-call-correct scorecard (retrieval top-1 / top-5 + request
well-formedness)
The engine is **API-agnostic by construction**: ingest, catalog, tools, and the caller
are not TxODDS-specific. As a worked example of that, the repo also ingests a **second
public API** (a public peg-state API) unilaterally with a no-auth session and scores
first-call-correctness on representative tasks — including correctly *refusing* to fire
an auth-gated operation on a public read.
## What is true about scope today
Ingest is **OpenAPI 3.x today.** Gecko does not yet ingest arbitrary human-only docs,
and it does **not** claim to "work on any API." It makes a *known* OpenAPI surface
agent-usable, proven deeply on one API and demonstrated on a second.
Gecko is a **comprehension and consumption** layer. It does **not**:
* verify, score, or vouch for the **data** an API returns (that's a separate, later
concern)
* act as a payment rail or settlement layer (it composes on top of those)
* act as a marketplace or registry (it composes on top of those too)
## What is deliberately deferred
| Tier | Scope | State |
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ----------------------- |
| **V1 — comprehension** | one painful API: ingest → first-call-correct tools → access → direct call. Lexical catalog, no vectors, no DB. | **live** |
| **V2 — multi-API + correctness path** | many APIs; a feedback/correctness path; vectorized catalog when scale demands it | **not live** |
| **V3 — trust / verification** | "is this the right call, is this response sane" | **deferred on purpose** |
Vector search is intentionally absent in V1 — at tens of endpoints, lexical search is
more accurate and far simpler. It becomes relevant only at multi-API / large-API scale.
## The honest caveat
What is real is a **working comprehension path on one genuinely painful API**, and a
clean, API-agnostic engine behind it. That is the claim — no more. As scope grows, this
page will say so plainly.
## Operational note
During testing, payment integration runs in **stub** mode by default. The on-chain
subscribe is **founder-run only**: the tooling simulates (no spend) and a human
broadcasts. Gecko never signs or broadcasts a mainnet transaction on its own.
# Stay correct
Source: https://docs.geckovision.tech/stay-correct
What happens when the upstream API changes — content-addressed surfaces, the regenerable-tool model, and the corpus tripwire. The watcher is V2.
It's Saturday. Nobody shipped anything. Your agent is down anyway — upstream renamed a
field, moved a path, tightened an enum, and your hand-written client knew none of it. It
keeps sending the old shape; the API keeps returning 422; the agent keeps confidently
retrying a call that can no longer succeed.
A hand-written client is a **frozen snapshot of an API that doesn't hold still.** Every
rename is a manual diff a human has to notice, read, and re-code. Multiply by the Nth
painful API and "keep the integrations correct" becomes a standing on-call burden.
## Why the generated-tool model changes the failure mode
Your agent never calls a hand-written client through Gecko — it calls **tools generated
from the spec.** Tool generation is a *pure function of the surface*: same spec in, same
tools out. If the source of truth moves, the tools move with it — you re-comprehend the
surface instead of hand-editing a client.
Gecko knows which surface a tool came from, down to the revision:
```
surface_rev = sha256(canonicalized spec)[:12]
```
Same spec → same `surface_rev`; any edit bumps it. It's a content fingerprint stamped on
the cached comprehension and on **every** correctness record in the corpus.
The loop below is **designed; the watcher, the op-level diff, and the alert are V2 and
not yet shipped.** What *is* shipped: content-addressed surfaces, comprehension as a pure
function of the spec, and the control-plane correctness corpus + validator replay. We
won't pretend the cron job exists — the architecture just makes it a small addition, not
a rewrite.
## The stay-correct loop
Poll the spec URL, take a provider webhook, or re-scrape the docs.
Recompute `surface_rev`. Unchanged? Nothing happened, stop.
Run the same comprehension engine on the new spec.
Old `surface_rev` vs new: what params were added, removed, renamed, retyped; what endpoints moved.
Emit the new tool defs and a human-readable changelog of what moved.
## The corpus is your early-warning system
There's a second drift signal that doesn't need the spec to change — because providers
don't always tell you. Every call your agent makes through Gecko logs a
**control-plane-only** outcome: status class, error class, first-call-correct or not, and
the `surface_rev` it ran against — **never** the response body, a param value, or a token
(the writer is a fail-closed allowlist). When a tool that was first-call-correct for ten
thousand calls starts returning `422` / `404` under the same `surface_rev`, the corpus
tells you *something moved* before a human files a bug.
## In one line
A hand-written client makes *you* the diffing engine: read the changelog, edit the code,
hope you caught everything before Saturday. Gecko makes the **spec** the source of truth
and the **tools a regenerable function of it** — so a change propagates instead of
rotting, and the corpus warns you when the surface moves under a spec that never changed.