Claude Code や Claude Desktop に GA4 や Figma の MCP を設定して使う、という記事はだいぶ増えました。実際 Claude Code に MCP をつないで実務を加速する実例 でも、市販の MCP をクライアントに設定して業務を回す型を紹介しています。ただ、これらはあくまで「誰かが作ってくれたアダプタを差し込む」段階です。本当に効くのは、自社にしか存在しない業務ツールやデータを LLM につないだときです。在庫管理システム、社内の顧客 DB、独自の見積もりロジック——こうした自社固有の資産を Claude から操作できるようにするには、MCP サーバーを自分で作る必要があります。
本記事では、MCP (Model Context Protocol) サーバーの自作を、最小構成の実装から認証・権限設計、エラー処理、デプロイ、本番運用までを実装視点で順に解説します。コードの 1 行 1 行を写経するための記事ではなく、自社業務に組み込むときに必ず迷う設計判断の勘所を押さえることを目的にしています。
MCP サーバーとは - クライアント利用との違い
MCP は、LLM に外部のツールやデータを使わせるための共通規格です。プロトコルとしては、クライアントとサーバーの 2 役で成り立っています。クライアントは Claude Code や Claude Desktop のような対話アプリケーションで、サーバーは LLM に「使える道具」と「参照できるデータ」を提供する側です。
ここを混同すると設計を誤ります。GA4 の MCP を設定して「先月のセッション数を集計して」と頼むのはクライアント利用です。一方で、自社の受発注システムを Claude から操作できるように公開し、「未出荷の注文を一覧にして」と頼めるようにするのがサーバー自作です。前者は市販のアダプタを差すだけですが、後者は自社専用のアダプタを設計して作る作業になります。
サーバーが LLM に提供するものは、大きく tools と resources の 2 種類です。tools は「実行できる関数」で、注文を検索する、レコードを更新する、レポートを生成するといった能動的な操作を指します。resources は「参照できるデータ源」で、ドキュメントやレコードの内容を LLM に読ませるための入口です。多くの業務連携では tools が主役になりますが、参照専用の情報を読ませたいなら resources を使い分けると設計がすっきりします。
重要なのは、LLM はサーバーが公開したものしか触れないという点です。裏を返せば、何を公開し、何を公開しないか、どこまでの権限を持たせるかは、すべてサーバー側の設計で決まります。安全性も使い勝手も、サーバーの作り方しだいです。
最小構成の MCP サーバーを作る - tools と resources
最初の一歩は、tools をひとつだけ持つ最小のサーバーを動かすことです。公式 SDK は TypeScript と Python が最も整っているので、既存の業務ツールが書かれている言語に合わせて選びます。社内システムが Node.js や Python なら、その資産をそのまま取り込めます。
最小構成でやることは、サーバーのインスタンスを立てて名前とバージョンを宣言し、tools をひとつ登録して、通信方式を指定して待ち受けるところまでです。tools の登録では、ツール名・何をするツールかの説明文・入力パラメータのスキーマ (型と必須項目) を定義します。通信方式には標準入出力 (stdio) を使うのが手軽で、これはクライアントがサーバーをサブプロセスとして起動してやり取りする方式なので、ローカル検証にちょうど向いています。
ここで効いてくるのが、ツールの説明文とパラメータスキーマの書き方です。LLM はこの説明だけを手がかりに、どのツールをいつ呼ぶかを判断します。「注文を検索する」とだけ書くより、「注文番号・顧客名・ステータスのいずれかで注文を検索し、該当する注文の一覧を返す。ステータスは pending / shipped / cancelled のいずれか」と具体的に書いたほうが、誤った呼び出しが激減します。パラメータも、自由文字列で受けるより列挙型 (enum) で候補を固定したほうが、LLM が変な値を渡す事故を防げます。ツール定義は、LLM に対するインターフェース仕様書だと考えると質が上がります。
resources を使う場合も発想は同じで、URI のような識別子でデータの場所を表し、読み出されたときに中身を返す関数を用意します。社内 Wiki のページや特定のレコードを「読ませたいだけ」のときは、tools ではなく resources にしておくと、LLM が誤って書き込み操作と混同しにくくなります。
最小構成が Claude から呼べることを確認できたら、いよいよ自社の API や DB へつなぎます。
自社 API・DB を安全につなぐ認証と権限設計
ここが MCP サーバー自作で最も神経を使う部分です。LLM は指示されたツールを呼ぶだけで、自分で安全か危険かを判断してくれません。だからこそ、認証・認可・監査の責任はすべてサーバー側が握る、という原則を最初に据えます。
認証は、サーバーが外部システムにアクセスするための資格情報の管理から始めます。DB 接続文字列や API キーは、ソースコードや LLM に渡る場所には決して置かず、環境変数やシークレットマネージャから読み込みます。LLM はツールの入力パラメータしか見ないので、認証情報がプロンプトに混ざらない構成にすることが第一歩です。
認可、つまり「何をどこまでできるか」は、業務影響に直結するので段階的に絞ります。最初は読み取り専用の接続でサーバーを作るのが安全です。DB なら read-only のロールで接続し、API なら参照系のスコープだけを与えます。書き込みや削除を伴うツールを足すのは、読み取りで運用が安定してからにします。書き込み系ツールを公開するときも、影響範囲を最初からツール側で制限します。たとえば「1 回の呼び出しで更新できるのは 1 レコードまで」「削除は論理削除のみで物理削除は提供しない」といった具合に、危険な操作そのものをツールとして存在させない設計が効きます。
そして見落とされがちなのが、LLM の出力を信用しないことです。LLM が渡してきたパラメータを、そのまま SQL に文字列連結したり API のパスに埋め込んだりするのは厳禁です。サーバー側で型・範囲・許可リストを必ず検証し、プレースホルダを使ったクエリに通します。LLM はときに想定外の値を渡してくるので、入力検証は外部からの不正入力と同じ厳しさで扱うのが正解です。ツールの引数を決まった形で安定して受け取るためのスキーマ設計とバリデーションは LLM の構造化出力を安定させる設計 で詳しく扱っています。
書き込み系の重い操作については、人間の承認を挟む設計も有効です。「この操作を実行してよいか」を一度返し、確認が取れてから本実行する二段構えにすると、誤操作の被害を抑えられます。どこまで自動化し、どこで人間が握るかの線引きは、業務のリスク許容度に合わせて決めます。
エラー処理とレート制限・タイムアウトの実装
最小構成が動くと、つい本番に出したくなりますが、その前にエラー処理を作り込みます。MCP サーバーのエラー処理には、通常の API とは違う観点が要ります。エラーメッセージを読むのは人間ではなく LLM だからです。
エラーを返すときは、LLM が次の行動を判断できる情報を添えます。たとえば「注文が見つかりません」だけでなく「指定された注文番号は存在しません。注文番号は 8 桁の数字です」と返せば、LLM は番号の形式を見直して再試行できます。逆に、内部のスタックトレースや DB のエラー文をそのまま返すと、LLM が混乱したり、機密情報が漏れたりします。エラーは LLM 向けに整えて返す、というのが基本姿勢です。
レート制限は、外部システムを守るために欠かせません。LLM は人間と違い、短時間に同じツールを何度も連続で呼ぶことがあります。意図せぬループに入ると、つないだ先の API の上限を一瞬で食い潰したり、DB に過剰な負荷をかけたりします。サーバー側で 1 分あたりの呼び出し回数に上限を設け、超えたら待つか明確なエラーを返す仕組みを入れておきます。
タイムアウトも必須です。外部 API や DB クエリが応答しないとき、サーバーが無限に待つと、クライアント側も固まります。各ツールの処理に上限時間を設け、超えたら打ち切ってエラーを返します。打ち切りのメッセージも LLM 向けに「処理が時間内に完了しませんでした。条件を絞って再試行してください」と書いておくと、LLM がより軽い条件で自動的にやり直せます。
冪等性 (べきとうせい) にも気を配ります。LLM がタイムアウトを誤解して同じ書き込みを再実行することがあるため、同じリクエストを 2 回受けても二重登録にならない設計にしておくと安全です。リクエストごとに識別子を持たせ、すでに処理済みなら結果だけ返す、といった工夫が効きます。
ローカルからリモートへ - デプロイと配布の選択肢
サーバーが安定して動くようになったら、チームに届ける段階です。配布方法はローカルとリモートの 2 つに大別できます。
ローカル配布は、stdio で動くサーバーをパッケージとして配り、各自がクライアントの設定ファイルに追記して使う形です。個人や少人数のチームで完結するなら、これが最も手軽です。サーバーは利用者のマシン上でサブプロセスとして起動し、ローカルから DB や社内 API にアクセスします。導入の敷居が低い反面、更新のたびに全員が入れ直す必要があり、利用者ごとに環境差が出やすいのが弱点です。
リモート配布は、HTTP で待ち受けるサーバーをどこかにデプロイし、利用者は接続先 URL と認証トークンを設定するだけで使えるようにする形です。チーム全体や複数システムから使う場合に向いています。サーバーを中央で管理できるので、更新を一度で全員に反映でき、ログや監視も一元化できます。クラウドのコンテナ実行基盤やサーバーレス環境に載せると運用が楽になります。リモート構成では、トークンの発行・失効や、誰がどのサーバーにアクセスできるかのアクセス制御を、サーバー側できちんと設計することが前提になります。
進め方としては、まずローカルで作って業務での価値を検証し、利用が広がってきた段階でリモートへ移行する流れが、運用負荷とのバランスを取りやすいです。最初からリモートで作り込むと、価値が確かめられないうちに認証基盤やインフラの設計コストを払うことになります。小さく作って効果を見てから本格化する、という順序が AI 駆動開発全体の考え方とも噛み合います。
本番運用のロギング・監視と壊れにくい設計
自作 MCP サーバーを業務で常用するなら、運用設計が品質を決めます。ここを軽視すると、「いつの間にか壊れていて、誰も気づかなかった」という事態になります。
ロギングは、誰が・いつ・どのツールを・どんなパラメータで呼び、結果がどうだったかを追える形で残します。LLM 経由の操作は、人間が直接画面を操作するより経緯が見えにくいので、後から監査できることが特に重要です。書き込み系の操作については、変更前後の値も記録しておくと、問題が起きたときの復旧や原因究明が速くなります。一方で、ログに機密情報そのものを書かないよう、マスキングの方針も同時に決めます。
監視は、サーバーの死活だけでなく、ツールごとのエラー率や応答時間を見ます。特定のツールのエラーが急に増えたら、つないだ先の API 仕様が変わったか、LLM の呼び方が変化したサインです。早く気づければ、利用者が困る前に手を打てます。
壊れにくさという観点では、つないだ先の外部システムが落ちてもサーバー自体は生き続ける設計を意識します。外部呼び出しはタイムアウトと再試行で囲み、失敗しても LLM に状況を伝えて全体は止めない。ツールを追加・変更するときも、既存のツール名やパラメータの意味を勝手に変えないことが大切です。LLM はツール定義を前提に振る舞いを学習するため、後方互換を壊すと、これまで動いていた指示が急に効かなくなります。新しい挙動が必要なら、既存ツールを変えるより新しいツールとして足すほうが安全です。
こうした運用の型は、エージェントを実務に組み込む全般のノウハウと地続きです。私たちがエージェントを使って業務オペレーションを自動化した事例は AI エージェントによる業務オペレーション自動化の実績 でも紹介しており、MCP サーバーを軸に自社業務をつなぐときの参考になります。
自社業務に MCP サーバーを組み込む AI 駆動開発
MCP サーバーの自作は、単なる API ラッパー作りではありません。自社の業務をどこまで LLM に任せ、どこを人間が握るかを、ツール定義と権限設計という形で意思決定する作業です。だからこそ、業務理解と実装力の両方が要ります。
最小構成を動かすところまでは、本記事の手順をなぞれば多くのチームが到達できます。難しいのはその先の、認証・権限・運用を本番品質に仕上げる部分です。読み取り専用から始める、書き込みは影響範囲を絞る、LLM の出力を検証する、すべてを監査可能に残す——こうした原則を自社のリスク許容度に合わせて具体化していくと、安全に業務へ組み込めます。作った MCP サーバーをエージェントから呼ばせて複数ステップの業務を回す段階では、AI エージェントの設計パターン で扱う型の選び方が指針になります。
FIXIT は AI 駆動開発のクリエイティブスタジオとして、自社ツールと LLM をつなぐ MCP サーバーの設計・実装から、エージェントを組み込んだ業務自動化までを一気通貫で手がけています。MCP を軸にした業務連携の進め方は AI エージェント開発のサービス に、AI を前提とした開発全体の取り組み方は AI 駆動開発のサービス にまとめています。
自社のどの業務を、どのツールを使って LLM につなげば効くのか。その入口の設計から、無料相談 でご一緒できます。「うちのこのシステムを Claude から触れるようにしたい」という具体的なテーマがあれば、実装の現実性とリスクを踏まえてお話しします。

