Frequently asked questions

What Pinakes is, when to use the CLI vs MCP vs REST, what makes it deterministic, and how keys, licensing, and pricing work.

Basics

What is Pinakes?
Pinakes is a deterministic, verifiable data layer for AI agents. It sits over the world's major biological databases (the beachhead) and a second literature domain (arXiv), and exposes one engine through three surfaces: a CLI (pinakes), a hosted MCP server at https://mcp.pinakes.sh/mcp, and a REST API. The core promise is that the same query returns byte-identical records every time, retrieval is complete-or-fails-loudly, and every result ships a re-runnable provenance manifest that verify() can prove.
Why not just call NCBI, EBI, or UniProt directly?
The underlying data is mostly free at the source, but those APIs are rate-limited, messy, and non-reproducible: identical queries can return different counts on different days, IPs get banned under load, and there is no provenance record you can re-run. Pinakes doesn't sell the bytes; it sells the guarantee — determinism, completeness, a provenance manifest, never-IP-banned access (the Governor), and one interface across many sources. You point an agent at one typed tool instead of hand-rolling a dozen brittle clients.
What does "deterministic and verifiable" actually mean here?
Deterministic means a query pinned to a content-addressed snapshot produces the exact same normalized logical records — and therefore the same SHA-256 logical-record hash — on every run and platform. Verifiable means each result carries a manifest, and verify() re-derives the result from the pinned snapshot plus the pinned connector code and confirms the hash matches. If anything has drifted, verify refuses loudly rather than returning a different answer silently.
What's the famous failure Pinakes is built to prevent?
A silent truncation: identical Ebolavirus queries once returned 106, 15, and 5 sequences on different runs, which pushed an estimate of the outbreak's origin anywhere from 1922 to April 2014 (the correct answer was January 2014). The data layer beneath an agent has to be boringly reliable — a quietly incomplete result is worse than an error. Pinakes's complete-or-fail rule and count reconciliation exist precisely to make that class of bug impossible to hide.
Is Pinakes a website I log into to browse data?
No. Pinakes is headless: there is no human web data-browser to click through and nothing to scrape. An agent (or your script) calls a typed tool — catalog, search, get, resolve, export, or verify — and gets back normalized records plus a manifest. There is a public catalog/docs plane for discovery, but the product itself is an API for machines, not a portal for humans.

CLI vs MCP vs REST

What is the hosted MCP server and when should I use it?
The hosted MCP server at https://mcp.pinakes.sh/mcp lets your AI agent or IDE — Claude Code, Cursor, VS Code, Codex, Claude Desktop, Windsurf, Zed — call Pinakes's typed tools live, mid-task. It is best for interactive agent work: "fetch me this protein while I reason about it." Nothing is installed; you point the client at the URL and the tools appear.
What is the CLI and when should I use it?
The pinakes CLI is a single binary for your shell, scripts, CI/CD, and reproducible data pulls. It writes files plus a manifest to disk, so it is best for automation, pipelines, notebooks, and capturing a result you can verify() and cite later. The CLI can also run as a local stdio MCP server via pinakes mcp, exposing the same typed tools to a local agent without the hosted endpoint.
What is the REST API for?
The REST API is programmatic access to the same engine from any language or runtime. It exposes the same typed verbs over HTTP (for example POST /v1/search, POST /v1/get, POST /v1/export, POST /v1/verify), so a backend service, a worker, or a non-MCP client can drive Pinakes directly. Use it when you want HTTP integration rather than an agent tool or a shell binary.
What's the real difference between the three?
They are three surfaces over one engine, so they produce identical, verifiable manifests — the choice is about where the work happens. Use MCP when an agent should retrieve data during a task; use the CLI when you're scripting, automating, or want files plus manifests on disk; use REST for programmatic HTTP access from any language. The typed tool set and the determinism guarantees are the same across all three.
Can I use more than one at once?
Yes. A common pattern is an agent using hosted MCP to fetch data interactively, then the CLI in CI to re-pull that data reproducibly and verify() it. Because every surface shares the same engine, a manifest captured via MCP can be verified by the CLI or REST, and vice versa. There is no lock-in between surfaces.
Do I need to install anything?
For the hosted MCP server, no — point your agent or IDE at https://mcp.pinakes.sh/mcp and you're done. For the CLI you install the pinakes binary (it's a single signed static binary, also packaged on PyPI and npm as pinakes). For REST you need nothing but an HTTP client.

Use cases

How does Pinakes help me build agents?
Agents need a data layer that is boringly reliable so the model's creativity sits on solid ground. With hosted MCP, your agent calls typed tools (catalog, search, get, resolve, export, verify) mid-reasoning and gets normalized records plus a manifest instead of raw, inconsistent API responses. The Governor means the agent never gets IP-banned under load, and complete-or-fail means it never silently reasons over a truncated result.
Can I build reproducible pipelines with it?
Yes — this is the CLI's sweet spot. A pipeline pins each pull to a content-addressed snapshot, writes the records plus a manifest to disk, and can re-run later to byte-identical output. Because the manifest pins the snapshot version, the connector spec version, and the serializer codec, the same pipeline produces the same logical-record hash months later, on any machine.
How do I make a citable dataset snapshot for a paper?
Run your query pinned to a specific snapshot version (not latest) so the result is reproducible, then keep the exported files and the manifest alongside your paper. The manifest records the exact snapshot, sources, license/attribution, and logical-record hash, so reviewers and readers can run verify() to confirm the dataset is exactly what you reported. That turns a normally non-reproducible database pull into a fixed, checkable artifact.
Can I validate data in CI?
Yes. Check a manifest into your repo and run pinakes verify in CI; it re-derives the result from the pinned snapshot and the vendored pinned connector code and fails the build if the hash no longer matches or any provenance field has drifted. This catches a changed upstream, a moved snapshot, or an accidental query change before it reaches production, and is a natural CI step because the CLI is a single static binary.
Can it resolve identifiers across sources?
Yes. Cross-identifier resolution maps an ID in one namespace to another (for example a UniProt accession to an Ensembl gene). The identifier graph is versioned and snapshot-aware — edges carry source, source-version, confidence, and a validity window — and conflicting many-to-many mappings are surfaced in the manifest rather than silently collapsed, with a documented authority policy deciding the default when sources disagree.

Determinism & verify()

What is a snapshot?
A snapshot is a content-addressed, point-in-time materialization of a source's data that Pinakes pins a query against. Reproducibility is snapshot-pinned, never query-pinned: a query tied to a concrete snapshot version reproduces exactly, while a query against latest does not (it can change as the upstream changes). Querying a snapshot also bypasses the upstream rate ceiling entirely, which is why it is the core scaling mechanism, not just a reproducibility feature.
What is a manifest?
A manifest is the re-runnable provenance record that ships with every result. It records the engine version, the connector spec version, the serializer codec, the normalized query, per-source provenance (snapshot version, maturity, license/attribution), the completeness verdict, the served_from freshness stamp, and the logical_record_hash. It is the exact input verify() executes against, and it is frozen as a JSON Schema paired with the engine's Manifest type.
What does "complete or fail" mean?
The engine never claims complete without reconciling the records it actually retrieved against the source's authoritative count. If those match, the completeness state is complete; if they can't be reconciled, the result is downgraded to best_effort or partial with a mandatory reason (and a resume cursor for a partial), never a silent truncation. This is the rule that would have flagged the Ebola 106/15/5 discrepancy instead of hiding it.
How does verify() work?
verify() takes a manifest and re-derives the result by re-running the exact vendored, pinned connector code against the content-addressed snapshot named in the manifest, recomputing the canonical NDJSON logical-record set and its SHA-256 hash. If the hash and every provenance field match, it confirms; if anything drifted — the hash, the snapshot, the filter logic, the serializer, the schema, the license — it refuses with a specific drift error rather than returning a different answer. The hash is computed over the normalized logical records, never over the Parquet or other export bytes, which are derived artifacts.
How does the Ebola completeness story connect to all this?
The Ebola case is the canonical failure Pinakes prevents: a silent truncation that turned one question into wildly different answers (origin estimates from 1922 to 2014 for an outbreak that began in January 2014). Pinakes's count-reconciled complete-or-fail rule means an incomplete pull is labeled best_effort or partial with a reason, and the snapshot-pinned manifest plus verify() let anyone reproduce the exact result. The same query yields the same records, provably.

Access, keys & limits

Do I need an API key to use Pinakes?
Public catalog reads need no key — you can discover sources and how to query them with nothing installed and nothing signed up. You add a pk_live_ key (or run pinakes login) only to raise your limits beyond the free tier. The hosted MCP server needs nothing installed to start using it.
What is a "resolve"?
A resolve is the metered unit: one deterministic record retrieval — a get, a search, or an export. Your tier allowance is expressed in resolves per month (for example 50k/mo on Free, 4M on Pro). It is the count of record-retrieval operations, not bytes or compute. (Not to be confused with the resolve verb, which maps an identifier across namespaces via the identifier graph.)
What counts against my limits?
Two things are metered separately. Resolves (get/search/export) count against your monthly resolve allowance, while asset downloads — structures, AlphaFold models, figures — count against a per-tier GB allowance. Public catalog reads are free and don't consume either.
What are the rate limits?
Each tier has a requests-per-second ceiling alongside its monthly resolve allowance: Free is 5 rps, Starter 10, Developer 25, and Pro 50. The rps cap is your downstream throughput limit; the resolve count is the monthly volume limit. Both rise as you move up the ladder.
How is the key handled — is it ever exposed?
Machine auth is the primary model: keys are prefixed pk_live_, stored hashed at rest, and validated in the API middleware. For the CLI and MCP, prefer short-lived tokens or the login flow and OS-keychain references over a static key sitting in a config file, and Pinakes redacts secrets in output. The environment variable is PINAKES_API_KEY.

Data & licensing

Where does the data come from?
From the world's major public biological databases plus arXiv literature. The first build wave covers NCBI Virus, NCBI E-utilities, PDB, AlphaFold, Ensembl, UniProt, PubChem, ClinVar, ChEMBL, and gnomAD; arXiv ships last as the literature domain. Pinakes normalizes, snapshots, and serves this data with a determinism and completeness guarantee — the bytes are mostly free at the source, but the trustworthy access is what Pinakes provides.
Can I redistribute the results I get back?
It depends on the source's own license, which the manifest records per source. Most genuinely-open sources (CC0/CC-BY/public-domain like PDB, AlphaFold, UniProt, Ensembl, ClinVar) carry attribution that is embedded inside every export, so redistribution is fine with attribution. Copyleft sources (ChEMBL CC-BY-SA, gnomAD ODbL) carry share-alike obligations, and index/proxy or gated sources you generally cannot rehost — always check the per-source license and attribution in the manifest.
What does "copyleft-isolated" mean?
Copyleft-isolated applies to share-alike sources — ChEMBL (CC-BY-SA 3.0) and gnomAD (ODbL) — whose license forces any normalized derivative back under the same share-alike terms. Pinakes serves these only from an isolated namespace and never co-mingles them into the metered proprietary bundle, so the share-alike obligation can't contaminate other data. The engine enforces this: a copyleft license cannot be given a rehost-and-serve posture.
What does "index/proxy-only" mean?
Index/proxy-only sources are not rehosted on Pinakes storage; instead Pinakes indexes the metadata and streams or redirects the raw bytes from the source. This covers the submitter-IP-encumbered NCBI archives — NCBI E-utilities, SRA, GEO, and NCBI Virus — where the bytes are already free at AWS/GCP and per-record submitter IP can attach. You get the resolved object list plus manifest, not a re-hosted copy of the petabytes.
What does "gated / controlled-access" mean?
Gated sources (TCGA controlled, dbGaP) hold controlled-access human data under data-use agreements. They never transit Pinakes's multi-tenant infrastructure and never appear in cache, logs, or manifests — access is a pass-through inside the customer's own approved cloud boundary, under the customer's own authorization. This is a hard engine rule, not a policy you can opt out of.
Why are some sources marked "coming soon" and not available yet?
Pinakes is being built to its full final state across all primary databases, but sources go live in waves so quality is proven before fan-out — the first wave is roughly ten sources across data types. Everything beyond that wave is marked planned (coming soon) until its connector and license posture are verified. A few sources are deliberately excluded or redirect-only because their licenses prohibit rehosting (for example COSMIC, the CC-BY-NC DrugBank knowledgebase, and KEGG).

Pricing & billing

What do the tiers cost?
The self-serve ladder is Free $0 (50k resolves/mo, 5 rps), Starter $10 (500k, 10 rps), Developer $29 (2M, 25 rps), and Pro $49 (4M, 50 rps). Bigger needs — private snapshots, SSO, SOC 2 / HIPAA, controlled-access sources, or on-prem — are available; email us. You pay for the service guarantee (reliability, snapshots, higher limits, compliance), not for the data.
How does overage work?
If you exceed your monthly resolve allowance, overage is billed at roughly $0.40–0.50 per 1,000 resolves. You get usage alerts at 85% and 100% of your allowance so there are no surprises. The unit is the resolve (a get/search/export), the same unit your tier allowance is measured in.
Can I cap my spend so I'm never surprised by a bill?
Yes — a hard cap is available, so you can stop usage at your limit rather than accrue unbounded overage. Combined with the 85% and 100% alerts, that gives you both a warning and a firm ceiling. Pick the cap if predictable cost matters more than uninterrupted overflow.
Is there an academic discount?
Yes. Academic labs can get a free research upgrade by email. Pinakes treats academic research as a first-class use case, so reach out rather than paying a standard tier if you qualify.

Troubleshooting

I'm getting a 401 with an empty bearer token — what's wrong?
An empty or malformed bearer token is treated as an authentication failure, not as an anonymous request, so it returns 401. If you meant to make a public catalog read, send no Authorization header at all — public reads need no key, and an empty bearer is rejected rather than silently downgraded. If you meant to authenticate, supply a valid pk_live_ key (or set PINAKES_API_KEY / run pinakes login).
Why is a stale or leftover auth header blocking my public reads?
If a client is sending an old, revoked, or malformed Authorization header, the request is authenticated as that (bad) credential and rejected, instead of falling through to the keyless public path. Clear the stale header — drop PINAKES_API_KEY from the environment or unset the client's bearer — so a public catalog read goes out with no credential. Public reads work precisely because they carry no auth, so a broken header is worse than no header.
My result says reproducible:false — what does that mean?
reproducible:false means verify() is not promised to reproduce this result byte-for-byte, so it isn't a deterministic, citable snapshot. It is set whenever the result wasn't served from a pinned snapshot — for example a query against latest, a result that isn't complete, or one that includes an immature (L0/L1) source. To get reproducible:true, pin the query to a concrete snapshot version so it is served from a snapshot and complete with all sources mature.
verify() refused my manifest with a drift error — why?
verify() refuses when the re-derived result no longer matches the manifest, and it names what drifted — for example a hash mismatch, a moved or missing snapshot, changed filter logic, a serializer or schema change, or a license change. These come back as 422 (the request was well-formed but the engine won't attest it), distinct from a 400 for a malformed query or a 404 for an unknown source/snapshot. This is by design: a drifted manifest is surfaced loudly, never reconciled into a different answer.
Why does my served_from say cache(stale) instead of snapshot?
On the hosted service, under upstream pressure or an outage, the Governor serve layer can return cached data stamped cache(stale) rather than fail your request outright — but it is never presented silently as fresh. The local engine only ever emits live or snapshot; cache(*) is a hosted-tier behavior. Either way, a cache(stale)/cache(fresh)/live result is not deterministic; only kind: snapshot with a concrete snapshot version is reproducible. If you need a verifiable result, re-run the query pinned to a snapshot version.

Still stuck? The full reference lives on GitHub, or email us.