Skip to main content
Glama

hn-mcp

An MCP server for Hacker News. Built against the 2026-07-28 protocol revision and MCP Python SDK v2.

Five read-only tools:

Tool

Does

list_stories

Browse a feed (top / new / best / ask / show / job)

get_story

One story, job or poll by id

get_discussion

A story plus its comment thread, flattened and capped

search_stories

Full-text and date-filtered search over all HN history

get_user

A user profile

Run it

uv sync
uv run mcp dev src/hn_mcp/server.py          # Inspector, stdio
uv run mcp run src/hn_mcp/server.py --transport streamable-http   # HTTP
uv run pytest                                 # 45 tests, no network

Related MCP server: HN-MCP

Architecture

server.py     MCP layer      tool schemas, annotations, response models
    |                        no I/O, no parsing
    v
hn_client.py  service layer  Firebase + Algolia, fan-out, BFS, caching
    |
    v
models.py     data layer     Story / Comment / User, normalization
cache.py                     TTL cache

Dependencies point one way only. models.py does not know MCP exists, which is why it can be tested without starting a server.

Design notes

Two upstreams, one vocabulary. Feeds, items and users come from HN's Firebase API; search comes from HN's Algolia index, because Firebase has no search endpoint at all. They name the same concepts differently (by vs author, score vs points, descendants vs num_comments), so both parse into the same models. The model never learns there were two APIs.

Server-side fan-out. Firebase returns id lists, so a 30-story feed is 31 requests. Doing that in the server costs one tool call; making the model walk the ids costs 31 round trips with raw JSON in context each time.

Comment trees are breadth-first. HN ranks kids by its own ordering, so breadth-first spends the comment budget on the highest-ranked comments across the whole thread instead of exhausting it inside one argument. Nesting is carried by an integer depth rather than nested objects, so the list stays valid wherever it is cut.

Truncation is reported, never silent. When caps bite, truncated is true and truncation_hint names the argument to raise. Each comment carries num_replies, so the model can tell "no replies" from "replies you were not shown" — a distinction it cannot otherwise make.

Errors are prompts. A failure says what went wrong, which tool to use instead, and hands back the id needed to recover. Asking get_story for a comment id returns the parent story's id rather than a validation error.

Constraints live in types. Literal feeds become schema enums; Field(ge=, le=) becomes minimum/maximum. The docstring explains what options mean; the type system enforces which are legal.

Stateless. The 2026-07-28 revision removed sessions, so the same code serves stdio and Streamable HTTP with no session plumbing. Any request can land on any instance.

Verified against live HN

search_stories and get_discussion have been run against the real API. Doing so found three bugs the fixtures could not:

  • Breadth-first traversal with only a total cap spent the entire comment budget on top-level comments and returned one reply out of forty. Real threads are far wider than they are deep. Fixed with max_top_level.

  • The truncation hint asserted a rule of thumb instead of measuring, and was wrong about which comments had hidden replies. It now counts them.

  • Per-comment truncation was computed and discarded, leaving a trailing ellipsis indistinguishable from the author's own. Now text_truncated.

tests/fake_hn.py carries a wide thread modelled on the real one so the first of those cannot regress.

Not done yet

  • list_stories, get_story and get_user have not been exercised against live HN, only against fixtures.

  • Never loaded into a host, so tool selection is untested: whether a model picks search_stories over list_stories unprompted is the real measure of the docstrings, and it has not been measured.

  • No rate limiting. Fine for stdio, needed before a public HTTP deployment.

  • search_stories only searches stories, not comments (tags is fixed).

Available Tools

5 tools
get_discussionA
Read-only

Read a Hacker News comment thread in one call.

Returns the story plus a flat list of comments ordered breadth-first: all top-level replies, then all of their replies, and so on. HN ranks kids by its own ordering, so breadth-first spends the comment budget on the highest-ranked comments across the whole thread rather than exhausting it inside one argument.

Nesting is carried by each comment's depth rather than by nested objects, so the list can be cut at any point and stay valid.

Popular threads are wide - often over a hundred top-level comments - so max_top_level bounds how many of them are opened. That is what leaves budget for replies: without it the comment cap is spent entirely on opening statements and no reply is ever reached. Lower it to read an argument in depth, raise it to survey opinions broadly.

Big threads will not fit. When anything is omitted, truncated is true and truncation_hint names which argument to raise and why. comments_with_hidden_replies counts how many returned comments have replies that were left out, and top_level_shown against top_level_total shows how much of the first level you are seeing.

Deleted and dead comments are skipped entirely.

Inputs: story_id (required), max_depth, max_comments, comment_chars, +1 more. Returns: A story with a flattened, capped slice of its comment tree.

get_storyA
Read-only

Fetch one Hacker News story, job or poll by id.

Use this when an id is already known - from list_stories, from search_stories, or from a news.ycombinator.com/item?id=N URL. Returns the story only; call get_discussion to read its comments.

Inputs: story_id (required). Returns: A story, job or poll - the unit an agent reasons about. Deliberately omits HN's…

get_userA
Read-only

Look up a Hacker News user profile.

Returns karma, account age, bio and submission count. Usernames are case-sensitive, and only accounts with public activity are exposed by HN's API.

This returns the profile, not the user's posts. To find what someone submitted, use search_stories.

Inputs: username (required). Returns: A Hacker News account.

list_storiesA
Read-only

Browse Hacker News story feeds.

Returns each story's title, score, author, comment count and links - enough to answer "what's on HN right now" in a single call.

Feeds: top front page, ranked by HN's algorithm. Also contains job posts new most recently submitted, unranked best highest-scoring stories of the last few days ask Ask HN text and discussion posts show Show HN project launches job YC portfolio job postings

top and new hold up to 500 ids; ask, show and job hold up to 200, so a large limit on those feeds returns fewer stories than requested.

Every story carries an id. Pass it to get_discussion to read comments - this tool returns no comment text.

Inputs: feed, limit, offset, min_score. Returns: A page of stories from a feed.

search_storiesA
Read-only

Full-text search across all of Hacker News history.

Use this for anything the feeds cannot answer: a topic, a company, a phrase, or anything older than the current front page. The feed tools only see what is on HN right now; this sees everything ever posted.

sort="relevance" is right for topic questions. sort="date" is right for "what is the latest on X", since the best match may be years old.

days_back filters by age, so days_back=30 with sort="date" answers "what has HN said about X recently".

Inputs: query (required), page, sort, limit, +1 more. Returns: Search hits from HN's Algolia index.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.5/5.0

    Scored across 5 tools

    Disambiguation5/5

    Each tool targets a distinct resource+action: search_stories is full-text history search, list_stories is live feeds, get_story is a single item by id, get_discussion is a comment thread, and get_user is a profile. The descriptions actively contrast the easily-confused pairs (search vs. feeds, story vs. discussion), so an agent can pick correctly without guessing.

    Naming Consistency5/5

    All five tools follow the same verb_noun snake_case pattern (search_stories, list_stories, get_story, get_discussion, get_user). The verbs also map cleanly onto intent: list for collections, search for queries, get for single lookups.

    Tool Count5/5

    Five tools is a tight, well-scoped surface for the Hacker News domain — search, browse, item, thread, user — with no filler or redundant variants. Each tool covers a workflow the others cannot answer.

    Completeness4/5

    Core lifecycle is covered: discovery via feeds/search, item retrieval, comment reading, and user lookup. The main gap is author-scoped browsing — get_user explicitly says to use search_stories for a user's submissions, but search_stories is documented only as text search, so per-user submission listing and single-comment/subthread fetch are workarounds rather than first-class operations.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      D
      maintenance
      Enables AI assistants to search, retrieve, and interact with HackerNews content including stories, comments, polls, and user information. Provides comprehensive access to all HackerNews API endpoints with 15 specialized tools for content discovery and analysis.
      15
      60 npm
      5
      MIT
    • A
      license
      A
      quality
      D
      maintenance
      Enables browsing Hacker News, searching discussions, analyzing users, and tracking tech trends with zero setup required—no API keys or authentication needed.
      5
      27 npm
      6
      MIT
    • F
      license
      A
      quality
      D
      maintenance
      Enables AI assistants to read and search Hacker News for top stories, comments, user profiles, and job listings using the Firebase and Algolia APIs. It facilitates natural language research into community discussions and technological trends across the HN platform.
      8
      -