mcpField
H
hn-mcp-server

hn-mcp-server

リモート
github.com/cyanheadsソーシャルメディア5今日更新
リポジトリ

hn-mcp-server について

Hacker Newsのフィード、議論、ユーザープロフィール、投稿を検索するMCPサーバーです。読者や調査担当者向けに、コメントツリー、プロフィール参照、Algoliaによる検索を提供します。

主な機能

  1. 016種類のHacker Newsフィード表示
  2. 02コメントスレッドのページ取得
  3. 03ユーザープロフィールと投稿の取得
  4. 04ストーリー、コメント、投票、求人の検索
  5. 05作者、日付、スコアによる絞り込み

活用シーン

  1. 01新着または人気の投稿を追跡
  2. 02長い議論を再開可能なページで読む
  3. 03キーワード、作者、日付で投稿を検索

MCP 対応

Hacker Newsのフィード、スレッド、プロフィール、コンテンツ検索用の4つのツールを提供します。MCPクライアントはSTDIOまたはStreamable HTTPで接続でき、ホスト型エンドポイントも利用できます。

設定

リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。

エンドポイントhttps://hn.caseyjhand.com/mcp
インストールコマンドをコピー
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。

パッケージ
npm@cyanheads/hn-mcp-server0.6.0

ツール

4
パラメーター型必須説明
feedenumはい取得する HN フィード。「top」には jobs が含まれます。「ask」と「show」は Ask HN / Show HN の投稿です。top | new | best | ask | show | jobs
countintegerいいえ返す投稿数。数が多いほど時間がかかります。
offsetintegerいいえフィードの先頭からスキップする投稿数。ページネーションには count と併用します。

詳細

@cyanheads/hn-mcp-server

MCP 経由で Hacker News のフィード、スレッド、ユーザープロフィールを全文検索とともに閲覧できます。STDIO または Streamable HTTP に対応しています。

4 つのツール

Version License Docker MCP SDK npm TypeScript Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework

公開ホストサーバー: https://hn.caseyjhand.com/mcp


概要

Hacker News のフィード、スレッド、プロフィールを利用できます。ランキング付きフィードの閲覧、コメントスレッド全体の読み込み、ユーザーの検索に加え、キーワード、投稿者、日付、スコアでストーリー、コメント、投票、求人を検索できます。

ツール
ツール説明
hn_get_storiesHN フィード(top、new、best、ask、show、jobs)から、タイトル、URL、スコア、投稿者、コメント数とともにストーリーを取得します
hn_get_threadアイテムとそのコメントツリーをスレッド形式のディスカッションとして取得します。深さとコメント数を指定でき、長いスレッドをページごとに取得するカーソルにも対応しています
hn_get_userカルマ、自己紹介、必要に応じて解決済み投稿のページを含むユーザープロフィールを取得します
hn_search_contentAlgolia を利用して、キーワード、フィルターのみ、またはその両方でストーリー、コメント、投票、求人を検索します。種類、投稿者、親ストーリー、日付範囲、最低ポイントで絞り込めます

機能リファレンス

hn_get_stories ツール
  • 6 種類のフィード:top、new、best、ask、show、jobs。ページネーションには count(デフォルトは 30)と offset を指定します。1 回の呼び出しで取得できるストーリーは最大 100 件です。count が 1,000 までの場合、100 件ずつ取得し、次の offset を示す notice が返されます
  • id、type、title、url、domain、score、author、timestamp、コメント数、本文テキストを返します。HN から提供されないフィールドは、null ではなく省略されます
  • 拡張情報では total、offset、hasMore が報告されます。ストーリーが残っている場合は truncated が設定され、次の offset を示す notice が返されます。また、空のページ(空のフィード、末尾を超えた offset、またはページ内のすべての項目が削除済み/フラグ付き)については notice で説明されます。最終ページには切り捨て情報は付きません
  • 再試行後も取得に失敗した項目は failedIds に列挙され、再試行を示す notice が付けられます。ページ内のすべての項目の取得に失敗した場合は、空のリストではなく、分類された上流エラーが返されます

hn_get_thread ツール
  • itemId に加え、depth(デフォルトは 3。0 を指定するとコメントなしで項目を返します)と maxComments(デフォルトは 50。全階層を通じた 1 回のレスポンスの上限)を指定できます。コメントの間でのみ切り分ける固定 64,000 バイトのテキスト上限も適用されます。1 回の呼び出しで解決できるのは最大 10 階層、200 コメントです。depth が 100 までの場合は 10 階層まで、maxComments が 1,000 までの場合は 200 件まで取得し、次に itemId として渡すコメント、または残りのコメントに到達する nextCursor を示す notice が返されます
  • HN の順位に沿って幅優先で探索します。上位にランクされたトップレベルコメントを先に解決し、その階層をすべて処理した後に返信を取得します
  • 中断した箇所から再開できます。maxComments、バイト上限、または上流のレート制限によってレスポンスが中断された場合は nextCursor が返されます。同じ itemId とともに cursor として渡すと、次に未取得のコメントから続行します。カーソルには未訪問のコメントそのものが含まれるため、返信の順位が変わっても位置がずれることはなく、サーバーはセッション状態を保持しません。このツールが発行していないカーソル、改変されたカーソル、または異なる itemId とともに渡されたカーソルは、invalid_cursor エラーになります
  • ルートには関連情報と状態が含まれます。コメントの場合は parent と storyId(そのコメントが属するストーリーまたは投票)、投票の選択肢の場合は poll、投票の場合は parts と解決済みの options(すべての階層におけるテキストと票数)、さらに deleted/dead マーカーが含まれます。content[] の見出しには種類が記されます。タイトル、Comment by <author>、Poll option by <author> on poll <id> のいずれかで、ルートが削除済みまたは無効であることも示されます
  • フラットなコメントリストには、ツリーを再構成するための depth/parentId に加え、childCount と、コメントの投稿者がスレッドのストーリーを投稿した本人である場合の isOp フラグが含まれます。コメントがルートの場合は、そのコメント自身の投稿者ではなく、storyId のストーリーの投稿者が対象です。無効または削除済みのコメントは省略されますが、その返信が有効であれば、正しい depth で返され、省略されたコメントを示す parentId が付けられます
  • truncated と truncationReason(count、size、rate_limited、または返信が深度制限より下にある場合の depth)は、未読のコメントが残っている場合にのみ設定されます。上限ちょうどでスレッド全体を取得できた場合を含め、最終ページには設定されません。notice では、探索中に省略された削除済み/無効のコメントと次の手順を報告します。次の手順はカーソル、より大きな depth、または itemId として渡すコメント ID です。深度制限によって返信が切り捨てられた省略コメントは、ID で示されます
  • 再試行後も取得に失敗したコメントと投票の選択肢は failedIds に列挙され、再試行を示す notice に ID が記載されます。取得に失敗したコメントは nextCursor に含まれるため、ページを再取得するときに再試行され、省略されることはありません。ルートの項目は引き続き返され、取得失敗が maxComments/depth の制限として扱われることはありません

hn_get_user tool
  • username は大文字と小文字を区別し、前後の空白は削除されます。includeSubmissions(デフォルトは false)を指定すると、最近の投稿を取得します。長い投稿履歴をページ分割するには、submissionCount(デフォルトは 10)と submissionOffset を使用します。1 回の呼び出しで取得できる投稿は最大 50 件です。submissionCount に 50 を超える値(最大 1,000)を指定した場合は 50 件を取得し、次の submissionOffset を示す notice が返されます
  • プロフィールには、カルマ、作成日、自己紹介文(HTML を除去済み)が含まれます。投稿には、削除済みまたは非表示のアイテムは含まれません
  • コメントの投稿には parent が、投票の選択肢の投稿には poll が含まれるため、どちらも回答対象へのリンクをたどれます
  • 取得結果には submissionOffset と次に送信するオフセットが含まれます。または、指定したオフセットが履歴の末尾を過ぎている場合は notice が返されます
  • 再試行後も取得に失敗した投稿は failedIds に一覧表示され、再試行について示す notice が返されます。対象範囲内のすべての投稿の取得に失敗した場合は、分類された上流エラーが返されます

hn_search_content ツール
  • フリーテキストのqueryに加え、tags(story/comment/poll/job/ask_hn/show_hn/front_page)、author(大文字と小文字を区別する完全一致のユーザー名)、storyId、dateRange、minPointsで絞り込めます。sortでは関連度順または日付順に並べ替え、count(デフォルトは30)とpageでページネーションを指定します。1回の呼び出しで取得できるのは最大50件です。countが1,000以下の場合、指定したページの先頭ヒットから始まる50件のページが返され、次に渡すcount: 50のページを示すnoticeが含まれます。pageが0以外で、その先頭ヒットが50件単位のページの先頭にならない場合は、count_page_unalignedエラーとなり、その位置から始まるcountとpageが示されます。また、そのcountが25未満の場合は、そのヒットを含む50件のページも示されます。
  • tags: "front_page"は現在のフロントページ(約30件のストーリー)を示し、過去のフロントページは対象外です。過去の期間を調べるには、tags: "story"とdateRange、minPointsを使用してください。
  • フィルターを設定すればqueryは省略できます。Ask HN、Show HN、投票、求人を単独で一覧表示するか、ストーリーのstoryIdとtags: "comment"を渡して、1つのスレッド内を検索できます。queryもフィルターも指定しない場合は、missing_query_or_filterエラーとなります。
  • ページについて議論されているかを確認するには、そのURLだけをqueryとして渡してください。検索前に先頭のhttp://、https://、またはwww.は削除されるため、どちらのスキームでも、またwww.の有無にかかわらず一致します。出力のqueryとnoticeには、検索に使用した内容が示されます。
  • dateRangeの範囲には、ISO 8601形式(YYYY、YYYY-MM、YYYY-MM-DD、またはオフセットを省略可能な日時)を指定します。UTCとして解釈され、両端は範囲に含まれません。空の範囲または順序が逆の範囲を指定すると、invalid_date_rangeエラーとなります。
  • minPointsはストーリーと投票に適用されます。コメントと求人にはポイントがないため、tags: "comment"または"job"と併用するとmin_points_unscored_typeエラーとなります。
  • view: "compact"を指定すると、本文テキストのフィールド2つ(text、highlights.text)が省略されます。これらは指定しない場合、長いコメントをヒットごとに2回繰り返します。本文を読むには、ヒットIDをhn_get_threadに渡してください。
  • 各ヒットには、Algoliaに記録されている場合、そのtype(story、comment、poll、pollopt、job)が含まれます。タグを指定しない検索では投票の選択肢も返されます。選択肢にはID、作成者、投票数、日付のみが含まれます。選択肢のテキストと投票内容を読むには、hn_get_threadを使用してください。投票のヒットにはstoryIdがなく、そのid自体が議論のルートです。
  • 求人の説明はtextとして返されますが、キーワード検索では検索対象になりません。
  • ハイライトのメタデータ(highlights.title、highlights.text、matchedWords)には、一致した語句とその位置が示されます。
  • エンリッチメントでは、適用されたcriteriaが返されます。各フィルター設定(前後の空白を除去したauthor、適用された排他的なUTCの範囲を秒単位で示すdateRange)に加え、デフォルト値を補完したsort、count、viewが含まれるため、保存した結果から何に答えるものかが分かります。
  • エンリッチメントでは、totalHits、page、実際に到達可能なtotalPagesが報告されます。広範なクエリではAlgoliaが提供できる件数を大幅に上回るヒットが報告されるため、totalPagesはtotalHitsから算出されません。totalHitsExact: falseはtotalHitsが推定値であることを示し、reachableHits: 1000は検索結果がAlgoliaの1,000件の上限を超えていることを示します。このような検索の最終ページには、上限と、残りを取得するために範囲を狭めたdateRangeが記載されたnoticeが含まれます。残りのページがある場合はtruncatedが設定され、次のpageがnoticeに示されます。最終ページを超えるページを指定すると、最後に有効なページ(上限を超えた場合はpage: 0)を示すnoticeが返されます。

特徴

@cyanheads/mcp-ts-core を基盤としており、stdio および Streamable HTTP トランスポート、差し替え可能な認証(none/jwt/oauth)、切り替え可能なストレージ(in-memory、filesystem、Supabase、Cloudflare KV/R2/D1)、オプションの OpenTelemetry トレーシングに対応した構造化ログを備えています。

HN 固有の機能:

  • 2 つの上流 API に対応:フィード、アイテム、ユーザーには HN の Firebase API、全文検索には Algolia の HN Search API を使用します
  • アイテム解決のための並行バッチ取得に対応し、並列度を設定できます(HN_CONCURRENCY_LIMIT)
  • HTML 本文をプレーンテキストに変換します。エンティティは一度だけデコードし、コードブロックはそのまま保持し、各リンクは完全な URL として一度だけ表示します。HTML ではないタイトルは、一部にエンティティを含む場合があるためデコードしますが、タグの除去は行いません
  • サーバーレベルの instructions を initialize 時に LLM クライアントへ転送します。アイテムの種類、ツール間での ID の再利用、大文字と小文字を区別するユーザー名、フィールドの欠落について説明します
  • API キーは不要です。どちらの上流 API も公開されています

エージェントに適した出力:

  • 部分的な失敗を適切に処理します。再試行後に取得に失敗したアイテムは、削除済み、非表示、または存在しないアイテムとは区別して、結果を黙って縮小するのではなく ID を failedIds で報告します。hn_get_thread は除外した削除済みおよび非表示のコメント数も集計します。また、アイテムがレート制限に達した場合は、残りの各アイテムに個別の再試行を繰り返すのではなく、バッチを停止します
  • 判別可能な出力コントラクトを提供します。型付きエラー理由(item_not_found、upstream_rate_limited、upstream_html、…)には理由ごとの復旧用テキストが付属します(レート制限時は上流の Retry-After を retryAfter として渡します)。さらに、すべてのコメントに depth/parentId のペアを含めるため、呼び出し側は入れ子の深さを推測せずにツリーを再構築できます
  • ページネーションの出所情報を提供します。ページ分割されたリストは使用したオフセット(offset、submissionOffset、page)と、次のオフセットの正確な値を notice で返します。hn_search_content は検索に使用した criteria も返し、hn_get_thread は自己完結型の nextCursor を返すため、エージェントは状態を再計算せずに処理を再開できます
  • 応答を整形します。HTML の除去、URL の正規化、ドメインの抽出によって上流のマークアップ由来のノイズを取り除きます。hn_search_content の view: "compact" は、通常なら検索結果の全文と重複する本文フィールド 2 つを省きます
  • 上流テキストをフェンス化します。content[] では本文の各行をブロック引用にし、タイトルは周囲の Markdown を崩す可能性がある箇所だけをエスケープするため、コメントがサーバー作成の行として扱われることはありません

はじめに

公開ホストインスタンス

公開インスタンスは https://hn.caseyjhand.com/mcp で利用できます。インストールは不要です。Streamable HTTP を介して、任意の MCP クライアントから接続してください:

{
  "mcpServers": {
    "hn-mcp-server": {
      "type": "streamable-http",
      "url": "https://hn.caseyjhand.com/mcp"
    }
  }
}
セルフホスト/ローカル環境

MCP クライアントの設定ファイルに追加してください:

{
  "mcpServers": {
    "hn-mcp-server": {
      "type": "stdio",
      "command": "bunx",
      "args": ["@cyanheads/hn-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

または npx を使用する場合(Bun は不要です):

{
  "mcpServers": {
    "hn-mcp-server": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@cyanheads/hn-mcp-server"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

または Docker を使用する場合:

{
  "mcpServers": {
    "hn-mcp-server": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "MCP_TRANSPORT_TYPE=stdio",
        "ghcr.io/cyanheads/hn-mcp-server:latest"
      ]
    }
  }
}
前提条件
インストール
git clone https://github.com/cyanheads/hn-mcp-server.git
cd hn-mcp-server
bun install

設定

設定はすべて環境変数で行います。API キーは不要です。HN API は公開されています。

変数説明デフォルト
HN_CONCURRENCY_LIMITアイテムのバッチ取得における最大同時 HTTP リクエスト数(整数、1~50)。10
MCP_TRANSPORT_TYPEトランスポート:stdio または http。stdio
MCP_HTTP_PORTHTTP サーバーのポート。3010
MCP_HTTP_HOSTHTTP サーバーのホスト。127.0.0.1
MCP_SESSION_MODEHTTP セッションの処理方法:stateful、stateless、または auto(stateful に解決されます)。ソースではサーバーに stateless が指定されており、公開されている Docker イメージと .env.example でも同様に設定されています。有効な値を環境変数で指定した場合は、引き続きそちらが優先されます。stateless
MCP_LOG_LEVELログレベル:debug、info、notice、warning、error。info
LOGS_DIRログファイルのディレクトリ(Node.js のみ)。<project-root>/logs

オプションの上書き設定の全リストは .env.example を参照してください。

サーバーの実行

ローカル開発
  • 開発モード(自動リロード):

    MCP_TRANSPORT_TYPE=stdio bun --watch src/index.ts   # stdio
    MCP_TRANSPORT_TYPE=http bun --watch src/index.ts    # HTTP
    
  • ビルドして実行:

    bun run rebuild
    bun run start:stdio   # or start:http
    
  • チェックとテストを実行:

    bun run devcheck   # Lint, format, typecheck, security
    bun run test       # Vitest test suite
    
Docker
docker build -t hn-mcp-server .
docker run --rm -p 3010:3010 hn-mcp-server

Dockerfile は、HTTP トランスポート、ステートレスセッションモード、/var/log/hn-mcp-server へのログ出力をデフォルトで設定します。OpenTelemetry のピア依存関係はデフォルトでインストールされます。省略するには、--build-arg OTEL_ENABLED=false を指定してビルドしてください。

プロジェクト構成

ディレクトリ用途
src/index.tsエントリーポイントの createApp()。ツールを登録し、HN サービスを初期化します。
src/config/サーバー固有の環境変数を Zod で解析・検証します。
src/mcp-server/tools/definitions/ツールの定義(*.tool.ts)。
src/services/hn/HN Firebase と Algolia API のクライアント、およびドメイン型。
tests/src/ に対応するユニットテストと統合テスト。

開発ガイド

開発ガイドラインとアーキテクチャ上のルールについては、CLAUDE.md を参照してください。概要は次のとおりです。

  • ハンドラーは例外をスローし、フレームワークが捕捉します。ツールのロジックでは try/catch を使用しません。
  • リクエスト単位のログには ctx.log を使用します。
  • すべてのツールは読み取り専用のため、認証スコープは不要です。
  • 外部 API の呼び出しはラップします。生データを検証し、ドメイン型に正規化してから、出力スキーマに沿って返します。不足しているフィールドを捏造してはいけません。

コントリビューション

問題の報告を歓迎します。提出前にチェックを実行してください。

bun run devcheck
bun run test

ライセンス

Apache-2.0 — 詳細は LICENSE を参照してください。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。