MCPサーバーを自作する方法|TypeScript/Python SDKで独自ツールを開発する実践ガイド

  • 2026年3月14日
  • 最終更新: 2026年3月14日

ブログ目次


——「既存のMCPサーバーでは自社の業務フローに合わない」「社内APIをAIエージェントから直接叩けるようにしたい」。MCPの導入が進む中で、こうしたニーズに直面する開発チームが急速に増えています。詳しくは「MCPサーバーの構築ガイド」で解説しています。

MCPサーバーを自作する方法

Anthropic社が公開したModel Context Protocol(MCP)は、AIモデルと外部システムをつなぐオープンスタンダードとして広がりを見せていますが、公開されているMCPサーバーは汎用的なものが中心です。自社独自の業務ロジックや社内APIをMCP対応させるには、MCPサーバーを自作する必要があります。AI活用完全ガイドで、AI活用の全体像を把握できます。

CRM特化型コンサルタントとして、HubSpot MCPサーバーやfreee MCPサーバーを日常的に活用している立場から言えば、MCPサーバーの自作は「AIエージェントの可能性を自社業務に最適化するための最短ルート」です。本記事では、TypeScript SDKとPython SDKの選定基準から、ツール定義の設計パターン、認証・エラーハンドリングの実装まで、独自MCPサーバーを開発するために必要な知識を体系的に解説します。詳しくは「MCPのエンタープライズ導入ガイド」で解説しています。

この記事でわかること

  • MCPサーバーを自作するメリットと、既存サーバーとの使い分けの判断基準
  • TypeScript SDKとPython SDKの特性比較と、プロジェクトに応じた選び方
  • ツール定義(Tool)の設計パターンと、Zod/Pydanticによる入力スキーマの書き方
  • OAuth 2.1やAPIキー認証の実装方法とセキュリティ設計
  • 実用的なエラーハンドリングパターンとデバッグ手法
  • 社内APIやCRMデータをMCP対応させる具体的な実装手順

MCPサーバーを自作すべきケースとは

既存MCPサーバーではカバーできない領域

2026年3月時点で、MCPのエコシステムには数千のサーバーが公開されています。HubSpot、Slack、Notion、GitHub、Google Workspaceなど主要SaaSのMCPサーバーは充実していますが、以下のケースでは自作が必要になります。

ケース 具体例 自作が必要な理由
社内専用API 在庫管理システム、独自CRM、社内ナレッジDB 公開サーバーが存在しない
業務ロジックの組み込み 見積計算、与信判断、承認フロー 汎用サーバーでは業務ロジックを表現できない
複数システムの統合操作 CRM + 会計 + 在庫の横断クエリ 個別サーバーの組み合わせでは非効率
セキュリティ要件 オンプレミス限定、特定IPレンジ制限 公開サーバーではセキュリティポリシーに合わない
パフォーマンス最適化 大量データの事前集約、キャッシュ戦略 汎用サーバーでは応答速度が不十分

ここが結構ミソなのですが、MCPサーバーの自作は「既存のAPIラッパーを書く」こととは根本的に異なります。MCPサーバーは、AIモデルが「どのツールを使うべきか」を自律的に判断するためのメタ情報(ツールの説明文、入力スキーマ、アノテーション)を含む設計が求められます。単にAPIを呼べるだけでは不十分で、AIが適切に判断できるよう、ツールの意味・用途・副作用を正確に記述する必要があるのです。

自作 vs 既存サーバーの判断フレームワーク

自作するかどうかの判断は、以下の3つの軸で整理すると明確になります。

  1. カバレッジ: 必要な操作の80%以上が既存サーバーでカバーできるなら、まず既存サーバーを試す
  2. カスタマイズ性: 業務固有のバリデーションやワークフローが必要なら、自作の価値が高い
  3. メンテナンスコスト: 自作サーバーは自分たちで保守する必要がある。長期的な運用体制を確保できるか

MCPサーバーのアーキテクチャ全体像についてはMCPサーバーの構築ガイド|自社データをAIに接続するための設計と実装手順で詳しく解説しています。


TypeScript SDK vs Python SDK——どちらを選ぶべきか

SDK選定の比較表

MCPの公式SDKは、TypeScriptとPythonの2つが提供されています。どちらもMCPプロトコルの全機能をサポートしていますが、特性が異なります。詳しくは「HubSpot MCP Serverの活用ガイド」で解説しています。

比較軸 TypeScript SDK Python SDK
GitHubリポジトリ modelcontextprotocol/typescript-sdk modelcontextprotocol/python-sdk
スキーマ定義 Zod Pydantic
トランスポート stdio / Streamable HTTP stdio / Streamable HTTP
型安全性 TypeScriptの型システムで静的チェック 型ヒント + Pydanticで実行時バリデーション
非同期処理 Node.js のイベントループ asyncio
デプロイ先 Vercel / Cloudflare Workers / AWS Lambda AWS Lambda / Google Cloud Functions / 自社サーバー
推奨ユースケース Webアプリ連携、フロントエンドとの統合 データ分析、ML連携、既存Pythonシステムとの統合
コミュニティ規模 MCPサーバーの多くがTS製(参考実装が豊富) データサイエンス系の連携事例が多い

選定の指針

TypeScript SDK: 既存のNode.js/TypeScriptプロジェクトへの組み込み、Webアプリ(Next.js等)との統合、リファレンス実装の参照(多くがTS製)に適しています。

Python SDK: 既存のPythonシステム(Django、FastAPI)へのMCP追加、データ分析・ML連携、Pydanticベースのバリデーション活用に適しています。


TypeScript SDKでMCPサーバーを実装する

基本構造——最小構成のMCPサーバー

ここでは、TypeScript SDKを使って社内の顧客情報APIをMCP対応させるサーバーを実装します。以下が最小構成のコードです。

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

// MCPサーバーのインスタンスを作成
const server = new McpServer({
  name: "internal-crm-server",
  version: "1.0.0",
  description: "社内CRMの顧客情報をAIエージェントから検索・更新するためのMCPサーバー",
});

// ツール定義: 顧客を検索する
server.tool(
  "search_customers",
  "顧客名・メールアドレス・会社名で顧客情報を検索します。部分一致で検索され、最大20件を返します。",
  {
    query: z.string().describe("検索キーワード(顧客名、メールアドレス、会社名のいずれか)"),
    limit: z.number().optional().default(10).describe("取得件数の上限(デフォルト: 10、最大: 20)"),
  },
  async ({ query, limit }) => {
    // 社内APIを呼び出す
    const response = await fetch(`https://internal-api.example.com/customers/search`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${process.env.INTERNAL_API_TOKEN}`,
      },
      body: JSON.stringify({ query, limit: Math.min(limit, 20) }),
    });

    if (!response.ok) {
      return {
        content: [{ type: "text", text: `検索に失敗しました: ${response.statusText}` }],
        isError: true,
      };
    }

    const customers = await response.json();
    return {
      content: [{
        type: "text",
        text: JSON.stringify(customers, null, 2),
      }],
    };
  }
);

// サーバーを起動
const transport = new StdioServerTransport();
await server.connect(transport);

このコードが示すように、MCPサーバーの基本構造は非常にシンプルです。McpServerのインスタンスを作成し、server.tool()でツールを定義し、StdioServerTransportで接続するだけです。

ツール定義のベストプラクティス

ツール定義において最も重要なのは、description(説明文)の品質です。AIモデルはこの説明文を読んで「どのツールを使うべきか」を判断します。

以下の原則を守ることで、AIの判断精度が大きく向上します。

  1. 何ができるかを明確に書く: 「顧客情報を操作します」ではなく「顧客名・メールアドレス・会社名で顧客情報を検索します」
  2. 制約を明示する: 「最大20件を返します」「この操作は元に戻せません」
  3. パラメータの意味を具体的に記述する: z.string().describe("検索キーワード(顧客名、メールアドレス、会社名のいずれか)")
  4. 副作用を宣言する: 読み取り専用か、データを変更するか、削除するかをdescriptionとアノテーションの両方で示す

Python SDKでMCPサーバーを実装する

FastMCPによる簡潔な実装

Python SDKでは、FastMCPクラスを使うことで、デコレータベースの直感的なツール定義が可能です。

from mcp.server.fastmcp import FastMCP
from pydantic import BaseModel, Field
import httpx

mcp = FastMCP(
    "internal-crm-server",
    description="社内CRMの顧客情報をAIエージェントから検索・更新するためのMCPサーバー"
)

class CustomerSearchResult(BaseModel):
    id: str
    name: str
    email: str
    company: str
    status: str

@mcp.tool()
async def search_customers(
    query: str = Field(description="検索キーワード(顧客名、メールアドレス、会社名)"),
    limit: int = Field(default=10, le=20, description="取得件数の上限")
) -> list[CustomerSearchResult]:
    """顧客名・メールアドレス・会社名で顧客情報を検索します。部分一致で最大20件を返します。"""
    async with httpx.AsyncClient() as client:
        response = await client.post(
            "https://internal-api.example.com/customers/search",
            json={"query": query, "limit": limit},
            headers={"Authorization": f"Bearer {os.environ['INTERNAL_API_TOKEN']}"},
        )
        response.raise_for_status()
        return [CustomerSearchResult(**c) for c in response.json()]

if __name__ == "__main__":
    mcp.run()

Python SDKのFastMCPは、関数のdocstringをツールの説明文として、型ヒントとPydanticのFieldをスキーマ定義として自動的に利用します。TypeScript SDKに比べてコード量が少なく、Pythonに慣れた開発者にとっては取り回しが楽です。


認証・認可の実装パターン

MCPサーバーにおける認証の3つのレイヤー

MCPサーバーの認証設計では、3つのレイヤーを区別して考える必要があります。

レイヤー 説明 実装例
クライアント認証 MCPクライアント(Claude Desktop等)がMCPサーバーに接続する際の認証 OAuth 2.1、APIキー
バックエンド認証 MCPサーバーが社内APIや外部サービスに接続する際の認証 環境変数でのトークン管理
ユーザー認証 エンドユーザーの権限に基づくアクセス制御 JWTトークン、RBAC

stdioトランスポートの場合: クライアント認証はトランスポート層で不要です(ローカルプロセスとして起動されるため)。バックエンド認証のみ実装すれば十分です。環境変数で社内APIのトークンを管理するのが一般的なパターンです。

Streamable HTTPトランスポートの場合: リモートサーバーとして公開するため、クライアント認証が必須になります。MCPの仕様ではOAuth 2.1が推奨されています。

環境変数による認証情報の管理

stdioトランスポートでの典型的な設定例を示します。Claude Desktopの設定ファイル(claude_desktop_config.json)で環境変数を渡す形です。

{
  "mcpServers": {
    "internal-crm": {
      "command": "node",
      "args": ["./dist/server.js"],
      "env": {
        "INTERNAL_API_TOKEN": "your-api-token-here",
        "DATABASE_URL": "postgresql://user:pass@localhost:5432/crm"
      }
    }
  }
}

認証情報はコードにハードコードせず、必ず環境変数で管理します。MCPのセキュリティ設計の詳細はMCPのセキュリティリスクと実践的な対策ガイドを参照してください。


エラーハンドリングの設計

MCPサーバーにおけるエラーの分類

MCPサーバーのエラーハンドリングは、AIエージェントが「エラーの原因を理解して次のアクションを判断できる」ことを目標に設計します。単にエラーを投げるのではなく、AIが読み取れる形でエラー情報を返すことが重要です。

// エラーハンドリングのパターン(抜粋)
if (response.status === 404) {
  return {
    content: [{ type: "text", text: `顧客ID "${customerId}" は存在しません。search_customersツールで検索できます。` }],
    isError: true,
  };
}
if (response.status === 429) {
  return {
    content: [{ type: "text", text: "APIレート制限に達しました。30秒後に再試行してください。" }],
    isError: true,
  };
}

ポイントは、エラーメッセージの中に次のアクションのヒントを含めることです。「顧客IDが存在しません」だけでなく、「search_customersツールで検索できます」と書くことで、AIエージェントが自律的にリカバリー操作を選択できるようになります。


社内APIをMCP対応させる実践手順

5ステップの開発フロー

既存の社内APIをMCPサーバーとして公開する手順を整理します。

Step 1: API仕様の棚卸し

まず、社内APIのエンドポイント一覧を整理し、MCPツールとして公開する範囲を決定します。すべてのAPIエンドポイントをMCPツール化する必要はありません。AIエージェントが使う可能性のある操作だけに絞ります。

Step 2: ツール粒度の設計

ここが結構ミソなのですが、MCPのツール粒度はREST APIのエンドポイント粒度とは異なります。REST APIではGET /customersGET /customers/:idは別のエンドポイントですが、MCPツールとしては「顧客検索」と「顧客詳細取得」を1つのツールにまとめるか、分けるかを「AIの判断しやすさ」の観点で設計します。

Step 3: 入力スキーマの定義

Zod(TypeScript)またはPydantic(Python)でスキーマを定義します。AIモデルが正しい値を渡せるよう、各フィールドのdescriptionを充実させることが成功の鍵です。

Step 4: エラーハンドリングの実装

前節で解説したパターンに従い、AIが理解できるエラーメッセージを設計します。

Step 5: テストとデバッグ

MCPサーバーのテストには、MCP Inspectorが便利です。ブラウザベースのUIからツールを直接呼び出してレスポンスを確認できます。

npx @modelcontextprotocol/inspector node ./dist/server.js

CRM/SFA連携でのMCPサーバー活用例

HubSpotのカスタムオブジェクトをMCP対応させる

HubSpot CRMでは標準オブジェクト(コンタクト、取引、会社)に加えて、カスタムオブジェクトを作成できます。例えば「プロジェクト管理」や「サブスクリプション管理」のカスタムオブジェクトを作成している企業は多いでしょう。

公式のHubSpot MCPサーバーは標準オブジェクトの操作に対応していますが、業務固有のカスタムオブジェクトを操作するには、専用のMCPサーバーを自作するか、既存サーバーを拡張する必要があります。

自作MCPサーバーを使えば、「この取引に紐づくプロジェクトの進捗を教えて」「サブスクリプションの更新期限が今月中の顧客を一覧にして」といった業務固有の問い合わせに、AIエージェントが直接応答できるようになります。

HubSpot MCPサーバーの基本的な活用方法についてはHubSpot MCPサーバーによるCRM操作の自動化で詳しく解説しています。


開発環境とデバッグツール

効率的な開発のためのツールチェーン

MCPサーバーの開発を効率化するツール群を紹介します。

ツール 用途 公式/サードパーティ
MCP Inspector ブラウザUIでツール呼び出しをテスト 公式
Claude Desktop 実際のAIクライアントでの動作確認 Anthropic
Claude Code CLIベースでの高速テスト・反復開発 Anthropic
MCP CLI (mcp dev) Python SDK付属の開発サーバー 公式

Claude Code Hooksを活用した開発自動化と組み合わせることで、MCPサーバーのコード変更時に自動でテストを実行する仕組みも構築できます。

ログとモニタリング

stdioトランスポートの場合、console.logの出力はMCPの通信を妨害します。ログ出力にはconsole.error(stderr)を使うか、server.sendLoggingMessage()を使用してください。

// NG: stdioを汚染する
console.log("Processing request...");

// OK: stderrに出力する
console.error("[DEBUG] Processing request...");

// OK: MCP標準のログメッセージ
server.sendLoggingMessage({
  level: "info",
  data: "Processing customer search request",
});

MCPサーバー開発の制限事項と注意点

MCPサーバーの自作にあたって、正直に把握しておくべき制限事項があります。

プロトコルの進化途上: MCPは2025年末にStreamable HTTPトランスポートが追加されるなど、仕様が進化し続けています。SDKのバージョンアップに伴い、コードの修正が必要になる可能性があります。

LLMの判断精度への依存: ツールの説明文やスキーマの品質がAIの判断精度に直結します。「動くけれどAIが正しく使ってくれない」という問題は、コードの品質ではなくメタ情報の品質に起因することがほとんどです。

セキュリティの自己責任: 自作サーバーのセキュリティは開発者が担保する必要があります。特にStreamable HTTPで公開する場合、認証・認可・レート制限・入力バリデーションを自前で実装する必要があります。

デバッグの難しさ: AIエージェントが「なぜそのツールを選んだか」「なぜそのパラメータを渡したか」のデバッグは、従来のAPIデバッグとは質が異なります。ツールの説明文を微調整しながら反復テストするプロセスが必要です。


まとめ——MCPサーバー自作は「AIエージェント時代の必須スキル」

MCPサーバーの自作は、一見すると技術的なハードルが高く感じるかもしれませんが、TypeScript/Python SDKの成熟により、基本的なサーバーであれば数時間で構築できるレベルまで開発体験が向上しています。このテーマの全記事はMCP連携ガイドでご覧いただけます。

重要なのは、コードの書き方よりも設計の考え方です。ツール粒度の設計、説明文の品質、エラーメッセージの設計——これらはすべて「AIが適切に判断できるか」という観点で設計する必要があります。CRMやSFAの業務フローをAIエージェントで自動化する際には、この設計力が成果を大きく左右します。

自社の業務データやAPIをMCP対応させることで、AIエージェントの活用範囲は飛躍的に広がります。まずは小さなツール1つから始めて、MCPサーバー開発の基礎を身につけてみてください。


よくある質問(FAQ)

Q1. MCPサーバーの開発にはどのくらいの期間が必要ですか?

ツール1〜3個の小規模なサーバーであれば、1〜2日で開発からテストまで完了できます。10個以上のツールを持つ本格的なサーバーの場合、設計・実装・テスト・ドキュメント整備を含めて1〜2週間が目安です。SDKが提供するボイラープレートが充実しているため、プロトコルの理解さえあれば実装作業自体はスムーズに進みます。

Q2. TypeScript SDKとPython SDK、どちらが情報が多いですか?

2026年3月時点では、TypeScript SDKの方が参考実装やコミュニティの事例が豊富です。Anthropic公式のリファレンスサーバーもTypeScriptで書かれているものが多く、初めてMCPサーバーを自作する場合はTypeScript SDKから始めるのが効率的です。ただし、Python SDKも急速にエコシステムが拡大しており、特にデータ分析やML連携の領域ではPython SDKの事例が充実しています。

Q3. stdioとStreamable HTTP、どちらのトランスポートを選ぶべきですか?

個人の開発環境やチーム内での利用であれば、stdioトランスポートが最もシンプルです。サーバーをnodeやpythonのプロセスとして起動するだけで使えるため、デプロイの手間がかかりません。一方、社外のユーザーや複数チームに公開する場合、Streamable HTTPトランスポートが適しています。ただし、OAuth 2.1認証やHTTPSの設定が追加で必要になります。

Q4. MCPサーバーのテストはどのように行いますか?

MCP Inspector(npx @modelcontextprotocol/inspector)を使うのが最も効率的です。ブラウザベースのUIからツールを直接呼び出し、レスポンスの形式や内容を確認できます。また、ユニットテストとしてMCPクライアントライブラリを使ってサーバーにプログラマティックに接続し、各ツールの入出力を検証する方法も推奨されています。

Q5. 自作MCPサーバーをClaude Desktopで使うにはどうすればよいですか?

Claude Desktopの設定ファイル(macOSの場合~/Library/Application Support/Claude/claude_desktop_config.json)のmcpServersセクションに、サーバーの起動コマンドと環境変数を記述します。設定後にClaude Desktopを再起動すると、ツールバーにMCPサーバーのアイコンが表示され、登録したツールが利用可能になります。

Q6. HubSpotのカスタムオブジェクトをMCPで操作するにはどうすればよいですか?

HubSpot APIのカスタムオブジェクトエンドポイントをラップするMCPツールを自作します。標準MCPサーバーではカスタムオブジェクトの操作に制限があるため、業務で本格的に活用するなら自作が現実的です。

Q7. MCPサーバーの自作に必要な前提知識は何ですか?

TypeScriptまたはPythonの基本的な開発経験と、REST APIの基本概念の理解があれば十分です。MCPプロトコル自体は公式ドキュメント(modelcontextprotocol.io)を一読すれば概要を把握できます。


株式会社StartLinkは、事業推進に関わる「販売促進」「DXによる業務効率化(ERP/CRM/SFA/MAの導入)」などのご相談を受け付けております。 サービスのプランについてのご相談/お見積もり依頼や、ノウハウのお問い合わせについては、無料のお問い合わせページより、お気軽にご連絡くださいませ。

関連キーワード:

サービス資料を無料DL

著者情報

7-1

今枝 拓海 / Takumi Imaeda

株式会社StartLinkの代表取締役。
HubSpotのトップパートナーである株式会社H&Kにて、HubSpotのCRM戦略/設計/構築を軸として、 国内・外資系エンタープライズ企業へコンサルティング支援を実施。 パーソルホールティングス株式会社にて、大規模CRM/SFA戦略の策定・PERSOLグループ横断のグループAI戦略/企画/開発ディレクションの業務を遂行経験あり。
株式会社StartLinkでは、累計100社以上のHubSpotプロジェクト実績を元にHubSpot×AIを軸にした経営基盤DXのコンサルティング事業を展開。