SEP-1488: securitySchemes in Tool Metadata for Mixed-Auth Servers

Author: thiago-openaiCreated Sep 18, 2025Updated Sep 15, 2026
LabelsauthsecuritySEPdraft

SEP: securitySchemes in Tool Metadata for Mixed-Auth Servers

Authors: Duke Kim ([email protected]), Thiago Hirai ([email protected]) Status: Draft Sponsor: Nick Cooper ([email protected]) Type: Standards Track Created: 2025-09-17

Summary

We propose adding an optional securitySchemes field to MCP tool descriptors. This makes it possible for a server to mark which tools are open to everyone and which need auth. Clients can then:

  • Show clear UI labels (e.g. “Public” vs. “Requires sign-in”).
  • Ask users to sign in before calling protected tools.
  • Pick between public and authenticated versions of the same tool.

This is a small, backward-compatible change. For now, we support just two scheme types:

  • "noauth" → tool can be called without credentials
  • "oauth2" → tool needs OAuth 2.0 (with optional scopes list)

More scheme types can be added later without changing the shape of the field.

Motivation

Right now, clients only discover auth needs by trying and failing, or by reading docs. This isn’t great. By declaring securitySchemes per tool, servers can:

  • Improve UX: Clients know upfront if a tool is public or needs auth.
  • Guide flows: Clients can prompt users for login before invoking a protected tool.
  • Reduce mistakes: Servers can mark tools as public vs. protected.
  • Stay flexible: Easy to add new auth schemes (API keys, mTLS, etc.) later.

Design

Tool Descriptor Change

Each tool can include a new optional securitySchemes field in its tools/list response:

{
  "name": "get_weather",
  "title": "Weather Info",
  "description": "Get current weather for a location",
  "inputSchema": {
    "type": "object",
    "properties": { "location": { "type": "string" } },
    "required": ["location"]
  },
  "securitySchemes": [
    { "type": "noauth" },
    { "type": "oauth2", "scopes": ["weather.read"] }
  ]
}

Field Definition

securitySchemes (array, optional)

  • If missing → tool follows the server’s default policy.
  • If empty array → discouraged, same as missing.
  • If present with entries → lists supported auth schemes.

Scheme types (so far):

  • noauth: no credentials required.
  • oauth2: needs OAuth2; can list scopes if relevant.

Multiple Schemes

  • Tools can list both noauth and oauth2 to mean “works anonymously, but auth gives more features.”
  • Clients can pick any scheme they can satisfy, usually preferring authenticated.
  • Servers must enforce auth rules regardless of client metadata.

Examples

Public with optional auth:

{
  "name": "search",
  "title": "Public Search",
  "description": "Search public documents.",
  "inputSchema": { "type": "object", "properties": { "q": { "type": "string" } }, "required": ["q"] },
  "securitySchemes": [
    { "type": "noauth" },
    { "type": "oauth2", "scopes": ["search.read"] }
  ]
}

Auth required:

{
  "name": "create_doc",
  "title": "Create Document",
  "description": "Make a new doc in your account.",
  "inputSchema": { "type": "object", "properties": { "title": { "type": "string" } }, "required": ["title"] },
  "securitySchemes": [
    { "type": "oauth2", "scopes": ["docs.write"] }
  ]
}

No field (inherits server policy):

{
  "name": "status",
  "title": "Server Status",
  "description": "Basic health info.",
  "inputSchema": { "type": "object", "properties": {} }
}

JSON Schema (informative)

{
  "$id": "https://modelcontextprotocol.io/schemas/tool.securitySchemes.v1",
  "type": "object",
  "properties": {
    "securitySchemes": {
      "type": "array",
      "items": {
        "oneOf": [
          { "type": "object", "required": ["type"], "properties": { "type": { "const": "noauth" } } },
          { "type": "object", "required": ["type"], "properties": {
              "type": { "const": "oauth2" },
              "scopes": { "type": "array", "items": { "type": "string", "minLength": 1 }, "uniqueItems": true }
            }
          }
        ]
      }
    }
  },
  "additionalProperties": true
}

Compatibility

  • Optional field → no breaking changes.
  • Old clients ignore it and keep using runtime errors/docs to figure out auth.
  • Old servers just don’t send it.

Security Notes

  • Declaring noauth makes public tools explicit and auditable.
  • Declaring oauth2 with scopes helps clients request the right tokens.
  • This field is just metadata; servers still must enforce auth.
  • Misconfigurations (e.g. forgetting to require auth) are the main risk.

Source: modelcontextprotocol/modelcontextprotocol