docs: scaffold trust/privacy extension repo from SEP-1913 carve
Carve the schema-bearing parts of SEP-1913 into three independent experimental extensions, per @localden's "narrower first cut" ask and the Tool Annotations IG's 2026-05-28 extension-first decision: - io.modelcontextprotocol/trust-annotations (headline): narrow data-classification taxonomy (sensitive, untrusted) + open-ended evidenceRef pointer. - io.modelcontextprotocol/action-metadata: carries forward SEP-2061 (inputMetadata/returnMetadata/outcomes + requiresReview). - io.modelcontextprotocol/ifc-fides: FIDES information-flow control as a profile of evidenceRef, not a wire root. Adds repo meta (README, MAINTAINERS, CONTRIBUTING, LICENSE) and docs (sep-disposition, intent-comment, decisions, open-questions, trust-model, related-work). FIDES demoted to a profile; DataClass and requiresReview rehomed; maliciousActivityHint and propagation parked on the SEP-1913 umbrella. Citations index on public sources only. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
fe722986ff
commit
2aea5dc6be
1 changed files with 1022 additions and 1 deletions
136
specification/draft/action-metadata.mdx
Normal file
136
specification/draft/action-metadata.mdx
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
---
|
||||
title: Action Metadata
|
||||
extension_identifier: io.modelcontextprotocol/action-metadata
|
||||
status: Draft (experimental)
|
||||
maintainers:
|
||||
- "@rreichel3"
|
||||
- "@SamMorrowDrums"
|
||||
related:
|
||||
- https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2061
|
||||
- https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1913
|
||||
---
|
||||
|
||||
> ⚠️ **Experimental draft skeleton.** This carries forward
|
||||
> [SEP-2061: Action Security Metadata](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2061)
|
||||
> by [@rreichel3](https://github.com/rreichel3) into the IG's experimental repo,
|
||||
> per the May 28 2026 decision to pursue trust/privacy work as an extension
|
||||
> first. SEP-2061 remains the canonical discussion thread for the field
|
||||
> semantics.
|
||||
|
||||
## Abstract
|
||||
|
||||
This extension adds a small, declarative contract to a tool's static
|
||||
`ToolAnnotations` describing **what the tool does with data**: where inputs may
|
||||
go, where outputs originate, and what real-world outcome invoking it can cause.
|
||||
Where [`trust-annotations`](./trust-annotations.mdx) classifies *data in
|
||||
transit*, this extension classifies *tool behavior*. The two are complementary
|
||||
and independently adoptable — a client can consume action metadata without
|
||||
implementing trust annotations at all.
|
||||
|
||||
## Motivation
|
||||
|
||||
MCP today treats all tool calls as equivalent at the protocol level beyond the
|
||||
coarse `readOnlyHint` / `destructiveHint` / `idempotentHint` / `openWorldHint`
|
||||
hints. A tool that reads drafts and a tool that sends email are otherwise
|
||||
indistinguishable, even though their privacy and consent implications differ
|
||||
radically. Runtimes fall back to inferring risk from tool names or model
|
||||
behavior, which does not scale.
|
||||
|
||||
This was reinforced in the May 28 2026 IG meeting: a model often **cannot tell
|
||||
whether a target is private or public**, and absent that signal it may push
|
||||
content somewhere it should not. A declarative behavioral contract lets clients
|
||||
and models make safer decisions without baking domain knowledge into every
|
||||
model.
|
||||
|
||||
The canonical worked example from SEP-2061: `read_drafts`, `list_inbox`, and
|
||||
`send_email` can share an identical JSON Schema yet have completely different
|
||||
security semantics — only action metadata distinguishes them.
|
||||
|
||||
## Specification
|
||||
|
||||
### Dependencies
|
||||
|
||||
This extension annotates the existing `ToolAnnotations` object returned by
|
||||
`tools/list`. It has no dependency on `trust-annotations` or on Tool Resolution.
|
||||
|
||||
### Fields
|
||||
|
||||
Carried under the extension-namespaced key on `ToolAnnotations`:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"annotations": {
|
||||
"io.modelcontextprotocol/action-metadata": {
|
||||
"inputMetadata": {
|
||||
"destination": "external", // where input data may be stored/sent
|
||||
"sensitivity": "personal" // kind of data the tool accepts
|
||||
},
|
||||
"returnMetadata": {
|
||||
"source": "open-world", // where returned data originates
|
||||
"sensitivity": "public"
|
||||
},
|
||||
"outcome": "consequential", // benign | consequential | irreversible
|
||||
"requiresReview": true // host SHOULD seek human confirmation
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Meaning |
|
||||
| :--- | :--- |
|
||||
| `inputMetadata.destination` | Where data passed to the tool may end up (e.g. `local`, `internal`, `external`). |
|
||||
| `inputMetadata.sensitivity` | The kind of data the tool is designed to accept. |
|
||||
| `returnMetadata.source` | Where the tool's returned data originates (e.g. `first-party`, `open-world`). |
|
||||
| `returnMetadata.sensitivity` | The kind of data the tool is designed to return. |
|
||||
| `outcome` | Real-world effect class: `benign` / `consequential` / `irreversible`. |
|
||||
| `requiresReview` | The tool author signals that a host SHOULD obtain explicit human confirmation before invocation. |
|
||||
|
||||
> Exact enum value sets are inherited from SEP-2061 and are **not** re-litigated
|
||||
> here; this draft tracks that proposal. Where SEP-2061 evolves, this file
|
||||
> follows.
|
||||
|
||||
### `requiresReview` lives here, deliberately
|
||||
|
||||
`requiresReview` is a **workflow/consent** signal, not a data-classification
|
||||
property. It was intentionally moved out of [`trust-annotations`](./trust-annotations.mdx)
|
||||
(which stays strictly data-classifying) to avoid reproducing SEP-1913's
|
||||
"several concerns in one schema" problem at smaller scale. It sits next to
|
||||
`outcome` because both describe the *act* of calling the tool rather than the
|
||||
*data* in flight.
|
||||
|
||||
### Lifecycle and `list_changed`
|
||||
|
||||
These fields are part of the **tool definition** (`ToolAnnotations`). They are
|
||||
therefore covered by `tools/list_changed`: a server that changes a tool's
|
||||
action metadata MUST emit `list_changed` as it would for any tool-definition
|
||||
change. (This is the opposite of `trust-annotations`, which is response-level.)
|
||||
|
||||
## Relationship to existing annotations
|
||||
|
||||
`outcome: irreversible` overlaps conceptually with `destructiveHint` but is
|
||||
strictly richer (a three-way classification vs. a boolean) and is scoped to the
|
||||
real-world effect rather than to whether the operation is destructive to
|
||||
server-side state. The IG will need to decide whether action metadata
|
||||
*supersedes* or *coexists with* the legacy hints before any graduation.
|
||||
|
||||
## Reference implementation
|
||||
|
||||
Per [SEP-2061](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2061):
|
||||
the `read_drafts` / `list_inbox` / `send_email` worked example with identical
|
||||
schemas and divergent action metadata. A public MCP server emitting these
|
||||
fields (candidate: [`github-mcp-server`](https://github.com/github/github-mcp-server))
|
||||
would anchor the draft in a real ecosystem.
|
||||
|
||||
## Open questions
|
||||
|
||||
- Coexistence vs. replacement of `destructiveHint` / `readOnlyHint`.
|
||||
- Whether `destination` / `source` / `sensitivity` enums should be open strings
|
||||
(consistent with `evidenceRef.type`) or closed enums.
|
||||
- Whether `requiresReview` needs a machine-readable *reason* (vs. a bare
|
||||
boolean) to drive good client UX.
|
||||
|
||||
## Changelog
|
||||
|
||||
| Date | Change |
|
||||
| ---------- | ------------------------------------------------------------------- |
|
||||
| 2026-06-10 | Initial draft skeleton, carrying SEP-2061 into the experimental repo; absorbed `requiresReview` from the trust taxonomy. |
|
||||
Loading…
Reference in a new issue