AIエージェント入門

MCPサーバーの作り方|Python・TS最小実装【2026年10月】

MCPサーバーの作り方|Python・TS最小実装【2026年10月】

この記事の結論

MCP サーバー 作り方を公式SDK v2で解説。Python・TypeScriptの最小実装、3機能、Claude系・Cursor接続、HTTP公開、OAuth、Inspectorを2026年10月2日時点で確認できます。

MCP サーバー 作り方に必要なものは4つです。公式SDK、公開する機能、接続方式、テスト用クライアントを用意し、最初はローカルのstdioで1機能だけ動かします。共有が必要になった段階でStreamable HTTPとOAuth 2.1を追加してください。

  1. PythonまたはTypeScriptの公式SDKを入れる
  2. tool・resource・promptのうち必要な機能を定義する
  3. MCP Inspectorで一覧取得と呼び出しを確認する
  4. Claude Desktop、Claude Code、Cursorのいずれかへ起動コマンドを登録する

2026年10月2日時点の現行安定系は、MCP仕様が2026-07-28、Python SDKとTypeScript SDKはいずれもv2です。古い記事にあるPythonのFastMCPやTypeScriptの@modelcontextprotocol/sdkを、そのまま新規実装へ持ち込まない点が最初の分岐になります。

手順1:PythonかTypeScriptかを先に決める

手順1:PythonかTypeScriptかを先に決める
手順1:PythonかTypeScriptかを先に決める

最初の判断は言語です。どちらも公式SDKでtool・resource・promptとstdio・Streamable HTTPを扱えます。Pythonは型ヒントとデコレータから短く書けるため、社内スクリプトやデータ処理の延長に向きます。TypeScriptはZodで入力スキーマを明示しやすく、Node.jsのWebアプリと一緒に管理したい場合に扱いやすい構成です。

判断軸 Python TypeScript
現行公式パッケージ mcp @modelcontextprotocol/server
現行の高水準API MCPServerとデコレータ McpServerと登録メソッド
入力定義 Pythonの型ヒント ZodなどのStandard Schema
選びやすい場面 Python資産、分析、社内自動化 Node.js資産、Web API、型を厳密に管理する開発

仕様の全体像を先に押さえたい場合は、内部記事のMCPサーバーとは何かを整理したガイドも参照してください。この記事では概念説明を最小限にし、動く1ファイルから接続・公開へ進みます。

図解1:最小構成から接続確認までの順番

手順2:Pythonで最小サーバーを1ファイルで動かす

手順2:Pythonで最小サーバーを1ファイルで動かす
手順2:Pythonで最小サーバーを1ファイルで動かす

MCP Python SDK公式ドキュメントではPython 3.10以上を要件とし、CLIを含むインストール方法としてuv add "mcp[cli]"またはpip install "mcp[cli]"を案内しています。ここでは依存関係をプロジェクト単位で固定しやすいuvを使います。

動作環境:Python 3.10以上、uv、MCP Python SDK v2。

注意:本番環境で使用する前に、必ずテスト環境で動作確認してください。

mkdir mcp-python
cd mcp-python
uv init
uv add "mcp[cli]"

次のserver.pyは、計算を行うtool、読み取り専用のresource、利用者が選ぶpromptを同じサーバーへ登録します。外部APIやファイル書き込みはまだ入れません。まずプロトコル上の3種類が見える状態を作るためです。

動作環境:Python 3.10以上、mcp v2。

注意:本番環境で使用する前に、必ずテスト環境で動作確認してください。

from mcp.server import MCPServer

mcp = MCPServer("Workspace Helper")


@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two integers."""
    return a + b


@mcp.resource("guide://policy")
def usage_policy() -> str:
    """Return the usage policy."""
    return "外部送信の前に、内容と宛先を人が確認する。"


@mcp.prompt(name="review-request")
def review_request(subject: str) -> str:
    """Create a review request for a subject."""
    return f"{subject}を、事実・機密情報・宛先の3点で確認してください。"


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

mcp.run()の既定はstdioです。プロセスは標準入力でリクエストを待ち、標準出力へMCPのメッセージだけを書きます。手動起動して何も表示されず待機し続けるのは、失敗ではありません。ログが必要ならPythonの標準loggingなど、標準エラーへ出る方法を使います。

ポイント:

  • 関数名がtool・resource・promptの名前の基礎になります。
  • docstringはクライアントへ渡る説明です。何をする機能か、短く限定して書きます。
  • 入力スキーマは型ヒントから生成されます。曖昧なdictだけで受けず、引数ごとに型を付けます。
  • Python v1系のfrom mcp.server.fastmcp import FastMCPは、v2ではMCPServerへ改称されています。

FastMCPという名前の旧世代コードとの違いやPython中心の実装を掘り下げたい場合は、内部記事のFastMCPでMCPサーバーを作るPythonガイドもあわせて確認してください。既存コードを読む際の背景として有効ですが、新規コードではインストールしたSDKの現行ドキュメントを優先します。

手順3:TypeScriptで同じ3機能を定義する

手順3:TypeScriptで同じ3機能を定義する
手順3:TypeScriptで同じ3機能を定義する

TypeScript SDK v2は、旧来の単一パッケージからサーバー・クライアント・各ランタイムのアダプターへ分割されました。サーバーは@modelcontextprotocol/server、入力検証はZod v4を使います。公式の最初のサーバー手順ではNode.js 20以上、ES Modules、tsxを使った実行例が示されています。

動作環境:Node.js 20以上、TypeScript SDK v2、Zod v4、tsx。

注意:本番環境で使用する前に、必ずテスト環境で動作確認してください。

mkdir mcp-typescript
cd mcp-typescript
npm init -y
npm pkg set type=module
npm install @modelcontextprotocol/server zod tsx
mkdir src

src/index.tsを作成します。v2ではregisterTool、registerResource、registerPromptを使い、各設定をオブジェクトで渡します。

動作環境:Node.js 20以上、@modelcontextprotocol/server v2。

注意:本番環境で使用する前に、必ずテスト環境で動作確認してください。

import { McpServer } from '@modelcontextprotocol/server';
import { serveStdio } from '@modelcontextprotocol/server/stdio';
import * as z from 'zod/v4';

function createServer(): McpServer {
  const server = new McpServer({
    name: 'workspace-helper',
    version: '1.0.0'
  });

  server.registerTool(
    'add',
    {
      description: 'Add two integers',
      inputSchema: z.object({ a: z.number().int(), b: z.number().int() })
    },
    async ({ a, b }) => ({
      content: [{ type: 'text', text: String(a + b) }]
    })
  );

  server.registerResource(
    'usage-policy',
    'guide://policy',
    { title: 'Usage policy', mimeType: 'text/plain' },
    async uri => ({
      contents: [{
        uri: uri.href,
        text: '外部送信の前に、内容と宛先を人が確認する。'
      }]
    })
  );

  server.registerPrompt(
    'review-request',
    {
      description: 'Create a review request',
      argsSchema: z.object({ subject: z.string().min(1) })
    },
    ({ subject }) => ({
      messages: [{
        role: 'user' as const,
        content: {
          type: 'text' as const,
          text: `${subject}を、事実・機密情報・宛先の3点で確認してください。`
        }
      }]
    })
  );

  return server;
}

void serveStdio(createServer);
console.error('workspace-helper MCP server running on stdio');

ポイント:

  • serveStdioへサーバーを作る関数を渡すのがv2の短い起動方法です。
  • inputSchemaとargsSchemaはz.object(...)で包みます。
  • stdioではconsole.logを使いません。標準出力はプロトコル専用なので、ログはconsole.errorへ出します。
  • 旧パッケージ@modelcontextprotocol/sdkのimport例と混在させないでください。

tool・resource・promptの役割を混ぜない

tool・resource・promptの役割を混ぜない
tool・resource・promptの役割を混ぜない

コード量より重要なのが機能境界です。3種類は「モデルがいつ使うか」「誰が選ぶか」が異なります。読み取り処理をすべてtoolにすると、モデルが意図せず実行対象として扱う範囲が広がります。逆に、状態を変更する処理をresourceへ押し込むと、読み取り専用という期待を壊します。

種類 主な役割 選ぶ主体 例
tool 計算・検索・更新などの処理を呼ぶ 主にモデル 在庫照会、チケット作成、計算
resource URIで識別した読み取り用データを返す クライアント 規約、設定、レポート
prompt 利用者が選ぶ会話テンプレートを返す 主に利用者 レビュー依頼、要約手順

Python SDKのPrompt解説は、toolをモデルが選ぶ機能、promptを利用者が選ぶテンプレートとして区別しています。resourceはクライアントが一覧・読み取りを行うデータです。この境界を先に決めると、権限と監査ログの設計も単純になります。

図解2:3つの機能は呼び出す主体と責任が異なる

手順4:MCP Inspectorで一覧・入力・戻り値を確認する

手順4:MCP Inspectorで一覧・入力・戻り値を確認する
手順4:MCP Inspectorで一覧・入力・戻り値を確認する

クライアント設定へ進む前に、MCP Inspectorでサーバー単体を確認します。2026年10月2日時点のMCP Inspector公式ドキュメントではNode.js 22.19.0以上を要件とし、npxからWeb UI、CLI、TUIを起動できます。

PythonのstdioサーバーをWeb UIで開く例です。/absolute/path/to/server.pyは実ファイルの絶対パスへ置き換えます。

動作環境:Node.js 22.19.0以上、npx、uv。

注意:本番環境で使用する前に、必ずテスト環境で動作確認してください。

npx @modelcontextprotocol/inspector \
  uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py

TypeScriptでは、起動コマンド全体をInspectorへ渡します。

動作環境:Node.js 22.19.0以上、プロジェクトにtsxをインストール済み。

注意:本番環境で使用する前に、必ずテスト環境で動作確認してください。

npx @modelcontextprotocol/inspector npx tsx src/index.ts

Inspectorでは次の順で確認します。

  1. サーバーへ接続できるか
  2. Toolsにaddが表示されるか
  3. 引数aとbが整数として表示されるか
  4. Resourcesからguide://policyを読めるか
  5. Promptsからreview-requestを選び、引数を渡せるか
  6. 不正な入力がスキーマエラーとして拒否されるか

CLIでTools一覧だけを取得する場合は、Inspectorの--cliと--method tools/listを使えます。ブラウザを介さずCIへ組み込みたい場合に便利です。

動作環境:Node.js 22.19.0以上。

注意:本番環境で使用する前に、必ずテスト環境で動作確認してください。

npx @modelcontextprotocol/inspector --cli \
  uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py \
  --method tools/list

起動できない場合のログの読み方や切り分け順は、内部記事のMCPサーバーのデバッグ手順で詳しく確認できます。

手順5:Claude Desktop・Claude Code・Cursorへつなぐ

ローカルstdioサーバーの接続で渡すものは、URLではなく「サーバーを起動するコマンド」です。ホストが子プロセスを起動し、stdinとstdoutで通信します。シェルのカレントディレクトリやPATHに依存しないよう、サーバーファイルと必要ならuvも絶対パスにします。

Claude Desktopは公式CLIでローカル設定を書く

Python SDKはClaude Desktop用の設定を書き込むmcp installを提供しています。Claude Desktopを一度起動して設定ディレクトリを作ったうえで実行し、完了後はアプリを完全終了して再起動します。

動作環境:Claude Desktop、uv、MCP Python SDK v2。

注意:本番環境で使用する前に、必ずテスト環境で動作確認してください。APIキーをコマンド履歴へ直接残さず、環境変数または秘密情報管理を使ってください。

uv run mcp install /absolute/path/to/server.py

macOSの設定先は~/Library/Application Support/Claude/claude_desktop_config.json、Windowsは%APPDATA%\Claude\claude_desktop_config.jsonです。これはローカルstdio向けです。リモートMCPはClaude DesktopのCustomize > Connectorsから追加し、リモートURLをこのJSONへ直接書く方法と混同しないでください。

Claude Codeはclaude mcp addで登録する

Claude Code公式MCPリファレンスでは、--より後ろをサーバーの起動コマンドとして渡します。

動作環境:Claude Code、uv、MCP Python SDK v2。

注意:本番環境で使用する前に、必ずテスト環境で動作確認してください。

claude mcp add workspace-helper -- \
  uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py

claude mcp list
claude mcp get workspace-helper

Claude Code内では/mcpで接続状態と公開機能を確認できます。チーム共有用の.mcp.jsonを使う場合は、認証情報をリポジトリへ書かず、プロジェクトスコープのサーバー承認も確認してください。

Cursorは.cursor/mcp.jsonへ同じ起動コマンドを書く

Cursor公式MCPドキュメントは、プロジェクト設定を.cursor/mcp.json、全体設定を~/.cursor/mcp.jsonへ置く方法を案内しています。

動作環境:Cursor、uv、MCP Python SDK v2。

注意:本番環境で使用する前に、必ずテスト環境で動作確認してください。次の例のパスは必ず実環境の絶対パスへ差し替えてください。

{
  "mcpServers": {
    "workspace-helper": {
      "type": "stdio",
      "command": "/absolute/path/to/uv",
      "args": [
        "run",
        "--with",
        "mcp[cli]",
        "mcp",
        "run",
        "/absolute/path/to/server.py"
      ]
    }
  }
}
図解3:同じstdio起動コマンドを3クライアントへ登録

手順6:共有するときだけStreamable HTTPへ切り替える

stdioは1台の端末で使うローカル統合に向きます。複数端末や複数利用者から接続するなら、サーバーをURLで提供するStreamable HTTPへ切り替えます。独立したHTTPとSSEの旧トランスポートは非推奨であり、新規実装はStreamable HTTPを選びます。

項目 stdio Streamable HTTP
起動主体 Claude Desktopなどのホスト 運用側のアプリサーバー
接続先 コマンドと引数 PH_8_
主な用途 個人・単一端末・ローカル資産 複数利用者・クラウドAPI・共有
認証境界 起動したローカルプロセス OAuth 2.1のBearer token

Pythonでは、同じMCPServerをStreamable HTTPで起動できます。既定のエンドポイントは/mcpです。

動作環境:Python 3.10以上、MCP Python SDK v2。

注意:この起動例はローカル確認用です。本番環境で使用する前に、必ずテスト環境で動作確認し、TLS・認証・Host許可リスト・監視を追加してください。

if __name__ == "__main__":
    mcp.run(transport="streamable-http", port=8000)

起動後のローカル接続先はPH_9_です。Claude CodeへリモートHTTPとして登録する場合は次の形式です。

動作環境:Claude Code。

注意:本番環境ではHTTPSの正式なURLを使い、秘密情報をURLやシェル履歴へ埋め込まないでください。

claude mcp add --transport http workspace-helper \
  PH_10_

TypeScript v2はcreateMcpHandlerをNode.jsへ載せる

TypeScript SDK v2のHTTP公式手順では、Web標準のcreateMcpHandlerでリクエストごとに新しいMcpServerを作ります。Node.jsでは@modelcontextprotocol/nodeのアダプターを追加します。

動作環境:Node.js 20以上、TypeScript SDK v2、@modelcontextprotocol/node、Zod v4、tsx。

注意:次のコードは127.0.0.1だけで確認する構成です。本番環境で使用する前に、必ずテスト環境で動作確認し、公開先に合うHost・Origin検証、Bearer token検証、TLSを追加してください。

npm install @modelcontextprotocol/node
npm install -D @types/node

TypeScript 6以降でtscも実行する場合は、tsconfig.jsonのcompilerOptions.typesへ["node"]を指定します。

src/http.tsを作成します。

import { createServer as createHttpServer } from 'node:http';

import {
  localhostHostValidation,
  localhostOriginValidation,
  toNodeHandler
} from '@modelcontextprotocol/node';
import { createMcpHandler, McpServer } from '@modelcontextprotocol/server';
import * as z from 'zod/v4';

const handler = createMcpHandler(() => {
  const server = new McpServer({
    name: 'workspace-helper-http',
    version: '1.0.0'
  });

  server.registerTool(
    'add',
    {
      description: 'Add two integers',
      inputSchema: z.object({ a: z.number().int(), b: z.number().int() })
    },
    async ({ a, b }) => ({
      content: [{ type: 'text', text: String(a + b) }]
    })
  );
  return server;
});

const nodeHandler = toNodeHandler(handler);
const validateHost = localhostHostValidation();
const validateOrigin = localhostOriginValidation();

createHttpServer((req, res) => {
  if (!validateHost(req, res) || !validateOrigin(req, res)) return;
  void nodeHandler(req, res);
}).listen(3000, '127.0.0.1');
npx tsx src/http.ts

ローカルの接続先はPH_12_です。外部公開ではExpress、Fastify、HonoまたはWeb標準ランタイム向けの公式アダプターを選び、Host・Origin検証と認証をハンドラーの前段へ置きます。createMcpHandler自体はトークンを検証しないため、検証済みの認証情報だけをauthInfoへ渡します。旧v1のStreamableHTTPServerTransport例を混ぜないでください。

プロトコル移行時の接続処理を比較したい場合は、内部記事のStreamable HTTPのクライアント・サーバー実装ガイドも参照してください。

図解4:stdioとStreamable HTTPの分岐

手順7:HTTP公開に認証とHost制限を加える

HTTPへ切り替えただけでは公開準備は終わりません。MCP Python SDKの現行ドキュメントは、リモートサーバーをOAuth 2.1のリソースサーバーとして扱います。MCPサーバー自身がログイン画面やトークンを発行するのではなく、認可サーバーが発行したBearer tokenを各リクエストで検証します。

公式SDKではTokenVerifierとAuthSettingsを対で設定します。重要なのは、認証用に空のサーバーを別途作らないことです。サーバー生成を関数へまとめ、その認証済みインスタンスへtool・resource・promptの3機能を登録します。次のLocalTestVerifierだけは仕組みを確認するローカルテスト用です。

動作環境:Python 3.10以上、MCP Python SDK v2、Pydantic。

注意:本番環境で使用する前に、必ずテスト環境で動作確認してください。コード内へ実際のトークンやクライアントシークレットを書かないでください。

from pydantic import AnyHttpUrl

from mcp.server import MCPServer
from mcp.server.auth.provider import AccessToken, TokenVerifier
from mcp.server.auth.settings import AuthSettings

LOCAL_RESOURCE = "http://127.0.0.1:8000/mcp"


class LocalTestVerifier(TokenVerifier):
    async def verify_token(self, token: str) -> AccessToken | None:
        if token != "local-test-token":
            return None
        return AccessToken(
            token=token,
            client_id="local-test-client",
            scopes=["notes:read"],
            resource=LOCAL_RESOURCE,
        )


def create_protected_server(
    verifier: TokenVerifier,
    issuer_url: str,
    resource_url: str,
) -> MCPServer:
    server = MCPServer(
        "Workspace Helper",
        token_verifier=verifier,
        auth=AuthSettings(
            issuer_url=AnyHttpUrl(issuer_url),
            resource_server_url=AnyHttpUrl(resource_url),
            required_scopes=["notes:read"],
            validate_token_resource=True,
        ),
    )

    @server.tool()
    def add(a: int, b: int) -> int:
        """Add two integers."""
        return a + b

    @server.resource("guide://policy")
    def usage_policy() -> str:
        """Return the usage policy."""
        return "外部送信の前に、内容と宛先を人が確認する。"

    @server.prompt(name="review-request")
    def review_request(subject: str) -> str:
        """Create a review request for a subject."""
        return f"{subject}を、事実・機密情報・宛先の3点で確認してください。"

    return server


# local_auth_server.py専用。公開用server.pyへコピーしない
local_mcp = create_protected_server(
    LocalTestVerifier(),
    "https://auth.example.com",
    LOCAL_RESOURCE,
)

# SDK既定のlocalhost向けHost保護を使う
local_app = local_mcp.streamable_http_app()

このインスタンスにも3機能が登録されるため、認証を追加した結果、toolなどが消える事故を防げます。Streamable HTTPで起動すると、SDKは保護対象リソースのメタデータを公開し、無認証リクエストへ401 Unauthorizedを返します。stdioにはAuthorizationヘッダーがないため、このOAuth境界は適用されません。stdioの防御は、誰がプロセスを起動できるか、どの環境変数・ファイルへアクセスできるかで設計します。

公開用へ切り替える条件:LocalTestVerifierを削除し、JWTの署名・発行者・有効期限・audienceを検証する実装、またはRFC 7662のintrospection endpointへ問い合わせる実装をverifierへ渡します。公式SDKリポジトリのsimple-auth例にはIntrospectionTokenVerifierを使う構成があります。さらにresource_urlと、検証器が返すAccessToken.resourceを、クライアントが接続する完全一致の公開URL(例:PH_15_)へそろえます。認可基盤が独自のaudience識別子を使う場合は、検証器の中でaudienceを照合し、不一致ならNoneを返します。

ここまでをlocal_auth_server.pyとして保存し、local_appはローカルの401・resource・scope検証だけに使います。このファイルを公開用のserver.pyへ改名したり、固定トークンのまま外部へ出したりしません。

Pythonは公開用server.pyを別に作り、TLS終端の内側で起動する

公開用のserver.pyでは、同じcreate_protected_serverへ実際のTokenVerifier、認可サーバーのissuer、PH_16_を渡し、返された同じサーバーからapp = mcp.streamable_http_app(transport_security=security)を生成します。これにより、3機能、認証、Host・Origin制限が1つのASGIアプリへまとまります。

公開ホストではDNS rebinding対策のHost許可リストを明示します。Python SDKの既定はlocalhost向けに安全側へ倒れているため、公開用server.pyだけに実ドメインを設定します。

動作環境:Python 3.10以上、MCP Python SDK v2、ASGIサーバー。

注意:本番環境で使用する前に、必ずテスト環境で動作確認してください。許可するホストとOriginは実際の公開先だけに限定してください。

from mcp.server.transport_security import TransportSecuritySettings

security = TransportSecuritySettings(
    allowed_hosts=["mcp.example.com", "mcp.example.com:*"],
    allowed_origins=["https://app.example.com"],
)

# mcpは実TokenVerifierと公開HTTPS URLで生成済みのインスタンス
app = mcp.streamable_http_app(transport_security=security)

公開用ファイルを完成とみなす条件は4つです。

  • LocalTestVerifierを一切importせず、JWT署名検証またはRFC 7662 introspectionを行う検証器を使う
  • resource_server_urlとAccessToken.resourceを接続先の完全一致HTTPS URLへそろえる
  • 同じ認証済みMCPServerへtool・resource・promptを登録する
  • そのサーバーから生成したappだけをuvicornへ渡す

4条件を満たすまでは、次の公開起動コマンドへ進みません。MCPServerは本番向けのTLSやプロセス管理を提供しないため、公式のDeploy & scale手順に従い、完成したASGIアプリをTLS終端の内側で起動します。

動作環境:Python 3.10以上、MCP Python SDK v2、uvicorn、Host・Originを制限したapp。

注意:uvicornのポートをインターネットへ直接開かず、到達元をTLS終端のリバースプロキシに限定してください。転送元IPは実際のプロキシだけを指定します。

uv add uvicorn
uv run uvicorn server:app \
  --host 127.0.0.1 \
  --port 8000 \
  --proxy-headers \
  --forwarded-allow-ips='<reverse-proxy-ip>'

TLS終端側でPH_17_をこのプロセスへ転送し、この完全一致URLをcreate_protected_serverのresource_urlにも設定します。Inspectorと実際のクライアントで接続を確認し、無認証、期限切れ、異なるresource、scope不足をそれぞれ拒否できることを確かめます。421 Misdirected RequestならHost許可リスト、HTTPSからHTTPへのリダイレクト拒否ならプロキシヘッダー設定を先に見直します。複数プロセス化はSDKではなく、uvicornの--workersや利用する実行基盤で管理します。

公開前には、TLS終端、トークンのaudienceまたはresource検証、必要scope、タイムアウト、リクエストサイズ、レート制限、監査ログ、ツール単位の権限を確認します。特に「読み取りtoolだから安全」と決めつけず、取得した外部コンテンツにプロンプトインジェクションが含まれる前提で、モデルへ渡す範囲を狭めてください。

図解5:OAuth 2.1で分ける3者の責任

接続できないときに最初に見る5か所

失敗1:v1とv2のimportを混ぜる

❌ PythonでFastMCP、TypeScriptで@modelcontextprotocol/sdkの古い例をコピーし、v2パッケージへ継ぎ足す。

⭕ Pythonはfrom mcp.server import MCPServer、TypeScriptは@modelcontextprotocol/serverへ統一し、移行ガイドとインストール済みのメジャーバージョンを照合します。

なぜ重要か:クラス名だけでなく、登録メソッド、パッケージ構成、HTTPの入口も変わっているためです。

失敗2:stdioの標準出力へログを書く

❌ print()やconsole.log()でデバッグ文字列をstdoutへ出す。

⭕ Pythonはstderr向けのlogging、TypeScriptはconsole.errorを使います。

なぜ重要か:stdoutはMCPメッセージの通信路です。通常ログが混ざるとクライアントは接続を切ります。

失敗3:相対パスとシェルのPATHに依存する

❌ 設定にserver.pyだけを書き、自分のターミナルで動いたことを接続確認とする。

⭕ サーバーファイルを絶対パスにし、必要ならwhich uvまたはwhere uvでランタイムの絶対パスも確認します。

なぜ重要か:Claude DesktopやIDEは、普段のシェルと異なる作業ディレクトリ・最小限の環境変数で子プロセスを起動するためです。

失敗4:ローカルとリモートの設定方法を混同する

❌ Streamable HTTPのURLを、stdio用のcommand欄へ入れる。

⭕ ローカルはcommandとargs、リモートはHTTP URLとして登録します。Claude Codeでは--transport httpを明示します。

なぜ重要か:一方は子プロセス、もう一方はWebサービスであり、起動主体も認証境界も異なります。

失敗5:HTTP公開だけ済ませて認証とHost制限を後回しにする

❌ 開発用ポートを外部へ開き、Bearer token検証や許可ホストを設定しない。

⭕ 先にOAuth 2.1のリソースサーバー設計、Host・Origin許可リスト、HTTPS、最小scope、監査を決めてから公開します。

なぜ重要か:MCP toolは外部APIや社内データへ到達できるため、通常のWeb APIと同じか、それ以上に権限境界を明確にする必要があります。

よくある質問

MCPサーバーは何をするプログラムですか?

AIアプリケーションへ、tool・resource・promptを共通形式で提供するプログラムです。モデル本体を動かすサーバーではなく、モデルと業務ツール・データの間に置く接続層です。

PythonとTypeScriptはどちらがおすすめですか?

既存資産で選ぶのが安全です。Pythonのスクリプトや分析処理を公開するならPython、Node.jsのWeb APIや型付きのフロントエンド資産と一緒に管理するならTypeScriptが自然です。機能差だけで選ぶ必要はありません。

PythonのFastMCPはもう使えませんか?

公式Python SDK v2では高水準クラス名がFastMCPからMCPServerへ変わりました。v1系を保守する場合はその版のドキュメントを参照し、新規実装ではv2のimportへ揃えてください。別プロジェクトとして提供される同名ライブラリと公式SDKの旧クラス名も区別が必要です。

TypeScriptで旧パッケージを使う記事は間違いですか?

当時のv1向けとしては成立しますが、2026年10月2日時点の新規実装では分割されたv2パッケージが現行です。@modelcontextprotocol/serverを使い、v1のimportと混在させないでください。

最初からStreamable HTTPで作るべきですか?

1台の端末だけで使うならstdioから始める方が、認証・TLS・Webサーバーを切り離してtoolの設計を確認できます。複数人や複数端末で共有する要件がある場合にStreamable HTTPへ進みます。

SSEは使えなくなったのですか?

独立した旧HTTPとSSEのトランスポートは非推奨です。新規のリモートサーバーはStreamable HTTPを選んでください。ただしStreamable HTTPの応答でストリームが使われる場面まで消えた、という意味ではありません。

MCP Inspectorだけで動作確認は十分ですか?

単体確認には有効ですが、十分ではありません。Inspectorで一覧・入力検証・戻り値・エラーを確認した後、実際に使うClaude Desktop、Claude Code、Cursorでも接続し、権限確認と失敗時の表示まで確認します。HTTP公開時は無認証の401、誤ったHostの拒否、scope不足もテストしてください。

Claude Desktopの設定JSONへリモートURLを書けますか?

ローカルstdioの開発サーバーはclaude_desktop_config.jsonで起動コマンドを設定できます。一方、Anthropicの現行案内ではリモートMCPはCustomize > Connectorsから追加し、リモートURLをローカル設定JSONへ直接書く方法では接続しません。

Cursorではどこに設定を書きますか?

プロジェクト単位なら.cursor/mcp.json、全プロジェクト共通なら~/.cursor/mcp.jsonです。ローカルstdioはtypeをstdioにしてcommandとargsを指定し、リモートはurlを使います。

公開するならMCP Registryへの登録は必須ですか?

必須ではありません。社内専用サーバーは、認証された利用者だけがURLを知る構成でも運用できます。広く見つけてもらう配布と、安全に到達させる公開は別の判断です。先に認証・権限・運用責任を固めてください。

運営元 Uravation よりAIエージェントを構想から本番運用まで進める順番と、体制・KPIの決め方をまとめた資料を無料で公開しています。 AIエージェント導入ロードマップを受け取る(無料)

参考・出典

要点の整理

  1. 最初の1本:PythonならMCPServer、TypeScriptなら@modelcontextprotocol/server v2でtoolを1つ作ります。
  2. 接続前:MCP Inspectorでtools・resources・promptsの一覧、正常入力、異常入力を確認します。
  3. ローカル利用:絶対パスの起動コマンドをClaude Desktop、Claude Code、Cursorへ登録します。
  4. 共有利用:Streamable HTTPへ切り替え、OAuth 2.1、HTTPS、Host・Origin制限、最小scopeを揃えます。

最小構成で大切なのは、コードを短くすることではなく、toolの権限と入出力を小さく保つことです。stdioで1機能を確認し、接続先と利用者が増えるタイミングでHTTPと認証を足すと、原因を切り分けやすくなります。

あわせて読みたい:

この記事を読んで導入イメージが固まってきた方へ

UravationではAIエージェント導入の研修・コンサルを行っています。

この記事はAIgent Lab編集部がお届けしました。

Need help moving from reading to rollout?

この記事を読んで導入イメージが固まってきた方へ

Uravationでは、AIエージェントの要件整理、PoC設計、社内導入、研修まで一気通貫で支援しています。

この記事をシェア

X Facebook LINE

※ 本記事の情報は2026年10月時点のものです。サービスの料金・仕様は変更される可能性があります。最新情報は各サービスの公式サイトをご確認ください。

関連記事