Make any API agent-usable without integration code. V1: comprehension layer — turn a human-shaped OpenAPI surface into question-shaped, first-call-correct agent tools. (Working name; rename on brand pick.)
Project description
gecko-surf — make any API agent-usable without integration code
Coding agents already one-shot clean, documented APIs. They break on the painful ones — messy, paywalled, half-documented, always drifting. Today your options are: dump the whole spec (your agent picks the wrong call and sends malformed requests) or hand-write an MCP wrapper (tedious — and stale the next time the API changes).
Gecko reads the API and turns it into tools your agent calls right the first time — no integration code. Point an agent at an API — even one behind human-shaped docs and a paywall — add it in one line, and it finds the right call, drives the access/auth handshake, and calls the real API directly. Free and open source.
Docs and endpoints are built for humans. Gecko translates them for agents.
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/docs), 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
| Layer | What it does | Who |
|---|---|---|
| APIs get PAID | billing / settlement rail | Metera (gate402), MCPay |
| skills get DISTRIBUTED | marketplace / discovery | frames.ag, Bazaar |
| APIs get USED | comprehension / consumption | Gecko |
Gecko composes on top of x402 / MCP / pay.sh — it consumes a payment catalog 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.
Try it in 10 seconds — one line, zero install
Give your agent a Gecko-comprehended surface and watch it make first-call-correct
calls — no pip, no spec, no key:
claude mcp add --transport http gecko-txline https://mcp.geckovision.tech/txline/mcp
That connects your agent to the TxODDS TxLINE World Cup API — 18 question-shaped,
first-call-correct tools over an API with a two-token on-chain paywall, served
agent-native. It's a recorded demo (responses synthesized from schema, $0,
offline — so you can explore the surface without a subscription); point it at your own
TxLINE session for live data. Also live: Jito at /jito/mcp.
Not using Claude Code? claude mcp add and /plugin are Claude-Code-only. Everywhere
else — Cursor (~/.cursor/mcp.json), VS Code, or any MCP client — add the same
endpoint to your mcp.json:
{ "mcpServers": { "gecko-txline": { "type": "http", "url": "https://mcp.geckovision.tech/txline/mcp" } } }
The transport is MCP Streamable HTTP (protocol 2025-11-25), not SSE. From the Python
MCP SDK, connect with mcp.client.streamable_http.streamablehttp_client(url) (an
sse_client will 400).
This is the fastest way to see what Gecko does before you bring your own API. When you're ready to make your API agent-usable, jump to Make any API agent-usable below.
⚠️ Status (honest)
V1 is live on mainnet, end-to-end, against the real TxODDS World Cup API: ingest → comprehend → catalog → access (a two-token on-chain subscribe) → first-call-correct → real data. A $0 recorded mode runs the entire path offline with no subscription. 442 tests pass.
What is not proven: consumer willingness-to-pay — the actual decider for the business. That is discovery-interview work, not a demo claim. So: never read this repo as "Gecko is a proven business." What is real today is a working comprehension path on one genuinely painful API, and a clean, API-agnostic engine behind it.
Watch it run — the 70-second launch demo
Three acts, every number from a real run:
- Plug in a paywalled API (TxODDS) → 18 ops comprehended, 8/8 first-call-correct, live World Cup odds.
- Stay safe → a poisoned spec that drains a naive agent 8/8 is blocked 0/8, benign calls still served — caught in simulation, before any signature exists.
- Stay correct →
gecko testwrites 32/32 first-call-correctness checks and emits them to CI.
Architecture
Gecko is a control plane, not a data plane. It 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 any API unilaterally.
flowchart TD
A["AI agent<br/>(has a goal, no API docs)"] -->|"what can this API do for X?"| S
subgraph SC["Gecko — comprehension layer (control plane)"]
direction TB
ING[("ingest<br/>OpenAPI / docs — the *surface* only")]
CAT["catalog<br/>intent → endpoint"]
TOOL["tools<br/>question-shaped, first-call-correct<br/>(auth hidden)"]
ACC["access<br/>subscribe / session handshake"]
ING --> CAT --> TOOL
TOOL --> ACC
end
S --> TOOL
ACC -->|"injects auth"| CALL
A -->|"calls the real API directly"| CALL["the real API<br/>(data plane — Gecko never stores it)"]
CALL -->|"data"| A
- Ingest the API surface (OpenAPI 3.x) → normalized operations + params (
$refresolved, cycle/depth guarded). Never the response data. - Catalog — a structured capability list (intent → endpoint). Lexical at this scale; no vectors.
- Comprehend — each operation becomes a question-shaped tool def an agent picks correctly with no API docs. Auth headers are hidden.
- Access — drive the access/subscription handshake; the seam is one function,
Session.auth_headers(). - Call — the agent calls the real API directly; Gecko injects credentials and stays out of the data path.
- Validate — replay calls, confirm first-call-correct, log outcomes (JSONL). That log is the seed of the V2 correctness corpus — the compounding moat.
What you get
| Surface | Entry point | Status |
|---|---|---|
| Serve any API to agents (paste a spec → hosted MCP + one-click "add to Claude/Cursor") | gecko serve <openapi-url> (or bare gecko <openapi-url>) |
shipped |
| Generate + run first-call-correctness tests (before any live call) | gecko test <openapi-url> [-o test_api.py] |
shipped |
| Recover a draft OpenAPI from human docs (no spec? point it at the doc page) | gecko from-docs <doc-url-or-path> [-o draft.json] |
shipped |
Embed the SDK (search / list_tools / prepare / call) |
from gecko import AgentApiClient |
shipped |
| Forkable starter (an app on any API, ~20 lines, $0) | examples/_starter/ |
shipped |
| $0 recorded demo (goal → discover → correct call → data, offline) | python -m gecko.demo |
runnable now |
| Live demo against real TxODDS World Cup data | gecko.demo:live_demo (after subscribe) |
mainnet-proven |
| Correctness harness (first-call-correct + flywheel log) | gecko.validator |
shipped |
Make any API agent-usable
Point it at an OpenAPI and your agent can call it — no client code, auth handled, first call correct. Two ways in — by where your agent lives:
A · In Claude Code — install the plugin (skills + commands + a live demo surface):
/plugin marketplace add GeckoVision/gecko-surf
/plugin install gecko-surf@geckovision
/make-agent-ready https://api.example.com/openapi.json
Installing wires the live gecko-txline demo surface (working tools, zero setup) and
gives you the skills/commands: /make-agent-ready comprehends your API, serves it over
MCP, and prints the one-click add string — plus /setup-x402 and the anti-poisoning guard.
B · Anywhere else — install the CLI (Cursor, VS Code, any agent framework, or a plain terminal):
# no-install, nothing to trust — a versioned package, run directly:
uvx --from "gecko-surf[serve]" gecko <openapi-url>
# or the one-line installer — but VERIFY it first (an agent should never blind-execute):
python3 <(curl -fsSL https://raw.githubusercontent.com/GeckoVision/gecko-surf/main/scripts/verify_install.py)
# → checks the served script's SHA-256 + static-scans it; prints SAFE/UNSAFE
curl -fsSL https://get.geckovision.tech/install.sh | bash # only after it says SAFE
gecko <openapi-url>
Prove it's safe before you run it.
verify_install.py(stdlib-only, readable) confirms the installer is tamper-evident (SHA-256 matches the value published in this repo), no-blind-execute (the only pipe-to-shell is the officialuvinstaller; everything else pins a versioned GitHub release), and pattern-clean (no eval, no credential reads, no exfil). Prefer theuvxline and there's nothing to verify at all.
gecko <url> prints the comprehension summary, the MCP URL, and a one-click add for
each host — a Cursor or VS Code deeplink to click, or the raw MCP URL to point
any framework at. Building your own app? Skip the server and embed the SDK (below).
Claude Code → the Marketplace; everything else → the CLI. You don't need both.
Or embed the SDK in your own app:
from gecko import AgentApiClient, public_session
client = AgentApiClient(spec, session=public_session())
hit = client.search("what you want")[0] # intent → right endpoint
client.call(hit["name"], {...}, mode="recorded") # correct call; "live" for real data
A complete forkable example: examples/_starter/ — an app on
any API in ~20 lines, runnable at $0. For a full agent (Telegram + an LLM tool-loop),
see examples/sos_vzla_bot/.
Fetch surfaces from the registry
Surfaces can be served straight from the Gecko registry — fixes propagate as rev bumps, no package upgrade:
gecko serve --registry colosseum --auth-env COLOSSEUM_COPILOT_PAT
Free surfaces need no account. Premium surfaces take a Gecko key
(GECKO_API_KEY), issued agent-natively: POST /registry/keys {email} →
email OTP → POST /registry/keys/verify → gk_live_... (shown once; we
store only a salted hash). Your PROVIDER key never travels to Gecko — the
runner injects it locally and calls the provider directly.
Develop / falsify offline ($0, no keys, no subscription)
git clone https://github.com/GeckoVision/gecko-surf
cd gecko-surf && uv sync
uv run pytest # 442 passing
uv run python -m gecko.demo # E2E: goal → discover → correct call → data (recorded, $0)
The recorded demo runs the same code path as live — it just synthesizes responses from the schema instead of hitting the network. That's the point: you can falsify the comprehension offline before spending a cent.
Going live (real World Cup data)
Recorded mode needs no subscription. For live data, do the one-time on-chain subscribe
— see scripts/SUBSCRIBE.md — then pass a real Session:
from gecko.client import AgentApiClient
client = AgentApiClient(spec, base_url="https://...", session=my_session)
client.call(tool, args, mode="live") # same path as recorded
Mainnet boundary: the subscribe transaction is founder-run only. The tooling simulates (no spend) and hands over the exact command; a human broadcasts.
What's in this repo
| Path | Purpose |
|---|---|
gecko/ingest.py |
OpenAPI 3.x → normalized Operation/Param ($ref resolution, 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 + JSONL outcome log (moat seed) |
gecko/demo.py |
run() (recorded) + live_demo() |
gecko/serve.py |
gecko <url> CLI — comprehend + serve over Streamable-HTTP MCP (+ one-click add) |
examples/_starter/ |
forkable "app on any API" (engine-only, $0); examples/sos_vzla_bot/ is the full LLM agent |
scripts/subscribe.py |
one-time on-chain subscribe (solders); simulate by default |
docs/ · private/ |
strategy & PRD · gitignored business docs (canvas, pitch, numbers) |
Rule: the comprehension logic is the product and lives in gecko/. The MCP
server, the client, and scripts are thin transport.
Stack
| Layer | Tool |
|---|---|
| Language | Python 3.11+, managed with uv |
| Engine | stdlib-first (urllib); minimal deps; pyyaml for spec loading |
| Agent surface | mcp (Model Context Protocol) |
| Access / payments | x402; on-chain subscribe via solders; modes stub / live |
| Quality | ruff · mypy · pytest (442 tests) |
Environment variables
Source of truth: .env.example.
| Variable | Required | Default | Notes |
|---|---|---|---|
X402_MODE |
no | stub |
stub / live. Stub is intentional during user-testing — do not flip to live without founder go-ahead. |
TXODDS_* / session file |
for live only | — | live World Cup access after the on-chain subscribe (see scripts/SUBSCRIBE.md) |
Recorded mode and the test suite need no keys.
Development
uv run ruff format && uv run ruff check --fix
uv run mypy gecko
uv run pytest # targeted invocations preferred
uv run python -m gecko.demo # $0 recorded smoke
See CLAUDE.md for the architecture invariants, the subagent team, and
conventions.
Team
- Ernani (@ernanibritto) — Technical co-founder. Builds the Gecko engine end-to-end: ingest, comprehension, the access layer, and the MCP surface.
- Leticia (@0xLeti) — Co-founder, Product Designer. 8+ years designing for enterprises and startups; ex-Liga Ventures.
License
Apache License 2.0 — see LICENSE and NOTICE. Apache-2.0 carries
an explicit patent grant. The engine is open (the distribution funnel); the correctness corpus
and hosted layer stay private (open-core).
The comprehension layer for the agentic economy.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gecko_surf-0.4.1.tar.gz.
File metadata
- Download URL: gecko_surf-0.4.1.tar.gz
- Upload date:
- Size: 3.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b365ddbef58a806a93ad909a25132887ad93d8032d4495e672a82de81c05016d
|
|
| MD5 |
d35e620adfa184f08defdfe2584f76a4
|
|
| BLAKE2b-256 |
b6a0930f5eb22846482876ac2044e8fda8e06fb885685e782c0b0fbef70b4f3a
|
Provenance
The following attestation bundles were made for gecko_surf-0.4.1.tar.gz:
Publisher:
release.yaml on GeckoVision/gecko-surf
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gecko_surf-0.4.1.tar.gz -
Subject digest:
b365ddbef58a806a93ad909a25132887ad93d8032d4495e672a82de81c05016d - Sigstore transparency entry: 2165569734
- Sigstore integration time:
-
Permalink:
GeckoVision/gecko-surf@ca861238f4c2d3bc3579843d662ca5fa58590a64 -
Branch / Tag:
refs/tags/v0.4.1 - Owner: https://github.com/GeckoVision
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@ca861238f4c2d3bc3579843d662ca5fa58590a64 -
Trigger Event:
push
-
Statement type:
File details
Details for the file gecko_surf-0.4.1-py3-none-any.whl.
File metadata
- Download URL: gecko_surf-0.4.1-py3-none-any.whl
- Upload date:
- Size: 322.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f745cafe5941f300021f25837b8a185453b60c6ab23a67a955303b5fe1453781
|
|
| MD5 |
93e5469114f60bde81c4f76198adb2d6
|
|
| BLAKE2b-256 |
f48adecb17c142b4a130fd62dc3d97634eb9124a6e0e99ec1d830832f6b28d3b
|
Provenance
The following attestation bundles were made for gecko_surf-0.4.1-py3-none-any.whl:
Publisher:
release.yaml on GeckoVision/gecko-surf
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gecko_surf-0.4.1-py3-none-any.whl -
Subject digest:
f745cafe5941f300021f25837b8a185453b60c6ab23a67a955303b5fe1453781 - Sigstore transparency entry: 2165569736
- Sigstore integration time:
-
Permalink:
GeckoVision/gecko-surf@ca861238f4c2d3bc3579843d662ca5fa58590a64 -
Branch / Tag:
refs/tags/v0.4.1 - Owner: https://github.com/GeckoVision
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@ca861238f4c2d3bc3579843d662ca5fa58590a64 -
Trigger Event:
push
-
Statement type: