完整生命周期
静态声明 vs 动态注册
Finch 的能力注册普遍是两段式:manifest 声明槽位,代码填充行为。
| manifest 静态声明 | activate() 动态注册 | |
|---|---|---|
| 决定 | 按钮/容器是否存在、图标、tooltip | badge 文字、菜单内容、点击行为 |
| 何时读取 | 安装与启动时 | 用户交互时按需调用 |
| 能否隐藏 | 声明即保留槽位 | getBadge() 抛错可隐藏按钮 |
这样设计是因为 Finch 在小工具尚未激活时就要渲染 UI 骨架,静态声明保证界面不闪烁。
注意:getMenu() 返回空数组不会让按钮消失。 可见性由 manifest 决定。
三种能力出口
Capability:小工具之间的协作
小工具不互相 import,通过命名接口协作。提供方和消费方都必须在 manifest 声明:
{
"provides": { "capabilities": ["my.feature"] },
"requires": { "capabilities": ["mcp.client"] }
}
// 提供方
ctx.capabilities.provide('my.feature', {
async listItems() { return []; },
}, { version: '1.2.0' });
// 消费方
if (ctx.capabilities.has('my.feature')) {
const feature = ctx.capabilities.get('my.feature');
const items = await feature.listItems(); // 消费侧一律异步
}
三条注意事项:
- 消费侧所有方法都是异步的,跨进程路由决定的。
- 激活顺序不是依赖契约。目标 capability 可能晚于你激活,需要短轮询等待(见《MCP 集成》)。
- 接口保持小而稳定,演进时用
version区分。