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:
Sam Morrow 2026-06-10 23:50:22 +02:00
commit 2aea5dc6be
No known key found for this signature in database

View 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. |