LAN越しにClaude認証を共有する
出発点
ある認証済みアカウントでClaude Codeを使っている。認証済みアカウントはトークン制限が緩く、実用的な長さのやり取りが可能だ。
ただし、このアカウントにログインできるのはホストPC上のClaude CLIだけ。機密上の理由から、別のPC(クライアントPC)でこのアカウントに直接ログインすることはできない。
一方で、2台のPCは同じLANにつながっている。ホストPCではClaude CLIがOAuth認証済みの状態で動く。クライアントPCにはVSCodeがあり、そこからClaude Codeを使いたい。
仕様書の「背景・目的」には、こう書いた。
- 認証済みアカウントのClaudeはトークン制限が緩い
- 認証済みアカウントをクライアントPCで直接ログインすることは機密上NG
- ホストPCを踏み台にして、認証・API呼び出しをホストPC上で完結させる
要するに、認証情報を動かせないなら、リクエストのほうを動かす。クライアントPCからプロンプトをホストPCに送り、ホストPC上でClaude CLIを叩き、結果を返す。認証情報はホストPCから一歩も出ない。
発想自体はシンプルだが、実現するには「VSCodeのAIアシスタント連携がどういうプロトコルで動いているのか」を理解する必要があった。
MCPとは何か
VSCode 1.115.0以降には、MCP(Model Context Protocol)クライアントが組み込まれている。MCPは、AIアシスタントと外部ツールをつなぐためのオープンプロトコルだ。
MCPの通信は JSON-RPC 2.0 をベースにしており、以下のようなメソッドで構成される。
initialize── ハンドシェイク。クライアントとサーバーが互いのcapabilities(対応機能)を交換するtools/list── サーバーが提供するツールの一覧をクライアントが取得するtools/call── クライアントがツールを実行する。引数を渡して結果を受け取る
トランスポート方式はいくつかあるが、VSCodeのMCPクライアントは「Streamable HTTP」をサポートしている。これは、単一のHTTPエンドポイント(POST /mcp)にJSON-RPCリクエストを送り、レスポンスをJSONまたはSSE(Server-Sent Events)で返すという方式だ。
これを知った時点で、構想が具体化した。
ホストPCにMCPサーバーを立てる。ask_claude というツールを1つだけ公開する。クライアントPCのVSCodeはそのMCPサーバーにLAN経由で接続し、ツールを呼ぶ。ホストPC側ではClaude CLIをサブプロセスとして起動し、出力をSSEでストリーミング返却する。
クライアントPC(VSCode MCP Client)
│
│ HTTP POST(JSON-RPC 2.0)/ SSE(同一LAN)
│ 例: http://192.168.x.x:8080/mcp
▼
ホストPC:MCPプロキシサーバー(Node.js)
│
│ 子プロセス(spawn)
▼
claude --print "..." --output-format stream-json
↑
認証済みアカウントでOAuth認証済み
MCPプロトコルに準拠することで、VSCode側は「リモートにあるMCPサーバーに接続している」としか認識しない。特別なクライアント実装は不要で、VSCodeの標準的なMCP接続設定(.vscode/mcp.json)にURLを書くだけで済む。
設計方針を決める
プロキシサーバーを claudeway と名付けた。名前の意図としては Claude + gateway ── Claude AIへの通り道だ。
実装に入る前に、いくつかの設計方針を決めた。
外部依存ゼロ
Node.jsの標準ライブラリだけで実装する。使うモジュールは http と child_process の2つ。
Express や Fastify といったフレームワークは使わない。MCPサーバーが受け付けるエンドポイントは POST /mcp、GET /mcp、GET /health の3つだけであり、ルーティングの複雑さはほぼない。LAN内で動く個人ツールに依存ツリーを持ち込むメリットはなく、むしろ node src/server.js 一発で起動できることのほうが価値がある。
実際、最終的な package.json に dependencies フィールドは存在しない。テストも node:test と node:assert で書いており、devDependencies もゼロだ。
単機能
公開するMCPツールは ask_claude の1つだけ。プロンプト文字列を受け取り、Claudeの回答テキストを返す。
仕様書のツール定義はこうなっている。
{
"name": "ask_claude",
"description": "ホストPCのClaude CLIを通じてプロンプトを実行し、結果を返す",
"inputSchema": {
"type": "object",
"properties": {
"prompt": {
"type": "string",
"description": "Claudeに送信するプロンプト",
"maxLength": 100000
}
},
"required": ["prompt"]
}
}
ファイル操作、コード実行、コンテキスト管理といった機能はスコープ外。プロキシが扱うのはテキストの入出力だけだ。機能を絞ることはセキュリティの簡素化にも直結する。
LAN前提の割り切り
認証機構は持たない。HTTPS化もしない。IPホワイトリストも実装しない。「同じLANに接続している=信頼できる」という前提で設計した。
README にも仕様書にも「LAN内専用、インターネットには絶対に公開しない」と明記している。この割り切りがあるからこそ、実装をシンプルに保てる。セキュリティ上の考慮は「信頼境界をLANの内側に限定する」ことで対処する設計だ。
ストリーミング対応
Claude CLIには --output-format stream-json というオプションがある。これを指定すると、回答がNDJSON(1行1JSONオブジェクト)形式でストリーミング出力される。
このストリーミング出力をそのままSSE経由でクライアントに流せば、VSCode上でClaudeの回答がリアルタイムに表示される。回答全文の生成を待ってから一括返却するよりも、ユーザー体験は格段に良い。
ただし、実際に --output-format stream-json を試してみると、--verbose フラグも同時に指定しないとエラーになることがわかった(CLI バージョン 2.1.100での検証結果)。このような「ドキュメントに書かれていない挙動」は、事前に検証しておかないと実装時にハマる。CLIの出力スキーマの検証結果は docs/verify-cli-results.md に記録した。
同時リクエスト制限
tools/call(=Claude CLI呼び出し)は同時に1件だけ受け付ける。2件目以降は即座にJSON-RPCエラー(-32000 Server busy)を返す。
個人利用のプロキシであり、マルチユーザー対応は不要だ。Claude CLIの同時実行を避けることで、リソース管理の複雑さを排除した。
技術スタック
最終的な構成を一覧にするとこうなる。
| レイヤー | 技術 | 補足 |
|---|---|---|
| ランタイム | Node.js v18+ | engines フィールドで明示 |
| HTTP サーバー | node:http |
標準ライブラリ |
| プロセス管理 | node:child_process(spawn) |
shell: false でコマンドインジェクション防止 |
| プロトコル | JSON-RPC 2.0 over Streamable HTTP | MCP仕様 2025-11-25 準拠 |
| ストリーミング | Server-Sent Events (SSE) | keepalive 30秒間隔 |
| CLI連携 | claude --print --output-format stream-json --verbose |
--verbose は必須 |
| テスト | node:test + node:assert |
標準ライブラリ。39テスト |
| 外部依存 | なし | dependencies / devDependencies ともにゼロ |
開発の進め方
このプロジェクトは、Claude Code自身をペアプログラマーとして使いながら開発した。仕様策定、コードレビュー、テスト設計といった工程を、Claude Codeのエージェント機能を活用して進めた。
開発はすべて2026年4月11日の1日で行っている。最初のコミットが14:04(JST)、v1.0.0のリリース準備が完了したのが翌日の0:07。約10時間で仕様策定から実装・テスト・LAN実機検証・公開準備まで完了した。コミット数は29。
大まかな流れはこうだった。
- 仕様策定 ── MCPプロトコルの要件、CLI連携の方式、エラーハンドリング方針をまとめた仕様書を作成
- 実装 ── 仕様に基づいて
src/server.jsを実装(最終的に約800行) - レビュー・バグ修正 ── レビューで2件のバグを発見・修正(SSEハンドリング関連)
- テスト追加 ── 39のテストケースを作成。MCPプロトコル準拠、入力バリデーション、エラーパス、エッジケースをカバー
- 仕様・実装・テストの三点突合 ── 仕様書と実装とテストの間に12件のギャップを発見し、すべて解消
- 実機検証 ── ローカルおよびLAN越しの実機で動作確認(VSCode 1.115.0、Windows 11 Pro)
- 公開準備 ── 用語の中立化、IPアドレスの匿名化、英語READMEの追加、MITライセンスの付与
次回は、MCPプロトコルの実装で具体的にどう躓き、どう解決したかについて書く。
claudeway は GitHub で公開しています(MIT License)。


コメント