MCPcopy
hub / github.com/coder/mux / transformMCPResult

Function transformMCPResult

src/node/services/mcpResultTransform.ts:64–130  ·  view source on GitHub ↗
(result: unknown)

Source from the content-addressed store, hash-verified

62 * Truncates large images to prevent context overflow.
63 */
64export function transformMCPResult(result: unknown): unknown {
65 if (!result || typeof result !== "object") {
66 return result;
67 }
68
69 const typed = result as MCPCallToolResult;
70
71 // If it's an error or has toolResult, pass through as-is
72 if (typed.isError || typed.toolResult !== undefined) {
73 return result;
74 }
75
76 // If no content array, pass through
77 if (!typed.content || !Array.isArray(typed.content)) {
78 return result;
79 }
80
81 // Check if any content is an image
82 const hasImage = typed.content.some((c) => c.type === "image");
83 if (!hasImage) {
84 return result;
85 }
86
87 // Debug: log what we received from MCP
88 log.debug("[MCP] transformMCPResult input", {
89 contentTypes: typed.content.map((c) => c.type),
90 imageItems: typed.content
91 .filter((c): c is MCPImageContent => c.type === "image")
92 .map((c) => ({ type: c.type, mimeType: c.mimeType, dataLen: c.data?.length })),
93 });
94
95 // Transform to AI SDK content format
96 const transformedContent: AISDKContentPart[] = typed.content.map((item) => {
97 if (item.type === "text") {
98 return { type: "text" as const, text: item.text };
99 }
100 if (item.type === "image") {
101 const imageItem = item;
102 // Check if image data exceeds the limit
103 const dataLength = imageItem.data?.length ?? 0;
104 if (dataLength > MAX_IMAGE_DATA_BYTES) {
105 log.warn("[MCP] Image data too large, omitting from context", {
106 mimeType: imageItem.mimeType,
107 dataLength,
108 maxAllowed: MAX_IMAGE_DATA_BYTES,
109 });
110 return {
111 type: "text" as const,
112 text: `[Image omitted: ${formatBytesSI(dataLength)} exceeds per-image guard of ${formatBytesSI(MAX_IMAGE_DATA_BYTES)}. Reduce resolution or quality and retry.]`,
113 };
114 }
115 // Ensure mediaType is present - default to image/png if missing
116 const mediaType = imageItem.mimeType || "image/png";
117 log.debug("[MCP] Transforming image content", { mimeType: imageItem.mimeType, mediaType });
118 return { type: "media" as const, data: imageItem.data, mediaType };
119 }
120 // For resource type, convert to text representation
121 if (item.type === "resource") {

Callers 2

wrapMCPToolsFunction · 0.90

Calls 2

formatBytesSIFunction · 0.85
debugMethod · 0.80

Tested by

no test coverage detected