SEP-2571: Resource Submission for Agent Coordination by cswelker · Pull Request #2571 · modelcontextprotocol/modelcontextprotocol · GitHub
https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2571/files • 377 KB fetched
Open original page
SEP-2571: Resource Submission for Agent Coordination by cswelker · Pull Request #2571 · modelcontextprotocol/modelcontextprotocol · GitHub
Skip to content
Navigation Menu
Sign in Appearance settings
* Platform
* AI CODE CREATION
* GitHub Copilot Write better code with AI
* GitHub Copilot app Direct agents from issue to merge
* MCP Registry Integrate external tools
* DEVELOPER WORKFLOWS
* Actions Automate any workflow
* Codespaces Instant dev environments
* Issues Plan and track work
* Code Review Manage code changes
* Code Quality Enforce quality at merge
* APPLICATION SECURITY
* GitHub Advanced Security Find and fix vulnerabilities
* Code security Secure your code as you build
* Secret protection Stop leaks before they start
* EXPLORE
* Why GitHub
* Documentation
* Blog
* Changelog
* Marketplace
View all features
* Solutions
* BY COMPANY SIZE
* Enterprises
* Small and medium teams
* Startups
* Nonprofits
* BY USE CASE
* App Modernization
* DevSecOps
* DevOps
* CI/CD
* View all use cases
* BY INDUSTRY
* Healthcare
* Financial services
* Manufacturing
* Government
* View all industries
View all solutions
* Resources
* EXPLORE BY TOPIC
* AI
* Software Development
* DevOps
* Security
* View all topics
* EXPLORE BY TYPE
* Customer stories
* Events & webinars
* Ebooks & reports
* Business insights
* GitHub Skills
* SUPPORT & SERVICES
* Documentation
* Customer support
* Community forum
* Trust center
* Partners
View all resources
* Open Source
* COMMUNITY
* GitHub Sponsors Fund open source developers
* PROGRAMS
* Security Lab
* Maintainer Community
* GitHub Stars
* Archive Program
* REPOSITORIES
* Topics
* Trending
* Collections
* Enterprise
* ENTERPRISE SOLUTIONS
* Enterprise platform AI-powered developer platform
* AVAILABLE ADD-ONS
* GitHub Advanced Security Enterprise-grade security features
* Copilot for Business Enterprise-grade AI features
* Premium Support Enterprise-grade 24/7 support
* Pricing
Search /
Sign in
Sign up Appearance settings
You signed in with another tab or window. Reload to refresh your session.
You signed out in another tab or window. Reload to refresh your session.
You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
Uh oh!
There was an error while loading. Please reload this page .
modelcontextprotocol
/
modelcontextprotocol
Public
*
Notifications
You must be signed in to change notification settings
*
Fork
1.8k
*
Star
9.2k
*
Code
*
Issues
69
*
Pull requests
78
*
Discussions
*
Actions
*
Projects
*
Security and quality
1
*
Insights
Additional navigation options
*
Code
*
Issues
*
Pull requests
*
Discussions
*
Actions
*
Projects
*
Security and quality
*
Insights
SEP-2571: Resource Submission for Agent Coordination
#2571
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.
Sign up for GitHub
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
Open
cswelker
wants to merge
6
commits into
modelcontextprotocol : main
base:
main
Choose a base branch
Branches
Tags
Loading
Loading
from
cswelker : sep/resource-submission
+193
−0
Conversation
1
Commits
6
Checks
9
Files changed
1
Open
SEP-2571: Resource Submission for Agent Coordination
#2571
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
d07be34
SEP: Resource Submission — resources/create and resources/delete
cswelker Apr 14, 2026
30f0d1d
SEP-2571: update number now that PR is open
cswelker Apr 14, 2026
d8a48ad
SEP-2571: link ZeroMCP as reference implementation
cswelker Apr 14, 2026
f001a68
SEP-2571: strengthen security implications with prompt injection concern
cswelker Apr 14, 2026
29d3b0b
SEP-2571: reference impl is in-progress by SEP author
cswelker Apr 14, 2026
fd1745b
SEP-2571: expand motivation with 3 concrete scenarios, add industry p…
cswelker Apr 14, 2026
File filter
Filter by extension
Filter by extension
.md 
(1)
All 1 file type selected
Viewed files
Clear filters
Conversations
Failed to load comments. Retry
Loading
Uh oh!
There was an error while loading. Please reload this page .
Jump to
Jump to file
Failed to load files. Retry
Loading
Uh oh!
There was an error while loading. Please reload this page .
Diff view
Unified
Split
Hide whitespace
Apply and reload
Show whitespace
Diff view
Unified
Split
Hide whitespace
Apply and reload
There are no files selected for viewing
193 changes: 193 additions & 0 deletions
193
seps/2571-resource-submission.md
Show comments
View file
Edit file
Delete file
Open in desktop
Original file line number
Diff line number
Diff line change
@@ -0,0 +1,193 @@
# SEP-2571: Resource Submission — Client-to-Server Resource Creation
- **Status**: Draft
- **Type**: Standards Track
- **Created**: 2026-04-14
- **Author(s)**: Chris Welker (@cswelker)
- **Sponsor**: None (seeking sponsor)
- **PR**: https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2571
## Abstract
This SEP proposes adding `resources/create` and `resources/delete` methods to the MCP specification, allowing clients to submit resources to a server and receive a URI back. The current resources API is read-only from the client's perspective — servers expose resources, clients consume them. This proposal makes the interface bidirectional, enabling agents to deliver content (prompts, configs, data) to a server without requiring custom tools. This unlocks a class of coordination patterns — multi-agent handoffs, job orchestration, async pipelines — that the current spec cannot address with a standard interface.
## Motivation
The current MCP resources spec is read-only from the client's perspective. Servers expose resources; clients list and read them. This works well for static, server-owned content but breaks down in agentic and multi-step orchestration scenarios where a client needs to *deliver* content to a server for later use.
### Concrete use case: job orchestration
Consider an orchestrator MCP server that accepts job definitions — configs, prompt templates, data payloads — from clients. When a job is registered, its associated resources must be stored server-side so the job can execute later, independently of the submitting client. Today this requires a custom tool (e.g. `upload_prompt`, `store_config`). This works but forces every orchestration system to reinvent the same pattern with a different interface.
### Concrete use case: agent handoff
A research agent completes a web scraping run and needs to pass a large document corpus to a synthesis agent. Today it must either keep running (holding the connection open) or serialize the data through a custom tool. With `resources/create`, the research agent deposits its output and returns a set of URIs. The synthesis agent reads those URIs independently, on its own schedule, with no coupling to the producer's lifecycle.
### Concrete use case: async pipeline stages
A multi-step data pipeline runs each stage as a separate agent invocation: extract → transform → load. Each stage needs to deposit its output for the next stage to consume. Without `resources/create`, every pipeline operator builds a custom handoff mechanism — a tool, a file path, a database row. With `resources/create`, stage output is a URI. The next stage reads it with `resources/read`. The pipeline becomes composable across different server implementations.
### Concrete use case: pre-loaded context for long-running jobs
A client registers a background job that will run hours later. The job needs a large prompt template and a dataset that exist only on the client at registration time. With `resources/create`, the client submits both at registration and hands the server stable URIs. When the job executes — long after the client has disconnected — it retrieves its inputs via `resources/read` with no dependency on the original client.
### Why a standard primitive matters
Custom tools work. But they push a general coordination primitive into application-specific territory. Every orchestrator, every async job runner, every agent handoff system ends up building the same thing with slightly different interfaces, none of which compose. `resources/create` is the natural complement to `resources/read`. The concept of a URI-addressable resource already exists in the spec — this proposal makes it writable.
### Why a standard primitive matters
Custom tools work. But they push a general coordination primitive into application-specific territory. Every orchestrator, every async job runner, every agent handoff system ends up building the same thing with slightly different interfaces, none of which compose. `resources/create` is the natural complement to `resources/read`. The concept of a URI-addressable resource already exists in the spec — this proposal makes it writable.
## Specification
### `resources/create`
Submits a resource to the server. The server stores it and returns a URI that can be used in any subsequent context where a resource URI is accepted.
#### Request
```json
{
"method": "resources/create",
"params": {
"name": "prospect-research-prompt",
"mimeType": "text/plain",
"content": "Research the following company and extract...",
"metadata": {
"ttl": 3600,
"tags": ["prompts", "prospecting"]
}
}
}
```
| Field | Type | Required | Description |
|---|---|---|---|
| `name` | string | yes | Human-readable name for the resource |
| `mimeType` | string | yes | MIME type of the content (`text/plain`, `application/json`, `application/octet-stream`, etc.) |
| `content` | string | yes | Resource content. UTF-8 text, or base64-encoded binary when `mimeType` is not a text type |
| `metadata` | object | no | Arbitrary key-value pairs. Servers may define well-known keys (e.g. `ttl`, `tags`). Servers that do not recognize a key MUST ignore it |
#### Response
```json
{
"uri": "resource://prompts/prospect-research-prompt/abc123",
"name": "prospect-research-prompt",
"mimeType": "text/plain",
"createdAt": "2026-04-14T00:00:00Z"
}
```
The returned `uri` is the canonical reference for this resource. It MUST be stable for at least the duration of the server session. Servers MAY expire resources after the TTL specified in metadata, if provided.
### `resources/delete`
Deletes a resource previously created by the client.
#### Request
```json
{
"method": "resources/delete",
"params": {
"uri": "resource://prompts/prospect-research-prompt/abc123"
}
}
```
#### Response
Empty result on success. Servers MUST return an error if the URI does not exist or the client does not have permission to delete it.
### Capability negotiation
Servers that support resource submission MUST advertise this in their capabilities:
```json
{
"capabilities": {
"resources": {
"create": true,
"delete": true
}
}
}
```
Clients MUST check for these capabilities before issuing `resources/create` or `resources/delete`.
### Binary content
When submitting binary content, the client MUST base64-encode the `content` field and set `mimeType` to a non-text type. Servers MUST decode it accordingly. This follows the same convention as the existing `BlobResourceContents` type.
### Error handling
Servers SHOULD return standard JSON-RPC error codes:
- `-32602` (Invalid params) — missing required fields or malformed content
- `-32000` (Server error) — storage failure or quota exceeded
- A server-defined code for permission errors on `resources/delete`
## Rationale
### Why not a custom tool?
Custom tools work for single implementations but do not compose. If resource submission is part of the spec, any compliant client can submit resources to any compliant server without prior coordination. This is the same argument that justified standardizing `tools/call` rather than leaving every server to define its own invocation convention.
### Why `resources/create` rather than `resources/write` or `resources/upload`?
`create` is consistent with the HTTP/REST pattern (`POST` to create a new resource, receive a reference back). `write` implies updating an existing resource at a known URI, which is a different operation. `upload` is informal. `create` is unambiguous.
### Why allow `metadata`?
Servers have legitimate reasons to accept hints — TTL, tags, access scope — without the spec needing to enumerate them. Making `metadata` an open object with defined ignore-unknown semantics follows the same pattern as `_meta` elsewhere in the spec.
### Prior art: the industry already agrees on this pattern
Every major storage and content API converges on the same shape: submit content, receive a stable reference back.
| System | Submit | Reference returned |
|---|---|---|
| HTTP | `POST /resources` | `Location:` header URI |
| AWS S3 | `PutObject` | S3 URI / presigned URL |
| Google Cloud Storage | `insert` (resumable upload) | Object URI |
| Cloudflare R2 | `PutObject` | R2 URI |
| GitHub Gists / Pastebin | `POST` | Stable URL |
MCP already has `resources/read`. The absence of `resources/create` is the anomaly. This proposal brings MCP into alignment with a pattern the industry has considered settled for decades.
### Alternatives considered
**Reuse the `prompts` primitive.** The `prompts` primitive is close but is server-defined — servers publish named prompt templates, clients fill them in. It does not support client-submitted content. Extending it to handle arbitrary client submissions would distort its semantics.
**Use a tool.** Works today, but produces N incompatible interfaces. Ruled out as a standard approach for the reasons above.
**Server-defined upload endpoints outside MCP.** Breaks the single-transport model and requires clients to discover and authenticate against a separate channel.
## Backward Compatibility
This proposal adds new methods; it does not modify existing ones. Clients that do not use `resources/create` or `resources/delete` are unaffected. The capability negotiation mechanism ensures clients can detect whether a server supports the new methods before using them. No breaking changes.
## Security Implications
**Storage limits.** Servers accepting arbitrary client-submitted content must enforce size and quota limits. The spec should require servers to return an appropriate error (suggest `-32000`) when limits are exceeded.
**Access control.** Resources created by one client should not be readable by arbitrary other clients unless the server explicitly allows it. The spec does not prescribe the access model but SHOULD require that the URI returned is not trivially guessable (e.g. no sequential IDs).
**Content injection.** Servers that later serve submitted content to other agents should treat it as untrusted input. This is particularly relevant in agentic pipelines where a submitted resource may be read directly into an LLM context — a malicious submission could attempt prompt injection against a downstream agent. Servers SHOULD surface the submitting client's identity alongside the resource when serving it, so consumers can apply appropriate trust levels.
**Deletion scope.** `resources/delete` MUST be scoped so a client can only delete resources it created, unless the server explicitly grants broader permissions.
## Reference Implementation
The `resources/create` pattern is already implemented in practice by job orchestration systems that require prompt and config payloads to be stored server-side before a job executes. The interface proposed here generalizes what those systems do with custom tools today.
A reference implementation is being built into [ZeroMCP](https://github.com/probeo-io/antidrift/tree/main/zeromcp) (`@antidrift/zeromcp`, npm) by the author of this SEP. ZeroMCP is a zero-config MCP runtime supporting HTTP transport across 10 languages, MIT-licensed and in active use. The implementation link will be added here once the feature is published.
## Open Questions
1. Should `resources/create` support updating an existing resource (idempotent re-submission by name), or should each call always create a new URI? The current proposal always creates a new URI; an `upsert` variant could be a follow-on.
2. Should `resources/list` return client-created resources alongside server-defined ones, or should there be a filter? The current proposal does not modify `resources/list` behavior — servers may include or exclude submitted resources at their discretion.
3. Should TTL be a first-class field rather than buried in `metadata`? Open to community input.
Loading
Oops, something went wrong.
Retry
Uh oh!
There was an error while loading. Please reload this page .
Toggle all file notes
Toggle all file annotations
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Footer
(c) 2026 GitHub, Inc.
Footer navigation
*
Terms
*
Privacy
*
Security
*
Status
*
Community
*
Docs
*
Contact
*
Mana
Links found on this page
- Skip to content [direct]
- Sign in [direct]
- GitHub Copilot Write better code with AI [direct]
- GitHub Copilot app Direct agents from issue to merge [direct]
- MCP Registry Integrate external tools [direct]
- Actions Automate any workflow [direct]
- Codespaces Instant dev environments [direct]
- Issues Plan and track work [direct]
- Code Review Manage code changes [direct]
- Code Quality Enforce quality at merge [direct]
- GitHub Advanced Security Find and fix vulnerabilities [direct]
- Code security Secure your code as you build [direct]
- Secret protection Stop leaks before they start [direct]
- Why GitHub [direct]
- Documentation [direct]
- Blog [direct]
- Changelog [direct]
- Marketplace [direct]
- View all features [direct]
- Enterprises [direct]
- Small and medium teams [direct]
- Startups [direct]
- Nonprofits [direct]
- App Modernization [direct]
- DevSecOps [direct]
- DevOps [direct]
- CI/CD [direct]
- View all use cases [direct]
- Healthcare [direct]
- Financial services [direct]
- Manufacturing [direct]
- Government [direct]
- View all industries [direct]
- View all solutions [direct]
- AI [direct]
- Software Development [direct]
- DevOps [direct]
- Security [direct]
- View all topics [direct]
- Customer stories [direct]
- Events & webinars [direct]
- Ebooks & reports [direct]
- Business insights [direct]
- GitHub Skills [direct]
- Customer support [direct]
- Community forum [direct]
- Trust center [direct]
- Partners [direct]
- View all resources [direct]
- GitHub Sponsors Fund open source developers [direct]
- Security Lab [direct]
- Maintainer Community [direct]
- GitHub Stars [direct]
- Archive Program [direct]
- Topics [direct]
- Trending [direct]
- Collections [direct]
- Copilot for Business Enterprise-grade AI features [direct]
- Premium Support Enterprise-grade 24/7 support [direct]
- Pricing [direct]
- Sign up [direct]
- modelcontextprotocol [direct]
- modelcontextprotocol [direct]
- Notifications [direct]
- Issues
69 [direct]
- Pull requests
78 [direct]
- Discussions [direct]
- Actions [direct]
- Projects [direct]
- Security and quality
1 [direct]
- Insights [direct]
- Sign up for GitHub [direct]
- terms of service [direct]
- privacy statement [direct]
- Sign in [direct]
- cswelker [direct]
- modelcontextprotocol : main [direct]
- cswelker : sep/resource-submission [direct]
- Conversation
1 [direct]
- Commits
6 [direct]