React MCP连接钩子

一个轻量级的React钩子,用于连接Model Context Protocol(MCP)服务器,简化AI系统的认证和工具调用。

  • by Automata-Labs-team
  • TypeScript
  • 本地部署
  • 更新于
在 GitHub 查看 Automata-Labs-team/use-mcp

使用说明

🦑 使用MCP(可能是指某种工具、框架或协议)🦑

一个用于连接的轻量级React Hook 模型上下文协议(MCP) 服务器。简化了实施MCP标准的AI系统的身份验证和工具调用。

试试看: 聊天演示 | MCP 检查器 | Cloudflare Workers AI 实验室

安装

npm install use-mcp
# or
pnpm add use-mcp
# or
yarn add use-mcp

发展

要运行包含所有示例和服务器的开发环境:

pnpm dev

这开始了:

  • 检查员http://localhost:5001 - MCP服务器调试工具
  • 聊天用户界面http://localhost:5002 - 示例聊天界面
  • Hono MCP 服务器http://localhost:5101 - 示例MCP服务器
  • CF代理MCP服务器http://localhost:5102 - Cloudflare Workers AI MCP 服务器

测试

集成测试位于 test/ 默认情况下,以无头模式运行目录(或:默认情况下,以无头模式执行目录中的操作)

cd test && pnpm test              # Run tests headlessly (default)
cd test && pnpm test:headed       # Run tests with visible browser
cd test && pnpm test:watch        # Run tests in watch mode
cd test && pnpm test:ui           # Run tests with interactive UI

特点/特性

  • 🔄 自动连接管理,支持重新连接和重试
  • 🔐 支持弹出窗口和回退机制的OAuth认证流程处理
  • 📦 简单的React钩子接口,用于MCP集成
  • 全面支持MCP工具、资源和提示
  • 📄 访问服务器资源并读取其内容
  • 💬 使用服务器提供的提示模板
  • 🧰 用于编辑器辅助和类型检查的TypeScript类型
  • 📝 全面的日志记录用于调试
  • 🌐 支持HTTP和SSE(服务器发送事件)两种传输方式
  • 🧠 服务器驱动的引出支持,支持可选的处理器注册

快速入门

import { useEffect } from 'react'
import { useMcp } from 'use-mcp/react'

function MyAIComponent() {
  const {
    state,          // Connection state: 'discovering' | 'pending_auth' | 'authenticating' | 'connecting' | 'loading' | 'ready' | 'failed'
    tools,          // Available tools from MCP server
    resources,      // Available resources from MCP server
    prompts,        // Available prompts from MCP server
    error,          // Error message if connection failed
    callTool,       // Function to call tools on the MCP server
    readResource,   // Function to read resource contents
    getPrompt,      // Function to get prompt messages
    retry,          // Retry connection manually
    authenticate,   // Manually trigger authentication
    clearStorage,   // Clear stored tokens and credentials
    onEliciation,   // Register handler for server elicitations
  } = useMcp({
    url: 'https://your-mcp-server.com',
    clientName: 'My App',
    autoReconnect: true,
  })

  useEffect(() => {
    if (state !== 'ready') return
    onEliciation(async params => {
      if (params.prompt === 'confirm-action') {
        return { action: 'respond', content: { type: 'text', text: 'Approved' } }
      }
      return { action: 'decline' }
    })
  }, [state, onEliciation])

  // Handle different states
  if (state === 'failed') {
    return (
      <div>
        <p>Connection failed: {error}</p>
        <button onClick={retry}>Retry</button>
        <button onClick={authenticate}>Authenticate Manually</button>
      </div>
    )
  }

  if (state !== 'ready') {
    return <div>Connecting to AI service...</div>
  }

  // Use available tools
  const handleSearch = async () => {
    try {
      const result = await callTool('search', { query: 'example search' })
      console.log('Search results:', result)
    } catch (err) {
      console.error('Tool call failed:', err)
    }
  }

  return (
    <div>
      <h2>Available Tools: {tools.length}</h2>
      <ul>
        {tools.map(tool => (
          <li key={tool.name}>{tool.name}</li>
        ))}
      </ul>
      <button onClick={handleSearch}>Search</button>
      
      {/* Example: Display and read resources */}
      {resources.length > 0 && (
        <div>
          <h3>Resources: {resources.length}</h3>
          <button onClick={async () => {
            const content = await readResource(resources[0].uri)
            console.log('Resource content:', content)
          }}>
            Read First Resource
          </button>
        </div>
      )}
      
      {/* Example: Use prompts */}
      {prompts.length > 0 && (
        <div>
          <h3>Prompts: {prompts.length}</h3>
          <button onClick={async () => {
            const result = await getPrompt(prompts[0].name)
            console.log('Prompt messages:', result.messages)
          }}>
            Get First Prompt
          </button>
        </div>
      )}
    </div>
  )
}

设置OAuth回调

为了处理OAuth认证流程,您需要在您的应用中设置一个回调端点。

使用 React Router

// App.tsx with React Router
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import { useEffect } from 'react'
import { onMcpAuthorization } from 'use-mcp'

function OAuthCallback() {
  useEffect(() => {
    onMcpAuthorization()
  }, [])

  return (
    <div>
      <h1>Authenticating...</h1>
      <p>This window should close automatically.</p>
    </div>
  )
}

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/oauth/callback" element={<OAuthCallback />} />
        <Route path="/" element={<YourMainComponent />} />
      </Routes>
    </Router>
  )
}

使用 Next.js Pages 路由器

// pages/oauth/callback.tsx
import { useEffect } from 'react'
import { onMcpAuthorization } from 'use-mcp'

export default function OAuthCallbackPage() {
  useEffect(() => {
    onMcpAuthorization()
  }, [])

  return (
    <div>
      <h1>Authenticating...</h1>
      <p>This window should close automatically.</p>
    </div>
  )
}

API 参考文档

useMcp 钩子

function useMcp(options: UseMcpOptions): UseMcpResult

选项

选项 类型 描述
url string 必需的您的MCP服务器的URL
clientName string OAuth注册时您的客户名称
clientUri string OAuth 注册时客户端的 URI
callbackUrl string OAuth重定向的自定义回调URL(默认为 /oauth/callback (基于当前的起源)
storageKeyPrefix string 用于在localStorage中存储OAuth数据的键前缀(默认为“mcp:auth”)
clientConfig object MCP客户端身份的自定义配置
debug boolean 是否启用详细调试日志记录
autoRetry boolean | number 如果初始连接失败,则自动重试连接,延迟以毫秒为单位
autoReconnect boolean | number 如果已建立的连接丢失,则自动重新连接,延迟以毫秒为单位(默认:3000)
transportType 'auto' | 'http' | 'sse' 传输类型偏好:'auto'(HTTP,备选SSE),'http'(仅HTTP),'sse'(仅SSE)(默认:'auto')
preventAutoAuth boolean 防止初始连接时自动弹出身份验证窗口(默认:false)
onPopupWindow (url: string, features: string, window: Window | null) => void 认证弹窗打开后立即调用回调函数

返回值

属性 类型 描述
state string 当前连接状态:'发现中', '等待授权', '正在授权', '正在连接', '加载中', '就绪', '失败'
tools Tool[] 来自MCP服务器的可用工具
resources Resource[] 来自MCP服务器的可用资源
resourceTemplates ResourceTemplate[] 来自MCP服务器的可用资源模板
prompts Prompt[] 来自MCP服务器的可用提示
error string | undefined 如果连接失败,显示错误信息
authUrl string | undefined 如果弹窗被阻止,则使用手动认证URL
log { level: 'debug' | 'info' | 'warn' | 'error'; message: string; timestamp: number }[] 日志消息数组
callTool (name: string, args?: Record<string, unknown>) => Promise<any> 在MCP服务器上调用工具的功能
listResources () => Promise<void> 刷新可用资源列表
readResource (uri: string) => Promise<{ contents: Array<...> }> 读取特定资源的内容
listPrompts () => Promise<void> 刷新可用提示列表
getPrompt (name: string, args?: Record<string, string>) => Promise<{ messages: Array<...> }> 获取带有可选参数的特定提示
retry () => void 手动尝试重新连接
disconnect () => void 与MCP服务器断开连接
authenticate () => void 手动触发身份验证
clearStorage () => void 清除所有存储的认证数据
onEliciation (cb: (params) => Promise<ElicitResult> | ElicitResult) => void 注册一个处理程序以响应服务器的引出请求

许可证

麻省理工学院(MIT)