軽くて速いMCPサーバの作り方

Claude Codeで使えるMCPサーバ「sqlew」を作ってnpmで公開しました。MCPサーバを作りたい人ってほとんどバイブコーダーだと思うのでみんな割と簡単に作ってると思います。MCPサーバ特有の「最適化」については誰も語ってないような気がしたので、いろいろと工夫した結果を共有します。

MCPサーバって何?

このブログを見てる方には説明不要かもしれませんけど。。MCPサーバは、Claude CodeなどAIエージェントに、新しいツールを追加できる仕組みです。

基本的には標準入力でJSONを受け取って、標準出力でJSONを返すCLIアプリケーションです。(Webベースでも作れますけどそっちは作ったことがないので、以降の話はstdioの前提で読んでもらえれば)

言語は何で作るの?

Terminalなどのコマンドラインで動かせる実行形式がつくれて、メインループで待ち受けができる言語なら使用言語は何でもOKです。

cmdとかshとかでも作れるかもしれないです。誰かチャレンジしません?

配布する予定がある場合は配布先でコンパイルなりして動作するバイナリになっている必要があります。要するにコマンドラインで起動できる状態になっていればAIから呼び出せるということですね。

一般公開することを検討しているなら、npmやuvで気軽にインストールできるNode.jsかPythonが楽だと思います。


MCPサーバ特有の問題

さてここからが本題です。MCPサーバを作って初めて気づいたんですが、MCPサーバは読み込むだけでトークンを消費するんですよね。

読み込み時の消費トークンは主に「ツールの説明文」です。claudeのプロンプトで/doctorコマンドを打つと、MCPモリモリにしてるとこんな警告が出ます。

2番目のsqlewが私が作ったMCPですけど、serena並にトークンを浪費している状態でした。オハズカシイ

これは「起動した時点で3.6万トークン消費済み」という意味でもあります。SerenaとかPlaywrightとか、機能が豊富なMCPサーバはめちゃくちゃトークンを消費します。Claude Code v2.0.0から使わないツールをdisableにできるようになったので必要なときだけOnにする使い方ができるようになりましたが、作る側としてもトークン消費を抑える工夫はしたいところです。

MCPサーバのトークン消費を減らすための工夫

実際にsqlewで試した方法を紹介します。

ツールの説明文を簡潔にする

一番ダイレクトに効果がある方法です。上に書いてますが、読み込み時の消費トークンはほぼ全部説明文なので、物理的に量を減らす作戦です。

Before

After

スッキリ。

ただ、説明文を削りすぎるとAIのツールに対する理解が弱くなりそうなので、他の方法で補う必要があります。

GithubのREADME.mdにガッツリ書く

公開できるコードの場合ですけど、GithubのREADME.mdをcontext7 MCPを使って使い方を読ませる事もできます。AIが必要に応じて詳細な情報にアクセスできます。が、context7もドキュメントそのまま渡してくるのでコンテクスト量には注意です。

READMEを何ページかに分けるのもいいのかもです。

ツールの数を減らす

MCPサーバの各機能は”ツール”と呼ばれていて、ClaudeCodeなどから読み込まれた時に、ツールの一覧と説明文をJSONで渡しています。

簡潔な説明文でも1ツールで500~600トークンくらい消費しています。機能を精査して、本当に必要なツールだけに絞ることができれば、その分コンテキスト消費量は減ります。

set_〇〇、get_〇〇のツールは統合できる

もともとの設計ではsetter/getterのような構成で作成していましたが、単一のツールに引数を与えて処理内容を変える、Strategyパターンならツール数がかなり減らせます。例えば:

  • set_configget_configupdate_config の3つのツール
  • config ツール1つで、引数で action: "get" | "set" | "update" を指定

sqlewでも、もともと20ツールあったのを6ツールに統合しました。

ツールで分けておくのにもメリットはありまして。ツールごとにAllow/Denyの権限設定が出来るのですが、Strategyパターンの場合はそれを捨てる判断ということにもなります。セキュリティリスクがありそうなMCPでは使えないかも。

helpコマンドをつける

説明文を簡潔にすると、AIが使い方に迷うことがありますがしっかりした説明は使ってない時もトークンを消費してしまう。そこで、しっかりめの説明文を返すhelpコマンドを用意してあげると良いです。要はツール一覧に載ってなければコンテキストの浪費は起こりませんので。

上のconfigの場合

  • config action: “get” | “set” | “update” | “help”

みたいな構成ですね。

実際の削減効果

sqlewで実践した結果がこちらです。

Before

~13,730 tokens

After

~4,482 tokens

ドヤァ

約67%、9000トークンの削減に成功しました。これだけトークンが減ると、Claude Codeの起動も速くなりますし、他のMCPサーバと組み合わせる余裕も生まれます。なによりもコーディング自体に使えるトークンが増えるのがとても重要。


実装のポイント

まぁどうせみんなバイブコーディングで作るんでしょうから、ここから先はオマケみたいなもんです。

基本構造

MCPサーバの実装自体はシンプル。競技プログラミングの入出力がJSONだと思えば、まぁやることは一緒です。

細かい実装はGithubでも見てもらうとして、基本的な構造は

  • メインループ起動
    • (標準入力待ち)
    • →AIからinitializeのリクエストを受け取る
      • ←MCPサーバ情報をJSONで返す
    • →AIからtools/listリクエストを受け取る
      • ←ツールリストを返す
    • (標準入力待ち)
    • →AIからツール呼び出し
      • ←処理して標準出力に返す
    • (標準入力待ち)

こんな感じです。最低限必要なのはinitializetools/listだけです。

initializeのレスポンスはこんな感じ。

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "tools": {}
    },
    "serverInfo": {
      "name": "sqlew",
      "version": "1.0.0"
    }
  }
}

tools/listのレスポンスはこんな感じ。

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "query",
        "description": "Execute SQL queries",
        "inputSchema": { ... }
      }
    ]
  }
}

この出力ではqueryというツールが存在していること、inputSchemaの内容でデータを受け入れるということをAIに伝えています。

配布方法

Node.jsで作った場合、npmで公開するのが一番楽です。

ちな私は今回初めてnpmパッケージを公開したくらいのnoobです。もっと詳しいブログが他にあるはずなので、npmに関しては検索してください。

npmで公開するにはアカウント作成が必要です。

アカウント作成後、ビルド済みのプロジェクトルートで

npm login
# ブラウザや2FAでログイン
npm publish

これであっさり公開されました。AndroidのPlayストアとかと比べて楽すぎて拍子抜けしてます。

公開し終わったら

npm install パッケージ名
# または
npx パッケージ名@バージョン

ユーザーはこれだけで使えるようになります。

まとめ

AIコーディングだと割と誰でもMCPサーバは作れちゃいますが、設計ひとつでトークン消費量がかなり変わるというのが今回の気付き。

  • ツールの数は少なめに
  • ツールの説明文は簡潔に
  • helpコマンドで補完する

この辺を意識すると、使いやすくてトークン効率の良いMCPサーバが作れるんじゃないかと思います。

みんなも便利なMCPいっぱい作ってね。

sqlewの宣伝

今回作った「sqlew」は、ClaudeCodeのサブエージェント同士のコンテキスト共有を強化し、並列処理時のコンテキスト消費量を削減したり重複コードの発生を防いだりできるMCPサーバです。

ぜひ使って(はぁと

あとIssue投げて(まさかり

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です