First running version

This commit is contained in:
qingjie.du
2026-03-30 17:39:13 +09:00
parent 5ffea3d849
commit bce2a5672c
67 changed files with 16503 additions and 0 deletions

BIN
dev/Flow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

BIN
dev/Platform.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

723
dev/build-detail.md Normal file
View File

@@ -0,0 +1,723 @@
# MCPletA2A Platform - 详细开发计划
> 基于 Platform.png 架构图、Flow.png 参考流程及 MCPlet-spec-v202603-03 编写。
---
## 1. 目标
| 产出 | 路径 |
|------|------|
| 平台实现 | `/Users/qingjie.du/HDD/my-prjs/MCPletA2A/platform_impl/` |
| 参考实现 | `/Users/qingjie.du/HDD/my-prjs/MCPletA2A/reference_impl/` |
**平台实现**MCPlet Agent Profile Host含 Director Agent、A2A 协议层、MCPlet Pool 管理与权限执行、Passkey Web Page、Dashboard、可替换 LLM 适配器。
**参考实现**:「降低餐厅取消率」场景——情報収集・分析 Agent → 企画・Plan Agent店长 Passkey 确认)→ 発信・発注・発令 Agent发邮件驱动对应 MCPlets。
---
## 2. 技术栈
| 层次 | 选型 | 理由 |
|------|------|------|
| 语言 | TypeScript 5.x, Node.js 20+ | 与 reference_impl_restaurant 一致 |
| MCP | `@modelcontextprotocol/sdk` | 规范要求 |
| HTTP | Node.js 原生 `http` | 与现有参考实现一致,轻量 |
| 配置 | YAML + `js-yaml` | 可读性强,企业级友好 |
| 定时任务 | `node-cron` | Director Agent schedule |
| LLM 默认 | `@anthropic-ai/sdk` (claude-sonnet-4-6) | 通过适配器接口可替换任意 LLM |
| 测试 | `jest` + `ts-jest` | 标准 TS 测试方案 |
---
## 3. 完整目录结构
```
/MCPletA2A/
├── platform_impl/
│ ├── src/
│ │ ├── types/
│ │ │ ├── a2a.ts # A2AAgentCard / Envelope / TaskRequest / TaskResponse
│ │ │ ├── mcplet.ts # MCPletMeta / MCPletType / Visibility / PoolName
│ │ │ └── config.ts # PlatformConfig / PoolPolicy / AgentConfig / DirectorAgentConfig
│ │ ├── config/
│ │ │ └── loader.ts # 加载并验证 platform.yaml → PlatformConfig
│ │ ├── discovery/
│ │ │ └── mcplet-discovery.ts # MCP tools/list + 热重载 + 合规校验
│ │ ├── pools/
│ │ │ └── pool-registry.ts # Pool 注册表 + canAgentAccessPool + getToolsForAgent
│ │ ├── llm/
│ │ │ ├── llm-adapter.ts # LLMAdapter 接口定义
│ │ │ └── claude-adapter.ts # Claude 实现(@anthropic-ai/sdk
│ │ ├── agents/
│ │ │ ├── base-agent.ts # BaseAgent 抽象类(含 dispatchMCPlet 权限检查)
│ │ │ └── director-agent.ts # Director Agentcron 触发,防并发)
│ │ ├── a2a/
│ │ │ ├── local-bus.ts # A2A local protocol进程内注册+路由)
│ │ │ └── external-endpoint.ts# A2A 外部 HTTP 端点(鉴权+Pool校验
│ │ ├── passkey/
│ │ │ └── passkey-server.ts # Passkey Web Pagelocalhost 模式,动态端口)
│ │ ├── dashboard/
│ │ │ └── dashboard-server.ts # Dashboard HTTP 服务MCPlet 列表+审计日志)
│ │ ├── host/
│ │ │ └── mcplet-host.ts # MCPlet Host 主类,整合全部模块
│ │ └── index.ts # 程序入口
│ ├── config/
│ │ └── platform.yaml # 平台配置模板
│ ├── public/
│ │ ├── passkey/
│ │ │ └── index.html # Passkey Web Pageminimal, strict CSP
│ │ └── dashboard/
│ │ └── index.html # Dashboard 页面
│ ├── package.json
│ └── tsconfig.json
└── reference_impl/
├── mcplets/
│ ├── media-pool/
│ │ ├── site-access/
│ │ │ └── index.ts # read_site_stats (read, media-pool, model-visible)
│ │ ├── email/
│ │ │ └── index.ts # send_email (action, media-pool, passkey strict)
│ │ └── sns/
│ │ └── index.ts # post_sns (action, media-pool, passkey strict)
│ ├── info-pool/
│ │ ├── web-access/
│ │ │ └── index.ts # fetch_web_content (read, info-pool, model-visible)
│ │ └── api-access/
│ │ └── index.ts # call_external_api (read, info-pool, model-visible)
│ └── internal/
│ ├── crm/
│ │ └── index.ts # query_crm (read, no pool, model-visible)
│ ├── erp/
│ │ └── index.ts # query_erp (read, no pool, model-visible)
│ └── hr/
│ └── index.ts # query_hr (read, no pool, model-visible)
├── agents/
│ ├── info-gathering/
│ │ └── index.ts # 情報収集・分析 Agent (accessiblePools: [info-pool])
│ ├── planning/
│ │ └── index.ts # 企画・Plan Agent (accessiblePools: [])
│ └── dispatch/
│ └── index.ts # 発信・発注・発令 Agent (accessiblePools: [media-pool])
├── mock-services/
│ ├── server.ts # Mock HTTP 服务器(端口 5100挂载所有端点
│ └── data/
│ ├── customers.json # CRM含 cancel_tendency 字段的顾客数据5条
│ ├── inventory.json # ERP各商品库存
│ ├── reservations.json # 明日の予約一覧
│ └── weather.json # 天気予報(固定:明日は雨)
├── config/
│ └── reference.yaml # 参考实现配置场景、schedule、agents、pools、mockServices
├── package.json
└── tsconfig.json
```
---
## 4. 核心类型定义(`src/types/`
### 4.1 `a2a.ts`
```typescript
// Spec Section 18
export interface A2AAgentCard {
agentId: string;
displayName?: string;
description?: string;
requestedPools?: string[];
inputSchema?: object;
outputSchema?: object;
version?: string;
}
export interface A2AMessageEnvelope {
messageId: string; // UUID v4
contextId?: string; // UUID v4, stable across delegated workflow
senderId: string;
recipientId: string;
timestamp?: string; // ISO 8601 UTC
locale?: string; // BCP 47
}
export interface A2ATaskRequest extends A2AMessageEnvelope {
type: 'task_request';
payload: {
parameters: Record<string, unknown>;
history?: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>;
};
}
export interface A2ATaskResponse extends A2AMessageEnvelope {
type: 'task_response';
replyToMessageId: string;
status: 'success' | 'error' | 'timeout' | 'cancelled' | 'partial';
payload?: {
result?: unknown;
error?: { message: string; code?: string };
};
}
```
### 4.2 `mcplet.ts`
```typescript
export type MCPletType = 'read' | 'prepare' | 'action';
export type Visibility = 'model' | 'app';
export interface MCPletMeta {
mcpletType: MCPletType;
pool?: string;
visibility: Visibility[];
mcpletToolResultSchemaUri?: string;
auth?: {
required: 'passkey';
enforcement: 'strict' | 'host-only';
promptMessage?: string;
};
}
// MCPlet 工具结果信封Spec Section 9.1
export interface MCPletToolResult<T = unknown> {
result?: T;
error?: { message: string; code: string };
_meta: {
timestamp: string;
toolId: string;
mcpletType: MCPletType;
visibility: Visibility[];
};
}
```
### 4.3 `config.ts`
```typescript
export interface PoolPolicy {
rateLimitPerMinute?: number;
domainAllowlist?: string[];
}
export interface AgentConfig {
class: string; // Agent 类名,用于注册表查找
accessiblePools: string[];
a2aCard?: Partial<A2AAgentCard>;
}
export interface DirectorAgentConfig {
schedule: string; // cron 表达式
promptTemplate: string;
targetAgentId: string; // 接收指令的 Agent
maxRetries: number;
backoffMs: number;
}
export interface PasskeyConfig {
mode: 'localhost' | 'https';
rpId: string;
fido2ServerUrl?: string;
}
export interface PlatformConfig {
llm: { provider: string; model: string; apiKey?: string };
pools: Record<string, PoolPolicy>;
agents: Record<string, AgentConfig>;
directorAgent?: DirectorAgentConfig;
externalAgents?: Array<{ agentId: string; apiKey: string; accessiblePools: string[] }>;
passkey?: PasskeyConfig;
dashboard?: { port: number };
a2aExternalEndpoint?: { port: number };
}
```
---
## 5. 各模块详细规格
### 5.1 `discovery/mcplet-discovery.ts`
```typescript
class MCPletDiscovery {
constructor(private mcpClient: MCPClient, private poolRegistry: PoolRegistry) {}
async discover(): Promise<ToolDefinition[]>
// 1. 调用 tools/list
// 2. 过滤: 无 _meta.mcpletType → reject
// 3. 过滤: action + visibility含model + 无auth → reject (记录 warn)
// 4. 按 _meta.pool 注册到 poolRegistry
// 5. 返回合规工具列表
subscribeToChanges(): void
// 监听 notifications/tools/list_changed → 重新执行 discover()
// 新增工具重新验证,删除工具从路由表移除
}
```
### 5.2 `pools/pool-registry.ts`
```typescript
class PoolRegistry {
constructor(private poolPolicies: Record<string, PoolPolicy>) {}
registerTool(tool: ToolDefinition, poolName?: string): void
canAgentAccess(agentId: string, poolName: string | undefined, agentPools: string[]): boolean
// - pool-less 工具:任何 Agent 可访问
// - pool 工具agentPools 必须包含该 pool
getToolsForAgent(agentId: string, agentPools: string[]): ToolDefinition[]
// 返回该 Agent 被授权访问的全部工具(用于构建 LLM tool set
checkRateLimit(poolName: string): boolean
}
```
### 5.3 `llm/llm-adapter.ts`
```typescript
export interface Message {
role: 'system' | 'user' | 'assistant';
content: string;
}
export interface ToolDef {
name: string;
description: string;
inputSchema: object;
}
export interface LLMToolCall {
toolName: string;
arguments: Record<string, unknown>;
}
export interface LLMResponse {
text?: string;
toolCalls?: LLMToolCall[];
}
export interface LLMAdapter {
chat(messages: Message[], tools?: ToolDef[]): Promise<LLMResponse>;
}
```
### 5.4 `agents/base-agent.ts`
```typescript
abstract class BaseAgent {
constructor(
public readonly agentId: string,
public readonly accessiblePools: string[],
protected poolRegistry: PoolRegistry,
protected mcpClient: MCPClient,
protected llm: LLMAdapter,
) {}
abstract handle(task: A2ATaskRequest): Promise<A2ATaskResponse>;
protected getAuthorizedTools(): ToolDef[]
// 调用 poolRegistry.getToolsForAgent仅返回 model-visible 工具
protected async invokeMCPlet(toolName: string, args: object): Promise<MCPletToolResult>
// 1. 检查工具是否在授权 Pool 内(否则抛出 403 等价错误)
// 2. 检查 mcpletTypeaction 工具走 Passkey 拦截流程
// 3. 发送 MCP tools/call
// 4. 返回结果
protected buildSuccessResponse(task: A2ATaskRequest, result: unknown): A2ATaskResponse
protected buildErrorResponse(task: A2ATaskRequest, message: string, code?: string): A2ATaskResponse
}
```
### 5.5 `agents/director-agent.ts`
```typescript
class DirectorAgent {
private running = false;
private cronJob: cron.ScheduledTask;
constructor(
private config: DirectorAgentConfig,
private llm: LLMAdapter,
private localBus: A2ALocalBus,
) {}
start(): void
// node-cron.schedule(config.schedule, this.run.bind(this))
private async run(): Promise<void>
// 1. if (this.running) { log "skipping, previous cycle still active"; return; }
// 2. this.running = true
// 3. try:
// a. LLM(config.promptTemplate) → instruction
// b. 解析失败 → log + return不 dispatch
// c. localBus.sendTask(config.targetAgentId, instruction)
// d. 重试逻辑:最多 config.maxRetries 次,间隔 config.backoffMs
// 4. finally: this.running = false
stop(): void
}
```
### 5.6 `a2a/local-bus.ts`
```typescript
class A2ALocalBus {
private agents = new Map<string, BaseAgent>();
register(agent: BaseAgent): void
async sendTask(request: A2ATaskRequest): Promise<A2ATaskResponse>
// 1. 查找 recipientId 对应 Agent未找到 → error response
// 2. 调用 agent.handle(request)
// 3. local bus 消息 MUST NOT 路由到进程外(纯内存调用)
}
```
### 5.7 `a2a/external-endpoint.ts`
```typescript
// HTTP POST /a2a/task
// Headers: Authorization: Bearer <apiKey>
class A2AExternalEndpoint {
constructor(
private config: PlatformConfig,
private localBus: A2ALocalBus,
private poolRegistry: PoolRegistry,
) {}
start(port: number): void
private async handleTask(req, res): Promise<void>
// 1. 验证 Bearer token → 找到对应外部 Agent 配置(否则 401
// 2. 解析 A2ATaskRequestSpec Section 18 schema
// 3. 检查 recipientId 对应 Agent 的工具 ∩ 外部 Agent 授权 Pool否则 403
// 4. 转发到 localBus.sendTask
// 5. 返回 A2ATaskResponse JSON
}
```
### 5.8 `passkey/passkey-server.ts`
```typescript
class PasskeyServer {
private port: number;
async startCeremony(promptMessage: string): Promise<PasskeyAssertion>
// 1. 动态绑定 loopback 端口
// 2. 在系统浏览器打开 http://localhost:{port}/passkey?msg=...
// 3. 等待回调POST /passkey/callback或超时< 60s
// 4. 超时/取消 → 抛出错误Host 返回 MCP Error
// 5. 回调成功 → 返回 assertion关闭页面和端口
stop(): void
}
// public/passkey/index.html:
// - 读取 ?msg query param
// - 调用 navigator.credentials.get()WebAuthn
// - POST assertion 到 /passkey/callback
// - 严格 CSPno external scripts
```
### 5.9 `host/mcplet-host.ts`
```typescript
class MCPletHost {
async start(configPath: string): Promise<void>
// 按序初始化:
// 1. loadConfig(configPath) → PlatformConfig
// 2. new PoolRegistry(config.pools)
// 3. new MCPletDiscovery(mcpClient, poolRegistry) → discover()
// 4. new LLMAdapter(config.llm) // ClaudeAdapter 或其他
// 5. new A2ALocalBus()
// 6. 注册参考实现中的 AgentInfo/Plan/Dispatch
// 7. new DirectorAgent(config.directorAgent, llm, localBus) → start()
// 8. if (config.passkey) → new PasskeyServer(config.passkey)
// 9. if (config.dashboard) → new DashboardServer(...) → start()
// 10. if (config.a2aExternalEndpoint) → new A2AExternalEndpoint(...) → start()
}
```
---
## 6. 参考实现 MCPlet 规格
所有 MCPlet 遵循以下模式(以 `email/index.ts` 为例):
```typescript
import { registerModelTool, registerAppTool } from '../../../platform_impl/src/mcplet-lib';
// send_email: action, media-pool, app-only需 Passkey 授权后由 dispatch agent 调用)
registerAppTool(server, {
name: 'send_email',
title: 'メール送信',
description: 'Send email to specified recipients',
inputSchema: SendEmailSchema,
mcpletType: 'action',
pool: 'media-pool',
visibility: ['app'],
auth: {
required: 'passkey',
enforcement: 'strict',
promptMessage: 'メール送信を承認してください'
},
handler: sendEmailHandler,
});
```
### Mock Service 端点port 5100
| 端点 | 方法 | 说明 | 对应 MCPlet |
| ---- | ---- | ---- | ---------- |
| `/crm/customers?filter=rain_cancel_tendency` | GET | 雨天取消倾向高的顾客列表5条固定数据 | query_crm |
| `/crm/reservations?date=YYYY-MM-DD` | GET | 指定日期预约列表 | query_crm |
| `/erp/inventory?item=dessert` | GET | 甜点库存 | query_erp |
| `/weather/forecast?date=YYYY-MM-DD` | GET | 天气预报(固定返回「明日は雨」) | fetch_web_content |
| `/site/stats` | GET | EPARK 站点访问数据 | read_site_stats |
| `/email/send` | POST | Mock 发信(记录日志,不真实发送) | send_email |
| `/sns/post` | POST | Mock SNS记录日志 | post_sns |
MCPlet handler 通过 `config.mockServiceUrl``http://localhost:5100`调用以上端点替换真实服务只需修改配置handler 代码不变。
---
## 7. 参考实现 MCPlet 规格
| MCPlet | Tool 名 | mcpletType | pool | visibility | auth |
|--------|---------|-----------|------|------------|------|
| サイトアクセス | `read_site_stats` | read | media-pool | [model] | — |
| Email | `send_email` | action | media-pool | [app] | passkey strict |
| SNS | `post_sns` | action | media-pool | [app] | passkey strict |
| 外部Web | `fetch_web_content` | read | info-pool | [model] | — |
| 外部API | `call_external_api` | read | info-pool | [model] | — |
| CRM | `query_crm` | read | (none) | [model] | — |
| ERP | `query_erp` | read | (none) | [model] | — |
| HR | `query_hr` | read | (none) | [model] | — |
---
## 7. 参考实现 Agent 规格
### 7.1 情報収集・分析 Agent
```typescript
class InfoGatheringAgent extends BaseAgent {
// agentId: 'info-gathering-agent'
// accessiblePools: ['info-pool']
// 可用工具: fetch_web_content, call_external_api, query_crm, query_erp, query_hr (pool-less)
async handle(task: A2ATaskRequest): Promise<A2ATaskResponse> {
// 1. 将 task.payload.parameters 拼入 system prompt
// 2. LLM 根据任务决定调用哪些 read MCPlets
// 3. 执行工具调用循环tool_use → invokeMCPlet → 返回结果给 LLM
// 4. LLM 输出分析总结
// 5. 返回 success responseresult: { analysis, rawData }
}
}
```
### 7.2 企画・Plan Agent
```typescript
class PlanningAgent extends BaseAgent {
// agentId: 'planning-agent'
// accessiblePools: [] (只访问 pool-less MCPlets)
// 可用工具: query_crm, query_erp, query_hr
async handle(task: A2ATaskRequest): Promise<A2ATaskResponse> {
// 1. 接收来自 info-gathering 的分析结果
// 2. 查询必要的 CRM/ERP 数据pool-less MCPlets
// 3. LLM 生成 Plan含具体施策、对象顾客列表、邮件文案
// 4. 通过 Passkey Web Page 请求店长审批auth.enforcement: host-only 模式)
// 5. 审批通过 → 返回 successresult: { plan, approvedAt }
// 6. 审批拒绝/超时 → 返回 cancelled
}
}
```
### 7.3 発信・発注・発令 Agent
```typescript
class DispatchAgent extends BaseAgent {
// agentId: 'dispatch-agent'
// accessiblePools: ['media-pool']
// 可用工具: read_site_stats, send_email, post_sns (需 Passkey)
async handle(task: A2ATaskRequest): Promise<A2ATaskResponse> {
// 1. 接收企划方案plan + 顾客列表 + 邮件文案)
// 2. 对 send_email 工具调用:
// a. BaseAgent.invokeMCPlet 拦截 action 工具
// b. 调用 PasskeyServer.startCeremony()
// c. 拿到 assertion → 注入 params._meta.mcplet_auth
// d. 真正执行 MCP tools/call
// 3. 记录发送结果到审计日志
// 4. 返回 successresult: { sent: n, failed: m }
}
}
```
---
## 8. 参考实现配置 `reference.yaml`
```yaml
llm:
provider: claude
model: claude-sonnet-4-6
apiKey: ${ANTHROPIC_API_KEY}
pools:
media-pool:
rateLimitPerMinute: 60
info-pool:
rateLimitPerMinute: 120
agents:
info-gathering-agent:
class: InfoGatheringAgent
accessiblePools: [info-pool]
planning-agent:
class: PlanningAgent
accessiblePools: []
dispatch-agent:
class: DispatchAgent
accessiblePools: [media-pool]
directorAgent:
schedule: "0 7 * * *"
targetAgentId: info-gathering-agent
promptTemplate: |
今日の天気予報と在庫情報、キャンセル傾向の高い予約客情報を収集・分析し、
キャンセル率を下げる施策を立案してください。
maxRetries: 3
backoffMs: 5000
passkey:
mode: localhost
rpId: localhost
dashboard:
port: 4000
a2aExternalEndpoint:
port: 4001
```
---
## 9. 完整流程Flow.png 场景)
```
[cron 07:00]
DirectorAgent.run()
│ LLM(promptTemplate) → "キャンセル率低減タスク開始"
A2ALocalBus.sendTask("info-gathering-agent", task)
InfoGatheringAgent.handle(task)
├─ invokeMCPlet("fetch_web_content", {url: "天気予報"}) ← info-pool
├─ invokeMCPlet("call_external_api", {source: "在庫API"}) ← info-pool
└─ invokeMCPlet("query_crm", {filter: "雨天キャンセル傾向"}) ← pool-less
│ → LLM分析 → { analysis: "明日は雨、在庫あり、高キャンセル客10名" }
A2ALocalBus.sendTask("planning-agent", { analysis })
PlanningAgent.handle(task)
├─ invokeMCPlet("query_erp", {item: "デザート"}) ← pool-less
└─ LLM生成企划: "無料デザートキャンペーン、対象: 10名"
│ PasskeyServer.startCeremony("キャンペーン計画を承認してください")
│ [店长在浏览器中进行 WebAuthn 认证]
│ → { plan, approvedAt }
A2ALocalBus.sendTask("dispatch-agent", { plan })
DispatchAgent.handle(task)
└─ invokeMCPlet("send_email", { to: [...10名...], body: "..." })
├─ 拦截 action 工具
├─ PasskeyServer.startCeremony("メール送信を承認してください")
├─ 注入 params._meta.mcplet_auth
└─ MCP tools/call → Email MCPlet 后端验证 Passkey → 发送邮件
```
---
## 10. 开发阶段与顺序
```
Phase 1: 项目骨架
platform_impl: package.json, tsconfig.json, 目录结构
reference_impl: package.json, tsconfig.json, 目录结构
Phase 2: 类型层src/types/
a2a.ts, mcplet.ts, config.ts
Phase 3: 配置加载src/config/loader.ts
+ platform.yaml 示例
Phase 4: Pool 管理src/pools/pool-registry.ts
+ MCPlet 发现src/discovery/mcplet-discovery.ts
Phase 5: LLM 适配器src/llm/
llm-adapter.ts接口 + claude-adapter.ts实现
Phase 6: Agent 框架src/agents/
base-agent.ts含 invokeMCPlet 权限检查 + action 拦截骨架)
director-agent.tscron + 防并发 + 重试)
Phase 7: A2A 协议src/a2a/
local-bus.ts进程内路由
external-endpoint.tsHTTP + 鉴权 + Pool校验
Phase 8: Host 主入口src/host/mcplet-host.ts + src/index.ts
整合 Phase 2-7平台实现可独立运行
Phase 9: 参考实现 MCPlets
info-pool: fetch_web_content, call_external_api
internal: query_crm, query_erp, query_hr
media-pool: read_site_stats, send_email, post_sns
Phase 10: 参考实现 Agents
InfoGatheringAgent, PlanningAgent, DispatchAgent
+ reference.yaml
Phase 11: Passkey Web Pagesrc/passkey/ + public/passkey/
localhost 模式动态端口WebAuthn ceremony
Phase 12: Dashboardsrc/dashboard/ + public/dashboard/
MCPlet 列表 + action 审计日志展示
Phase 13: 集成测试
完整流程 E2EDirector → 情報収集 → 企画 → 発信
```
---
## 11. 验收标准Checklist
### 平台实现
- [ ] MCPlet 发现:无 `_meta.mcpletType` 工具被拒绝;`action + model-visible + 无auth` 被拒绝
- [ ] Pool 权限Agent 调用授权范围外工具时得到明确错误
- [ ] Director Agentcron 按时触发LLM 解析失败时跳过不 panic同一 Director 不并发执行
- [ ] A2A Local Bus进程内消息路由正确
- [ ] A2A 外部端点:未授权 → 401Pool 范围外 → 403合法请求转发 → 正确响应
- [ ] Passkey Web Pagelocalhost 动态端口assertion 回调后关闭;超时返回 MCP Error
- [ ] Dashboard可查看 MCPlet 列表 + 最近 action 审计日志
### 参考实现
- [ ] 各 MCPlet 正确注册mcpletType / pool / visibility / auth
- [ ] InfoGatheringAgent 只能访问 info-pool + pool-less MCPlets
- [ ] PlanningAgent 只能访问 pool-less MCPlets
- [ ] DispatchAgent 只能访问 media-pool MCPlets
- [ ] 完整场景流程一次性跑通Director → 情報収集 → 企画 → Passkey 审批 → 発信
- [ ] send_email 调用经过 Passkey 拦截 + assertion 注入 + 后端验证

18
dev/build.md Normal file
View File

@@ -0,0 +1,18 @@
实现Platform.png的MCPletA2A平台Agent Profile及Flow.png的参考实现。
## 参考:
1. MCPlet规范/Users/qingjie.du/HDD/my-prjs/MCPlet/about/MCPlet-spec-v202603-03.md
2. 餐厅预订参考实现属于WebUI Profile不是Agent Profile所以只需要参考其可用部分/Users/qingjie.du/HDD/my-prjs/MCPlet/reference_impl_restaurant_reservations
## 注意事项
- 平台实现及参考实现的代码要明确分开且要有清晰的目录结构。平台实现主要负责MCPletA2A平台的搭建和维护而参考实现则是基于该平台的具体应用示例。
- 在实现过程中要严格遵守MCPlet规范确保平台和参考实现的兼容性和可扩展性。
- 参考实现的代码要尽量简洁明了,注释清晰,以便其他开发者能够快速理解和使用。
- 在开发过程中可以参考MCPlet规范中的示例代码和最佳实践但要根据实际需求进行调整和优化。
- 在完成平台和参考实现后,要进行充分的测试,确保其功能的正确性和稳定性。可以编写单元测试和集成测试来验证各个模块的功能。
- 编码及架构选择要考虑企业级应用的需求,如性能、可维护性、安全性等方面。可以采用分层架构、模块化设计等方式来提高系统的可扩展性和可维护性。
- 最后要编写详细的文档说明平台和参考实现的架构设计、使用方法、API接口等以便其他开发者能够快速上手和使用。文档可以包括代码注释、使用指南、API文档等内容。
- 代码的输出路径:
- 平台实现:/Users/qingjie.du/HDD/my-prjs/MCPlet/MCPletA2A/platform_impl
- 参考实现:/Users/qingjie.du/HDD/my-prjs/MCPlet/MCPletA2A/reference_impl