使用说明
🧠 mcp-js(可译为:“大脑(或思维)mcp-js”,但具体含义需根据上下文确定,因为“mcp-js”本身是一个技术或项目名称,没有直接的中文对应)
一个轻量级的、浏览器原生的运行时环境,用于处理大型语言模型(LLM)工具调用,具备完整功能 模型上下文协议(MCP) 符合JSON-RPC 2.0标准。
✨ 特点
- 🌐(表示“互联网”或“世界”的符号) 浏览器原生的 - 完全在浏览器中运行,无需Node.js
- 🔍(放大镜图标,常用于表示搜索、查看细节等含义) 智能解析 - 从文本、JSON或流式响应中提取工具调用
- ✅ JSON Schema 验证 - 使用AJV内置参数验证
- ⚡(闪电符号,常用于表示速度、能量或快速充电等概念) 异步执行 - 支持顺序执行和并行执行
- 📝 事件系统 - 监听执行生命周期事件
- 🛠️(扳手或工具的象征,无直接对应中文翻译,可理解为“工具”或“修理/维修”) 框架无关 - 兼容React、Vue、原生JavaScript或任何框架
- 🎯(瞄准靶心) TypeScript 准备就绪 - 包含完整的类型定义
- 📊(表格/数据图表) 内置日志记录 - 全面的调试和错误日志记录
- 🌐 表示“地球,互联网,全球网络”的意思,常用来象征互联网或全球连接。 MCP协议 - 标准MCP客户端完全符合JSON-RPC 2.0规范
- 📡(卫星天线或无线电信标) 与传输方式无关 - WebSocket、HTTP 或任何传输层
- 🔧(扳手) 双API - 直接使用或通过MCP协议消息使用
🤔 为什么要在浏览器中使用MCP?
传统的AI交互需要 服务器往返(或服务器来回) 对于每一个操作——大型语言模型(LLM)与你的后端进行交互,后端随后更新前端。这会带来延迟、增加复杂性,并限制人工智能代理所能执行的操作。
mcp-js 改变了一切 通过将模型上下文协议直接引入浏览器:
🎯(目标/靶心) 直接用户界面操作
- 无需服务器 - 大语言模型(LLMs)可以直接操控您应用程序的状态、文档对象模型(DOM)和用户界面(UI)组件
- 实时互动 - 语音代理可以即时更新文档、移动元素、更改样式
- 零延迟 - UI操作无需网络往返
🎮 表示游戏(Game)的符号 革命性的用例/应用场景
📝 文档编辑: “嘿,AI,把标题放大点,并在这里加个项目符号。”
mcp.register('update_document', ({elementId, changes}) => {
document.getElementById(elementId).style.fontSize = changes.fontSize;
// Direct DOM manipulation - no server required!
});
🎨 可视化构建器: “把这个框向右移动,并连接到另一个元素上。”
mcp.register('move_flowchart_node', ({nodeId, x, y}) => {
const node = flowchart.getNode(nodeId);
node.position = { x, y };
flowchart.render(); // Instant visual feedback
});
🎪 互动体验: “将主题更改为暗模式,并突出显示该部分”
mcp.register('update_ui_theme', ({theme, highlightSelector}) => {
document.body.className = theme;
document.querySelector(highlightSelector).classList.add('highlight');
});
🚀 结果
- 无缝AI代理 那种感觉就像原生于您的应用一样
- 语音驱动的界面 用于复杂的视觉任务
- 基于人工智能的创意工具 实时响应
- 无障碍技术的突破 - 对任何用户界面元素进行语音控制
🚀 快速入门
安装
npm install @azmai/mcp-js
基本用法
import mcp from '@azmai/mcp-js';
// Enable debug logging
mcp.debug = true;
// Register a tool
mcp.register('add_numbers', ({x, y}) => x + y, {
schema: {
type: 'object',
properties: {
x: { type: 'number' },
y: { type: 'number' }
},
required: ['x', 'y']
},
description: 'Add two numbers together'
});
// Parse LLM response
const llmResponse = '{"tool_call":{"tool":"add_numbers","args":{"x":5,"y":10}}}';
const toolCalls = mcp.parse(llmResponse);
// Execute tool calls
const results = await mcp.execute(toolCalls);
console.log(results);
// → [{ tool: 'add_numbers', result: 15, metadata: {...} }]
🌐 MCP协议支持
mcp-js 现在实现了完整的(功能/特性) 模型上下文协议(MCP) 规范符合JSON-RPC 2.0标准,允许标准的MCP客户端(如Claude)与您的工具进行通信。
快速MCP示例
import mcp from '@azmai/mcp-js';
// Register tools normally
mcp.register('calculate', ({op, a, b}) => {
return op === 'add' ? a + b : a * b;
}, {
schema: { /* JSON Schema */ },
description: 'Basic calculator'
});
// Handle MCP messages
const response = await mcp.handleMCPMessage({
jsonrpc: '2.0',
method: 'tools/call',
id: '1',
params: { name: 'calculate', arguments: { op: 'add', a: 5, b: 3 } }
});
// → { jsonrpc: '2.0', id: '1', result: { output: 8, metadata: {...} } }
WebSocket 集成
// Browser WebSocket client
const ws = new WebSocket('ws://localhost:8080');
ws.onopen = async () => {
// Initialize MCP session
ws.send(JSON.stringify({
jsonrpc: '2.0',
method: 'initialize',
id: '1',
params: { clientInfo: { name: 'my-client', version: '1.0.0' } }
}));
};
ws.onmessage = (event) => {
const response = JSON.parse(event.data);
console.log('MCP Response:', response);
};
支持的MCP方法
| 方法 | 描述 | 状态 |
|---|---|---|
initialize |
初始化MCP会话 | ✅ |
tools/list |
列出可用工具 | ✅ |
tools/call |
执行工具 | ✅ |
shutdown |
优雅关闭 | ✅ |
exit |
终止连接 | ✅ |
📚 API参考
核心方法
mcp.register(name, fn, options)
注册一个工具函数,可选地进行模式验证。
参数:
name(字符串) - 唯一工具名称fn(功能) - 要执行的功能options(对象) - 配置选项schema(object) - 用于参数验证的JSON Schemadescription(字符串) - 人类可读的描述
返回值: boolean - 成功状态
mcp.register('calculate_area', ({width, height}) => width * height, {
schema: {
type: 'object',
properties: {
width: { type: 'number', minimum: 0 },
height: { type: 'number', minimum: 0 }
},
required: ['width', 'height']
},
description: 'Calculate rectangle area'
});
mcp.parse(llmResponse)
解析大型语言模型(LLM)的响应并提取工具调用。
参数:
llmResponse(string|object) - 需要解析的LLM响应
返回值: Array|null - 工具调用数组或空值
// Supports various formats
const calls1 = mcp.parse('{"tool_call":{"tool":"add","args":{"x":1,"y":2}}}');
const calls2 = mcp.parse({ tool_call: { tool: 'add', args: { x: 1, y: 2 } } });
const calls3 = mcp.parse('Use the calculator: {"tool_call":{"tool":"add","args":{"x":5,"y":3}}}');
mcp.execute(toolCalls, options)
执行工具调用时进行验证和错误处理。
参数:
toolCalls(数组) - 要执行的工具调用数组options(对象) - 执行选项parallel(boolean) - 并行执行(默认:false)continueOnError(boolean) - 在错误时继续(默认:true)maxConcurrency(数字) - 最大并行执行数(默认:5)
返回值: Promise<Array> - 结果数组
const results = await mcp.execute(toolCalls, {
parallel: true,
continueOnError: false,
maxConcurrency: 3
});
实用方法
mcp.executeSingle(name, args)
直接通过名称执行单个工具。
const result = await mcp.executeSingle('add_numbers', { x: 10, y: 20 });
console.log(result); // → 30
mcp.listTools()
获取所有已注册工具的信息。
const tools = mcp.listTools();
console.log(tools);
// → [{ name: 'add_numbers', description: '...', schema: {...}, metadata: {...} }]
mcp.describeTools()
为大型语言模型(LLM)上下文生成可读性强的工具描述。
const descriptions = mcp.describeTools();
console.log(descriptions);
// → **add_numbers**: Add two numbers together
// Parameters: x, y
// Required: x, y
mcp.parseAndExecute(llmResponse, options)
一步完成解析和执行。
const results = await mcp.parseAndExecute(llmResponse, { parallel: true });
配置
mcp.debug
启用/禁用调试日志记录。
mcp.debug = true; // Enable verbose logging
mcp.debug = false; // Disable debug logs
mcp.setStrict(enabled)
启用/禁用严格模式进行验证。
mcp.setStrict(true); // Throw errors on validation failures
mcp.setStrict(false); // Log errors but continue execution
活动
监听执行生命周期事件:
mcp.on('call', (data) => {
console.log(`Executing: ${data.tool}`, data.args);
});
mcp.on('result', (data) => {
console.log(`Success: ${data.tool} (${data.duration}ms)`, data.result);
});
mcp.on('error', (data) => {
console.log(`Error: ${data.tool} - ${data.error}`);
});
mcp.on('tool_registered', (data) => {
console.log(`Registered: ${data.name}`);
});
可用事件:
call- 工具执行开始result- 工具执行成功完成error- 工具执行失败tool_registered- 新工具已注册tool_unregistered- 工具已移除registry_cleared- 所有工具已清点完毕
MCP协议方法
mcp.handleMCPMessage(message)
根据MCP规范处理传入的JSON-RPC 2.0消息。
const response = await mcp.handleMCPMessage({
jsonrpc: '2.0',
method: 'tools/list',
id: '1'
});
mcp.setTransport(sendFn, receiveFn)
为MCP通信配置传输层。
mcp.setTransport(
(message) => websocket.send(JSON.stringify(message)),
(message) => console.log('Received:', message)
);
mcp.getMCPStatus()
获取MCP服务器的状态和功能。
const status = mcp.getMCPStatus();
// → { initialized: true, capabilities: {...}, toolCount: 5, ... }
流解析器
处理部分/流式响应:
const parser = mcp.createStreamingParser();
// Process chunks as they arrive
const chunk1 = '{"tool_call":{"tool":"add"';
const chunk2 = ',"args":{"x":1,"y":2}}}';
const calls1 = parser.addChunk(chunk1); // → null (incomplete)
const calls2 = parser.addChunk(chunk2); // → [{ tool: 'add', args: {x:1, y:2} }]
// Get all found calls
const allCalls = parser.getAllCalls();
统计
获取执行统计信息:
const stats = mcp.getStats();
console.log(stats);
// → {
// toolCount: 5,
// totalCalls: 42,
// totalErrors: 3,
// successRate: 92.86,
// tools: [...]
// }
🎯 使用示例
React 集成
import { useState, useEffect } from 'react';
import mcp from '@azmai/mcp-js';
function ToolExecutor() {
const [result, setResult] = useState(null);
useEffect(() => {
// Register tools on component mount
mcp.register('greet', ({name}) => `Hello, ${name}!`, {
schema: {
type: 'object',
properties: { name: { type: 'string' } },
required: ['name']
}
});
// Listen to events
const handleResult = (data) => setResult(data);
mcp.on('result', handleResult);
return () => mcp.off('result', handleResult);
}, []);
const executeTool = async () => {
const calls = mcp.parse('{"tool_call":{"tool":"greet","args":{"name":"World"}}}');
await mcp.execute(calls);
};
return (
<div>
<button onClick={executeTool}>Execute Tool</button>
{result && <div>Result: {JSON.stringify(result)}</div>}
</div>
);
}
Vue 集成
<template>
<div>
<button @click="executeTool">Execute Tool</button>
<div v-if="result">Result: {{ result }}</div>
</div>
</template>
<script>
import mcp from '@azmai/mcp-js';
export default {
data() {
return { result: null };
},
mounted() {
mcp.register('timestamp', () => new Date().toISOString(), {
description: 'Get current timestamp'
});
mcp.on('result', (data) => {
this.result = data.result;
});
},
methods: {
async executeTool() {
await mcp.executeSingle('timestamp');
}
}
};
</script>
高级工具注册
// Async tool with complex validation
mcp.register('fetch_data', async ({url, options = {}}) => {
const response = await fetch(url, options);
return response.json();
}, {
schema: {
type: 'object',
properties: {
url: {
type: 'string',
format: 'uri',
description: 'URL to fetch'
},
options: {
type: 'object',
properties: {
method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'DELETE'] },
headers: { type: 'object' }
},
default: {}
}
},
required: ['url']
},
description: 'Fetch data from a URL'
});
// Tool with error handling
mcp.register('safe_divide', ({x, y}) => {
if (y === 0) throw new Error('Division by zero');
return x / y;
}, {
schema: {
type: 'object',
properties: {
x: { type: 'number' },
y: { type: 'number', not: { const: 0 } }
},
required: ['x', 'y']
},
description: 'Safely divide two numbers'
});
🔧 高级功能
自定义验证
import { schemaValidator } from '@azmai/mcp-js';
// Add custom format validator
schemaValidator.ajv.addFormat('email', /^[^@]+@[^@]+\.[^@]+$/);
mcp.register('send_email', ({to, subject, body}) => {
// Send email logic
}, {
schema: {
type: 'object',
properties: {
to: { type: 'string', format: 'email' },
subject: { type: 'string' },
body: { type: 'string' }
},
required: ['to', 'subject', 'body']
}
});
中间件模式
// Create custom execution wrapper
const originalExecute = mcp.execute.bind(mcp);
mcp.execute = async function(toolCalls, options = {}) {
console.log('Pre-execution hook');
try {
const results = await originalExecute(toolCalls, options);
console.log('Post-execution hook');
return results;
} catch (error) {
console.log('Error hook:', error);
throw error;
}
};
🧪 测试
// Mock tools for testing
mcp.register('mock_tool', (args) => ({ mocked: true, args }), {
schema: { type: 'object' }
});
// Test parsing
const testResponse = '{"tool_call":{"tool":"mock_tool","args":{"test":true}}}';
const calls = mcp.parse(testResponse);
assert(calls.length === 1);
assert(calls[0].tool === 'mock_tool');
// Test execution
const results = await mcp.execute(calls);
assert(results[0].result.mocked === true);
🎪 试演/演示
开放 examples/demo.html 在您的浏览器中查看所有功能的交互式演示。
🚀 MCP 集成示例
Node.js WebSocket 服务器
import { WebSocketServer } from 'ws';
import mcp from '@azmai/mcp-js';
// Register your tools
mcp.register('greet', ({name}) => `Hello, ${name}!`, {
schema: {
type: 'object',
properties: { name: { type: 'string' } },
required: ['name']
}
});
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', (ws) => {
console.log('MCP client connected');
mcp.setTransport((message) => ws.send(JSON.stringify(message)));
ws.on('message', async (data) => {
const message = JSON.parse(data.toString());
const response = await mcp.handleMCPMessage(message);
ws.send(JSON.stringify(response));
});
});
Express HTTP 服务器
import express from 'express';
import mcp from '@azmai/mcp-js';
const app = express();
app.use(express.json());
app.post('/mcp', async (req, res) => {
const response = await mcp.handleMCPMessage(req.body);
res.json(response);
});
app.listen(3000);
浏览器WebSocket客户端
class MCPClient {
constructor(url) {
this.ws = new WebSocket(url);
this.requestId = 1;
this.pending = new Map();
this.ws.onmessage = (event) => {
const response = JSON.parse(event.data);
const resolve = this.pending.get(response.id);
if (resolve) {
this.pending.delete(response.id);
resolve(response);
}
};
}
async call(method, params = {}) {
const id = String(this.requestId++);
return new Promise((resolve) => {
this.pending.set(id, resolve);
this.ws.send(JSON.stringify({
jsonrpc: '2.0',
method,
params,
id
}));
});
}
async initialize() {
return this.call('initialize', {
clientInfo: { name: 'browser-client', version: '1.0.0' }
});
}
async listTools() {
return this.call('tools/list');
}
async callTool(name, args) {
return this.call('tools/call', { name, arguments: args });
}
}
// Usage
const client = new MCPClient('ws://localhost:8080');
await client.initialize();
const tools = await client.listTools();
const result = await client.callTool('greet', { name: 'World' });
🤝 贡献(或:参与贡献)
- 为仓库创建分支(或“克隆仓库”)
- 创建你的特性分支(
git checkout -b feature/amazing-feature) - 提交您的更改(
git commit -m 'Add amazing feature') - 推送到分支(
git push origin feature/amazing-feature) - 提交一个拉取请求
📄 许可证
这个项目遵循MIT许可证授权——详见 许可证 文件中有详细信息。
🔗 链接
🙏 致谢
- AJV 用于JSON Schema验证
- 寻求大型语言模型(LLM)社区的灵感和反馈
以❤️之心打造,迎接AI应用以浏览器为先的未来。
