-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Update guidance for use of Embedded Resources in CallToolResult #415
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update guidance for use of Embedded Resources in CallToolResult #415
Conversation
|
Thanks for opening this, I think it is sorely needed. Coming from this discussion, there has been repeated misalignment across potentially a half dozen individuals with respect to the idea of using EmbeddedResource as a way to return shapes like JSON or HTML from a A thought: would it make sense to make For example, take the following scenario:
Would we expect the server to come up with some custom URI scheme for this, even though the URI and associated scheme are entirely ignored by both sides? Seems like it would be better to just make it optional. If there's an argument to keep it required, though, I could be convinced that this scenario is too contrived and the reality is that we want to push implementers to invest in defining and documenting thoughtful custom URI's instead of skipping that step entirely. |
|
Great question - I'd propose it remain mandatory for the following reasons:
I think the need here is to make it clearer what RFC3986 means in practice for integrators, and some use-cases to show how uris and associated schemes could be useful. A couple of examples:
And also the really important fact that RFC3986 doesn't make guarantees of permanence - meaning integrators are free to use There's a lot of value to be unlocked here. For example:
MCP Tool Calls have been a delighting feature as it has allowed developers to quickly and easily integrate their code with a huge number of Hosts. I personally think the next wave of value is unlocked by integrators producing libraries and schemes that enable much richer integrations. Because MCP can be used in so many different environments, it doesn't necessarily make sense to e.g. include UX primitives in the core - but to enable Host application writers to combine the libraries and schemes that make sense to them. |
|
I am a big fan of increasing clarity on embedded resources and encouraging this use case. It took me and some others a while to understand that using embedded resources in this way is possible. It also feels like it supplants the need for adding tool result schemas to the spec, which to me feels substantially more complex and less ergonomic.
I wonder if we could add some annotation to
Not sure if something like this feels right, but here's example I've mocked up in the context of the servers I've been developing (Cloudflare's official MCP servers): this.server.tool(
"create_bucket",
`Creates a R2 bucket for object storage. An example workflow:
- User: "Create a bucket for me to store image"
- Call tool create_bucket, returns
- Call a file write tool to some valid wrangler.json, which contains the result of create_database
`,
async () => {
const bucketName = "bucket123"
return {
content: [
{
type: "resource",
resource: {
/**
* The "ephemeral" uri scheme implies that this embedded resource
* only exists for this tool call and can't be subscribed to or
* fetched later
*/
uri: "ephemeral:/wrangler.json",
mimeType: "application/json",
text: JSON.stringify({
r2_buckets: [{ binding: "MY_BUCKET", bucket_name: bucketName }]
}),
},
},
{
type: "text",
text: "Here is a JSON config snippet, which can be added to a valid wrangler.json",
},
],
};
}
); |
|
GREAT change @evalstate!!
For what it's worth, I feel like this is actually the crux of the problem. Because embedded resources are so tightly tied to normal resources, when I first read the spec I absolutely felt like I couldn't return an embedded resource unless I also server it up as a resource. Maybe I misread something, but I read it as you could optionally take a resource that your server hosts and serve it to he client as the response to this call. That's very different than the use case you've outlined here! It might be that read the spec linearally and read the resource section before the tools section, so when I got to the tools section I was all primed for resources to be pervasive.
Your examples here are great, though I'm not sure the examples change much if the URI is optional? If it's there you have these semantics, if not, no big deal?
I'll admit I fall into this camp - I'm not entirely sure when to use them. For instance, in the hosting working group, we're discussing multi-tenancy. If you're an agent and you have access to two tenants, should that be a resource? Should it be multiple resources?? I know that's a silly one example, but I've been genuinely struggling with it. I don't know if the answer is documentation related or what, but not being sure how exactly to use resources then immediately wrapped around to, when I read the tool call details, because I felt I didn't understand resources very well, I didn't really give embedded resources a lot of thought, I figured they were solving a different problem than json delivery. Hope this perspective helps! |
|
It does thanks @patwhite I think the danger is in overthinking them. A Resource is simply some text or binary data, an identifier (uri) and a mimeType - no more, no less. They can be delivered with Tool Results, Prompts and directly as Resources. If you want - and the server and uri scheme support it - you can subscribe for live updates to them, specify a templating scheme and use completions for discovery - but these things are all optional if you need them. I'd encourage people to use those capabilities, and think it good practice to have an integrated scheme, but it's flexible. I do also think that commonly accepted uri schemes for MCP would be really helpful for the wider community. RFC3986 gives us the rules about using them (e.g. how to use |
…ink at top is not obvious).
|
Update 28/04/2025 - I have also updated the server/Resources page to include a sub-section on Custom URI schemes, primarily as the link in the opening paragraph is not obvious. |
|
@evalstate first of all, thanks for your patience with the sprawly discourse on #356 :) A few general questions/observations here, and then I'll follow up on #356 with some questions related specifically to schematized tool results. Apologies for the split commentary but I figure that's the best way to keep the schematized tool results discussion in one place.
|
Embedded simply means a Resource contained within a CallToolResult or PromptMessage. It doesn't have special meaning beyond that.
We only need a mental model of I'm not particularly comfortable with the idea of promoting "optional ephemerality". The behaviour of the Resource uri scheme is defined by the Server author. They may choose to publish a well known scheme such as
I'm sorry, I've read this multiple times and I'm afraid I don't understand this point at all. |
The problem is that irrespective of RFC 3986, MCP broadly assumes/relies on the persistence of Resources (e.g. the So it would be actively confusing to use Section 7.1 RFC 3986 as a basis for explicitly defining all Resources as being "optionally persistent" without further qualification, since Resources as commonly used do in fact need to be persistent. If we add guidance about using ephemeral EmbeddedResources, we'll need to be very clear about this distinction. (Regardless of whether we use EmbeddedResources to return structured tool results.)
Yeah, I see why adding an ephemerality bit would be redundant, given that this information should be derivable from the URI (given sufficient information from the server). I think this moves EmbeddedResource further away from being a reasonably lightweight solution for tools that simply want to return ephemeral structured results though.
My point was just, "a client needs a way to find out if a Resource is ephemeral", which I think you answered above with "a server should either use a well-known URI scheme or publish + document one of its own, and the client should use this information to derive this information from the URI " |
There's a chance we're overthinking this. The fact I do a directory listing doesn't mean the filesystem guarantees the later availability of a file.
Would you mind being specific, as I'm not inferring that from either https://modelcontextprotocol.io/docs/concepts/resources or https://modelcontextprotocol.io/specification/2025-03-26/server/resources. |
|
A potential slippery slope to be aware of:
Beyond |
good catch :) Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com>
dsp-ant
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am okay for this to be accepted, but please make teh changes only to DRAFT.
|
|
||
| ### Custom URI Schemes | ||
|
|
||
| Custom URI schemes SHOULD be in accordance with [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Custom URI schemes SHOULD be in accordance with [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986), | |
| Custom URI schemes MUST be in accordance with [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986), |
In the schema we say format: uri, which according to JSON-Spec referes to RFC3986, see https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.7.3.5
|
@evalstate thanks for the quick turnaround! If you could fix merge conflicts then it's button-pushing time |
bhosmer-ant
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
|
Thanks @bhosmer-ant -- should be good, tripped over the lastModified merge. Should be mergeable |
|
Done! ! Yeah I don't think that lastModified thing was due to your merge tbh 😁 |

This change updates the guidance on the use of EmbeddedResources within CallToolResults to clarify the use of custom URI Schemes, and add guidance that Servers using EmbeddedResources SHOULD implement the
resourcescapability.Motivation and Context
The documentation for Resources makes it clear that MCP Servers are:
And references RFC 3986 in the opening paragraph.
The existing wording for CallToolResult is worded in a way which makes it sound like there are guarantees for later availability:
Whereas a custom URI scheme within RFC3986 (7.1 Reliability and Consistency) states:
The update to the wording is intended to make it clearer that MCP Server implementors are able to define and use their own scheme.
How Has This Been Tested?
Local document serving.
Breaking Changes
No breaking changes.
Types of changes
Checklist
Additional context
A number of discussions threads, for example:
https://github.com/orgs/modelcontextprotocol/discussions/287#discussioncomment-12944736