( id: RequestId, serverId: string, rpcParams: unknown )
| 537 | ) |
| 538 | |
| 539 | async function handleToolsList( |
| 540 | id: RequestId, |
| 541 | serverId: string, |
| 542 | rpcParams: unknown |
| 543 | ): Promise<NextResponse> { |
| 544 | try { |
| 545 | const duplicateToolName = await getDuplicateToolName(serverId) |
| 546 | if (duplicateToolName) { |
| 547 | return NextResponse.json( |
| 548 | createError(id, ErrorCode.InvalidRequest, 'MCP server has duplicate tool names', { |
| 549 | code: 'duplicate_tool_name', |
| 550 | toolName: duplicateToolName, |
| 551 | recovery: 'Rename or remove duplicate workflow MCP tools before listing this server', |
| 552 | }), |
| 553 | { status: 409 } |
| 554 | ) |
| 555 | } |
| 556 | |
| 557 | const cursor = getToolsListCursor(rpcParams) |
| 558 | const pageCondition = cursor ? gt(workflowMcpTool.id, cursor) : undefined |
| 559 | const toolSizes = await db |
| 560 | .select({ |
| 561 | id: workflowMcpTool.id, |
| 562 | toolNameBytes: sql<number>`octet_length(${workflowMcpTool.toolName})`, |
| 563 | toolDescriptionBytes: sql<number>`coalesce(octet_length(${workflowMcpTool.toolDescription}), 0)`, |
| 564 | parameterSchemaBytes: sql<number>`octet_length(${workflowMcpTool.parameterSchema}::text)`, |
| 565 | }) |
| 566 | .from(workflowMcpTool) |
| 567 | .where( |
| 568 | and( |
| 569 | eq(workflowMcpTool.serverId, serverId), |
| 570 | isNull(workflowMcpTool.archivedAt), |
| 571 | pageCondition |
| 572 | ) |
| 573 | ) |
| 574 | .orderBy(asc(workflowMcpTool.id)) |
| 575 | .limit(MAX_MCP_TOOLS_LIST_COUNT + 1) |
| 576 | |
| 577 | const pageSizes = toolSizes.slice(0, MAX_MCP_TOOLS_LIST_COUNT) |
| 578 | |
| 579 | let estimatedSchemaBytes = 0 |
| 580 | let estimatedMetadataBytes = 0 |
| 581 | for (const toolSize of pageSizes) { |
| 582 | estimatedSchemaBytes += Number(toolSize.parameterSchemaBytes) || 0 |
| 583 | estimatedMetadataBytes += |
| 584 | (Number(toolSize.toolNameBytes) || 0) + |
| 585 | (Number(toolSize.toolDescriptionBytes) || 0) + |
| 586 | (Number(toolSize.parameterSchemaBytes) || 0) |
| 587 | assertKnownSizeWithinLimit( |
| 588 | estimatedSchemaBytes, |
| 589 | MAX_MCP_TOOLS_LIST_SCHEMA_BYTES, |
| 590 | 'MCP tools/list schemas' |
| 591 | ) |
| 592 | assertKnownSizeWithinLimit( |
| 593 | estimatedMetadataBytes, |
| 594 | MAX_MCP_TOOLS_LIST_RESPONSE_BYTES, |
| 595 | 'MCP tools/list stored metadata' |
| 596 | ) |
no test coverage detected