Docs
From connect to a verified result — the same correct bytes every run, with a manifest you can re-run.
Connect an agent — MCP
Pinakes is an MCP server first. Point your client at the hosted server — nothing to install,
and no key for public catalog reads. Add your pk_live_ key only to raise limits. The agent
then calls a typed tool (catalog, search, get, resolve, export, verify), not a portal.
Fastest — one installer
Install the pinakes CLI (below), then let it write each client’s
config into the correct file for you. It detects Claude Code, Cursor, VS Code, Windsurf, Zed, and Codex:
Target one with pinakes mcp install --client cursor. Run pinakes login
(or export PINAKES_API_KEY) first to bind your key; skip it to stay on public reads.
Or configure one client
Prefer to wire it yourself? Pick your client — each reads MCP servers from its own file:
Writes the hosted server straight into Claude Code’s config — no CLI, no key for public reads.
Add to ~/.cursor/mcp.json (or a project .cursor/mcp.json); same shape for Windsurf and Zed. The ${env:…} ref resolves at runtime — drop the headers block for key-less reads.
.vscode/mcp.json uses a top-level servers map and an inputs prompt; VS Code asks for the key once and stores it in its secret store.
Writes to ~/.codex/config.toml. The flag stores the env var’s name, read at runtime, so the key never lands in the file.
Run the CLI itself as a stdio server instead of the hosted URL. The key passes through the process env; the :? form errors loudly if it’s unset rather than passing an empty one.
Keys, headless & troubleshooting
- Public reads need no key. Add one only for higher limits — via
pinakes login, the named env var, or the runtime-resolved${PINAKES_API_KEY}ref. Never commit a raw key; keep it in your environment or OS keychain. - Empty-bearer footgun.
--header "Authorization: Bearer $PINAKES_API_KEY"expands at paste time — if the variable is unset the shell sendsBearer(empty), the add succeeds, and it only 401s later. Use the runtime-resolved forms above; they fail loudly when the key is missing. - A stale header blocks key-less reads. An invalid
Authorizationheader is rejected rather than falling back to public access — remove theheadersblock to read without a key. - Headless / CI. Set
PINAKES_API_KEYin the job environment and use a runtime-resolved form. A key pasted into a literal--headerpersists in shell history and on-disk config, so use a disposable token in pipelines.
Pre-launch: mcp.pinakes.sh and the published pinakes packages go live at launch — the commands above are the real, final shapes.
CLI, MCP & REST — which do I use?
One deterministic engine, three surfaces — all produce identical, verifiable manifests; the difference is purely how you reach it.
Point an agent or IDE (Claude Code, Cursor, VS Code, Codex, Windsurf, Zed) at mcp.pinakes.sh/mcp and it calls the typed tools live while reasoning — “fetch this protein and its AlphaFold model while I work.” Nothing to install; public reads need no key. Reach for it when the consumer is an agent retrieving data inside a task loop.
The pinakes binary for your shell, CI/CD, and notebooks — it writes files plus a re-runnable manifest to disk, and doubles as a local stdio MCP server (pinakes mcp). Reach for it when you’re automating, or want artifacts you can verify() and cite later.
Plain HTTP access to the same engine from any language or runtime, with no native client. Reach for it when you’re embedding Pinakes into a service or web backend.
Mix them freely — pin a snapshot with the CLI in CI, then let an agent query that same snapshot over MCP — and every result carries a manifest verify() can re-derive byte-for-byte.
Install the CLI
One line installs the pinakes CLI and puts it on your path — for shell use and the local MCP server.
Also pip install pinakes · brew install pinakes · conda. Pre-launch: packages and the installer publish at launch — see GitHub for current availability.
Authenticate
Sign in and create a key on the dashboard at /app/, then export it as an environment variable; the published CLI and the hosted MCP server use it to raise your limits. The public catalog needs no key.
Your first query
Export every Zaire ebolavirus sequence, pinned to a snapshot — complete-or-fails-loudly, and it writes a manifest you can re-run.
Verify it
Re-run the manifest to reproduce the result from scratch.
reproducible: true proves the result is complete and byte-identical: every record was reproduced (106/106, never a silent truncation) and the content hash matches the original. The @ prefix tells the CLI to read the manifest from a file. Anyone with the manifest gets the same answer.
Core concepts
snapshot
latest) is what makes a result reproducible: the same query against the same pinned snapshot plus pinned connector code yields a byte-identical normalized record set. A result served from latest is explicitly reproducible:false because live sources reorder and mutate.manifest
logical_record_hash. It is the citable, machine-readable receipt that verify() consumes; the Go Manifest type and its JSON Schema are frozen as a pair.resolve (the metered unit)
get, search, or export operation. Resolves are the billing unit across tiers (e.g. 50k/mo on Free, 4M/mo on Pro). Asset downloads (structures, AlphaFold models, figures) are not resolves; they count separately against a per-tier GB allowance. (Distinct from the resolve verb, which maps an identifier across namespaces via the identifier graph.)verify()
verify() re-derives the result against the pinned content-addressed snapshot plus the vendored pinned connector code and confirms the logical_record_hash matches. It runs the vendored serializer version a manifest was created with, so old manifests keep verifying even after the serializer evolves.completeness (complete-or-fail-loudly)
complete:true only after reconciling the delivered record count against the source’s authoritative count; if it cannot reconcile, it is downgraded to best_effort with an explicit reason, or it fails — never a quiet partial answer. This is the guarantee that prevents the famous failure where a silent truncation once dated an Ebola outbreak’s origin anywhere from 1922 to 2014.the catalog
the identifier graph
Ambiguity; its version is pinned into the manifest.L1 Proxied / reachable
reproducible:false. This is the honest floor: a reachable source must never wear the word ‘deterministic’.L2 Normalized / verified
latest is not. The accuracy SLO applies.L3 Materialized / full determinism
Command reference
List/inspect integrated sources from the public, key-free index — including each source's maturity level and license posture.
Run a filtered, complete-or-fail query against a source; pin --snapshot-version for a reproducible result. Counts as one resolve.
Deterministically retrieve specific records by identifier. Pin to a snapshot for byte-identical results.
Map identifiers across namespaces via the versioned identifier graph; conflicts surface as explicit ambiguities, not silent picks.
Write a query result to disk as files plus a re-runnable manifest (e.g. for pipelines, notebooks, or a citable dataset).
Re-derive a result from its manifest against the pinned snapshot and confirm the logical-record hash matches.
Published CLI (at launch): authenticate with a pk_live_ key to raise limits. Public catalog reads need no key.
Wire Pinakes into an agent/IDE — connect the hosted MCP server, or run the CLI as a local stdio MCP server.
Examples — pin --snapshot-version for a reproducible result; repeat --ids per id; filters are field:operator:value; @ reads a file:
login and mcp install ship with the published CLI at launch; the engine verbs above run today against the local binary.
Use cases
Connects to the hosted MCP server and retrieves a protein record, its AlphaFold model, and ClinVar variants live while reasoning — never getting IP-banned, never silently truncated, with a manifest it can hand back for verification.
Uses the CLI in a notebook or script to pull a dataset pinned to a specific snapshot, writing files plus a manifest to disk so the exact same records can be re-derived and verified months later.
Exports the figures' underlying data against a pinned L3 snapshot and cites the manifest as a re-runnable provenance record, so any reviewer can run verify() and confirm the bytes match what the paper reports.
Adds a CLI verify() step to the pipeline that re-derives a manifest and fails the build loudly if the result hash drifts or a source returns an incomplete (non-reconciled) record set — catching silent truncation before it reaches production.
Uses the resolve verb over the versioned identifier graph to map identifiers across namespaces (Ensembl gene → UniProt accession → PDB structure) deterministically, with conflicting mappings surfaced as explicit ambiguities rather than a silently chosen winner.
Calls the REST API from any language to embed deterministic, snapshot-pinned retrieval into a web backend, getting the same verifiable manifests the CLI and MCP produce without installing a binary.
Queries the arXiv literature domain (full-corpus, rehosted) for citable paper records through the same typed tools — and qualifying labs claim a free research upgrade by email to raise resolve limits.
The authoritative CLI and API reference lives in the GitHub repo.