10 分钟内将任何 React 应用转变为 MCP 客户端

2025-05-25

10 分钟内将任何 React 应用转变为 MCP 客户端

AI 代理已经解锁了强大的用例,因此开发人员正在自动化复杂的工作流程。

但有时您只是想构建智能的东西而不需要额外的复杂性,这可以使用无代理架构来实现。

今天,我们将了解它的含义、MCP 如何适应整个场景,以及如何使用带有 Composio 服务器的 CopilotKit(框架)构建我们自己的无代理应用程序。

让我们开始吧。


涵盖哪些内容?

简而言之,我们正在详细介绍这些主题。

  1. 什么是无代理架构?
  2. MCP及其核心组件介绍。
  3. 如何在三十分钟内运行 Next.js + MCP 客户端。
  4. 构建工作记忆项目来管理来自 Linear 等工具的任务和项目。
  5. 一些具有用例的真实示例。

注意:Copilotkit(用于构建 AI Copilots 的框架)最近推出了对 MCP 的内置支持,我们将在本指南中使用它。

为了使事情变得简单,我们将它连接到Composio,它提供了具有内置身份验证和最少设置的即用型 MCP 服务器。

我们将涵盖很多内容,让我们开始吧。


1.什么是无代理架构?

Agentless architecture指前端(通常是 Web 或移动客户端)直接与智能后端(例如 MCP 服务器)交互的系统设计,无需部署或维护自定义agent来管理状态、工具或操作。

在 AI 应用领域,这意味着您的 React 前端可以向兼容 MCP 的服务器发送结构化的提示和上下文,并接收智能响应,而无需托管您自己的 AI 代理。

您无需编写后端逻辑来处理工具、内存或操作(它们都是 MCP 的一部分),只需向现有的 MCP 服务器发送请求,它就会为您处理智能内容。

🧠 示例:React 应用中 AI 任务助手

假设您正在构建一个基于 React 的项目管理应用程序。

采用无代理架构:

  • 您添加一个聊天框。
  • 用户类型:Create a new task for our launch checklist
  • 您的应用将其转发到像 CopilotKit 这样的 MCP 服务器。
  • MCP 服务器理解该请求,连接到您的工具(例如 Linear),并回复:Task Finalize Launch Assets has been created in the Marketing project.

无需托管您自己的 AI 代理或编写编排逻辑。它就是这么简单。

 

何时采用无代理模式,何时采用基于代理模式?

这取决于用例的复杂程度。以下是一个简单的比较:

无代理架构 基于代理的架构
易于设置,无需后端代理 需要额外设置来托管和管理代理
非常适合简单的前端、静态站点或快速演示 最适合需要内存的复杂工作流程、工具或应用程序
没有内置记忆,大多无状态 支持记忆、历史和不断发展的背景
非常适合 AI 聊天 UI、助手或小助手 非常适合开发代理、RPA 机器人和完全自主代理
只需要访问兼容 MCP 的服务器 需要自己的后端或容器运行时
只需部署前端即可轻松跨用户扩展 需要针对多个并发代理的后端扩展策略

我的建议是两种方法都试试,看看哪种有效。至少,这样你就能大致了解每种方法可能带来的问题。

了解了Agentless架构之后,我们来快速了解一下MCP以及其核心组件。


2.MCP及其核心组件介绍。

模型上下文协议 (MCP) 是一种新的开放协议,它标准化了应用程序向 LLM 提供上下文和工具的方式。

可以将其视为 AI 的通用连接器。MCP 作为 Cursor 的插件系统,允许您通过将其连接到各种数据源和工具来扩展 Agent 的功能。

mcp 服务器

YouTube 上的版权归于 Greg Isenburg

 

MCP 帮助您在 LLM 之上构建代理和复杂的工作流程。

例如,Obsidian 的 MCP 服务器可帮助 AI 助手搜索和阅读 Obsidian 保险库中的笔记。

您的 AI 代理现在可以:

→ 通过 Gmail 发送电子邮件
→ 在 Linear 中创建任务
→ 在 Notion 中搜索文档
→ 在 Slack 中发布消息
→ 在 Salesforce 中更新记录

所有这些都通过标准化界面发送自然语言指令来实现。

想想这对生产力意味着什么。以前需要在 5 个以上应用之间切换的任务,现在只需与客服人员进行一次对话即可完成。

从本质上讲,MCP 遵循客户端-服务器架构,其中主机应用程序可以连接到多个服务器。

mcp 服务器

感谢 ByteByteGo

 

核心组件。

以下是任何通用 MCP 服务器的核心组件。

  • MCP hosts- 想要通过 MCP 访问数据的 Claude Desktop、Cursor、Windsurf 或 AI 工具等应用程序。

  • MCP Clients- 协议客户端与 MCP 服务器保持 1:1 连接,充当通信桥梁。

  • MCP Servers- 轻量级程序,每个程序通过标准化模型上下文协议公开特定功能(如读取文件、查询数据库......)。

  • Local Data Sources- 您计算机上的 MCP 服务器可以安全访问的文件、数据库和服务。例如,浏览器自动化 MCP 服务器需要访问您的浏览器才能运行。

  • Remote Services- MCP 服务器可以连接的外部 API 和基于云的系统。

如果您有兴趣了解该架构,请查看官方文档。它涵盖了协议层、连接生命周期、错误处理以及整体实现。

我们将涵盖所有内容,但如果您有兴趣了解有关 MCP 的更多信息,请查看以下两个博客:


3. 如何在三十分钟内运行 Next.js + MCP 客户端。

在本节中,我们将讨论如何使用 CopilotKit 为您的 Next.js 项目添加 MCP 支持。

我们将集成 Copilotkit,它内置了对模型上下文协议 (MCP) 的支持。这将使我们能够创建一个前端,直接连接到兼容 MCP 的外部服务器。

如果您有兴趣自己阅读,请阅读docs.copilotkit.ai/guides/model-context-protocol上的文档。如果您不想读也没关系;我会详细解释所有步骤和概念。

文档

 

🎯 使用 CLI 的一行命令安装 MCP 支持

如果您没有现有的 Next.js 应用程序,则可以使用npx create-next-app@latest终端中的命令创建一个。

创建 nextjs 项目

项目准备就绪后,集成 MCP 支持的最快方法是使用CopilotKit CLI。只需在终端中运行以下命令即可。

npx copilotkit@latest init -m MCP
Enter fullscreen mode Exit fullscreen mode

这个命令在后台做了很多事情:

  • 安装所有必需的 CopilotKit 依赖项
  • 设置一个可立即使用的接口,用于与 MCP 服务器交互
  • 添加组件以集成 MCP 并安装 shadcn/ui 进行 UI 样式设置

它将指导您安装所需的软件包,并建议您使用 Copilot Cloud 进行部署(无需额外设置)。

使用 CLI 安装

使用 CLI 安装

 

它将验证配置并检测现有的 Next.js 应用是否有效。之后,您可以选择 或default projectmcp demo这是 Copilotkit 团队制作的一个展示项目)。

我已经尝试使用 CLI,但在本指南的范围内,我们将使用默认项目。

默认项目

然后它会提示您安装shadcn/ui内置组件样式。

由于我们使用的是React 19,它非常新。某些库可能尚未正式支持它,并且 npm 可能会因为版本冲突(称为peer dependency issues)而显示错误。

为了解决这个问题,CLI 建议使用--legacy-peer-deps,它告诉 npm 忽略这些版本警告并继续安装。

这是一种通常可以很好地发挥作用的解决方法,特别是对于仍在获得支持的较新 React 版本而言。

安装shadcn ui

安装shadcn ui

 

安装完成后,您将看到已添加内容的摘要。

终于安装好了

您可以使用本地启动服务器npm run dev并导航至http://localhost:3000/copilotkit以查看您的 MCP 就绪前端。

最终的 localhost copilotkit 输出

 

📧 连接到 Gmail MCP 服务器(演示)

您需要输入您希望使用的 MCP 服务器的 SSE 网址。您可以在mcp.composio.dev上找到 100 多个可用的托管 MCP 服务器列表

让我们简单检查一下流程。我使用的 Gmail 服务器是mcp.composio.dev/gmail

Gmail MCP 服务器

复制您从 Composio 服务器页面生成的 MCP 服务器 URL,并将其粘贴到Enter MCP server URL页面上的占位符字段 ( ) 中。此 URL 属于敏感信息,仅供个人使用,因此我对其进行了模糊处理。

模糊的 mcp 服务器

我已经给出了发送一封电子邮件的提示,并在电子邮件正文中说明了hi@anmolbaranwal.com主题。working demo of copilotkit mcpcomposio server works

它将调用适当的 MCP 服务器(如果您有多个),并根据您的提示采取正确的操作。

由于没有活动连接,它将首先建立一个连接(如上图所示)。您需要通过在浏览器中复制 OAuth URL 来进行身份验证。

💡 建议先用虚拟账户测试一下,尤其是在实验的时候。一旦满意,就可以用主账户自动执行操作。

Gmail 身份验证

您必须提供对服务器的访问权限,以便它可以根据您的提示采取行动。

操作权限

一旦您通过身份验证,您将在浏览器中看到确认信息。

身份验证成功

你只需输入一些信息done,代理就可以验证你的活动连接。让我惊讶的是,它在发送电子邮件之前仍然会请求批准,这确保了你仍然掌控着一切。

赞同

获得批准后,代理将继续发送电子邮件。

电子邮件已发送

不知何故,它没有提供主题,但我们收到了带有适当正文回复的电子邮件。

Gmail MCP

耶!🎉 您现在已经使用 CopilotKit 完成了与 MCP 服务器的端到端集成。

您可以对所有其他 MCP 服务器执行相同操作并创建多步骤工作流程。

接下来:我们将从头开始手动构建此流程,以便更好地理解底层组件。

 

🎯 从头开始​​设置整个集成

让我们从头开始演示如何设置 CopilotKit 集成以使用 MCP 服务器。这将帮助您了解端到端的架构和流程。

如果您已经有现有的 Next.js 项目,请跳至步骤 2。

步骤 1:使用 TypeScript 创建 Next.js 项目

如果您没有前端,您可以使用以下命令创建一个项目next.jsTypeScriptTailwind CSS

npx create-next-app@latest 
Enter fullscreen mode Exit fullscreen mode

创建 nextjs 项目

您的项目结构如下所示。我们将使用最新版本的 Next.js 以及 App Router。我添加了一些文件(用于我的风格偏好),我每个项目都会这样做,所以这不是强制性的。

目录结构

🧠 你可能会注意到没有tailwind.config.js。这是因为,使用Tailwind CSS V4,我们现在可以直接在 globals.css 中自定义样式,而新的 next.js 应用程序不再需要配置文件。

 

第 2 步:安装 CopilotKit 包并设置提供程序。

安装必要的 CopilotKit 包。

npm install @copilotkit/react-core @copilotkit/react-ui
Enter fullscreen mode Exit fullscreen mode
  • @copilotkit/react-core提供将您的 React 应用程序与 CopilotKit 后端和 MCP 服务器连接的核心上下文和逻辑。

  • @copilotkit/react-ui提供现成的 UI 组件,例如<CopilotChat />快速构建 AI 聊天或助手界面。

安装 copilotkit 包

<CopilotKit>组件必须包裹应用中支持 Copilot 的部分。大多数情况下,最好将其放置在整个应用的周围,例如app/layout.tsx

import type { Metadata } from 'next'
import './globals.css'

import '@copilotkit/react-ui/styles.css'
import './globals.css'
import { CopilotKit } from '@copilotkit/react-core'

export const metadata: Metadata = {
  title: 'CopilotKit MCP Demo',
  description: 'CopilotKit MCP Demo',
}

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode
}>) {
  return (
    <html lang="en">
      <body
        className={
          'relative flex flex-col overflow-x-hidden font-sans antialiased'
        }
        suppressHydrationWarning
      >
        <CopilotKit publicApiKey="<replace_with_your_own>">
          {children}
        </CopilotKit>
      </body>
    </html>
  )
}
Enter fullscreen mode Exit fullscreen mode

将其替换为cloud.copilotkit.ai<replace_with_your_own>中的 API 密钥。它是免费的,如果你正在构建用于生产环境的代码,建议使用。

如果您有兴趣使用 MCP 服务器配置自托管运行时,请阅读文档

copilotkit 云

只需单击“开始”,您就会找到一个公共 API 密钥。

API 密钥

 

步骤 3:创建组件来配置 MCP 服务器连接

现在我们将创建一个辅助组件,用于将您的应用连接到 MCP 服务器。在 处创建一个新文件src\components\McpServerManager.tsx

'use client'

import { useCopilotChat } from '@copilotkit/react-core'
import { useEffect } from 'react'

function McpServerManager() {
  const { setMcpServers } = useCopilotChat()

  useEffect(() => {
    setMcpServers([
      {
        // Try a sample MCP server at https://mcp.composio.dev/
        endpoint: 'your_mcp_sse_url',
      },
    ])
  }, [setMcpServers])

  return null
}

export default McpServerManager
Enter fullscreen mode Exit fullscreen mode

McpServerManager组件将您的应用连接到 MCP 服务器。

  • 当组件加载(useEffect运行)时,它会通过提供服务器 URL 来告诉 CopilotKit 连接到哪个 MCP 服务器。

  • 组件本身不渲染任何内容(return null),它只是在后台建立连接。

它会将您的应用配置为在页面加载时自动与 MCP 服务器通信。您只需在属性中设置your_mcp_sse_url用于工具访问的特定 MCP 端点 ( ) endpoint

 

第四步:添加聊天界面。

ChatInterface组件会创建实际的聊天 UI,并确保聊天功能知道您要连接的 MCP 服务器。在 处创建一个新文件src\components\ChatInterface.tsx

'use client'

import { CopilotChat } from '@copilotkit/react-ui'
import McpServerManager from './McpServerManager'

export default function ChatInterface() {
  return (
    <div className="flex h-screen p-4">
      <McpServerManager />
      <CopilotChat
        instructions="You are a helpful assistant with access to MCP servers."
        className="w-full flex-grow rounded-lg"
      />
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

以下是对正在发生的事情的简单解释。

  • McpServerManager在页面加载时运行并告诉 CopilotKit 使用哪个 MCP 服务器。

  • CopilotChat显示用户可以与 AI 交谈的聊天框。

  • 告诉instructions人工智能它应该成为哪种助手。

 

步骤 5:可视化 MCP 工具调用(可选)。

要监控助手触发的工具调用,请添加一个ToolRenderer组件。这完全是可选的,但在开发过程中很有用。

在 处创建一个新文件src\components\ToolRenderer.tsx

'use client'

import {
  useCopilotAction,
  CatchAllActionRenderProps,
} from '@copilotkit/react-core'
import McpToolCall from './McpToolCall'

export function ToolRenderer() {
  useCopilotAction({
    /**
     * The asterisk (*) matches all tool calls
     */
    name: '*',
    render: ({ name, status, args, result }: CatchAllActionRenderProps<[]>) => (
      <McpToolCall status={status} name={name} args={args} result={result} />
    ),
  })
  return null
}
Enter fullscreen mode Exit fullscreen mode

然后创建McpToolCall.tsx(在同一components目录下)。这将在可折叠的 UI 中显示工具名称、状态、参数和结果。

它是一个可视化调试组件,显示工具调用的详细信息,例如助手尝试执行的操作以及返回的结果。

/* eslint-disable @typescript-eslint/no-explicit-any */
'use client'

import * as React from 'react'

interface ToolCallProps {
  status: 'complete' | 'inProgress' | 'executing'
  name?: string
  args?: any
  result?: any
}

export default function McpToolCall({
  status,
  name = '',
  args,
  result,
}: ToolCallProps) {
  const [isOpen, setIsOpen] = React.useState(false)

  const classes = {
    container:
      'bg-white rounded-xl overflow-hidden w-full border-2 border-gray-200 shadow-md transition-all duration-200 hover:shadow-xl my-1',
    header:
      'p-4 flex items-center cursor-pointer group bg-gray-50 border-b border-gray-200',
    title: 'text-gray-900 font-semibold overflow-hidden text-ellipsis',
    statusContainer: 'ml-auto flex items-center gap-2',
    statusText: 'text-xs text-gray-700 font-medium mr-1',
    content: 'px-5 pb-5 pt-3 text-gray-800 font-mono text-xs',
    section: 'mb-4',
    sectionTitle:
      'text-gray-700 text-xs uppercase tracking-wider mb-2 font-sans font-bold',
    codeBlock:
      'whitespace-pre-wrap max-h-[200px] overflow-auto text-gray-900 bg-gray-50 p-3 rounded border border-gray-200',
    chevron: {
      base: 'text-gray-700 mr-2 transition-transform duration-200',
      open: 'rotate-90',
      hover: 'group-hover:text-gray-900',
    },
    contentWrapper: {
      base: 'overflow-hidden transition-all duration-300 ease-in-out',
      open: 'max-h-[600px] opacity-100',
      closed: 'max-h-0 opacity-0',
    },
  }

  // Status indicator colors
  const statusColors = {
    complete: 'bg-emerald-500 shadow-emerald-500/40',
    inProgress: 'bg-amber-500 shadow-amber-500/40',
    executing: 'bg-blue-500 shadow-blue-500/40',
  }

  // Simplified format function
  const format = (content: any): React.ReactNode => {
    if (!content) return null
    return typeof content === 'object' ? (
      <span>{JSON.stringify(content, null, 2)}</span>
    ) : (
      <span>{String(content)}</span>
    )
  }

  const getStatusColor = () => {
    const baseColor = statusColors[status].split(' ')[0]
    const shadowColor = statusColors[status].split(' ')[1]
    return `${baseColor} ${status === 'inProgress' || status === 'executing' ? 'animate-pulse' : ''} shadow-[0_0_10px] ${shadowColor}`
  }

  return (
    <div className={classes.container}>
      <div className={classes.header} onClick={() => setIsOpen(!isOpen)}>
        <ChevronRight isOpen={isOpen} chevronClasses={classes.chevron} />
        <span className={classes.title}>{name || 'MCP Tool Call'}</span>
        <div className={classes.statusContainer}>
          <span className={classes.statusText}>
            {status === 'complete'
              ? 'Completed'
              : status === 'inProgress'
                ? 'In Progress'
                : 'Executing'}
          </span>
          <div className={`h-3 w-3 rounded-full ${getStatusColor()}`} />
        </div>
      </div>

      <div
        className={`${classes.contentWrapper.base} ${isOpen ? classes.contentWrapper.open : classes.contentWrapper.closed}`}
      >
        <div className={classes.content}>
          <div className={classes.section}>
            <div className={classes.sectionTitle}>Name</div>
            <pre className={classes.codeBlock}>{name}</pre>
          </div>
          {args && (
            <div className={classes.section}>
              <div className={classes.sectionTitle}>Parameters</div>
              <pre className={classes.codeBlock}>{format(args)}</pre>
            </div>
          )}

          {status === 'complete' && result && (
            <div className={classes.section}>
              <div className={classes.sectionTitle}>Result</div>
              <pre className={classes.codeBlock}>{format(result)}</pre>
            </div>
          )}
        </div>
      </div>
    </div>
  )
}

const ChevronRight = ({
  isOpen,
  chevronClasses,
}: {
  isOpen: boolean
  chevronClasses: any
}) => {
  return (
    <svg
      width="16"
      height="16"
      viewBox="0 0 24 24"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      className={`${chevronClasses.base} ${isOpen ? chevronClasses.open : ''} ${chevronClasses.hover}`}
      stroke="currentColor"
      strokeWidth="2.5"
      strokeLinecap="round"
      strokeLinejoin="round"
    >
      <polyline points="9 18 15 12 9 6"></polyline>
    </svg>
  )
}
Enter fullscreen mode Exit fullscreen mode

 

步骤6:组合所有组件。

创建所有单独的组件后,就该将它们全部组合起来了src/app/page.tsx

'use client'

import { CopilotChat } from '@copilotkit/react-ui'
import McpServerManager from '../components/McpServerManager'
import { ToolRenderer } from '../components/ToolRenderer'

export default function Page() {
  return (
    <div className="flex h-screen p-4">
      <McpServerManager />
      <CopilotChat
        instructions="You are a helpful assistant with access to MCP servers."
        className="w-full flex-grow rounded-lg"
      />
      <ToolRenderer />
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

恭喜!🎉 您的 CopilotKit 和 MCP 服务器设置已完成!

 

步骤 7:添加 MCP 服务器端点

现在我们只需要添加端点 URL 来连接到外部 MCP 服务器。这可以在组件内部通过像这样的属性McpServerManager传递 URL来实现。endpoint

setMcpServers([
  {
    // Try a sample MCP server at https://mcp.composio.dev/
    endpoint: 'your_mcp_sse_url',
  },
])
Enter fullscreen mode Exit fullscreen mode

有两种更简单的方法可以立即连接到 100 多个 MCP 服务器:

1) Composio - Composio 拥有完全托管的服务器,无需复杂的设置,并内置 Auth 功能。它支持 250 多种工具,并提供 20,000 多个预构建的 API 操作,无需编码即可集成。

它还可以在本地或远程操作。并提供更好的工具调用准确性,使AI代理能够与集成应用程序顺畅交互。

作曲家

这也意味着更少的停机时间和维护问题。您可以在status.composio.dev/查看状态

状态组成

通过每个选项,您将找到活跃用户总数、当前版本、最近更新的时间以及所有可用的操作。

TypeScript您将找到使用、安装它的说明Python,并且它支持 Claude (MacOS)、Windsurf (MacOS) 和 Cursor 作为 MCP 主机。

 

2)Zapier - Zapier 支持超过8,000 个应用程序,但每小时只能进行 80 次工具调用,这可能是一个限制。

扎皮尔

如果出现服务器问题,只需使用其他选项。

 

🔧 MCP 服务器故障排除

最简单的方法是使用 Cursor 或 Claude 等客户端(您只需要在 Cursor 中运行 npx 命令),然后您可以通过打开聊天来测试工具调用。

如果您不确定您的 MCP 服务器是否正常工作:

⚡ 直接在浏览器中打开 MCP 服务器 URL。如果它返回数据流(通常是 JSON 行),则表示服务器正常运行。⚡
检查浏览器的 DevTools 是否存在网络或控制台错误。⚡
有时,过时的连接可能会导致静默故障,重启开发服务器可以解决此问题。

 

步骤 8:添加 MCP 端点并运行服务器。

您可以使用 在 next.js 应用中运行服务器npm run dev。现在您应该可以看到聊天界面。

手动积分ui界面

这个流程与上一个非常相似。我再次使用 Gmail 服务器https://mcp.composio.dev/gmail来帮助您理解从头设置和通过 CLI 设置之间的结果差异。

Gmail MCP 服务器

添加端点后,只需提供提示,您将能够看到我们使用该ToolRenderer组件以来的工具调用。

成分

和以前一样,它会请求批准并相应地发送电子邮件。我已确认邮件已成功发送到我的收件箱。

mcp 服务器工作

在下一节中,我们将举一个复杂的例子。


4. 构建工作记忆项目来管理来自 Linear 等工具的任务和项目。

让我们研究一个工作记忆项目,它将教我们如何构建交互式、人工智能聊天应用程序,并使用 MCP 和 CopilotKit 与 Linear 和 Slack 等外部工具连接。

涉及的技术栈:

在继续之前,请确保您有Node.js(推荐使用 LTS 版本)。

步骤 1:克隆并设置存储库。

为了简单起见,我们将在 GitHub 上克隆copilotkit mcp 存储库。

git clone https://github.com/CopilotKit/copilotkit-mcp-demo.git
Enter fullscreen mode Exit fullscreen mode

git 克隆

请使用安装依赖项npm install

npm i

之后,我们需要.env在该目录下创建一个文件root。然后将你的OpenAI API 密钥添加到该.env文件中。我已附上文档链接,方便查阅。

这将是命名约定。

OPENAI_API_KEY= YOUR_API_KEY
Enter fullscreen mode Exit fullscreen mode

OpenAI API密钥

OpenAI API密钥

 

您还需要将cloud.copilotkit.ai中的 API 密钥放入文件.env。如果您要构建用于生产环境的代码,则建议您使用这个密钥。

这将是命名约定。

NEXT_PUBLIC_COPILOT_CLOUD_API_KEY= YOUR_API_KEY
Enter fullscreen mode Exit fullscreen mode

只需单击“开始”,您就会找到一个公共 API 密钥。

API 密钥

 

第 2 步:让我们看一下项目结构。

项目结构如下。

  • /src/app:包含 Next.js 页面、布局和全局样式。

  • /src/components:包括可重复使用的 UI 组件和代理界面,如旅行、研究、聊天、地图和侧边栏。

  • /src/providers:包装用于管理代理状态的全局状态提供程序。

  • /src/lib:包含实用函数和配置文件。

  • /src/hooks:用于可重复使用逻辑的自定义 React 钩子。

  • /src/contexts:提供用于管理全局状态的 React 上下文。

项目结构

 

步骤 3:让我们了解代码库。

我不会逐一介绍每个组件的代码,否则这篇博客会太长,所以我会尽量涵盖所涉及的概念。请查看代码库并继续学习,了解所有组件是如何协同工作的。

⚡ 1. Entry 是src/app/layout.tsx,它导入全局样式,加载 Google 字体,然后将所有内容包装在您的顶级中<Providers>

⚡ 2. Providers(src/providers/Providers.tsx)是设置应用程序的状态、API 访问和服务器配置的全局提供程序的组件。

"use client";

import { CoAgentsProvider } from "@/components/coagents-provider";
import McpServerManager from "@/components/McpServerManager";
import { ToolRenderer } from "@/components/ToolRenderer";
import { useLocalStorage } from "@/hooks/use-local-storage";
import { CopilotKit } from "@copilotkit/react-core";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import React from "react";

export interface Config {
  endpoint: string;
  serverName: string;
}

export interface ConfigContextType {
  config: Config[];
  setConfig: (config: Config[]) => void;
}

const queryClient = new QueryClient();
export const ServerConfigsContext = React.createContext<
  ConfigContextType | undefined
>(undefined);
export default function Providers({ children }: { children: React.ReactNode }) {
  const [mcpConfig] = useLocalStorage("mcpConfig", []);
  const [config, setConfig] = React.useState<Config[]>(mcpConfig || []);

  return (
    <ServerConfigsContext.Provider value={{ config, setConfig }}>
      <QueryClientProvider client={queryClient}>
        <CopilotKit
          publicApiKey={process.env.NEXT_PUBLIC_COPILOT_CLOUD_API_KEY}
        >
          <McpServerManager configs={config} />
          <ToolRenderer />
          {/* <MCPToolCall /> */}
          <CoAgentsProvider>{children}</CoAgentsProvider>
        </CopilotKit>
        <ReactQueryDevtools initialIsOpen={false} />
      </QueryClientProvider>
    </ServerConfigsContext.Provider>
  );
}
Enter fullscreen mode Exit fullscreen mode
  • ServerConfigsContext:保存已配置的“MCP”服务器列表
  • QueryClientProvider:连接 React Query
  • <CopilotKit>:初始化 CopilotKit 运行时(使用您的公共 API 密钥)
  • <McpServerManager>:从上下文读取配置并告诉 CopilotKit 使用哪些服务器
  • <ToolRenderer>:捕获所有 CopilotKit“工具调用”并将其呈现为 MCPToolCall 卡
  • <CoAgentsProvider>:整理代理状态的占位符(目前仅通过子级传递)

⚡ 3. MCP 服务器配置

  • MCPConfigModal(src/components/mcp-config-modal.tsx):一种模式,可让您添加/删除 SSE 或 stdio 服务器,持久保存到 localStorage,更新上下文和 CopilotKit。
  • use-local-storage ( src\hooks\use-local-storage.tsx) :用于保存这些设置的钩子

由于代码太长,因此我没有将其包括在内。

⚡ 4. 聊天用​​户界面

  • ChatWindow(src/components/chat-window.tsx)只是一个样式包装器@copilotkit/react-ui’s <CopilotChat>
  • 你通过了:
    • “指示”(告诉 AI 始终通过 MCP 服务器并提供当前的待办事项状态)
    • 标签、图标、旋转/停止按钮
"use client";
import { useTodo } from "@/contexts/TodoContext";
import { CopilotChat } from "@copilotkit/react-ui";
import "@copilotkit/react-ui/styles.css";
import { Loader2, RotateCw, SendIcon, Square } from "lucide-react";
import { FC } from "react";
import { Loader } from "./Loader";

export const ChatWindow: FC = () => {
  const { todos } = useTodo();
  return (
    <CopilotChat
      className="h-full flex flex-col"
      instructions={`Always use the MCP server to complete the task. You will be provided with a list of MCP servers. Use the appropriate MCP server to complete the task.
      To perform any actions over the todo task use the following data for manipulation ${JSON.stringify(
        todos
      )}`}
      labels={{
        title: "To-do Assistant",
        initial:
          "Hi! I'm your AI task assistant, powered by MCP servers that you can configure to help manage and break down your tasks. \n\nHow can I help you today?",
        placeholder: "Type your message here...",
        regenerateResponse: "Try another response",
      }}
      icons={{
        sendIcon: (
          <SendIcon className="w-4 h-4 hover:scale-110 transition-transform" />
        ),
        activityIcon: (
          <Loader
            texts={[
              "Thinking...",
              "Analyzing Your Query...",
              "Taking Action...",
            ]}
          />
        ),
        spinnerIcon: <Loader2 className="w-4 h-4 animate-spin" />,
        stopIcon: (
          <Square className="w-4 h-4 hover:text-red-500 transition-colors" />
        ),
        regenerateIcon: (
          <RotateCw className="w-4 h-4 hover:rotate-180 transition-transform duration-300" />
        ),
      }}
    />
  );
};
Enter fullscreen mode Exit fullscreen mode

⚡ 5. 待办事项状态和操作

  • TodoContext(src/contexts/TodoContext.tsx)保存内存中的待办事项和子任务列表以及所有 CRUD/切换功能
  • TodoApp(src/components/Todo.tsx)渲染用于添加/切换/删除任务和子任务的 UI
  • 在 TodoApp 内部,您还注册了一套 useCopilotAction 钩子(ADD_TASK、ADD_SUBTASK、COMPLETE_TASK 等)和一个用于 JSON 编码列表的 useCopilotReadable。

当 AI 决定调用其中一个操作时,CopilotKit 将调用您的处理程序,以更新相同的 React 上下文。

⚡ 6. 视觉表现

  • 视觉呈现 ( src/components/VisualRepresentation.tsx)
    • 订阅相同的待办事项上下文
    • 每当您的待办事项发生变化时,构建一组“节点”和“边”
    • 使用自定义 ParentNode/ChildNode 组件在 React Flow 中呈现树视图(src/components/Nodes.tsx
    • 点击节点可切换相应的任务/子任务

⚡ 7. 工具调用

  • ToolRenderer( src/components/ToolRenderer.tsx) 安装一个通配符 useCopilotAction 监听器
  • 每次 CopilotKit 发出“工具调用”(即访问 MCP 服务器)时,您都会呈现一个 MCPToolCall 卡(src/components/MCPToolCall.tsx)来显示状态、错误/结果等。

⚡ 8. 画布布局

  • Canvas( src/components/canvas.tsx) 将所有内容缝合在一起:
    • 左窗格:聊天窗口
    • 主区域:两张卡片并排(VisualRepresentation + TodoApp)
    • 切换 MCPConfigModal 的“MCP 服务器”按钮
    • 在底层,它还会调用 useCopilotChatSuggestions 来呈现 AI 驱动的建议

⚡ 9. UI 基元和实用程序

  • src/components/ui/… – 基于基数的按钮、卡片、对话框等,均使用 Tailwind 设置样式
  • src/lib/utils.ts – 用于组合 Tailwind 类的小型“cn”助手
  • src/hooks – useLocalStorage、useIsMobile

🧠 流程摘要:

这是所有组件的流程。

1) 您通过模态框配置一个或多个 MCP 服务器 → 它们被保存在localStorage→ 然后通过 传递到 CopilotKit McpServerManager

2) 您在聊天中输入一条消息 → CopilotKit 将其路由到 AI → AI 可以ADD_TASK通过 MCP 服务器“调用”您注册的操作(例如)。

3) 然后ToolRenderer可视化每个工具调用 → 您的动作处理程序在 React 上下文中更新状态 → TodoApp 和 VisualRepresentation 都使用新状态重新渲染 → 您的聊天流继续。

我相信,如果你打开代码库并了解流程,一切都会变得有意义。

步骤 4:最终演示

您可以在本地运行服务器,并使用copilotkit-mcp-demo.vercel.appnpm run dev检查实时演示应用程序

copilotkit mcp 官方 demo

Star CopilotKit MCP 演示⭐️


5. 一些具有用例的真实示例。

掌握基础知识后,您可以通过以下一些先进且富有创意的方法将 CopilotKit 与 MCP 结合使用,以构建无代理的强大工作流程。

我们可以使用 MCP 的可组合服务器端点进行链工具交互。

✅ 跨 API 的多步骤工作流自动化。

让我们假设一个示例任务:Fetch unresolved Linear issues, summarize them and send a report to the team via Slack.

技术流程可能是:

  • MCP Server 1 (Linear):使用操作获取线性问题Linear_get_linear_issue

线性问题

  • Local LLM (such as OpenAI):使用任何 API 总结问题标题和描述。

  • MCP Server 2 (Slack):使用slack_message操作在定义的频道中发布摘要。

Slack 发布消息

您可以通过提示、工具和 MCP 服务器定义多步骤工作流程。

 

✅ 语义代码审查助手。

我们可以用自定义逻辑构建一个简单的代码审查助手。

让我们假设一个示例任务:Review this PR using our frontend checklist and comment inline on unoptimized code.

技术流程可能是:

  • GitHub MCP Server:获取 PR 差异或文件列表。

  • Prompt Templates:将清单规则加载为结构化提示。

  • LLM (such as OpenAI):运行语义分析并生成内联反馈。

  • GitHub MCP:使用适当的行动,例如post_comment_on_pull_request留言。

GitHub MCP 服务器

 

✅ 情境 CRM 助手

我们可以构建根据过去的线索和对话历史做出回应的助手。

让我们假设一个示例任务:Find all unanswered emails from investors and suggest follow-ups based on the last threads.

技术流程可能是:

  • Gmail MCP:使用 从 Gmail 获取线程列表gmail_list_threads

  • LLM + Context Chunking:使用 OpenAI 函数调用总结最近的线程。

  • Draft Reply:通过 LLM 生成响应。

  • Gmail MCP:用于gmail_send_email发送草稿。

Gmail MCP 服务器

您可以使用 Notion 或 Airtable MCP 进行扩展,以记录交互或添加提醒,例如:Remind me next week if no reply.

 

这些只是起点。MCP 允许您完全通过提示(逻辑上)自动化几乎任何多工具工作流程。


许多开发者认为集成 MCP 为时过早或过于复杂。但愿 CopilotKit 的内置支持能够证明这一点。

所以,去创造一些疯狂的东西吧。让它变得有用。让世界见证当工作流程与环境相遇时所能创造的一切。

祝你今天过得愉快!下次再见 :)

你可以在anmolbaranwal.com
查看 我的作品 感谢阅读!🥰
叽叽喳喳 GitHub 领英

在Twitter上关注 CopilotKit  并打招呼,如果您想构建一些很酷的东西,请加入 Discord 社区。

文章来源:https://dev.to/copilotkit/add-an-mcp-client-to-any-react-app-in-under-30-minutes-55gm
PREV
🚀我如何在 Dub.co 中集成 AI 副驾驶(几分钟内)🤖✨
NEXT
🎄𝟐𝟒 𝐥𝐢𝐛𝐫𝐚𝐫𝐢𝐞𝐬 𝐭𝐨 𝐚𝐜𝐡𝐢𝐞𝐯𝐞 全栈精通(𝐛𝐞𝐟𝐨𝐫𝐞 𝐂𝐡𝐫𝐢𝐬𝐭𝐦𝐚𝐬)🎅🏽🎁 Web-Dev🌐:UI/UX 🦋:GenAI🤖:安全/隐私🔐:移动📱:其他🎅:圣诞快乐! 🎅🏽☃️ 1. Swirl 2. 简历匹配器