MCPサーバー自作入門(TypeScript)

5
スポンサーリンク
※ 本記事には広告・PR(アフィリエイト)リンクが含まれています

📋 Claude Code コマンド指示書(クリックで展開)

.claude/commands/ に保存して /コマンド で実行

---
description: "MCPサーバー自作入門(TypeScript)"
---

# MCPサーバー自作入門(TypeScript)

この指示書は https://akahara-vlab.com/mcp-server-typescript-guide/ の内容をClaude Codeコマンドとして実行するためのものです。

## 概要

MCPサーバー自作入門

## 使い方

1. このテキストを `.claude/commands/mcp-server-typescript-guide.md` に保存
2. Claude Codeで `/mcp-server-typescript-guide` と入力して実行

## 指示

上記の記事の知識をもとに、ユーザーの質問に回答してください。
記事URL: https://akahara-vlab.com/mcp-server-typescript-guide/

※ 平文なので中身を確認してから使ってください。安全性は目視で確認できます。


この記事でわかること
– MCP(Model Context Protocol)の仕組みと3つの提供物
– TypeScriptでMCPサーバーをゼロから作る手順
– ツール・リソース・プロンプトの実装方法
– Claude Codeへの登録と動作確認

Claude Codeに「社内DBを直接クエリしてほしい」「自社APIを叩いてほしい」——そんな要望に応えるのがMCPサーバー自作だ。

MCPはAnthropicが策定したオープンプロトコルで、AIクライアントに外部ツールを接続するための標準仕様。TypeScriptの公式SDKを使えば、30分程度で独自のMCPサーバーが作れる。


スポンサーリンク

MCPが提供できる3つのもの

種類説明
ToolsAIが呼び出せる関数DB検索・API呼び出し・ファイル変換
ResourcesAIが読めるデータソースファイル・DB・ログ・設定値
Prompts再利用可能なプロンプトテンプレートコードレビュー定型・ドキュメント生成

今回はToolsの実装をメインに、Resourcesも触れる。


セットアップ

mkdirmy-mcp-server
cdmy-mcp-server
npminit-y
npminstall@modelcontextprotocol/sdk
npminstall-Dtypescript@types/nodetsx
npxtsc--init

tsconfig.json を調整:

{
 "compilerOptions":{
   "target":"ES2022",
   "module":"Node16",
   "moduleResolution":"Node16",
   "outDir":"./dist",
   "strict":true,
   "esModuleInterop":true
 },
 "include":["src/**/*"]
}

最小構成のMCPサーバー

src/index.ts を作る:

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

constserver=newMcpServer({
 name:"my-mcp-server",
 version:"1.0.0",
});

// ツールを定義
server.tool(
 "add",                         // ツール名
 "2つの数を足す",                // 説明(AIが使い方を判断する)
 {
   a:z.number().describe("1つ目の数"),
   b:z.number().describe("2つ目の数"),
 },
 async({a,b})=>({
   content:[{type:"text",text:String(a+b)}],
 })
);

// stdioトランスポートで起動
consttransport=newStdioServerTransport();
awaitserver.connect(transport);

これで動くMCPサーバーの完成。ツール名・説明・入力スキーマ・ハンドラの4つを書くだけだ。


実践例:天気APIを叩くツール

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

constserver=newMcpServer({
 name:"weather-server",
 version:"1.0.0",
});

server.tool(
 "get_weather",
 "指定した都市の現在の天気を取得する",
 {
   city:z.string().describe("都市名(例: Tokyo, Osaka)"),
 },
 async({city})=>{
   constapiKey=process.env.WEATHER_API_KEY;
   constres=awaitfetch(
     `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}&units=metric&lang=ja`
   );

   if(!res.ok){
     return{
       content:[{type:"text",text:`エラー:${res.status}${res.statusText}`}],
       isError:true,
     };
   }

   constdata=awaitres.json()as{
     name:string;
     main:{temp:number;humidity:number};
     weather:Array<{description:string}>;
   };

   return{
     content:[{
       type:"text",
       text:`${data.name}:${data.weather[0].description}, 気温${data.main.temp}℃, 湿度${data.main.humidity}%`,
     }],
   };
 }
);

consttransport=newStdioServerTransport();
awaitserver.connect(transport);

実践例:SQLiteを直接クエリするツール

社内ツールや個人プロジェクトでよくあるパターン。

npminstallbetter-sqlite3
npminstall-D@types/better-sqlite3
importDatabasefrom"better-sqlite3";
import{McpServer}from"@modelcontextprotocol/sdk/server/mcp.js";
import{StdioServerTransport}from"@modelcontextprotocol/sdk/server/stdio.js";
import{z}from"zod";

constdb=newDatabase(process.env.DB_PATH??"./data.db");

constserver=newMcpServer({
 name:"sqlite-server",
 version:"1.0.0",
});

// SELECT専用(書き込みは別ツールに分離してリスク管理)
server.tool(
 "query_db",
 "SQLiteデータベースにSELECTクエリを実行する",
 {
   sql:z.string().describe("実行するSELECT文"),
   limit:z.number().default(50).describe("最大行数"),
 },
 async({sql,limit})=>{
   // SELECT以外は拒否
   if(!/^s*SELECT/i.test(sql)){
     return{
       content:[{type:"text",text:"SELECTクエリのみ許可されています"}],
       isError:true,
     };
   }

   constrows=db.prepare(`${sql} LIMIT${limit}`).all();
   return{
     content:[{type:"text",text:JSON.stringify(rows,null,2)}],
   };
 }
);

server.tool(
 "list_tables",
 "データベースのテーブル一覧を返す",
 {},
 async()=>{
   consttables=db
     .prepare("SELECT name FROM sqlite_master WHERE type='table'")
     .all()asArray<{name:string}>;
   return{
     content:[{type:"text",text:tables.map(t=>t.name).join(", ")}],
   };
 }
);

consttransport=newStdioServerTransport();
awaitserver.connect(transport);

Resourcesの実装

ToolsはAIが能動的に呼ぶ関数だが、Resourcesは「読めるデータ」として公開する仕組みだ。

// ログファイルをリソースとして公開
server.resource(
 "app-logs",
 "logs://app/latest",
 async(uri)=>{
   constcontent=awaitfs.readFile("/var/log/app.log","utf-8");
   constlines=content.split("n").slice(-100).join("n");// 直近100行

   return{
     contents:[{
       uri:uri.href,
       mimeType:"text/plain",
       text:lines,
     }],
   };
 }
);

Claude Codeへの登録

~/.claude/settings.json に追記:

{
 "mcpServers":{
   "my-mcp-server":{
     "command":"node",
     "args":["/path/to/my-mcp-server/dist/index.js"],
     "env":{
       "WEATHER_API_KEY":"your-api-key",
       "DB_PATH":"/path/to/data.db"
     }
   }
 }
}

TypeScriptをビルドせず tsx で直接実行する場合:

{
 "mcpServers":{
   "my-mcp-server":{
     "command":"npx",
     "args":["tsx","/path/to/my-mcp-server/src/index.ts"]
   }
 }
}

登録後、Claude Codeを再起動すれば自動的にMCPサーバーが接続される。Claude Codeに「天気を調べて」と話しかけると、定義した get_weather ツールを呼び出してくれる。


セキュリティ上の考慮点

ツール名・説明は攻撃者に見える

MCPサーバーの情報はAIに渡されるため、悪意あるプロンプトでツールを悪用しようとする攻撃が成立しうる。特にDBアクセス系ツールは「SELECT専用」「対象テーブルを限定」など最小権限で設計する。

環境変数でシークレット管理

APIキー・DB接続文字列はコードに直書きせず、env フィールドで渡す。settings.jsonはgit管理外(~/.claude/ 配下)に置く。

信頼できないMCPサーバーを追加しない

claude-code-third-party-skills-securityで書いたように、野良MCPサーバーはプロンプトインジェクションのベクターになりうる。自作か信頼できるソースのものだけを使う。


まとめ

// 最小構成テンプレート
constserver=newMcpServer({name:"...",version:"1.0.0"});

server.tool("tool_name","説明",{param:z.string()},async({param})=>({
 content:[{type:"text",text:"結果"}],
}));

awaitserver.connect(newStdioServerTransport());

やること:
1. npm install @modelcontextprotocol/sdk
2. ツール定義(名前・説明・スキーマ・ハンドラ)
3. settings.json に登録

この3ステップだけ。Claude Codeに独自のDB・API・ファイル操作を追加したいなら、まず小さいツールを1つ作って動作確認するのが早道だ。


あわせて読みたい


参考: Model Context Protocol Documentation, @modelcontextprotocol/sdk (npm)


{
“@context”: “https://schema.org”,
“@type”: “FAQPage”,
“mainEntity”: [
{
“@type”: “Question”,
“name”: “MCPサーバーとは何ですか?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Model Context Protocol(MCP)に対応したサーバーです。Claude CodeなどのAIクライアントに「ツール」「リソース」「プロンプト」を提供します。自作することでClaude Codeに独自の機能(社内APIへのアクセス、ファイル変換、DBクエリなど)を追加できます。”
}
},
{
“@type”: “Question”,
“name”: “MCPサーバーを作るのに必要なものは何ですか?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Node.js 18以上とTypeScriptの基本的な知識があれば作れます。@modelcontextprotocol/sdkパッケージが公式SDKです。Claude Codeに登録するだけで利用でき、API認証は不要です。”
}
},
{
“@type”: “Question”,
“name”: “MCPサーバーはClaude Codeにどうやって登録しますか?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “~/.claude/settings.jsonのmcpServersフィールドに追加します。nameとcommand(起動コマンド)を指定するだけで、Claude Code起動時に自動接続されます。”
}
}
]
}

見てもらえるだけで応援になります

このブログはアフィリエイトリンクで運営されています。以下のリンクから気になるサービスをチェックしてもらえると、僕たちの活動の支えになります。


この記事を書いたのは わさび(ニホンイシガメ / 3歳 / VTuberあかはら。の家族)です。

あかはらVラボ — Claude特化の情報を発信中。

この記事が参考になったら|以下のリンクから見てもらえるだけで、ブログ運営の応援になります。




  • MCP自作ツールの実運用はVPS環境が便利です。

コメント

タイトルとURLをコピーしました