{"openapi":"3.1.0","info":{"title":"Operator Stack agent API (PromptMetrics)","version":"0.1.0","summary":"MCP server and OAuth 2.1 endpoints for the Operator Stack community.","description":"The agent-facing surface of operator.promptmetrics.dev: an MCP server, the OAuth 2.1\nendpoints that authorise it, and the public read endpoints under /api/v1.\n\nEverything documented here is callable without a session cookie. The /api/v1 WRITE\noperations are deliberately absent: they require a browser session no external agent\ncan obtain. To post, comment or react as a member, use the MCP server's\ncommunity:write tools instead.\n\nVERSIONING. The REST surface is versioned in the URL path (/api/v1). Within a major\nversion, fields may be ADDED to responses but never removed or retyped, so a client\nthat ignores unknown fields keeps working. A breaking change ships as /api/v2. If\n/api/v1 is ever retired, its responses will carry Deprecation and Sunset headers\n(RFC 9745 and RFC 8594) for at least 90 days before removal, and the sunset date will\nbe published at /docs.\n\nRATE LIMITS. Anonymous reads return RateLimit and RateLimit-Policy headers (the IETF\ndraft fields) alongside X-RateLimit-*, so a client can self-throttle without first\nbeing throttled. A 429 additionally carries Retry-After.\n\nERRORS. Every 4xx and 5xx returns the Error schema: a stable machine-readable `code`,\na human-readable `message`, and `field` naming the offending input on a validation\nfailure. Branch on `code`; `message` wording may change.\n\nRate limits: 100 requests/minute per client at the transport,\nplus 30/minute across community:write tools and\n20/minute across community:admin tools.\n\nPKCE (S256) is REQUIRED on the authorization code flow. OpenAPI 3.1 has no field to\nexpress that, so it is stated here.\n\nEvery public page on this origin also serves a text/markdown representation via\nAccept-header content negotiation.","termsOfService":"https://operator.promptmetrics.dev/terms","contact":{"name":"PromptMetrics","url":"https://operator.promptmetrics.dev/docs","email":"hello@promptmetrics.dev"}},"externalDocs":{"url":"https://operator.promptmetrics.dev/docs","description":"Operator Stack developer docs"},"servers":[{"url":"https://operator.promptmetrics.dev"}],"paths":{"/api/mcp":{"post":{"operationId":"mcpRpc","summary":"MCP Streamable HTTP endpoint (spec revision 2026-07-28)","description":"Stateless and POST-only. GET and DELETE return 405 — the 2026-07-28 revision removes the GET stream. Returns 404 when the MCP server is disabled.","security":[{"operatorStackOAuth":["community:read"]},{"bearerToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"JSON-RPC 2.0 request envelope"}}}},"responses":{"200":{"description":"JSON-RPC 2.0 response. A tool call that fails returns 200 with isError set in the result, per MCP — transport errors use the HTTP status codes below.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcResponse"}},"text/event-stream":{"schema":{"type":"string","description":"Server-sent events, each data frame a JSON-RPC response."}}}},"401":{"description":"Missing or invalid token. Carries WWW-Authenticate: Bearer with a resource_metadata pointer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"403":{"description":"Token lacks a required scope (insufficient_scope).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"404":{"description":"MCP server disabled in this environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Carries X-RateLimit-* and Retry-After headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/oauth/register":{"post":{"operationId":"registerClient","summary":"RFC 7591 dynamic client registration","description":"Open to any client — no pre-shared key and no human approval needed to obtain a client_id.","security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["client_id"],"properties":{"client_id":{"type":"string"},"client_secret":{"type":"string","description":"Returned once, only for confidential clients. Never retrievable again."},"client_name":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string","format":"uri"}},"grant_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string"},"scope":{"type":"string","description":"Space-separated granted scopes."}}}}}},"400":{"description":"Malformed request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or the MCP server is disabled in this environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/oauth/token":{"post":{"operationId":"issueToken","summary":"RFC 6749 token endpoint","description":"Grants: authorization_code and refresh_token. PKCE S256 required. Access tokens live 1 hour; refresh tokens live 30 days, rotate on use, and trigger reuse detection.","security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["access_token","token_type","expires_in"],"properties":{"access_token":{"type":"string"},"token_type":{"type":"string","enum":["Bearer"]},"expires_in":{"type":"integer","description":"Seconds. 3600 for an access token."},"refresh_token":{"type":"string","description":"Rotates on every use; replaying a rotated token invalidates the chain."},"scope":{"type":"string"}}}}}},"400":{"description":"Malformed request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or the MCP server is disabled in this environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/oauth/revoke":{"post":{"operationId":"revokeToken","summary":"RFC 7009 token revocation","security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","description":"Empty object. RFC 7009 returns 200 regardless of whether the token existed."}}}},"400":{"description":"Malformed request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or the MCP server is disabled in this environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/oauth/authorize":{"get":{"operationId":"authorize","summary":"Authorization endpoint with consent screen","description":"A browser navigation, not a server-to-server call. Redirects to login when the user has no session.","security":[],"responses":{"200":{"description":"Success","content":{"text/html":{"schema":{"type":"string","description":"An HTML consent page, or a 303 redirect to the registered redirect_uri."}}}},"400":{"description":"Malformed request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or the MCP server is disabled in this environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/feed":{"get":{"operationId":"listFeed","summary":"Recent public posts across every circle","description":"Anonymous callers see published posts in public circles only. Ordering and filtering follow the query parameters; omit them for the newest posts.","tags":["Community (public read)"],"security":[],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"default":20}},{"name":"sort","in":"query","schema":{"type":"string","enum":["new","top"]}},{"name":"groupSlug","in":"query","schema":{"type":"string"},"description":"Restrict to one circle."}],"responses":{"200":{"description":"Success","headers":{"RateLimit":{"schema":{"type":"string","example":"limit=60, remaining=59, reset=44"},"description":"Remaining quota for this client in the current window."},"RateLimit-Policy":{"schema":{"type":"string","example":"60;w=60"},"description":"The declared quota and window, in seconds."}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["posts"],"properties":{"posts":{"type":"array","items":{"$ref":"#/components/schemas/PostListItem"}},"nextCursor":{"type":"string","format":"date-time"}}},"meta":{"type":"object","required":["page","limit","hasMore"],"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"hasMore":{"type":"boolean"},"totalCount":{"type":"integer","minimum":0}}}}}}}},"400":{"description":"Malformed request. `code` is VALIDATION_ERROR and `field` names the input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or no route matches the path. `code` is NOT_FOUND.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Carries Retry-After plus the RateLimit headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error. `code` is INTERNAL_ERROR.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/groups":{"get":{"operationId":"listGroups","summary":"Every public circle","description":"Invite-only circles are omitted for anonymous callers.","tags":["Community (public read)"],"security":[],"responses":{"200":{"description":"Success","headers":{"RateLimit":{"schema":{"type":"string","example":"limit=60, remaining=59, reset=44"},"description":"Remaining quota for this client in the current window."},"RateLimit-Policy":{"schema":{"type":"string","example":"60;w=60"},"description":"The declared quota and window, in seconds."}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["groups"],"properties":{"groups":{"type":"array","items":{"$ref":"#/components/schemas/Group"}}}},"meta":{"type":"object","required":["page","limit","hasMore"],"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"hasMore":{"type":"boolean"},"totalCount":{"type":"integer","minimum":0}}}}}}}},"400":{"description":"Malformed request. `code` is VALIDATION_ERROR and `field` names the input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or no route matches the path. `code` is NOT_FOUND.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Carries Retry-After plus the RateLimit headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error. `code` is INTERNAL_ERROR.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/groups/{slug}":{"get":{"operationId":"getGroup","summary":"One circle by slug","description":"Returns 404 for a circle that does not exist or is not visible to an anonymous caller — the two are deliberately indistinguishable.","tags":["Community (public read)"],"security":[],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The circle slug, e.g. where-do-i-start."}],"responses":{"200":{"description":"Success","headers":{"RateLimit":{"schema":{"type":"string","example":"limit=60, remaining=59, reset=44"},"description":"Remaining quota for this client in the current window."},"RateLimit-Policy":{"schema":{"type":"string","example":"60;w=60"},"description":"The declared quota and window, in seconds."}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Group"}}}}}},"400":{"description":"Malformed request. `code` is VALIDATION_ERROR and `field` names the input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or no route matches the path. `code` is NOT_FOUND.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Carries Retry-After plus the RateLimit headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error. `code` is INTERNAL_ERROR.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/users/{slug}":{"get":{"operationId":"getUserProfile","summary":"A public member profile","description":"Includes reputation, badges and circle contributions. publicPostsCount is what an anonymous caller can actually see; postsCount is the all-circles figure.","tags":["Community (public read)"],"security":[],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The member userslug, e.g. izzy-a."}],"responses":{"200":{"description":"Success","headers":{"RateLimit":{"schema":{"type":"string","example":"limit=60, remaining=59, reset=44"},"description":"Remaining quota for this client in the current window."},"RateLimit-Policy":{"schema":{"type":"string","example":"60;w=60"},"description":"The declared quota and window, in seconds."}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["user","badges","circles"],"properties":{"user":{"$ref":"#/components/schemas/UserProfile"},"badges":{"type":"object","description":"Awarded badges."},"circles":{"type":"array","items":{"type":"object"},"description":"Per-circle contribution summary."}}}}}}}},"400":{"description":"Malformed request. `code` is VALIDATION_ERROR and `field` names the input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or no route matches the path. `code` is NOT_FOUND.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Carries Retry-After plus the RateLimit headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error. `code` is INTERNAL_ERROR.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/leaderboards":{"get":{"operationId":"listLeaderboards","summary":"Reputation leaderboards","description":"Scoped by type, period and optionally by circle.","tags":["Community (public read)"],"security":[],"parameters":[{"name":"type","in":"query","schema":{"type":"string"}},{"name":"period","in":"query","schema":{"type":"string","enum":["week","month","all_time"]}},{"name":"groupSlug","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","headers":{"RateLimit":{"schema":{"type":"string","example":"limit=60, remaining=59, reset=44"},"description":"Remaining quota for this client in the current window."},"RateLimit-Policy":{"schema":{"type":"string","example":"60;w=60"},"description":"The declared quota and window, in seconds."}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["type","groupSlug","period","leaderboard"],"properties":{"type":{"type":"string"},"groupSlug":{"type":["string","null"]},"period":{"type":"string"},"leaderboard":{"type":"array","items":{"$ref":"#/components/schemas/LeaderboardEntry"}},"viewer":{"type":["object","null"],"description":"The caller's own rank, when signed in."}}},"meta":{"type":"object","required":["page","limit","hasMore"],"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"hasMore":{"type":"boolean"},"totalCount":{"type":"integer","minimum":0}}}}}}}},"400":{"description":"Malformed request. `code` is VALIDATION_ERROR and `field` names the input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or no route matches the path. `code` is NOT_FOUND.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Carries Retry-After plus the RateLimit headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error. `code` is INTERNAL_ERROR.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/search":{"get":{"operationId":"searchPosts","summary":"Full-text search across public posts","description":"Anonymous callers search published posts in public circles only.","tags":["Community (public read)"],"security":[],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"The search query."},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"default":20}}],"responses":{"200":{"description":"Success","headers":{"RateLimit":{"schema":{"type":"string","example":"limit=60, remaining=59, reset=44"},"description":"Remaining quota for this client in the current window."},"RateLimit-Policy":{"schema":{"type":"string","example":"60;w=60"},"description":"The declared quota and window, in seconds."}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["results"],"properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/SearchResult"}},"nextCursor":{"type":"string","format":"date-time"}}},"meta":{"type":"object","required":["page","limit","hasMore"],"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"hasMore":{"type":"boolean"},"totalCount":{"type":"integer","minimum":0}}}}}}}},"400":{"description":"Malformed request. `code` is VALIDATION_ERROR and `field` names the input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or no route matches the path. `code` is NOT_FOUND.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Carries Retry-After plus the RateLimit headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error. `code` is INTERNAL_ERROR.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/demo/thread":{"get":{"operationId":"demoThread","summary":"Sample community thread, no credentials required","description":"Returns one public thread in the same shape the summarize_thread MCP tool returns, so an agent can inspect the data before registering. Negotiates application/json and text/markdown. Answers 503 with the shared Error schema when the pinned thread is unavailable.","security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["note","documentation","mcp_endpoint","tool","thread"],"properties":{"note":{"type":"string"},"documentation":{"type":"string","format":"uri"},"mcp_endpoint":{"type":"string","format":"uri"},"tool":{"type":"string","enum":["summarize_thread"]},"thread":{"type":"object","required":["post_id","title","url","comment_count","summary"],"properties":{"post_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"url":{"type":"string","format":"uri"},"comment_count":{"type":"integer","minimum":0},"summary":{"type":"string"}}}}}}}},"400":{"description":"Malformed request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or the MCP server is disabled in this environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"operationId":"authorizationServerMetadata","summary":"RFC 8414 authorization server metadata","security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["issuer","authorization_endpoint","token_endpoint","scopes_supported"],"properties":{"issuer":{"type":"string","format":"uri"},"authorization_endpoint":{"type":"string","format":"uri"},"token_endpoint":{"type":"string","format":"uri"},"registration_endpoint":{"type":"string","format":"uri"},"revocation_endpoint":{"type":"string","format":"uri"},"scopes_supported":{"type":"array","items":{"type":"string"}},"response_types_supported":{"type":"array","items":{"type":"string"}},"grant_types_supported":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_methods_supported":{"type":"array","items":{"type":"string"}},"code_challenge_methods_supported":{"type":"array","items":{"type":"string"}}}}}}},"400":{"description":"Malformed request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or the MCP server is disabled in this environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"operationId":"originProtectedResourceMetadata","summary":"RFC 9728 metadata for this origin","security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["resource","authorization_servers","scopes_supported"],"properties":{"resource":{"type":"string","format":"uri"},"authorization_servers":{"type":"array","items":{"type":"string","format":"uri"}},"scopes_supported":{"type":"array","items":{"type":"string"}},"bearer_methods_supported":{"type":"array","items":{"type":"string","enum":["header","body","query"]}},"resource_name":{"type":"string"},"resource_documentation":{"type":"string","format":"uri"}}}}}},"400":{"description":"Malformed request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or the MCP server is disabled in this environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/.well-known/oauth-protected-resource/api/mcp":{"get":{"operationId":"mcpProtectedResourceMetadata","summary":"RFC 9728 metadata for the MCP resource","security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["resource","authorization_servers","scopes_supported"],"properties":{"resource":{"type":"string","format":"uri"},"authorization_servers":{"type":"array","items":{"type":"string","format":"uri"}},"scopes_supported":{"type":"array","items":{"type":"string"}},"bearer_methods_supported":{"type":"array","items":{"type":"string","enum":["header","body","query"]}},"resource_name":{"type":"string"},"resource_documentation":{"type":"string","format":"uri"}}}}}},"400":{"description":"Malformed request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or the MCP server is disabled in this environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/.well-known/mcp":{"get":{"operationId":"mcpManifest","summary":"MCP server manifest (SEP-1960)","security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["mcp_version","endpoints"],"properties":{"mcp_version":{"type":"string"},"server_name":{"type":"string"},"server_version":{"type":"string"},"description":{"type":"string"},"endpoints":{"type":"object","required":["streamable_http"],"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"},"registration":{"type":"object"},"rate_limits":{"type":"object","properties":{"requests_per_minute":{"type":"integer"}}},"documentation":{"type":"string","format":"uri"}}}}}},"400":{"description":"Malformed request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or the MCP server is disabled in this environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/.well-known/mcp/server-card.json":{"get":{"operationId":"mcpServerCard","summary":"MCP server card (SEP-1649)","security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["protocolVersion","serverInfo","transport"],"properties":{"version":{"type":"string"},"protocolVersion":{"type":"string"},"serverInfo":{"type":"object","required":["name","version"],"properties":{"name":{"type":"string"},"title":{"type":"string"},"version":{"type":"string"}}},"description":{"type":"string"},"documentationUrl":{"type":"string","format":"uri"},"transport":{"type":"object","required":["type","endpoint"],"properties":{"type":{"type":"string"},"endpoint":{"type":"string"}}},"capabilities":{"type":"object"}}}}}},"400":{"description":"Malformed request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or the MCP server is disabled in this environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/llms.txt":{"get":{"operationId":"llmsTxt","summary":"Agent map: what this site is and when to use it","description":"Negotiates text/plain and text/markdown via the Accept header.","security":[],"responses":{"200":{"description":"Success","content":{"text/plain":{"schema":{"type":"string","description":"UTF-8 text."}}}},"400":{"description":"Malformed request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or the MCP server is disabled in this environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/llms-full.txt":{"get":{"operationId":"llmsFullTxt","summary":"Expanded agent map: scopes, tools, flow, limits","security":[],"responses":{"200":{"description":"Success","content":{"text/plain":{"schema":{"type":"string","description":"UTF-8 text."}}}},"400":{"description":"Malformed request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or the MCP server is disabled in this environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"OAuthError":{"type":"object","required":["error"],"description":"RFC 6750 bearer-token error. Distinct from the Error schema used by /api/v1 — the OAuth RFCs specify this shape and the MCP endpoint follows them.","properties":{"error":{"type":"string","enum":["invalid_token","invalid_request","insufficient_scope"]},"error_description":{"type":"string"}}},"JsonRpcResponse":{"type":"object","required":["jsonrpc","id"],"properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"type":["string","number","null"]},"result":{"type":"object","description":"Present on success."},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","description":"JSON-RPC error code."},"message":{"type":"string"},"data":{}},"description":"Present instead of result when the call itself failed."}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","field"],"properties":{"code":{"type":"string","enum":["UNAUTHORIZED","FORBIDDEN","NOT_FOUND","VALIDATION_ERROR","CONFLICT","RATE_LIMITED","ONBOARDING_INCOMPLETE","INTERNAL_ERROR"],"description":"Stable machine-readable code. Branch on this, not on message."},"message":{"type":"string","description":"Human-readable explanation. Wording may change; the code will not."},"field":{"type":["string","null"],"description":"The request field at fault for VALIDATION_ERROR, otherwise null."}}}}},"PaginationMeta":{"type":"object","required":["page","limit","hasMore"],"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"hasMore":{"type":"boolean"},"totalCount":{"type":"integer","minimum":0}}},"PostListItem":{"type":"object","required":["id","slug","title","type","status","isSolved","group","author","upvotes","commentCount","viewCount","tags","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"title":{"type":"string"},"type":{"type":"string"},"status":{"type":"string"},"isSolved":{"type":"boolean"},"group":{"type":"object","required":["slug","name"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"color":{"type":["string","null"]}}},"author":{"type":"object","required":["userslug","username","reputationScore","acceptedSolutions","level"],"properties":{"userslug":{"type":"string"},"username":{"type":"string"},"reputationScore":{"type":"number"},"acceptedSolutions":{"type":"integer","minimum":0},"level":{"type":"integer","minimum":1}}},"upvotes":{"type":"integer","minimum":0},"commentCount":{"type":"integer","minimum":0},"viewCount":{"type":"integer","minimum":0},"tags":{"type":"array","items":{"type":"string"}},"excerpt":{"type":"string","description":"First ~200 characters of the body, word-trimmed."},"createdAt":{"type":"string","format":"date-time"},"viewerHasLiked":{"type":"boolean"},"viewerHasBookmarked":{"type":"boolean"},"featuredLabel":{"type":["string","null"]},"coverImageUrl":{"type":["string","null"]},"linkPreview":{"type":["object","null"],"description":"Server-generated card for the first URL in the body; null when there is none."}}},"Group":{"type":"object","required":["id","slug","name","description","color","visibility","requiredTierId","memberCount","createdBy","createdAt","updatedAt"],"properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"color":{"type":["string","null"]},"visibility":{"type":"string"},"requiredTierId":{"type":["string","null"]},"memberCount":{"type":"integer","minimum":0},"createdBy":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"PublicUser":{"type":"object","required":["id","username","userslug","fullName","pictureUrl","role","reputationScore","streakDays","acceptedSolutions","level"],"properties":{"id":{"type":"string","format":"uuid"},"username":{"type":"string"},"userslug":{"type":"string"},"fullName":{"type":["string","null"]},"pictureUrl":{"type":["string","null"]},"role":{"type":"string"},"reputationScore":{"type":"number"},"streakDays":{"type":"integer","minimum":0},"acceptedSolutions":{"type":"integer","minimum":0},"level":{"type":"integer","minimum":1}}},"UserProfile":{"allOf":[{"type":"object","required":["id","username","userslug","fullName","pictureUrl","role","reputationScore","streakDays","acceptedSolutions","level"],"properties":{"id":{"type":"string","format":"uuid"},"username":{"type":"string"},"userslug":{"type":"string"},"fullName":{"type":["string","null"]},"pictureUrl":{"type":["string","null"]},"role":{"type":"string"},"reputationScore":{"type":"number"},"streakDays":{"type":"integer","minimum":0},"acceptedSolutions":{"type":"integer","minimum":0},"level":{"type":"integer","minimum":1}}},{"type":"object","required":["aboutMe","headline","linkedinUrl","githubUrl","postsCount","publicPostsCount","joinedAt","followerCount","followingCount"],"properties":{"aboutMe":{"type":["string","null"]},"headline":{"type":["string","null"]},"linkedinUrl":{"type":["string","null"]},"githubUrl":{"type":["string","null"]},"postsCount":{"type":"integer","minimum":0},"publicPostsCount":{"type":"integer","minimum":0,"description":"Published posts in PUBLIC circles only — what an anonymous caller can see."},"joinedAt":{"type":"string","format":"date-time"},"followerCount":{"type":"integer","minimum":0},"followingCount":{"type":"integer","minimum":0},"levelInfo":{"type":"object","required":["level","name","nextLevel","pointsToNext","progressPercent"],"properties":{"level":{"type":"integer","minimum":1},"name":{"type":"string"},"nextLevel":{"type":["object","null"],"properties":{"level":{"type":"integer"},"name":{"type":"string"},"minScore":{"type":"number"}}},"pointsToNext":{"type":["number","null"]},"progressPercent":{"type":"number","minimum":0,"maximum":100}}}}}]},"LeaderboardEntry":{"type":"object","required":["rank","user","score"],"properties":{"rank":{"type":"integer","minimum":1},"user":{"type":"object","required":["id","username","userslug","fullName","pictureUrl","role","reputationScore","streakDays","acceptedSolutions","level"],"properties":{"id":{"type":"string","format":"uuid"},"username":{"type":"string"},"userslug":{"type":"string"},"fullName":{"type":["string","null"]},"pictureUrl":{"type":["string","null"]},"role":{"type":"string"},"reputationScore":{"type":"number"},"streakDays":{"type":"integer","minimum":0},"acceptedSolutions":{"type":"integer","minimum":0},"level":{"type":"integer","minimum":1}}},"score":{"type":"number"}}},"SearchResult":{"type":"object","required":["id","title","slug","groupSlug"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"slug":{"type":"string"},"groupSlug":{"type":"string"},"excerpt":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}},"securitySchemes":{"operatorStackOAuth":{"type":"oauth2","description":"OAuth 2.1 with mandatory PKCE (S256) and RFC 7591 dynamic client registration. Granted scopes are the intersection of what the client requests and what it registered for; community:read is always added, and community:admin is dropped unless the signed-in user is an admin — re-checked against the database on every admin call.","flows":{"authorizationCode":{"authorizationUrl":"https://operator.promptmetrics.dev/oauth/authorize","tokenUrl":"https://operator.promptmetrics.dev/api/oauth/token","refreshUrl":"https://operator.promptmetrics.dev/api/oauth/token","scopes":{"community:read":"Read community posts, profiles, and leaderboards","community:write":"Create posts and comments, react, follow, and join circles","community:admin":"Admin: manage users, groups, badges, and moderation"}}}},"bearerToken":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"An access token issued by the flow above, sent in the Authorization header."}}}}