概要
AnythingMCP のコードモードによる実用的なプログラムを3つ紹介します。オンラインショップ(Shopify)と会計(Lexware Office)をまたいだ月次売上、注文と請求書の照合、そして100件の顧客価格照会を100回ではなく1回のツール呼び出しで行う方法です。コード、押さえておきたい制限、プログラムをツールとして保存するタイミングも解説します。
TL;DR: コードモードが効果を発揮するのは、エージェントが同じ呼び出しを何度も繰り返す場面や、2つの長いリストを読んで比較する場面です。以下の3つのレシピは、2つのシステムをまたいだ集計、2つのリストの突き合わせ、1つの照会を多数の項目に対して繰り返す処理というパターンを示しています。いずれも amcp.run を通じて MCP ツールを呼び出し、結果だけを返す短い JavaScript プログラムです。インラインで実行する(エージェントが code_execute でプログラムを書く)ことも、チームが名前で呼び出せるコードツールとして保存することもできます。コードモードはセルフホスト版 AnythingMCP の v0.52.0 から利用でき、AnythingMCP Cloud では近日公開予定です。
コードモードが初めての方は、まず MCP コードモードとは? と 最初のコードツールを作る をご覧ください。
プログラムをコピーする前に
- ツール名は実在しますが、レスポンスの形は異なります。 レシピでは Shopify コネクタと Lexware Office コネクタのツールを使っています。フィールド名は各 API のレスポンスに従います。フィールドを使う前に、Test パネルでツールを一度実行するか、プログラム内で
amcp.describe(name)を呼び出して確認してください。 - 1回の実行は10秒までです。 実行は10秒で停止します。ページ取得や互いに独立した呼び出しは、1つずつ順番に行うのではなく並列で実行してください(同時に最大16件)。
- 読み取り専用です。 インラインコードはデータを変更するツールを呼び出しません。保存したコードツールは、管理者が許可した場合(Enterprise)に限り呼び出せます。3つのレシピはいずれも読み取りのみを行います。
- 数値は架空のものです。 表示されている結果は、作成した例です。
レシピ1 — ショップと会計をまたいだ月次売上
質問: 「10月の売上はいくらでしたか? オンラインショップとB2B請求書の合計でお願いします。」
コードモードがない場合、エージェントは数百件のショップ注文や請求書をページ送りで取得し、すべてのレコードをコンテキストに読み込み、数字を読みながら加算します。コードモードを使えば、受け取るのは2つの合計値だけです。
// Input: args.month as "YYYY-MM", e.g. "2026-10".
const [y, m] = String(args.month).split('-').map(Number);
const from = `${y}-${String(m).padStart(2, '0')}-01`;
const to = m === 12 ? `${y + 1}-01-01` : `${y}-${String(m + 1).padStart(2, '0')}-01`;
// Shop: paid orders created in the month (Shopify search syntax), 250 per page.
let shop = 0, shopOrders = 0, after = undefined;
do {
const res = await amcp.run('shopify_search_orders', {
query: `created_at:>=${from} created_at:<${to} financial_status:paid test:false`,
first: 250,
after,
});
const page = res.orders ?? res.data?.orders; // depends on how the tool wraps the GraphQL result
for (const o of page.nodes) {
shop += Number(o.currentTotalPriceSet.shopMoney.amount);
shopOrders++;
}
after = page.pageInfo.hasNextPage ? page.pageInfo.endCursor : undefined;
} while (after);
// Accounting: sales invoices dated in the month, without drafts and voided ones.
let b2b = 0, invoices = 0, p = 0, last = false;
const lastDay = new Date(Date.UTC(y, m, 0)).toISOString().slice(0, 10);
while (!last) {
const res = await amcp.run('lexware_office_list_vouchers', {
voucherType: 'salesinvoice',
voucherStatus: 'open,paid,paidoff',
voucherDateFrom: from,
voucherDateTo: lastDay,
size: 250,
page: p++,
});
for (const v of res.content ?? []) { b2b += Number(v.totalAmount); invoices++; }
last = res.last ?? true;
}
return {
month: args.month,
shop: { orders: shopOrders, gross: Math.round(shop * 100) / 100 },
invoices: { count: invoices, gross: Math.round(b2b * 100) / 100 },
total: Math.round((shop + b2b) * 100) / 100,
};
返ってくるのは600件のレコードではなく、4つの数値です。
{ "month": "2026-10", "shop": { "orders": 412, "gross": 38214.9 }, "invoices": { "count": 57, "gross": 91380.12 }, "total": 129595.02 }
合計を信頼する前に、定義を確認してください。 ショップの注文が会計でも請求書として発行されている場合、両方を足すと二重計上になります。その場合は、請求書をB2B顧客のものに絞り込んでください。ここでの両方の金額は、ショップおよび帳簿の通貨での総額(税込)であり、返金やクレジットノートは差し引かれていません。こうした判断はツールの説明文に書いておくと、AI がその数値の意味を正しく伝えられます。
レシピ2 — 請求書のない注文、注文のない請求書
質問: 「先月の支払い済みショップ注文のうち、会計に請求書がないものはどれですか? また、金額が一致しないものはどれですか?」
これは、モデルが読むだけでは最も苦手とする作業です。数百行ずつの2つのリストを目で比較することになります。コードなら辞書(Map)の検索で済みます。
// Where your accounting keeps the shop order number. Adapt to your setup:
// many shop integrations write it into the invoice's reference or title.
const orderRefOf = (invoice) => invoice.orderReference;
const orders = args.orders; // [{ name: "#1042", total: 89.9 }, ...] from a first step
const invoices = args.invoices; // [{ orderReference: "#1042", totalAmount: 89.9, voucherNumber: "RE0815" }, ...]
const byOrder = new Map(invoices.map((i) => [orderRefOf(i), i]));
const missing = [], mismatched = [];
for (const o of orders) {
const inv = byOrder.get(o.name);
if (!inv) missing.push(o.name);
else if (Math.abs(Number(inv.totalAmount) - Number(o.total)) > 0.01)
mismatched.push({ order: o.name, invoice: inv.voucherNumber, order_total: o.total, invoice_total: inv.totalAmount });
}
const orderNames = new Set(orders.map((o) => o.name));
const orphanInvoices = invoices.filter((i) => !orderNames.has(orderRefOf(i))).map((i) => i.voucherNumber);
return { checked: orders.length, missing, mismatched, orphanInvoices };
このバージョンでは、突き合わせのロジックを読みやすくするため、2つのリストを入力として受け取っています。保存したコードツールでは、レシピ1のページ送りループを使ってプログラム内でそれらを取得します(注文は shopify_search_orders から、請求書は lexware_office_list_vouchers から取得し、参照フィールドが必要な場合は lexware_office_get_invoice も使います)。これにより、AI は月を指定して1つのツールを呼び出すだけで、短い3つのリストを受け取れます。
{ "checked": 412, "missing": ["#1077", "#1139"], "mismatched": [{ "order": "#1101", "invoice": "RE0902", "order_total": 129.0, "invoice_total": 119.0 }], "orphanInvoices": [] }
レシピ3 — 100回ではなく1回の呼び出しで100件の価格照会
質問: 「顧客からの問い合わせにある100件の品番があります。この顧客向けの価格を教えてください。」
多くの ERP は、品番と顧客ごとに顧客別価格を1リクエストずつ計算します。ERP 用の独自の REST コネクタに、入力として article と customer を受け取るツール erp_get_customer_price があるとします(これは例としての名前です。REST API を MCP ツールに変換する方法もご覧ください)。コードモードがない場合、エージェントは100回呼び出し、100件の結果を読み込みます。コードモードなら次のようになります。
// Inputs: args.customer, args.articles (array of article numbers).
const articles = [...new Set(args.articles.map(String))];
const rows = [];
const BATCH = 10; // at most 16 calls may be in flight at once
for (let i = 0; i < articles.length; i += BATCH) {
const batch = articles.slice(i, i + BATCH);
const results = await Promise.all(batch.map(async (article) => {
try {
const r = await amcp.run('erp_get_customer_price', { article, customer: args.customer });
return { article, price: r.netPrice, unit: r.priceUnit, currency: r.currency };
} catch (e) {
return { article, error: String(e.message ?? e) };
}
}));
rows.push(...results);
}
return {
customer: args.customer,
found: rows.filter((r) => !r.error).length,
notFound: rows.filter((r) => r.error).map((r) => r.article),
prices: rows.filter((r) => !r.error),
};
一度に10件ずつ実行されるため、1件あたり数百ミリ秒の100件の照会でも、10秒の制限内に余裕をもって完了します。1つの品番で失敗しても残りの処理は止まらず、その品番は notFound に入ります。モデルは100個のバラバラなツール結果ではなく、見積書のドラフトやメールにそのまま変換できる1つの表を受け取ります。
まず、そもそもコードが必要かどうかを確認してください。 API が品番のリストによる絞り込みを1リクエストで行える場合(たとえば weclapp は in 演算子で品番を絞り込めます)、通常のツール呼び出し1回のほうがシンプルです。コードモードは、それができない API のためのものです。
インラインか、保存か?
インライン(code_execute) | 保存したコードツール | |
|---|---|---|
| プログラムを書く人 | エージェントが、その質問のために書く | 管理者が1回だけ書く(またはエージェントが提案する) |
| 向いている用途 | 単発の分析、調査 | チームが毎週行う質問 |
| 権限 | 呼び出し元自身の権限、読み取り専用 | 呼び出し元または定義者の権限。書き込みが許可されていない限り読み取り専用(Enterprise) |
| エディション(v0.52 の発表時点) | Team と Enterprise | Community 3、Starter 5、Team 20、Enterprise 無制限 |
エージェントがインラインで2回解決したパターンは、保存ツールの候補です。インラインコードを有効にしていれば、エージェントが提案し、管理者がワンクリックで承認できます。
FAQ
これらのプログラムはデータを書き込めますか? たとえば、不足している請求書を作成できますか? インラインではできません。保存したコードツールが書き込みツールを呼び出せるのは、管理者が Allow write tools をオンにした場合のみで、これには Enterprise が必要です。データを変更する処理では、プログラムを読み取り専用に保ち、操作の確認は人が行うようにしてください。
実行に10秒以上かかる場合はどうなりますか? 分割してください。たとえば1年分ではなく1か月ごとに実行する、または1回の呼び出しあたりの項目数を減らします。制限を超えた実行はエラーで停止します。プログラムは読み取りしか行わないため、中途半端に書き込まれることはありません。
プログラムによって私のデータがどこかに送信されますか? いいえ。プログラムはネットワークのない隔離されたランナー内で実行されます。あなたのシステムには、あなたのロールのもとで MCP ツールを通じてのみアクセスします。詳しくは AI エージェントのための安全なコード実行 をご覧ください。
関連記事
- MCP コードモードとは?
- 最初のコードツールを作る:ステップバイステップ
- AI エージェントのための安全なコード実行
- エージェントがコードツールを提案し、管理者が承認する
- PDF や Excel の価格表から品番を見つける
- Shopify、Lexware Office、weclapp を Claude に接続する
このガイドは役に立ちましたか?