📑

Postman で Remote MCP Server をテストする

に公開

今日はPostmanのMCPテスト機能を使ってRemote MCP Serverとの接続をやってみます。
過去こちらの記事でSTDIO方式でMCP Serverとの通信をテストする方法をご紹介しましたが、今日はHTTP方式、いわゆるRemote MCP Serverと言われている通信方式のテストを行います。

Remote MCP Server のテストについて

https://serverless.co.jp/blog/b-rab5q77fd/
こちらでまとめていますが、MCP Serverの場合、認証認可はオプショナルとなっておりOAuthが採用されています。STDIO方式ではローカルで動作するためその実装が求められることは現時点ではあまりないようですが、HTTP/SSE方式であるRemote MCP Serverではそのエンドポイントがインターネット上に露出するため認証認可はとても重要です。規格上は認証認可は「Optional」ですが、Claude系のMCPクライアントなどは、OAuthを実装していないRemote MCP Serverとは接続できない制限があります。

このため上記の記事ではVSCode + Copilotでテストを行いました。
今日はPostmanでRemote MCP Serverとの接続をテストします。

さっそくやってみる

1.テスト用Remote MCP Serverの準備

まずは前回用いたテスト環境を整備します。
とはいっても以下のスクリプトをnodeで起動するだけです。

remotemcp.js
const http = require('http');
const url = require('url');

// MCPメッセージのIDカウンター
let messageId = 1;

// レスポンスヘルパー関数
function sendJsonResponse(res, data, statusCode = 200) {
  res.writeHead(statusCode, {
    'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type'
  });
  res.end(JSON.stringify(data));
}

// MCPプロトコルメッセージハンドラー
function handleMCPMessage(message) {
  const { method, params } = message;

  switch (method) {
    case 'initialize':
      return {
        jsonrpc: '2.0',
        id: message.id,
        result: {
          protocolVersion: '2024-11-05',
          capabilities: {
            tools: {},
            prompts: {},
            resources: {}
          },
          serverInfo: {
            name: 'hello-world-mcp-server',
            version: '1.0.0'
          }
        }
      };

    case 'notifications/initialized':
      // initialized通知には応答不要
      return null;

    case 'tools/list':
      return {
        jsonrpc: '2.0',
        id: message.id,
        result: {
          tools: [
            {
              name: 'hello_world',
              description: 'Returns a simple hello world message',
              inputSchema: {
                type: 'object',
                properties: {
                  name: {
                    type: 'string',
                    description: 'Name to greet (optional)'
                  }
                }
              }
            }
          ]
        }
      };

    case 'tools/call':
      const { name: toolName, arguments: args } = params;
      
      if (toolName === 'hello_world') {
        const name = args?.name || 'World';
        return {
          jsonrpc: '2.0',
          id: message.id,
          result: {
            content: [
              {
                type: 'text',
                text: `Hello, ${name}! This is a simple MCP server response.`
              }
            ]
          }
        };
      }
      
      // 未知のツール
      return {
        jsonrpc: '2.0',
        id: message.id,
        error: {
          code: -32601,
          message: `Unknown tool: ${toolName}`
        }
      };

    default:
      return {
        jsonrpc: '2.0',
        id: message.id,
        error: {
          code: -32601,
          message: `Method not found: ${method}`
        }
      };
  }
}

// HTTPサーバー作成
const server = http.createServer((req, res) => {
  const parsedUrl = url.parse(req.url, true);
  
  // CORS preflight
  if (req.method === 'OPTIONS') {
    sendJsonResponse(res, {});
    return;
  }

  // GET - サーバー情報
  if (req.method === 'GET' && parsedUrl.pathname === '/') {
    sendJsonResponse(res, {
      name: 'Hello World MCP Server',
      version: '1.0.0',
      description: 'A simple MCP server that responds with hello world messages',
      endpoints: {
        mcp: '/mcp'
      }
    });
    return;
  }

  // POST - MCPメッセージ処理
  if (req.method === 'POST' && parsedUrl.pathname === '/mcp') {
    let body = '';
    
    req.on('data', chunk => {
      body += chunk.toString();
    });
    
    req.on('end', () => {
      try {
        const message = JSON.parse(body);
        console.log('Received MCP message:', JSON.stringify(message, null, 2));
        
        const response = handleMCPMessage(message);
        
        if (response) {
          console.log('Sending response:', JSON.stringify(response, null, 2));
          sendJsonResponse(res, response);
        } else {
          // notifications/initializedなど、応答不要の場合
          res.writeHead(204);
          res.end();
        }
      } catch (error) {
        console.error('Error processing message:', error);
        sendJsonResponse(res, {
          jsonrpc: '2.0',
          id: null,
          error: {
            code: -32700,
            message: 'Parse error'
          }
        }, 400);
      }
    });
    return;
  }

  // 404
  sendJsonResponse(res, { error: 'Not found' }, 404);
});

const PORT = process.env.PORT || 3000;

server.listen(PORT, () => {
  console.log(`MCP HTTP Server running on port ${PORT}`);
  console.log(`Server info: http://localhost:${PORT}/`);
  console.log(`MCP endpoint: http://localhost:${PORT}/mcp`);
});

// グレースフルシャットダウン
process.on('SIGINT', () => {
  console.log('\nShutting down server...');
  server.close(() => {
    console.log('Server closed');
    process.exit(0);
  });
});

node remotemcp.jsで起動します。

MCP HTTP Server running on port 3000
Server info: http://localhost:3000/
MCP endpoint: http://localhost:3000/mcp

2.Postman Desktop を用いたテスト

Postmanはブラウザ版とDesktop版がありますが、localhostにHTTPで接続するためにはもちろんDesktop版が必要です。いろいろ役に立つツールなので入れてしまいましょう。
https://www.postman.com/downloads/

コレクションから新規のボタンをクリックします。

MCPを選択します。

http://localhost:3000/mcpと入力し接続をクリックします。

ステータスがConnectedになれば完成です。

サーバー側で以下の様にログが出力されます。

remotemcp.js ログ
Received MCP message: {
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-03-26",
    "capabilities": {},
    "clientInfo": {
      "name": "Postman Client - 640e494e-a4a5-4b59-8180-e516f8e04eba",
      "version": "1.0.0"
    }
  },
  "jsonrpc": "2.0",
  "id": 0
}
Sending response: {
  "jsonrpc": "2.0",
  "id": 0,
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "tools": {},
      "prompts": {},
      "resources": {}
    },
    "serverInfo": {
      "name": "hello-world-mcp-server",
      "version": "1.0.0"
    }
  }
}
Received MCP message: {
  "method": "notifications/initialized",
  "jsonrpc": "2.0"
}
Received MCP message: {
  "method": "tools/list",
  "jsonrpc": "2.0",
  "id": 1
}
Sending response: {
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "hello_world",
        "description": "Returns a simple hello world message",
        "inputSchema": {
          "type": "object",
          "properties": {
            "name": {
              "type": "string",
              "description": "Name to greet (optional)"
            }
          }
        }
      }
    ]
  }
}
Received MCP message: {
  "method": "prompts/list",
  "jsonrpc": "2.0",
  "id": 3
}
Sending response: {
  "jsonrpc": "2.0",
  "id": 3,
  "error": {
    "code": -32601,
    "message": "Method not found: prompts/list"
  }
}
Received MCP message: {
  "method": "resources/list",
  "jsonrpc": "2.0",
  "id": 2
}
Sending response: {
  "jsonrpc": "2.0",
  "id": 2,
  "error": {
    "code": -32601,
    "message": "Method not found: resources/list"
  }
}
Received MCP message: {
  "method": "resources/templates/list",
  "jsonrpc": "2.0",
  "id": 4
}
Sending response: {
  "jsonrpc": "2.0",
  "id": 4,
  "error": {
    "code": -32601,
    "message": "Method not found: resources/templates/list"
  }
}

notifications/initialize,notifications/initialized,tools/list,prompts/list,resources/list,resources/templates/listが行われていることがわかります。
サーバ側ではprompts/list,resources/list,resources/templates/listは実装していないので受け取ったJSON-RPC電文が表示されているだけで、Method not foundを戻しています。
なお、このMethod not foundはJSON-RPCに準拠した戻り値となっています。
https://www.jsonrpc.org/specification#error_object
Postmanではnullを戻しても動作しますが、別のMCP Clientだと動作しないケースもあるようです。

次にPromptを送ります。


無事Responseが戻ってきています。

{
    "content": [
        {
            "type": "text",
            "text": "Hello, kameda! This is a simple MCP server response."
        }
    ]
}

サーバー側では以下の通りログが出ています。

Received MCP message: {
  "method": "tools/call",
  "params": {
    "name": "hello_world",
    "arguments": {
      "name": "kameda"
    }
  },
  "jsonrpc": "2.0",
  "id": 5
}
Sending response: {
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Hello, kameda! This is a simple MCP server response."
      }
    ]
  }
}

OAuth認証のテスト

このサーバはまだOauthを組み込んでいないためテストが行えませんが、Postmanでは簡単にOAuth2.0のテストも行えるようになっています。これはRemote MCP Serverの準備ができ次第改めて試してみたいと思います。

OAuth機能ご参考ブログ:
https://zenn.dev/kameoncloud/articles/0b0a2267d91b81

Discussion