@@ -4,7 +4,12 @@ import { createLogger } from '@sim/logger'
44import { generateId } from '@sim/utils/id'
55import { and , asc , eq , inArray , isNull , ne , sql } from 'drizzle-orm'
66import type { DbOrTx } from '@/lib/db/types'
7- import { MAX_MCP_SERVERS_PER_WORKFLOW , MAX_MCP_TOOLS_PER_SERVER } from '@/lib/mcp/constants'
7+ import {
8+ MAX_MCP_SERVER_PARAMETER_SCHEMAS_BYTES ,
9+ MAX_MCP_SERVER_TOOLS_METADATA_BYTES ,
10+ MAX_MCP_SERVERS_PER_WORKFLOW ,
11+ MAX_MCP_TOOLS_PER_SERVER ,
12+ } from '@/lib/mcp/constants'
813import { mcpPubSub } from '@/lib/mcp/pubsub'
914import {
1015 acquireWorkflowMcpServerLock ,
@@ -13,9 +18,13 @@ import {
1318} from '@/lib/mcp/server-locks'
1419import {
1520 addMcpToolMetadataUsage ,
21+ addMcpToolMetadataUsageRow ,
22+ createMcpToolMetadataUsageRow ,
1623 getMcpServerToolMetadataUsageRows ,
1724 getMcpToolDescriptionForStorage ,
25+ getMcpToolMetadataSizes ,
1826 getMcpToolMetadataUsageFromRows ,
27+ type McpToolMetadataUsage ,
1928 validateMcpServerToolMetadataBudget ,
2029 validateMcpToolMetadataForStorage ,
2130} from '@/lib/mcp/tool-limits'
@@ -181,6 +190,25 @@ async function validateServerToolMetadataBudget(
181190 return validateMcpServerToolMetadataBudget ( usage )
182191}
183192
193+ function validateServerToolMetadataBudgetForUpdate (
194+ currentUsage : McpToolMetadataUsage ,
195+ proposedUsage : McpToolMetadataUsage
196+ ) : string | null {
197+ if (
198+ proposedUsage . schemaBytes > MAX_MCP_SERVER_PARAMETER_SCHEMAS_BYTES &&
199+ proposedUsage . schemaBytes > currentUsage . schemaBytes
200+ ) {
201+ return `MCP server tool schemas exceed maximum size of ${ MAX_MCP_SERVER_PARAMETER_SCHEMAS_BYTES } bytes`
202+ }
203+ if (
204+ proposedUsage . metadataBytes > MAX_MCP_SERVER_TOOLS_METADATA_BYTES &&
205+ proposedUsage . metadataBytes > currentUsage . metadataBytes
206+ ) {
207+ return `MCP server tool metadata exceeds maximum size of ${ MAX_MCP_SERVER_TOOLS_METADATA_BYTES } bytes`
208+ }
209+ return null
210+ }
211+
184212async function prepareWorkflowMcpTool ( params : {
185213 workflowRecord : WorkflowMcpToolWorkflowRecord
186214 toolName ?: string
@@ -863,7 +891,7 @@ export async function performUpdateWorkflowMcpTool(
863891 id : workflowMcpTool . id ,
864892 toolName : workflowMcpTool . toolName ,
865893 toolDescription : workflowMcpTool . toolDescription ,
866- parameterSchema : workflowMcpTool . parameterSchema ,
894+ parameterSchemaBytes : sql < number > `octet_length( ${ workflowMcpTool . parameterSchema } ::text)` ,
867895 } )
868896 . from ( workflowMcpTool )
869897 . where (
@@ -885,13 +913,13 @@ export async function performUpdateWorkflowMcpTool(
885913 ? updateData . toolDescription
886914 : currentTool . toolDescription
887915 const effectiveParameterSchema =
888- updateData . parameterSchema !== undefined
889- ? updateData . parameterSchema
890- : currentTool . parameterSchema
916+ updateData . parameterSchema !== undefined ? updateData . parameterSchema : undefined
891917 const metadataLimitError = validateMcpToolMetadataForStorage ( {
892918 toolName : effectiveToolName ,
893919 toolDescription : effectiveToolDescription ,
894- parameterSchema : effectiveParameterSchema ,
920+ ...( effectiveParameterSchema !== undefined && {
921+ parameterSchema : effectiveParameterSchema ,
922+ } ) ,
895923 } )
896924 if ( metadataLimitError ) {
897925 throw new WorkflowMcpExpectedError ( metadataLimitError , 'validation' )
@@ -919,18 +947,36 @@ export async function performUpdateWorkflowMcpTool(
919947 }
920948 }
921949
922- const budgetError = await validateServerToolMetadataBudget (
923- params . serverId ,
924- [
925- {
926- toolName : effectiveToolName ,
927- toolDescription : effectiveToolDescription ,
928- parameterSchema : effectiveParameterSchema ,
929- } ,
930- ] ,
931- tx ,
932- params . toolId
950+ const baseUsage = getMcpToolMetadataUsageFromRows (
951+ await getMcpServerToolMetadataUsageRows ( tx , params . serverId , params . toolId )
952+ )
953+ const currentUsage = addMcpToolMetadataUsageRow ( baseUsage , {
954+ id : currentTool . id ,
955+ ...getMcpToolMetadataSizes ( {
956+ toolName : currentTool . toolName ,
957+ toolDescription : currentTool . toolDescription ,
958+ } ) ,
959+ parameterSchemaBytes : Number ( currentTool . parameterSchemaBytes ) || 0 ,
960+ } )
961+ const proposedUsage = addMcpToolMetadataUsageRow (
962+ baseUsage ,
963+ effectiveParameterSchema !== undefined
964+ ? createMcpToolMetadataUsageRow ( {
965+ id : currentTool . id ,
966+ toolName : effectiveToolName ,
967+ toolDescription : effectiveToolDescription ,
968+ parameterSchema : effectiveParameterSchema ,
969+ } )
970+ : {
971+ id : currentTool . id ,
972+ ...getMcpToolMetadataSizes ( {
973+ toolName : effectiveToolName ,
974+ toolDescription : effectiveToolDescription ,
975+ } ) ,
976+ parameterSchemaBytes : Number ( currentTool . parameterSchemaBytes ) || 0 ,
977+ }
933978 )
979+ const budgetError = validateServerToolMetadataBudgetForUpdate ( currentUsage , proposedUsage )
934980 if ( budgetError ) {
935981 throw new WorkflowMcpExpectedError ( budgetError , 'validation' )
936982 }
0 commit comments