Skip to content

Conversation

@SamMorrowDrums
Copy link
Contributor

@SamMorrowDrums SamMorrowDrums commented Nov 21, 2025

Summary

This SEP proposes a tool resolution mechanism that enables servers to provide argument-specific metadata before tool invocation. The design takes inspiration from LSP's resolve pattern and HTTP preflight OPTION requests while adapting it for MCP's unique requirements.

Key Changes

  • New tools/resolve method: Clients can request refined tool metadata based on intended arguments
  • New resolve field: Tools can indicate they support resolution
  • New server capability: tools.resolve: true

The Problem

Tool definitions from tools/list are static. A manage_files tool must declare destructiveHint: true even though read operations are completely safe. This causes:

  • Over-prompting with unnecessary confirmation dialogs
  • Reduced trust from LLMs that avoid "destructive" tools
  • Poor UX for versatile, multi-action tools

The Solution

Before invoking a tool, clients can call tools/resolve with the tool name and intended arguments. The server returns a complete tool definition with annotations refined for that specific operation:

// Request
{ "method": "tools/resolve", "params": { "name": "manage_files", "arguments": { "action": "read" }}}

// Response - safe operation!
{ "tool": { "name": "manage_files", "annotations": { "readOnlyHint": true, "destructiveHint": false }}}

Why This Approach?

This design follows @findleyr's suggestion to adopt an LSP-inspired resolve pattern:

"we probably want to avoid a future where there are a bunch of separate preflight checks for a single tool call--it would be better to consolidate them into a single exchange"

By returning the full Tool object, we:

  1. Prevent method proliferation (tools/annotations, tools/scopes, tools/costs)
  2. Enable future extensions without protocol changes
  3. Provide a single preflight exchange for all metadata needs

Future Extensibility

The pattern supports future metadata beyond annotations:

  • Scope requirements: OAuth scopes needed for specific operations
  • Cost estimates: Token/credit costs that vary by arguments
  • Rate limits: Different operations may have different limits

These are explicitly out of scope for this SEP but the mechanism supports them.

Backward Compatibility

Fully backward compatible:

  • Existing servers work unchanged
  • Existing clients can ignore resolve: true
  • Static annotations remain the fallback

Checklist:

  • SEP follows the template format
  • Abstract and motivation are clear
  • Specification is complete with request/response formats
  • Backward compatibility addressed
  • Security implications considered
  • Reference implementations provided

@SamMorrowDrums SamMorrowDrums marked this pull request as ready for review November 21, 2025 13:34
@dsp-ant dsp-ant changed the title SEP: Dynamic Tool Annotations SEP-1862: Dynamic Tool Annotations Nov 21, 2025
@dsp-ant dsp-ant added proposal SEP proposal without a sponsor. SEP labels Nov 21, 2025
@SamMorrowDrums
Copy link
Contributor Author

SamMorrowDrums commented Nov 21, 2025

Coincidentally there may already be a case for a preflight request for other purposes. As @findleyr mentioned on Discord, we might not be able to support forwarding of 403 errors during tool calls due to SEP-1699 and so we might wish to enable a preflight checks to support scope challenges also.

cc @dend

@findleyr
Copy link
Contributor

findleyr commented Nov 24, 2025

By comparison, LSP has a notion of 'resolve', which is when the client asks the server to 'finish filling out' a particular stub. For example codeAction/resolve, though this exists for many constructs.

That's slightly different, because the client isn't passing in any specific arguments in the resolve request: it's simply exchanging the stub for a fully filled-out version, but I think there's something to be learned from the design: we probably want to avoid a future where there are a bunch of separate preflight checks for a single tool call--it would be better to consolidate them into a single exchange. I'm not sure what that means, concretely: do we return the entire tool from the preflight check, rather than just its annotations?

@SamMorrowDrums
Copy link
Contributor Author

Revised Direction

Thanks @findleyr for the excellent feedback on adopting an LSP-inspired resolve pattern. I've substantially revised this SEP based on your suggestions and additional considerations around extensibility.

Key Changes

Renamed concept: tools/annotationstools/resolve

  • Field: dynamicAnnotationsresolve
  • Capability: dynamicAnnotationsresolve
  • Method: tools/annotationstools/resolve

Returns full Tool object instead of just annotations

  • Enables future extensions (scopes, costs, rate limits) without new preflight methods
  • Follows the principle of "consolidate into a single exchange"
  • Maintains structural consistency with tools/list responses

Added LSP context with comparison table

  • Clarified that we're adapting LSP's useful patterns for MCP
  • Key difference: MCP tools are fully functional from tools/list, resolution refines metadata based on intended arguments

Added Future Extensibility section

  • Discussed potential uses for scope requirements (addressing my comment about scope challenges)
  • Noted these are out of scope but the mechanism supports them

Cleaned up examples

  • Consolidated duplicate file examples
  • Removed redundant sections

Open for Discussion

I'd appreciate feedback on:

  1. The naming (resolve vs alternatives)
  2. Whether the LSP comparison is helpful or distracting
  3. The scope of "future extensibility" - should we be more or less specific?

The goal is a clean, extensible foundation that avoids the "proliferation of preflight methods" concern @findleyr raised.

@SamMorrowDrums SamMorrowDrums changed the title SEP-1862: Dynamic Tool Annotations SEP: Tool Resolution Nov 25, 2025
@SamMorrowDrums
Copy link
Contributor Author

As an example trying to do Scope Challenge for GitHub MCP, I would ideally allow public repo access without a repo scope challenge, however then I won't be able to send a challenge for accessing private repos, so the granularity of 1 scope for one tool is definitely not sufficient for our use case. In order to allow least privilege generally, I am forced to provide a scope challenge for all available data, which is a problem when a legitimate user wants to access only public repo data and not give the token full repo scope.

This is currently not solvable.

SamMorrowDrums added a commit to SamMorrowDrums/modelcontextprotocol that referenced this pull request Nov 27, 2025
Introduces trust and sensitivity annotations for MCP requests and responses,
enabling clients and servers to track, propagate, and enforce trust boundaries
on data as it flows through tool invocations.

Key features:
- Result annotations: sensitiveHint, privateHint, openWorldHint, maliciousActivityHint, attribution
- Request annotations for propagating trust context
- Propagation rules ensuring sensitivity markers persist across agent sessions
- Integration with Tool Resolution (modelcontextprotocol#1862) for pre-execution annotations
- Per-item annotations for mixed results (e.g., search results)
- Defense-in-depth approach complementing tool-level annotations

Closes modelcontextprotocol#711
@dsp-ant dsp-ant changed the title SEP: Tool Resolution SEP-1862: Tool Resolution Dec 3, 2025
@localden
Copy link
Contributor

@SamMorrowDrums this SEP does not have an assigned sponsor. Are you looking to continue working on it and find sponsorship?

@SamMorrowDrums
Copy link
Contributor Author

Very much so @localden, it underpins several things I think are important when needed, I have got a few folks interested (including some major companies in the space) but I'm not sure how best to identify a sponsor.

If you have any advice I'd love to hear it. I'll bring it up on discord, perhaps I just need to work out which group would care most on discord or propose an IG, if there isn't one.

I'm going to have some opportunity in the Tool Scopes WG to see if it's a good fit there shortly, given that there isn't a 1:1 mapping with scopes and tools and it's not clear until runtime what the concrete requirement would be, it could be adopted for this.

I believe it would make the trust and privacy SEP proposal better too, reduce over prompting and give MCP clients a better UX.

I discussed its possible applicability to FGP with @nbarbettini last week also.

Need a little more time, and might need to tighten up the elevator pitch to encourage more interest.

@SamMorrowDrums SamMorrowDrums force-pushed the sep-dynamic-tool-annotations branch from cb51903 to 7cf417f Compare January 29, 2026 10:40
@SamMorrowDrums SamMorrowDrums requested a review from a team as a code owner January 29, 2026 10:40
@SamMorrowDrums
Copy link
Contributor Author

SamMorrowDrums commented Jan 29, 2026

@localden @nicknotfun will be sponsoring.

@SamMorrowDrums SamMorrowDrums force-pushed the sep-dynamic-tool-annotations branch from 7cf417f to 619ffb1 Compare January 29, 2026 14:32
SamMorrowDrums added a commit to SamMorrowDrums/modelcontextprotocol that referenced this pull request Jan 30, 2026
Introduces trust and sensitivity annotations for MCP requests and responses,
enabling clients and servers to track, propagate, and enforce trust boundaries
on data as it flows through tool invocations.

Key features:
- Result annotations: sensitiveHint, privateHint, openWorldHint, maliciousActivityHint, attribution
- Request annotations for propagating trust context
- Propagation rules ensuring sensitivity markers persist across agent sessions
- Integration with Tool Resolution (modelcontextprotocol#1862) for pre-execution annotations
- Per-item annotations for mixed results (e.g., search results)
- Defense-in-depth approach complementing tool-level annotations

Closes modelcontextprotocol#711
SamMorrowDrums and others added 7 commits January 30, 2026 16:01
- Update creation date to 2025-11-21
- Consolidate duplicate file/API examples into single table-based example
- Remove redundant 'Why Return Full Tool?' section (already in Rationale)
- Clean up TypeScript comments
- Apply prettier formatting
…eristics, and related SEPs

- Add authorization delegation context example (based on SEP-214 token exchange)
- Add execution characteristics example for long-running task indication
- Update motivation to mention execution characteristics and auth boundary crossings
- Add SEP-1385 (Tool Execution Requirements) to Related Work
- Add SEP-214 (On-Behalf-Of Token Exchange) to Related Work
SamMorrowDrums and others added 5 commits January 30, 2026 16:01
Adds argument-specific scope requirements as a key use case:
- Motivation: Over-scoping problem (e.g., GitHub repo scope for public repos)
- Future Extensibility: Dynamic securitySchemes example with noauth/oauth2
- Related Work: Cross-reference to SEP-1488 and SEP-711 (Trust Annotations)

The key insight is that static securitySchemes declarations require
maximum permissions upfront, but tool resolution enables servers to
return argument-specific requirements (e.g., noauth for public repos,
repo scope only for private repos).

This reduces unnecessary OAuth prompts and enables principle of least
privilege in MCP tool invocations.
- Update header to match SEP-1850 PR-based workflow format
- Emphasize key design principles: opt-in, backward compatible, resilient fallback, lightweight
- Add confirmation fatigue framing in consequences section
- Strengthen performance requirements (milliseconds, like HTTP OPTIONS/HEAD)
- Add extensibility messaging for auth/security/trust/privacy specifications
- Cross-reference SEP-1913 (Trust and Sensitivity Annotations)
- Add curated App Store use case showing layered approval model
- Regenerate SEP documentation for docs site
@SamMorrowDrums SamMorrowDrums force-pushed the sep-dynamic-tool-annotations branch from 619ffb1 to b4faa03 Compare January 30, 2026 15:01
@sep-automation-bot sep-automation-bot bot added draft SEP proposal with a sponsor. and removed proposal SEP proposal without a sponsor. labels Feb 4, 2026
@sep-automation-bot
Copy link

State Transition: proposal → draft

This SEP has been transitioned from proposal to draft.

@nickcoai has been assigned as the sponsor for this SEP.


This is an automated message from the SEP lifecycle bot.

@connor4312
Copy link
Contributor

This is a nice proposal and I'm generally a big fan. Some notes:

  • The resolved tool returns inputSchema again. How should a client handle if this is different from the unresolved schema -- it could potentially invalidate the input just passed to the tool? The SEP says "other fields may match the original" but this is not a MUST. And if this is the case, should we just omit the fields that are immutable in the resolve result?
  • I wonder if this should be a server capability vs a annotation on the tool schema which is resolve-able. This feels like something that a server wouldn't necessarily care to implement for every single tool.
  • "Clients MAY skip resolution for tools where static metadata is acceptable" -- I'm not sure what this means.

@SamMorrowDrums
Copy link
Contributor Author

"Clients MAY skip resolution for tools where static metadata is acceptable" -- I'm not sure what this means

What I intended here is that if a client wasn't going to prompt a user anyway (because for example they enabled skipping confirmations for a given tool, all write tools or they're running yolo mode), the result of the resolution would be immaterial to the client and therefore could be reasonably skipped.

The static annotations are meant to represent the worst case and so clients should be free to determine if there would be any value in the call.

The caveat to this is if we were to one day extend tools/resolve to support additional actionable data or behaviours such as issuing a scope challenge, it would then be better if clients always called tools/resolve when offered.

Do you have a suggestion for rephrasing @connor4312 or do you think we should just remove this part?

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

Labels

draft SEP proposal with a sponsor. SEP

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

6 participants