# 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 agent sees a tool with no auth field; Gecko injects the credentials into the real request (BYOK) 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 Gecko architecture — a control plane, never a data plane. An AI agent (a goal, no API docs) asks the Gecko comprehension layer (the control plane) 'what can this API do for X?'. Inside, four stages run in order: ingest (OpenAPI — the surface only) → catalog (intent → endpoint) → tools (question-shaped, auth hidden) → access (session handshake). The access stage injects auth into the real API — the only line crossing from the control plane into the data plane. The agent then calls the real API directly and receives the data back directly; that data never passes through Gecko. 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. Gecko turns a raw OpenAPI operation into a question-shaped tool with a JSON schema — auth header removed ## 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. gecko comprehends an API and prints the MCP URL + one-click add strings 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 ``` 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://`. ## 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. $0 recorded mode — intent → the right capability → a first-call-correct request, proven offline ```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. Editing one field flips surface_rev and regenerates the affected tool 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.