- n8nの「Anthropic Chat Model」ノードはAPI課金前提ですが、認証情報のBase URL欄を差し替えるとバックエンドを自由に変えられます
- Claude Code CLI(
claude login済み)をAnthropic Messages API互換の小さな中継サーバーでラップし、エンドポイントを向けることで、サブスク(Pro/Max)契約のままn8nのAgentノードを動かしました
Claude Pro/Maxの利用規約は個人の対話利用が前提なので、自動化ツールからの恒常的な呼び出しは規約上グレーゾーンです。検証目的の小規模利用を想定しています。
背景
n8nでAI Agentワークフローを組むとき、Anthropicモデルを使うにはAPI課金(従量課金)のキーが必要になります。手元でサブスク(Pro/Max)契約を持っているのでワークフローの動作検証まではAPIキーを使わずに行いたい、というのが出発点でした。
n8nの「Anthropic Chat Model」ノードには、公式APIサーバーのURLを差し替えられるBase URLという欄があります。ここを差し替えるとノードもワークフロー構成も変えずにバックエンドを変更できます。
全体構成
[claude-proxyコンテナ] --- 共有Dockerネットワーク(claude-net) --- [n8nコンテナ]
Node.js + Express 素のn8nio/n8n:latest(無改造)
claude CLI(サブスクログイン済み) Anthropic Chat Modelノードの
POST /v1/messages, GET /v1/models Base URLを http://claude-proxy:4141 に設定
claude-proxyコンテナがAnthropic Messages APIの顔をした窓口になり、裏側ではclaude -p(Claude Code CLI)を叩いて応答を返します。
前提
- Docker Desktopがインストール・起動済みであること
- Claude Pro / Maxのサブスクアカウントを持っていること
手順1: n8nコンテナ
すでにn8nを動かしている場合は、あとでclaude-netネットワークに参加させます。
docker network create claude-net
docker run -d --name n8n \
--network claude-net \
-p 5678:5678 \
-v "$HOME/docker/n8n_data:/home/node/.n8n" \
n8nio/n8n:latest
手順2: 中継サーバー(claude-proxy)
Dockerfile
FROM node:22-alpine
RUN npm install -g @anthropic-ai/claude-code
WORKDIR /app
COPY package.json server.js ./
RUN npm install --omit=dev
EXPOSE 4141
CMD ["node", "server.js"]
server.js(要点だけ)
Anthropic形式のmessages配列を1本のプロンプト文字列に平坦化してclaude -pに渡し、結果をAnthropic Messages APIのレスポンス形式に整形して返します。
const express = require('express');
const { execFile } = require('child_process');
const crypto = require('crypto');
const app = express();
app.use(express.json({ limit: '10mb' }));
function flattenMessages(messages) {
return messages
.map((m) => `${m.role === 'assistant' ? 'Assistant' : 'User'}: ${
typeof m.content === 'string' ? m.content : JSON.stringify(m.content)
}`)
.join('\n\n');
}
// n8nの「Test connection」ボタン用エンドポイント
app.get('/v1/models', (req, res) => {
res.json({ data: [{ type: 'model', id: 'claude-proxy' }], has_more: false });
});
app.post('/v1/messages', async (req, res) => {
const { model, messages, system } = req.body;
const prompt = flattenMessages(messages || []);
const args = ['-p', prompt, '--output-format', 'json'];
if (system) args.push('--system-prompt', system);
execFile('claude', args, { maxBuffer: 1024 * 1024 * 32 }, (err, stdout) => {
if (err && !stdout) return res.status(500).json({ type: 'error', error: { message: err.message } });
const cli = JSON.parse(stdout);
res.json({
id: `msg_${crypto.randomUUID()}`,
type: 'message',
role: 'assistant',
model: model || 'claude-proxy',
content: [{ type: 'text', text: cli.result }],
stop_reason: 'end_turn',
usage: { input_tokens: cli.usage?.input_tokens ?? 0, output_tokens: cli.usage?.output_tokens ?? 0 },
});
});
});
app.listen(4141, () => console.log('claude-proxy listening on 4141'));
GET /v1/modelsを用意しておく必要があります。n8nの資格情報テスト(Test connection)はここを叩くので、無いと「Not Found」で失敗します。claude -p --output-format jsonの結果をAnthropicレスポンス風に包み直せば、n8n側からAPIとして利用できます。
起動
docker build -t claude-proxy .
docker run -d --name claude-proxy --network claude-net -p 127.0.0.1:4141:4141 claude-proxy
ログイン
コンテナ単体でサブスク認証を持たせます。ここだけは対話操作が必要です。
docker exec -it claude-proxy claude login
表示された認証用URLをコピーして改行を取り除いた上でブラウザに貼り付けて認証します。
手順3: n8n側の設定と確認
疎通確認
curl -s http://localhost:4141/v1/messages -H 'content-type: application/json' \
-d '{"model":"claude-3-5-sonnet","messages":[{"role":"user","content":"こんにちは"}]}'
Anthropic形式のJSONが返ってくればOKです。
n8nのノード設定
- n8nキャンバス上に「Anthropic Chat Model」ノードを配置します
- 認証情報を新規作成します
- API Key: ダミー文字列でかまいません(例:dummy-key)
- Base URL:
http://claude-proxy:4141
- 保存して「Connection tested successfully」が出れば設定完了です
- Chat Model系のノードに繋いで実行し、応答が返れば完成です
Tool呼び出し(Function Calling)に対応させる場合
n8nの「AI Agent」ノードにToolを繋いで使いたい場合、少し工夫が必要になります。claude -pは「外部から渡されたツール定義を受けて、呼び出し意思だけをJSONで返す」素のAPIではなく、自分自身のツール実行ループを持つエージェントだからです。
これはclaude -p --json-schema(出力を指定したJSON Schemaに強制的に適合させるオプション)で解決できました。ツール一覧をシステムプロンプトに埋め込み「ツールを使いたければ{"type":"tool_use","name":...,"input":...}の形式で応答すること」と指示して、CLI自身の内蔵ツール(Bash/Editなど)は--disallowedToolsで防ぎます。
const TOOL_RESPONSE_SCHEMA = {
type: 'object',
properties: {
type: { type: 'string', enum: ['text', 'tool_use'] },
text: { type: 'string' },
name: { type: 'string' },
input: { type: 'object' },
},
required: ['type'],
additionalProperties: false,
};
Anthropicのinput_schemaはoneOf/allOf/anyOfをトップレベルで受け付けないため、判別共用体ではなくフラットな1つのスキーマにしています。この方式で、n8nのAgent+Toolの往復(tool_use応答→ツール実行→結果を踏まえた最終回答)が動作しました。正規APIではなく「なんちゃってAPI」なので、複雑な多段のツール呼び出しでは崩れる可能性があります。
似たようなことをしている人たち
「サードパーティのAPIクライアントからAnthropic OAuthトークンは使えないが、Claude Code CLI経由なら使える」という同じ発想のプロジェクトは、いくつか公開されています。
| プロジェクト | 概要 |
|---|---|
| thhuang/claude-max-api-proxy-rs | Rust製。claudeCLIをサブプロセスとしてラップし、OpenAI形式・Anthropic形式の両方のHTTP APIを提供する |
| wrentheai/claude-code-proxy | ローカルのAnthropic API互換プロキシをclaude -p経由で動かす、今回とほぼ同じ構成 |
| fuergaosi233/claude-code-proxy | Claude API形式のリクエストをOpenAI API形式に変換するタイプ |
今回作ったものは n8nの「AI Agent」ノードでTool呼び出し(Function Calling)まで使えるように、--json-schemaによるtool_use模倣を組み込んだ点が違っています。この用途に絞って動作確認まで済ませた実装が見当たらなかったので自作しました。
注意点
- Claude Pro/Maxの利用規約は個人の対話利用が前提です。自動化ツールからの「恒常的な」呼び出しは規約上グレーゾーンなので、検証目的の範囲にとどめましょう
- 中継サーバーには認証・アクセス制御を入れていません。同一Dockerネットワーク上であれば誰でも呼び出せる状態なので、共有環境で使う場合は注意してください
-
model/max_tokens/temperatureなどのパラメータはCLI側に渡す手段が無く、無視されます
まとめ
n8nの「Anthropic Chat Model」ノードは、認証情報のBase URL欄を差し替えればバックエンドを自由に選べます。この性質を利用し、Claude Code CLIをAnthropic API互換の中継サーバーでラップすることで、サブスク契約のままn8nのAI Agentワークフローが検証できるようになりました。


