{"record":{"id":"5e45de72c7f88ec8","repo":"different-ai/openwork","slug":"mcp-catalog-byte-limit-5e45de","errorCode":"MCP_CATALOG_BYTE_LIMIT","errorMessage":"MCP_CATALOG_BYTE_LIMIT","messagePattern":"MCP_CATALOG_BYTE_LIMIT","errorType":"error_code","errorClass":"ExternalMcpDiagnosticError","httpStatus":null,"severity":"error","filePath":"ee/apps/den-api/src/capability-sources/external-mcp-client.ts","lineNumber":655,"sourceCode":"    value: input.tool.description,\n    field: \"description\",\n    limit: EXTERNAL_MCP_TOOL_DESCRIPTION_LIMIT_BYTES,\n    code: \"MCP_CATALOG_TOOL_DESCRIPTION_LIMIT\",\n  })\n  validateToolSchema({ diagnostic: input.diagnostic, schema: input.tool.inputSchema })\n  if (input.tool.outputSchema !== undefined) {\n    validateToolSchema({ diagnostic: input.diagnostic, schema: input.tool.outputSchema })\n  }\n\n  const measurement = measureSerializedJson(\n    input.tool,\n    Math.max(0, input.remainingBytes),\n    EXTERNAL_MCP_TOOL_SCHEMA_DEPTH_LIMIT + 4,\n  )\n  if (!measurement.ok) {\n    throw catalogDiagnosticError({\n      tracker: input.diagnostic,\n      code: \"MCP_CATALOG_BYTE_LIMIT\",\n      operatorAction: `Reduce the complete serialized tool catalog below ${EXTERNAL_MCP_CATALOG_LIMIT_BYTES} bytes.`,\n    })\n  }\n  return measurement.bytes\n}\n\nexport async function collectExternalMcpToolPages(input: {\n  listPage: (cursor: string | undefined, options: RequestOptions) => Promise<ExternalMcpToolPage>\n  diagnostic: ExternalMcpDiagnosticTracker\n  pageLimit?: number\n  itemLimit?: number\n  deadline?: ExternalMcpLifecycleDeadline\n}): Promise<ExternalMcpToolPage[\"tools\"]> {\n  const pageLimit = input.pageLimit ?? EXTERNAL_MCP_TOOL_PAGE_LIMIT\n  const itemLimit = input.itemLimit ?? EXTERNAL_MCP_TOOL_ITEM_LIMIT\n  const deadline = input.deadline ?? createExternalMcpLifecycleDeadline()\n  const tools: ExternalMcpToolPage[\"tools\"] = []\n  const seenCursors = new Set<string>()","sourceCodeStart":637,"sourceCodeEnd":673,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-api/src/capability-sources/external-mcp-client.ts#L637-L673","documentation":"Thrown by measureCatalogTool when measuring an individual tool's serialized JSON would exceed the remaining budget of EXTERNAL_MCP_CATALOG_LIMIT_BYTES (8 MiB). The gateway caps the entire serialized tool catalog per provider so downstream storage and agent contexts stay bounded.","triggerScenarios":"Cumulative catalogBytes plus the current tool's measured size surpasses 8 MiB, so measureSerializedJson is called with remainingBytes <= 0 or too little room and reports failure.","commonSituations":"One provider exposing thousands of very large tools; servers shipping huge JSON Schemas per tool; aggregating gateways that proxy many upstream servers into one catalog.","solutions":["Reduce the number of tools exposed by the provider","Shrink each tool's inputSchema/outputSchema (drop redundant fields, flatten oneOfs)","Split the provider into multiple scoped MCP servers and connect only the needed ones","Register the provider with a narrower tool allowlist if the gateway supports scoping"],"exampleFix":"// before: server exposes 500 tools with ~20KB schemas each (~10MB total)\n// after: expose only the 50 tools the org actually uses (~1MB total)","handlingStrategy":"validation","validationCode":"const catalogBytes = new TextEncoder().encode(JSON.stringify({ tools })).byteLength\nif (catalogBytes > 8 * 1024 * 1024) throw new Error(`catalog too large: ${catalogBytes} bytes (limit 8MiB)`)","typeGuard":"function fitsCatalogBudget(serialized: string): boolean {\n  return new TextEncoder().encode(serialized).byteLength < 8 * 1024 * 1024\n}","tryCatchPattern":"try {\n  await connectExternalMcp(...)\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"MCP_CATALOG_BYTE_LIMIT\")) {\n    console.error(\"Serialized catalog exceeds 8MiB; reduce tool count/schema size\")\n  } else throw err\n}","preventionTips":["Budget ~8MiB total serialized catalog per provider","Keep JSON Schemas small: avoid deeply nested oneOf/anyOf sprawl","Expose only tools your org uses; use scoped servers","Measure serialized catalog size in your server's CI"],"tags":["mcp","catalog-validation","byte-limit"],"backgroundTag":"payload-size-limit-exceeded","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}