Source Intelligence
Sweep 28 Aug 2026 · 00:00Z Build v2.1.250 478 read Stable v2.1.236 Latest v2.1.250 Next v2.1.250 Feeds RSS JSON llms.txt

DisclaimerUnofficial, and not affiliated with Anthropic. Nearly all of this is read straight out of what ships: npm bundles, captured prompts, published docs. Anthropic's own notes go in verbatim, marked as theirs. The rest is my reading, and every entry carries the strings behind it. If one looks wrong, vote it down and say why.

Page history

SEP-2106: Tools `inputSchema` & `outputSchema` Conform to JSON Schema 2020-12

seps/2106-json-schema-2020-12

1 recorded change 434 lines First seen Last changed Upstream

History

seps/2106-json-schema-2020-12 First recorded · 434 lines, first recorded

# SEP-2106: Tools `inputSchema` & `outputSchema` Conform to JSON Schema 2020-12 ## Abstract ## Motivation ### Real-World Impact ### Schema Composition Use Cases ## Specification ### 1. Loosen inputSchema ### 2. Loosen outputSchema ### 3. Loosen structuredContent ### 4. Documentation Updates ### 5. Examples #### Tool returning an array of objects: #### Tool with composition schema: ## Rationale ### Why not just allow arrays? ### Why not require a wrapper object? ### Real-World API Patterns ### Alignment with JSON Schema 2020-12 ### SDK Ecosystem Evidence ### OpenAPI Precedent ## Backward Compatibility ### Compatibility Matrix ### TypeScript / SDK Migration ### Migration Path ## Security Implications ### `$ref` Dereferencing (SSRF and Fetch-DoS) ### Composition-Keyword Resource Use ## Reference Implementation ### TypeScript SDK ### Everything Server Demo Tools ### Related Links ### Implementation Guidance ## Acknowledgments

The first capture of this source. The page was already there, and this is what it said.

# SEP-2106: Tools `inputSchema` & `outputSchema` Conform to JSON Schema 2020-12

> Tools `inputSchema` & `outputSchema` Conform to JSON Schema 2020-12

<div className="flex items-center gap-2 mb-4">
  <Badge color="green" shape="pill">
    Final
  </Badge>

  <Badge color="gray" shape="pill">
    Standards Track
  </Badge>
</div>

<Note>
  This SEP has reached Final status and is preserved as a historical record of
  the design as accepted. Changes made to the protocol after finalization are
  not reflected here. Refer to the [current
  specification](/specification/latest) and its changelog for authoritative
  requirements.
</Note>

| Field         | Value                                                                                                                                                                         |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **SEP**       | 2106                                                                                                                                                                          |
| **Title**     | Tools `inputSchema` & `outputSchema` Conform to JSON Schema 2020-12                                                                                                           |
| **Status**    | Final                                                                                                                                                                         |
| **Type**      | Standards Track                                                                                                                                                               |
| **Created**   | 2026-01-06                                                                                                                                                                    |
| **Author(s)** | John McBride ([@jpmcb](https://github.com/jpmcb)) — original proposal; Ola Hungerford ([@olaservo](https://github.com/olaservo)) — current shepherd, post-SEP-1850 conversion |
| **Sponsor**   | Ola Hungerford ([@olaservo](https://github.com/olaservo))                                                                                                                     |
| **PR**        | [#2106](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2106)                                                                                               |

***

## Abstract

This SEP proposes loosening the restrictions on `inputSchema`, `outputSchema`, and `structuredContent` to better support JSON Schema 2020-12. Specifically:

* **`inputSchema`**: Keeps `type: "object"` required (since tool arguments are objects), but allows any additional JSON Schema properties to support powerful validation compositions (`anyOf`, `oneOf`, `allOf`, etc.)
* **`outputSchema`**: Fully supports JSON Schema 2020-12 since MCP servers may return any valid JSON
* **`structuredContent`**: Accepts any JSON value validated by `outputSchema`

This proposal enables MCP servers to leverage the expressiveness of JSON Schema 2020-12 while maintaining backward compatibility with existing implementations.

## Motivation

The current MCP specification restricts tool schemas in ways that conflict with full JSON Schema support:

1. **inputSchema restriction**: Currently only allows `type`, `properties`, and `required` fields. This prevents use of composition keywords like `anyOf`, `oneOf`, and `allOf` for sophisticated object validation patterns.

2. **outputSchema restriction**: Also restricted to `type: "object"` with only `properties` and `required`, despite the specification claiming to support "JSON Schema."

3. **structuredContent restriction**: Defined as `{ [key: string]: unknown }` (an object with string keys), which prevents returning arrays—a common API response pattern.

### Real-World Impact

Consider a weather API tool that returns hourly forecasts:

```json theme={null}
[
  { "hour": "09:00", "temp": 68, "conditions": "sunny" },
  { "hour": "10:00", "temp": 72, "conditions": "partly cloudy" },
  { "hour": "11:00", "temp": 75, "conditions": "cloudy" }
]
```

Currently, this natural array response is **impossible** because `structuredContent` must be an object. Developers are forced to wrap arrays in unnecessary container objects:

```json theme={null}
{
  "forecasts": [
    { "hour": "09:00", "temp": 68, "conditions": "sunny" },
    ...
  ]
}
```

This artificial constraint:

* Adds unnecessary nesting to responses
* Conflicts with common REST API patterns
* Prevents direct schema validation of array responses

### Schema Composition Use Cases

The current `inputSchema` restriction prevents legitimate schema patterns. With this SEP, tools can use composition keywords alongside `type: "object"`:

```json theme={null}
{
  "type": "object",
  "oneOf": [
    { "properties": { "id": { "type": "string" } }, "required": ["id"] },
    { "properties": { "name": { "type": "string" } }, "required": ["name"] }
  ]
}
```

This pattern allows a tool to accept either an ID-based or name-based lookup—a common API design that is currently unsupported because the schema only allows `type`, `properties`, and `required` fields.

## Specification

### 1. Loosen inputSchema

**Current definition:**

```typescript theme={null}
inputSchema: {
  type: "object";
  properties?: { [key: string]: object };
  required?: string[];
};
```

**Proposed definition:**

```typescript theme={null}
inputSchema: {
  $schema?: string;
  type: "object";
  [key: string]: unknown;
};
```

The `inputSchema` field retains the `type: "object"` requirement (since tool arguments are always objects), but now accepts any additional JSON Schema properties. This enables:

* Composition keywords: `anyOf`, `oneOf`, `allOf`, `not`
* Conditional schemas: `if`/`then`/`else`
* Reference schemas: `$ref`, `$defs`
* Any other valid JSON Schema 2020-12 keywords

### 2. Loosen outputSchema

**Current definition:**

```typescript theme={null}
outputSchema?: {
  type: "object";
  properties?: { [key: string]: object };
  required?: string[];
};
```

**Proposed definition:**

```typescript theme={null}
outputSchema?: {
  $schema?: string;
  [key: string]: unknown;
};
```

The `outputSchema` field accepts any valid JSON Schema 2020-12 object, enabling schemas that validate arrays, primitives, or complex compositions. Unlike `inputSchema`, there is no `type: "object"` requirement since tool outputs can be any valid JSON.

### 3. Loosen structuredContent

**Current definition:**

```typescript theme={null}
structuredContent?: { [key: string]: unknown };
```

**Proposed definition:**

```typescript theme={null}
structuredContent?: unknown;
```

The `structuredContent` field accepts any valid JSON value that conforms to the tool's `outputSchema`. This includes:

* Objects: `{ "key": "value" }`
* Arrays: `[1, 2, 3]` or `[{ "id": "abc" }, { "id": "xyz" }]`
* Primitives: `"string"`, `42`, `true`, `null`

### 4. Documentation Updates

Update `docs/specification/draft/server/tools.mdx`:

* Remove statement that `structuredContent` is "returned as a JSON object"
* Clarify that `structuredContent` can be any JSON value conforming to `outputSchema`
* Add examples demonstrating array responses

### 5. Examples

#### Tool returning an array of objects:

```json theme={null}
{
  "name": "list_users",
  "description": "List all users in the system",
  "inputSchema": {
    "type": "object",
    "properties": {
      "limit": { "type": "integer", "minimum": 1, "maximum": 100 }
    }
  },
  "outputSchema": {
    "type": "array",
    "items": {
      "type": "object",
      "properties": {
        "id": { "type": "string" },
        "name": { "type": "string" },
        "email": { "type": "string", "format": "email" }
      },
      "required": ["id", "name"]
    }
  }
}
```

Response:

```json theme={null}
{
  "content": [
    {
      "type": "text",
      "text": "Found 2 users: Alice (u1, [email protected]) and Bob (u2, [email protected])."
    }
  ],
  "structuredContent": [
    { "id": "u1", "name": "Alice", "email": "[email protected]" },
    { "id": "u2", "name": "Bob", "email": "[email protected]" }
  ]
}
```

#### Tool with composition schema:

```json theme={null}
{
  "name": "find_resource",
  "description": "Find a resource by ID or name",
  "inputSchema": {
    "type": "object",
    "oneOf": [
      {
        "properties": { "id": { "type": "string", "format": "uuid" } },
        "required": ["id"]
      },
      {
        "properties": { "name": { "type": "string", "minLength": 1 } },
        "required": ["name"]
      }
    ]
  }
}
```

## Rationale

### Why not just allow arrays?

While we could simply extend `structuredContent` to allow arrays, this would be an incomplete solution. The root cause is that the schema types are artificially restricted to `type: "object"`. By allowing any valid JSON Schema, we:

1. Enable the full power of JSON Schema 2020-12
2. Align with the specification's claim of JSON Schema support
3. Provide a consistent, principled approach rather than piecemeal fixes

### Why not require a wrapper object?

Requiring arrays to be wrapped in objects (e.g., `{ "items": [...] }`) was considered but rejected because:

1. It adds unnecessary complexity to responses
2. It conflicts with common API design patterns
3. It prevents direct schema validation of the actual response structure
4. JSON Schema already handles array validation elegantly

### Real-World API Patterns

Many production APIs return arrays directly:

* **GitHub Events API**: Returns arrays of event objects
* **AccuWeather Search API**: Returns arrays of location matches
* **REST collection endpoints**: Standard `GET /users` returns `[{...}, {...}]`

Forcing wrapper objects creates friction for developers integrating existing APIs with MCP. Generic JSON Schema validation libraries should work without MCP-specific customization.

### Alignment with JSON Schema 2020-12

JSON Schema 2020-12 provides powerful features for schema composition and validation. By removing artificial restrictions, MCP aligns with industry standards (OpenAPI 3.1 uses JSON Schema 2020-12) and enables developers to leverage existing JSON Schema knowledge and tooling.

### SDK Ecosystem Evidence

The friction caused by current restrictions is not theoretical. FastMCP, one of the most popular Python SDKs for MCP, has implemented extensive workarounds:

1. **Explicit error messages** acknowledge the limitation:

   ```python theme={null}
   raise ValueError(
       f"Output schemas must represent object types due to MCP spec limitations."
   )
   ```

2. **Auto-wrapping infrastructure** adds complexity:
   * A `_WrappedResult` dataclass wraps non-object returns
   * A custom `x-fastmcp-wrap-result` extension enables client-side unwrapping
   * Both SDK and client need matching wrap/unwrap logic

Cut at 300 lines.