NATSのMCPサーバーでClaudeからPub/Subを操作する
非公式のmcp-natsを使い、SubjectやJetStreamストリームをClaudeから探索する手順と、認証方式ごとの使い分け・公式実装が存在しない点を扱います。
NATSのMCPサーバーとは何か
mcp-natsは、Go製のNATSメッセージングシステム向けMCPサーバーです。作者個人が開発しているコミュニティ実装です。NATS本体を開発するnats-ioorganizationのGitHubリポジトリにMCPサーバーはなく、mcp-natsはその一覧に含まれない個人のリポジトリです。README上も「NATS公式」とは書かれておらず、独立した第三者ツールとして配布されています。第三者レビューサービス「MCP Review」の認証(Certified)バッジは付いていますが、NATS.io自身の認定ではありません。
対象になるのは、Subject階層の探索・Stream(JetStreamの永続化されたメッセージ列)の状態確認・Key-Valueバケットの読み書き・Object Storeの操作です。どれも、NATSクライアントライブラリでコードを書かないと見えない情報です。READMEの機能一覧で「Read-only Operations」と付いているのはサーバー管理とStream操作の2群だけです。Key-Value・Object Store・Publish・アカウントバックアップは書き込みも含みます。
導入前に確認すること
- Go 1.25以上(ソースからビルドする場合)、またはDockerでコンテナイメージを使う方法
- 接続先のNATSサーバー(URLと、必要なら認証情報)
- Claude CodeまたはClaude Desktopなど、MCPクライアントとして動く環境
- JetStreamのStreamやKey-Valueバケットを扱う場合は、対象アカウントにその権限があること
stdioとHTTPのどちらで繋ぐか
mcp-natsの--transportはstdio・sse・streamable-httpの3種類で、フラグを省略するとstreamable-httpです。Claude Code側の--transportはstdio・sse・httpなので、同じ「HTTP」でも綴りが違います。
接続方式の選び方
stdio(Docker)
Claude CodeやClaude Desktopがコンテナを子プロセスとして起動します。資格情報は設定のenvで渡せるので、手元で試すときに手順が少なく済みます。
Streamable HTTP
mcp-natsを先に起動し、/mcpへURLで繋ぎます。Kubernetesに置いて複数人で共有する構成はこちらで、資格情報はサーバー側の環境変数に置きます。
Claude Desktopにstdioで接続する
READMEのCursor向けインストールリンクに埋め込まれた設定を、Claude Desktop形式に書き直すと次のようになります。
{
"mcpServers": {
"nats": {
"command": "docker",
"args": [
"run", "-i", "--rm", "--init",
"-e", "NATS_URL",
"-e", "NATS_NO_AUTHENTICATION",
"ghcr.io/sinadarbouy/mcp-nats:0.1.4",
"--transport", "stdio"
],
"env": {
"NATS_URL": "nats://host.docker.internal:4222",
"NATS_NO_AUTHENTICATION": "true"
}
}
}
}READMEのリンクではNATS_URLがnats://localhost:4222ですが、この設定はコンテナの中で動きます。コンテナから見たlocalhostはコンテナ自身なので、ホストで動くNATSには届きません。Docker Desktopのドキュメントには、ホストの内部IPに解決される名前としてhost.docker.internalが載っています。上の例はこれに置き換えてあります。NATSがコンテナや別ホストにあるなら、そのURLを入れます。
Claude Codeに登録する
登録コマンドはstdioとHTTPで形が変わります。まずclaude mcp add --helpの抜粋です(v2.1.289で実行)。
claude mcp add --helpUsage: claude mcp add [options] <name> <commandOrUrl> [args...]
# Add stdio server with environment variables:
claude mcp add my-server -e API_KEY=xxx -- npx my-mcp-server
-e, --env <env...> Set environment variables (e.g. -e KEY=value)
-s, --scope <scope> Configuration scope (local, user, or project)
(default: "local")
-t, --transport <transport> Transport type (stdio, sse, http). Defaults to
stdio if not specified.Claude Codeに登録するまで
- 1
接続方式を決める
手元で試すだけならstdio、共有サーバーならHTTPです。
- 2
stdioならコンテナごと登録する
Claude Codeの
-eは、コンテナを起動するコマンドに渡す環境変数です。Docker側の-e NATS_URLが、それを中へ引き継ぎます。claude mcp add --scope project nats \ -e NATS_URL=nats://host.docker.internal:4222 \ -e NATS_NO_AUTHENTICATION=true \ -- docker run -i --rm --init \ -e NATS_URL -e NATS_NO_AUTHENTICATION \ ghcr.io/sinadarbouy/mcp-nats:0.1.4 --transport stdio - 3
HTTPならURLだけ登録する
mcp-natsを
--transportなしで起動し、待ち受け先の/mcpを指定します。既定のアドレスは0.0.0.0:8000です。claude mcp add --transport http --scope project nats http://localhost:8000/mcp
どちらのコマンドも、実行するとプロジェクトの.mcp.jsonに書き出されます。HTTPの場合は次の形です。
{
"mcpServers": {
"nats": {
"type": "http",
"url": "http://localhost:8000/mcp"
}
}
}stdioの場合はtypeがstdioで、commandにdocker、argsにコンテナの引数、envに-eで渡した2つの値が入ります。
READMEのJSONをそのまま貼ると読み込まれない
READMEのCursor向けの設定例は、urlだけでtypeがありません。Claude Codeのドキュメントでは、urlがあってtypeがないJSONエントリは設定エラーです。typeがないエントリはstdioサーバーとして読まれるためで、そのサーバーは読み込まれずに飛ばされます。.mcp.jsonに手で書くときは、上の出力のように"type": "http"を付けます。
同じJSONをclaude mcp add-jsonに渡すと、次のように弾かれます(typeなしで実行)。
Invalid configuration: : Invalid inputenvを書いてもHTTPサーバーには届かない
READMEのJSON例には、urlとenvを並べたものもあります。Claude Codeはそのサーバーへ接続するだけで、起動済みのmcp-natsプロセスの環境変数は変えられません。資格情報は、mcp-natsを起動する側のコマンドで渡します。
NATS_URL=nats://localhost:4222 \
NATS_SYS_CREDS=<SYSアカウントcredsのBase64> \
NATS_A_CREDS=<Aアカウントcredsのbase64> \
mcp-nats --address 0.0.0.0:8000NATS_<ACCOUNT>_CREDSには、.credsファイルを改行なしの1行でBase64にした文字列を入れます。Helmチャートのドキュメントには、次のエンコード方法が載っています。
# macOS(BSD base64)
base64 -i a.creds | tr -d '\n'
# Linux(GNU coreutils)
base64 -w 0 a.creds3つの認証方式をどう使い分けるか
接続認証は3種類あり、環境の性質で選びます。
認証方式の選び分け
資格情報(既定)
NATS_<ACCOUNT>_CREDSにBase64の.credsを渡します。全ツール呼び出しにaccount_nameが必要で、複数アカウントを持つ本番運用向けです。ユーザー名とパスワード
NATS_USERとNATS_PASSWORD、または--userと--passwordで渡します。NATS_USERにはトークンも入れられます。単純な認証設定のサーバー向けです。匿名接続
NATS_NO_AUTHENTICATION=trueまたは--no-authenticationで有効になります。ローカル開発や検証用サーバー向けです。
最初のバージョンは資格情報方式しか持たず、すべてのツールがaccount_nameを要求していました。GitHubのissue 1には、認証なしのローカルNATSに繋ぎたい利用者の質問が残っています。匿名接続とユーザー名/パスワードは、その後のプルリクエスト(2番)で加わりました。古い設定例にaccount_nameが必須と書かれていても、方式を変えれば不要になります。
資格情報方式でのツール呼び出しは、リポジトリのstdioテスト手順に例があります。「Aアカウントにダミーメッセージを発行して」と頼むと、次の引数でツールが呼ばれ、結果が返ります。
{
"account_name": "A",
"subject": "test.message",
"body": "Hello from test message!"
}Published 1 message(s) to test.message読み取り専用で動かす
mcp-natsは、何も指定しなければPublish・Key-Value書き込み・Object Store書き込み・アカウントのバックアップと復元のツールをすべて登録します。READMEの本文は読み取り専用を強調していますが、サーバーの既定は書き込み可能です。
書き込みを外すには--read-onlyを付けるか、環境変数MCP_NATS_READ_ONLYを1・true・yesのいずれかにします。この指定をすると、次のツールがツール一覧に出なくなります。
- Publish:
publish - Key-Value:
kv_add・kv_put・kv_create・kv_update・kv_del・kv_purge・kv_compact - Object Store:
object_add・object_put・object_del・object_seal - アカウント:
account_backup・account_restore
起動時のログにRead-only mode enabled; mutating tools omittedと出ます。このフラグはREADMEの設定一覧にはなく、取り込まれたプルリクエスト(5番)の説明にあります。本番相当のNATSに繋ぐ最初の1回は、このフラグ付きで中身を眺めるだけにとどめる使い方ができます。
Subject階層の探索とJetStreamの確認
NATSはトピックにあたる概念を「Subject」と呼びます。mcp-natsはStreamのSubject確認とメッセージ閲覧、JetStream(NATSの永続化・再送機能)の状態確認を別のツールとして持ちます。たとえば次のように頼めます。
- 「
ORDERSストリームの保持ポリシーと現在のメッセージ数を教えて」 - 「
configバケットのfeature-flagキーを見て、最後に更新されたのはいつ?」 - 「サーバーのRTT(往復遅延時間)を測定して」
- 「Aアカウントの接続数のレポートを出して」
Object StoreとKey-Valueのバケットには、作成・削除・Watch(変更の監視)のツールがあります。Publishは非同期発行にも対応します。書き込みは本物のブローカーに届くので、匿名接続や共有トークンのまま本番Subjectに向けるのは避けるほうが安全です。
アカウント運用向けには、接続数と統計のレポート生成、アカウント状態のバックアップと復元、TLS接続先のサーバー証明書チェーンの検査があります。複数アカウントを1つのクラスタで運用しているなら、account_nameを切り替えるだけで同じ依頼を繰り返せます。
インストールと署名の検証
Goのツールチェーンがあれば1コマンドで入ります。
go install github.com/sinadarbouy/mcp-nats/cmd/mcp-nats@latestDockerイメージのタグ付きリリースは、Sigstore Cosignで署名されると説明されています。検証コマンドは次のとおりです。
cosign verify ghcr.io/sinadarbouy/mcp-nats:0.1.4 \
--certificate-identity-regexp 'https://github.com/sinadarbouy/mcp-nats/.github/workflows/(release\.yml@refs/tags/v.*|sign-image\.yml@refs/heads/main)' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com0.1.4は2026年4月1日に公開されたリリースです。署名を付けるコミットは2026年9月2日に入りました。READMEには、署名追加より前に公開されたタグはActionsのsign-imageから後で署名できるとあります。0.1.4の検証が通らないときは、署名前に公開されたタグが未署名のままかもしれません。
Kubernetesで運用する場合
Helmチャートが同梱されており、リポジトリ内のパスからも、OCIレジストリ経由でもインストールできます。
helm install mcp-nats oci://ghcr.io/sinadarbouy/charts/mcp-nats \
--version "0.1.4" --namespace mcp-nats --create-namespaceチャートの必要条件はKubernetes 1.25以上とHelm 3で、OCIの取得にはHelm 3.8以上が要ります。値の主なキーは次のとおりです。
| 値のキー | 設定される内容 |
|---|---|
nats.url / nats.noAuthentication | 設定される内容NATS_URLとNATS_NO_AUTHENTICATION |
auth.existingSecret | 設定される内容ユーザー名/パスワードを入れたSecret |
auth.extraSecretEnv | 設定される内容NATS_SYS_CREDSのような資格情報をSecretから環境変数へ |
server.transport / server.endpointPath | 設定される内容既定はstreamable-httpと/mcp(ポート8000) |
HTTPトランスポートでは3つのヘルスエンドポイントが使えます。/livezはプロセスの生存だけを見ます。/readyzはNATS_URLへのTCP到達性まで見ます。/healthzは/livezと同等の互換エイリアスです。チャートはstartupProbeとlivenessProbeを/livez、readinessProbeを/readyzに割り当てています。
HashiCorp Vault Agent Injectorで資格情報を注入する構成例もあります。commandを自分で指定した場合、チャートは既定の--transportと--addressを足さないので、起動コマンドにその指定を含めます。ルートファイルシステムを読み取り専用にしても、資格情報の一時ファイル用に/tmpのemptyDirが既定で付きます。
よくあるつまずき
- livenessに
/readyzを割り当てる: NATSの一時的な不調でPodごと再起動されます。逆に両方を/livezにすると、NATS側の障害がreadinessに映りません --sse-addressを新規設定で使う:--addressの非推奨エイリアスです
まとめ
本番相当のNATSには--read-onlyと資格情報方式で繋ぎ、書き込みが要るときだけフラグを外す、という段階の踏み方ができます。
MCPの基礎はMCPとは何かにあります。claude mcp addのスコープや認証の詳細はClaude Code MCP設定ガイドです。Kubernetes上のMCPサーバーをClaudeから操作する場合はKubernetes MCPサーバーでClaudeからクラスタを操作するも参考になります。