{"openapi":"3.1.0","info":{"title":"hackernews-mcp","version":"2.0.0","description":"The HTTP API of a Hacker News resource server. It is a sibling of the MCP endpoint at /mcp rather than a translation of it: both read the same data, and each is shaped for its own kind of caller."},"servers":[{"url":"https://hackernews.mcp.cedricm.dev"}],"paths":{"/api/v1/stories":{"get":{"operationId":"listStories","summary":"List stories from a feed","description":"A page of one Hacker News feed, in the site's own order. Article text is not included: that is a separate resource behind a separate scope.","tags":["stories"],"parameters":[{"name":"feed","in":"query","required":false,"description":"Which feed to read. Defaults to top.","schema":{"type":"string","enum":["top","new","best","ask","show","job"],"default":"top"}},{"name":"limit","in":"query","required":false,"description":"Stories per page, at most 30.","schema":{"type":"integer","minimum":1,"maximum":30,"default":10}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` from the previous page. Opaque, and only ever a value this API issued.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","title":"Story","properties":{"id":{"type":"integer"},"type":{"type":["string","null"],"enum":["story","comment","job","poll","pollopt",null]},"title":{"type":["string","null"]},"by":{"type":["string","null"]},"score":{"type":["integer","null"]},"comment_count":{"type":["integer","null"]},"posted_at":{"type":["string","null"],"format":"date-time"},"url":{"type":["string","null"],"format":"uri"},"text":{"type":["string","null"],"description":"The post body as markdown, for Ask HN and Show HN."},"discussion_url":{"type":"string","format":"uri"}},"required":["id","type","title","by","score","comment_count","posted_at","url","text","discussion_url"]}},"next_cursor":{"type":"string","description":"Pass as `cursor` for the next page. Absent when this is the last page."}},"required":["items"]}}}},"400":{"description":"The request was malformed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"No token, or a token this server did not accept. The WWW-Authenticate header names the issuer to get one from.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The token is valid but does not carry the hackernews:stories.read scope. The WWW-Authenticate header names it.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"security":[{"oauth2":["hackernews:stories.read"]}]}},"/api/v1/stories/{id}":{"get":{"operationId":"getStory","summary":"Get one story","description":"One item's metadata and, for an Ask HN or Show HN post, its body as markdown. `url` is the page it links to, which is what `/api/v1/articles` takes.","tags":["stories"],"parameters":[{"name":"id","in":"path","required":true,"description":"The Hacker News item id.","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","title":"Story","properties":{"id":{"type":"integer"},"type":{"type":["string","null"],"enum":["story","comment","job","poll","pollopt",null]},"title":{"type":["string","null"]},"by":{"type":["string","null"]},"score":{"type":["integer","null"]},"comment_count":{"type":["integer","null"]},"posted_at":{"type":["string","null"],"format":"date-time"},"url":{"type":["string","null"],"format":"uri"},"text":{"type":["string","null"],"description":"The post body as markdown, for Ask HN and Show HN."},"discussion_url":{"type":"string","format":"uri"}},"required":["id","type","title","by","score","comment_count","posted_at","url","text","discussion_url"]}}}},"400":{"description":"The request was malformed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"No token, or a token this server did not accept. The WWW-Authenticate header names the issuer to get one from.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The token is valid but does not carry the hackernews:stories.read scope. The WWW-Authenticate header names it.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"security":[{"oauth2":["hackernews:stories.read"]}]}},"/api/v1/stories/{id}/comments":{"get":{"operationId":"listComments","summary":"List a story's comment threads","description":"A page of TOP-LEVEL threads, each with its replies nested to `max_depth`. The page is over the roots because paginating a tree by node would mean nothing to a reader, and a story's replies already arrive in the site's ranking order.","tags":["stories"],"parameters":[{"name":"id","in":"path","required":true,"description":"The Hacker News item id.","schema":{"type":"integer","minimum":1}},{"name":"limit","in":"query","required":false,"description":"Top-level threads per page, at most 50.","schema":{"type":"integer","minimum":1,"maximum":50,"default":10}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` from the previous page. Opaque, and only ever a value this API issued.","schema":{"type":"string"}},{"name":"max_depth","in":"query","required":false,"description":"How deep to follow reply chains.","schema":{"type":"integer","minimum":1,"maximum":8,"default":3}},{"name":"max_comments","in":"query","required":false,"description":"Total comments fetched for this page, across every thread on it. The Hacker News API has no batch endpoint, so this is a subrequest budget rather than a preference.","schema":{"type":"integer","minimum":1,"maximum":200,"default":40}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$id":"urn:hackernews-mcp:schema:comment","type":"object","title":"Comment","properties":{"id":{"type":"integer"},"by":{"type":["string","null"]},"posted_at":{"type":["string","null"],"format":"date-time"},"text":{"type":["string","null"],"description":"The comment body as markdown."},"depth":{"type":"integer","description":"0 for a top-level comment."},"replies":{"type":"array","description":"Replies, nested to the requested max_depth.","items":{"$ref":"#"}}},"required":["id","by","posted_at","text","depth","replies"]}},"next_cursor":{"type":"string","description":"Pass as `cursor` for the next page. Absent when this is the last page."}},"required":["items"]}}}},"400":{"description":"The request was malformed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"No token, or a token this server did not accept. The WWW-Authenticate header names the issuer to get one from.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The token is valid but does not carry the hackernews:stories.read scope. The WWW-Authenticate header names it.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"security":[{"oauth2":["hackernews:stories.read"]}]}},"/api/v1/articles":{"get":{"operationId":"getArticle","summary":"Extract the readable text of a linked page","description":"Fetches the URL and reduces it to plain text. Answers 502 when the page cannot be read, which covers paywalls, PDFs, dead links and pages rendered entirely in the browser. Those are all routine on Hacker News rather than faults in this server.","tags":["articles"],"parameters":[{"name":"url","in":"query","required":true,"description":"The page to read, usually the `url` field of a story.","schema":{"type":"string","format":"uri"}},{"name":"max_chars","in":"query","required":false,"description":"How much text to return before truncating.","schema":{"type":"integer","minimum":200,"maximum":12000,"default":1500}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","title":"Article","properties":{"requested_url":{"type":"string","format":"uri"},"final_url":{"type":"string","format":"uri"},"text":{"type":"string"},"chars":{"type":"integer"},"truncated":{"type":"boolean"}},"required":["requested_url","final_url","text","chars","truncated"]}}}},"400":{"description":"The request was malformed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"No token, or a token this server did not accept. The WWW-Authenticate header names the issuer to get one from.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The token is valid but does not carry the hackernews:articles.read scope. The WWW-Authenticate header names it.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"security":[{"oauth2":["hackernews:articles.read"]}]}}},"components":{"schemas":{"Problem":{"type":"object","title":"Problem","description":"RFC 7807. Served as application/problem+json.","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["title","status"]}},"securitySchemes":{"oauth2":{"type":"oauth2","description":"Tokens come from the issuer below. A client that has none can discover the issuer from /.well-known/oauth-protected-resource, which is what lets a tool connect having been told nothing but this URL.","flows":{"authorizationCode":{"authorizationUrl":"https://auth.cedricm.dev/authorize","tokenUrl":"https://auth.cedricm.dev/token","refreshUrl":"https://auth.cedricm.dev/token","scopes":{"hackernews:stories.read":"Read stories, their metadata and their comment threads from the public Hacker News API.","hackernews:articles.read":"Fetch a page linked from Hacker News and return its readable text. This makes an outbound request to a site somebody submitted, which reading stories alone does not."}}}}}}}