MCPサーバーの作り方|Python・TypeScriptで社内ツールをClaudeにつなぐ実装手順【2026年版】

執筆・監修: Links-Create AI研修チーム
Claude Code・MCP・AI エージェントを実プロダクト開発で日常的に運用するチームが、 実務で詰まった点に基づいて執筆しています。 公開: 2026-06-16

この記事でわかること

  • MCPサーバーとクライアントの違い:何を作るのか、どちらを実装するのか
  • Python(FastMCP)で最小MCPサーバーを作る — デコレータ1つでツール化
  • TypeScript(@modelcontextprotocol/sdk)で同じものを作る手順
  • 作ったサーバーを Claude Code / Claude Desktop に登録して動かす設定
  • MCP Inspector での動作確認と、社内DB連携時のセキュリティ4原則

結論:MCPサーバーは「ツール1つ」から始められる

MCP(Model Context Protocol)は、Claude のような AI に「外部ツールの使い方」を教える共通プロトコルです。一度サーバーを書けば、Claude Code / Claude Desktop / Cursor など対応クライアントから等しく使えます。

作るのはサーバー側だけです。クライアント(AI側)は既製品を使うので、あなたが書くのは「ツールを公開する小さなサーバー」だけ。Python なら関数にデコレータを1つ付けるだけで動きます。

この記事では Python(FastMCP)と TypeScript の両方で最小サーバーを作り、Claude Code / Claude Desktop に登録して動かすところまでを、実際に動くコードで示します。「MCPとは何か」という概念は MCP入門 で扱っているので、本記事は作り方の実装手順に集中します。

MCPサーバーとクライアントの違い

最初につまずきやすいのがこの区別です。

MCPクライアントMCPサーバー
役割AI側(ツールを呼ぶ)ツール提供側(あなたが書く)
具体例Claude Code / Claude Desktop / Cursor社内DB照会、Slack投稿、ファイル操作…
実装するか既製品を使う(書かない)これを書く
通信サーバーを子プロセス起動 or HTTP接続stdio / HTTP で待ち受け

つまり「MCPサーバーの作り方」を調べているあなたが書くのは、自社のツールを Claude に公開する側です。

準備:SDK のインストール

# Python
pip install mcp        # FastMCP を含む公式 SDK

# TypeScript
npm i @modelcontextprotocol/sdk zod

Python は 3.10 以上、TypeScript は Node.js の最新 LTS を推奨します(SDK のバージョンにより必要 Node が上がることがあるため、npm i 時の engines 警告を確認してください)。

Python で最小MCPサーバーを作る(FastMCP)

FastMCP を使うと、普通の関数に @mcp.tool() を付けるだけでツールになります。

# server.py
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("demo-tools")  # サーバー名

@mcp.tool()
def add(a: int, b: int) -> int:
    """2つの整数を足し算する"""
    return a + b

@mcp.tool()
def get_weather(city: str) -> str:
    """都市名から天気を返す(デモ)"""
    return f"{city} の天気: 晴れ(demo)"

if __name__ == "__main__":
    mcp.run()  # stdio トランスポートで起動

これだけで動く MCPサーバーが完成です。ポイント:

  • 型ヒント(a: int)から入力スキーマが自動生成される。Claude はこれを見て「addはintを2つ取る」と理解します。
  • docstring がツールの説明になる。「いつこのツールを使うか」を Claude に伝える最重要要素なので、丁寧に書きます。
  • 戻り値はそのまま Claude に返ります。

TypeScript で同じものを作る

TypeScript では McpServerzod(スキーマ定義)を使います。

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

const server = new McpServer({ name: "demo-tools", version: "1.0.0" });

server.registerTool(
  "add",
  {
    description: "2つの整数を足し算する",
    inputSchema: z.object({ a: z.number(), b: z.number() }),
  },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b) }],
  }),
);

server.registerTool(
  "get_weather",
  {
    description: "都市名から天気を返す(デモ)",
    inputSchema: z.object({ city: z.string() }),
  },
  async ({ city }) => ({
    content: [{ type: "text", text: `${city} の天気: 晴れ(demo)` }],
  }),
);

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
}

main();

実行は npx tsx server.ts(または tsc でビルド後 node)。zod スキーマから入力定義が自動生成され、返り値は content 配列で返します。

補足:より低レベルに制御したい場合は @modelcontextprotocol/sdk/server/index.jsServer クラスで ListTools / CallTool ハンドラを直接書く方式もあります(MCP入門で扱っています)。最初は上記の高レベル API で十分です。

動作確認:MCP Inspector

Claude につなぐ前に、サーバー単体で動くかを確認します。MCP Inspector はブラウザUIでツール一覧と実行結果を見られる公式ツールです。

# Python サーバーを検査
npx @modelcontextprotocol/inspector python server.py

# TypeScript サーバーを検査
npx @modelcontextprotocol/inspector npx tsx server.ts

ブラウザが開いたら「Tools」タブで addget_weather が見えるか、実行して期待通りの結果が返るかを確認します。ここで動けばサーバーは正しいので、以降のトラブルは登録・接続側の問題に切り分けられます。

Claude Code に登録して使う

claude mcp add コマンドが最も簡単です。

# Python サーバーを登録
claude mcp add demo-tools -- python /absolute/path/to/server.py

# 登録を確認
claude mcp list

または、プロジェクトルートに .mcp.json を置く方法(チームで共有しやすい):

{
  "mcpServers": {
    "demo-tools": {
      "command": "python",
      "args": ["/absolute/path/to/server.py"]
    }
  }
}

登録後、Claude Code で「add ツールで 17 と 25 を足して」のように自然文で呼び出せます。

Claude Desktop に登録して使う

設定ファイル(macOS: ~/Library/Application Support/Claude/claude_desktop_config.json、Windows: %APPDATA%\Claude\claude_desktop_config.json)に追記し、Claude Desktop を再起動します。

{
  "mcpServers": {
    "demo-tools": {
      "command": "python",
      "args": ["/absolute/path/to/server.py"]
    }
  }
}

再起動後、UIにツールアイコンが表示されれば接続成功です。

実用例:社内DBの read-only 照会ツール

最小サーバーを「実際に役立つツール」に育てる例です。Python で社内 PostgreSQL を 読み取り専用で照会するツール:

import os
import psycopg2
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("company-db")
DSN = os.environ["COMPANY_DB_RO_URL"]  # 認証情報は環境変数で

@mcp.tool()
def query(sql: str) -> str:
    """社内DBに SELECT クエリを投げて結果を返す(読み取り専用)"""
    if not sql.strip().upper().startswith("SELECT"):
        return "エラー: SELECT 文のみ実行できます"
    with psycopg2.connect(DSN) as conn, conn.cursor() as cur:
        cur.execute(sql)
        rows = cur.fetchall()
    return str(rows[:100])  # 件数を制限

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

ここで効いているのが次のセキュリティ設計です。

セキュリティ4原則(社内ツール連携の必須事項)

  1. 認証情報を Claude に渡さない:DSN・APIキーは環境変数でサーバー側に閉じる。Claude が見るのはツールの入出力だけ。
  2. 権限分離:DB は GRANT SELECT のみの専用ロールで接続。API は read-only スコープのトークンを使う。
  3. 破壊的操作のハードブロック:DELETE / DROP / 課金系はサーバー側のコードで拒否する(プロンプトでお願いするのではなく、実装で塞ぐ)。
  4. 監査ログ:いつ・どのツールが・どんな引数で呼ばれたかを記録。誤実行調査とセキュリティ監査に必須です。

これらは「Claude が暴走する」対策というより、ツール実装のミスや想定外入力から守るための設計です。実務ではこちらのほうが事故率が高いです。

stdio と HTTP の使い分け

stdioHTTP(SSE / Streamable HTTP)
起動Claude が子プロセスとして起動常駐サーバーに接続
配布不要(ローカル完結)エンドポイントを共有
向き個人の試作・ローカルツールチーム共有・常駐サービス
認証ローカル前提で軽量OAuth 等を別途実装

個人で試すなら stdio、チームで共有する段階で HTTP 化、という順番が現実的です。

既存の公式MCPサーバーも活用する

ゼロから全部作る必要はありません。Filesystem / GitHub / Slack / PostgreSQL などは公式・コミュニティの MCPサーバーが公開されています。まず公式サーバーで感覚を掴み、自社固有のツールだけ自作するのが失敗の少ない進め方です。

まとめ

  • MCPサーバー=ツール提供側。書くのはサーバーだけ、クライアントは既製品を使う
  • Python は FastMCP(@mcp.tool())、TypeScript は McpServer + zod で最小実装できる
  • Claude につなぐ前に MCP Inspector で単体確認 → claude mcp add.mcp.json / Desktop config で登録
  • 社内連携は「認証情報を渡さない・権限分離・破壊的操作のブロック・監査ログ」の4原則
  • 個人は stdio、共有段階で HTTP 化

手を動かして定着させる:MCP は触ってみないと感覚が掴めないプロトコルです。当サイトの「AIエージェント活用実践編」では Tool Use と MCP を提出物テンプレ + 採点ルーブリック付きの演習で扱います。先に試すなら バイブコーディング実践編 の MCP の章を 4 週間限定無料で受講できます。

関連ガイド:

関連する AI 研修コース・事例

このガイドで解説した内容を、提出物・採点ルーブリック付きの実装演習で 実務レベルまで定着させるためのコースと、国内外の AI 活用事例を見るための入口です。