npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@super_studio/ecforce-ai-agent-react

v1.5.0

Published

このドキュメントでは、`@super_studio/ecforce-ai-agent-react` と `@super_studio/ecforce-ai-agent-server` を使って、Webアプリに AI Agent のチャット UI とサーバー連携を組み込む手順を説明します。

Readme

セットアップ

このドキュメントでは、@super_studio/ecforce-ai-agent-react と @super_studio/ecforce-ai-agent-server を使って、Webアプリに AI Agent のチャット UI とサーバー連携を組み込む手順を説明します。

想定構成は以下です。

  • フロントエンドで @super_studio/ecforce-ai-agent-react を使ってチャット UI を表示する
  • バックエンドで @super_studio/ecforce-ai-agent-server を使ってセッショントークンを発行する
  • 必要に応じて MCP エンドポイントでトークンを検証し、アプリ固有のツールを公開する

1. インストール

pnpm add @super_studio/ecforce-ai-agent-react @super_studio/ecforce-ai-agent-server

2. 環境変数を設定する

通常の本番環境 (https://agent.ec-force.com) に接続するだけであれば、NEXT_PUBLIC_CHATBOT_URL は不要です。

@super_studio/ecforce-ai-agent-server を使う場合は、API キーとして AI_AGENT_API_KEY を設定してください。

MCP を実装する場合は、あわせて MCP_TOKEN_SECRET も必要です。

AI_AGENT_API_KEY と MCP_TOKEN_SECRET は AI チームから共有された値を使用してください。

AI_AGENT_API_KEY=your-api-key
MCP_TOKEN_SECRET=your-mcp-token-secret

開発環境やプレビュー環境など、本番以外の AI Agent に接続したい場合のみ、接続先 URL を設定します。

開発用のエンドポイントは以下です。

NEXT_PUBLIC_CHATBOT_URL=https://dev-agent.ec-force.com
AI_AGENT_API_ENDPOINT=https://dev-agent.ec-force.com
  • NEXT_PUBLIC_CHATBOT_URL: フロントエンドの ChatbotSheet / ChatbotFrame を dev / preview 環境へ向けたい場合に使います
  • AI_AGENT_API_ENDPOINT: サーバー側の createClient() を dev / preview 環境へ向けたい場合に使います
  • AI_AGENT_API_KEY: サーバー SDK から API を呼ぶために必須です
  • MCP_TOKEN_SECRET: MCP トークンの署名・検証に使います。MCP を実装する場合に必須です

3. @super_studio/ecforce-ai-agent-react のセットアップ

3-1. スタイルを読み込む

グローバル CSS で、パッケージが提供するスタイルを読み込みます。

@import "@super_studio/ecforce-ai-agent-react/preset.css";
@import "@super_studio/ecforce-ai-agent-react/chatbot-sheet.css";

3-2. アプリを ChatbotProvider でラップする

チャット UI や useChatbot() を使う場合は、アプリ全体または必要な範囲を ChatbotProvider で囲みます。

"use client";

import { ChatbotProvider } from "@super_studio/ecforce-ai-agent-react";

type Props = {
  children: React.ReactNode;
};

export function AppProviders({ children }: Props) {
  return <ChatbotProvider>{children}</ChatbotProvider>;
}

3-3. チャット UI を表示する

ChatbotSheet にアプリ名、セッション取得関数を渡します。通常は本番環境へ接続されるため、URL 指定は不要です。

"use client";

import { ChatbotSheet } from "@super_studio/ecforce-ai-agent-react";

export function Chatbot() {
  return (
    <ChatbotSheet
      appName="your-app-name"
      getSession={async () => {
        const res = await fetch("/api/agent/session", {
          method: "POST",
        });

        if (!res.ok) {
          throw new Error("Failed to create AI agent session");
        }

        return (await res.json()) as {
          token: string;
          expiresAt: string;
        };
      }}
    />
  );
}

各 props の役割

  • url: AI Agent サーバーのベース URL。dev / preview 環境に向けたい場合のみ指定します
  • appName: 呼び出し元アプリを識別する名前
  • getSession: AI Agent に接続するためのセッショントークンを返す関数

dev / preview 環境へ接続する場合のみ、以下のように url を指定してください。

<ChatbotSheet
  url={process.env.NEXT_PUBLIC_CHATBOT_URL}
  appName="your-app-name"
  getSession={...}
/>

3-4. アプリ側の状態や文脈を AI Agent に渡す

useChatbot() の sendAppMessage() を使うと、ホストアプリから AI Agent に対してプログラム経由でメッセージを送れます。

典型的には、以下のような場面で使います。

  • 現在表示中の商品、注文、顧客などを前提に AI へ依頼したい
  • ユーザーが押したボタンに応じて、定型プロンプトをそのまま送信したい
  • 画面には見せたくない補足情報を AI にだけ渡したい
  • 画像やファイル URL を添付して、その内容を前提に会話を始めたい

sendAppMessage() を呼ぶと、チャットが閉じていても自動で開きます。チャット iframe の初期化がまだ終わっていない場合でも、メッセージは内部で一時保持され、準備完了後に送信されます。

"use client";

import { useChatbot } from "@super_studio/ecforce-ai-agent-react";

export function SendContextButton() {
  const { sendAppMessage } = useChatbot();

  return (
    <button
      onClick={() => {
        sendAppMessage({
          title: "売上ダッシュボードの要約",
          message:
            "現在の売上ダッシュボードを前提に、注目すべき変化を3つ挙げてください。",
          hiddenMessage:
            "dashboardId=dashboard_123, dashboardName=売上ダッシュボード",
        });
      }}
    >
      コンテキストを送信
    </button>
  );
}

sendAppMessage() の payload

type SendAppMessagePayload = {
  title?: string;
  message: string;
  hiddenMessage?: string;
  startOnNewChat?: boolean;
  model?: string;
  attachments?: {
    fileName: string;
    mediaType: string;
    url: string;
  }[];
};
  • message: AI Agent に実際に依頼したい本文です。必須です
  • title: 依頼の要約タイトルです。UI 上でタスク名のように扱いたいときに使います
  • hiddenMessage: ユーザーに見せなくてよい補足文脈です。内部 ID、画面状態、回答方針などを渡す用途に向いています
  • startOnNewChat: true なら新しいチャットを開始して送信します。省略時は true です。現在の会話の続きに送りたい場合だけ false を指定します
  • model: このメッセージ送信で使うモデルの alias key です。例: claude-sonnet-4-6
  • attachments: AI Agent に参照させたい添付ファイルです。公開 URL で取得できるファイルを渡してください

visible な依頼と hidden な文脈の使い分け

基本的には、ユーザーが見ても自然な内容を message に書き、アプリ内部の補足情報を hiddenMessage に分けるのがおすすめです。

  • message: 「この注文の要点を要約して」
  • hiddenMessage: orderId=ord_123, status=paid, customerTier=gold

このように分けると、ユーザー向けの依頼文を保ちながら、AI 側には必要な文脈も渡せます。

新しいチャットで送るか、現在の会話に続けるか

新しい依頼を独立した会話として扱いたい場合は、デフォルトのまま startOnNewChat: true を使います。すでに進行中の会話に追加指示したい場合は false を指定します。

sendAppMessage({
  title: "続きの依頼",
  message: "最も良い案を、2行のヒーローコピーに言い換えてください。",
  startOnNewChat: false,
});

添付ファイルを渡す例

sendAppMessage({
  title: "バナー案のレビュー",
  message: "添付画像を確認し、改善案を3つ提案してください。",
  attachments: [
    {
      fileName: "campaign-banner.png",
      mediaType: "image/png",
      url: "https://example.com/campaign-banner.png",
    },
  ],
});

これにより、AI Agent 側で現在の画面や対象データに応じた応答をしやすくなります。

送信せず、入力欄に入れるだけにしたい場合は setInput()

sendAppMessage() はそのまま送信されます。ユーザーに内容を確認・編集してもらってから送信させたい場合は、useChatbot() の setInput() を使います。

"use client";

import { useChatbot } from "@super_studio/ecforce-ai-agent-react";

export function SalesReportButton() {
  const { setInput } = useChatbot();

  return (
    <button
      type="button"
      onClick={() =>
        setInput("直近1週間の売上分析を行い、キャンバス上のレポートにまとめてください")
      }
    >
      売上レポートを作る
    </button>
  );
}

sendAppMessage() と同じく、チャットが閉じていても自動で開き、iframe の初期化が終わっていない場合はテキストを一時保持して準備完了後に反映します。送信はユーザーが送信ボタンを押すまで行われません。

| | sendAppMessage() | setInput() | |---|---|---| | 送信 | する | しない(入力欄に入れるだけ) | | チャットを自動で開く | する | する | | 初期化前の呼び出し | 保持して後で送る | 保持して後で反映する | | hidden な文脈・添付 | 渡せる | 渡せない(テキストのみ) |

3-5. useClientTool() でクライアントツールを登録する

ブラウザ上で実行したい処理を AI Agent から呼ばせたい場合は、useClientTool() を使います。

典型的には、以下のような用途で使います。

  • 現在開いている画面の React state を参照して結果を返す
  • ユーザー確認付きでクライアント側の state を更新する
  • クライアント側の UI 操作をトリガーする

useClientTool() は ChatbotProvider 配下で呼び出してください。引数定義には zod を使います。

"use client";

import { useState } from "react";
import { z } from "zod";
import { useClientTool } from "@super_studio/ecforce-ai-agent-react";

export function CartToolRegistration() {
  const [selectedSku, setSelectedSku] = useState("sku_001");
  const [isPinned, setIsPinned] = useState(false);

  useClientTool({
    name: "checkSelectedSku",
    displayName: "選択中SKU確認",
    description: "現在画面で選択中の商品 SKU を返します。",
    summary: "選択中の SKU を返します。",
    parameters: z.object({}),
    execute: () => {
      return {
        selectedSku,
        isPinned,
      };
    },
  });

  useClientTool({
    name: "togglePinnedState",
    displayName: "ピン留め切り替え",
    description: "現在の商品をピン留めするかどうかを切り替えます。",
    summary: "ピン留め状態を更新します。",
    requireConfirmation: true,
    parameters: z.object({
      pinned: z.boolean().describe("更新後のピン留め状態"),
    }),
    execute: ({ pinned }) => {
      setIsPinned(pinned);

      return {
        selectedSku,
        isPinned: pinned,
      };
    },
  });

  return (
    <div>
      <p>selectedSku: {selectedSku}</p>
      <p>isPinned: {String(isPinned)}</p>
      <button onClick={() => setSelectedSku("sku_002")}>
        SKU を切り替える
      </button>
    </div>
  );
}

useClientTool() の options

type UseClientToolOptions<TParameters extends z.ZodTypeAny> = {
  name: string;
  displayName: string;
  description: string;
  summary?: string;
  requireConfirmation?: boolean;
  parameters: TParameters;
  execute: (args: z.output<TParameters>) => Promise<unknown> | unknown;
};
  • name: ツール識別子です。内部では自動で page_ プレフィックスが付きます
  • displayName: UI 上で表示するツール名です
  • description: AI Agent が参照する詳細説明です。何をするツールか、どんな引数を受けるかを明確に書いてください
  • summary: ユーザー向けの短い要約です
  • requireConfirmation: true の場合、実行前にユーザー確認を要求します
  • parameters: ツール引数を表す zod スキーマです
  • execute: 検証済み引数を受け取ってクライアント側の処理を実行する関数です

補足

  • name に page_ を自分で付けても動きますが、通常は素の名前で問題ありません
  • execute の返り値は AI Agent に渡されるため、JSON 化しやすい値を返すのがおすすめです
  • コンポーネントがアンマウントされるとツール登録は自動で解除されます

4. @super_studio/ecforce-ai-agent-server のセットアップ

4-1. サーバー側で AI Agent セッションを発行する

フロントエンドの getSession() から呼ばれる API を用意し、createClient() を使って AI Agent サーバーへセッション作成を依頼します。

このとき、サーバー環境に AI_AGENT_API_KEY の設定が必要です。

以下は Next.js App Router の Route Handler 例です。

import { NextResponse } from "next/server";
import { createClient } from "@super_studio/ecforce-ai-agent-server";

const aiClient = createClient();

export async function POST() {
  // ここは自分の認証基盤に置き換えてください
  const currentUser = {
    email: "[email protected]",
    projectId: "project_123",
  };

  const session = await aiClient.internalChat.createSession({
    email: currentUser.email,
    projectId: currentUser.projectId,
  });

  return NextResponse.json(session);
}

dev / preview 環境へ接続する場合は、AI_AGENT_API_ENDPOINT を設定するか、createClient({ baseUrl: "..." }) を使って接続先を上書きしてください。

getSession() には、この API が返す以下の形式の値をそのまま返せば動作します。

type AgentSession = {
  token: string;
  expiresAt: string;
};

4-2. MCP エンドポイントでトークンを検証する

アプリ固有のツールを AI Agent に公開する場合は、MCP エンドポイント側で受け取ったトークンを検証します。

このとき、サーバー環境に MCP_TOKEN_SECRET の設定が必要です。

@super_studio/ecforce-ai-agent-server/mcp-auth には、MCP トークンを扱うためのユーティリティが含まれています。

import { getMcpToken } from "@super_studio/ecforce-ai-agent-server/mcp-auth";

export async function GET(req: Request) {
  const mcpToken = getMcpToken(req);

  if (!mcpToken) {
    return new Response("Unauthorized", { status: 401 });
  }

  return new Response("ok");
}

トークンの中身を利用したい場合は decodeMCPToken() を使います。

import { decodeMCPToken } from "@super_studio/ecforce-ai-agent-server/mcp-auth";

export async function GET(req: Request) {
  const authHeader = req.headers.get("authorization");
  const token = authHeader?.replace(/^Bearer\s+/i, "");

  if (!token) {
    return new Response("Unauthorized", { status: 401 });
  }

  const payload = await decodeMCPToken(token);

  return Response.json({
    source: payload.source,
    user: payload.user,
  });
}