{
  "schemaVersion": "2026-04",
  "name": "Kineticist",
  "description": "Pinball industry database, hype tracker, and editorial publication. 1,700+ pinball machines, 8,300+ locations, 347 hype themes, 600+ articles.",
  "url": "https://www.kineticist.com",
  "homepage": "https://www.kineticist.com",
  "capabilities": [
    "read",
    "write",
    "search",
    "content-negotiation:markdown",
    "user-library"
  ],
  "skills": [
    { "id": "search_pinball_games", "name": "Search Pinball Games", "description": "Search and filter the Kineticist pinball game database." },
    { "id": "get_game_details", "name": "Get Game Details", "description": "Get full details for a pinball game including editions, images, tags, description, and rules links." },
    { "id": "get_random_game", "name": "Get Random Game", "description": "Get a random pinball game with full details." },
    { "id": "get_pinball_stats", "name": "Get Database Stats", "description": "Get database statistics: total games, in production, manufacturers, designers." },
    { "id": "get_game_credits", "name": "Get Game Design Team", "description": "Get the design team for a pinball game — designer, artist, programmer, etc." },
    { "id": "kineticist_log_play", "name": "Log a Play", "description": "Log a play of a pinball game for the authenticated user." },
    { "id": "kineticist_toggle_ownership", "name": "Toggle Game Ownership", "description": "Mark a game as owned or no longer owned for the authenticated user." },
    { "id": "kineticist_toggle_want", "name": "Toggle Want-to-Play / Wishlist", "description": "Toggle the authenticated user's wishlist flag for a game." },
    { "id": "kineticist_set_fun_score", "name": "Set Fun Score", "description": "Set the authenticated user's fun score (1-100) for a game." },
    { "id": "kineticist_toggle_favorite", "name": "Toggle Favorite", "description": "Toggle the authenticated user's favorite flag for a game." },
    { "id": "kineticist_submit_review", "name": "Submit Review", "description": "Save the authenticated user's review (fun score + optional written body) for a game." },
    { "id": "kineticist_get_my_state", "name": "Get My Engagement State", "description": "Get the authenticated user's engagement state for a game." }
  ],
  "skillsCatalog": "https://www.kineticist.com/.well-known/agent-card.json",
  "contact": {
    "email": "colin@kineticist.com",
    "url": "https://www.kineticist.com/contact"
  },
  "documentation": {
    "human": "https://www.kineticist.com/docs/api",
    "reference": "https://www.kineticist.com/docs/api/reference",
    "openapi": "https://www.kineticist.com/openapi.json",
    "llmsTxt": "https://www.kineticist.com/llms.txt",
    "agentCard": "https://www.kineticist.com/.well-known/agent-card.json"
  },
  "contentNegotiation": {
    "markdown": {
      "accept": "text/markdown",
      "endpoint": "https://www.kineticist.com/api/markdown",
      "note": "Any URL on www.kineticist.com requested with Accept: text/markdown is rewritten to /api/markdown, which serves the curated llms.txt site overview as text/markdown."
    }
  },
  "api": {
    "baseUrl": "https://www.kineticist.com/api/v1",
    "protocol": "REST",
    "auth": {
      "type": "bearer",
      "header": "Authorization: Bearer <key>",
      "signup": "https://www.kineticist.com/settings"
    },
    "rateLimits": {
      "model": "per-key, 3 tiers, enforced as burst + per-minute + per-day",
      "tiers": [
        { "name": "free", "burst": "10/s", "perMinute": 60, "perDay": 1000 },
        { "name": "builder", "burst": "20/s", "perMinute": 120, "perDay": 5000 },
        { "name": "partner", "burst": "30/s", "perMinute": 200, "perDay": 25000 }
      ],
      "notes": "All tiers are free during early access. New keys start on free. Email colin@kineticist.com for a higher ceiling."
    },
    "capabilities": ["read", "write"],
    "resources": [
      "games",
      "game-files",
      "stats",
      "user-library (plays, ownership, wishlist, fun scores)"
    ]
  },
  "packages": {
    "cli": {
      "name": "@kineticist/cli",
      "command": "pinball",
      "registry": "https://www.npmjs.com/package/@kineticist/cli",
      "install": "npm install -g @kineticist/cli"
    },
    "mcpServer": {
      "name": "@kineticist/mcp-server",
      "command": "kineticist-mcp",
      "registry": "https://www.npmjs.com/package/@kineticist/mcp-server",
      "install": "npx @kineticist/mcp-server",
      "transports": ["stdio", "streamable-http", "webmcp"],
      "httpEndpoint": "https://www.kineticist.com/api/mcp",
      "httpAuth": "bearer (same Kineticist API key as /api/v1/*)",
      "rateLimitNote": "MCP HTTP requests consume the per-key tier limit twice per tools/call — once at the /api/mcp route, once on the tool's internal /api/v1/* fetch. Free tier (1000/day) supports about 500 MCP calls/day.",
      "webmcpNote": "Every public page on www.kineticist.com registers tools via navigator.modelContext (Web Model Context API). Anonymous visitors get the read tools (search_pinball_games, get_game_details, find_locations_near_zip); signed-in visitors additionally get the write tools (log_play, toggle_owned, toggle_wishlist, set_fun_score, undo_last_play). In-page polyfill via @mcp-b/webmcp-polyfill so the API is reachable in browsers that haven't yet shipped native navigator.modelContext.",
      "clients": ["Claude Desktop", "Cursor", "ChatGPT", "any MCP-compatible client", "in-browser agents (WebMCP)"]
    }
  },
  "allowed": {
    "crawling": true,
    "training": "see /robots.txt and /llms.txt"
  }
}
