React Native SDK

专为React Native环境设计的轻量级SDK,提供高效的内存通信和完整TypeScript支持。

  • by JXnan
  • TypeScript
  • 本地部署
  • 更新于
在 GitHub 查看 JXnan/typescript-sdk-rn

使用说明

MCP TypeScript SDK for React Native

🎯 React Native 优化版本的 MCP SDK 专为 React Native 环境设计,使用 inMemory 传输方式,实现客户端和服务端在同一进程内高效通信。

✨ 特性

  • ✅ 完全兼容 React Native - 无 Node.js 特定依赖
  • ✅ 零网络开销 - Client 和 Server 在同一进程内通信
  • ✅ 类型安全 - 完整的 TypeScript 类型支持
  • ✅ 简单易用 - 开箱即用的 API
  • ✅ 轻量级 - 移除了 HTTP/stdio 等传输层,只保留核心功能
  • ✅ 高性能 - 内存直传,无序列化开销

📦 安装

# npm
npm install @jxee/sdk

# yarn
yarn add @jxee/sdk

# pnpm
pnpm add @jxee/sdk

🚀 快速开始

基础示例

import { McpServer, Client, InMemoryTransport } from '@jxee/sdk';
import { z } from 'zod';

// 1. 创建 MCP Server
const server = new McpServer({
  name: 'my-rn-server',
  version: '1.0.0'
});

// 2. 注册一个工具
server.registerTool(
  'calculate',
  {
    title: '计算器',
    description: '执行数学计算',
    inputSchema: {
      expression: z.string().describe('数学表达式,如 "2 + 3"')
    },
    outputSchema: {
      result: z.number()
    }
  },
  async ({ expression }) => {
    const result = eval(expression); // 实际应用中请使用安全的计算方法
    return {
      content: [{ type: 'text', text: `结果: ${result}` }],
      structuredContent: { result }
    };
  }
);

// 3. 创建配对的传输层
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();

// 4. 连接 Server
await server.connect(serverTransport);

// 5. 创建 Client 并连接
const client = new Client({
  name: 'my-rn-client',
  version: '1.0.0'
});

await client.connect(clientTransport);

// 6. 调用工具
const result = await client.callTool({
  name: 'calculate',
  arguments: { expression: '10 * 5' }
});

console.log(result.structuredContent); // { result: 50 }

📚 完整示例

1. 注册多个工具

// 天气查询工具
server.registerTool(
  'get-weather',
  {
    title: '获取天气',
    description: '查询指定城市的天气信息',
    inputSchema: {
      city: z.string().describe('城市名称')
    },
    outputSchema: {
      temperature: z.number(),
      condition: z.string()
    }
  },
  async ({ city }) => {
    // 模拟天气数据
    const weather = {
      temperature: 25,
      condition: '晴朗'
    };

    return {
      content: [
        {
          type: 'text',
          text: `${city}的天气:${weather.condition},温度${weather.temperature}°C`
        }
      ],
      structuredContent: weather
    };
  }
);

// 用户信息工具
server.registerTool(
  'get-user-info',
  {
    title: '获取用户信息',
    description: '根据用户ID获取用户信息',
    inputSchema: {
      userId: z.string()
    },
    outputSchema: {
      name: z.string(),
      email: z.string(),
      age: z.number()
    }
  },
  async ({ userId }) => {
    const user = {
      name: '张三',
      email: 'zhangsan@example.com',
      age: 30
    };

    return {
      content: [
        { type: 'text', text: JSON.stringify(user, null, 2) }
      ],
      structuredContent: user
    };
  }
);

2. 注册资源

import { ResourceTemplate } from '@jxee/sdk';

// 静态资源
server.registerResource(
  'app-config',
  'config://app',
  {
    title: '应用配置',
    description: '应用的全局配置信息',
    mimeType: 'application/json'
  },
  async (uri) => ({
    contents: [{
      uri: uri.href,
      text: JSON.stringify({
        version: '1.0.0',
        apiUrl: 'https://api.example.com',
        features: ['tool1', 'tool2']
      }, null, 2)
    }]
  })
);

// 动态资源(带参数)
server.registerResource(
  'user-profile',
  new ResourceTemplate('user://{userId}/profile', { list: undefined }),
  {
    title: '用户资料',
    description: '获取用户的详细资料'
  },
  async (uri, { userId }) => ({
    contents: [{
      uri: uri.href,
      text: `用户 ${userId} 的资料信息`
    }]
  })
);

3. 注册提示词(Prompts)

import { completable } from '@jxee/sdk';

server.registerPrompt(
  'code-review',
  {
    title: '代码审查',
    description: '对提供的代码进行审查和建议',
    argsSchema: {
      code: z.string().describe('需要审查的代码'),
      language: completable(
        z.enum(['javascript', 'typescript', 'python', 'java']),
        (value) => {
          const langs = ['javascript', 'typescript', 'python', 'java'];
          return langs.filter(lang => lang.startsWith(value));
        }
      )
    }
  },
  ({ code, language }) => ({
    messages: [
      {
        role: 'user',
        content: {
          type: 'text',
          text: `请审查以下 ${language} 代码并提供改进建议:\n\n${code}`
        }
      }
    ]
  })
);

🎨 React Native 集成示例

在 React Native 组件中使用

import React, { useEffect, useState } from 'react';
import { View, Text, Button, ActivityIndicator } from 'react-native';
import { McpServer, Client, InMemoryTransport } from '@jxee/sdk';

function McpDemo() {
  const [client, setClient] = useState<Client | null>(null);
  const [result, setResult] = useState<string>('');
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    initializeMcp();
  }, []);

  const initializeMcp = async () => {
    // 创建并配置 Server
    const server = new McpServer({
      name: 'rn-demo-server',
      version: '1.0.0'
    });

    server.registerTool(
      'greet',
      {
        title: '打招呼',
        description: '向用户打招呼',
        inputSchema: { name: z.string() },
        outputSchema: { greeting: z.string() }
      },
      async ({ name }) => {
        const greeting = `你好,${name}!欢迎使用 MCP SDK for RN`;
        return {
          content: [{ type: 'text', text: greeting }],
          structuredContent: { greeting }
        };
      }
    );

    // 创建传输层
    const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();

    // 连接
    await server.connect(serverTransport);

    const newClient = new Client({
      name: 'rn-demo-client',
      version: '1.0.0'
    });

    await newClient.connect(clientTransport);
    setClient(newClient);
  };

  const handleCallTool = async () => {
    if (!client) return;

    setLoading(true);
    try {
      const response = await client.callTool({
        name: 'greet',
        arguments: { name: '浮浮酱' }
      });

      setResult(response.structuredContent.greeting);
    } catch (error) {
      setResult(`错误: ${error.message}`);
    } finally {
      setLoading(false);
    }
  };

  return (
    <View style={{ padding: 20 }}>
      <Text style={{ fontSize: 18, marginBottom: 20 }}>MCP SDK Demo</Text>

      <Button
        title="调用工具"
        onPress={handleCallTool}
        disabled={!client || loading}
      />

      {loading && <ActivityIndicator style={{ marginTop: 20 }} />}

      {result ? (
        <Text style={{ marginTop: 20, fontSize: 16 }}>
          结果: {result}
        </Text>
      ) : null}
    </View>
  );
}

export default McpDemo;

使用 Context 管理 MCP 实例

import React, { createContext, useContext, useEffect, useState } from 'react';
import { McpServer, Client, InMemoryTransport } from '@jxee/sdk';

interface McpContextType {
  client: Client | null;
  server: McpServer | null;
  isReady: boolean;
}

const McpContext = createContext<McpContextType>({
  client: null,
  server: null,
  isReady: false
});

export const McpProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [client, setClient] = useState<Client | null>(null);
  const [server, setServer] = useState<McpServer | null>(null);
  const [isReady, setIsReady] = useState(false);

  useEffect(() => {
    const setup = async () => {
      // 创建 Server
      const mcpServer = new McpServer({
        name: 'app-server',
        version: '1.0.0'
      });

      // 注册你的工具、资源等...
      // mcpServer.registerTool(...)

      // 创建传输层并连接
      const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
      await mcpServer.connect(serverTransport);

      const mcpClient = new Client({
        name: 'app-client',
        version: '1.0.0'
      });
      await mcpClient.connect(clientTransport);

      setServer(mcpServer);
      setClient(mcpClient);
      setIsReady(true);
    };

    setup();

    return () => {
      client?.close();
      server?.close();
    };
  }, []);

  return (
    <McpContext.Provider value={{ client, server, isReady }}>
      {children}
    </McpContext.Provider>
  );
};

export const useMcp = () => useContext(McpContext);

🔧 API 参考

InMemoryTransport

// 创建配对的传输层
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();

// 启动传输
await clientTransport.start();
await serverTransport.start();

// 关闭传输
await clientTransport.close();
await serverTransport.close();

Client API

// 列出所有工具
const tools = await client.listTools();

// 调用工具
const result = await client.callTool({
  name: 'tool-name',
  arguments: { /* ... */ }
});

// 列出资源
const resources = await client.listResources();

// 读取资源
const resource = await client.readResource({
  uri: 'resource://uri'
});

// 列出提示词
const prompts = await client.listPrompts();

// 获取提示词
const prompt = await client.getPrompt({
  name: 'prompt-name',
  arguments: { /* ... */ }
});

Server API

// 注册工具
server.registerTool(name, config, handler);

// 注册资源
server.registerResource(name, uriOrTemplate, metadata, handler);

// 注册提示词
server.registerPrompt(name, config, handler);

// 获取客户端能力
const capabilities = server.getClientCapabilities();

// 发送通知
await server.sendToolListChanged();
await server.sendResourceListChanged();
await server.sendPromptListChanged();

🎯 为什么选择 inMemory 传输?

在 React Native 环境中,使用 inMemory 传输有以下优势:

  1. 零网络开销 - Client 和 Server 在同一进程,无需 HTTP/WebSocket
  2. 简单可靠 - 没有网络错误、连接断开等问题
  3. 高性能 - 直接内存传递,无序列化/反序列化开销
  4. 易于调试 - 所有通信都在同一进程,方便断点调试
  5. 完全离线 - 不依赖任何网络连接

📖 与原版 SDK 的区别

特性 原版 SDK RN 版本
HTTP 传输 ✅ ❌
stdio 传输 ✅ ❌
SSE 传输 ✅ ❌
WebSocket 传输 ✅ ❌
inMemory 传输 ✅ ✅
核心协议 ✅ ✅
工具系统 ✅ ✅
资源系统 ✅ ✅
提示词系统 ✅ ✅
Node.js 依赖 有 无
RN 兼容 部分 完全

🤝 贡献

欢迎贡献!请查看 CONTRIBUTING.md 了解详情。

📄 许可证

MIT License - 详见 LICENSE 文件

🔗 相关链接


由 jxee 维护