{"openapi":"3.1.0","info":{"title":"aicoolies Public API","version":"1.0.0","description":"Read-only catalog, dataset, health, and MCP discovery endpoints for aicoolies.com. No API key is required and every operation declares `security: []`.\n\n## Permissions\n\nPublic catalog reads need no credential. The only authorization aicoolies performs is a human GitHub sign-in for /dev profiles, comments, and personal stacks; that session is first-party, scoped to the signed-in account, and cannot be obtained by a third-party client, so those routes are not part of this contract. aicoolies is deliberately not an OAuth authorization server: it issues no third-party access tokens, and /.well-known/oauth-authorization-server answers 404 with that explanation rather than a fabricated document. The machine-readable statement of this model is published at /.well-known/oauth-protected-resource (RFC 9728), and the security schemes below name the exact GitHub scopes aicoolies requests.\n\n## Versioning\n\nThe current major version is 1. Every response carries `API-Version: 1`. Version-pinned paths live under `/api/v1`; the unversioned paths are permanent aliases of the current major. A breaking change ships under a new prefix, and the outgoing major then answers with `Deprecation` (RFC 9745), `Sunset` (RFC 8594), and `Link; rel=\"deprecation\"` for at least 180 days before removal. Policy: https://aicoolies.com/developers#versioning.\n\n## Errors\n\nEvery 4xx and 5xx is an RFC 9457 problem document served as `application/problem+json`, with a machine-readable `code`, a human-readable `detail`, and a `type` URI that resolves to the matching anchor on the developer portal.\n\n## Rate limits\n\nAdvisory quotas: agent-api 120/60s, dataset 60/60s, mcp 120/60s. Responses carry RateLimit-Policy, RateLimit, and the RateLimit-Limit/-Remaining/-Reset trio; a 429 adds Retry-After. Values seen through a shared cache may be a few seconds stale.","contact":{"name":"aicoolies","url":"https://aicoolies.com/developers","email":"rasitakyol@digitalkarinca.com"},"license":{"name":"Catalog datasets: CC-BY-4.0. API contract: MIT.","url":"https://creativecommons.org/licenses/by/4.0/"}},"externalDocs":{"description":"aicoolies developer portal","url":"https://aicoolies.com/developers"},"servers":[{"url":"https://aicoolies.com","description":"Production"}],"security":[],"x-api-version":1,"x-version-path-prefix":"/api/v1","x-deprecation-policy":{"minimum_notice_days":180,"signals":["Deprecation","Sunset","Link; rel=\"deprecation\""],"documentation":"https://aicoolies.com/developers#versioning"},"x-rate-limits":{"policies":[{"name":"agent-api","requests":120,"window_seconds":60},{"name":"dataset","requests":60,"window_seconds":60},{"name":"mcp","requests":120,"window_seconds":60}],"headers":["RateLimit-Policy","RateLimit","RateLimit-Limit","RateLimit-Remaining","RateLimit-Reset","Retry-After"]},"x-error-format":"application/problem+json","tags":[{"name":"Agents","description":"JSON indexes for research agents"},{"name":"Datasets","description":"CC-BY 4.0 bulk files"},{"name":"MCP","description":"Model Context Protocol"},{"name":"Discovery","description":"Machine-readable contracts"},{"name":"Pages","description":"HTML pages with markdown content negotiation"},{"name":"Ops","description":"Liveness"}],"paths":{"/api/agents/context":{"get":{"operationId":"getAgentContext","summary":"Filterable JSON site index for research agents","description":"Returns the aicoolies catalog as a typed JSON index of tools, comparisons, reviews, stacks, use cases, categories, and tags. Supports conditional GET via If-None-Match / If-Modified-Since. CORS is * for GET and OPTIONS. Responses carry RateLimit headers so a client can self-throttle.","tags":["Agents"],"security":[],"parameters":[{"name":"category","in":"query","required":false,"description":"Category slug. Limits tools and related records to that category.","schema":{"type":"string","examples":["ai-native-ides"]}},{"name":"include","in":"query","required":false,"description":"Comma-separated collections to include. Allowed: tools, comparisons, reviews, stacks, use_cases, categories, tags.","schema":{"type":"string","examples":["tools,reviews"]}},{"name":"compact","in":"query","required":false,"description":"When true, each included collection is an array of slugs only.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Catalog index","headers":{"API-Version":{"description":"Major version of the API contract that produced this response.","schema":{"type":"string","examples":["1"]}},"RateLimit-Policy":{"description":"Advisory quota for this endpoint family, in the draft-ietf-httpapi-ratelimit-headers format.","schema":{"type":"string","examples":["\"agent-api\";q=120;w=60"]}},"RateLimit":{"description":"Remaining requests (r) and seconds until the window resets (t).","schema":{"type":"string","examples":["\"agent-api\";r=119;t=60"]}},"RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer","examples":[120]}},"RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer","examples":[119]}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer","examples":[60]}},"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentContext"}}}},"304":{"description":"Not modified — the ETag or Last-Modified you sent still matches.","headers":{"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}}},"400":{"description":"Invalid include value or unknown category slug","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. Retry-After carries the wait in seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Server error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/agents/meta":{"get":{"operationId":"getAgentMeta","summary":"Collection counts and freshness probe","description":"Cheap freshness document for agents. The ETag matches /api/agents/context so a client can skip the full payload. Supports conditional GET via If-None-Match / If-Modified-Since. CORS is * for GET and OPTIONS. Responses carry RateLimit headers so a client can self-throttle.","tags":["Agents"],"security":[],"responses":{"200":{"description":"Counts and latest-updated timestamps","headers":{"API-Version":{"description":"Major version of the API contract that produced this response.","schema":{"type":"string","examples":["1"]}},"RateLimit-Policy":{"description":"Advisory quota for this endpoint family, in the draft-ietf-httpapi-ratelimit-headers format.","schema":{"type":"string","examples":["\"agent-api\";q=120;w=60"]}},"RateLimit":{"description":"Remaining requests (r) and seconds until the window resets (t).","schema":{"type":"string","examples":["\"agent-api\";r=119;t=60"]}},"RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer","examples":[120]}},"RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer","examples":[119]}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer","examples":[60]}},"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentMeta"}}}},"304":{"description":"Not modified — the ETag or Last-Modified you sent still matches.","headers":{"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}}},"429":{"description":"Rate limit exceeded. Retry-After carries the wait in seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Server error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/agents/exclusion":{"get":{"operationId":"getAgentExclusion","summary":"Slug lists for exclusion-style sync","description":"Returns slug arrays for tools, comparisons, reviews, and stacks so an agent can detect deletions. Supports conditional GET via If-None-Match / If-Modified-Since. CORS is * for GET and OPTIONS. Responses carry RateLimit headers so a client can self-throttle.","tags":["Agents"],"security":[],"parameters":[{"name":"category","in":"query","required":false,"description":"Optional category slug filter.","schema":{"type":"string","examples":["ai-cli-agents"]}}],"responses":{"200":{"description":"Slug lists","headers":{"API-Version":{"description":"Major version of the API contract that produced this response.","schema":{"type":"string","examples":["1"]}},"RateLimit-Policy":{"description":"Advisory quota for this endpoint family, in the draft-ietf-httpapi-ratelimit-headers format.","schema":{"type":"string","examples":["\"agent-api\";q=120;w=60"]}},"RateLimit":{"description":"Remaining requests (r) and seconds until the window resets (t).","schema":{"type":"string","examples":["\"agent-api\";r=119;t=60"]}},"RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer","examples":[120]}},"RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer","examples":[119]}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer","examples":[60]}},"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentExclusion"}}}},"304":{"description":"Not modified — the ETag or Last-Modified you sent still matches.","headers":{"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}}},"400":{"description":"Unknown category slug","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. Retry-After carries the wait in seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Server error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/data/tools.json":{"get":{"operationId":"getToolsDataset","summary":"CC-BY 4.0 tools dataset","description":"Full aicoolies tool catalog as JSON. Licensed CC-BY 4.0, attribution aicoolies.com. Each record carries an as_of date. Supports conditional GET via If-None-Match / If-Modified-Since. CORS is * for GET and OPTIONS. Responses carry RateLimit headers so a client can self-throttle.","tags":["Datasets"],"security":[],"responses":{"200":{"description":"Tools envelope","headers":{"API-Version":{"description":"Major version of the API contract that produced this response.","schema":{"type":"string","examples":["1"]}},"RateLimit-Policy":{"description":"Advisory quota for this endpoint family, in the draft-ietf-httpapi-ratelimit-headers format.","schema":{"type":"string","examples":["\"agent-api\";q=120;w=60"]}},"RateLimit":{"description":"Remaining requests (r) and seconds until the window resets (t).","schema":{"type":"string","examples":["\"agent-api\";r=119;t=60"]}},"RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer","examples":[120]}},"RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer","examples":[119]}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer","examples":[60]}},"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolsDataset"}}}},"304":{"description":"Not modified — the ETag or Last-Modified you sent still matches.","headers":{"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}}},"429":{"description":"Rate limit exceeded. Retry-After carries the wait in seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/data/comparisons.json":{"get":{"operationId":"getComparisonsDataset","summary":"CC-BY 4.0 comparisons dataset","description":"Published aicoolies comparisons as JSON with tool slugs and as_of dates. Licensed CC-BY 4.0. Supports conditional GET via If-None-Match / If-Modified-Since. CORS is * for GET and OPTIONS. Responses carry RateLimit headers so a client can self-throttle.","tags":["Datasets"],"security":[],"responses":{"200":{"description":"Comparisons envelope","headers":{"API-Version":{"description":"Major version of the API contract that produced this response.","schema":{"type":"string","examples":["1"]}},"RateLimit-Policy":{"description":"Advisory quota for this endpoint family, in the draft-ietf-httpapi-ratelimit-headers format.","schema":{"type":"string","examples":["\"agent-api\";q=120;w=60"]}},"RateLimit":{"description":"Remaining requests (r) and seconds until the window resets (t).","schema":{"type":"string","examples":["\"agent-api\";r=119;t=60"]}},"RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer","examples":[120]}},"RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer","examples":[119]}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer","examples":[60]}},"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComparisonsDataset"}}}},"304":{"description":"Not modified — the ETag or Last-Modified you sent still matches.","headers":{"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}}},"429":{"description":"Rate limit exceeded. Retry-After carries the wait in seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/data/reviews.json":{"get":{"operationId":"getReviewsDataset","summary":"CC-BY 4.0 reviews dataset","description":"Published aicoolies editorial reviews with 0–100 scores for overall, speed, privacy, and developer experience. Licensed CC-BY 4.0. Supports conditional GET via If-None-Match / If-Modified-Since. CORS is * for GET and OPTIONS. Responses carry RateLimit headers so a client can self-throttle.","tags":["Datasets"],"security":[],"responses":{"200":{"description":"Reviews envelope","headers":{"API-Version":{"description":"Major version of the API contract that produced this response.","schema":{"type":"string","examples":["1"]}},"RateLimit-Policy":{"description":"Advisory quota for this endpoint family, in the draft-ietf-httpapi-ratelimit-headers format.","schema":{"type":"string","examples":["\"agent-api\";q=120;w=60"]}},"RateLimit":{"description":"Remaining requests (r) and seconds until the window resets (t).","schema":{"type":"string","examples":["\"agent-api\";r=119;t=60"]}},"RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer","examples":[120]}},"RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer","examples":[119]}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer","examples":[60]}},"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewsDataset"}}}},"304":{"description":"Not modified — the ETag or Last-Modified you sent still matches.","headers":{"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}}},"429":{"description":"Rate limit exceeded. Retry-After carries the wait in seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/agents/context":{"get":{"operationId":"getAgentContextV1","summary":"Filterable JSON site index for research agents","description":"Returns the aicoolies catalog as a typed JSON index of tools, comparisons, reviews, stacks, use cases, categories, and tags. Supports conditional GET via If-None-Match / If-Modified-Since. CORS is * for GET and OPTIONS. Responses carry RateLimit headers so a client can self-throttle. Version-pinned alias of /api/agents/context; both paths run the same handler. Versioning and deprecation policy: https://aicoolies.com/developers#versioning.","tags":["Agents"],"security":[],"parameters":[{"name":"category","in":"query","required":false,"description":"Category slug. Limits tools and related records to that category.","schema":{"type":"string","examples":["ai-native-ides"]}},{"name":"include","in":"query","required":false,"description":"Comma-separated collections to include. Allowed: tools, comparisons, reviews, stacks, use_cases, categories, tags.","schema":{"type":"string","examples":["tools,reviews"]}},{"name":"compact","in":"query","required":false,"description":"When true, each included collection is an array of slugs only.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Catalog index","headers":{"API-Version":{"description":"Major version of the API contract that produced this response.","schema":{"type":"string","examples":["1"]}},"RateLimit-Policy":{"description":"Advisory quota for this endpoint family, in the draft-ietf-httpapi-ratelimit-headers format.","schema":{"type":"string","examples":["\"agent-api\";q=120;w=60"]}},"RateLimit":{"description":"Remaining requests (r) and seconds until the window resets (t).","schema":{"type":"string","examples":["\"agent-api\";r=119;t=60"]}},"RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer","examples":[120]}},"RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer","examples":[119]}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer","examples":[60]}},"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentContext"}}}},"304":{"description":"Not modified — the ETag or Last-Modified you sent still matches.","headers":{"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}}},"400":{"description":"Invalid include value or unknown category slug","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. Retry-After carries the wait in seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Server error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/agents/meta":{"get":{"operationId":"getAgentMetaV1","summary":"Collection counts and freshness probe","description":"Cheap freshness document for agents. The ETag matches /api/agents/context so a client can skip the full payload. Supports conditional GET via If-None-Match / If-Modified-Since. CORS is * for GET and OPTIONS. Responses carry RateLimit headers so a client can self-throttle. Version-pinned alias of /api/agents/meta; both paths run the same handler. Versioning and deprecation policy: https://aicoolies.com/developers#versioning.","tags":["Agents"],"security":[],"responses":{"200":{"description":"Counts and latest-updated timestamps","headers":{"API-Version":{"description":"Major version of the API contract that produced this response.","schema":{"type":"string","examples":["1"]}},"RateLimit-Policy":{"description":"Advisory quota for this endpoint family, in the draft-ietf-httpapi-ratelimit-headers format.","schema":{"type":"string","examples":["\"agent-api\";q=120;w=60"]}},"RateLimit":{"description":"Remaining requests (r) and seconds until the window resets (t).","schema":{"type":"string","examples":["\"agent-api\";r=119;t=60"]}},"RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer","examples":[120]}},"RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer","examples":[119]}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer","examples":[60]}},"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentMeta"}}}},"304":{"description":"Not modified — the ETag or Last-Modified you sent still matches.","headers":{"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}}},"429":{"description":"Rate limit exceeded. Retry-After carries the wait in seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Server error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/agents/exclusion":{"get":{"operationId":"getAgentExclusionV1","summary":"Slug lists for exclusion-style sync","description":"Returns slug arrays for tools, comparisons, reviews, and stacks so an agent can detect deletions. Supports conditional GET via If-None-Match / If-Modified-Since. CORS is * for GET and OPTIONS. Responses carry RateLimit headers so a client can self-throttle. Version-pinned alias of /api/agents/exclusion; both paths run the same handler. Versioning and deprecation policy: https://aicoolies.com/developers#versioning.","tags":["Agents"],"security":[],"parameters":[{"name":"category","in":"query","required":false,"description":"Optional category slug filter.","schema":{"type":"string","examples":["ai-cli-agents"]}}],"responses":{"200":{"description":"Slug lists","headers":{"API-Version":{"description":"Major version of the API contract that produced this response.","schema":{"type":"string","examples":["1"]}},"RateLimit-Policy":{"description":"Advisory quota for this endpoint family, in the draft-ietf-httpapi-ratelimit-headers format.","schema":{"type":"string","examples":["\"agent-api\";q=120;w=60"]}},"RateLimit":{"description":"Remaining requests (r) and seconds until the window resets (t).","schema":{"type":"string","examples":["\"agent-api\";r=119;t=60"]}},"RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer","examples":[120]}},"RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer","examples":[119]}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer","examples":[60]}},"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentExclusion"}}}},"304":{"description":"Not modified — the ETag or Last-Modified you sent still matches.","headers":{"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}}},"400":{"description":"Unknown category slug","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded. Retry-After carries the wait in seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Server error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/data/tools.json":{"get":{"operationId":"getToolsDatasetV1","summary":"CC-BY 4.0 tools dataset","description":"Full aicoolies tool catalog as JSON. Licensed CC-BY 4.0, attribution aicoolies.com. Each record carries an as_of date. Supports conditional GET via If-None-Match / If-Modified-Since. CORS is * for GET and OPTIONS. Responses carry RateLimit headers so a client can self-throttle. Version-pinned alias of /data/tools.json; both paths run the same handler. Versioning and deprecation policy: https://aicoolies.com/developers#versioning.","tags":["Datasets"],"security":[],"responses":{"200":{"description":"Tools envelope","headers":{"API-Version":{"description":"Major version of the API contract that produced this response.","schema":{"type":"string","examples":["1"]}},"RateLimit-Policy":{"description":"Advisory quota for this endpoint family, in the draft-ietf-httpapi-ratelimit-headers format.","schema":{"type":"string","examples":["\"agent-api\";q=120;w=60"]}},"RateLimit":{"description":"Remaining requests (r) and seconds until the window resets (t).","schema":{"type":"string","examples":["\"agent-api\";r=119;t=60"]}},"RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer","examples":[120]}},"RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer","examples":[119]}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer","examples":[60]}},"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolsDataset"}}}},"304":{"description":"Not modified — the ETag or Last-Modified you sent still matches.","headers":{"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}}},"429":{"description":"Rate limit exceeded. Retry-After carries the wait in seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/data/comparisons.json":{"get":{"operationId":"getComparisonsDatasetV1","summary":"CC-BY 4.0 comparisons dataset","description":"Published aicoolies comparisons as JSON with tool slugs and as_of dates. Licensed CC-BY 4.0. Supports conditional GET via If-None-Match / If-Modified-Since. CORS is * for GET and OPTIONS. Responses carry RateLimit headers so a client can self-throttle. Version-pinned alias of /data/comparisons.json; both paths run the same handler. Versioning and deprecation policy: https://aicoolies.com/developers#versioning.","tags":["Datasets"],"security":[],"responses":{"200":{"description":"Comparisons envelope","headers":{"API-Version":{"description":"Major version of the API contract that produced this response.","schema":{"type":"string","examples":["1"]}},"RateLimit-Policy":{"description":"Advisory quota for this endpoint family, in the draft-ietf-httpapi-ratelimit-headers format.","schema":{"type":"string","examples":["\"agent-api\";q=120;w=60"]}},"RateLimit":{"description":"Remaining requests (r) and seconds until the window resets (t).","schema":{"type":"string","examples":["\"agent-api\";r=119;t=60"]}},"RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer","examples":[120]}},"RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer","examples":[119]}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer","examples":[60]}},"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComparisonsDataset"}}}},"304":{"description":"Not modified — the ETag or Last-Modified you sent still matches.","headers":{"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}}},"429":{"description":"Rate limit exceeded. Retry-After carries the wait in seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/data/reviews.json":{"get":{"operationId":"getReviewsDatasetV1","summary":"CC-BY 4.0 reviews dataset","description":"Published aicoolies editorial reviews with 0–100 scores for overall, speed, privacy, and developer experience. Licensed CC-BY 4.0. Supports conditional GET via If-None-Match / If-Modified-Since. CORS is * for GET and OPTIONS. Responses carry RateLimit headers so a client can self-throttle. Version-pinned alias of /data/reviews.json; both paths run the same handler. Versioning and deprecation policy: https://aicoolies.com/developers#versioning.","tags":["Datasets"],"security":[],"responses":{"200":{"description":"Reviews envelope","headers":{"API-Version":{"description":"Major version of the API contract that produced this response.","schema":{"type":"string","examples":["1"]}},"RateLimit-Policy":{"description":"Advisory quota for this endpoint family, in the draft-ietf-httpapi-ratelimit-headers format.","schema":{"type":"string","examples":["\"agent-api\";q=120;w=60"]}},"RateLimit":{"description":"Remaining requests (r) and seconds until the window resets (t).","schema":{"type":"string","examples":["\"agent-api\";r=119;t=60"]}},"RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer","examples":[120]}},"RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer","examples":[119]}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer","examples":[60]}},"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewsDataset"}}}},"304":{"description":"Not modified — the ETag or Last-Modified you sent still matches.","headers":{"ETag":{"description":"Strong validator. Send it back as If-None-Match to get a 304.","schema":{"type":"string"}},"Last-Modified":{"description":"Newest updatedAt across the records in this payload.","schema":{"type":"string"}}}},"429":{"description":"Rate limit exceeded. Retry-After carries the wait in seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/health":{"get":{"operationId":"getHealth","summary":"Process and database health","description":"Returns ok when the app can reach PostgreSQL. Used by uptime checks and the container healthcheck, not by agents for catalog data.","tags":["Ops"],"security":[],"responses":{"200":{"description":"Healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}},"503":{"description":"Database unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthError"}}}}}}},"/openapi.json":{"get":{"operationId":"getOpenApiDocument","summary":"OpenAPI 3.1 document","description":"Machine-readable description of the aicoolies public API, including this operation. YAML alias: /api/openapi.yaml.","tags":["Discovery"],"security":[],"responses":{"200":{"description":"OpenAPI 3.1 object","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenApiDocument"}}}}}}},"/.well-known/mcp.json":{"get":{"operationId":"getMcpManifest","summary":"MCP discovery manifest","description":"Short MCP server discovery document (RFC 8615 well-known URI): name, description, icon, and the Streamable HTTP endpoint. Richer variants live at /.well-known/mcp and /.well-known/mcp/server-card.json.","tags":["MCP"],"security":[],"responses":{"200":{"description":"Manifest JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpManifest"}}}}}}},"/.well-known/mcp":{"get":{"operationId":"getMcpDiscovery","summary":"MCP endpoint and capability discovery","description":"Lists the protocol versions this aicoolies MCP server speaks, its transport endpoints, its capabilities, and its authentication requirements (none for the public catalog tools).","tags":["MCP"],"security":[],"responses":{"200":{"description":"Discovery document","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDiscovery"}}}}}}},"/.well-known/mcp/server-card.json":{"get":{"operationId":"getMcpServerCard","summary":"MCP server card","description":"Server card describing the aicoolies MCP server: protocol versions, transport, capabilities, and the full tool list with input schemas, so a client can inspect the tools before connecting.","tags":["MCP"],"security":[],"responses":{"200":{"description":"Server card JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpServerCard"}}}}}}},"/mcp":{"post":{"operationId":"postMcp","summary":"MCP Streamable HTTP endpoint","description":"JSON-RPC 2.0 MCP server over Streamable HTTP. Send initialize, tools/list, and tools/call. Public catalog tools need no auth. Accept must list application/json and text/event-stream. The server is stateless: it issues no Mcp-Session-Id.","tags":["MCP"],"security":[],"parameters":[{"name":"MCP-Protocol-Version","in":"header","required":false,"description":"Protocol version negotiated during initialize. An unsupported value is answered with HTTP 400.","schema":{"type":"string","examples":["2025-11-25"]}}],"requestBody":{"required":true,"description":"JSON-RPC 2.0 request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcRequest"}}}},"responses":{"200":{"description":"JSON-RPC 2.0 response","headers":{"MCP-Protocol-Version":{"description":"The version this response speaks, after negotiation.","schema":{"type":"string","examples":["2025-11-25"]}},"API-Version":{"description":"Major version of the API contract that produced this response.","schema":{"type":"string","examples":["1"]}},"RateLimit-Policy":{"description":"Advisory quota for this endpoint family, in the draft-ietf-httpapi-ratelimit-headers format.","schema":{"type":"string","examples":["\"agent-api\";q=120;w=60"]}},"RateLimit":{"description":"Remaining requests (r) and seconds until the window resets (t).","schema":{"type":"string","examples":["\"agent-api\";r=119;t=60"]}},"RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer","examples":[120]}},"RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer","examples":[119]}},"RateLimit-Reset":{"description":"Seconds until the current window resets.","schema":{"type":"integer","examples":[60]}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcResponse"}}}},"202":{"description":"Notification or response accepted; no body."},"400":{"description":"Parse error, invalid JSON-RPC envelope, or unsupported protocol version","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcResponse"}}}},"429":{"description":"Rate limit exceeded. Retry-After carries the wait in seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"operationId":"getOAuthProtectedResourceMetadata","summary":"OAuth 2.0 protected resource metadata","description":"RFC 9728 metadata for the aicoolies API resource. It states the permission model in machine-readable form: public catalog reads need no authorization, and the account routes are gated by a first-party session that no third-party client can obtain.","tags":["Discovery"],"security":[],"responses":{"200":{"description":"Protected resource metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthProtectedResourceMetadata"}}}}}}},"/llms.txt":{"get":{"operationId":"getLlmsTxt","summary":"llms.txt overview for language models","description":"Markdown overview of aicoolies: what the catalog covers, the named developer resources, and the machine-readable files. /llms.txt is the short index; /llms-full.txt enumerates every page.","tags":["Discovery"],"security":[],"responses":{"200":{"description":"llms.txt body","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/tools/{slug}":{"get":{"operationId":"getToolPage","summary":"Tool page as HTML or markdown","description":"Canonical aicoolies page for one tool. Content negotiation is honoured on every page URL: send Accept: text/markdown for the markdown rendition, or append .md to the path. Responses carry Vary: Accept so a shared cache keeps the two renditions apart.","tags":["Pages"],"security":[],"parameters":[{"name":"slug","in":"path","required":true,"description":"Tool slug, for example cursor.","schema":{"type":"string","examples":["cursor"]}},{"name":"Accept","in":"header","required":false,"description":"text/html (default) or text/markdown. An Accept header that excludes both is answered with HTTP 406.","schema":{"type":"string","enum":["text/html","text/markdown"],"default":"text/html"}}],"responses":{"200":{"description":"Tool page in the negotiated representation","headers":{"Vary":{"description":"Always includes Accept and Accept-Encoding.","schema":{"type":"string","examples":["Accept, Accept-Encoding"]}}},"content":{"text/html":{"schema":{"type":"string"}},"text/markdown":{"schema":{"type":"string"}}}},"404":{"description":"No such tool. The markdown rendition lists recovery links.","content":{"text/html":{"schema":{"type":"string"}},"text/markdown":{"schema":{"type":"string"}}}},"406":{"description":"Neither text/html nor text/markdown is acceptable to the client.","content":{"text/plain":{"schema":{"type":"string"}}}}}}}},"components":{"schemas":{"Problem":{"type":"object","description":"RFC 9457 problem details. Served as application/problem+json on every 4xx and 5xx from the public API. Branch on `code`, which is a closed set; `detail` is prose for humans.","required":["type","title","status","code","detail"],"properties":{"type":{"type":"string","format":"uri","description":"Stable URI for this error class; resolves to the docs anchor."},"title":{"type":"string","description":"Short, human-readable summary of the error class."},"status":{"type":"integer","description":"HTTP status code, repeated for convenience."},"code":{"type":"string","description":"Machine-readable error code.","enum":["invalid_parameter","unknown_category","malformed_request","unsupported_protocol_version","not_found","method_not_allowed","rate_limited","internal_error","database_unavailable"]},"detail":{"type":"string","description":"What went wrong for this specific request."},"error":{"type":"string","description":"Mirror of detail, kept for clients written before the move to RFC 9457."},"instance":{"type":"string","description":"Path of the request that produced the error."},"policy":{"type":"string","description":"Rate-limit policy name, on 429 only."},"retry_after_seconds":{"type":"integer","description":"Seconds to wait before retrying, on 429 only."}}},"AgentContext":{"type":"object","required":["schema_version","generated_at","base_url","counts"],"properties":{"schema_version":{"type":"integer"},"generated_at":{"type":"string","format":"date-time"},"base_url":{"type":"string","format":"uri"},"counts":{"$ref":"#/components/schemas/CatalogCounts"},"tools":{"type":"array","items":{"$ref":"#/components/schemas/AgentTool"}},"comparisons":{"type":"array","items":{"$ref":"#/components/schemas/AgentComparison"}},"reviews":{"type":"array","items":{"$ref":"#/components/schemas/AgentReview"}},"stacks":{"type":"array","items":{"$ref":"#/components/schemas/AgentStack"}},"use_cases":{"type":"array","items":{"$ref":"#/components/schemas/AgentUseCase"}},"categories":{"type":"array","items":{"$ref":"#/components/schemas/AgentCategory"}},"tags":{"type":"array","items":{"$ref":"#/components/schemas/AgentTag"}}}},"AgentTool":{"type":"object","required":["slug","name","status"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["active","graveyard"]},"categories":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"string"}},"is_open_source":{"type":"boolean"},"is_recommended":{"type":"boolean"},"pricing_summary":{"type":["string","null"]},"alternatives":{"type":"array","items":{"type":"string"}},"updated_at":{"type":"string","format":"date-time"}}},"AgentComparison":{"type":"object","required":["slug","title"],"properties":{"slug":{"type":"string"},"title":{"type":"string"},"tool_slugs":{"type":"array","items":{"type":"string"}},"updated_at":{"type":"string","format":"date-time"}}},"AgentReview":{"type":"object","required":["slug"],"properties":{"slug":{"type":"string"},"tool_slug":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time"}}},"AgentStack":{"type":"object","required":["slug","title"],"properties":{"slug":{"type":"string"},"title":{"type":"string"},"tool_slugs":{"type":"array","items":{"type":"string"}},"budget_range":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time"}}},"AgentUseCase":{"type":"object","required":["slug"],"properties":{"slug":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"AgentCategory":{"type":"object","required":["slug","name"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"tool_count":{"type":"integer"}}},"AgentTag":{"type":"object","required":["slug"],"properties":{"slug":{"type":"string"}}},"AgentMeta":{"type":"object","required":["schema_version","generated_at","counts","latest_updated","payload_etag"],"properties":{"schema_version":{"type":"integer"},"generated_at":{"type":"string","format":"date-time"},"counts":{"$ref":"#/components/schemas/CatalogCounts"},"latest_updated":{"$ref":"#/components/schemas/LatestUpdated"},"payload_etag":{"type":"string"}}},"AgentExclusion":{"type":"object","required":["generated_at","tools","comparisons","reviews","stacks"],"properties":{"generated_at":{"type":"string","format":"date-time"},"tools":{"type":"array","items":{"type":"string"}},"comparisons":{"type":"array","items":{"type":"string"}},"reviews":{"type":"array","items":{"type":"string"}},"stacks":{"type":"array","items":{"type":"string"}}}},"CatalogCounts":{"type":"object","description":"Record count per collection.","properties":{"tools":{"type":"integer"},"comparisons":{"type":"integer"},"reviews":{"type":"integer"},"stacks":{"type":"integer"},"use_cases":{"type":"integer"},"categories":{"type":"integer"},"tags":{"type":"integer"}}},"LatestUpdated":{"type":"object","description":"Newest updatedAt per collection, or null when the collection is empty.","properties":{"tools":{"type":["string","null"],"format":"date-time"},"comparisons":{"type":["string","null"],"format":"date-time"},"reviews":{"type":["string","null"],"format":"date-time"},"stacks":{"type":["string","null"],"format":"date-time"},"use_cases":{"type":["string","null"],"format":"date-time"},"categories":{"type":["string","null"],"format":"date-time"},"tags":{"type":["string","null"],"format":"date-time"}}},"DatasetLicense":{"type":"object","required":["license","attribution"],"properties":{"license":{"type":"string","enum":["CC-BY-4.0"]},"license_url":{"type":"string","format":"uri"},"attribution":{"type":"string"},"attribution_url":{"type":"string","format":"uri"},"base_url":{"type":"string","format":"uri"},"generated_at":{"type":"string","format":"date-time"},"count":{"type":"integer"}}},"ToolsDataset":{"type":"object","required":["license","tools","count"],"properties":{"license":{"type":"string","enum":["CC-BY-4.0"]},"license_url":{"type":"string","format":"uri"},"attribution":{"type":"string"},"attribution_url":{"type":"string","format":"uri"},"base_url":{"type":"string","format":"uri"},"generated_at":{"type":"string","format":"date-time"},"count":{"type":"integer"},"tools":{"type":"array","items":{"$ref":"#/components/schemas/DatasetTool"}}}},"DatasetTool":{"type":"object","required":["slug","name","url","status","as_of"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"status":{"type":"string","enum":["active","graveyard"]},"categories":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"string"}},"is_open_source":{"type":"boolean"},"is_recommended":{"type":"boolean"},"pricing_summary":{"type":["string","null"]},"as_of":{"type":"string","format":"date-time"}}},"ComparisonsDataset":{"type":"object","required":["license","comparisons","count"],"properties":{"license":{"type":"string","enum":["CC-BY-4.0"]},"license_url":{"type":"string","format":"uri"},"attribution":{"type":"string"},"attribution_url":{"type":"string","format":"uri"},"base_url":{"type":"string","format":"uri"},"generated_at":{"type":"string","format":"date-time"},"count":{"type":"integer"},"comparisons":{"type":"array","items":{"$ref":"#/components/schemas/DatasetComparison"}}}},"DatasetComparison":{"type":"object","required":["slug","title","url","as_of"],"properties":{"slug":{"type":"string"},"title":{"type":"string"},"url":{"type":"string","format":"uri"},"tool_slugs":{"type":"array","items":{"type":"string"}},"published_at":{"type":["string","null"],"format":"date-time"},"as_of":{"type":"string","format":"date-time"}}},"ReviewsDataset":{"type":"object","required":["license","reviews","count"],"properties":{"license":{"type":"string","enum":["CC-BY-4.0"]},"license_url":{"type":"string","format":"uri"},"attribution":{"type":"string"},"attribution_url":{"type":"string","format":"uri"},"base_url":{"type":"string","format":"uri"},"generated_at":{"type":"string","format":"date-time"},"count":{"type":"integer"},"reviews":{"type":"array","items":{"$ref":"#/components/schemas/DatasetReview"}}}},"DatasetReview":{"type":"object","required":["slug","title","url","as_of"],"properties":{"slug":{"type":"string"},"title":{"type":"string"},"url":{"type":"string","format":"uri"},"tool_slug":{"type":["string","null"]},"score_overall":{"type":["integer","null"],"description":"0–100 aicoolies Score v1."},"score_speed":{"type":["integer","null"]},"score_privacy":{"type":["integer","null"]},"score_dev_experience":{"type":["integer","null"]},"verdict":{"type":["string","null"]},"published_at":{"type":["string","null"],"format":"date-time"},"as_of":{"type":"string","format":"date-time"}}},"Health":{"type":"object","required":["status","database"],"properties":{"status":{"type":"string","enum":["ok"]},"database":{"type":"string","enum":["connected"]}}},"HealthError":{"type":"object","required":["status","message"],"properties":{"status":{"type":"string","enum":["error"]},"message":{"type":"string"}}},"OpenApiDocument":{"type":"object","description":"An OpenAPI 3.1 document.","required":["openapi","info","paths"],"properties":{"openapi":{"type":"string","enum":["3.1.0"]},"info":{"type":"object","required":["title","version"],"properties":{"title":{"type":"string"},"version":{"type":"string"},"description":{"type":"string"}}},"servers":{"type":"array","items":{"type":"object","additionalProperties":true}},"paths":{"type":"object","additionalProperties":true},"components":{"type":"object","additionalProperties":true}}},"McpManifest":{"type":"object","required":["name","description","endpoint"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"icon":{"type":"string","format":"uri"},"endpoint":{"type":"string","format":"uri"}}},"McpDiscovery":{"type":"object","required":["mcp_version","server_name","endpoints","capabilities"],"properties":{"mcp_version":{"type":"string","description":"Newest protocol version supported."},"supported_mcp_versions":{"type":"array","items":{"type":"string"}},"server_name":{"type":"string"},"server_version":{"type":"string"},"endpoints":{"type":"object","properties":{"streamable_http":{"type":"string","format":"uri"}}},"capabilities":{"type":"object","properties":{"tools":{"type":"boolean"},"resources":{"type":"boolean"},"prompts":{"type":"boolean"},"sampling":{"type":"boolean"},"roots":{"type":"boolean"}}},"authentication":{"type":"object","properties":{"required":{"type":"boolean"},"methods":{"type":"array","items":{"type":"string"}}}},"documentation":{"type":"string","format":"uri"},"privacy_policy":{"type":"string","format":"uri"}}},"McpServerCard":{"type":"object","required":["protocolVersion","serverInfo","transport","tools"],"properties":{"$schema":{"type":"string","format":"uri"},"version":{"type":"string"},"protocolVersion":{"type":"string"},"supportedProtocolVersions":{"type":"array","items":{"type":"string"}},"serverInfo":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"}}},"transport":{"type":"object","properties":{"type":{"type":"string","enum":["streamable-http"]},"url":{"type":"string","format":"uri"}}},"capabilities":{"type":"object","additionalProperties":true},"tools":{"type":"array","items":{"$ref":"#/components/schemas/McpTool"}}}},"McpTool":{"type":"object","required":["name","description","inputSchema"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"inputSchema":{"type":"object","additionalProperties":true}}},"OAuthProtectedResourceMetadata":{"type":"object","description":"RFC 9728 OAuth 2.0 Protected Resource Metadata.","required":["resource"],"properties":{"resource":{"type":"string","format":"uri"},"resource_name":{"type":"string"},"resource_documentation":{"type":"string","format":"uri"},"resource_policy_uri":{"type":"string","format":"uri"},"bearer_methods_supported":{"type":"array","items":{"type":"string"}},"scopes_supported":{"type":"array","items":{"type":"string"}},"authorization_details_types_supported":{"type":"array","items":{"type":"string"}}}},"JsonRpcRequest":{"type":"object","required":["jsonrpc","method"],"properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"type":["string","number","null"]},"method":{"type":"string","description":"MCP method, for example initialize, tools/list, or tools/call."},"params":{"type":"object","additionalProperties":true}}},"JsonRpcResponse":{"type":"object","required":["jsonrpc"],"properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"type":["string","number","null"]},"result":{"type":"object","additionalProperties":true},"error":{"$ref":"#/components/schemas/JsonRpcError"}}},"JsonRpcError":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","description":"JSON-RPC 2.0 error code."},"message":{"type":"string"},"data":{"type":"object","additionalProperties":true}}}},"securitySchemes":{"githubOAuth":{"type":"oauth2","description":"Human sign-in only. aicoolies acts as an OAuth 2.0 client of GitHub and requests the two identity scopes listed here — the narrowest set that can populate a public developer profile. It never requests repository, organization, or write scopes, and it issues no access tokens of its own to third parties.","flows":{"authorizationCode":{"authorizationUrl":"https://github.com/login/oauth/authorize","tokenUrl":"https://github.com/login/oauth/access_token","refreshUrl":"https://github.com/login/oauth/access_token","scopes":{"read:user":"Read the public GitHub profile (id, username, avatar) of the signer-in.","user:email":"Read the verified email address on that GitHub account."}}}},"sessionCookie":{"type":"apiKey","in":"cookie","name":"payload-token","description":"First-party session cookie issued after GitHub sign-in. Scoped to the signed-in account: it can read and write only that user profile, its stack, its subscriptions, and its comments. Third-party clients cannot obtain one, which is why no account route appears in this document."}}}}