|
1 | | -# Registry Authorization Specification |
| 1 | +# Registry Authorization |
2 | 2 |
|
3 | | -A standardized authentication and authorization mechanism for MCP registries, based on the [MCP Authorization Specification](https://modelcontextprotocol.io/specification/draft/basic/authorization). |
| 3 | +MCP registries wishing to implement authentication SHOULD follow the [MCP Authorization Specification](https://modelcontextprotocol.io/specification/draft/basic/authorization). |
4 | 4 |
|
5 | | -**Scope:** This specification is intended for downstream sub-registries (e.g., private company registries). The official modelcontextprotocol.io registry remains public for reading, and uses a different auth system for publishing for legacy reasons (this may change in future). |
| 5 | +## How it works |
6 | 6 |
|
7 | | -## Architecture |
| 7 | +The registry acts as an OAuth 2.1 Resource Server, identical to how MCP servers work. This means: |
8 | 8 |
|
9 | | -Sub-registries implementing this specification act as OAuth 2.1 Resource Servers, identical to how MCP servers work: |
| 9 | +- **MCP clients** can reuse their existing MCP authorization implementation without any changes |
| 10 | +- **Registries** validate access tokens the same way MCP servers do |
| 11 | +- **Users** get a consistent login experience across MCP servers and registries |
10 | 12 |
|
11 | | -- **Registry** = OAuth 2.1 Resource Server (validates access tokens) |
12 | | -- **MCP Client** = OAuth 2.1 Client (requests registry resources with tokens) |
13 | | -- **Authorization Server** = Issues tokens and manages authentication |
| 13 | +## Registry-Specific Scopes |
14 | 14 |
|
15 | | -This allows clients to reuse their existing MCP authorization implementation without modification. |
| 15 | +Registries MAY use these scopes: |
16 | 16 |
|
17 | | -## Client Requirements |
| 17 | +- `mcp-registry:read` - List and read server metadata |
| 18 | +- `mcp-registry:write` - Publish, update, and delete servers |
18 | 19 |
|
19 | | -Clients MUST follow the [MCP Authorization Specification](https://modelcontextprotocol.io/specification/draft/basic/authorization) when authenticating to registries. The flow is identical to MCP server authentication. |
| 20 | +These are recommendations - registries may use any set of scopes they deem sensible. |
20 | 21 |
|
21 | | -### Discovery |
| 22 | +Note that scopes only control what *types* of operations a user can perform. Registries should still apply user-level authorization to control which specific resources a user can access. For example, a user with `mcp-registry:write` might only be able to publish servers to namespaces they own, and may not have permissions to edit servers if the registry treats servers as immutable. |
22 | 23 |
|
23 | | -Registries requiring auth SHOULD return discovery information via a 401 Unauthorized response with the WWW-Authenticate header: |
| 24 | +## Official Registry Authentication |
24 | 25 |
|
25 | | -```http |
26 | | -GET /v0/servers HTTP/1.1 |
27 | | -Host: registry.example.com |
28 | | -
|
29 | | -HTTP/1.1 401 Unauthorized |
30 | | -WWW-Authenticate: Bearer realm="MCP Registry", scope="registry:read", resource_metadata="https://registry.example.com/.well-known/oauth-protected-resource" |
31 | | -``` |
32 | | - |
33 | | -(but for compatibility with the MCP spec, registries MAY serve metadata at a well-known URI) |
34 | | - |
35 | | -Clients supporting auth MUST then retrieve the Protected Resource Metadata from the provided URL: |
36 | | - |
37 | | -```json |
38 | | -{ |
39 | | - "resource": "https://registry.example.com", |
40 | | - "authorization_servers": ["https://auth.example.com"], |
41 | | - "scopes_supported": ["registry:read", "registry:write"], |
42 | | - "bearer_methods_supported": ["header"] |
43 | | -} |
44 | | -``` |
45 | | - |
46 | | -### Authorization Server Discovery |
47 | | - |
48 | | -Clients MUST discover the authorization server using standard OAuth 2.0 / OpenID Connect well-known endpoints, following the same priority order specified in the MCP Authorization Specification. |
49 | | - |
50 | | -### Token Requests |
51 | | - |
52 | | -Clients MUST include the `resource` parameter (RFC 8707) identifying the registry in all token requests: |
53 | | - |
54 | | -```http |
55 | | -POST /token HTTP/1.1 |
56 | | -Host: auth.example.com |
57 | | -Content-Type: application/x-www-form-urlencoded |
58 | | -
|
59 | | -grant_type=authorization_code |
60 | | -&code=AUTHORIZATION_CODE |
61 | | -&redirect_uri=http://localhost:3000/callback |
62 | | -&client_id=CLIENT_ID |
63 | | -&code_verifier=CODE_VERIFIER |
64 | | -&resource=https%3A%2F%2Fregistry.example.com |
65 | | -``` |
66 | | - |
67 | | -Clients MUST use PKCE with the S256 challenge method. |
68 | | - |
69 | | -### Authenticated Requests |
70 | | - |
71 | | -Clients MUST include the access token in the Authorization header for all authenticated requests: |
72 | | - |
73 | | -```http |
74 | | -GET /v0/servers HTTP/1.1 |
75 | | -Host: registry.example.com |
76 | | -Authorization: Bearer eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9... |
77 | | -``` |
78 | | - |
79 | | -Clients MUST NOT include tokens in query strings. |
80 | | - |
81 | | -### Scope Selection |
82 | | - |
83 | | -Clients MUST follow this priority hierarchy for scope selection: |
84 | | - |
85 | | -1. Use scopes from the `WWW-Authenticate` header's `scope` parameter if provided |
86 | | -2. Use all scopes from `scopes_supported` in Protected Resource Metadata if available |
87 | | -3. Omit the scope parameter if neither option exists |
88 | | - |
89 | | -### Step-Up Authorization |
90 | | - |
91 | | -When clients receive a 403 response with `error="insufficient_scope"`, clients SHOULD: |
92 | | - |
93 | | -1. Parse the required scopes from the `scope` parameter in the WWW-Authenticate header |
94 | | -2. Initiate a new authorization flow with the expanded scope set |
95 | | -3. Retry the original request with the new token |
96 | | - |
97 | | -Clients MUST implement retry limits to prevent infinite loops. |
98 | | - |
99 | | -## Security Requirements |
100 | | - |
101 | | -Registries and clients implementing this specification MUST follow all security requirements defined in the [MCP Authorization Specification](https://modelcontextprotocol.io/specification/draft/basic/authorization). |
102 | | - |
103 | | -### Scopes |
104 | | - |
105 | | -Registries SHOULD use scopes aligned with their API operations: |
106 | | - |
107 | | -- `registry:read` - List and read server metadata |
108 | | -- `registry:write` - Publish and update servers |
109 | | -- `registry:admin` - Administrative operations (optional) |
110 | | - |
111 | | -Registries MAY define additional scopes for fine-grained access control (e.g., `registry:read:acme-internal` for organization-specific private servers). |
112 | | - |
113 | | -### Permission-Based Server Visibility |
114 | | - |
115 | | -Registries MAY implement permission-based filtering of server lists. When a client provides an access token, registries SHOULD filter the response based on the token's claims, excluding servers the user does not have permission to access. |
116 | | - |
117 | | -Example approach: |
118 | | - |
119 | | -```json |
120 | | -{ |
121 | | - "name": "io.github.acme/internal-tools", |
122 | | - "title": "ACME Internal Tools", |
123 | | - "visibility": "private", |
124 | | - "allowed_scopes": ["registry:read:acme-internal"] |
125 | | -} |
126 | | -``` |
127 | | - |
128 | | -When listing servers, the registry filters results based on the token's scope claims. Users without appropriate scopes do not see private servers in responses. |
129 | | - |
130 | | -### Step-Up Authorization Responses |
131 | | - |
132 | | -When a user attempts an operation requiring additional permissions, registries SHOULD return a 403 response with: |
133 | | - |
134 | | -```http |
135 | | -HTTP/1.1 403 Forbidden |
136 | | -WWW-Authenticate: Bearer error="insufficient_scope", scope="registry:read registry:write", resource_metadata="https://registry.example.com/.well-known/oauth-protected-resource" |
137 | | -``` |
138 | | - |
139 | | -## Benefits |
140 | | - |
141 | | -**For clients:** Zero new code required - reuse existing MCP authorization implementation with identical flow and libraries. |
142 | | - |
143 | | -**For sub-registries:** Industry-standard OAuth 2.1 with flexible permissions and proven security model. |
144 | | - |
145 | | -**For users:** Consistent login experience across MCP servers and registries. |
146 | | - |
147 | | -## Comparison with Official Registry Authentication |
148 | | - |
149 | | -The official modelcontextprotocol.io registry uses a custom JWT-based authentication system for publishing servers. Reading servers remains public and does not require authentication. |
150 | | - |
151 | | -We may in future look at moving the official registry to this standardized OAuth 2.1-based system for consistency. |
152 | | - |
153 | | -## References |
154 | | - |
155 | | -- [MCP Authorization Specification](https://modelcontextprotocol.io/specification/draft/basic/authorization) |
156 | | -- [OAuth 2.1 Authorization Framework](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1) |
157 | | -- [RFC 8707: Resource Indicators for OAuth 2.0](https://datatracker.ietf.org/doc/html/rfc8707) |
158 | | -- [RFC 7591: OAuth 2.0 Dynamic Client Registration](https://datatracker.ietf.org/doc/html/rfc7591) |
159 | | -- [Issue #751](https://github.com/modelcontextprotocol/registry/issues/751) |
| 26 | +The official modelcontextprotocol.io registry remains public for reading. For publishing servers, it uses a custom JWT-based authentication system for legacy reasons - see [its API spec](official-registry-api.md#authentication). This may change in future to align with the MCP Authorization Specification. |
0 commit comments