今まであなたは間借り人でした。他の人が書いたMCPをインストールし、あなたのAIがそれを使う。それでいい。でも、それでは物足りなくなる瞬間が来ます——社内APIがある、データベースがある、あなたにしか分からないスクリプトがある。そして、その出力をチャットにコピペせずに、Claudeに直接触らせたいと思う。そこが、消費する側から公開する側へと変わる分岐点です。MCPサーバーは標準の差し込み口です。ツールを一度記述すれば、このプロトコルを話すどんなAIも、まるで自分のツールのように呼び出せます。FastMCPは、MCPの公式SDK(Anthropicが公開したもの)をラップするTypeScriptのフレームワークで、ボイラープレートをまるごと取り除いてくれます——ExpressがNodeのhttpモジュールに対してもたらしたのと同じ飛躍です。このガイドでは、stdio上の'add'ツールを15分で作るところから、自動で検証されるZodスキーマ付きのツール、データを公開するresources、再利用可能なprompts、そして最後には本物の本番環境まで進みます。認証、HTTPストリーミング、セッション、エッジ。最後には、Claude Codeが本気で呼び出す自分だけのMCPが手に入ります——デモではなく、あなたの世界につながった、あなたのパイプです。
何週間もAIをツールにつないできました。ブラウザを開けと頼めば開く。リポジトリを読めと頼めば読む。それらはすべて他の人が書いたMCPです——誰かが公開し、あなたがインストールした標準の差し込み口。うまくいくのは共通の言語を話しているからです。Model Context Protocol、どんなAIも外部ツールを発見して呼び出せるようにするオープンな標準で、特定のどれにも密結合しません。
その瞬間が来るのは、必要なものがMCPとして存在しないとき。注文の状態を返す社内エンドポイントがある。あなたにしか読めないスプレッドシートがある。あなたのドメイン固有の何かを計算する40行のスクリプトがある。今日、AIにそれを使わせたいたびに、あなたは使い走りのダンスを踊る。自分で実行し、出力をコピーし、チャットに貼り付け、待つ。一度なら機能します。10回目には、なぜAIが自分でやってくれないのかと自問することになります。
このリソースは一つの弧を閉じます。agent-browserでは、AIに世界を消費するための外部能力を与える方法を学びました——ページを見る、クリックする、抽出する。ここではカメラを反転させます。他のAIが消費できるよう、あなた自身の能力を公開する方法を学ぶのです。ユーザーから作者へ。同じプロトコルを、ケーブルの反対側から見るということです。
MCPの公式SDKを初めて開くと、レーシングカーのボンネットを開けたような感覚になります。すべてがそこにあり、すべてが正しく、そして何一つ自明ではない。ハンドラを手動で登録し、プロトコルのリクエストをマッピングし、クライアントが期待するまさにその形式でレスポンスをシリアライズし、接続のライフサイクルを管理し、入力パラメータを自力でパースして検証しなければならない。2つの数を足すたった一つのツールを公開するために、足し算をする行にたどり着く前に何十行もの配管工事を書くのです。
その痛みはどこから来るのか?公式SDKがわざと低レベルだからです。それは最終的なエルゴノミクスではなく、その上に構築するための土台です——ちょうどNodeのhttpモジュールが正しくても誰も直接それでWebサーバーを書かず、Expressを使うのと同じ。SDKはプロトコルへの完全なアクセスを与えます。その代償は、あなたがすべてのボイラープレートを背負うこと。フレームワークを作る人にはいい。自分のAPIを差し込みたいだけの人には手厳しい。
FastMCPは、まさにそのボイラープレートを消すために存在します。MCPの公式SDKをラップするTypeScriptのフレームワークで——置き換えるのではなく、その上に立つ——宣言的なAPIを与えてくれます。ツールとそのスキーマと関数を記述すれば、あとはFastMCPが引き受ける(登録、シリアライズ、接続ライフサイクル、検証)。足し算のツールは、あの配管工事の絡まりから、ほんの十数行に変わります。しかもそれは重要な行です。本当に足し算をする行なのです。
ボイラープレートなしでMCPサーバーを構築するTypeScriptのフレームワーク。MCPの公式SDK(@modelcontextprotocol/sdk、Anthropicが公開したもの)の上に立ち、スキーマ検証付きのツール(Zodやその他のStandard Schema)、resources、prompts、認証、HTTPストリーミング、セッション、開発用CLIを追加します。アイデアから、Claudeが本当に呼び出すMCPサーバーへ最速でたどり着く方法。
MCPサーバーの公開は、一度やって忘れるものではありません。特定の瞬間に発動する反射です。それを見分けられるようになれば、構築に時間をかける価値がいつあるかが常に分かります。
FastMCPはどんなnpmパッケージとも同じようにインストールできます。TypeScriptで動く現代のNode上で走ります。最小の新規プロジェクトは、3つのファイルが入った一つのフォルダに収まります。
# サーバー用の新しいフォルダで mkdir mi-mcp && cd mi-mcp npm init -y # FastMCP + Zod(各ツールの入力スキーマ用)+ tsx(コンパイルせずにTSを走らせる用) npm install fastmcp zod npm install -D tsx typescript
aは数値、emailはメール形式の文字列、edadはオプションの整数。FastMCPはそのスキーマを取り、2つのことを無料でやります。(1)ツールがどんなパラメータを期待するかをクライアントに伝え、AIが正しく埋められるようにする。(2)入力があなたのコードに届く前に検証する。AIがゴミを送っても、それを弾くのはあなたの関数ではなくスキーマです。書かなくていい門番。(FastMCPは同じ標準の他のバリデータ——ArkType、Valibot——も受け入れますが、Zodが最も踏み固められた道です。)MCPの'ハローワールド'から始めます。2つの数を足すツール一つだけのサーバー。わざと単純にしてあります——面白いのは足し算ではなく、ケーブル全体を見ることです。サーバーを定義し、スキーマ付きのツールを登録し、起動し、Claudeがそれを呼び出す。この骨格さえできれば、あとはすべてバリエーションです。
// server.ts
import { FastMCP } from "fastmcp";
import { z } from "zod";
const server = new FastMCP({
name: "Mi Servidor",
version: "1.0.0",
});
server.addTool({
name: "add",
description: "Suma dos números",
parameters: z.object({
a: z.number(),
b: z.number(),
}),
execute: async (args) => {
return String(args.a + args.b);
},
});
server.start({
transportType: "stdio",
});上から下まで読んでください。このパターンは、あなたが構築するすべてで繰り返されます。new FastMCPは名前とバージョンを持つサーバーを作ります——それがClaudeの接続リストに表示されるものです。addToolはツールを登録します。名前(AIがそれで呼び出す)、説明(AIがそれを読んでいつ使うか判断する——うまく書きましょう、機械に向けたマーケティングです)、Zodスキーマとしてのparameters、そして本当に走る関数execute。文字列を返せば、FastMCPがプロトコルの形式で包んでくれます。
transportType: "stdio"は、サーバーが標準入力と標準出力——ターミナルのプログラムがテキストを受け取り出力するのと同じチャンネル——で話すことを意味します。最もシンプルなトランスポートです。クライアント(Claude Code)はサーバーをサブプロセスとして起動し、そのパイプ越しに会話します。ネットワークゼロ、ポートゼロ、設定ゼロ。自分のローカルツールに最適です。インターネット越しに公開したくなったら、このトランスポートをHTTPに変えます——でも始めるにはstdioで十分です。Claudeに差し込む前に、単独で試しましょう。FastMCPにはサーバーを起動して対話できるCLIが付いており、加えて視覚的なインターフェースで見るためのMCPの公式Inspectorもあります。これがあなたの開発ループです。コードを変え、ここで試し、動いたときにだけ本物のクライアントにつなぐ。
# 開発モードでサーバーを起動(ツールと対話する) npx fastmcp dev server.ts # MCP Inspectorで開く(tools/resources/promptsを検査する視覚的インターフェース) npx fastmcp inspect server.ts
npx fastmcp devを作業台として使いましょう。そこで生のエラー、正確な出力、サーバーが公開するそのままのスキーマが見えます。ツールが望みどおりに動いたときにだけ、クライアントにつなぐ一歩を踏み出す。ifを試すために本番にデプロイしないのと同じ——まずローカルで試すのです。ここで演習が終わり、本物になります。MCPクライアント(Claude Desktop、Claude Code)はサーバーをサブプロセスとして起動し、stdioで話しかけます。必要なのはどう起動するかを知ることだけ。どのコマンドとどの引数か。それはMCPサーバーのリストが入った設定ファイルに宿ります。
{
"mcpServers": {
"mi-servidor": {
"command": "npx",
"args": ["tsx", "/ruta/absoluta/a/mi-mcp/server.ts"]
}
}
}commandはサーバーを起動する実行ファイル、argsはその引数です——ここではnpx tsxを使ってTypeScriptをコンパイルせず直接走らせます。絶対パスを使ってください。クライアントはどのフォルダから起動するか知りません。保存してクライアントを再起動すると、サーバーがリストに現れ、Claudeに「128と45を足して」と頼めば、頭の中で計算する代わりにあなたのツールaddを呼び出すのが見えます。その瞬間——AIが自分で呼び出す、あなた初のツール——が病みつきにさせるものです。
argsに相対パス(./server.ts)を入れることです。クライアントはその作業ディレクトリからサブプロセスを起動するので、あなたのディレクトリではなく、./server.tsは虚空を指し、サーバーは起動しません——たいてい静かに。もしMCPが現れないか接続に失敗したら、まずこれを確認してください。絶対パス、常に。addツールはZodを最小限に使っていました。でも本当の力は、入力が形とルールを持つ現実のツールで現れます。ユーザーを作るツールを想像してください。emailはメール形式でなければならず、年齢は正の整数でなければならず、ロールはリストの一つでなければならない。Zodなら、それをすべて記述し、FastMCPが無効な入力があなたのコードに触れる前に弾きます。if (!email.includes('@'))を書くことは決してありません。スキーマが門番です。
server.addTool({
name: "crear_usuario",
description: "Crea un usuario en el sistema con validación completa",
parameters: z.object({
nombre: z.string().min(2),
email: z.string().email(),
edad: z.number().int().positive().optional(),
rol: z.enum(["admin", "editor", "lector"]),
}),
execute: async (args) => {
// Si llegaste aquí, args YA está validado: email es email, rol es válido.
const usuario = await miBaseDeDatos.insertar(args);
return `Usuario ${usuario.id} creado con rol ${args.rol}`;
},
});executeの中でargsはTypeScriptで型付けされ、オートコンプリートが効く。検証し、ドキュメント化し、型付けする、たった一つのコードブロック。これは公式SDKがあなたに手で3回書かせていたものです。ツールは動詞です——AIが何かを起こすために実行します。でも時にはアクションではなく、コンテキストを与えたい。ログファイル、設定ドキュメント、READMEの中身。そのためにresourcesがあります。サーバーが公開するデータで、AIが必要なときに読めるものです。URIで識別されます。ツールをリモコンのボタン、resourcesを情報を表示する画面だと考えてください。
server.addResource({
uri: "file:///logs/app.log",
name: "Logs de la Aplicación",
mimeType: "text/plain",
async load() {
const contenido = await fs.readFile("/var/log/app.log", "utf-8");
return { text: contenido };
},
});uriはresourceの一意な識別子です——クライアントはそれを使って要求します。mimeTypeはコンテンツの種類(プレーンテキスト、JSON、markdown)をAIに伝え、正しく解釈させます。そしてloadは、誰かが要求したときにコンテンツを取ってくる関数です——設計上、遅延的です。必要になるまでファイルを読みません。バイナリデータには{ text }の代わりにbase64の{ blob }を返します。resourceは「AIよ、必要なときに新鮮なデータをここに置いておくよ」と、まさにその瞬間までプロンプトで消費せずに言う、きれいなやり方です。
プロトコルの三つ目の要素はpromptsです。しょっちゅう使うテンプレートがあるなら——'このdiffからコミットメッセージを生成する'、'この会議をこの形式で要約する'——MCPのpromptが名前と引数付きでそれをパッケージ化し、どのクライアントも呼び出せます。同じ長い指示をコピペするのをやめ、サーバーのもう一つの能力として提供するのです。
server.addPrompt({
name: "git-commit",
description: "Genera un mensaje de commit a partir de un diff",
arguments: [
{
name: "changes",
description: "El diff de git o una descripción de los cambios",
required: true,
},
],
load: async (args) => {
return `Genera un mensaje de commit conciso para estos cambios:\n${args.changes}`;
},
});これまではすべてstdioで走っていました。ローカル、あなたのもの、あなたのマシンのサブプロセス。始めるには完璧です。でも他の人にMCPを使わせたくなったら——チーム、顧客、あるいは複数の場所からのあなた自身——インターネット越しに公開する必要があります。そこでHTTPストリーミングのトランスポートが登場します。ローカルのパイプの代わりに、サーバーがポートで待ち受け、イベントストリーミングでHTTP応答します。ツールのコードは一行も変わりません。変わるのは起動の仕方だけです。
server.start({
transportType: "httpStream",
httpStream: {
port: 8080,
endpoint: "/mcp", // opcional, por defecto es /mcp
},
});それがスイッチ全体です。同じツール、同じresources、同じprompts——今度はポート8080、エンドポイント/mcpのHTTPで提供されます。リモートのクライアントはhttps://tu-dominio/mcpを指して差し込みます。ここであなたのMCPは個人ツールでなくなり、サービスになります。そしておもちゃと製品を分ける問いが現れます。誰がそれを呼べるのか?
認証なしのHTTP越しのMCPは、開けっ放しのドアです。URLを知る誰もがあなたのツールを呼び、データベースに触れ、リソースを消費する。FastMCPはこれをauthenticateオプションで解決します。各接続で走る関数で、リクエスト(ヘッダー、APIキー、トークン)を検査し、通すかどうか決めます。通すなら、各ツールの中で使えるセッションオブジェクトを返します。
const server = new FastMCP({
name: "Mi Servidor",
version: "1.0.0",
authenticate: (request) => {
const apiKey = request.headers["x-api-key"];
if (apiKey !== process.env.MCP_API_KEY) {
throw new Response(null, { status: 401, statusText: "Unauthorized" });
}
return { id: 1, role: "user" }; // esto se vuelve la sesión
},
});
server.addTool({
name: "sayHello",
execute: async (args, { session }) => {
return `Hola, usuario ${session.id}!`; // session viene de authenticate
},
});authenticateが検証するトークン。両者はライバルではありません。本番のMCPは錠前付きのパイプです。錠前がなければ、あなたのパイプは誰もが開ける公共の蛇口です。process.env.MCP_API_KEYに注目してください。キーは決してコードに直書きせず、gitにアップしません——シークレットのリソースと同じ黄金律です。リポジトリの外、環境変数かシークレットマネージャーに。キーをハードコードしたMCPは、ドアに'施錠'とペイントしたが本物の錠がないMCPです。コードを見る誰もが、入れます。現実のツールは瞬時ではありません。大きなファイルを処理するツール、遅いAPIを呼ぶツール、コンテンツを生成するツールは数秒かかります。FastMCPはexecuteの中で、そのツールが息をするためのツール群を含むコンテキストを与えます。進捗の報告、コンテンツのストリーミング出力、ログ、そして認証済みユーザーのセッションへのアクセスです。
server.addTool({
name: "procesar_lote",
description: "Procesa un lote reportando progreso en vivo",
parameters: z.object({ total: z.number() }),
annotations: { streamingHint: true },
execute: async (args, { streamContent, reportProgress, log, session }) => {
log.info(`Iniciando lote para ${session.id}`);
await streamContent({ type: "text", text: "Empezando..." });
await reportProgress({ progress: 50, total: 100 });
// ... trabajo real ...
return "Completado";
},
});reportProgress({ progress, total })はクライアントに'50%まで来た'と伝え、AI(と人間)は苦しい沈黙の代わりにバーを見ます。streamContentは生成されるにつれ出力を小分けに出し、最後まで待ちません——テキストが現れるのを見るか、スピナーを眺めるかの違いです。logはデバッグ用の構造化された痕跡を残します。そしてsessionはauthenticateが検証したユーザーなので、各ツールは誰が呼んでいるかを知ります。これらで、あなたのツールは時間のかかるブラックボックスであることをやめ、観測可能なプロセスになります。
ここに、保存すべき唯一のプロンプトがあります。サーバーを手で書く代わりに、AIに——このガイドのFastMCPのコンテキストをすべて目の前に持っているAIに——それを説明すれば、完全な骨格をテスト済み、接続準備完了の状態で生成してくれます。角括弧を実際のケースで埋め、構築させましょう。一つのプロンプトだけ、五つではありません。これがプロジェクト全体を立ち上げます。
MCPのシニアエンジニアとして振る舞ってください。FastMCPを使ってTypeScriptでMCPサーバーを構築します(MCPの公式SDK、Anthropicが公開したものをラップするフレームワークで、`npm install fastmcp zod`でインストールします)。
私のサーバー:
- 名前:[サーバーの名前、例「社内CRM」]
- 何を公開するか:[AIに触らせたいツール/データを2行で説明]
必要なツール(AIが実行するアクション):
1. [tool_name] — [何をするか] — 入力:[フィールドとその型/ルール]
2. [tool_name] — [何をするか] — 入力:[フィールドとその型/ルール]
RESOURCES(AIが読むデータ、該当する場合):
- [名前] — [どんなデータを公開するか、例:ログ、設定]
モード:[開発用に「ローカルstdio」から始める | その後、本番用に「APIキー認証付きhttpStream」へ移行する]
構築せよ:
1. 完全なserver.ts:名前とバージョン付きの`new FastMCP`、各ツールを`addTool`で(name、AIがいつ使うか分かるよう明確な説明のdescription、本当に検証するZodスキーマとしてのparameters——該当箇所で.email()、.int().positive()、.enum()、そしてオプションには.optional()、型付けされたexecute)。
2. resourcesを`addResource`で(uri、name、mimeType、{text}か{blob}を返す遅延loadを持つ)、頼んだ場合。
3. 選んだトランスポートでの`server.start`(stdioか、port/endpoint付きのhttpStream)。
4. 本番を頼んだ場合:`process.env`からAPIキーを読む`authenticate`オプション(決してハードコードしない)、合わなければ`new Response(null, {status: 401})`を投げてセッションを返す、加えて`session`を使うツール。
5. Claude Codeにつなぐための`mcpServers`のJSONブロック、`npx tsx`と絶対パスで。
6. 正確なコマンド:インストール、`npx fastmcp dev server.ts`でのテスト、`npx fastmcp inspect server.ts`での検査。
制約:コードにシークレットゼロ。ツールの説明はAIがいつ呼び出すか正しく判断できるよう書く。あらゆる入力を手動のifではなくZodで検証する。各ツールをコードの前に一行で説明せよ。npx fastmcp devで試せる最小限。それが動いてClaudeが本当に呼び出したら、同じプロンプトに戻ってモードを認証付きの本番に変える。こうして、試さずに巨大なサーバーを吐き出す代わりに、検証可能な層で構築します。そしていつもの習慣を適用しましょう。まず動く骨格のコミット、それから残り。MCPの公開には、あなたがどこに立っているかで二つの道があり、いつどちらを取るか知っておくとよいでしょう。
server.tsを生成します。mcpServersブロックと、差し込む前に試すためのfastmcp devのコマンドをくれます。npx fastmcp inspect server.tsが視覚的なInspectorを開きます——そこでツール、resources、promptsをクライアントが見るように見られます。一歩下がって道を見てください。あなたは他の人が書いたMCPを消費するところから始めました——AIは他人のツールを使っていた。agent-browserで、世界を見て触る能力を与えることを学んだ。そしてここで、FastMCPとともにカメラを反転させた。今やあなたは、どんなAIも消費できる自分自身の能力を公開する。15分のaddツールが、Zod・resources・prompts・認証・HTTPを備えたツールになった。ユーザーから作者への弧を閉じた。あなたはもうMCPエコシステムの間借り人ではありません。差し込み口の所有者です。
Join 4,200+ builders. No credit card. Build your first app with AI in minutes.