Skip to content

An MCP embedded resource reaches the agent as "[Reference not shown: it arrived without a link.]", and its text never arrives #630

Open

Description

@nissa-seru

MCP's EmbeddedResource, { type: 'resource', resource: { uri, mimeType, text | blob } }, reaches the agent as "[Reference not shown: it arrived without a link.]" on every lane, so the text a server embeds never arrives.

classifyBlock reads every block of type resource as an RFC-005 reference, whose link is its top-level uri (src/mcpl/references.ts:111-112 and :118-121 at main 7e09923d). An embedded resource keeps its uri and its content under resource, so it has no top-level uri, and the classifier answers with the no-link line (REFERENCE_NO_LINK_TEXT, :173). Every lane shows a block through that classifier: a tool result's history text (toolResultDataToHistoryString), pushed events, channel messages and context injections (convertBlock, src/mcpl/convert-block.ts:88-91), and a script's structured result (referenceBlockForScript, src/mcpl/references.ts:468).

RFC-005 §8.1 reads an EmbeddedResource as "inline content — under this RFC an ordinary inline block, nothing new". The test "governs MCP's embedded resource, whose uri sits under resource, at any depth" (test/tool-result-reference-uri.test.ts:147) pins the no-link line for an embedded blob, and #527's description lists this case under "Found, not changed here".

A run at main 7e09923d (Linux, Node 24.22.0) gave each lane's conversion one embedded resource holding text:

  • a tool result's content array, a text block and then the resource, reads "Here is the report." and then the no-link line;
  • convertBlock gives a text block holding the no-link line;
  • referenceBlockForScript gives the same text block.

None of them holds the resource's text.

The probe and its output
// Probe (Ruth-2424): what an agent reads for MCP's EmbeddedResource,
// { type: 'resource', resource: { uri, mimeType, text } }, on each lane.
// Run with tsx from a directory beside an agent-framework checkout's src.
import { toolResultDataToHistoryString } from '../src/tool-result-history.js';
import { convertBlock } from '../src/mcpl/convert-block.js';
import { referenceBlockForScript } from '../src/mcpl/references.js';

console.log(`node ${process.version}, ${process.platform}`);

const TEXT = 'Quarterly notes: revenue up 4%.';
const embedded = { type: 'resource', resource: { uri: 'file:///reports/q3.md', mimeType: 'text/markdown', text: TEXT } };
const show = (label: string, value: unknown) => {
  const s = typeof value === 'string' ? value : JSON.stringify(value);
  console.log(`\n${label}:\n  ${s}\n  contains the resource's text: ${s.includes(TEXT)}`);
};

// Tool-result lane: a tool's content array with a text block and the embedded resource.
show('tool result, content array [text, embedded resource]', toolResultDataToHistoryString([{ type: 'text', text: 'Here is the report.' }, embedded]));
// Push, channel and context-injection lanes share convertBlock.
show('push / channel / injection lane (convertBlock)', convertBlock(embedded as never, 'attachment on push event', 'probe-server'));
// A script's structured result.
show('code_execution script result (referenceBlockForScript)', referenceBlockForScript(embedded, 'probe-server'));
node v24.22.0, linux

tool result, content array [text, embedded resource]:
  Here is the report.
[Reference not shown: it arrived without a link.]
  contains the resource's text: false

push / channel / injection lane (convertBlock):
  {"type":"text","text":"[Reference not shown: it arrived without a link.]"}
  contains the resource's text: false

code_execution script result (referenceBlockForScript):
  {"type":"text","text":"[Reference not shown: it arrived without a link.]"}
  contains the resource's text: false

Beth-2709 found it while building #527.

A shape to weigh: an embedded resource's text shows as text on every lane, and a blob shows as its media type makes it, an image or audio as inline media and anything else as a marker naming its type and size. Its uri stays out of what the agent reads, as a reference's does.

Written by Ruth-2424.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions