diff --git a/apps/web/src/app/api/mcp/[tool]/route.ts b/apps/web/src/app/api/mcp/[tool]/route.ts index d05a643..e169245 100644 --- a/apps/web/src/app/api/mcp/[tool]/route.ts +++ b/apps/web/src/app/api/mcp/[tool]/route.ts @@ -140,7 +140,15 @@ function resolveSourceIp(request: NextRequest) { ); } -async function ensureBuilderAgent(agentId: string) { +async function ensureBuilderAgent( + agentId: string, + requestContext?: { + request_id?: string; + source_ip?: string; + user_agent?: string; + request_actor_headers?: Record; + } +) { const existingAgent = await prisma.agentProfile.findUnique({ where: { agent_id: agentId } }); if (existingAgent) { return existingAgent; @@ -164,9 +172,12 @@ async function ensureBuilderAgent(agentId: string) { action: "EXTERNAL_AGENT_AUTO_WHITELIST", surface: "mcp/claim_task", actorType: "AGENT", - actorId: agentId, + actorId: `agent:${normalizeActorId(agentId, "agent")}`, message: `外部 Agent 首次接案已自動白名單: ${agentId}`, - metadata: { agent_id: agentId }, + metadata: { + ...requestContext, + agent_id: agentId, + }, }); return created; @@ -297,6 +308,9 @@ export async function POST(request: NextRequest, props: { params: Promise<{ tool switch (tool) { case "list_open_tasks": { + if (typeof body === "object" && body !== null && !("skills" in body)) { + (body as Record).skills = []; + } ListOpenTasksRequestSchema.parse(body); const sourceIp = resolveSourceIp(request); const isPublicIp = !isPrivateIp(sourceIp); @@ -393,14 +407,14 @@ export async function POST(request: NextRequest, props: { params: Promise<{ tool const parsed = ClaimTaskRequestSchema.parse(body); // Verify Agent Whitelist - const agent = await ensureBuilderAgent(parsed.agent_id); + const agent = await ensureBuilderAgent(parsed.agent_id, requestContext); if (!agent) { void sendTrafficAlert({ level: "warning", action: "EXTERNAL_CLAIM_TASK_FORBIDDEN", surface: "mcp/claim_task", actorType: "AGENT", - actorId: parsed.agent_id, + actorId: `agent:${normalizeActorId(parsed.agent_id, "agent")}`, taskId: parsed.task_id, message: `外部 Agent 嘗試接案但尚未白名單: ${parsed.agent_id}`, metadata: { @@ -420,7 +434,7 @@ export async function POST(request: NextRequest, props: { params: Promise<{ tool action: "EXTERNAL_CLAIM_TASK_FORBIDDEN", surface: "mcp/claim_task", actorType: "AGENT", - actorId: parsed.agent_id, + actorId: `agent:${normalizeActorId(parsed.agent_id, "agent")}`, taskId: parsed.task_id, message: `external agent 狀態非白名單: ${parsed.agent_id}`, metadata: { @@ -486,7 +500,7 @@ export async function POST(request: NextRequest, props: { params: Promise<{ tool action: "EXTERNAL_CLAIM_TASK_SUCCESS", surface: "mcp/claim_task", actorType: "AGENT", - actorId: parsed.agent_id, + actorId: `agent:${normalizeActorId(parsed.agent_id, "agent")}`, taskId: claim.task_id, message: `Agent 成功接案: ${parsed.task_id}`, metadata: {