Skip to Content
卡片 SDKAPI 参考给智能体的工具(MCP)

给智能体的工具(MCP)

卡片可以赋予智能体新的能力。在清单中声明一个工具并在卡片中实现它,所有通过箭头与卡片相连的智能体都会在工具列表中看到它—— 经由应用本来就为智能体运行的 MCP 服务器(Claude Code、Codex、Qwen Code)。不需要任何权限:用户画出的箭头就是同意。

声明

"tools": [ { "name": "run_tests", "title": "Run the tests", "description": "Runs the project's tests in the connected terminal and returns the failing tests with their messages, or 'All tests passed'.", "inputSchema": { "type": "object", "properties": { "filter": { "type": "string", "maxLength": 200, "description": "Only tests whose name contains this" } } }, "timeoutMs": 120000 } ]

智能体看到的名称是 <card name with - → _>_<tool>——名为 test-radar 的卡片对应 test_radar_run_tests—— 参数是你的 inputSchema,外加应用添加的可选参数 card(id 或名称,用于在连了多张副本时指定其中一张)。 描述在交给模型时会加上前缀 [Custom card "<displayName>" by <author>, community code]。如果两个卡片包会产生同一个名称,先安装的那个保留它,后安装的会加上 _2、_3。

应用在安装时会拒绝的名称:与 NeuroSquad 自有工具(canvas_spawn_card、terminal_send_keys、browser_navigate……)相同的对外名称、 任何包含 __ 的名称(为用户安装的 MCP 服务器保留),以及属于内置工具族的卡片 name,例如 telegram、squad、ports 或 mcp (参见保留名)。新增工具或改变工具描述措辞的更新会再次征求用户同意。

描述是写给模型看的:这个工具做什么、何时使用、返回什么。参数要少且有约束(enum、maxLength、minimum……);应用会在你的卡片看到之前校验它们。

实现

import { toolError } from '@neurosquad/card-sdk' card.tools.handle<{ filter?: string }>('run_tests', async ({ filter }, call) => { call.progress('running the tests…') // shown on the arrow const terminal = (await card.agents.list()).find((a) => a.kind === 'shell' && a.connected) if (!terminal) return toolError('Connect a terminal card to the Test radar card first.') const result = await card.terminals.run(terminal.id, `npm test -- ${filter ?? ''}`, { timeoutMs: 110_000 }) if (call.signal.aborted) return // the agent gave up; nothing is sent return result.exitCode === 0 ? 'All tests passed' : result.output })

处理函数会收到校验过的参数和一个 call:

call.说明
callId本次调用的 id。
tool清单中的工具名。
agent发起调用的智能体的 { id, name }。
deadline应用放弃等待的时间戳(毫秒)。
signal一个 AbortSignal,在取消或到达截止时间时中止。
progress(message)工作期间在箭头上显示的一行短文字(≤ 200);限流为每秒 4 次。

你的返回值就是工具结果:

返回智能体得到
字符串这段文本
undefinedOK
其他任意 JSON 值格式化后的 JSON 文本
toolText(text)文本(与返回字符串相同)
toolImage(base64, 'image/png', caption?)一张图片,以及作为文本的说明文字
toolError(message)一个失败结果(isError: true),模型可以读到并作出反应
ToolResultPayload原样:{ content: [{ type: 'text', text } or { type: 'image', data, mimeType }], isError? },1–16 个部分

抛出异常也会把错误返回给智能体,内容为异常消息(并在卡片日志中写一条警告)。结果 ≤ 1 MB。

时间

  • 默认超时 30 秒,或工具的 timeoutMs(最长 120 秒)。到达截止时间时,应用告诉智能体调用超时,并向你的卡片发送 tools.cancel—— call.signal 会中止,你之后返回的任何内容都会被丢弃。
  • 在你的处理函数注册之前到达的调用(例如卡片仍在加载数据时)会等待 handle(),直到截止时间。
  • 调用页面已暂停的卡片会唤醒它(最多 10 秒);如果它所在的工作区没有打开,智能体会被告知去打开包含这张卡片的工作区。
  • 每次调用都会显示在箭头上:箭头标签显示工具名和你的进度文字,并记入箭头日志。

开关工具

await card.tools.setEnabled('run_tests', false) // hidden from agents (e.g. until the user signs in) await card.tools.setEnabled('run_tests', true)

这会作用于你卡片的所有副本。

配合 React

import { useTool } from '@neurosquad/card-sdk/react' export function Scratchpad({ text }: { text: string }) { useTool('read_scratchpad', () => text || '(empty)') // the latest `text` is always used return <pre>{text}</pre> }

工具结果会直接进入智能体的上下文。你返回的任何来自网页、文件或用户的内容都应视为不可信:注明来源、保持简短, 并且绝不要让智能体能调用的工具悄悄做出破坏性操作——先用 card.ui.confirm 询问用户。