日曜日, 6月 22, 2025
日曜日, 6月 22, 2025
- Advertisment -
ホームニューステックニュースVercelのmcp-adapterはいいぞ!AWSでも使える! #Next.js - Qiita

Vercelのmcp-adapterはいいぞ!AWSでも使える! #Next.js – Qiita



Vercelのmcp-adapterはいいぞ!AWSでも使える! #Next.js - Qiita

前書き

Streamable HTTP対応のMCPサーバーを気軽にデプロイしたい!
その思いから@vercel/mcp-adapterと出会いました。使用感も良好で、皆さんに紹介したいと思います。

MCPについてまだご存知でない方は、こちらのスライドをご覧ください。

プロジェクト初期化

まずはNext.jsのプロジェクトを初期化します。

Next.jsを使ってMCPサーバーを作るのは少し不思議な感覚ですが、Next.jsは普通にAPIサーバーとしても使えるので、フルスタック開発が可能です。

公式ドキュメント

npx create-next-app@latest my-mcp-server

初期化完了したら、@vercel/mcp-adapterzodをインストールします。

npm install @vercel/mcp-adapter zod

下記のファイルを追加します。
シンプルなツールで、使用するとランダムに点数が返ってきます。

src/app/api/mcp/route.ts


import { z } from 'zod';
import { createMcpHandler } from '@vercel/mcp-adapter';
 
const handler = createMcpHandler(
  (server) => {
    server.tool(
      'roll_dice',
      'Rolls an N-sided die',
      { sides: z.number().int().min(2) },
      async ({ sides }) => {
        const value = 1 + Math.floor(Math.random() * sides);
        return {
          content: [{ type: 'text', text: `🎲 You rolled a ${value}!` }],
        };
      },
    );
  },
  {},
  { basePath: '/api' },
);
 
export { handler as GET, handler as POST, handler as DELETE };

実装は以上です!

VScodeからテストします

まずはNext.jsのローカルサーバーを立ち上げます。

VScodeの設定を開き、settings.jsonを編集します。

698281ED-7DEF-4F09-9C05-F24A90CAF3EB.jpeg

下記の内容を追加してください。
portは実際に立ち上げたサーバーの利用ポートに変更してください。

"local-server": {
  "url": "http://localhost:3000/api/mcp"
}

次はCopilotを開き、エージェントモード でツールを利用するようにプロンプトを投げてください。
特に問題がなければ、ダイスの結果が返ってきます。

8A8AA36B-1A21-4D71-8A9E-0C8BDED3C369.jpeg

MCP Inspectorからテストします

VScodeがインストールされてない場合、MCP Inspectorからでも接続テストを行えます。

npx @modelcontextprotocol/inspector

実行後、下記の内容が出力されると思います。

...
Session Tokenに ⚙️ Proxy server listening on 127.0.0.1:6277
🔑 Session token: token_value
...

http://127.0.0.1:6274 にアクセスして MCP Inspector を開きます。

  • Transport Type で「Streamable HTTP」を選択する
  • URLhttp://localhost:3000/api/mcp を入力する
  • Proxy Session Tokenにtoken_valueを入力する

Connect ボタンをクリックすれば、MCPサーバーに接続できます。

4F73560F-5A48-4AB7-8733-BF3A865EF0D1_4_5005_c.jpeg

mcp-adapterの認証

公式のドキュメントには記載されていませんが、mcp-adapterには認証用の関数が用意されています。

まだ検証段階のようですが、experimental_withMcpAuthという関数です。

src/app/api/mcp/route.tsのcodeを下記のように修正してください。

src/app/api/mcp/route.ts

import { z } from 'zod';
import { createMcpHandler,experimental_withMcpAuth } from '@vercel/mcp-adapter';
 
const handler = createMcpHandler(
  (server) => {
    server.tool(
      'roll_dice',
      'Rolls an N-sided die',
      { sides: z.number().int().min(2) },
      async ({ sides }, {authInfo}) => {
       console.log('authInfo', authInfo);
      if (!authInfo?.token) {
        return { content: [{ type: "text", text: "Unauthorized" }] };
      }
        const value = 1 + Math.floor(Math.random() * sides);
        return {
          content: [{ type: 'text', text: `🎲 You rolled a ${value}!` }],
        };
      },
    );
    server.tool(
      'story_list',
      'Display a list of stories owned by this user',
      {},
      async ({}, {authInfo}) => {
        console.log('authInfo', authInfo);
        if (!authInfo?.token) {
          return { content: [{ type: "text", text: "Unauthorized" }] };
        }
        return {
          content: [{ type: 'text', text: `黒い馬,天から降りる災難` }],
        };
      },
    )
  },
  {},
  { basePath: '/api' },
);

const wrappedHandler = async (req: Request) => {
  const authHandler = experimental_withMcpAuth(handler, (req) => {
    const header = req.headers.get("Authorization");

    if (header?.startsWith("Bearer ")) {
      const token = header.slice(7).trim();
      return Promise.resolve({
        token,
        clientId: "agent-mcp",
        scopes: ["runAgent"],
      });
    }

    return undefined;
  });

  return authHandler(req);
};
 
export { wrappedHandler as GET, wrappedHandler as POST, wrappedHandler as DELETE };

VScodeのsettings.jsonに、headersを追加し、Bearer tokenを渡せるようにします。

settings.json

    "local-server": {
      "url": "http://localhost:3000/api/mcp",
      "headers": {
        "Authorization": "Bearer my-api-key",
      },
     }

修正後、再度VScodeからMCPサーバーのツールを呼び出してみると、
追加したlogの内容が出力されたことが確認できます。

authInfo { token: 'my-api-key', clientId: 'agent-mcp', scopes: [ 'runAgent' ] }

Vercelにデプロイ

作業中にプロジェクトをGitHubにプッシュしてから、Vercelで連携するのが最も簡単な方法ですね。

507307C5-8A97-4C3A-8C4B-70EC514D9AA8.jpeg

オプションはデフォルトのままで大丈夫です。

F1E7F944-62BE-48A1-BFBB-4B8C6666FD43.jpeg

デプロイが完了すると、Vercelから提供されるドメインが付与されます。
それを使って、デプロイされたMCPサーバーに接続してみます。

setting.json

    "vercel-server": {
+      "url": "https://xxxx-xxx.vercel.app/api/mcp",
      "headers": {
        "Authorization": "Bearer my-api-key",
      },
     }

VercelにデプロイされたMCP Serverのツールも呼び出しに成功することがわかります。

24531D74-BB71-42C8-824A-686A379C9D8A.jpeg

Vercelのダッシュボードからログの内容を確認することができます。

71210CF8-0D6B-4112-B0E0-A3A0A73A2E76.jpeg

Next.js製のMCPサーバーを簡単にデプロイできて良いですね。
しかもクライアントとしての機能も残しているため、管理が楽で便利です。

AWS Amplifyでもいけるか

AWS Amplifyは、Webアプリケーションやモバイルアプリケーションを構築、デプロイ、管理するためのフルスタック開発プラットフォームです。

29f8d74d-7229-2a63-9291-64dfcf705e2e.png

Next.jsのプロジェクトも簡単にデプロイできます。

C4BFB0BD-6105-457E-8E85-440BAEAA8545.jpeg

GitHubAmplifyの連携が完了したら、リポジトリとブランチを選択して、「次へ」

76D079A4-E93F-4AAC-B436-73015AF9FD50.jpeg

アプリケーションの設定はそのままで大丈夫です。

171D6A1F-1396-4E87-B818-0B8418320B07.jpeg

最後に特に問題がなければ、「保存してデプロイ」。

初回デプロイは多少時間がかかりますが、それでも5分以内にロケットの打ち上げが確認できるでしょう。

URLをAmplifyから付与されたURLに変更します。

settings.json

+    "amplify-server": {
+      "url": "https://main.xxxxx.amplifyapp.com/api/mcp",
      "headers": {
        "Authorization": "Bearer my-api-key",
      },
     }

問題なくツールを呼び出せます。

E5E496A0-5D93-4048-98C9-154414FD7171.jpeg

ログも確認してみましょう!

Amplifyのモニタリングからホスティングしているコンピューティングログを開き、
CloudWatch ログストリームを確認します
C07103DA-F8CD-4A61-A9A5-0B4CB8437D05.jpeg

FB6F156D-6E20-4ADF-8ED0-F247877D80F5.jpeg

何が嬉しいかというと、AmplifyでMCPサーバーをデプロイすれば、既存のAWSリソースを利用できることです。
簡単にファイアウォールやカスタムドメインを追加することができます。

検証に使用したリポジトリ

参考資料





Source link

Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -