Proposal: Add a secrets object to every server type in mcp.json
#46
willvelida
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
secretsobject to every server type inmcp.jsonthat contains declaration metadata only. The package declares what it needs, and the responsibility of supplying the values falls to the various clients (GitHub Copilot, Cursor, etc.), similar to how GitHub Actions, Terraform, K8s etc. use.The complete updated MCP schema would look like the following:
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://agent-plugins.org/schemas/1.1.0/mcp.schema.json", "title": "Agent Plugins MCP Configuration", "description": "Machine-readable schema for mcp.json in Agent Plugins 1.1.0. The Agent Plugins specification defines additional semantic and operational requirements.", "type": "object", "properties": { "$schema": { "const": "https://agent-plugins.org/schemas/1.1.0/mcp.schema.json", "description": "Canonical identifier of the MCP configuration schema for the Agent Plugins version targeted by this document." }, "mcpServers": { "type": "object", "additionalProperties": { "$ref": "#/$defs/server" } } }, "required": ["$schema", "mcpServers"], "additionalProperties": false, "$defs": { "server": { "title": "MCP server", "oneOf": [ { "$ref": "#/$defs/stdioServer" }, { "$ref": "#/$defs/streamableHttpServer" }, { "$ref": "#/$defs/sseServer" } ] }, "stdioServer": { "title": "stdio MCP server", "type": "object", "properties": { "type": { "const": "stdio" }, "command": { "type": "string", "minLength": 1, "description": "Executable token. Resolution rules are defined by the Agent Plugins specification." }, "args": { "type": "array", "items": { "type": "string" } }, "env": { "type": "object", "propertyNames": { "not": { "enum": ["PLUGIN_ROOT", "PLUGIN_DATA"] } }, "additionalProperties": { "type": "string" } }, "secrets": { "$ref": "#/$defs/environmentSecrets" }, "cwd": { "type": "string", "pattern": "^(?:\\./|\\$\\{PLUGIN_ROOT\\}(?:/|$)|\\$\\{PLUGIN_DATA\\}(?:/|$))", "description": "Plugin-relative, PLUGIN_ROOT-rooted, or PLUGIN_DATA-rooted working directory. Filesystem containment is validated separately." } }, "required": ["type", "command"], "additionalProperties": false }, "streamableHttpServer": { "title": "Streamable HTTP MCP server", "type": "object", "properties": { "type": { "const": "streamable-http" }, "url": { "type": "string", "minLength": 1, "description": "MCP endpoint URL. URL semantics are defined by the Agent Plugins specification." }, "headers": { "$ref": "#/$defs/headers" }, "secrets": { "$ref": "#/$defs/headerSecrets" } }, "required": ["type", "url"], "additionalProperties": false }, "sseServer": { "title": "Legacy HTTP+SSE MCP server", "type": "object", "properties": { "type": { "const": "sse" }, "url": { "type": "string", "minLength": 1, "description": "MCP endpoint URL. URL semantics are defined by the Agent Plugins specification." }, "headers": { "$ref": "#/$defs/headers" }, "secrets": { "$ref": "#/$defs/headerSecrets" } }, "required": ["type", "url"], "additionalProperties": false }, "headers": { "title": "HTTP headers", "type": "object", "additionalProperties": { "type": "string" } }, "environmentSecrets": { "title": "Declared environment secrets", "description": "Environment variable names whose sensitive values are supplied by the client. Plugins declare requirements, never values.", "type": "object", "propertyNames": { "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "not": { "enum": ["PLUGIN_ROOT", "PLUGIN_DATA"] } }, "additionalProperties": { "$ref": "#/$defs/secretDeclaration" } }, "headerSecrets": { "title": "Declared header secrets", "description": "HTTP header names whose sensitive values are supplied by the client. Plugins declare requirements, never values.", "type": "object", "propertyNames": { "pattern": "^[!#$%&'*+.^_`|~0-9A-Za-z-]+$" }, "additionalProperties": { "$ref": "#/$defs/secretDeclaration" } }, "secretDeclaration": { "title": "Declared secret", "type": "object", "properties": { "description": { "type": "string", "minLength": 1, "description": "What the value is and what it must grant. Clients present this when asking a user to supply the value." }, "documentationUrl": { "type": "string", "description": "Where a user can obtain the value." } }, "required": ["description"], "additionalProperties": false } } }Some initial points to support this proposal
stdiocan use environment variables, or HTTP fields can be retrieved on remote transports.args,cwd,command.secretcannot be resolved, then that MCP server does not start per $7.2.2 rule 5.Example implementations
stdio: Uses an environment variable, so the server reads it exactly as it does today and needs no changes.{ "type": "stdio", "command": "npx", "args": ["-y", "@upstash/context7-mcp"], "secrets": { "CONTEXT7_API_KEY": { "description": "Context7 API key for higher rate limits", "documentationUrl": "https://context7.com/dashboard" } } }streamable-http: The key is a header name, declared alongside any literal headers rather than written into them.{ "type": "streamable-http", "url": "https://mcp.vendor.example/mcp", "headers": { "X-Tenant": "acme" }, "secrets": { "X-API-Key": { "description": "Vendor API key with read scope", "documentationUrl": "https://vendor.example/account/api-keys" } } }sse: similar tostreamable-http{ "type": "sse", "url": "https://legacy.vendor.example/sse", "secrets": { "Authorization": { "description": "Bearer token for the legacy endpoint", "documentationUrl": "https://vendor.example/account/tokens" } } }Open questions for discussion (plus my opinions)
envisRequired: falsefor example? (Yes).All reactions