react-mcp

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

assistant-ui React MCP

assistant-ui React MCP

Always consult assistant-ui.com/llms.txt for the latest API.
Let end users add, authenticate, and manage MCP servers from the browser with
@assistant-ui/react-mcp
. The connected servers' tools are merged into the chat runtime automatically.
请始终查阅assistant-ui.com/llms.txt获取最新API。
借助
@assistant-ui/react-mcp
,让终端用户能在浏览器中添加、验证和管理MCP服务器。已连接服务器的工具会自动合并到聊天运行时中。

Contents

目录

References

参考文档

  • ./references/setup.md -- McpManagerResource, defineConnector, storage, useAui({ mcp })
  • ./references/ui.md -- McpManagerPrimitive / McpServerPrimitive / McpConfigDialog
  • ./references/oauth.md -- OAuth connect flow and auth modes
  • ./references/setup.md -- McpManagerResource、defineConnector、存储、useAui({ mcp })
  • ./references/ui.md -- McpManagerPrimitive / McpServerPrimitive / McpConfigDialog
  • ./references/oauth.md -- OAuth连接流程与认证模式

Routes vs tools

路由 vs 工具

This skill is for user-managed MCP servers: the end user picks and authenticates servers at runtime in the browser. Each server's tools are namespaced as
serverId__toolName
and exposed to the chat runtime with no extra wiring.
For developer-defined tools (frontend
makeAssistantTool
, backend AI SDK
tool()
, custom tool-call UI), use the tools skill instead. The two compose: a chat built with
useChatRuntime
can use both app tools and user-connected MCP tools at once.
本技能适用于用户管理的MCP服务器:终端用户可在浏览器运行时选择并验证服务器。每个服务器的工具会以
serverId__toolName
为命名空间,无需额外配置即可暴露给聊天运行时。
对于开发者定义的工具(前端
makeAssistantTool
、后端AI SDK
tool()
、自定义工具调用UI),请改用工具技能。两者可组合使用:基于
useChatRuntime
构建的聊天应用可同时使用应用工具和用户连接的MCP工具。

Mount the manager

挂载管理器

McpManagerResource({ connectors })
builds the
mcp
scope; pass it to
useAui
and wrap the app in
AuiProvider
. Connectors are presets declared with
defineConnector
.
tsx
"use client";
import { AuiProvider, useAui } from "@assistant-ui/react";
import { McpManagerResource, defineConnector } from "@assistant-ui/react-mcp";

const connectors = [
  defineConnector({
    id: "linear",
    name: "Linear",
    url: "https://mcp.linear.app",
    auth: { type: "oauth", scopes: ["read"] },
    icon: "/icons/linear.svg",
  }),
  defineConnector({
    id: "weather",
    name: "Weather",
    url: "https://mcp.example.com/weather",
    auth: { type: "none" },
  }),
];

export function Providers({ children }: { children: React.ReactNode }) {
  const aui = useAui({ mcp: McpManagerResource({ connectors }) });
  return <AuiProvider value={aui}>{children}</AuiProvider>;
}
Defaults:
storage
is
McpLocalStorage()
,
oauthRedirectUri
is
${window.location.origin}/mcp/callback
, and
autoConnect
is
true
.
McpManagerResource({ connectors })
用于构建
mcp
作用域;将其传入
useAui
并使用
AuiProvider
包裹应用。连接器是通过
defineConnector
声明的预设。
tsx
"use client";
import { AuiProvider, useAui } from "@assistant-ui/react";
import { McpManagerResource, defineConnector } from "@assistant-ui/react-mcp";

const connectors = [
  defineConnector({
    id: "linear",
    name: "Linear",
    url: "https://mcp.linear.app",
    auth: { type: "oauth", scopes: ["read"] },
    icon: "/icons/linear.svg",
  }),
  defineConnector({
    id: "weather",
    name: "Weather",
    url: "https://mcp.example.com/weather",
    auth: { type: "none" },
  }),
];

export function Providers({ children }: { children: React.ReactNode }) {
  const aui = useAui({ mcp: McpManagerResource({ connectors }) });
  return <AuiProvider value={aui}>{children}</AuiProvider>;
}
默认配置:
storage
McpLocalStorage()
oauthRedirectUri
${window.location.origin}/mcp/callback
autoConnect
true

Drop-in dialog

嵌入对话框

McpConfigDialog
is the shadcn dialog that lists connectors and custom servers with inline auth controls and an add form. Drop it anywhere under the provider.
tsx
import { McpConfigDialog } from "@/components/assistant-ui/mcp-config";

export default function Page() {
  return (
    <header className="flex items-center justify-between">
      <h1>My app</h1>
      <McpConfigDialog />
    </header>
  );
}
Pass
children
to override the default trigger:
<McpConfigDialog><Button>Servers</Button></McpConfigDialog>
.
McpConfigDialog
是shadcn风格的对话框,列出连接器和自定义服务器,包含内嵌认证控件和添加表单。可将其放置在Provider下的任意位置。
tsx
import { McpConfigDialog } from "@/components/assistant-ui/mcp-config";

export default function Page() {
  return (
    <header className="flex items-center justify-between">
      <h1>我的应用</h1>
      <McpConfigDialog />
    </header>
  );
}
传入
children
可覆盖默认触发器:
<McpConfigDialog><Button>服务器</Button></McpConfigDialog>

Compose from primitives

基于原语组合

McpManagerPrimitive
iterates servers; nested
McpServerPrimitive.*
reads each item's scope automatically. Conditional buttons render only when the connection state matches.
tsx
"use client";
import { McpManagerPrimitive, McpServerPrimitive } from "@assistant-ui/react-mcp";

const ServerCard = () => (
  <McpServerPrimitive.Root>
    <McpServerPrimitive.Icon />
    <McpServerPrimitive.Name />
    <McpServerPrimitive.Status />
    <McpServerPrimitive.ConnectButton>Connect</McpServerPrimitive.ConnectButton>
    <McpServerPrimitive.DisconnectButton>Disconnect</McpServerPrimitive.DisconnectButton>
    <McpServerPrimitive.OAuthLink>Authorize</McpServerPrimitive.OAuthLink>
    <McpServerPrimitive.RemoveButton>Remove</McpServerPrimitive.RemoveButton>
    <McpServerPrimitive.Error />
  </McpServerPrimitive.Root>
);

export default function McpPage() {
  return (
    <McpManagerPrimitive.Root>
      <h2>Connectors</h2>
      <McpManagerPrimitive.Connectors>{() => <ServerCard />}</McpManagerPrimitive.Connectors>
      <h2>Your servers</h2>
      <McpManagerPrimitive.CustomServers>{() => <ServerCard />}</McpManagerPrimitive.CustomServers>
      <McpManagerPrimitive.AddCustomTrigger>Add custom server</McpManagerPrimitive.AddCustomTrigger>
    </McpManagerPrimitive.Root>
  );
}
RemoveButton
is hidden on connectors (presets cannot be removed). Omit
AddCustomTrigger
and
CustomServers
to disable user-added servers. Build the add form with
McpAddFormPrimitive
(
Root
,
NameField
,
UrlField
,
AuthSelect
,
AuthFields
,
Error
,
Submit
,
Cancel
); see ui.md.
McpManagerPrimitive
用于遍历服务器;嵌套的
McpServerPrimitive.*
会自动读取每个项的作用域。条件按钮仅在连接状态匹配时渲染。
tsx
"use client";
import { McpManagerPrimitive, McpServerPrimitive } from "@assistant-ui/react-mcp";

const ServerCard = () => (
  <McpServerPrimitive.Root>
    <McpServerPrimitive.Icon />
    <McpServerPrimitive.Name />
    <McpServerPrimitive.Status />
    <McpServerPrimitive.ConnectButton>连接</McpServerPrimitive.ConnectButton>
    <McpServerPrimitive.DisconnectButton>断开连接</McpServerPrimitive.DisconnectButton>
    <McpServerPrimitive.OAuthLink>授权</McpServerPrimitive.OAuthLink>
    <McpServerPrimitive.RemoveButton>移除</McpServerPrimitive.RemoveButton>
    <McpServerPrimitive.Error />
  </McpServerPrimitive.Root>
);

export default function McpPage() {
  return (
    <McpManagerPrimitive.Root>
      <h2>连接器</h2>
      <McpManagerPrimitive.Connectors>{() => <ServerCard />}</McpManagerPrimitive.Connectors>
      <h2>你的服务器</h2>
      <McpManagerPrimitive.CustomServers>{() => <ServerCard />}</McpManagerPrimitive.CustomServers>
      <McpManagerPrimitive.AddCustomTrigger>添加自定义服务器</McpManagerPrimitive.AddCustomTrigger>
    </McpManagerPrimitive.Root>
  );
}
RemoveButton
在连接器(预设)上会隐藏(预设无法移除)。省略
AddCustomTrigger
CustomServers
可禁用用户添加服务器。使用
McpAddFormPrimitive
Root
NameField
UrlField
AuthSelect
AuthFields
Error
Submit
Cancel
)构建添加表单;详情请见ui.md

OAuth connect flow

OAuth连接流程

auth
is one of
{ type: "none" }
,
{ type: "bearer", token? }
, or
{ type: "oauth", scopes?, ... }
. For OAuth, add a callback route at the configured
oauthRedirectUri
and render
McpOAuthCallback
inside the same provider so it can finish the handshake.
tsx
"use client";
import { McpOAuthCallback } from "@assistant-ui/react-mcp";
import { useRouter } from "next/navigation";
import { Providers } from "../../providers";

export default function Callback() {
  const router = useRouter();
  return (
    <Providers>
      <McpOAuthCallback onComplete={() => router.replace("/mcp")} />
    </Providers>
  );
}
See oauth.md for the full auth-mode shapes and connection-state values (
connected
,
connecting
,
authRequired
,
authPending
,
error
,
disconnected
).
auth
可选值为
{ type: "none" }
{ type: "bearer", token? }
{ type: "oauth", scopes?, ... }
。对于OAuth,需在配置的
oauthRedirectUri
处添加回调路由,并在同一个Provider内渲染
McpOAuthCallback
以完成握手。
tsx
"use client";
import { McpOAuthCallback } from "@assistant-ui/react-mcp";
import { useRouter } from "next/navigation";
import { Providers } from "../../providers";

export default function Callback() {
  const router = useRouter();
  return (
    <Providers>
      <McpOAuthCallback onComplete={() => router.replace("/mcp")} />
    </Providers>
  );
}
完整的认证模式结构和连接状态值(
connected
connecting
authRequired
authPending
error
disconnected
)请见oauth.md

Custom storage

自定义存储

Replace the default
McpLocalStorage()
to persist custom servers and auth state on a backend (use
McpMemoryStorage()
for SSR/tests).
ts
import { McpManagerResource, McpCustomStorage } from "@assistant-ui/react-mcp";

const aui = useAui({
  mcp: McpManagerResource({
    connectors,
    storage: McpCustomStorage({
      loadCustomServers: async () => fetch("/api/mcp/servers").then((r) => r.json()),
      saveCustomServers: async (records) =>
        fetch("/api/mcp/servers", { method: "PUT", body: JSON.stringify(records) }),
      loadAuthState: async (id) =>
        fetch(`/api/mcp/auth/${id}`).then((r) => (r.ok ? r.json() : null)),
      saveAuthState: async (id, state) =>
        fetch(`/api/mcp/auth/${id}`, { method: "PUT", body: JSON.stringify(state) }),
      clearAuthState: async (id) => fetch(`/api/mcp/auth/${id}`, { method: "DELETE" }),
    }),
  }),
});
替换默认的
McpLocalStorage()
,可在后端持久化自定义服务器和认证状态(SSR/测试场景使用
McpMemoryStorage()
)。
ts
import { McpManagerResource, McpCustomStorage } from "@assistant-ui/react-mcp";

const aui = useAui({
  mcp: McpManagerResource({
    connectors,
    storage: McpCustomStorage({
      loadCustomServers: async () => fetch("/api/mcp/servers").then((r) => r.json()),
      saveCustomServers: async (records) =>
        fetch("/api/mcp/servers", { method: "PUT", body: JSON.stringify(records) }),
      loadAuthState: async (id) =>
        fetch(`/api/mcp/auth/${id}`).then((r) => (r.ok ? r.json() : null)),
      saveAuthState: async (id, state) =>
        fetch(`/api/mcp/auth/${id}`, { method: "PUT", body: JSON.stringify(state) }),
      clearAuthState: async (id) => fetch(`/api/mcp/auth/${id}`, { method: "DELETE" }),
    }),
  }),
});

Imperative API

命令式API

Inside event handlers, drive the manager through
useAui().mcp()
.
ts
const aui = useAui();
await aui.mcp().addCustomServer({ name, url, auth: { type: "bearer", token } });
await aui.mcp().server({ id }).connect();
await aui.mcp().server({ id }).callTool("echo", { text: "hi" });
Read reactive state with
useAuiState
, scoped under
s.mcp
(manager) and
s.mcpServer
(current item inside a
McpServerPrimitive
subtree):
ts
const isHydrated = useAuiState((s) => s.mcp.isHydrated);
const connectionState = useAuiState((s) => s.mcpServer.connectionState);
在事件处理器中,可通过
useAui().mcp()
驱动管理器。
ts
const aui = useAui();
await aui.mcp().addCustomServer({ name, url, auth: { type: "bearer", token } });
await aui.mcp().server({ id }).connect();
await aui.mcp().server({ id }).callTool("echo", { text: "hi" });
使用
useAuiState
读取响应式状态,作用域为
s.mcp
(管理器)和
s.mcpServer
McpServerPrimitive
子树内的当前项):
ts
const isHydrated = useAuiState((s) => s.mcp.isHydrated);
const connectionState = useAuiState((s) => s.mcpServer.connectionState);

Common Gotchas

常见问题

Tools not appearing in chat
  • The server must reach the
    connected
    state; check
    McpServerPrimitive.Status
    or
    s.mcpServer.connectionState
    .
  • Tool names are prefixed
    serverId__toolName
    ; reference that exact name in tool UI.
OAuth never completes
  • The callback route path must match
    oauthRedirectUri
    (default
    /mcp/callback
    ).
  • McpOAuthCallback
    must be rendered inside the same provider as the manager.
Servers not persisting / SSR errors
  • Default
    McpLocalStorage()
    needs the browser; use
    McpMemoryStorage()
    or
    McpCustomStorage(...)
    on the server.
Custom server cannot be removed
  • RemoveButton
    hides on connector presets by design; only user-added servers are removable.
Transport
  • Only StreamableHTTP is supported; resources, prompts, sampling, and auto-reconnect are not yet wired.
聊天中未显示工具
  • 服务器必须达到
    connected
    状态;请检查
    McpServerPrimitive.Status
    s.mcpServer.connectionState
  • 工具名称前缀为
    serverId__toolName
    ;在工具UI中需引用此完整名称。
OAuth流程无法完成
  • 回调路由路径必须与
    oauthRedirectUri
    匹配(默认值为
    /mcp/callback
    )。
  • McpOAuthCallback
    必须与管理器在同一个Provider内渲染。
服务器无法持久化 / SSR报错
  • 默认的
    McpLocalStorage()
    依赖浏览器环境;在服务器端请使用
    McpMemoryStorage()
    McpCustomStorage(...)
无法移除自定义服务器
  • RemoveButton
    默认在连接器预设上隐藏;仅用户添加的服务器可被移除。
传输
  • 仅支持StreamableHTTP;资源、提示词、采样和自动重连功能暂未实现。

Related Skills

相关技能

  • tools -- developer-defined frontend/backend tools and custom tool-call UI (
    makeAssistantTool
    , AI SDK
    tool()
    ,
    makeAssistantToolUI
    ); the complement to user-managed MCP servers.
  • setup -- scaffold with the
    mcp
    template (
    npx assistant-ui@latest create -t mcp
    ) and pick a runtime.
  • runtime -- the chat runtime (
    useChatRuntime
    ) that MCP tools are merged into.
  • 工具 -- 开发者定义的前端/后端工具及自定义工具调用UI(
    makeAssistantTool
    、AI SDK
    tool()
    makeAssistantToolUI
    );与用户管理的MCP服务器互为补充。
  • 初始化 -- 使用
    mcp
    模板快速搭建项目(
    npx assistant-ui@latest create -t mcp
    )并选择运行时。
  • 运行时 -- MCP工具会合并到其中的聊天运行时(
    useChatRuntime
    )。