@ frontmcp/plugin - 结果手
一个FrontMCP插件,用于解答过大而无法发送整个的工具. 超过尺寸阈值的答案被保存在
服务器,模型在它的位置得到一个预览,一个形状和一个手柄. 然后它只读到它所需要的部分与
result_query 工具:路径、范围或页面,以及它想要的字段。 一个手柄只对会话和
调用器是发给的,直到TTL耗尽为止.
安装
npm install @frontmcp/plugin-result-handles @frontmcp/sdk
需要节点.js 24或后. 保留 @frontmcp/sdk 上.
使用量
在应用程序上注册插件,该插件的答案应折叠,或打开 @FrontMcp({ plugins }) 每个应用程序。 数个
应用程序, 服务器列出一个 result_query,并读取每个应用程序副本的手柄:
import ResultHandlesPlugin from '@frontmcp/plugin-result-handles';
import { App } from '@frontmcp/sdk';
@App({
id: 'orders',
name: 'Orders',
tools: [ExportOrdersTool],
plugins: [ResultHandlesPlugin.init({ thresholdBytes: 32 * 1024, preview: { items: 2 } })],
})
export class OrdersApp {}
答复500个订单,然后送达客户:
{
"preview": {
"orders": [
{ "id": 0, "status": "open" },
{ "id": 1, "status": "shipped" }
],
"total": 500
},
"shape": {
"type": "object",
"keys": {
"orders": {
"type": "array",
"length": 500,
"items": {
"type": "object",
"keys": { "id": { "type": "number" }, "status": { "type": "string", "length": 4 } }
}
},
"total": { "type": "number" }
}
},
"handle": "3f1c2a4e-9b7d-4c1e-8f2a-1b2c3d4e5f60"
}
作为 structuredContent 接下来是一行 告诉模型如何阅读其余部分 结果
_meta['frontmcp/result-handle'] 持有 { handle, bytes, ttlSeconds }。 。 。 .
什么折叠
插件运行在 fitAnswer 阶段 tools/call,在答复预算之前output.budget因此,预算
看到折叠的答案。 答案折叠,当所有这些持有:
- 一个客户端叫工具:一个工具叫另一个工具
this.callTool()得到整个答案; - 答案是一个文本内容,或者
structuredContent最多只重复一个文本(作为 SDK) 写作). 图像、 音频、 资源、 多个文本、 旁边的文本structuredContent说着别的东西, 使部件成为部件的错误结果和答案被留下; - 其数据,
structuredContent或文本,大于thresholdBytes作为UTF-8 JSON; - 呼叫有经过核实的会话或经过认证的呼叫者。 一个无国籍的匿名电话被留下,因为没有人 可读取其手柄;
foldPolicy(toolName, answer, context)返回时true。 。 。 .answer这是structuredContent,或文本;一个文本 是 JSON 对象或数组被解析,所以策略和result_query获得值;- 工具的输出计划承认折叠的形式(以下).
当商店无法保存答案(Redis已倒下,如出一辙)时,答案会被完整发送,插件会记录一个警告.
带有输出方案的工具
客户端检查 structuredContent 反对: outputSchema 它被列出,所以一个工具 一个输出计划折叠
只有那个计划承认 { preview, shape, handle }添加 foldedAnswerSchema 作为工会成员:
import { foldedAnswerSchema } from '@frontmcp/plugin-result-handles';
import { Tool, ToolContext, z } from '@frontmcp/sdk';
const reportSchema = z.object({ orders: z.array(orderSchema), total: z.number() });
@Tool({ name: 'export_orders', inputSchema: {}, outputSchema: z.union([reportSchema, foldedAnswerSchema]) })
export class ExportOrdersTool extends ToolContext {
/* … */
}
Zod 计划必须接受无未申报密钥的折叠表; JSON Schema( 一个 OpenAPI 或远程工具) 必须接受 验证它。 一个其计划不承认它被完整发送的工具,而插件记录了一次给工具取名的警告.
result_query
| 参数 | 说明 |
|---|---|
handle | 折叠接答之柄. 要求. |
path | 点路径( E)$.orders[2].note, (中文(简体) ), orders.2.note或 JSON 指针(/orders/2/note) (中文(简体) ). 整个答案如果忽略. |
offset | 列表中,第一个读取的项目;字符串中,第一个字符. |
limit | 要读取多少项(默认为20项)或字符(默认为2000项). |
page | 页面 limit 从1起,取代 offset。 。 。 . |
fields | 只保留对象的这些密钥,或列表中每个对象的这些密钥. |
它会回答的 { path, value, total?, offset?, nextOffset? }数字 : total 是列表或字符串的长度,并且
nextOffset 设置时还有更多要读。 其出错对模型具有补救作用:
| 代码 | 何时 |
|---|---|
RESULT_HANDLE_NOT_FOUND | 手柄已过期,从未发行,或属于另一个会话或呼叫者. |
RESULT_PATH_NOT_FOUND | 路径不是"点"路径或"JSON指针",或者回答中的任何名字. |
RESULT_SLICE_TOO_LARGE | 切片的面积大于 thresholdBytes:读取的项目少,字段少或路径更深. |
INVALID_INPUT | 两者 page 财务报告和审定财务报表 offset 被给出,或者一个参数超出范围. |
谁能读取手柄
一个手柄是一个随机UUID,从未从答案中衍生出来. 电话被确认,除非
联系人是匿名的 不同的会话或不同的呼叫者得到
RESULT_HANDLE_NOT_FOUND,与一个从未存在的手柄, 和数据一样的答案.
店里从不见手柄. 每个答案都是用AES-256-GCM加密的,其加密密钥和其加密密钥都使用 存储密钥从手柄,会话和主题中导出(HKDF-SHA256). 存储器没有读取功能 没有手柄,另一个会话或呼叫者的查询则完全找不到记录,因为一个未知或过期 手柄.
选项
| 选项 | 默认 | 说明 |
|---|---|---|
thresholdBytes | 16384 | 答案大于此折叠, 不 result_query 切片比较大。 至少1024号. |
ttlSeconds | 600 | 折叠的答案可以读取多久. |
preview | { items: 5, chars: 500 } | 第一个 items 每个清单和 chars 用于预览所保存的每个字符串. |
foldPolicy | 每一个答案 | (toolName, answer, { bytes, fullName, request }) => boolean: 答案超过阈值折叠. |
storage | { type: 'auto' } | 将折叠的答案保存到 createStorage() 从 @frontmcp/utils:内存, Redis, Vercel KV, Upstash 或 SQLite. |
namespace | 'result-handles' | 存储中折叠答案的密钥前缀. |
无效的选项扔出 a ResultHandlesConfigurationError 从 init(),命名每个问题.
与 storage: { type: 'auto' } 商店是Redis, Vercel KV 或 Upstash 当它们的环境变量设定时,
和记忆 否则。 内存将答案保存在一个进程中,所以当服务器运行在多个程序上时使用共享存储
实例 :
ResultHandlesPlugin.init({ storage: { type: 'redis', redis: { url: process.env.REDIS_URL } } });
ResultHandlesPlugin.init({ storage: { type: 'sqlite', sqlite: { path: '/var/lib/my-server/results.sqlite' } } });
SQLite 需求 @frontmcp/storage-sqlite。在浏览器构建中(create() 在网页 WebMCP 、 Redis 和 SQLite 中
掷出 BrowserStoreUnavailableError 从 init()名称 storage: { type: 'memory' }: 页面没有 TCP 套接字
没有文件 . { type: 'auto' } 在那里选择记忆.
每个折叠的答案被保存,加密,直到其TTL耗尽. 一个记忆库最多有1000个答案
(单位:千美元)DEFAULT_MEMORY_MAX_ENTRIES并放下最古老的过去 storage.memory.maxEntries 更改,或改为 0
因为没有限制.
文档
相关软件包
@frontmcp/sdk: 此插件延伸的框架和答案 预算output.budget紧接着它运行@frontmcp/utils数字 :createStorage(),用于建立商店
捐款
资料来源: plugins/plugin-result-handles。 。 。 .
欢迎提出问题和拉动请求;见
捐款额。 。 。 .
许可证
阿帕奇2.0 (英语). 见 自由主义。 。 。 .