esa-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@esa-mcp所属する全esa teamから「オンボーディング」を検索して、teamとURLを一覧にして"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
esa-mcp
複数の esa.io team(workspace)を Codex CLI から横断検索・閲覧する read-only MCP server。Node.js と公式 MCP SDK を使い、stdio で通信します。esa への通信は公式 API v1 の GET のみです。記事・コメントの作成、編集、削除は実装していません。
1. インストール
Node.js 22 以上と npm、Codex CLI が必要です。このリポジトリを取得し、ディレクトリ内で実行します。
npm ci
npm testビルド不要です。手動起動は npm start、MCP クライアントからの起動には node /absolute/path/esa-mcp/src/index.js を使います。stdio server のため単独起動時は入力待ちになります。stdout は MCP 通信専用です。
Related MCP server: Qiita MCP Server
2. ESA_ACCESS_TOKEN の設定
esa の https://<所属team>.esa.io/user/applications でアクセストークンを発行し、読み取り用の read scope と必要な team・カテゴリへのアクセスを許可します。横断対象は、その token から取得できる所属 team と記事に限られます。token のアクセスポリシーで制限された情報は取得できません。
macOS 標準の zsh では、次の入力プロンプトで token を設定できます(値は画面にもコマンド履歴にも残りません)。
read -rs 'ESA_ACCESS_TOKEN?esa access token: '
export ESA_ACCESS_TOKEN
printf '\n'bash の場合:
read -rsp 'esa access token: ' ESA_ACCESS_TOKEN
export ESA_ACCESS_TOKEN
printf '\n'同じシェルから Codex CLI を起動してください。 server は起動時の環境変数 ESA_ACCESS_TOKEN だけを読み取ります。.env の自動読み込みは行いません。token をソース、README、Codex 設定、コマンド引数に書き込む必要はありません。変更後は Codex/server を再起動します。
3. Codex CLI への登録
リポジトリのディレクトリ内で実行します。
codex mcp add esa -- node "$PWD/src/index.js"続いて ~/.codex/config.toml の生成された [mcp_servers.esa] に env_vars を追加します。最終形は以下です。args は実際の絶対パスに置き換え、同じテーブルを二重に追加しないでください。
[mcp_servers.esa]
command = "node"
args = ["/absolute/path/esa-mcp/src/index.js"]
env_vars = ["ESA_ACCESS_TOKEN"]
tool_timeout_sec = 120env_vars は Codex の親プロセスの環境変数を server に渡す指定で、token 値は設定に保存されません。--env ESA_ACCESS_TOKEN=... は値を設定に保存するため使いません。node が見つからない場合は command -v node の絶対パスを command に指定します。
codex mcp list
codex mcp get esa
codexCodex 内で /mcp を開き、esa と下記 5 tools を確認します。登録方法と環境変数転送は Codex 公式 MCP ドキュメント を参照してください。
4. 動作確認
認証情報も esa へのネットワーク接続も不要な確認:
npm test
npm run smokesmoke は実際に server を子プロセスで起動し、公式 MCP client で initialize → tools/list → tools/call を実行します。5 tools の公開、read-only annotations、token 未設定時のエラーを検証し、プロセスを終了します。npm test にはモック API を使った横断検索・ページ継続・キャッシュ・エラー・Markdown 保持・MCP 入力検証も含みます。
実際の token で所属 team の取得まで確認する場合:
npm run smoke -- --liveこの確認は ESA_ACCESS_TOKEN が必要です。成功時には所属 team 数だけを表示します。記事検索・全文・コメントは、下記の例を Codex に依頼して確認できます。
主なエラー:
エラー | 確認事項 |
| token を export したシェルから Codex を起動し、 |
HTTP 401 / 403 | token の有効性、read scope、所属 team、アクセスポリシー |
HTTP 404 | team のサブドメインと、その team 内の記事番号・閲覧権限 |
|
|
| 接続・タイムアウト。エラー原因の生データや token は出力しません |
5. Tools と使用例
Tool | 引数 | 内容 |
|
| 所属 team を全ページ取得。60 秒キャッシュ |
|
| esa 検索式で検索。team 未指定は全 team |
|
| 記事全文の Markdown とメタデータ |
|
| team ごとの更新日時降順の記事一覧 |
|
| 記事コメントの Markdown 本文、投稿者、日時、URL |
team は表示名や URL ではなく example.esa.io の example です。team と teams の同時指定や空の teams はエラーです。重複 team は一度だけ問い合わせます。query は空白のみを許可せず、esa API の q に渡します。
Codex に依頼する例:
「esa の所属 team を一覧にして」
「所属する全 esa team から『オンボーディング』を検索し、team と記事 URL を並べて」
「esa の alpha と beta の team で
category:開発 APIを検索して」「esa の alpha team の記事 #42 を全文読んで要約して」
「全 esa team の最近更新された記事を team ごとに 5 件ずつ見せて」
「alpha team の記事 #42 のコメントを読んで」
MCP tool の引数例(架空の team / 記事番号):
{ "query": "オンボーディング" }{ "query": "category:開発 API", "teams": ["alpha", "beta"], "per_page": 10 }{ "team": "alpha", "post_number": 42 }検索と最近の記事は results に team ごとのページを返します。各記事に team、post_number、title、category、updated_at、url、excerpt が含まれます。記事番号は team 内でのみ一意です。全文は読みやすい Markdown の text content と、body_md を含む structured content の両方で返し、省略しません。
Pagination と API request 数
page は既定 1、per_page は既定 20、最大 100 です。件数はteam ごとで、全 team を合わせた上限ではありません。記事・コメントは 1 回の呼び出しにつき各対象の 1 ページを返し、page、per_page、next_page、prev_page、total_count を保持します。has_more が true なら続きがあります。
続きは next_page がある team のみ、同じ query と per_page で呼び出します。例えば alpha の next_page: 2 に対して:
{ "query": "オンボーディング", "team": "alpha", "page": 2, "per_page": 20 }next_page: null になるまで続ければ全件を辿れます。コメントも同様です。team により次ページが異なる場合は個別に続行します。esa のページ番号方式のため、ページ取得中に記事が更新されると重複・欠落が生じ得ます。固定時点のスナップショットは保証しません。
team 一覧だけは
per_page=100と API のnext_pageで最後まで自動取得します。成功した一覧を 60 秒メモリキャッシュし、同時取得は共有します。所属変更はrefresh: trueで反映できます。記事一覧は対象 team 数だけの API 呼び出しです。team 指定時には所属一覧を取得しません。抜粋は一覧に含まれる本文の冒頭から最大 240 文字を作り、個別記事の追加取得はしません。
抜粋は空白をまとめた Markdown の冒頭です。検索語のハイライトではありません。検索・最近の記事は各 team 内で更新日時降順です。
API request は server 全体で直列化し、各リクエストは 15 秒でタイムアウトします。自動リトライはしません。429 または残りリクエスト数 0 を検出すると、応答ヘッダに基づく待機期限まで追加リクエストを抑止します(期限不明時は 60 秒)。
一部 team の取得失敗は
partial: trueと team ごとのerrorで返します。成功した結果は残ります。全対象失敗の場合は MCP のisErrorも true です。エラーを検索結果ゼロとして扱わないでください。team 数が多い場合は
teamsで分割すると応答時間と出力量を抑えられます。記事本文と token はディスクにキャッシュしません。
実装範囲と参考資料
通信先は https://api.esa.io/v1 に固定し、GET のみを使い、HTTP redirect は追跡しません。認証は Authorization header で送信します。MCP tool はすべて read-only として公開されます。記事内のリンクや命令を server が実行することはありません。
esa 公式 API v1: 認証、team、記事、コメント、pagination、rate limit
esa 記事の検索方法:
queryに使用する検索式
ファイル構成: src/esa-client.js が API・キャッシュ、src/server.js が tool 定義、src/index.js が stdio 起動、test/ がテスト、scripts/smoke.js が実プロセスの接続確認です。
License
MIT License — Copyright (c) 2026 Takumi Otagaki
Available Tools
5 toolsesa_get_postARead-onlyIdempotent
Read the full Markdown body of an esa post. Post numbers are only unique within a team.
| Name | Required | Description | Default |
|---|---|---|---|
| team | Yes | ||
| post_number | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint and idempotentHint already provided by annotations, the description adds a critical behavioral nuance: post numbers are only unique within a team, which is essential knowledge beyond the annotation layer.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the action, zero waste, and immediately conveys both purpose and a key constraint.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given annotations cover safety and idempotency, the description provides the needed scoping rule for post_number, though it could note that the team parameter is required and perhaps formats for other fields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and description text does not define either parameter in detail, but the statement about post number uniqueness within a team adds significant meaning to the post_number parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (read) and resource (full Markdown body of an esa post), clearly distinguishing this from siblings like esa_search_posts or esa_list_recent_posts which do not return full bodies.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this is the tool to use when you need the full body instead of a snippet or list, but it does not explicitly compare to alternatives like esa_search_posts or esa_list_recent_posts.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
esa_list_commentsARead-onlyIdempotent
Read a page of comments on a post, with Markdown bodies and next_page. Comments are ordered by update time descending.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | esa page number, starting at 1. Use next_page from the previous result. | |
| team | Yes | ||
| per_page | No | Results per team/page. Keep unchanged when following next_page. | |
| post_number | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive reads, so the safety bar is met; the description adds genuinely new behavior: comments are ordered by update time descending and the result carries a next_page cursor. That pagination and ordering detail is what an agent needs beyond the structured hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single efficient sentence that front-loads the action and return shape with no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description usefully discloses the return content (Markdown bodies, next_page) and ordering. It is adequate for a read-only list tool, with the only gap being the undocumented team/post_number semantics.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%: page and per_page are well documented in the schema (including 'use next_page from previous result'), while team and post_number are undocumented. The description does not compensate by explaining those two parameters, but it does reinforce the pagination contract. Baseline 3 fits.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (read comments on a post) and adds scope details (a page, Markdown bodies, next_page). It does not differentiate from siblings like esa_get_post, but the resource is distinct enough that confusion is unlikely.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no when-to-use guidance and names no alternatives among the sibling tools. It only states the ordering, which is informational rather than routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
esa_list_recent_postsARead-onlyIdempotent
List recently updated posts per team, newest first. Returns one page per team with next_page. Omit team/teams for all teams.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | esa page number, starting at 1. Use next_page from the previous result. | |
| team | No | esa team subdomain, e.g. docs. Mutually exclusive with teams. | |
| teams | No | Team subdomains. Omit both team and teams to query all accessible memberships. | |
| per_page | No | Results per team/page. Keep unchanged when following next_page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), so the bar is lower. The description adds genuinely non-structured behavioral detail: results are paginated per team and a next_page cursor is returned, which is not derivable from the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences with no filler, and the core purpose is front-loaded ahead of the pagination and default-scope notes. Nothing needs to be removed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description steps in to explain the return shape (one page per team plus next_page) and the default all-teams scope. That covers what an agent needs to invoke and follow up correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents page, per_page, team, and teams. The description's 'Omit team/teams for all teams' largely restates the schema's own note about querying all accessible memberships, so it adds little beyond the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List recently updated posts per team') plus ordering ('newest first'), which is enough to distinguish it from esa_get_post or esa_list_comments. It does not explicitly name a sibling such as esa_search_posts, so it stops short of full differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives one useful routing rule — 'Omit team/teams for all teams' — which tells the agent how to query broadly. However, it never states when to prefer this over esa_search_posts or other listing tools, so usage is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
esa_list_teamsARead-onlyIdempotent
List all teams accessible to the current esa user, following all pages. Cached for 60 seconds.
| Name | Required | Description | Default |
|---|---|---|---|
| refresh | No | Bypass the team membership cache. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld). The description adds genuinely new behavior: pagination is followed automatically ('following all pages') and results are cached for 60 seconds, which tells the agent staleness can occur.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the verb and resource, with the pagination and caching facts attached where they matter. Nothing superfluous.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter, no-required-params list tool with no output schema, the description covers scope, pagination, and caching. Only the shape of returned team objects is unspecified, which is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the refresh param is already documented as bypassing the cache. The description's 'Cached for 60 seconds' reinforces why that flag exists and what its effect is, adding slight value over the schema baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (teams), plus a precise scope: teams 'accessible to the current esa user'. This is unambiguous and cannot be confused with the post/comment siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The purpose implies the use case (enumerate the caller's teams), but there is no explicit when-to-use guidance, no exclusions, and no alternatives referenced. Since no sibling covers teams, ambiguity is low, but the description still leaves usage to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
esa_search_postsARead-onlyIdempotent
Search esa posts using esa search syntax. Returns one page per team, newest updated first, with excerpts and per-team next_page. team/teams omitted searches all teams. team and teams cannot be combined.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | esa page number, starting at 1. Use next_page from the previous result. | |
| team | No | esa team subdomain, e.g. docs. Mutually exclusive with teams. | |
| query | Yes | Required esa search expression, forwarded as q without rewriting. | |
| teams | No | Team subdomains. Omit both team and teams to query all accessible memberships. | |
| per_page | No | Results per team/page. Keep unchanged when following next_page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, open-world behavior, so the safety profile is covered. The description adds genuine value beyond them by disclosing the return shape (one page per team, newest updated first, excerpts, per-team next_page), which is not derivable from annotations or schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences with zero filler. The core purpose is front-loaded, followed by return shape and then the team/teams constraint, in the order an agent needs them.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the burden of explaining results and does so well (per-team pages, excerpts, next_page). The mutual-exclusion constraint is covered. The only gap is that the referenced 'esa search syntax' is not characterized at all, which an agent unfamiliar with esa must guess at.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents page, per_page, team, teams, and query semantics. The description restates the team/teams mutual exclusion and the omit-to-search-all behavior, which is useful but largely duplicative of the structured fields. Baseline 3 applies when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Search esa posts') plus scope ('using esa search syntax'), and adds the return shape (one page per team, newest updated first). It does not explicitly name siblings like esa_list_recent_posts or esa_get_post, so the agent must infer the distinction, but the 'search syntax' framing distinguishes it reasonably well.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives real usage constraints: 'team/teams omitted searches all teams' and 'team and teams cannot be combined.' However, it never says when to choose this over esa_list_recent_posts or esa_get_post, so the when-to-use guidance is only implied by the search-syntax framing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.0- First observed
esa_get_post - First observed
esa_list_comments - First observed
esa_list_recent_posts - First observed
esa_list_teams - First observed
esa_search_posts
TDQS
Scored across 5 tools
Each tool targets a distinct resource and action: listing teams, searching posts, getting a post, listing recent posts, and listing comments. There is no overlap in purpose, so an agent can easily select the correct tool.
All tool names follow a consistent pattern: the 'esa_' prefix followed by a snake_case verb_noun combination (list_teams, search_posts, get_post, list_recent_posts, list_comments). This is predictable and easy to parse.
Five tools is a well-scoped set for a focused read-only client of the esa API. Each tool covers a meaningful operation, and there are no redundant or filler tools.
The surface covers core read operations (teams, posts, comments, search) but has notable gaps: no way to list all posts in a team (only recent or search), no single comment retrieval, and no create/update/delete operations that are typical for managing esa content. These omissions could cause agent failures for common workflows.
Maintenance
Related MCP Connectors
Search Stack Exchange questions, fetch Q&A threads as markdown, look up tag FAQs and user profiles.
Search, read and create Linear issues, projects, teams and cycles.
Read spaces, collections, pages and content; search docs and manage GitBook organization spaces.
Search and save your coding work in a CoralSwarm ocean: sessions, decisions, meetings.
1
Related MCP Servers
- AlicenseBqualityCmaintenanceEnables interaction with esa.io's API through the Model Context Protocol, supporting article search and retrieval with a compliant MCP interface.727 npm37MIT
- FlicenseAqualityDmaintenanceEnables searching and browsing Qiita articles, including filtering by tags and users, retrieving comments, and accessing bookmarked articles. Supports both public Qiita and private Qiita Team instances.7-
- AlicenseNot gradedqualityFmaintenanceEnables interaction with esa.io team documentation including creating, reading, updating, and deleting posts, managing tags, and handling comments through natural language.24 npm2MIT

esa MCP Serverofficial
AlicenseAqualityAmaintenanceEnables AI assistants to interact with esa.io teams, including reading, creating, updating, and managing articles, comments, categories, and more.282,249 npm62MIT