SEP-834 Support full JSON Schema 2020-12 #834

Description

@jpmcb

Preamble

Title: Support full JSON Schema 2020-12
Co-author: John McBride - @jpmcb
Co-author: Ola Hungerford - @olaservo (adopted from #655 per #881 (comment))
Status: proposal
PR: #881

Abstract

There's a major discrepancy with how 2025-06-18 handles structuredContent in relation to outputSchema being defined as JSON Schema.

Because structuredContentmust be an object, the types that can be returned by servers and validated by clients (like type: array which is fully supported by JSON Schema but throws errors in Inspector, the Typescript-SDK, etc) is dramatically narrow.

Further, which draft of JSON Schema clients and servers use is not well defined leading to general drift among client, SDK, and server implementations. For example, JSON Schema specs in one client that uses JSON Schema draft-07 will be very different from another that uses 2020-12.

Related:

This SEP loosens JSON schema usage across clients and servers as well as defines using JSON Schema 2020-12

Motivation

In 5.1 Data Types: Tool, the spec states:

outputSchema: Optional JSON Schema defining expected output structure

JSON Schema may be of type object, array, string, null, etc. etc. If it's valid JSON, then JSON Schema can validate it.

But the spec then goes on, in 5.2.6 Structured Content, to state:

Structured content is returned as a JSON object in the structuredContent field of a result.

This represents a dramatic discrepency and severly limits what type of content can be returned by a server and validated in the structured content.

Consider the following valid JSON Schema:

{"type": "array","items": {"type": "object","properties": {"id": {"type": "string","description": "A unique UUID"}},"required": ["id"],"additionalProperties": false}}

which defines an array of objects where the objects must have an id property. This is pretty typical, especially in "list" type of operations.

Now, suppose a server responds with the following JSON as structured content:

[{"id": "abc123"},{"id": "xyz987"}]

The spec would consider this structured content invalid and non-verifiable by the output schema.


Originally, the MCP specification didn't explicitly state which JSON Schema version to use for tool inputSchema/outputSchema and elicitation requestedSchema, causing compatibility issues between implementations. Different clients and servers assume different versions, leading to validation failures and runtime errors. See: https://github.com/orgs/modelcontextprotocol/discussions/366 (discussion includes links to related issues)

(original context before merged with this SEP: #655)

Specification

  • Clarifies JSON Schema dialect usage for embedded schemas within MCP messages by establishing 2020-12 as the default dialect and allowing explicit dialect declaration via the $schema field.
  • Loosens inputSchema to be an object with type: object and any additional property to support JSON schema Draft 2020-12 and more powerful validation compositions (like anyOf, oneOf, etc.)
  • Loosens outputSchema to fully support JSON Schema 2020-12 since MCP servers may return any valid JSON.
    • Loosens structuredContent to support any JSON validated by outputSchema's JSON Schema.

PR: #881

Backward Compatibility

No breaking changes.

Existing schemas without $schema will default to 2020-12. Servers can optionally add $schema to use other dialects.

Object schemas will continue to work as expected while the loosened specification can accept other valid JSON schema (like arrays of objects, etc.)

Rationale

The expectation is that any 2020-12 JSON Schema should be valid for fields that expect JSON schema. This includes outputSchema and structuredContent to be authentically validated by outputSchema, not just expected to always be an object: this is far too strict and narrows how tools can respond in ways that backends may not conform to. Further, 2020-12 has been widely adopted by the industry as the current standard but servers can define the schema they expect via the $schema metadata field.

Reference Implementation

TODO

Security Implications

There are no security implications.

Activity

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

Metadata

Metadata

Assignees

Labels

SEPbugSomething isn't workingin-reviewSEP proposal ready for review.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
     blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
    }
    } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
    })();
    (function(){
    try {
    var __m = "github.com";
    var __re = new RegExp('^' + "github\\.com" + '
    
    Skip to content

    SEP-834 Support full JSON Schema 2020-12 #834

    Description

    @jpmcb

    Preamble

    Title: Support full JSON Schema 2020-12
    Co-author: John McBride - @jpmcb
    Co-author: Ola Hungerford - @olaservo (adopted from #655 per #881 (comment))
    Status: proposal
    PR: #881

    Abstract

    There's a major discrepancy with how 2025-06-18 handles structuredContent in relation to outputSchema being defined as JSON Schema.

    Because structuredContentmust be an object, the types that can be returned by servers and validated by clients (like type: array which is fully supported by JSON Schema but throws errors in Inspector, the Typescript-SDK, etc) is dramatically narrow.

    Further, which draft of JSON Schema clients and servers use is not well defined leading to general drift among client, SDK, and server implementations. For example, JSON Schema specs in one client that uses JSON Schema draft-07 will be very different from another that uses 2020-12.

    Related:

    This SEP loosens JSON schema usage across clients and servers as well as defines using JSON Schema 2020-12

    Motivation

    In 5.1 Data Types: Tool, the spec states:

    outputSchema: Optional JSON Schema defining expected output structure

    JSON Schema may be of type object, array, string, null, etc. etc. If it's valid JSON, then JSON Schema can validate it.

    But the spec then goes on, in 5.2.6 Structured Content, to state:

    Structured content is returned as a JSON object in the structuredContent field of a result.

    This represents a dramatic discrepency and severly limits what type of content can be returned by a server and validated in the structured content.

    Consider the following valid JSON Schema:

    {"type": "array","items": {"type": "object","properties": {"id": {"type": "string","description": "A unique UUID"}},"required": ["id"],"additionalProperties": false}}

    which defines an array of objects where the objects must have an id property. This is pretty typical, especially in "list" type of operations.

    Now, suppose a server responds with the following JSON as structured content:

    [{"id": "abc123"},{"id": "xyz987"}]

    The spec would consider this structured content invalid and non-verifiable by the output schema.


    Originally, the MCP specification didn't explicitly state which JSON Schema version to use for tool inputSchema/outputSchema and elicitation requestedSchema, causing compatibility issues between implementations. Different clients and servers assume different versions, leading to validation failures and runtime errors. See: https://github.com/orgs/modelcontextprotocol/discussions/366 (discussion includes links to related issues)

    (original context before merged with this SEP: #655)

    Specification

    • Clarifies JSON Schema dialect usage for embedded schemas within MCP messages by establishing 2020-12 as the default dialect and allowing explicit dialect declaration via the $schema field.
    • Loosens inputSchema to be an object with type: object and any additional property to support JSON schema Draft 2020-12 and more powerful validation compositions (like anyOf, oneOf, etc.)
    • Loosens outputSchema to fully support JSON Schema 2020-12 since MCP servers may return any valid JSON.
      • Loosens structuredContent to support any JSON validated by outputSchema's JSON Schema.

    PR: #881

    Backward Compatibility

    No breaking changes.

    Existing schemas without $schema will default to 2020-12. Servers can optionally add $schema to use other dialects.

    Object schemas will continue to work as expected while the loosened specification can accept other valid JSON schema (like arrays of objects, etc.)

    Rationale

    The expectation is that any 2020-12 JSON Schema should be valid for fields that expect JSON schema. This includes outputSchema and structuredContent to be authentically validated by outputSchema, not just expected to always be an object: this is far too strict and narrows how tools can respond in ways that backends may not conform to. Further, 2020-12 has been widely adopted by the industry as the current standard but servers can define the schema they expect via the $schema metadata field.

    Reference Implementation

    TODO

    Security Implications

    There are no security implications.

    Activity

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

    Metadata

    Metadata

    Assignees

    Labels

    SEPbugSomething isn't workingin-reviewSEP proposal ready for review.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
      Skip to content

      SEP-834 Support full JSON Schema 2020-12 #834

      Description

      @jpmcb

      Preamble

      Title: Support full JSON Schema 2020-12
      Co-author: John McBride - @jpmcb
      Co-author: Ola Hungerford - @olaservo (adopted from #655 per #881 (comment))
      Status: proposal
      PR: #881

      Abstract

      There's a major discrepancy with how 2025-06-18 handles structuredContent in relation to outputSchema being defined as JSON Schema.

      Because structuredContentmust be an object, the types that can be returned by servers and validated by clients (like type: array which is fully supported by JSON Schema but throws errors in Inspector, the Typescript-SDK, etc) is dramatically narrow.

      Further, which draft of JSON Schema clients and servers use is not well defined leading to general drift among client, SDK, and server implementations. For example, JSON Schema specs in one client that uses JSON Schema draft-07 will be very different from another that uses 2020-12.

      Related:

      This SEP loosens JSON schema usage across clients and servers as well as defines using JSON Schema 2020-12

      Motivation

      In 5.1 Data Types: Tool, the spec states:

      outputSchema: Optional JSON Schema defining expected output structure

      JSON Schema may be of type object, array, string, null, etc. etc. If it's valid JSON, then JSON Schema can validate it.

      But the spec then goes on, in 5.2.6 Structured Content, to state:

      Structured content is returned as a JSON object in the structuredContent field of a result.

      This represents a dramatic discrepency and severly limits what type of content can be returned by a server and validated in the structured content.

      Consider the following valid JSON Schema:

      {"type": "array","items": {"type": "object","properties": {"id": {"type": "string","description": "A unique UUID"}},"required": ["id"],"additionalProperties": false}}

      which defines an array of objects where the objects must have an id property. This is pretty typical, especially in "list" type of operations.

      Now, suppose a server responds with the following JSON as structured content:

      [{"id": "abc123"},{"id": "xyz987"}]

      The spec would consider this structured content invalid and non-verifiable by the output schema.


      Originally, the MCP specification didn't explicitly state which JSON Schema version to use for tool inputSchema/outputSchema and elicitation requestedSchema, causing compatibility issues between implementations. Different clients and servers assume different versions, leading to validation failures and runtime errors. See: https://github.com/orgs/modelcontextprotocol/discussions/366 (discussion includes links to related issues)

      (original context before merged with this SEP: #655)

      Specification

      • Clarifies JSON Schema dialect usage for embedded schemas within MCP messages by establishing 2020-12 as the default dialect and allowing explicit dialect declaration via the $schema field.
      • Loosens inputSchema to be an object with type: object and any additional property to support JSON schema Draft 2020-12 and more powerful validation compositions (like anyOf, oneOf, etc.)
      • Loosens outputSchema to fully support JSON Schema 2020-12 since MCP servers may return any valid JSON.
        • Loosens structuredContent to support any JSON validated by outputSchema's JSON Schema.

      PR: #881

      Backward Compatibility

      No breaking changes.

      Existing schemas without $schema will default to 2020-12. Servers can optionally add $schema to use other dialects.

      Object schemas will continue to work as expected while the loosened specification can accept other valid JSON schema (like arrays of objects, etc.)

      Rationale

      The expectation is that any 2020-12 JSON Schema should be valid for fields that expect JSON schema. This includes outputSchema and structuredContent to be authentically validated by outputSchema, not just expected to always be an object: this is far too strict and narrows how tools can respond in ways that backends may not conform to. Further, 2020-12 has been widely adopted by the industry as the current standard but servers can define the schema they expect via the $schema metadata field.

      Reference Implementation

      TODO

      Security Implications

      There are no security implications.

      Activity

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

      Metadata

      Metadata

      Assignees

      Labels

      SEPbugSomething isn't workingin-reviewSEP proposal ready for review.

      Type

      No type

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions

        , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
        Skip to content

        SEP-834 Support full JSON Schema 2020-12 #834

        Description

        @jpmcb

        Preamble

        Title: Support full JSON Schema 2020-12
        Co-author: John McBride - @jpmcb
        Co-author: Ola Hungerford - @olaservo (adopted from #655 per #881 (comment))
        Status: proposal
        PR: #881

        Abstract

        There's a major discrepancy with how 2025-06-18 handles structuredContent in relation to outputSchema being defined as JSON Schema.

        Because structuredContentmust be an object, the types that can be returned by servers and validated by clients (like type: array which is fully supported by JSON Schema but throws errors in Inspector, the Typescript-SDK, etc) is dramatically narrow.

        Further, which draft of JSON Schema clients and servers use is not well defined leading to general drift among client, SDK, and server implementations. For example, JSON Schema specs in one client that uses JSON Schema draft-07 will be very different from another that uses 2020-12.

        Related:

        This SEP loosens JSON schema usage across clients and servers as well as defines using JSON Schema 2020-12

        Motivation

        In 5.1 Data Types: Tool, the spec states:

        outputSchema: Optional JSON Schema defining expected output structure

        JSON Schema may be of type object, array, string, null, etc. etc. If it's valid JSON, then JSON Schema can validate it.

        But the spec then goes on, in 5.2.6 Structured Content, to state:

        Structured content is returned as a JSON object in the structuredContent field of a result.

        This represents a dramatic discrepency and severly limits what type of content can be returned by a server and validated in the structured content.

        Consider the following valid JSON Schema:

        {"type": "array","items": {"type": "object","properties": {"id": {"type": "string","description": "A unique UUID"}},"required": ["id"],"additionalProperties": false}}

        which defines an array of objects where the objects must have an id property. This is pretty typical, especially in "list" type of operations.

        Now, suppose a server responds with the following JSON as structured content:

        [{"id": "abc123"},{"id": "xyz987"}]

        The spec would consider this structured content invalid and non-verifiable by the output schema.


        Originally, the MCP specification didn't explicitly state which JSON Schema version to use for tool inputSchema/outputSchema and elicitation requestedSchema, causing compatibility issues between implementations. Different clients and servers assume different versions, leading to validation failures and runtime errors. See: https://github.com/orgs/modelcontextprotocol/discussions/366 (discussion includes links to related issues)

        (original context before merged with this SEP: #655)

        Specification

        • Clarifies JSON Schema dialect usage for embedded schemas within MCP messages by establishing 2020-12 as the default dialect and allowing explicit dialect declaration via the $schema field.
        • Loosens inputSchema to be an object with type: object and any additional property to support JSON schema Draft 2020-12 and more powerful validation compositions (like anyOf, oneOf, etc.)
        • Loosens outputSchema to fully support JSON Schema 2020-12 since MCP servers may return any valid JSON.
          • Loosens structuredContent to support any JSON validated by outputSchema's JSON Schema.

        PR: #881

        Backward Compatibility

        No breaking changes.

        Existing schemas without $schema will default to 2020-12. Servers can optionally add $schema to use other dialects.

        Object schemas will continue to work as expected while the loosened specification can accept other valid JSON schema (like arrays of objects, etc.)

        Rationale

        The expectation is that any 2020-12 JSON Schema should be valid for fields that expect JSON schema. This includes outputSchema and structuredContent to be authentically validated by outputSchema, not just expected to always be an object: this is far too strict and narrows how tools can respond in ways that backends may not conform to. Further, 2020-12 has been widely adopted by the industry as the current standard but servers can define the schema they expect via the $schema metadata field.

        Reference Implementation

        TODO

        Security Implications

        There are no security implications.

        Activity

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

        Metadata

        Metadata

        Assignees

        Labels

        SEPbugSomething isn't workingin-reviewSEP proposal ready for review.

        Type

        No type

        Projects

        No projects

          Milestone

          No milestone

          Relationships

          None yet

          Development

          No branches or pull requests

          Issue actions

          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
          Skip to content

          SEP-834 Support full JSON Schema 2020-12 #834

          Description

          @jpmcb

          Preamble

          Title: Support full JSON Schema 2020-12
          Co-author: John McBride - @jpmcb
          Co-author: Ola Hungerford - @olaservo (adopted from #655 per #881 (comment))
          Status: proposal
          PR: #881

          Abstract

          There's a major discrepancy with how 2025-06-18 handles structuredContent in relation to outputSchema being defined as JSON Schema.

          Because structuredContentmust be an object, the types that can be returned by servers and validated by clients (like type: array which is fully supported by JSON Schema but throws errors in Inspector, the Typescript-SDK, etc) is dramatically narrow.

          Further, which draft of JSON Schema clients and servers use is not well defined leading to general drift among client, SDK, and server implementations. For example, JSON Schema specs in one client that uses JSON Schema draft-07 will be very different from another that uses 2020-12.

          Related:

          This SEP loosens JSON schema usage across clients and servers as well as defines using JSON Schema 2020-12

          Motivation

          In 5.1 Data Types: Tool, the spec states:

          outputSchema: Optional JSON Schema defining expected output structure

          JSON Schema may be of type object, array, string, null, etc. etc. If it's valid JSON, then JSON Schema can validate it.

          But the spec then goes on, in 5.2.6 Structured Content, to state:

          Structured content is returned as a JSON object in the structuredContent field of a result.

          This represents a dramatic discrepency and severly limits what type of content can be returned by a server and validated in the structured content.

          Consider the following valid JSON Schema:

          {"type": "array","items": {"type": "object","properties": {"id": {"type": "string","description": "A unique UUID"}},"required": ["id"],"additionalProperties": false}}

          which defines an array of objects where the objects must have an id property. This is pretty typical, especially in "list" type of operations.

          Now, suppose a server responds with the following JSON as structured content:

          [{"id": "abc123"},{"id": "xyz987"}]

          The spec would consider this structured content invalid and non-verifiable by the output schema.


          Originally, the MCP specification didn't explicitly state which JSON Schema version to use for tool inputSchema/outputSchema and elicitation requestedSchema, causing compatibility issues between implementations. Different clients and servers assume different versions, leading to validation failures and runtime errors. See: https://github.com/orgs/modelcontextprotocol/discussions/366 (discussion includes links to related issues)

          (original context before merged with this SEP: #655)

          Specification

          • Clarifies JSON Schema dialect usage for embedded schemas within MCP messages by establishing 2020-12 as the default dialect and allowing explicit dialect declaration via the $schema field.
          • Loosens inputSchema to be an object with type: object and any additional property to support JSON schema Draft 2020-12 and more powerful validation compositions (like anyOf, oneOf, etc.)
          • Loosens outputSchema to fully support JSON Schema 2020-12 since MCP servers may return any valid JSON.
            • Loosens structuredContent to support any JSON validated by outputSchema's JSON Schema.

          PR: #881

          Backward Compatibility

          No breaking changes.

          Existing schemas without $schema will default to 2020-12. Servers can optionally add $schema to use other dialects.

          Object schemas will continue to work as expected while the loosened specification can accept other valid JSON schema (like arrays of objects, etc.)

          Rationale

          The expectation is that any 2020-12 JSON Schema should be valid for fields that expect JSON schema. This includes outputSchema and structuredContent to be authentically validated by outputSchema, not just expected to always be an object: this is far too strict and narrows how tools can respond in ways that backends may not conform to. Further, 2020-12 has been widely adopted by the industry as the current standard but servers can define the schema they expect via the $schema metadata field.

          Reference Implementation

          TODO

          Security Implications

          There are no security implications.

          Activity

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

          Metadata

          Metadata

          Assignees

          Labels

          SEPbugSomething isn't workingin-reviewSEP proposal ready for review.

          Type

          No type

          Projects

          No projects

            Milestone

            No milestone

            Relationships

            None yet

            Development

            No branches or pull requests

            Issue actions

            , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
            Skip to content

            SEP-834 Support full JSON Schema 2020-12 #834

            Description

            @jpmcb

            Preamble

            Title: Support full JSON Schema 2020-12
            Co-author: John McBride - @jpmcb
            Co-author: Ola Hungerford - @olaservo (adopted from #655 per #881 (comment))
            Status: proposal
            PR: #881

            Abstract

            There's a major discrepancy with how 2025-06-18 handles structuredContent in relation to outputSchema being defined as JSON Schema.

            Because structuredContentmust be an object, the types that can be returned by servers and validated by clients (like type: array which is fully supported by JSON Schema but throws errors in Inspector, the Typescript-SDK, etc) is dramatically narrow.

            Further, which draft of JSON Schema clients and servers use is not well defined leading to general drift among client, SDK, and server implementations. For example, JSON Schema specs in one client that uses JSON Schema draft-07 will be very different from another that uses 2020-12.

            Related:

            This SEP loosens JSON schema usage across clients and servers as well as defines using JSON Schema 2020-12

            Motivation

            In 5.1 Data Types: Tool, the spec states:

            outputSchema: Optional JSON Schema defining expected output structure

            JSON Schema may be of type object, array, string, null, etc. etc. If it's valid JSON, then JSON Schema can validate it.

            But the spec then goes on, in 5.2.6 Structured Content, to state:

            Structured content is returned as a JSON object in the structuredContent field of a result.

            This represents a dramatic discrepency and severly limits what type of content can be returned by a server and validated in the structured content.

            Consider the following valid JSON Schema:

            {"type": "array","items": {"type": "object","properties": {"id": {"type": "string","description": "A unique UUID"}},"required": ["id"],"additionalProperties": false}}

            which defines an array of objects where the objects must have an id property. This is pretty typical, especially in "list" type of operations.

            Now, suppose a server responds with the following JSON as structured content:

            [{"id": "abc123"},{"id": "xyz987"}]

            The spec would consider this structured content invalid and non-verifiable by the output schema.


            Originally, the MCP specification didn't explicitly state which JSON Schema version to use for tool inputSchema/outputSchema and elicitation requestedSchema, causing compatibility issues between implementations. Different clients and servers assume different versions, leading to validation failures and runtime errors. See: https://github.com/orgs/modelcontextprotocol/discussions/366 (discussion includes links to related issues)

            (original context before merged with this SEP: #655)

            Specification

            • Clarifies JSON Schema dialect usage for embedded schemas within MCP messages by establishing 2020-12 as the default dialect and allowing explicit dialect declaration via the $schema field.
            • Loosens inputSchema to be an object with type: object and any additional property to support JSON schema Draft 2020-12 and more powerful validation compositions (like anyOf, oneOf, etc.)
            • Loosens outputSchema to fully support JSON Schema 2020-12 since MCP servers may return any valid JSON.
              • Loosens structuredContent to support any JSON validated by outputSchema's JSON Schema.

            PR: #881

            Backward Compatibility

            No breaking changes.

            Existing schemas without $schema will default to 2020-12. Servers can optionally add $schema to use other dialects.

            Object schemas will continue to work as expected while the loosened specification can accept other valid JSON schema (like arrays of objects, etc.)

            Rationale

            The expectation is that any 2020-12 JSON Schema should be valid for fields that expect JSON schema. This includes outputSchema and structuredContent to be authentically validated by outputSchema, not just expected to always be an object: this is far too strict and narrows how tools can respond in ways that backends may not conform to. Further, 2020-12 has been widely adopted by the industry as the current standard but servers can define the schema they expect via the $schema metadata field.

            Reference Implementation

            TODO

            Security Implications

            There are no security implications.

            Activity

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

            Metadata

            Metadata

            Assignees

            Labels

            SEPbugSomething isn't workingin-reviewSEP proposal ready for review.

            Type

            No type

            Projects

            No projects

              Milestone

              No milestone

              Relationships

              None yet

              Development

              No branches or pull requests

              Issue actions

              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
              Skip to content

              SEP-834 Support full JSON Schema 2020-12 #834

              Description

              @jpmcb

              Preamble

              Title: Support full JSON Schema 2020-12
              Co-author: John McBride - @jpmcb
              Co-author: Ola Hungerford - @olaservo (adopted from #655 per #881 (comment))
              Status: proposal
              PR: #881

              Abstract

              There's a major discrepancy with how 2025-06-18 handles structuredContent in relation to outputSchema being defined as JSON Schema.

              Because structuredContentmust be an object, the types that can be returned by servers and validated by clients (like type: array which is fully supported by JSON Schema but throws errors in Inspector, the Typescript-SDK, etc) is dramatically narrow.

              Further, which draft of JSON Schema clients and servers use is not well defined leading to general drift among client, SDK, and server implementations. For example, JSON Schema specs in one client that uses JSON Schema draft-07 will be very different from another that uses 2020-12.

              Related:

              This SEP loosens JSON schema usage across clients and servers as well as defines using JSON Schema 2020-12

              Motivation

              In 5.1 Data Types: Tool, the spec states:

              outputSchema: Optional JSON Schema defining expected output structure

              JSON Schema may be of type object, array, string, null, etc. etc. If it's valid JSON, then JSON Schema can validate it.

              But the spec then goes on, in 5.2.6 Structured Content, to state:

              Structured content is returned as a JSON object in the structuredContent field of a result.

              This represents a dramatic discrepency and severly limits what type of content can be returned by a server and validated in the structured content.

              Consider the following valid JSON Schema:

              {"type": "array","items": {"type": "object","properties": {"id": {"type": "string","description": "A unique UUID"}},"required": ["id"],"additionalProperties": false}}

              which defines an array of objects where the objects must have an id property. This is pretty typical, especially in "list" type of operations.

              Now, suppose a server responds with the following JSON as structured content:

              [{"id": "abc123"},{"id": "xyz987"}]

              The spec would consider this structured content invalid and non-verifiable by the output schema.


              Originally, the MCP specification didn't explicitly state which JSON Schema version to use for tool inputSchema/outputSchema and elicitation requestedSchema, causing compatibility issues between implementations. Different clients and servers assume different versions, leading to validation failures and runtime errors. See: https://github.com/orgs/modelcontextprotocol/discussions/366 (discussion includes links to related issues)

              (original context before merged with this SEP: #655)

              Specification

              • Clarifies JSON Schema dialect usage for embedded schemas within MCP messages by establishing 2020-12 as the default dialect and allowing explicit dialect declaration via the $schema field.
              • Loosens inputSchema to be an object with type: object and any additional property to support JSON schema Draft 2020-12 and more powerful validation compositions (like anyOf, oneOf, etc.)
              • Loosens outputSchema to fully support JSON Schema 2020-12 since MCP servers may return any valid JSON.
                • Loosens structuredContent to support any JSON validated by outputSchema's JSON Schema.

              PR: #881

              Backward Compatibility

              No breaking changes.

              Existing schemas without $schema will default to 2020-12. Servers can optionally add $schema to use other dialects.

              Object schemas will continue to work as expected while the loosened specification can accept other valid JSON schema (like arrays of objects, etc.)

              Rationale

              The expectation is that any 2020-12 JSON Schema should be valid for fields that expect JSON schema. This includes outputSchema and structuredContent to be authentically validated by outputSchema, not just expected to always be an object: this is far too strict and narrows how tools can respond in ways that backends may not conform to. Further, 2020-12 has been widely adopted by the industry as the current standard but servers can define the schema they expect via the $schema metadata field.

              Reference Implementation

              TODO

              Security Implications

              There are no security implications.

              Activity

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

              Metadata

              Metadata

              Assignees

              Labels

              SEPbugSomething isn't workingin-reviewSEP proposal ready for review.

              Type

              No type

              Projects

              No projects

                Milestone

                No milestone

                Relationships

                None yet

                Development

                No branches or pull requests

                Issue actions

                , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
                Skip to content

                SEP-834 Support full JSON Schema 2020-12 #834

                Description

                @jpmcb

                Preamble

                Title: Support full JSON Schema 2020-12
                Co-author: John McBride - @jpmcb
                Co-author: Ola Hungerford - @olaservo (adopted from #655 per #881 (comment))
                Status: proposal
                PR: #881

                Abstract

                There's a major discrepancy with how 2025-06-18 handles structuredContent in relation to outputSchema being defined as JSON Schema.

                Because structuredContentmust be an object, the types that can be returned by servers and validated by clients (like type: array which is fully supported by JSON Schema but throws errors in Inspector, the Typescript-SDK, etc) is dramatically narrow.

                Further, which draft of JSON Schema clients and servers use is not well defined leading to general drift among client, SDK, and server implementations. For example, JSON Schema specs in one client that uses JSON Schema draft-07 will be very different from another that uses 2020-12.

                Related:

                This SEP loosens JSON schema usage across clients and servers as well as defines using JSON Schema 2020-12

                Motivation

                In 5.1 Data Types: Tool, the spec states:

                outputSchema: Optional JSON Schema defining expected output structure

                JSON Schema may be of type object, array, string, null, etc. etc. If it's valid JSON, then JSON Schema can validate it.

                But the spec then goes on, in 5.2.6 Structured Content, to state:

                Structured content is returned as a JSON object in the structuredContent field of a result.

                This represents a dramatic discrepency and severly limits what type of content can be returned by a server and validated in the structured content.

                Consider the following valid JSON Schema:

                {"type": "array","items": {"type": "object","properties": {"id": {"type": "string","description": "A unique UUID"}},"required": ["id"],"additionalProperties": false}}

                which defines an array of objects where the objects must have an id property. This is pretty typical, especially in "list" type of operations.

                Now, suppose a server responds with the following JSON as structured content:

                [{"id": "abc123"},{"id": "xyz987"}]

                The spec would consider this structured content invalid and non-verifiable by the output schema.


                Originally, the MCP specification didn't explicitly state which JSON Schema version to use for tool inputSchema/outputSchema and elicitation requestedSchema, causing compatibility issues between implementations. Different clients and servers assume different versions, leading to validation failures and runtime errors. See: https://github.com/orgs/modelcontextprotocol/discussions/366 (discussion includes links to related issues)

                (original context before merged with this SEP: #655)

                Specification

                • Clarifies JSON Schema dialect usage for embedded schemas within MCP messages by establishing 2020-12 as the default dialect and allowing explicit dialect declaration via the $schema field.
                • Loosens inputSchema to be an object with type: object and any additional property to support JSON schema Draft 2020-12 and more powerful validation compositions (like anyOf, oneOf, etc.)
                • Loosens outputSchema to fully support JSON Schema 2020-12 since MCP servers may return any valid JSON.
                  • Loosens structuredContent to support any JSON validated by outputSchema's JSON Schema.

                PR: #881

                Backward Compatibility

                No breaking changes.

                Existing schemas without $schema will default to 2020-12. Servers can optionally add $schema to use other dialects.

                Object schemas will continue to work as expected while the loosened specification can accept other valid JSON schema (like arrays of objects, etc.)

                Rationale

                The expectation is that any 2020-12 JSON Schema should be valid for fields that expect JSON schema. This includes outputSchema and structuredContent to be authentically validated by outputSchema, not just expected to always be an object: this is far too strict and narrows how tools can respond in ways that backends may not conform to. Further, 2020-12 has been widely adopted by the industry as the current standard but servers can define the schema they expect via the $schema metadata field.

                Reference Implementation

                TODO

                Security Implications

                There are no security implications.

                Activity

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

                Metadata

                Metadata

                Assignees

                Labels

                SEPbugSomething isn't workingin-reviewSEP proposal ready for review.

                Type

                No type

                Projects

                No projects

                  Milestone

                  No milestone

                  Relationships

                  None yet

                  Development

                  No branches or pull requests

                  Issue actions