Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/mcp/runtime/truncate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@
* characters. OpenAPI-generated MCP servers regularly emit 30+ KB
* descriptions; without truncation a single tool can blow up the system
* prompt and break provider-side caches.
*
* The cap is a hard limit on the returned string: the truncation marker is
* reserved inside {@link MAX_MCP_TOOL_DESCRIPTION_LENGTH}, not appended past it.
*/

export const MAX_MCP_TOOL_DESCRIPTION_LENGTH = 2048;

const TRUNCATION_MARKER = "… [truncated]";

export function truncateMcpToolDescription(value: string): string {
if (value.length <= MAX_MCP_TOOL_DESCRIPTION_LENGTH) return value;
return value.slice(0, MAX_MCP_TOOL_DESCRIPTION_LENGTH) + "… [truncated]";
const headLength = MAX_MCP_TOOL_DESCRIPTION_LENGTH - TRUNCATION_MARKER.length;
return value.slice(0, headLength) + TRUNCATION_MARKER;
}
32 changes: 32 additions & 0 deletions tests/mcp/truncate.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import assert from "node:assert/strict";
import test from "node:test";

import {
MAX_MCP_TOOL_DESCRIPTION_LENGTH,
truncateMcpToolDescription,
} from "../../src/mcp/runtime/truncate.js";

test("truncateMcpToolDescription leaves descriptions at the limit unchanged", () => {
const atLimit = "x".repeat(MAX_MCP_TOOL_DESCRIPTION_LENGTH);
assert.equal(truncateMcpToolDescription(atLimit), atLimit);
});

test("truncateMcpToolDescription keeps one-over-limit output within the cap", () => {
const overLimit = "x".repeat(MAX_MCP_TOOL_DESCRIPTION_LENGTH + 1);
const result = truncateMcpToolDescription(overLimit);

assert.ok(
result.length <= MAX_MCP_TOOL_DESCRIPTION_LENGTH,
`expected <= ${MAX_MCP_TOOL_DESCRIPTION_LENGTH}, got ${result.length}`,
);
assert.equal(result.length, MAX_MCP_TOOL_DESCRIPTION_LENGTH);
assert.ok(result.endsWith("… [truncated]"));
});

test("truncateMcpToolDescription clamps very large descriptions to the limit", () => {
const huge = "x".repeat(30_000);
const result = truncateMcpToolDescription(huge);

assert.equal(result.length, MAX_MCP_TOOL_DESCRIPTION_LENGTH);
assert.ok(result.endsWith("… [truncated]"));
});