1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeScript版の公式SDK で自作MCPクライアントを試す(自作MCPサーバーのツール利用)

Posted at

はじめに

今回の記事の内容は、TypeScript版の公式SDK で自作MCPクライアントを試してみます。

MCP関連で試していたこと: 自作MCPサーバーの話

MCP関連の話で、過去に既存の MCPサーバーを試した後、自作MCPサーバーを試しましていました。具体的には、以下の TypeScript版の公式SDK を使ったものと、TypeScript版の FastMCP を使った自作MCPサーバーです。

●シンプルな自作MCPサーバーを VS Code に設定して GitHub Copilot の Agent mode で利用(Node.js で TypeScript を直接扱う) - Qiita
 https://qiita.com/youtoy/items/1d46724e40ab96607b18

●TypeScript版の FastMCP を少し試す(自作MCPサーバー) - Qiita
 https://qiita.com/youtoy/items/22bcaf99fe4444fe8215

今回試す内容

それで、ふと MCPクライアントや MCPホストの自作も試してみようと思い、今回は以下の TypeScript版の公式SDK を使った MCPクライアントの自作を試しました。

●modelcontextprotocol/typescript-sdk: The official Typescript SDK for Model Context Protocol servers and clients
 https://github.com/modelcontextprotocol/typescript-sdk?tab=readme-ov-file

自作MCPクライアントで行う処理は、冒頭に書いていた自作MCPサーバーのツールの一覧取得と、簡単なツールの利用になります。

MCPクライアントを実装する

MCPクライアントについて

MCPクライアントを作る前に、少し MCPクライアントの位置付けについて公式情報などを見ておきます。

以下の「公式ドキュメントの General architecture」を見てみます。

image.png

例えば「自作MCPサーバーを Claudeデスクトップで使う」という構成の場合、上記の図の真ん中の部分が自作MCPサーバーに該当します。
そして Claudeデスクトップは、図の左の「Host with MCP Client」という部分に含まれるようです。

また図の下の説明を見ると、ホスト・ツールに関しては以下のように書かれています。

  • MCP Hosts: Programs like Claude Desktop, IDEs, or AI tools that want to access data through MCP
  • MCP Clients: Protocol clients that maintain 1:1 connections with servers

Claudeデスクトップは MCPホストにあたり、そのホストがサーバーと接続するのに使うのがクライアントになるようです。

他の説明

その他、MCPサーバー・クライアント・ホストの説明・図が書かれた記事を見かけたので、それも該当箇所などを掲載してみます。

●最小限のMCP Host/Client/Serverをスクラッチで実装する
 https://zenn.dev/razokulover/articles/9a0aee8ceb9f3f

image.png

クライアントが接続する先の自作サーバーについて

今回、前に作成した自作MCPサーバーへの接続・ツールの利用を試します。
それらについて、実装内容だけ補足しておきます。

今回、TypeScript版の公式SDK を使ったものと、TypeScript版の FastMCP を使ったものの両方を利用してみます。

TypeScript版の公式SDK を使ったもの

過去に作った MCPサーバーのうち、TypeScript版の公式SDK を使ったものの内容は以下でした。

app.mjs
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",
  version: "1.0.0",
});

server.tool(
  "add_test",
  "与えられた数値の足し算をする(さらに10を足す)",
  { a: z.number(), b: z.number() },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b + 10) }],
  })
);

const transport = new StdioServerTransport();
await server.connect(transport);

"add_test" という名前でツールを実装していました。
また、処理の内容は、入力された 2つの数字に 10を加算した値を返すというものでした。

TypeScript版の FastMCP を使ったもの

もう1つ作成した MCPサーバーは、以下の TypeScript版の FastMCP を使って実装したものです。

image.png

コードは、以下のとおりです。

app.mjs
import { FastMCP } from "fastmcp";
import { z } from "zod";

const server = new FastMCP({
  name: "My Server",
  version: "1.0.0",
});

server.addTool({
  name: "add",
  description: "2つの数を足して、さらに5を足す",
  parameters: z.object({
    a: z.number(),
    b: z.number(),
  }),
  execute: async (args) => {
    return String(args.a + args.b + 5);
  },
});

server.start({
  transportType: "stdio",
});

基本的な処理は、1つ目と同じです。

1つ目との違いとしてはツールの名前が少し異なる "add" というものになっていたり、処理の中身で入力された 2つの数字に対して加算する値が 5 になっていたりする部分です。

TypeScript版の公式SDK を使った MCPクライアントの実装

それでは、以下の GitHubリポジトリの「Writing MCP Clients」という部分を参考にしつつ、TypeScript版の公式SDK で MCPクライアントを作ってみます。

※●modelcontextprotocol/typescript-sdk: The official Typescript SDK for Model Context Protocol servers and clients
 https://github.com/modelcontextprotocol/typescript-sdk?tab=readme-ov-file#writing-mcp-clients

image.png

公式で示されている実装

公式で示されている実装は以下のとおりです。

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

const transport = new StdioClientTransport({
  command: "node",
  args: ["server.js"]
});

const client = new Client(
  {
    name: "example-client",
    version: "1.0.0"
  }
);

await client.connect(transport);

// List prompts
const prompts = await client.listPrompts();

// Get a prompt
const prompt = await client.getPrompt({
  name: "example-prompt",
  arguments: {
    arg1: "value"
  }
});

// List resources
const resources = await client.listResources();

// Read a resource
const resource = await client.readResource({
  uri: "file:///example.txt"
});

// Call a tool
const result = await client.callTool({
  name: "example-tool",
  arguments: {
    arg1: "value"
  }
});

「prompts・resources・tool」のそれぞれに関する実装が盛り込まれています。今回は、自作MCPサーバー側の実装が tool(ツール)のみなので、「prompts・resources」の部分は削ります。

自分が試した内容(下準備・実装)

それでは、以下のコマンドでパッケージのインストールを行い、自作MCPクライアントを実装します。

npm install @modelcontextprotocol/sdk

TypeScript版の公式SDK で作った自作MCPサーバーとの組み合わせ

以下は、「TypeScript版の公式SDK で作った自作MCPサーバー」を使うためのクライアントです。

args: ["【実装した自作MCPサーバーへのフルパス】"] の部分は、自作MCPサーバーのファイルの実際のフルパスに置きかえてください。

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

async function main() {
  const transport = new StdioClientTransport({
    command: "node",
    args: ["【実装した自作MCPサーバーへのフルパス】"],
  });

  const client = new Client(
    { name: "add-tool-client", version: "1.0.0" },
    { capabilities: {} }
  );

  await client.connect(transport);

  const listRes = await client.listTools();
  const tools = listRes.tools;
  console.log(
    "Available tools:",
    tools.map((t) => t.name)
  );

  const a = 10;
  const b = 20;
  const callRes = await client.callTool({
    name: "add_test",
    arguments: { a, b },
  });
  console.log(`add(${a}, ${b}) + 10 =`, callRes);

  await client.close();
}

main().catch((err) => {
  console.error("Error in add-tool client:", err);
  process.exit(1);
});

これを実行した結果は以下のとおりです。
10・20 という入力値に対して、40 という値を得ることができています。

2025-05-06_16-12-40.jpg

ちなみに、取得できたツールの一覧の部分について、名前を取り出すのではなく console.dir(tools, { depth: null }); など全体を出力する処理を行うと、以下の内容が返ってきているのが確認できました。

image.png

TypeScript版の FastMCP で作った自作MCPサーバーとの組み合わせ

以下は、「TypeScript版の FastMCP で作った自作MCPサーバー」を使うためのクライアントです。

先ほどとほぼ同じ内容のコードになるので、コード・補足は折りたたんだ中に記載します。

【折りたたみ】TypeScript版の FastMCP で作った自作MCPサーバーを使うクライアント

args: ["【実装した自作MCPサーバーへのフルパス】"] の部分は、自作MCPサーバーのファイルの実際のフルパスに置きかえてください。

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

async function main() {
  const transport = new StdioClientTransport({
    command: "node",
    args: ["【実装した自作MCPサーバーのファイルへのフルパス】"],
  });

  const client = new Client(
    { name: "add-tool-client", version: "1.0.0" },
    { capabilities: {} }
  );

  await client.connect(transport);

  const listRes = await client.listTools();
  const tools = listRes.tools;
  console.log(
    "Available tools:",
    tools.map((t) => t.name)
  );

  const a = 10;
  const b = 20;
  const callRes = await client.callTool({
    name: "add",
    arguments: { a, b },
  });
  console.log(`add(${a}, ${b}) + 5 =`, callRes);

  await client.close();
}

main().catch((err) => {
  console.error("Error in add-tool client:", err);
  process.exit(1);
});

これを実行した結果、10・20 という入力値に対して、35 という値を得ることができました。

2025-05-06_16-12-40のコピー.jpg

また取得できたツール一覧の全体の内容については、以下となっていました。

image.png

おわりに

簡単なお試しではありましたが、TypeScript版の公式SDK を使って MCPクライアントを作ってみました。そのクライアントでは、自作MCPサーバーのツールを利用する処理を試し、想定通りの結果を得られることが確認できました。

今後、MCP に関連した内容の自作について、MCPホストの自作も試せればと思っています。

おまけ

今回、自作MCPサーバーのツールを使う MCPクライアントを実装したついでに、公式の Filesystem MCP Server(filesystem) のツール一覧を取得する処理も軽く試してみました。

実装内容

具体的なコードは、以下のとおりです。

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

async function main() {
  const transport = new StdioClientTransport({
    command: "npx",
    args: [
      "-y",
      "@modelcontextprotocol/server-filesystem",
      "【対象とするフォルダのフルパス】",
    ],
  });

  const client = new Client(
    { name: "filesystem-tool-client", version: "1.0.0" },
    { capabilities: {} }
  );

  await client.connect(transport);

  const listRes = await client.listTools();
  const tools = listRes.tools;
  console.log(
    "Available tools:",
    tools.map((t) => t.name)
  );

  await client.close();
}

main().catch((err) => {
  console.error("Error in add-tool client:", err);
  process.exit(1);
});

得られたツール一覧は以下となりました。

image.png

また、名前以外の部分を含む全体を取得した結果も、部分的に掲載してみます。

image.png

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?