GunSpec
AI & agents

AI & LLMs

How to hand the API to a model: drop-in packs for the coding agents, the workflow and rules they teach, a tool layer to generate, and the plain-text files a crawler or an agent reads first. Everything below is read from those packs and the spec, so what the page says is what an agent is told.

  • 5Agent packs
  • 12Rules in every pack
  • 6Recommended tools
  • 133Operations in the spec

One file per agent, derived from the same OpenAPI document and pointing the agent back to it for the full surface. Copy it in and the agent knows the base URL, the headers, the envelope, the errors, pagination, caching, webhooks, the endpoints that matter, and where in these docs to look for the rest.

  • Claude Code

    18 KB15 sections67 paths citedOpen

    Query the GunSpec.io firearms REST API. Use when a task involves fetching firearms, ammunition, calibers, manufacturers, countries, or game-balance stats from GunSpec, or building an integration against api.gunspec.io. Covers authentication, the response envelope, pagination, error handling, and the official TypeScript and Python SDKs.

    Goes in.claude/skills/gunspec-api/SKILL.md
    mkdir -p .claude/skills/gunspec-apicurl -s https://assets.gunspec.io/ai/claude-code/skills/gunspec-api/SKILL.md \  -o .claude/skills/gunspec-api/SKILL.md
  • GitHub Copilot

    12 KB13 sections22 paths citedOpen

    How to consume the GunSpec.io firearms REST API (auth, envelope, errors, pagination, SDKs).

    Goes in.github/instructions/gunspec-api.instructions.md
    mkdir -p .github/instructionscurl -s \  https://assets.gunspec.io/ai/github-copilot/instructions/gunspec-api.instructions.md \  -o .github/instructions/gunspec-api.instructions.md
  • OpenAI Codex

    13 KB14 sections22 paths citedOpen

    Guidance for consuming the GunSpec.io REST API: a firearms specification database (firearms, ammunition, calibers, manufacturers, countries, and game-balance stats). Merge this section into your project AGENTS.md (repo root) or ~/.codex/AGENTS.md for all projects.

    Goes inAGENTS.md
    curl -s https://assets.gunspec.io/ai/codex/AGENTS.md >> AGENTS.md
  • Cursor

    12 KB13 sections22 paths citedOpen

    How to consume the GunSpec.io firearms REST API (auth, envelope, errors, pagination, SDKs).

    Goes in.cursor/rules/gunspec-api.mdc
    mkdir -p .cursor/rulescurl -s https://assets.gunspec.io/ai/cursor/rules/gunspec-api.mdc \  -o .cursor/rules/gunspec-api.mdc
  • Any agent

    21 KB16 sections75 paths citedOpen

    Drop-in context that teaches an AI coding agent to consume the GunSpec.io REST API correctly. GunSpec is a firearms specification database: 9,000+ firearms with dimensions, ballistics, materials, and game-balance stats, plus ammunition, calibers, manufacturers, countries, conflicts, and aggregate statistics.

    Goes inyour system prompt or rules file
    curl -s https://assets.gunspec.io/ai/gunspec-api.md

Every pack deep-links 10 pages of these docs for detail: field-reference, errors, rate-limits, caching, endpoint-access, pagination, versioning, tools, ai, media.

The order of operations every pack and llms.txt teach, as written there. It exists because the expensive mistakes are the same ones each time: a guessed slug, a picked-for-you variant, an invented specification.

  1. 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. 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. 3

    GET /v1/firearms/{id} for the full record. GET /v1/firearms/{id}/variants for the rest of the family.

  4. 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. 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. 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. 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. 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.

The first step has its own endpoints: GET /v1/firearms/resolve Resolve a name to one firearm · POST /v1/firearms/resolve Resolve many names at once

The 12 rules at the end of the brief, verbatim. A pack that omits any of them is not one of ours.

  1. 01Read the key from the environment. Never hardcode or print it.
  2. 02Prefer the official SDK. Fall back to fetch with the X-API-Key header.
  3. 03Check success before reading data. On failure, surface error.code and request_id.
  4. 04Handle 429 with Retry-After backoff.
  5. 05When unsure about a field or endpoint, fetch https://api.gunspec.io/openapi.json. Do not guess.
  6. 06Resolve a name to an id with /firearms/search before fetching a record. Never guess a slug.
  7. 07When search returns several variants, ask the user which one. Do not pick for them.
  8. 08Never invent a missing specification. null means GunSpec does not hold it, so say so.
  9. 09Report units from the field-name suffix (...Mm, ...G, ...Mps). Never assume one.
  10. 10Treat dataConfidence as record completeness and provenance, not per-field accuracy. Cite sources for a specific figure.
  11. 11Cache what you fetch, and refresh with If-None-Match. Re-downloading a record whose version has not changed spends quota to learn nothing.
  12. 12If you keep a mirror, subscribe to webhooks rather than polling for changes, and dedupe on X-Webhook-Id.

Do not hand a model the raw API and the docs. Give it a small, named tool per job and let the workflow above drive the order. The layer the packs recommend, each mapped to the operation it calls; generate the schemas from the OpenAPI document rather than writing them by hand, so parameters and response types stay in step.

ToolCallsNote
search_firearms(query)GET /v1/firearms/search-
get_firearm(id)GET /v1/firearms/{id}-
list_variants(id)GET /v1/firearms/{id}/variants-
compare_firearms(ids)GET /v1/firearms/comparemax 5 ids
get_manufacturer(id)GET /v1/manufacturers/{id}-
get_caliber(id)GET /v1/calibers/{id}-

Anthropic tool calling

Anthropic tool calling
typescript
import Anthropic from '@anthropic-ai/sdk' const client = new Anthropic() // One tool the model can call. Generate the rest from the OpenAPI document// rather than writing them by hand, so the parameters stay in step.const tools = [{  name: 'search_firearms',  description: 'Search the GunSpec firearm database by free-text query.',  input_schema: {    type: 'object',    properties: {      q: { type: 'string', description: 'Search terms, e.g. "9mm service pistol"' },    },    required: ['q'],  },}] // The HTTP call you run when the model asks for the tool.async function searchFirearms(q) {  const res = await fetch(    `https://api.gunspec.io/v1/firearms/search?q=${encodeURIComponent(q)}`,    { headers: { 'X-API-Key': process.env.GUNSPEC_API_KEY } },  )  const { data } = await res.json()  return data // hand straight back to the model as the tool result} const message = await client.messages.create({  model: 'claude-sonnet-4-6',  max_tokens: 1024,  tools,  messages: [{ role: 'user', content: 'Compare the recoil of a Glock 17 and a SIG P320.' }],})

Inside a tool, prefer the SDKs (@buun_group/gunspec-sdk, gunspec) over raw fetch: they carry the auth, the envelope, auto-paging and retries, so the tool body is one call.

Three plain-text URLs an agent can fetch at runtime or a crawler can index, each served with open CORS. llms.txt is the index; llms-full.txt is the whole brief; the OpenAPI document is the source of truth both point at.

Sections of the index:

  1. 01Quick facts
  2. 02Response shape
  3. 03Pagination
  4. 04Versioning
  5. 05Agent workflow (read this before calling anything)
  6. 06Endpoints
  7. 07SDKs
  8. 08MCP server
  9. 09For AI agents

The contract is uniform, which keeps a prompt short and a parser small. The figures are from the spec.

  • One envelope on every JSON response across 133 operations: { success, data }, with a pagination block on lists. The few operations that return bytes or a redirect, namely the bullet diagram, raw media and model downloads and the seller click tracker, are listed on the media page.
  • One error shape with a stable code and one of 39 specific reasons, so a model can branch without reading prose. Every code and reason.
  • One header for auth (X-API-Key or Authorization: Bearer); 17 operations need none. Authentication.
  • Units live in the field names (Mps (m/s), Mm (mm), Rpm (rpm), G (g), J (J), N (N), M (m)), so a value can never be reported in the wrong unit. Field reference.
  • Every catalog record carries updatedAt, version and an ETag, so an agent can cache and refresh conditionally instead of re-reading. Caching.
  • Changes are pushed as signed webhooks, and the contract is versioned: additive changes land, breaking ones move to a new prefix.

GunSpec runs a hosted MCP server at https://mcp.gunspec.io. Point any MCP client at it with your API key to give an assistant the tool layer above, under your plan.