different-ai/openwork · error · ExternalMcpDiagnosticError

MCP_CATALOG_BYTE_LIMIT

MCP_CATALOG_BYTE_LIMIT

Error message

MCP_CATALOG_BYTE_LIMIT

What it means

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.

Solutions

  1. Reduce the number of tools exposed by the provider
  2. Shrink each tool's inputSchema/outputSchema (drop redundant fields, flatten oneOfs)
  3. Split the provider into multiple scoped MCP servers and connect only the needed ones
  4. Register the provider with a narrower tool allowlist if the gateway supports scoping

Example fix

// before: server exposes 500 tools with ~20KB schemas each (~10MB total)
// after: expose only the 50 tools the org actually uses (~1MB total)
Defensive patterns

Strategy: validation

Validate before calling

const catalogBytes = new TextEncoder().encode(JSON.stringify({ tools })).byteLength
if (catalogBytes > 8 * 1024 * 1024) throw new Error(`catalog too large: ${catalogBytes} bytes (limit 8MiB)`)

Type guard

function fitsCatalogBudget(serialized: string): boolean {
  return new TextEncoder().encode(serialized).byteLength < 8 * 1024 * 1024
}

Try / catch

try {
  await connectExternalMcp(...)
} catch (err) {
  if (err instanceof Error && err.message.includes("MCP_CATALOG_BYTE_LIMIT")) {
    console.error("Serialized catalog exceeds 8MiB; reduce tool count/schema size")
  } else throw err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/5e45de72c7f88ec8. Report an issue: GitHub.

Appendix: source

Thrown at ee/apps/den-api/src/capability-sources/external-mcp-client.ts:655

    value: input.tool.description,
    field: "description",
    limit: EXTERNAL_MCP_TOOL_DESCRIPTION_LIMIT_BYTES,
    code: "MCP_CATALOG_TOOL_DESCRIPTION_LIMIT",
  })
  validateToolSchema({ diagnostic: input.diagnostic, schema: input.tool.inputSchema })
  if (input.tool.outputSchema !== undefined) {
    validateToolSchema({ diagnostic: input.diagnostic, schema: input.tool.outputSchema })
  }

  const measurement = measureSerializedJson(
    input.tool,
    Math.max(0, input.remainingBytes),
    EXTERNAL_MCP_TOOL_SCHEMA_DEPTH_LIMIT + 4,
  )
  if (!measurement.ok) {
    throw catalogDiagnosticError({
      tracker: input.diagnostic,
      code: "MCP_CATALOG_BYTE_LIMIT",
      operatorAction: `Reduce the complete serialized tool catalog below ${EXTERNAL_MCP_CATALOG_LIMIT_BYTES} bytes.`,
    })
  }
  return measurement.bytes
}

export async function collectExternalMcpToolPages(input: {
  listPage: (cursor: string | undefined, options: RequestOptions) => Promise<ExternalMcpToolPage>
  diagnostic: ExternalMcpDiagnosticTracker
  pageLimit?: number
  itemLimit?: number
  deadline?: ExternalMcpLifecycleDeadline
}): Promise<ExternalMcpToolPage["tools"]> {
  const pageLimit = input.pageLimit ?? EXTERNAL_MCP_TOOL_PAGE_LIMIT
  const itemLimit = input.itemLimit ?? EXTERNAL_MCP_TOOL_ITEM_LIMIT
  const deadline = input.deadline ?? createExternalMcpLifecycleDeadline()
  const tools: ExternalMcpToolPage["tools"] = []
  const seenCursors = new Set<string>()

View on GitHub (pinned to 2b7df46e8a)