API & agents
Reading needs no key; responses send Access-Control-Allow-Origin: *. Agents can connect to the MCP server, call the search API, or read the static files below. Submitting goes through one small endpoint, described below.
Endpoints
| URL | What you get |
|---|---|
POST /mcp | Remote MCP server (Streamable HTTP, read-only, no auth). |
/api/v1/search | Ranked search with filters for agent, tags, category and verification. |
/feed.xml, /rss.xml | Atom and RSS feeds of new and updated loadouts. |
/sitemap.xml | Every indexable page, including agent and stack pages, with lastmod. |
/llms.txt | Short index of the site for LLMs (llms.txt format). |
/llms-full.txt | The whole catalogue as one markdown document, with every file inlined. |
/api/index.json | All loadouts with categories, stacks, compatibility, verification (Level 1) and agent test status. Also lists agents and their paths. |
/api/loadouts/<id>.json | One loadout: metadata, every file's content, install_to per agent, and an install plan per agent. |
/api/schema.json | JSON Schema for listing.yaml. |
/raw/<id>/<version>/<path> | One file as plain text. latest works in place of the version. |
/download/<id>/<agent>.zip | Files laid out at that agent's install paths. source.zip has them as stored. |
MCP server
Connect your agent to https://loadout.jnw-it.com/mcp and it can search loadouts, read files and get exact install paths without leaving the chat. It speaks MCP over Streamable HTTP (stateless JSON responses, protocol versions 2024-11-05 to 2025-11-25), is read-only and needs no sign-in.
Claude Code
terminal
claude mcp add --transport http agent-loadout https://loadout.jnw-it.com/mcp
Cursor
.cursor/mcp.json (project) or ~/.cursor/mcp.json
{
"mcpServers": {
"agent-loadout": {
"url": "https://loadout.jnw-it.com/mcp"
}
}
} Codex
~/.codex/config.toml, or run: codex mcp add agent-loadout --url https://loadout.jnw-it.com/mcp
[mcp_servers.agent-loadout] url = "https://loadout.jnw-it.com/mcp"
Gemini CLI
.gemini/settings.json or ~/.gemini/settings.json, or run: gemini mcp add --transport http agent-loadout https://loadout.jnw-it.com/mcp
{
"mcpServers": {
"agent-loadout": {
"httpUrl": "https://loadout.jnw-it.com/mcp"
}
}
} VS Code (GitHub Copilot)
.vscode/mcp.json
{
"servers": {
"agent-loadout": {
"type": "http",
"url": "https://loadout.jnw-it.com/mcp"
}
}
} Tools
| Tool | Arguments | Returns |
|---|---|---|
search_loadouts | query?, agent?, tags?[], category?, verified_only?, has?, limit? (1–20) | ranked search |
get_loadout | id | metadata, verification, agent tests and the file list with raw URLs and per-agent install paths |
get_loadout_file | id, path | raw contents of one file (≤100 KB) |
get_install_instructions | id, agent | exact target paths, raw URLs, curl commands, manual MCP steps, zip URL |
list_agents | none | each agent's instructions file, skills dir and MCP config location |
list_tags | none | tags (stacks) and categories with counts |
A typical flow: search_loadouts with the user's agent and stack → get_loadout → get_install_instructions → fetch files with get_loadout_file. The agent should still show the user what it will write and never overwrite an existing AGENTS.md or CLAUDE.md without asking.
Limits: 120 requests a minute per IP (HTTP 429 with Retry-After after that), 64 KB request bodies, files up to 100 KB. GET /mcp returns 405 because there is no server-to-client stream. A server card is served at /mcp/server-card (draft MCP server-card extension). Test it with npx @modelcontextprotocol/inspector --cli https://loadout.jnw-it.com/mcp --transport http --method tools/list.
Search API
GET https://loadout.jnw-it.com/api/v1/search. All parameters are optional; with none it lists the catalogue, featured and verified loadouts first.
| Parameter | Meaning |
|---|---|
q | Free text, up to 200 characters (12 terms). Matches titles, tags, skill names, summaries, highlights and file descriptions, weighted in that order. Every term must match; if nothing matches all of them, results matching any term come back with "match": "any". |
agent | claude-code, codex, cursor, gemini-cli, copilot. Leaves out loadouts that do not support that agent. |
tags (or stack) | Comma-separated stacks or categories, all of which must match, e.g. typescript,supabase. Up to 8. |
category | web-app, gamedev, security, bots, browser-extension, data, workflow, ai-agents |
verified | true for loadouts that passed the Level 1 automated install check, false for the rest. |
has | skills, mcp or rules. |
limit, offset | 1–50 (default 10), and 0–1000. |
curl -s 'https://loadout.jnw-it.com/api/v1/search?q=supabase+auth&agent=cursor&limit=1'
{
"query": { "q": "supabase auth", "terms": ["supabase", "auth"], "agent": "cursor", ... },
"match": "all",
"total": 2,
"count": 1,
"results": [{
"id": "nextjs-supabase-saas",
"title": "Next.js + Supabase SaaS",
"summary": "...",
"score": 7,
"matched_terms": ["supabase", "auth"],
"tags": ["nextjs", "react", "typescript", "supabase", "postgres"],
"agents": { "claude-code": "native", "codex": "adapter", "cursor": "native", ... },
"contains": { "rules": 2, "skills": 1, "mcp": 1 },
"verification": { "status": "verified", "verified": true, "checked_at": "..." },
"agent_tests": { "status": "untested", "per_agent": { ... } },
"urls": { "page": "...", "json": "...", "raw_base": "...", "source_zip": "...", "zips": { "cursor": "..." } }
}]
} Responses are cacheable for five minutes. Errors are JSON: 400 invalid_parameter (with field), 414 for URLs over 2,048 characters, 429 rate_limited after 60 searches a minute per IP. The index behind it is built with the site and published at /api/search-index.json.
Install a loadout from an agent
- Fetch
/api/loadouts/<id>.json. - Read
install.<your-agent-id>.files: each item has araw_urland atargetpath relative to the project root. - Before writing, check whether the target exists. If it does, show the user a merge rather than overwriting.
- Tell the user about any
manual_steps(usually MCP configs in another format) and anyrequires.envvalues.
curl -s https://loadout.jnw-it.com/api/loadouts/discord-bot-ts.json | jq '.install["claude-code"].files'
Agent ids and paths
| id | Instructions | Skills | MCP |
|---|---|---|---|
claude-code | CLAUDE.md (imports AGENTS.md with @AGENTS.md) | .claude/skills/<name>/ | .mcp.json |
codex | AGENTS.md | .agents/skills/<name>/ | manual step |
cursor | AGENTS.md + .cursor/rules/*.mdc | .agents/skills/<name>/ | .cursor/mcp.json |
gemini-cli | GEMINI.md (imports AGENTS.md with @./AGENTS.md) | .agents/skills/<name>/ | manual step |
copilot | AGENTS.md | .agents/skills/<name>/ | manual step |
These paths follow each tool's published conventions as of October 2026. The Level 1 verifier checks every loadout installs to exactly these paths and that the resulting layout is discovered correctly; it does not run the agents themselves, so treat them as documented and layout-checked rather than agent-tested.
Verification (Level 1)
Each loadout in /api/index.json carries a verification summary, and /api/loadouts/<id>.json adds every check:
"verification": {
"level": "verified-install",
"status": "verified", // verified | failing | incomplete | stale | none
"verified": true,
"checked_at": "2026-10-16T21:36:19Z",
"agent_tests": "not-run", // Level 1 never runs an AI agent
"checks": [{ "id": "install-paths", "status": "pass", "summary": "…", "details": ["…"] }, …]
} Checks: listing, parse, adapters, install-paths, mcp, safety, references, size, licence, starter-build. Each is pass, fail, skip (could not run) or n/a (does not apply, with the reason). stale means the files changed after the last run. Per-agent results live separately in tested.per_agent.
Submit a loadout
The submit form and agents use the same endpoint. Submissions are stored as pending, checked automatically for credentials and risky shell, then run through the Level 1 verifier and reviewed by a person before they are listed. Submitted files are never executed on intake.
| Request | What it does |
|---|---|
POST /api/v1/submissions | Submit one loadout as JSON. 201 returns id, status: "pending", the pre-check verdict and findings, and a status_url. |
GET /api/v1/submissions/<id> | Status of a submission: pending, imported, published or rejected. |
GET /api/v1/ | Machine-readable summary of the fields and limits below. |
Authentication
- Agents and scripts send
Authorization: Bearer alk_…. Keys are issued by hand while we are small; ask through the contact form on jnw-it.com. With no key, use the form. Each key has its own daily limit (20 by default). - Browsers (the form) send a Cloudflare Turnstile token and a signed form token instead, from an allowed origin, and are limited per network per hour. Cross-site browser requests are refused.
Body
| Field | Rules |
|---|---|
name | Required, 3–60 characters. |
summary | Required, 20–200 characters, one sentence. |
category | Required, one of web-app, gamedev, security, bots, browser-extension, data, workflow, ai-agents. |
stacks | Required, 1–8 lowercase-hyphenated slugs. |
agents | Required, the agents you have used it with: claude-code, codex, cursor, gemini-cli, copilot. |
files | Required, 1–30 items of { path, content }. Text only, 32 KB each, 128 KB in total, request body at most 192 KB. AGENTS.md is required. Allowed paths: AGENTS.md, CLAUDE.md, GEMINI.md, mcp.json, .cursor/rules/*.mdc, .claude/agents/*.md, skills/<skill>/SKILL.md (with name and description frontmatter) and other files under skills/<skill>/. Missing adapters and listing.yaml are generated. |
licence | Required, one of MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, MPL-2.0, CC-BY-4.0, CC0-1.0, Unlicense. license is accepted too. |
rights_confirmed | Required, must be true: you wrote the files or may share them under that licence. |
id, description, highlights | Optional. id defaults to a slug of the name. |
author, source_url, contact_email, notes | Optional. author is { name, url?, github? } and is published; contact_email is private and only used about this submission. |
curl -s -X POST https://loadout.jnw-it.com/api/v1/submissions \
-H "Authorization: Bearer $AGENT_LOADOUT_KEY" \
-H "Content-Type: application/json" \
--data @submission.json
# submission.json
{
"name": "Phaser platformer jam",
"summary": "Phaser 3 rules and a ship skill so your agent helps you finish a platformer in a weekend jam.",
"category": "gamedev",
"stacks": [
"phaser",
"javascript"
],
"agents": [
"claude-code",
"cursor"
],
"licence": "MIT",
"author": {
"name": "Your Name",
"github": "your-handle"
},
"rights_confirmed": true,
"files": [
{
"path": "AGENTS.md",
"content": "# Phaser jam rules\n- ..."
}
]
} Errors
Errors are JSON: { ok: false, error, message, issues? }. issues lists each field path and what to fix.
| Status | error | Meaning |
|---|---|---|
| 400 | invalid_json, too_fast, form_expired, turnstile_missing, turnstile_failed, rejected | Bad JSON, or a browser spam check failed. |
| 401 | invalid_api_key | Missing, unknown or revoked key. |
| 403 | origin_not_allowed | A browser request from another site, or a request with neither a key nor an allowed origin. |
| 413 | payload_too_large, file_too_large | Over the size limits above. |
| 415 | unsupported_media_type | Send Content-Type: application/json. |
| 422 | invalid_submission, secret_detected | A field needs fixing, or a file looks like it contains a real credential. Credentials are never stored; rotate the key if it was real. |
| 429 | rate_limited | Slow down; see Retry-After. |
| 503 | submissions_closed, intake_full | Not open yet, or today's intake cap is reached. |
Risky patterns such as curl … | sh to an unknown host, hidden Unicode or prompt-injection wording do not block a submission; they mark it flagged for a closer human review.
Coming next
- Per-agent test results from real runs, with dates.