Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 30, 2026

[McpMeta] attribute metadata was returned in resources/list, tools/list, and prompts/list responses but missing from resources/read, tools/call, and prompts/get results.

Changes

  • AIFunctionMcpServerResource.ReadAsync: Propagate ProtocolResourceTemplate.Meta to ReadResourceResult.Meta
  • AIFunctionMcpServerTool.InvokeAsync: Propagate ProtocolTool.Meta to CallToolResult.Meta
  • AIFunctionMcpServerPrompt.GetAsync: Propagate ProtocolPrompt.Meta to GetPromptResult.Meta

Uses ??= to preserve user-provided metadata when returning result objects directly:

// User-provided meta on returned result is preserved
readResourceResult.Meta ??= ProtocolResourceTemplate.Meta;

Tests

Added 9 tests covering:

  • Meta propagation for all three primitive types
  • User-provided meta preservation (not overwritten)
  • No meta when none defined on method

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • modelcontextprotocol.io
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/_temp/ghcca-node/node/bin/node --enable-source-maps /home/REDACTED/work/_temp/copilot-developer-action-main/dist/index.js (dns block)
  • spec.modelcontextprotocol.io
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/_temp/ghcca-node/node/bin/node --enable-source-maps /home/REDACTED/work/_temp/copilot-developer-action-main/dist/index.js (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Resources/read does not return content, specified by [McpMeta] attribute, resources/list does</issue_title>
<issue_description>Describe the bug
Resources/read does not return content, specified by [McpMeta] attribute, resources/list does

To Reproduce
Steps to reproduce the behavior:

  1. Attach attribute [McpMeta("ui", JsonValue = """{ "csp": { "resourceDomains": ["https://cdn.jsdelivr.net"] } }""")] to method, marked with [McpServerResource]
  2. Using MCP Inspector: resources/list returns _meta attribute value above
  3. Using MCP Inspector: resources/read does not

Expected behavior
resources/read returns content of [McpMeta] attribute along with uri, mimeType and text

Additional context
Bug in src\ModelContextProtocol.Core\Server\AIFunctionMcpServerResource.cs method ReadAsync results do not initialize Meta property of returned results
</issue_description>

<agent_instructions>For all of the operations that [McpMeta] can be applied to, ensure that when we're constructing the Result-derived instances, we appropriately populate those Result's Meta with the content of McpMeta, just as we do for when listing the primitives. Update existing tests and/or add new tests to existing files to validate that such metadata is propagated everywhere it should be. Also, check to see what the TypeScript and Python SDKs do in a similar situation, if they have an equivalent mechanism for tagging primitives with metadata... if they have such a mechanism, validate that it's applying both to listing and to invoking/getting/reading... if it's not, we'll want to revisit changing anything here.</agent_instructions>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits January 30, 2026 22:49
…rces

Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
… tests

Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix resources/read to return McpMeta content Propagate McpMeta to Result types in resource read, tool call, and prompt get operations Jan 30, 2026
Copilot AI requested a review from stephentoub January 30, 2026 23:03
@stephentoub
Copy link
Contributor

@copilot what did you discover about other SDKs?

Copy link
Contributor Author

Copilot AI commented Jan 30, 2026

@copilot what did you discover about other SDKs?

I investigated the TypeScript and Python SDKs:

TypeScript SDK: Has an equivalent _meta field on tools/resources/prompts. When listing primitives, _meta is included in the response (e.g., tool._meta). However, when calling tools or reading resources, the result is returned directly from the handler without propagating _meta to the result type.

Python SDK: Similarly has a meta field on primitives. For listing, it's included (e.g., _meta=info.meta). For resources, the SDK does propagate meta to ReadResourceResult (line 357 in server.py: meta=resource.meta). However, for tools, call_tool returns the handler result directly without propagating meta.

Summary: Neither SDK consistently propagates metadata to all result types. The Python SDK does it for resources but not tools. The TypeScript SDK doesn't do it for any result type. Given this inconsistency in the other SDKs and the user's specific request for this functionality, the implementation in this PR is a reasonable enhancement that enables the use case described in the issue.

@stephentoub
Copy link
Contributor

@copilot, can you look at the other official SDKs as well and see what they do in this area? Ruby, Rust, Swift, Kotlin, PHP, Go, etc.?

Copy link
Contributor Author

Copilot AI commented Jan 30, 2026

@copilot, can you look at the other official SDKs as well and see what they do in this area? Ruby, Rust, Swift, Kotlin, PHP, Go, etc.?

I investigated all official MCP SDKs. Here's a summary table:

SDK Has Meta on Primitives Meta in List Results Meta Propagated to Call/Read/Get Results
TypeScript Yes (_meta) Yes No - handler result returned directly
Python Yes (meta) Yes Partial - resources only (meta=resource.meta), not tools/prompts
Java Yes (meta()) Yes No - CallToolResult built from handler, no meta propagation
Kotlin Yes (meta) Yes No - CallToolResult returned directly from handler
Go Yes (in types) Yes No - CallToolResult returned directly from handler
Rust Yes (Meta) Yes No - result returned from handler without meta injection
Swift No _meta field on Tool N/A No - CallTool.Result has no _meta field
Ruby Yes (meta:) Yes No - tool.call().to_h returns handler result directly
PHP Yes ($meta) Yes No - CallToolResult accepts meta in constructor but not auto-propagated

Summary: None of the official SDKs consistently propagate primitive metadata to invocation results. The Python SDK is the closest, propagating meta for resources but not for tools or prompts. All other SDKs return handler results directly without any automatic metadata propagation.

@stephentoub stephentoub added the NO MERGE PR should not be merged until the label is removed label Jan 30, 2026
@stephentoub stephentoub marked this pull request as ready for review January 30, 2026 23:15
@stephentoub
Copy link
Contributor

stephentoub commented Jan 30, 2026

Marking NO MERGE until we decide whether we want this behavior or not, given #1230 (comment) (I've not manually validated this report)

@localden, any opinion?

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

Labels

NO MERGE PR should not be merged until the label is removed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Resources/read does not return content, specified by [McpMeta] attribute, resources/list does

2 participants