2025 年 6 月時点 Claude Desktop から Dog API から画像を持ってくるだけの MCP サーバーの画像ソースやり取りのメモ

2025 年 6 月時点 Claude Desktop から Dog API から画像を持ってくるだけの MCP サーバーの画像ソースやり取りのメモ

2025 年 6 月時点 Claude Desktop から Dog API から画像を持ってくるだけの MCP サーバーの画像ソースやり取りのメモです。

背景

あくまで 2025 年 6 月時点の仕様での試してみたお話です。ここから仕様が変わったり、より良いアプローチが見つかるかもしれません。

このように Dog API から画像を持ってくるだけの MCP サーバーができたので、まとめておきます。

stdio 標準入出力 MCP サーバーを TypeScript で作る

modelcontextprotocol/typescript-sdk: The official Typescript SDK for Model Context Protocol servers and clients

Node.js v18.19.0 で動かしています。fetch 関数を素直に動かすためです。これ以上のバージョンであれば fetch 関数は問題なく動きます。

モジュールのインストール

プロジェクトフォルダを作って

npm init -y

で準備します。

modelcontextprotocol/typescript-sdk: The official Typescript SDK for Model Context Protocol servers and clients

こちらをもとに、

npm install @modelcontextprotocol/sdk zod

npm install -D typescript ts-node @types/node

を実行してモジュールの準備をします。

stdio-dog-api-mcp-server.ts 用意

modelcontextprotocol/typescript-sdk: The official Typescript SDK for Model Context Protocol servers and clients の Running Your Server の stdio のソースを元に stdio-dog-api-mcp-server.ts を用意します。

// stdio-dog-api-mcp-server.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

async function main() {
  // 1. MCP サーバー初期化
  const server = new McpServer(
    {
      name:    "DogToolDemo",
      version: "1.0.0",
    }
  );

  // 2. fetchDogImage ツールを追加
  server.tool(
    "fetchDogImage",
    "Dog API からランダムな犬画像を取ってきて返します",
    /* inputSchema: 空のオブジェクトツール */
    {
      type: "object",
      properties: {},
      required: []
    },
    // コールバックでは args と extra を受け取る
    async (_args: {}, _extra) => {
      try {
        // 2-1) Dog API からランダム画像 URL を取得
        const apiRes = await fetch("https://dog.ceo/api/breeds/image/random");
        if (!apiRes.ok) throw new Error(`Dog API error: ${apiRes.status}`);
        const { message: imageUrl } = (await apiRes.json()) as { message: string; status: string };

        // 2-2) 取得した URL から画像バイナリをフェッチ
        const imgRes = await fetch(imageUrl);
        if (!imgRes.ok) throw new Error(`Image fetch error: ${imgRes.status}`);
        const arrayBuffer = await imgRes.arrayBuffer();
        const data      = Buffer.from(arrayBuffer).toString("base64");
        const mimeType  = imgRes.headers.get("content-type") ?? "image/jpeg";

        // 2-3) ToolResult 形式で返却
        return {
          content: [
            {
              type:     "image",
              data,
              mimeType,
            }
          ],
          isError: false
        };
      } catch (err: any) {
        return {
          content: [
            {
              type: "text",
              text: `Error: ${err.message}`
            }
          ],
          isError: true
        };
      }
    }
  );

  // 3. STDIO トランスポートで接続
  const transport = new StdioServerTransport();
  await server.connect(transport);
}

main().catch(err => {
  console.error(err);
  process.exit(1);
});

package.json に "type": "module" 加える

package.json はこんな構成です。

{
  "name": "stdio-dog-api-mcp-server-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.13.1",
    "zod": "^3.25.67"
  },
  "devDependencies": {
    "@types/node": "^24.0.3",
    "ts-node": "^10.9.2",
    "typescript": "^5.8.3"
  }
}

"type": "module" を加えます。

npm run で動かせるようにする

package.json の scripts 項目に

"stdio-dog-api-mcp-server": "node --no-warnings --loader ts-node/esm stdio-dog-api-mcp-server.ts"

を TypeScript で今回のプログラムを実行するコマンドを加えます。

{
  "name": "stdio-dog-api-mcp-server-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "stdio-dog-api-mcp-server": "node --no-warnings --loader ts-node/esm stdio-dog-api-mcp-server.ts"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.13.1",
    "zod": "^3.25.67"
  },
  "devDependencies": {
    "@types/node": "^24.0.3",
    "ts-node": "^10.9.2",
    "typescript": "^5.8.3"
  }
}

こんな風に加えました。

tsconfig.json

tsconfig.json も準備して、この後、TypeScript を動かす設定もしておきます。

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "types": ["node"],
    "strict": true
  },
  "include": ["**/*.ts"]
}

Claude Desktop で動かしてみる

では Claude Desktop に今回の MCP サーバーを設定します。

{
  "globalShortcut": "",
  "mcpServers": {
    "stdio-dog-api-mcp-server🐶": {
      "command": "npm",
      "args": [
        "--prefix",
        "C:\\workspace\\stdio-dog-api-mcp-server-test",
        "run",
        "stdio-dog-api-mcp-server",
        "--silent"
      ]
    }
  }
}

このように設定したので、起動して動かしてみます。

このように「かわいい犬の画像が欲しいです」と聞いてみると先ほどのが stdio-dog-api-mcp-server 選定されます。犬アイコンかわいいですね。

無事、DOG API からデータが呼ばれて Claude Desktop が解説してくれます!