diff --git a/docs/docs.json b/docs/docs.json
index 95785a0d5..a8c08f13a 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -428,6 +428,12 @@
"seps/2207-oidc-refresh-token-guidance",
"seps/2260-Require-Server-requests-to-be-associated-with-Client-requests"
]
+ },
+ {
+ "group": "Draft",
+ "pages": [
+ "seps/2200-clarify-tool-result-content-visibility"
+ ]
}
]
},
diff --git a/docs/seps/2200-clarify-tool-result-content-visibility.mdx b/docs/seps/2200-clarify-tool-result-content-visibility.mdx
new file mode 100644
index 000000000..d3c3d5f64
--- /dev/null
+++ b/docs/seps/2200-clarify-tool-result-content-visibility.mdx
@@ -0,0 +1,194 @@
+---
+title: "SEP-2200: Clarify Tool Result Content and Model Visibility"
+sidebarTitle: "SEP-2200: Clarify Tool Result Content and Model V…"
+description: "Clarify Tool Result Content and Model Visibility"
+---
+
+
+
+ Draft
+
+
+ Standards Track
+
+
+
+| Field | Value |
+| ------------- | ------------------------------------------------------------------------------- |
+| **SEP** | 2200 |
+| **Title** | Clarify Tool Result Content and Model Visibility |
+| **Status** | Draft |
+| **Type** | Standards Track |
+| **Created** | 2026-02-03 |
+| **Author(s)** | Kyle Rubenok ([@krubenok](https://github.com/krubenok)) |
+| **Sponsor** | Ola Hungerford ([@olaservo](https://github.com/olaservo)) |
+| **PR** | [#2200](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2200) |
+
+---
+
+## Abstract
+
+This SEP updates the intended usage and model visibility of `CallToolResult.content` and
+`CallToolResult.structuredContent`. It formalizes the distinction between model-oriented output
+(`content`) and machine-oriented output (`structuredContent`), provides guidance on semantic
+alignment when both fields are present, and clarifies client behavior for selecting which field to
+expose to models. The change is especially important now that MCP Apps is an official extension,
+where tool results may drive interactive UI experiences and should not inadvertently flood model
+context. This SEP does not change the protocol wire format or field types, but it does change the
+normative guidance for what servers are expected to return in `content` when `structuredContent`
+is present. Implementations that treated `content` as if it were always a JSON-serialized copy of
+`structuredContent`—an assumption made in some tooling and implementations, but not a universally
+safe one in practice—may need to be updated.
+
+## Motivation
+
+Since `structuredContent` was introduced in
+[PR #371](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/371) and back-compat was
+relaxed in [PR #559](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/559), servers
+and clients have implemented divergent interpretations of how `content` and `structuredContent`
+should be used:
+
+- Clients disagree on which field to pass to models, with some preferring `content`, others
+ preferring `structuredContent`, and some forwarding both.
+- Server authors have returned different semantic information in each field, causing inconsistent
+ behavior across clients.
+- Tool authors receive mixed guidance, including specification text and inspector checks that
+ reflect the prior recommendation that `content` contain a JSON-serialized copy of
+ `structuredContent`.
+
+The official MCP Apps extension
+(https://blog.modelcontextprotocol.io/posts/2026-01-26-mcp-apps/) makes the ambiguity more
+urgent. Tools can now return interactive UIs and richer data for hosts to render. Without explicit
+guidance, model context can be flooded with UI-oriented data or the UI can lack a reliable
+structured payload. The ext-apps issue
+[#380](https://github.com/modelcontextprotocol/ext-apps/issues/380) and related client issues (for
+example, [python-sdk #1796](https://github.com/modelcontextprotocol/python-sdk/issues/1796) and
+[vscode #290063](https://github.com/microsoft/vscode/issues/290063)) highlight persistent confusion
+about what is model-visible and what is host-only.
+
+Several SDK issues are also currently blocked on this clarification, including
+[typescript-sdk #911](https://github.com/modelcontextprotocol/typescript-sdk/issues/911),
+[python-sdk #1332](https://github.com/modelcontextprotocol/python-sdk/issues/1332),
+[csharp-sdk #747](https://github.com/modelcontextprotocol/csharp-sdk/issues/747), and
+[csharp-sdk #930](https://github.com/modelcontextprotocol/csharp-sdk/issues/930).
+
+The MCP Inspector check that expects `content` to JSON-stringify `structuredContent` is tracked in
+[inspector #1089](https://github.com/modelcontextprotocol/inspector/issues/1089). That behavior
+followed the pre-existing specification guidance; this SEP proposes changing that guidance.
+
+This SEP proposes updated guidance from issue #1624 and related discussions: `content` is the
+model-facing representation, `structuredContent` is for programmatic or UI use, and clients should
+choose the appropriate field for their use case rather than forwarding both verbatim.
+
+## Specification
+
+This SEP proposes the following updates to the MCP specification (draft):
+
+1. **Tool result audiences**
+ - `content` is the model-oriented representation of a tool result, optimized for readability
+ and token efficiency. It is the default field to pass into model context for conversational
+ and agent experiences.
+ - `structuredContent` is the machine-oriented representation for programmatic use, code
+ generation, typed orchestration, and UI hydration (including MCP Apps).
+
+2. **Semantic alignment**
+ - When both `content` and `structuredContent` are present, they SHOULD be semantically
+ equivalent (same information, different presentation). `content` may summarize or
+ textualize `structuredContent` without listing every field verbatim, but it SHOULD NOT
+ contradict it.
+ - For backwards compatibility, tools that return `structuredContent` SHOULD also return a
+ `content` representation of the same information. JSON-serialized text is acceptable, but
+ not required and may be suboptimal depending on the use case.
+
+3. **Client selection guidance**
+ - Clients SHOULD choose the field that best matches their experience:
+ - Conversational/agent UX: prefer `content`.
+ - Programmatic/code mode: prefer `structuredContent`.
+ - When providing tool results to a model context, clients SHOULD use `content` and only fall
+ back to `structuredContent` if `content` is empty.
+ - For programmatic/code mode, clients SHOULD use `structuredContent` when present and MAY fall
+ back to `content` if `structuredContent` is absent.
+ - Clients SHOULD NOT forward both fields verbatim to the model as separate inputs.
+
+4. **MCP Apps and model visibility**
+ - For MCP Apps hosts, `content` is the model-visible summary, while `structuredContent` and
+ `_meta` are typically used for UI rendering or host-specific metadata. Model visibility is
+ ultimately client-controlled; `_meta` should be treated as host-only metadata unless a
+ client explicitly exposes it.
+ - Apps can update model context explicitly using the MCP Apps API (e.g., `ui/update-model-context`).
+ - Example pattern: for a tool that renders an interactive view, `content` can be a concise
+ model-facing summary such as "A view was displayed for item 123, and the user can now
+ interact with it," while detailed UI state can remain in `structuredContent` or `_meta`.
+ - Implementers SHOULD ensure `content` still includes the pertinent result information the
+ model needs, even when the format is more concise or tailored for model use than for
+ populating UI controls.
+
+5. **Output schema documentation**
+ - The output schema section should emphasize that `outputSchema` applies to
+ `structuredContent`, while `content` remains a model-oriented representation.
+
+6. **Error results (`isError: true`)**
+ - When a tool call results in an error (`isError: true`), the error message SHOULD be
+ returned in `content`.
+ - Servers MAY omit `structuredContent` for error results, since the error is unlikely to
+ conform to the tool's `outputSchema`.
+ - Clients SHOULD NOT validate `structuredContent` against `outputSchema` when `isError` is
+ `true`.
+
+## Rationale
+
+This proposal adopts a clearer separation between model-facing and machine-facing tool result
+representations in response to how MCP Apps and related integrations are being built in practice.
+Historically, the protocol evolved from an initial design where `structuredContent` and `content`
+were more tightly coupled, and the current specification text preserved a compatibility-oriented
+duplication pattern. This SEP intentionally changes that guidance toward semantically aligned but
+presentation-specific outputs. It resolves cross-client inconsistencies and prevents the same tool
+result from being interpreted differently depending on which field a client prefers.
+
+With MCP Apps now official, clarifying model visibility is essential. UI hosts need a reliable,
+structured payload for rendering, while models benefit from concise summaries rather than raw UI
+data. Explicit guidance reduces token waste, improves context quality, and avoids inadvertent
+exposure of UI-only data to the model.
+
+Alternatives such as introducing new audience annotations or side-channel fields were considered
+but rejected for this SEP due to higher complexity and breaking-change risk. The goal is to revise
+guidance for existing fields without adding new protocol surface area.
+
+## Backward Compatibility
+
+This SEP does not change the protocol wire format or field types, so existing servers and clients
+remain schema-compatible. However, it does change the normative guidance for what servers are
+expected to return in `content` when `structuredContent` is present. Implementations that treated
+`content` as if it were always a JSON-serialized copy of `structuredContent`—an assumption made in
+some tooling and implementations, but not a universally safe one in practice—may need to be
+updated to handle model-optimized representations that remain semantically aligned without being
+structurally identical. Implementations that already return only `structuredContent` or only
+`content` continue to be allowed, though tool authors are encouraged to provide both when feasible
+for maximum compatibility.
+
+## Security Implications
+
+Clarifying model visibility reduces accidental leakage of large or sensitive UI data into model
+context. No new protocol features or attack surfaces are introduced.
+
+## Reference Implementation
+
+This SEP is implemented through documentation updates in the specification. SDK and inspector
+updates are expected to follow but are not required for adoption.
+
+## Alternatives Considered
+
+- **Extending audience annotations**: the existing audience annotation on content blocks provides
+ per-item visibility hints, but does not address the top-level distinction between `content` and
+ `structuredContent` as fields with different intended consumers. Extending audience annotations
+ to cover that distinction was considered but would add complexity without resolving the
+ fundamental question of which field clients should prefer for model context.
+- **Deprecating one field**: would break existing implementations.
+- **Treating `structuredContent` as a purely host-only side channel**: would conflict with
+ programmatic/code-mode use cases that benefit from structured model inputs.
+
+## Open Questions
+
+- Should future extensions define explicit audience selectors (model/host/user) for tool results?
+- Should empirical benchmarks on model performance with structured vs unstructured tool outputs be
+ published to guide best practices?
diff --git a/docs/seps/index.mdx b/docs/seps/index.mdx
index ad95db3bc..8cac55fab 100644
--- a/docs/seps/index.mdx
+++ b/docs/seps/index.mdx
@@ -14,6 +14,7 @@ Specification Enhancement Proposals (SEPs) are the primary mechanism for proposi
- **Accepted**: 2
- **Final**: 28
+- **Draft**: 1
## All SEPs
@@ -22,6 +23,7 @@ Specification Enhancement Proposals (SEPs) are the primary mechanism for proposi
| [SEP-2260](/seps/2260-Require-Server-requests-to-be-associated-with-Client-requests) | Require Server requests to be associated with a Client request. | Accepted | Standards Track | 2026-02-16 |
| [SEP-2243](/seps/2243-http-standardization) | HTTP Header Standardization for Streamable HTTP Transport | Final | Standards Track | 2026-02-04 |
| [SEP-2207](/seps/2207-oidc-refresh-token-guidance) | OIDC-Flavored Refresh Token Guidance | Accepted | Standards Track | 2026-02-04 |
+| [SEP-2200](/seps/2200-clarify-tool-result-content-visibility) | Clarify Tool Result Content and Model Visibility | Draft | Standards Track | 2026-02-03 |
| [SEP-2149](/seps/2149-working-group-charter-template) | MCP Group Governance and Charter Template | Final | Process | 2025-01-15 |
| [SEP-2148](/seps/2148-contributor-ladder) | MCP Contributor Ladder | Final | Process | 2026-01-15 |
| [SEP-2133](/seps/2133-extensions) | Extensions | Final | Standards Track | 2025-01-21 |
diff --git a/docs/specification/draft/changelog.mdx b/docs/specification/draft/changelog.mdx
index d7599580a..84b06fa29 100644
--- a/docs/specification/draft/changelog.mdx
+++ b/docs/specification/draft/changelog.mdx
@@ -17,6 +17,7 @@ N/A
2. Document OpenTelemetry trace context propagation conventions for `_meta` keys (`traceparent`, `tracestate`, `baggage`) ([SEP-414](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/414)).
3. Servers **SHOULD** return tools from `tools/list` in a deterministic order to enable client-side caching and improve LLM prompt cache hit rates.
4. Require standard MCP request headers (`Mcp-Method`, `Mcp-Name`) on Streamable HTTP POST requests, and add support for custom headers from tool parameters via `x-mcp-header` ([SEP-2243](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2243)).
+5. Clarify the intended audiences for `content` and `structuredContent` in tool results, including model visibility, fallback behavior, and `outputSchema` validation for non-error results ([SEP-2200](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2200)).
## Other schema changes
diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx
index 988b0d656..523c3fcb5 100644
--- a/docs/specification/draft/schema.mdx
+++ b/docs/specification/draft/schema.mdx
@@ -1394,8 +1394,8 @@ means intelligence is the most important factor.
### `ToolResultContent`
-
If true, the content typically describes the error that occurred.
Default: false
_meta?: MetaObject
Optional metadata about the tool result. Clients SHOULD preserve this field when
including tool results in subsequent sampling requests to enable caching optimizations.
@@ -1444,7 +1444,12 @@ for task augmentation of specific request types in their capabilities. interfaceCallToolResult{ _meta?:MetaObject; content:ContentBlock[]; structuredContent?:{[key:string]:unknown}; isError?:boolean; [key:string]:unknown; }
The result returned by the server for a tools/call request.
Example: Result with unstructured text
{ "content": [ { "type": "text", "text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy" } ], "isError": false }
{ "content": [ { "type": "text", "text": "Invalid departure date: must be in the future. Current date is 08/08/2025." } ], "isError": true }
_meta?: MetaObject
content: ContentBlock[]
A list of content objects that represent the model-oriented result of the tool call.
Clients SHOULD use this field when providing tool results to conversational or agentic model
+context.
structuredContent?: { [key: string]: unknown }
An optional JSON object that represents the structured, machine-oriented result of the tool
+call.
When both this field and CallToolResult.content are present, they SHOULD be
+semantically equivalent. For backwards compatibility, tools that return structured content
+SHOULD also return a content representation of the same information. JSON-serialized text is
+acceptable, but not required.
isError?: boolean
Whether the tool call ended in an error.
If not set, this is assumed to be false (the call was successful).
Any errors that originate from the tool SHOULD be reported inside the result
object, with isError set to true, not as an MCP protocol-level error
response. Otherwise, the LLM would not be able to see that an error occurred
and self-correct.
However, any errors in finding the tool, an error indicating that the
@@ -1489,7 +1494,7 @@ If present, there may be more results available.
description?: string
A human-readable description of the tool.
This can be used by clients to improve the LLM's understanding of available tools. It can be thought of like a "hint" to the model.
An optional JSON Schema object defining the structure of the tool's output returned in
-the structuredContent field of a CallToolResult.
Defaults to JSON Schema 2020-12 when no explicit $schema is provided.
+the structuredContent field of a CallToolResult.
This schema applies to structuredContent and does not constrain the format of CallToolResult.content.
Defaults to JSON Schema 2020-12 when no explicit $schema is provided.
Currently restricted to type: "object" at the root level.
annotations?: ToolAnnotations
Optional additional tool information.
Display name precedence order is: title, annotations.title, then name.
_meta?: MetaObject
diff --git a/docs/specification/draft/server/tools.mdx b/docs/specification/draft/server/tools.mdx
index c05a961b2..a61b72268 100644
--- a/docs/specification/draft/server/tools.mdx
+++ b/docs/specification/draft/server/tools.mdx
@@ -315,9 +315,9 @@ PII) with `x-mcp-header`, as header values are visible to network intermediaries
### Tool Result
-Tool results may contain [**structured**](#structured-content) or **unstructured** content.
-
-**Unstructured** content is returned in the `content` field of a result, and can contain multiple content items of different types:
+Tool results always include `content`, a list of content blocks that can contain multiple content
+items of different types. `content` is the model-oriented representation of the result. Tool
+results may also include [`structuredContent`](#structured-content) for machine-oriented consumers.
All content types (text, image, audio, resource links, and embedded resources)
@@ -407,18 +407,46 @@ Embedded resources support the same [Resource annotations](/specification/draft/
#### Structured Content
-**Structured** content is returned as a JSON object in the `structuredContent` field of a result.
+Tool results can include both a model-oriented representation and a machine-oriented representation:
+
+- `content` is the model-oriented representation of the result. Clients **SHOULD** use this field
+ when providing tool results to conversational or agentic model context.
+- `structuredContent` is the machine-oriented representation of the same result for programmatic
+ consumers, typed orchestration, and UI hydration.
+
+When both `content` and `structuredContent` are present, they **SHOULD** be semantically
+equivalent. `content` may summarize or textualize `structuredContent` without reproducing every
+field verbatim, but it **SHOULD NOT** contradict it.
+
+For backwards compatibility, a tool that returns structured content **SHOULD** also return a
+`content` representation of the same information. JSON-serialized text is acceptable, but it is
+not required and may be suboptimal depending on the use case.
+
+Clients providing tool results to conversational or agentic model context **SHOULD** use `content`.
+If `content` is empty, clients **MAY** fall back to `structuredContent`.
-For backwards compatibility, a tool that returns structured content SHOULD also return the serialized JSON in a TextContent block.
+Clients using tool results for programmatic, code, typed orchestration, or UI hydration workflows
+**SHOULD** use `structuredContent` when present. If `structuredContent` is absent, clients **MAY**
+fall back to `content`.
+
+Clients **SHOULD NOT** forward both fields verbatim to the model as separate inputs.
+
+When `isError` is `true`, the error message **SHOULD** be returned in `content`. Servers **MAY**
+omit `structuredContent` for error results.
#### Output Schema
-Tools may also provide an output schema for validation of structured results.
-If an output schema is provided:
+Tools may also provide an output schema for validation of `structuredContent`. This schema applies
+to the structured, machine-oriented representation and does not constrain the format of `content`.
+
+If an output schema is provided and the result is not an error:
- Servers **MUST** provide structured results that conform to this schema.
- Clients **SHOULD** validate structured results against this schema.
+Clients **SHOULD NOT** validate `structuredContent` against `outputSchema` when `isError` is
+`true`.
+
Example tool with output schema:
```json
@@ -467,7 +495,7 @@ Example valid response for this tool:
"content": [
{
"type": "text",
- "text": "{\"temperature\": 22.5, \"conditions\": \"Partly cloudy\", \"humidity\": 65}"
+ "text": "Current weather: 22.5C, partly cloudy, 65% humidity."
}
],
"structuredContent": {
diff --git a/schema/draft/examples/CallToolResult/result-with-structured-content.json b/schema/draft/examples/CallToolResult/result-with-structured-content.json
index b398586ca..b4c00ee21 100644
--- a/schema/draft/examples/CallToolResult/result-with-structured-content.json
+++ b/schema/draft/examples/CallToolResult/result-with-structured-content.json
@@ -2,7 +2,7 @@
"content": [
{
"type": "text",
- "text": "{\"temperature\": 22.5, \"conditions\": \"Partly cloudy\", \"humidity\": 65}"
+ "text": "Current weather: 22.5C, partly cloudy, 65% humidity."
}
],
"structuredContent": {
diff --git a/schema/draft/schema.json b/schema/draft/schema.json
index 83997a14e..407ce7bfc 100644
--- a/schema/draft/schema.json
+++ b/schema/draft/schema.json
@@ -177,7 +177,7 @@
"$ref": "#/$defs/MetaObject"
},
"content": {
- "description": "A list of content objects that represent the unstructured result of the tool call.",
+ "description": "A list of content objects that represent the model-oriented result of the tool call.\n\nClients SHOULD use this field when providing tool results to conversational or agentic model\ncontext.",
"items": {
"$ref": "#/$defs/ContentBlock"
},
@@ -189,7 +189,7 @@
},
"structuredContent": {
"additionalProperties": {},
- "description": "An optional JSON object that represents the structured result of the tool call.",
+ "description": "An optional JSON object that represents the structured, machine-oriented result of the tool\ncall.\n\nWhen both this field and {@link CallToolResult.content} are present, they SHOULD be\nsemantically equivalent. For backwards compatibility, tools that return structured content\nSHOULD also return a `content` representation of the same information. JSON-serialized text is\nacceptable, but not required.",
"type": "object"
}
},
@@ -4048,7 +4048,7 @@
"type": "string"
},
"outputSchema": {
- "description": "An optional JSON Schema object defining the structure of the tool's output returned in\nthe structuredContent field of a {@link CallToolResult}.\n\nDefaults to JSON Schema 2020-12 when no explicit `$schema` is provided.\nCurrently restricted to `type: \"object\"` at the root level.",
+ "description": "An optional JSON Schema object defining the structure of the tool's output returned in\nthe structuredContent field of a {@link CallToolResult}.\n\nThis schema applies to structuredContent and does not constrain the format of\n{@link CallToolResult.content}.\n\nDefaults to JSON Schema 2020-12 when no explicit `$schema` is provided.\nCurrently restricted to `type: \"object\"` at the root level.",
"properties": {
"$schema": {
"type": "string"
@@ -4171,7 +4171,7 @@
"description": "Optional metadata about the tool result. Clients SHOULD preserve this field when\nincluding tool results in subsequent sampling requests to enable caching optimizations."
},
"content": {
- "description": "The unstructured result content of the tool use.\n\nThis has the same format as {@link CallToolResult.content} and can include text, images,\naudio, resource links, and embedded resources.",
+ "description": "The model-oriented result content of the tool use.\n\nThis has the same format as {@link CallToolResult.content} and can include text, images,\naudio, resource links, and embedded resources.",
"items": {
"$ref": "#/$defs/ContentBlock"
},
@@ -4183,7 +4183,7 @@
},
"structuredContent": {
"additionalProperties": {},
- "description": "An optional structured result object.\n\nIf the tool defined an {@link Tool.outputSchema}, this SHOULD conform to that schema.",
+ "description": "An optional structured, machine-oriented result object.\n\nIf the tool defined an {@link Tool.outputSchema}, this SHOULD conform to that schema unless\n{@link ToolResultContent.isError} is true.",
"type": "object"
},
"toolUseId": {
diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts
index 29a6cecf6..d2f72c104 100644
--- a/schema/draft/schema.ts
+++ b/schema/draft/schema.ts
@@ -1548,12 +1548,21 @@ export interface ListToolsResultResponse extends JSONRPCResultResponse {
*/
export interface CallToolResult extends Result {
/**
- * A list of content objects that represent the unstructured result of the tool call.
+ * A list of content objects that represent the model-oriented result of the tool call.
+ *
+ * Clients SHOULD use this field when providing tool results to conversational or agentic model
+ * context.
*/
content: ContentBlock[];
/**
- * An optional JSON object that represents the structured result of the tool call.
+ * An optional JSON object that represents the structured, machine-oriented result of the tool
+ * call.
+ *
+ * When both this field and {@link CallToolResult.content} are present, they SHOULD be
+ * semantically equivalent. For backwards compatibility, tools that return structured content
+ * SHOULD also return a `content` representation of the same information. JSON-serialized text is
+ * acceptable, but not required.
*/
structuredContent?: { [key: string]: unknown };
@@ -1754,6 +1763,9 @@ export interface Tool extends BaseMetadata, Icons {
* An optional JSON Schema object defining the structure of the tool's output returned in
* the structuredContent field of a {@link CallToolResult}.
*
+ * This schema applies to structuredContent and does not constrain the format of
+ * {@link CallToolResult.content}.
+ *
* Defaults to JSON Schema 2020-12 when no explicit `$schema` is provided.
* Currently restricted to `type: "object"` at the root level.
*/
@@ -2467,7 +2479,7 @@ export interface ToolResultContent {
toolUseId: string;
/**
- * The unstructured result content of the tool use.
+ * The model-oriented result content of the tool use.
*
* This has the same format as {@link CallToolResult.content} and can include text, images,
* audio, resource links, and embedded resources.
@@ -2475,9 +2487,10 @@ export interface ToolResultContent {
content: ContentBlock[];
/**
- * An optional structured result object.
+ * An optional structured, machine-oriented result object.
*
- * If the tool defined an {@link Tool.outputSchema}, this SHOULD conform to that schema.
+ * If the tool defined an {@link Tool.outputSchema}, this SHOULD conform to that schema unless
+ * {@link ToolResultContent.isError} is true.
*/
structuredContent?: { [key: string]: unknown };
diff --git a/seps/2200-clarify-tool-result-content-visibility.md b/seps/2200-clarify-tool-result-content-visibility.md
new file mode 100644
index 000000000..8da0af310
--- /dev/null
+++ b/seps/2200-clarify-tool-result-content-visibility.md
@@ -0,0 +1,176 @@
+# SEP-2200: Clarify Tool Result Content and Model Visibility
+
+- **Status**: Draft
+- **Type**: Standards Track
+- **Created**: 2026-02-03
+- **Author(s)**: Kyle Rubenok (@krubenok)
+- **Sponsor**: Ola Hungerford (@olaservo)
+- **PR**: https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2200
+- **Related Issues**: [#1624](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1624), [#1411](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1411), [ext-apps #380](https://github.com/modelcontextprotocol/ext-apps/issues/380), [inspector #1089](https://github.com/modelcontextprotocol/inspector/issues/1089)
+
+## Abstract
+
+This SEP updates the intended usage and model visibility of `CallToolResult.content` and
+`CallToolResult.structuredContent`. It formalizes the distinction between model-oriented output
+(`content`) and machine-oriented output (`structuredContent`), provides guidance on semantic
+alignment when both fields are present, and clarifies client behavior for selecting which field to
+expose to models. The change is especially important now that MCP Apps is an official extension,
+where tool results may drive interactive UI experiences and should not inadvertently flood model
+context. This SEP does not change the protocol wire format or field types, but it does change the
+normative guidance for what servers are expected to return in `content` when `structuredContent`
+is present. Implementations that treated `content` as if it were always a JSON-serialized copy of
+`structuredContent`—an assumption made in some tooling and implementations, but not a universally
+safe one in practice—may need to be updated.
+
+## Motivation
+
+Since `structuredContent` was introduced in
+[PR #371](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/371) and back-compat was
+relaxed in [PR #559](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/559), servers
+and clients have implemented divergent interpretations of how `content` and `structuredContent`
+should be used:
+
+- Clients disagree on which field to pass to models, with some preferring `content`, others
+ preferring `structuredContent`, and some forwarding both.
+- Server authors have returned different semantic information in each field, causing inconsistent
+ behavior across clients.
+- Tool authors receive mixed guidance, including specification text and inspector checks that
+ reflect the prior recommendation that `content` contain a JSON-serialized copy of
+ `structuredContent`.
+
+The official MCP Apps extension
+(https://blog.modelcontextprotocol.io/posts/2026-01-26-mcp-apps/) makes the ambiguity more
+urgent. Tools can now return interactive UIs and richer data for hosts to render. Without explicit
+guidance, model context can be flooded with UI-oriented data or the UI can lack a reliable
+structured payload. The ext-apps issue
+[#380](https://github.com/modelcontextprotocol/ext-apps/issues/380) and related client issues (for
+example, [python-sdk #1796](https://github.com/modelcontextprotocol/python-sdk/issues/1796) and
+[vscode #290063](https://github.com/microsoft/vscode/issues/290063)) highlight persistent confusion
+about what is model-visible and what is host-only.
+
+Several SDK issues are also currently blocked on this clarification, including
+[typescript-sdk #911](https://github.com/modelcontextprotocol/typescript-sdk/issues/911),
+[python-sdk #1332](https://github.com/modelcontextprotocol/python-sdk/issues/1332),
+[csharp-sdk #747](https://github.com/modelcontextprotocol/csharp-sdk/issues/747), and
+[csharp-sdk #930](https://github.com/modelcontextprotocol/csharp-sdk/issues/930).
+
+The MCP Inspector check that expects `content` to JSON-stringify `structuredContent` is tracked in
+[inspector #1089](https://github.com/modelcontextprotocol/inspector/issues/1089). That behavior
+followed the pre-existing specification guidance; this SEP proposes changing that guidance.
+
+This SEP proposes updated guidance from issue #1624 and related discussions: `content` is the
+model-facing representation, `structuredContent` is for programmatic or UI use, and clients should
+choose the appropriate field for their use case rather than forwarding both verbatim.
+
+## Specification
+
+This SEP proposes the following updates to the MCP specification (draft):
+
+1. **Tool result audiences**
+ - `content` is the model-oriented representation of a tool result, optimized for readability
+ and token efficiency. It is the default field to pass into model context for conversational
+ and agent experiences.
+ - `structuredContent` is the machine-oriented representation for programmatic use, code
+ generation, typed orchestration, and UI hydration (including MCP Apps).
+
+2. **Semantic alignment**
+ - When both `content` and `structuredContent` are present, they SHOULD be semantically
+ equivalent (same information, different presentation). `content` may summarize or
+ textualize `structuredContent` without listing every field verbatim, but it SHOULD NOT
+ contradict it.
+ - For backwards compatibility, tools that return `structuredContent` SHOULD also return a
+ `content` representation of the same information. JSON-serialized text is acceptable, but
+ not required and may be suboptimal depending on the use case.
+
+3. **Client selection guidance**
+ - Clients SHOULD choose the field that best matches their experience:
+ - Conversational/agent UX: prefer `content`.
+ - Programmatic/code mode: prefer `structuredContent`.
+ - When providing tool results to a model context, clients SHOULD use `content` and only fall
+ back to `structuredContent` if `content` is empty.
+ - For programmatic/code mode, clients SHOULD use `structuredContent` when present and MAY fall
+ back to `content` if `structuredContent` is absent.
+ - Clients SHOULD NOT forward both fields verbatim to the model as separate inputs.
+
+4. **MCP Apps and model visibility**
+ - For MCP Apps hosts, `content` is the model-visible summary, while `structuredContent` and
+ `_meta` are typically used for UI rendering or host-specific metadata. Model visibility is
+ ultimately client-controlled; `_meta` should be treated as host-only metadata unless a
+ client explicitly exposes it.
+ - Apps can update model context explicitly using the MCP Apps API (e.g., `ui/update-model-context`).
+ - Example pattern: for a tool that renders an interactive view, `content` can be a concise
+ model-facing summary such as "A view was displayed for item 123, and the user can now
+ interact with it," while detailed UI state can remain in `structuredContent` or `_meta`.
+ - Implementers SHOULD ensure `content` still includes the pertinent result information the
+ model needs, even when the format is more concise or tailored for model use than for
+ populating UI controls.
+
+5. **Output schema documentation**
+ - The output schema section should emphasize that `outputSchema` applies to
+ `structuredContent`, while `content` remains a model-oriented representation.
+
+6. **Error results (`isError: true`)**
+ - When a tool call results in an error (`isError: true`), the error message SHOULD be
+ returned in `content`.
+ - Servers MAY omit `structuredContent` for error results, since the error is unlikely to
+ conform to the tool's `outputSchema`.
+ - Clients SHOULD NOT validate `structuredContent` against `outputSchema` when `isError` is
+ `true`.
+
+## Rationale
+
+This proposal adopts a clearer separation between model-facing and machine-facing tool result
+representations in response to how MCP Apps and related integrations are being built in practice.
+Historically, the protocol evolved from an initial design where `structuredContent` and `content`
+were more tightly coupled, and the current specification text preserved a compatibility-oriented
+duplication pattern. This SEP intentionally changes that guidance toward semantically aligned but
+presentation-specific outputs. It resolves cross-client inconsistencies and prevents the same tool
+result from being interpreted differently depending on which field a client prefers.
+
+With MCP Apps now official, clarifying model visibility is essential. UI hosts need a reliable,
+structured payload for rendering, while models benefit from concise summaries rather than raw UI
+data. Explicit guidance reduces token waste, improves context quality, and avoids inadvertent
+exposure of UI-only data to the model.
+
+Alternatives such as introducing new audience annotations or side-channel fields were considered
+but rejected for this SEP due to higher complexity and breaking-change risk. The goal is to revise
+guidance for existing fields without adding new protocol surface area.
+
+## Backward Compatibility
+
+This SEP does not change the protocol wire format or field types, so existing servers and clients
+remain schema-compatible. However, it does change the normative guidance for what servers are
+expected to return in `content` when `structuredContent` is present. Implementations that treated
+`content` as if it were always a JSON-serialized copy of `structuredContent`—an assumption made in
+some tooling and implementations, but not a universally safe one in practice—may need to be
+updated to handle model-optimized representations that remain semantically aligned without being
+structurally identical. Implementations that already return only `structuredContent` or only
+`content` continue to be allowed, though tool authors are encouraged to provide both when feasible
+for maximum compatibility.
+
+## Security Implications
+
+Clarifying model visibility reduces accidental leakage of large or sensitive UI data into model
+context. No new protocol features or attack surfaces are introduced.
+
+## Reference Implementation
+
+This SEP is implemented through documentation updates in the specification. SDK and inspector
+updates are expected to follow but are not required for adoption.
+
+## Alternatives Considered
+
+- **Extending audience annotations**: the existing audience annotation on content blocks provides
+ per-item visibility hints, but does not address the top-level distinction between `content` and
+ `structuredContent` as fields with different intended consumers. Extending audience annotations
+ to cover that distinction was considered but would add complexity without resolving the
+ fundamental question of which field clients should prefer for model context.
+- **Deprecating one field**: would break existing implementations.
+- **Treating `structuredContent` as a purely host-only side channel**: would conflict with
+ programmatic/code-mode use cases that benefit from structured model inputs.
+
+## Open Questions
+
+- Should future extensions define explicit audience selectors (model/host/user) for tool results?
+- Should empirical benchmarks on model performance with structured vs unstructured tool outputs be
+ published to guide best practices?
The result of a tool use, provided by the user back to the assistant.