# GunSpec.io API Docs > Developer documentation for the GunSpec.io REST API: a firearms specification > database covering 8,500+ firearms (dimensions, ballistics, materials, game-balance > stats) plus ammunition, calibers, manufacturers, and more. This file is a > machine-readable index for AI agents and crawlers. ## Quick facts - API base URL: https://api.gunspec.io/v1 - Authentication: API key in the `X-API-Key` header, or `Authorization: Bearer `. Both are accepted everywhere and neither is being retired. Some reads (blog, changelog, shared collections) need no key. - Rate limits (per minute): Explorer 10, Builder 60, Studio 120, Enterprise 300. A 429 is `RATE_LIMITED` (the per-minute limit: wait `Retry-After`, 60 seconds, and retry), `DAILY_CAP_EXCEEDED` (the key's allowance for the day) or `MONTHLY_CAP_EXCEEDED` (the plan's allowance for the month, shared by every key on the account). For the last two nothing is served until the reset, so stop at the first one and never retry in a loop: `Retry-After` is the seconds until the reset (at most a day, or a month), and the body carries `error.resetsAt`, `error.limit` and `error.retryAfter`. The SDKs wait out a reset only when it is a few seconds away and otherwise raise at once. Only calls that were served spend the month. A free key that keeps calling after a refusal is paused (`403` with `KEY_ON_HOLD`), or at once on a paid plan. There is no `X-RateLimit-Remaining`: the edge limiter reports whether a request was allowed, not how much of the minute is left. What is left is sent on every response: the *day*, per key (`X-Daily-Limit`, `X-Daily-Remaining` and `X-Daily-Reset`, the next midnight UTC, plus `X-Daily-MCP-*` on MCP traffic), and the *month*, for the account, on a call made with a key (`X-Monthly-Limit`, `X-Monthly-Remaining` and `X-Monthly-Reset`). Each remaining figure is what is left after that call. Pace from those and stop when either reaches 0; reconcile with `GET /v1/me/usage`, which is itself a counted request, so do not poll it. - Caching: encouraged. Read `Cache-Control` off each response; every catalog record carries `updatedAt` (when it last changed) and `version` (a hash of its own fields), and every catalog response carries an `ETag`. Send it back as `If-None-Match` to get `304 Not Modified` with no body. A 304 counts toward the per-minute rate limit but not the daily allowance. Table: https://docs.gunspec.io/en/caching - Webhooks: on Studio and Enterprise, `POST /v1/me/webhooks` registers an endpoint and catalog changes are pushed to it, so a mirror needs no polling loop. Events: `firearm.created` / `.updated` / `.deleted`, the same three for `manufacturer.*` and `caliber.*`, plus `firearm.variant.updated`, `firearm.source.changed`, `firearm.confidence.changed`, and `catalog.resynced` (too many records changed at once, so re-sync rather than applying it). The delivery carries the record in the same shape the detail endpoint returns it, `version` included; a deletion carries the id alone. Dedupe on `X-Webhook-Id` (unchanged across retries) and verify `X-Webhook-Signature` before trusting the body. - Tiers gate which endpoints a key may call (Explorer < Builder < Studio < Enterprise). - OpenAPI 3 spec: https://api.gunspec.io/openapi.json - Interactive explorer (Swagger UI): https://api.gunspec.io/docs - Human docs: https://docs.gunspec.io ## Response shape Success: `{ "success": true, "data": ... }`. List endpoints add `"pagination": { page, limit, total, totalPages }`. Error: `{ "success": false, "error": { "code", "message", "request_id" } }`. Not every success is JSON: `/v1/ammunition/{id}/bullet.svg`, `/v1/firearms/{id}/media/{selector}` and `/v1/firearms/{id}/images/{imageId}` with `format=raw` (the default) and `/v1/firearms/{id}/model` return the file's bytes, and `/v1/out/{clickId}` answers a 302 redirect. Check `Content-Type` before parsing; see https://docs.gunspec.io/en/media Error codes: VALIDATION_ERROR (400), UNAUTHORIZED (401), FORBIDDEN (403), SUBSCRIPTION_REQUIRED (403), NOT_FOUND (404), RATE_LIMITED (429), INTERNAL_ERROR (500), SERVICE_UNAVAILABLE (503). SUBSCRIPTION_REQUIRED is a 403 carrying `details.requiredTier`: the caller is authenticated but their plan does not include the endpoint. Treat it as "upgrade", not "retry". Every response carries an `X-Request-Id` header. ## Pagination `page` (1-based, max 10,000) and `per_page` (max 100; a few ranking endpoints take a single `limit` instead). Stop when a page comes back with fewer than `per_page` rows, which works on every plan. `pagination.total` and `totalPages` are absent on Explorer and anonymous calls, so never drive the loop from them. Page depth is capped per plan (403 `PAGINATION_DEPTH_EXCEEDED`) and more than 10 sequential pages in 90 seconds is a 429 `PAGINATION_BURST`. The official SDKs expose `listAutoPaging` / `list_auto_paging`. Full rules and every paged endpoint: https://docs.gunspec.io/en/pagination ## Versioning Every endpoint is under `/v1`; `info.version` in the OpenAPI document says which release of that contract is live. Additive changes (new endpoints, fields, parameters, enum values, error reasons) land under `/v1` without a new prefix, so ignore what you do not recognise. A breaking change ships under a new prefix and `/v1` keeps answering for at least 12 months; the one exception is a defect corrected in place on a surface almost nobody calls, announced as a `breaking` changelog entry at least 30 days ahead. Deprecated operations carry `deprecated: true` in the spec. Policy and history: https://docs.gunspec.io/en/versioning ## Agent workflow (read this before calling anything) 1. **Resolve the name to an id first.** `GET /v1/firearms/resolve?q={what the user said}`. Pass their words through unchanged. It is built for "G19 gen 5 MOS", "AK-47", "H&K MP5". Never guess a slug: `glock-19-gen5`, `glock-g19-gen5` and `glock-19` are not interchangeable, and a guess returns 404 or a record for a different variant. This is not search: `/v1/firearms/search` ranks a page of records *about* a query and has no notion of certainty; resolve answers which record a query *is*. 2. **`status: "ambiguous"` means ask the user, not pick the first.** `firearmId` is null and `alternatives` holds the tied candidates with their names. "Glock 19" does not name a generation, and the generations differ in exactly the weights and dimensions people ask about. `status: "not_found"` is a 200, not a 404 - say we hold no such record. Any `match: "fuzzy"` candidate is a suggestion, always scores 0, and is never an answer. Read `unresolvedTokens` before replying: those are words the resolver could not place, usually a variant the catalog does not hold. `POST /v1/firearms/resolve` resolves up to 50 names in one request (Studio). 3. `GET /v1/firearms/{id}` for the full record. `GET /v1/firearms/{id}/variants` for the rest of the family. 4. **Never infer a missing specification.** `null` means GunSpec does not hold the value. Do not fill it from model knowledge, from a sibling variant, or by computing it. Say it is not in the database. 5. **Units are in the field names**: `weightEmptyG` grams, `barrelLengthMm` and `overallLengthMm` millimetres, `muzzleVelocityMps` m/s. Read the suffix and state the unit. `/v1/firearms/{id}/dimensions` gives metric and imperial. 6. **`dataConfidence` is not accuracy.** It is a 0-1 record-level score set from what was actually sourced and never raised by hand, not a per-field probability that a number is correct: 0.95 does not mean the barrel length is 95% likely to be right. 0.5 with `verifiedAt` null is seed model knowledge; treat anything below 0.7 as unverified. Use it to rank and triage; follow `sources` (or the `provenance` object on a detail record) to verify a specific figure. Bands and source order: https://docs.gunspec.io/en/field-reference#data-confidence 7. Specifications legitimately differ by production year, factory, batch and regional variant. Where a record notes disagreement between sources, surface the disagreement rather than presenting one number as settled. 8. **Cache what you fetch, and refresh conditionally.** Store the `ETag` you were given and send it back as `If-None-Match`; a record that has not changed answers 304 with no body and no charge against your daily allowance. Compare `version` (stable across plans) rather than `ETag` when reconciling mirrors held under different keys. Full agent brief (workflow, tool-layer shape, pagination and error handling): https://docs.gunspec.io/llms-full.txt ## Endpoints ### Firearms - GET /v1/firearms - list. Filters: manufacturer, caliber, category, action_type, country_of_origin (NOT "country"), status, features, has_image, has_3d_model, year_introduced_min/_max, weight_min/_max, barrel_length_min, created_after/_before; sort + order; fields. An unknown parameter is ignored, not rejected. - GET /v1/firearms/resolve?q={name} - a name as a person writes it to one id, with an honest `ambiguous` when it is several. Call this first when you start from text - POST /v1/firearms/resolve - the same for up to 50 names in one request (Studio) - GET /v1/firearms/search?q={query} - full-text search - GET /v1/firearms/compare?ids={a},{b} - side-by-side comparison - GET /v1/firearms/filter-options - all filter dropdown values in one call - GET /v1/firearms/action-types - distinct action types - GET /v1/firearms/random - a random firearm - GET /v1/firearms/{id} - full specifications - GET /v1/firearms/{id}/variants - variant models - GET /v1/firearms/{id}/images - images - GET /v1/firearms/{id}/silhouette - SVG silhouette (raw / datauri / json) - GET /v1/firearms/{id}/game-stats - 0-100 game-balance stats - GET /v1/firearms/{id}/dimensions - metric + imperial dimensions - GET /v1/firearms/{id}/similar - similar firearms - GET /v1/popular/firearms - most-viewed firearms ### Ammunition & calibers - GET /v1/ammunition - list ammunition - GET /v1/ammunition/{id} - ammunition details - GET /v1/ammunition/{id}/ballistics - ballistics curve - GET /v1/ammunition/{id}/bullet.svg - bullet illustration - GET /v1/calibers - list calibers - GET /v1/calibers/{id} - caliber details + ballistics - GET /v1/calibers/ballistics - ballistics calculator - GET /v1/calibers/{id}/ammunition - ammunition for a caliber ### Manufacturers, categories, countries, conflicts - GET /v1/manufacturers, /v1/manufacturers/{id}, /v1/manufacturers/{id}/firearms - GET /v1/categories, /v1/categories/{slug}/firearms - GET /v1/countries, /v1/countries/{code}/arsenal - GET /v1/conflicts ### Statistics & game - GET /v1/stats/summary, /v1/stats/production-status, /v1/stats/field-coverage - GET /v1/stats/calibers/popular, /v1/stats/manufacturers/prolific, /v1/stats/by-category - GET /v1/game/tier-list, /v1/game/matchups, /v1/game/role-roster, /v1/game/balance-report - GET /v1/game-stats/versions, /v1/game-stats/versions/{v}/firearms ### Attachment compatibility (what fits what) Computed from mount interfaces, never from names. Browsing the catalog is open; anything that answers "does this go on that" is Studio. - GET /v1/attachments - attachment catalog (open). `requires=` narrows by interface. `fits=` runs the compatibility engine and therefore needs Studio. - GET /v1/attachments/{id} - one attachment (open) - GET /v1/interfaces - interface standards vocabulary, e.g. `thread:1/2x28`, `mag:stanag` (open) - GET /v1/attachments/{id}/firearms - firearms an attachment fits (Studio) - GET /v1/interfaces/{id}/firearms - firearms exposing a standard, id URL-encoded (Studio) - GET /v1/firearms/{id}/attachments - attachments that fit a firearm (Studio) - GET /v1/firearms/{id}/interfaces - a firearm's mount interfaces (Studio) - GET /v1/platforms, /v1/platforms/{id} - platform families (Studio) Every fit carries `source` (the weakest evidence behind it: `curated`, `universal`, `inherited:parent`, `inherited:platform` or `inferred`) and a `confidence` capped by the weakest interface it went through. Treat `inferred` as unverified; `min_confidence` hides fits below a figure you choose, and convention rows (a thread guessed from cartridge and country) are the weakest evidence and are labelled. A caliber, bore or minimum-barrel mismatch is never bridged by an adapter. A lower tier gets 403 SUBSCRIPTION_REQUIRED, not an empty list. ### Where to buy (open) - GET /v1/attachments/{id}/offers, GET /v1/firearms/{id}/offers - sellers stocking a record. Prices are integer minor units plus an ISO 4217 code; format at render, never divide first. ### Discovery and analysis - GET /v1/firearms/by-action (open) - GET /v1/firearms/by-designer, /v1/firearms/by-feature, /v1/firearms/by-material (Builder) - GET /v1/firearms/by-conflict (Studio) - GET /v1/firearms/timeline, /v1/firearms/top, /v1/firearms/head-to-head, /v1/firearms/power-rating (Builder) - GET /v1/firearms/media (media index), /v1/firearms/{id}/media/{slot}, /v1/firearms/{id}/images/{n} - GET /v1/firearms/{id}/calculate (derived ballistics), /v1/firearms/{id}/game-profile (Builder) - GET /v1/firearms/game-meta (Builder), /v1/firearms/{id}/family-tree (Builder) - GET /v1/firearms/{id}/schematics, /v1/firearms/{id}/adoption-map (Studio) - GET /v1/firearms/{id}/media, /v1/firearms/{id}/model, /v1/firearms/{id}/users, /v1/firearms/{id}/load - GET /v1/calibers/compare, /v1/calibers/{id}/family, /v1/calibers/{id}/parent-chain (Builder) - GET /v1/manufacturers/{id}/stats, /v1/manufacturers/{id}/timeline (Builder) ### Data quality (Enterprise) - GET /v1/data/confidence - per-record confidence scores, lowest first - GET /v1/data/coverage - field coverage across the dataset - GET /v1/data/gaps/records, /v1/data/gaps/checks/{checkId} - records missing a field, records failing a check ### Data quality (public, no key): see "Data quality and verification" below - GET /v1/contract?surface={suite} - the latest run of a check suite (catalogue, integrity, plausibility, anomalies, cartridges, materials, sources, corroboration, links, manufacturers), every check with its status - GET /v1/contract/findings?surface={suite}&check={checkId} - every finding of one check, paged - GET /v1/data/tasks?check={checkId}&subject={recordId}&stage={stage}&q={search} - the review tasks a finding opened; `q` finds a task by number (`12879` or `#12879`) or by text in the record id or check id; include=research adds what a researcher is handed - GET /v1/data/tasks/{number}?include=research - one task with what the check found (`research`: the check's line for this record, the steps, the evidence, every record it covers) and, once a person accepted it, what was decided (`decision`: the value, the quotes it rests on, the reasoning) - GET /v1/data/tasks/summary - open tasks per check - GET /v1/data/outcomes, /v1/data/verifications - results a person accepted, and the fields verified against a source - GET /v1/data/gaps, /v1/data/gaps/history - catalog gaps and integrity checks, and every past run ### Site - GET /v1/notices - active site notices - GET /v1/out/{clickId} - seller click tracker; 302s to the shop. Not for clients to call directly. ### Statistics (full list) - GET /v1/stats/summary - live catalog totals; use this rather than hardcoding counts - GET /v1/stats/by-category, /v1/stats/by-era, /v1/stats/action-types, /v1/stats/materials - GET /v1/stats/feature-frequency, /v1/stats/caliber-popularity-by-era, /v1/stats/catalog-coverage - GET /v1/stats/production-status, /v1/stats/field-coverage - GET /v1/stats/adoption/by-country, /v1/stats/adoption/by-type - GET /v1/stats/calibers/popular, /v1/stats/manufacturers/prolific - GET /v1/game/stat-distribution, /v1/game-stats/versions/{version}/firearms/{id} ### Seller (Enterprise, for shops listing stock) There is no such thing as a vendor key: a shop names an ordinary Enterprise key in Profile > Seller, and that mapping is the entire vendor scope. - GET /v1/vendor/shops - the shop ids this key may act for. An integration is handed a key, never a shop id. - GET /v1/vendor/offers - what the shop holds, private stock counts and click counts included - PUT /v1/vendor/offers - upsert up to 500 rows keyed by the shop's own SKU; unknown ids come back as `unmatched` - PATCH /v1/vendor/offers/{sku} - change one listing; every field optional, absent means unchanged ### Content (public, no key) - GET /v1/blog, /v1/blog/{slug} - GET /v1/changelog, /v1/changelog/{id} - GET /v1/collections/{shareId} ### Account (API key) - GET/POST/DELETE /v1/me/favorites, GET /v1/me/favorites/ids - GET/POST /v1/me/reports, /v1/me/support - GET/POST/PUT/DELETE /v1/me/webhooks, /v1/me/webhooks/{id}, POST /v1/me/webhooks/{id}/test (HMAC-signed delivery, X-Webhook-Signature) - DELETE /v1/me/favorites/{id}; GET /v1/me/support/{id}, /v1/me/support/{id}/replies - GET /v1/me/usage ## Data quality and verification How every figure is checked, for an assistant asked "is this right?" or "how do you know?". - Nothing automated writes to the catalog. A check files a finding; a finding opens a public review task; a person corrects the record from a quoted source, and the next run confirms it. - Every figure a check or a researcher writes carries the source's own words and the page they came from; the page is read again and the quote must still be on it. A figure no source states is left out, never estimated. - A record's `provenance` names its sources, their kind (manufacturer, standards body, government, reference, down to other) and the fields verified against a source. - Before stating a figure as settled, check /v1/data/tasks?subject={recordId}: an open task means it is under review. An open task is a question, not a verdict: the checks flag generously, and a task can close with the record confirmed as it stands. Do not tell a user a figure is wrong because a task is open. - Who raised a task: the checks raise every task on their own as they read the catalogue (`kind` gap, contradiction, verify, vocabulary); only `kind: report` comes from a person, a reader's report. - How a task closed: `closer` is `team` (a person worked it, or corrected the record so the check stopped finding it), `redback` (the research agent filed a conclusion nobody has reviewed yet, so it is not accepted) or `redback_accepted` (a person accepted it). `closedReason` is `finding_gone` (the record was corrected), `worked` or `by_hand`. `status` is the outcome: `resolved` (a value was found), `unverifiable` (searched, no quotable source), `not_a_fault` (right as it stands). - Every task has a page for people: https://docs.gunspec.io/en/quality/tasks/{number}, with what changed (each field before and now, records linked), the quoted source, the reasoning and when each step happened. The whole board, searchable: https://docs.gunspec.io/en/quality/tasks. - A record's `provenance.checks.history[]` lists every check run against it. Each entry's `finding` carries `why` (the check's own line for this record: the figures it read and what the method expects of them) and `evidence` (the numbers behind it). Quote `why` when asked why a value is under review. - Where each source stands: `GET /v1/data/sources` (every cited host with its kind, rank and basis, paged), `/v1/data/sources/summary` (counts by kind and tier) and `/v1/data/sources/{host}` (one host, with the evidence for its class). The method behind each check, as Markdown (equations, the figures each model was fitted to, one record worked through, and a decision table of verdicts): - Overview: https://docs.gunspec.io/md/methods-overview.md - Cartridge mass (a round from its bullet and case): https://docs.gunspec.io/md/methods-cartridge-mass.md - Loaded weight (loaded against empty): https://docs.gunspec.io/md/methods-loaded-weight.md - Apparent density (weight against size, and against the gun's own family): https://docs.gunspec.io/md/methods-apparent-density.md - Cartridge arithmetic (energy, pressure units, sectional density, calibre, velocity): https://docs.gunspec.io/md/methods-cartridge-arithmetic.md - Physical bounds (range with no air, recoil from momentum, order and containment): https://docs.gunspec.io/md/methods-physical-bounds.md - Statistical anomalies (a robust score on logarithms against a family or a cohort of like guns, barrel against length, what a record may say to explain an unusual figure): https://docs.gunspec.io/md/methods-statistical-anomalies.md - Trajectory (how `/v1/ammunition/{id}/ballistics` and a firearm's load curve are solved: point-mass RK4 through G1/G7 drag tables in the ICAO standard atmosphere, the barrel-length velocity correction, and zeroing, so `pathCm` is the drop from the line of sight and `dropCm` from the bore): https://docs.gunspec.io/md/methods-trajectory.md - Ballistic figures (effective range and its three thresholds, energy, momentum, Taylor KO, sectional density, Hatcher stopping power, energy density, and the fallbacks used when a load record lacks a diameter, a ballistic coefficient or a retention exponent): https://docs.gunspec.io/md/methods-ballistic-figures.md - Similar firearms (the weighted score behind `/v1/firearms/{id}/similar`, every weight and band): https://docs.gunspec.io/md/methods-similarity.md - Name matching (the resolver's score, when a name resolves, is ambiguous or is not found, and the order of search results): https://docs.gunspec.io/md/methods-name-matching.md - Fitment engine (how a part is judged to fit a gun: a person's verdict first, the caliber gate, mounting groups and placement, one adapter at most, confidence as the weakest interface used): https://docs.gunspec.io/md/methods-fitment.md - Comparisons (the spread of each figure across compared records, and the head-to-head's winner per figure with its editorial direction): https://docs.gunspec.io/md/methods-compare.md - Check thresholds (every threshold the plausibility, integrity, Wikidata, corroboration and link checks judge by): https://docs.gunspec.io/md/methods-check-rules.md - Material densities and compositions, each quoted: https://docs.gunspec.io/md/methods-materials.md - Sources and quotes (the source hierarchy, following a reference work to its citations, the quote rule): https://docs.gunspec.io/md/methods-sources.md - References (every page a method takes a figure from): https://docs.gunspec.io/md/methods-references.md - Source registry (every site the catalog cites, its kind, the basis for it, and how many records cite it): https://docs.gunspec.io/en/methods/source-registry, as JSON at https://docs.gunspec.io/data/source-registry.json Redback, the research agent that works the review queue, as Markdown. It reads makers' own pages, spec sheets and manuals (PDFs are read as documents, their tables rebuilt from where each word sits so a figure keeps its label; a scanned PDF is reported, never guessed from), quotes the exact words, has the quote re-checked in code against the page, and changes nothing until a person accepts it: - The pipeline (a task from claim to filing): https://docs.gunspec.io/md/methods-redback-pipeline.md - Evidence (what a figure must rest on): https://docs.gunspec.io/md/methods-redback-evidence.md - Models and tools, including reading a page and reading a PDF: https://docs.gunspec.io/md/methods-redback-tools.md - What it learns between tasks: https://docs.gunspec.io/md/methods-redback-learning.md - How it is measured: https://docs.gunspec.io/md/methods-redback-measurement.md - One task end to end: https://docs.gunspec.io/md/methods-redback-end-to-end.md Why the data quality work is public, how it is done and what a subscription pays for: https://docs.gunspec.io/md/quality-faq.md Telling us a figure is wrong (POST /v1/me/reports), and the path a report takes from filed to corrected: https://docs.gunspec.io/md/quality-reports.md What each check suite asks, with its latest results: https://docs.gunspec.io/md/quality-overview.md, and one page per suite (quality-catalogue, quality-integrity, quality-plausibility, quality-anomalies, quality-cartridges, quality-materials, quality-sources, quality-corroboration, quality-links, quality-manufacturer-checks) under https://docs.gunspec.io/md/. Live totals, one table per group (HTML, read from the public endpoints above): - Database: every catalog's records, fields filled, checks holding and failing, records flagged and review tasks open: https://docs.gunspec.io/en/quality/database-index - Records and sources: every suite's checks holding, failing and skipped, its findings and the methods it rests on: https://docs.gunspec.io/en/quality/records-index - Systems: the fitment, API and MCP runs with tests passed, failed and skipped, and the review queue by state: https://docs.gunspec.io/en/quality/systems-index - Completed work: every closed review task, newest first, with its outcome and who closed it (Redback, Redback accepted by the team, or the team), and totals for 7 days, 30 days and all time (GET /v1/data/tasks?state=closed): https://docs.gunspec.io/en/quality/completed A verdict is pass, fail or skip. A skip is a question the run could not ask (no key for a plan, a record not held yet, a source that refused an automated reader); it is neither a pass nor a failure. Through the MCP server, `gunspec_search_docs` and `gunspec_read_docs` search and read all of these pages; search for a method by name ("trajectory", "apparent density") or by the figure it judges. ## SDKs - TypeScript / Node: `npm install @buun_group/gunspec-sdk` - https://www.npmjs.com/package/@buun_group/gunspec-sdk - Python: `pip install gunspec` - https://pypi.org/project/gunspec/ ## MCP server - Hosted, read-only MCP server: https://mcp.gunspec.io (Streamable HTTP). Send the API key in `X-API-Key`. - Listed in the official MCP Registry as `io.gunspec/mcp`: https://registry.modelcontextprotocol.io/v0/servers/io.gunspec%2Fmcp/versions - Install guide an assistant can follow: https://docs.gunspec.io/mcp/install.md - Agent Skill for using the tools: https://docs.gunspec.io/mcp/SKILL.md - Every tool and its arguments: https://docs.gunspec.io/mcp/tools.md - The same as JSON, with each tool's example arguments and its JSON Schema exactly as `tools/list` sends it: https://docs.gunspec.io/mcp/tools.json - Tool calls count against the plan's daily requests and a lower daily MCP allowance: https://docs.gunspec.io/en/mcp/limits ## For AI agents - Generate tools from the OpenAPI spec (https://api.gunspec.io/openapi.json) for function/tool calling. - The uniform envelope and stable error codes make responses easy to parse. - Ready-made coding-agent packs (Claude Code, GitHub Copilot, Codex, Cursor): https://assets.gunspec.io/ai/ - More: https://docs.gunspec.io (see the AI & LLMs page).