Skip to content

Bug: MCP Resource Content Lost - Only the First Text Element Returned #74

@dmurat

Description

@dmurat

Bug: MCP Resource Content Lost - Only the First Text Element Returned

Summary

The callTool() method in src/mcp/client-pool.ts only extracts content from the first element of the MCP response content array and only handles type: "text".
This causes data loss when MCP servers return responses with multiple content items, particularly when the actual data is in a type: "resource" element.

According to the Model Context Protocol specification, MCP servers can return multiple content items of different types in a single CallToolResult. The current implementation violates
this spec by ignoring all content items except content[0] and by not handling the resource content type.

Environment

  • Repository: code-executor-MCP
  • Affected File: src/mcp/client-pool.ts (lines ~460-470)
  • Method: callTool()
  • MCP Version: 2025-06-18 specification

Steps to Reproduce

  1. Set up code-executor-MCP with the GitHub MCP server
  2. Execute a tool call to mcp__github__get_file_contents:
const result = await callMCPTool('mcp__github__get_file_contents', {
  owner: 'croz-ltd',
  repo: 'nrich',
  path: 'README.md'
});

console.log(result);
  1. Observe the returned value

Expected Behavior

Should return the actual file content from the README.md file:

[![Build](https://github.com/croz-ltd/nrich/actions/workflows/build.yml/badge.svg?branch=master)]...

# nrich

Nrich is a Java library developed at CROZ whose purpose is to make development of applications...

Actual Behavior

Returns only the status message:

successfully downloaded text file (SHA: fecd3ed044af12a5a51357da56c4f37642a5df0f)

The actual file content is completely lost.

Root Cause Analysis

What GitHub MCP Server Returns (from Docker logs)

The GitHub MCP server correctly follows the MCP specification and returns:

{
  "id": 9,
  "jsonrpc": "2.0",
  "result": {
    "content": [
      {
        "type": "text",
        "text": "successfully downloaded text file (SHA: fecd3ed044af12a5a51357da56c4f37642a5df0f)"
      },
      {
        "type": "resource",
        "resource": {
          "mimeType": "text/plain; charset=utf-8",
          "text": "[![Build](https://github.com/croz-ltd/nrich/...",
          "uri": "repo://croz-ltd/nrich/contents/README.md"
        }
      }
    ],
    "isError": false
  }
}

Current Buggy Code (src/mcp/client-pool.ts)

// Extract result from content
const content = result.content as Array<{ type: string; text?: string }> | undefined;
if (content && content.length > 0) {
  const firstContent = content[0];  // ← PROBLEM 1: Only checks first item
  if (firstContent && firstContent.type === 'text' && firstContent.text) {
    return firstContent.text;  // ← PROBLEM 2: Returns status message only
  }
}

return result;

Three Problems

  1. Only examines content[0]: Ignores all subsequent content items in the array
  2. Only handles type: "text": Doesn't recognize type: "resource" (or image, audio, etc.)
  3. Incomplete type definition: Type assertion doesn't include the resource property structure

Data Flow Visualization

GitHub MCP Server Response:
├─ content[0]: { type: "text", text: "successfully downloaded..." }
└─ content[1]: { type: "resource", resource: { text: "ACTUAL FILE CONTENT" } }
                 ↓
        code-executor-MCP callTool()
                 ↓
        Checks only content[0]
                 ↓
        Finds type="text", returns "successfully downloaded..."
                 ↓
        ❌ content[1] completely ignored
                 ↓
        User receives: "successfully downloaded..."
        Lost forever: "# nrich\n\nNrich is a Java library..."

Proposed Fix

Solution

Replace the extraction logic to handle all MCP content types per the specification:

// Extract result from content
const content = result.content as Array<{
  type: string;
  text?: string;
  resource?: {
    text?: string;
    blob?: string;
    uri?: string;
    mimeType?: string;
  };
  data?: string;  // For image/audio content
  mimeType?: string;
}> | undefined;

if (content && content.length > 0) {
  // Priority 1: Look for resource content (actual data)
  for (const item of content) {
    if (item.type === 'resource' && item.resource) {
      // Return the actual content from the resource
      if (item.resource.text) {
        return item.resource.text;
      }
      if (item.resource.blob) {
        return item.resource.blob;
      }
      // Return entire resource object if it has other properties
      return item.resource;
    }
  }

  // Priority 2: Look for image/audio data
  for (const item of content) {
    if ((item.type === 'image' || item.type === 'audio') && item.data) {
      return { type: item.type, data: item.data, mimeType: item.mimeType };
    }
  }

  // Priority 3: Fall back to text content
  for (const item of content) {
    if (item.type === 'text' && item.text) {
      return item.text;
    }
  }
}

return result;

Impact

Severity: High

This bug affects all MCP servers that follow the standard pattern of returning:

  • Status/metadata in text content items
  • Actual data in resource content items

Affected MCP Servers (Examples)

  1. GitHub MCP - File contents lost

    • get_file_contents - Returns status only, file content lost
  2. Filesystem MCP - File data lost

    • read_file - Returns "successfully read file", actual content lost
  3. Database MCP - Query results lost

    • execute_query - Returns "query executed", result rows lost
  4. Web Scraper MCP - Scraped content lost

    • fetch_page - Returns "page fetched", HTML content lost

User Impact

Users calling MCP tools through code-executor receive only status messages and never see the actual data, making many MCP integrations non-functional.

Test Case

Input

// MCP Server Response (standard compliant)
{
  content: [
    {
      type: "text",
      text: "successfully downloaded text file (SHA: abc123)"
    },
    {
      type: "resource",
      resource: {
        uri: "repo://owner/repo/contents/README.md",
        mimeType: "text/plain",
        text: "# Project\n\nThis is the actual content..."
      }
    }
  ],
  isError: false
}

Current Output (Bug)

"successfully downloaded text file (SHA: abc123)"

Expected Output (After Fix)

"# Project\n\nThis is the actual content..."

Additional Context

This issue was discovered when using the GitHub MCP server's get_file_contents tool. Docker logs confirmed that the GitHub MCP server was returning valid, spec-compliant responses with both status
messages and file content, but only the status message was being forwarded to the sandbox.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions