different-ai/openwork · error · ExternalMcpDiagnosticError

MCP_CATALOG_TOOL_TITLE_LIMIT

MCP_CATALOG_TOOL_TITLE_LIMIT

Error message

MCP_CATALOG_TOOL_TITLE_LIMIT

What it means

Thrown by measureCatalogTool in external-mcp-client.ts when an external MCP server advertises a tool whose title exceeds EXTERNAL_MCP_TOOL_TITLE_LIMIT_BYTES (4 KiB of UTF-8). The gateway enforces bounded catalog fields so a single malicious or misconfigured server cannot blow up the serialized catalog or UI rendering.

Source

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

function measureCatalogTool(input: {
  diagnostic: ExternalMcpDiagnosticTracker
  tool: ExternalMcpToolPage["tools"][number]
  remainingBytes: number
}): number {
  validateToolCatalogField({
    diagnostic: input.diagnostic,
    value: input.tool.name,
    field: "name",
    limit: EXTERNAL_MCP_TOOL_NAME_LIMIT_BYTES,
    code: "MCP_CATALOG_TOOL_NAME_LIMIT",
  })
  validateToolCatalogField({
    diagnostic: input.diagnostic,
    value: input.tool.title,
    field: "title",
    limit: EXTERNAL_MCP_TOOL_TITLE_LIMIT_BYTES,
    code: "MCP_CATALOG_TOOL_TITLE_LIMIT",
  })
  validateToolCatalogField({
    diagnostic: input.diagnostic,
    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,
  )

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Shorten the offending tool's `title` on the MCP server to under 4096 UTF-8 bytes
  2. If you operate the server, truncate or rewrite titles server-side before returning tools/list
  3. Use a scoped/narrowed MCP server that only exposes the needed tools
  4. Check which tool failed via the diagnostic tracker output and fix it at the provider

Example fix

// before (provider server config)
{ name: "search", title: `${entireDocumentationText}` }
// after
{ name: "search", title: "Documentation Search" }
Defensive patterns

Strategy: validation

Validate before calling

function validateToolTitle(title: string): boolean {
  return new TextEncoder().encode(title).byteLength <= 4096
}
if (!validateToolTitle(tool.title)) throw new Error("tool title exceeds 4096 UTF-8 bytes")

Type guard

function hasSafeTitle(tool: { title?: string }): boolean {
  return typeof tool.title !== "string" || new TextEncoder().encode(tool.title).byteLength <= 4096
}

Try / catch

try {
  await connectExternalMcp(...)
} catch (err) {
  if (err instanceof Error && err.message.includes("MCP_CATALOG_TOOL_TITLE_LIMIT")) {
    console.error("Provider tool title too large; fix provider server titles (<4KB)")
  } else throw err
}

Prevention

When it happens

Trigger: A tools/list response contains a tool whose `title` field serializes to more than 4096 UTF-8 bytes; validation runs during catalog discovery (collectExternalMcpToolPages -> measureCatalogTool).

Common situations: Providers auto-generating titles from long prompts or docs; misconfigured servers embedding template text into titles; servers reflecting an entire help page as the title; multilingual titles that inflate UTF-8 byte counts.

Related errors


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