Skip to main content
Glama
Riddhimaan-Senapati

unofficial-HackerNews-MCP-CLI

README.md
<h1 align="center">unofficial-HackerNews-MCP-CLI</h1>

<p align="center">
  An unofficial HackerNews MCP server and CLI. Reads the top, new, best, Ask, Show, and job story lists, individual items, threaded comments, and user profiles through one shared async client. Built with FastMCP and Typer.
</p>

<p align="center">
  <a href="https://pypi.org/project/hackernews-mcp-cli/"><img src="https://img.shields.io/pypi/v/hackernews-mcp-cli.svg?cacheSeconds=200" alt="PyPI version"></a>
  <a href="https://pypi.org/project/hackernews-mcp-cli/"><img src="https://img.shields.io/pypi/dm/hackernews-mcp-cli.svg?cacheSeconds=60" alt="PyPI downloads"></a>
  <a href="https://github.com/Riddhimaan-Senapati/unofficial-HackerNews-MCP-CLI/actions/workflows/ci.yml"><img src="https://github.com/Riddhimaan-Senapati/unofficial-HackerNews-MCP-CLI/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
  <a href="https://github.com/Riddhimaan-Senapati/unofficial-HackerNews-MCP-CLI/actions/workflows/release.yml"><img src="https://github.com/Riddhimaan-Senapati/unofficial-HackerNews-MCP-CLI/actions/workflows/release.yml/badge.svg" alt="Release workflow"></a>
  <a href="https://skills.sh/Riddhimaan-Senapati/unofficial-HackerNews-MCP-CLI"><img src="https://skills.sh/b/Riddhimaan-Senapati/unofficial-HackerNews-MCP-CLI" alt="skills.sh"></a>
  <a href="./LICENSE"><img src="https://img.shields.io/github/license/Riddhimaan-Senapati/unofficial-HackerNews-MCP-CLI.svg" alt="license"></a>
  <img src="https://img.shields.io/badge/python-3.10%2B-blue" alt="Python 3.10+">
</p>

<p align="center">
  <a href="#install">Install</a> •
  <a href="#cli">CLI</a> •
  <a href="#mcp-server">MCP server</a> •
  <a href="#skill">Skill</a> •
  <a href="./CONTRIBUTING.md">Contributing</a>
</p>

This project wraps the official [HackerNews API](https://github.com/HackerNews/API)
behind one shared async client and exposes it two ways:

- `hn`, a Typer CLI that renders Rich tables in the terminal.
- `hn-mcp`, a FastMCP server that exposes the same operations as MCP tools for
  Claude and other MCP clients.

The API is read-only, needs no authentication, and has no rate limit.

## Let your coding agent install it

You do not have to run the install commands yourself. Give this instruction to
the coding agent you already use:

```
Run curl -fsSL https://raw.githubusercontent.com/Riddhimaan-Senapati/unofficial-HackerNews-MCP-CLI/main/skills/install-hackernews/SKILL.md and follow the instructions in its output to install the HackerNews CLI.
```

That command fetches the
[`install-hackernews`](https://skills.sh/Riddhimaan-Senapati/unofficial-HackerNews-MCP-CLI/install-hackernews)
skill, which gives the agent each step.

If your agent supports the skills library, install the same skill with:

```
npx skills add Riddhimaan-Senapati/unofficial-HackerNews-MCP-CLI
```

## Install

Requires Python 3.10+ and [`uv`](https://docs.astral.sh/uv/).

```bash
uv sync                  # create .venv and install the locked dependencies
uv run hn stories top   # run the CLI in .venv
uv run hn-mcp           # run the MCP server in .venv
```

To install the published commands outside the project, use an isolated uv tool
environment:

```bash
uv tool install hackernews-mcp-cli
```

Upgrade an existing tool installation with:

```bash
uv tool upgrade hackernews-mcp-cli
```

The examples below use the installed commands. From a clone, prefix `hn` and
`hn-mcp` commands with `uv run`.

## CLI

```bash
hn stories top             # front-page (top) stories
hn stories top --limit 10  # -n 10
hn stories top --offset 30 --limit 10  # skip the first 30 stories
hn stories new             # newest stories
hn stories best            # best recent stories
hn stories ask             # latest Ask HN
hn stories show            # latest Show HN
hn stories job             # latest job postings

hn item 8863               # a single story, comment, job, or poll
hn comments 8863           # threaded comment tree (--depth, --limit, --offset)
hn user pg                 # a user's profile (case-sensitive name)

hn max-item                # id of the most recently created item
hn updates                 # recently changed items and profiles

hn --version               # print the installed version
```

Every command takes `--format` (`-f`): `table` (the default), `json`,
`markdown`, or `text`. Use `json` for scripting; `markdown` and `text` strip
HTML. Use `--json` as a shortcut for `--format json`. If you pass both options,
`--json` takes precedence. For the story lists, `--offset` plus `--limit` must
stay within the category's cap, 500 stories for top, new, and best, or 200 for
ask, show, and job.

```bash
hn stories top -n 5 --json | jq -r '.[] | "\(.title) (\(.url // .hn_url))"'
hn user pg --json | jq .karma
```

Run `hn --help` for the full command list, or `hn <command> --help` for that
command's options and examples.

## MCP server

The server uses FastMCP 4 and MCP SDK v2. It supports stdio and streamable
HTTP transports.

Run over stdio, the default transport for MCP clients:

```bash
hn-mcp
```

Or over HTTP:

```bash
hn-mcp --http --host 127.0.0.1 --port 8000
```

Register it with an MCP client such as Claude Desktop or Claude Code:

```json
{
  "mcpServers": {
    "hackernews": { "command": "hn-mcp" }
  }
}
```

### Tools

| Tool | Description |
|------|-------------|
| `get_stories(category, limit, offset, strip_html)` | A list of stories; `category` is one of `top`, `new`, `best`, `ask`, `show`, or `job` |
| `get_item(item_id, strip_html)` | A single story, comment, job, or poll |
| `get_items(item_ids, strip_html)` | A batch of items by id, in order, with missing ids dropped |
| `get_comments(item_id, max_depth, max_per_level, offset, strip_html)` | Threaded comment tree |
| `get_user(username, strip_html)` | A user's public profile |
| `get_max_item_id()` | id of the most recently created item |
| `get_updates()` | Items and profiles that changed most recently |

Every tool that returns items, comments, or users takes `strip_html` to return
plain text instead of HTML.

### Resources

The server also exposes read-only JSON at stable URIs: `hn://stories/{category}`,
`hn://item/{item_id}`, and `hn://user/{username}`.

### Prompts

- `daily_digest(category, limit)` asks the agent to summarize the day's stories.
- `thread_summary(item_id, max_depth)` asks the agent to summarize a comment
  thread.

## Skill

The repo ships two Agent Skills, published on
[skills.sh](https://skills.sh/):

- `skills/hackernews/SKILL.md` teaches an agent how and when to use the `hn` CLI
  and the `hn-mcp` MCP server.
- `skills/install-hackernews/SKILL.md` installs the package.

Install both with the skills CLI, or add the console scripts and let your agent
load them from this directory:

```bash
npx skills add Riddhimaan-Senapati/unofficial-HackerNews-MCP-CLI
```

The root [`skills.sh.json`](skills.sh.json) groups the two skills on the
skills.sh repo page.

## Project layout

```
src/hn/
  client.py   # shared async HackerNews API client (httpx)
  models.py   # Pydantic models + StoryCategory (endpoint, title, cap)
  server.py   # FastMCP server (hn-mcp)
  cli.py      # Typer CLI (hn)
skills/hackernews/SKILL.md
skills/install-hackernews/SKILL.md
tests/        # pytest + respx (mocked API)
```

### How it works

`client.py` owns every network call and bounds concurrency. `server.py` and
`cli.py` stay thin over it, so the CLI and the MCP tools behave identically.
`StoryCategory` in `models.py` is the single source of truth for the six story
lists: it holds a category's endpoint stem, display title, and cap. Add a
category or a model field there, not in each interface.

The client keeps a short in-process cache, about 60 seconds, for item, user, and
story responses. It mainly helps the long-lived MCP server; the CLI exits
between commands. `max_item` and `updates` are never cached.

Changing behavior also means updating the docs in the same change: README,
CONTRIBUTING, RELEASING, the source skills, and AGENTS.md. Only the maintainer
publishes a release, so follow RELEASING.md and push a tag only when asked.

Read [AGENTS.md](AGENTS.md) for the agent-facing rules, and
[CONTRIBUTING.md](CONTRIBUTING.md) for the contribution workflow.

## Development

```bash
uv run ruff check .          # lint
uv run ruff format --check . # formatting
uv run pytest                # test suite (API calls are mocked)
```

CI runs lint, formatting, and the test suite on Python 3.10 through 3.13 via
GitHub Actions. See [CONTRIBUTING.md](CONTRIBUTING.md) for the full workflow.

## License

MIT. See [LICENSE](LICENSE). This is an unofficial project and is not affiliated
with Hacker News or Y Combinator.

TDQS

A4.2/5.0

Scored across 7 tools

Disambiguation5/5

Each tool targets a distinct resource or access mode: single item, batch items, category stories, threaded comments, user profile, latest ID, and recent updates. There is no meaningful overlap that would cause an agent to select the wrong tool.

Naming Consistency5/5

All tool names follow the same get_* snake_case convention, with clear noun targets. Pluralization is used sensibly to distinguish batch endpoints from singular endpoints.

Tool Count5/5

Seven tools is well-scoped for a read-only Hacker News API client covering items, stories, comments, users, and metadata. Each tool adds distinct value without bloat.

Completeness5/5

The set covers the core Hacker News API surface: fetching items individually or in bulk, story categories, comment threads, user profiles, latest item ID, and recent updates. No significant dead ends or missing read operations are apparent.

Maintenance

ActivityNo data
ResponsivenessNo issues