RORK LABEN
VERIFY — Android の開発者認証が2026年9月に完全義務化されます。Android 17 以降の端末では認証が OS 側に実装され、認証を経ていないアプリは新規インストールが OS レベルでブロックされうる構造ですREVIEW — 9月から、App Store への新規申請・アップデート申請と、代替配信向けの notarization で回答の提出が必須になりますSDK — iOS 27 と Xcode 27 は9月に正式リリース見込みです。提出アプリへの iOS 27 SDK ビルド必須化は2027年春の予定で、こちらは1年近い猶予がありますTIMELINE — Rork の $15M シードと Paperline 買収は2026年4月9日の発表です。直近のニュースではないため、記事で扱う際は時系列を明確に区別する必要がありますMAX — Rork Max は native Swift を出力し、iPhone・iPad・Apple Watch・Apple TV・Vision Pro・iMessage が対象です。標準の Rork は React Native(Expo)でクロスプラットフォームのアプリを生成しますEXPORT — 自動の Publish が失敗しても、GitHub へ同期して React Native のソース一式を無料でエクスポートし、手動で提出まで進められますVERIFY — Android の開発者認証が2026年9月に完全義務化されます。Android 17 以降の端末では認証が OS 側に実装され、認証を経ていないアプリは新規インストールが OS レベルでブロックされうる構造ですREVIEW — 9月から、App Store への新規申請・アップデート申請と、代替配信向けの notarization で回答の提出が必須になりますSDK — iOS 27 と Xcode 27 は9月に正式リリース見込みです。提出アプリへの iOS 27 SDK ビルド必須化は2027年春の予定で、こちらは1年近い猶予がありますTIMELINE — Rork の $15M シードと Paperline 買収は2026年4月9日の発表です。直近のニュースではないため、記事で扱う際は時系列を明確に区別する必要がありますMAX — Rork Max は native Swift を出力し、iPhone・iPad・Apple Watch・Apple TV・Vision Pro・iMessage が対象です。標準の Rork は React Native(Expo)でクロスプラットフォームのアプリを生成しますEXPORT — 自動の Publish が失敗しても、GitHub へ同期して React Native のソース一式を無料でエクスポートし、手動で提出まで進められます
記事一覧/AIモデル
AIモデル/2026-08-07上級

MCP のツールを減らしても軽くならない — 定義 2,377 バイトと応答 110,298 バイトを測り直した記録

壁紙カタログ用の MCP サーバを最小構成で書き、ツール定義と応答のバイト数を実測しました。削るべき側と、ツールを統合する本当の理由についての記録です。

MCP4Rork528React Native220Expo159設計10実測advanced4

プレミアム記事

壁紙アプリのカタログを扱う MCP サーバのツールが、気づけば12本になっていました。

一覧、検索、条件指定、詳細取得。似た用途のものが少しずつ増えていく、あの膨らみ方です。

個人開発でアプリを複数抱えていますと、こうした補助の仕組みは誰にも相談せず自分ひとりで育てることになります。膨らみに気づくのが遅れるのは、たいていそのためです。

「多すぎるから重いのだろう」と考えて、使用頻度の低い6本を外しました。ところが体感はほとんど変わりません。

削った量が足りなかったのか、そもそも削る場所が違ったのか。判断がつかないまま手を動かし続けるのは、いちばん時間を溶かすやり方です。

測ることにしました。

測定用に、依存のない MCP サーバを書き直す

公式 SDK を使うと、フレーミングやセッション管理の分だけバイト数が上乗せされます。何が何バイトなのかを切り分けたかったので、stdio 上の JSON-RPC 2.0 を素で実装しました。

MCP は要するに「1行1メッセージの JSON-RPC を標準入出力で流す」プロトコルです。initialize / tools/list / tools/call の3つだけなら、この程度の分量で動きます。

カタログの 324 件は、App Store と Google Play に出している壁紙アプリの実データとほぼ同じフィールド構成にしてあります。フィールドを削って測っても、手元の判断材料にはなりませんので。

#!/usr/bin/env node
// server.mjs — 測定用の最小 MCP サーバ(stdio / JSON-RPC 2.0)
import { createInterface } from "node:readline";
 
// 壁紙カタログ 324 件(実アプリのフィールド構成に合わせています)
const CATALOG = Array.from({ length: 324 }, (_, i) => ({
  id: `wp_${String(i + 1).padStart(4, "0")}`,
  title: `Wallpaper ${i + 1}`,
  category: ["nature", "abstract", "minimal", "space", "city"][i % 5],
  width: 2796,
  height: 1290,
  bytes: 380000 + (i * 977) % 220000,
  sha256: Array.from({ length: 64 }, (_, k) => "0123456789abcdef"[(i * 7 + k) % 16]).join(""),
  tags: ["calm", "blue", "gradient", "night"].slice(0, (i % 4) + 1),
  license: "internal",
  createdAt: "2026-05-01T00:00:00Z",
  updatedAt: "2026-07-30T00:00:00Z",
  overlayScrim: { top: 0.42, bottom: 0.18 },
}));
 
const TOOLS = [
  { name: "list_wallpapers",
    description: "カタログの壁紙を一覧します。カテゴリで絞り込めます。",
    inputSchema: { type: "object", properties: {
      category: { type: "string", description: "カテゴリ名" },
      limit: { type: "integer", description: "最大件数" } } } },
  { name: "search_wallpapers",
    description: "カタログの壁紙をキーワードで検索します。タグと題名が対象です。",
    inputSchema: { type: "object", properties: {
      query: { type: "string", description: "検索語" },
      limit: { type: "integer", description: "最大件数" } }, required: ["query"] } },
  // …以下、find_wallpapers / get_wallpaper / get_locale_keys /
  //   get_missing_translations / check_i18n_completeness / get_build_config /
  //   get_app_config / list_categories / get_catalog_stats / validate_catalog
];
 
function call(name, args = {}) {
  if (name === "list_wallpapers") {
    let rows = CATALOG;
    if (args.category) rows = rows.filter((r) => r.category === args.category);
    return rows.slice(0, args.limit ?? rows.length);
  }
  if (name === "list_wallpapers_projected") {
    let rows = CATALOG;
    if (args.category) rows = rows.filter((r) => r.category === args.category);
    return rows.slice(0, args.limit ?? rows.length)
      .map((r) => ({ id: r.id, title: r.title, category: r.category }));
  }
  if (name === "get_wallpaper") return CATALOG.find((r) => r.id === args.id) ?? null;
  if (name === "list_categories") return [...new Set(CATALOG.map((r) => r.category))];
  return { ok: true };
}
 
const rl = createInterface({ input: process.stdin });
rl.on("line", (line) => {
  if (!line.trim()) return;                 // 空行は無視。ここを忘れると JSON.parse で落ちます
  const req = JSON.parse(line);
  let result;
  if (req.method === "initialize") {
    result = {
      protocolVersion: "2025-06-18",
      capabilities: { tools: {} },
      serverInfo: { name: "wallpaper-catalog", version: "0.1.0" },
    };
  } else if (req.method === "tools/list") {
    const n = req.params?.n ?? TOOLS.length; // 測定用にツール数を可変にしています
    result = { tools: TOOLS.slice(0, n) };
  } else if (req.method === "tools/call") {
    const payload = call(req.params.name, req.params.arguments);
    result = { content: [{ type: "text", text: JSON.stringify(payload) }] };
  } else {
    result = {};
  }
  process.stdout.write(JSON.stringify({ jsonrpc: "2.0", id: req.id, result }) + "\n");
});

計測に使った環境は Node.js v22.22.3 の Linux 上で、子プロセスとして起動した本サーバに対し標準入出力越しに要求を投げています。以下の数値はすべてこの構成で実際に走らせて取得したものです。実機やネットワーク越しの数字ではありません。

tools/list にわざと n パラメータを足してあるのは、ツール数を1本ずつ変えながら応答サイズを測るためです。仕様外の余計な引数ですが、測定用のサーバなので割り切りました。

ツール定義のコストは、想像していたより二桁小さい

まず tools/list の応答サイズです。ツール数を変えながら、返ってきた result を UTF-8 のバイト数で数えました。

ツール数tools/list の応答1本あたり平均
1297 bytes297 bytes
3873 bytes291 bytes
51,260 bytes252 bytes
71,665 bytes238 bytes
102,106 bytes211 bytes
122,377 bytes198 bytes

1本目から12本目までの差を本数で割ると、追加1本あたりの限界コストは 189.1 バイト でした。

つまり私が外した6本は、合計でおよそ 1.2 KB です。

この時点で、削ったのに変わらなかった理由の見当がつきました。1.2 KB は、そもそも体感が変わる大きさではありません。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
ツール定義12本で 2,377 バイト、応答1回で 110,298 バイト。削るべき側を実測で特定します
バイト予算からレコード境界で切り出すページャの実装。充填率 99.3〜100.0% を実測しています
ツール名と説明の文字bigram類似度を測り、45.5% で衝突していた2本を統合するまでの手順
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

AI モデル2026-04-02
Rork × MCP(Model Context Protocol)実装ガイド — AIツールを自在に統合する次世代モバイルアプリ開発
Anthropic が提唱するMCP(Model Context Protocol)をRorkアプリに統合する完全ガイド。アーキテクチャ設計からストリーミング対応・認証・プロダクション運用まで、実装コード付きで体系的に解説します。
AI モデル2026-06-19
Rork Max に月 $200 を払う前に、Expo でどこまで届くかを3階層で見極める
ウィジェットや Live Activities が欲しくなると Rork Max が視野に入りますが、その多くは標準 Rork の Expo 構成でも届きます。機能ごとに「Expo で届く・自作モジュールで届く・Max が現実解」の3階層に分け、課金前に実機で見極める手順を整理しました。
AI モデル2026-06-14
Rork(Expo)製アプリから Apple Foundation Models を呼ぶ — オンデバイスAIをネイティブモジュールで橋渡しする
Rork が生成する Expo(React Native)アプリから iOS のオンデバイスAI、Apple Foundation Models を呼ぶには、Swift 側のネイティブモジュールを挟む必要があります。Expo Modules API で橋渡しを書き、未対応端末ではクラウドへ逃がす構成を実装します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →