MCP authentication
Requests to the Casdoor MCP server at /api/mcp are authenticated in the same ways as requests to the Casdoor API. This page describes how a client discovers what the server requires, and how each authentication method affects the tools that the client can call.
OAuth discovery
Casdoor publishes OAuth 2.0 Protected Resource Metadata (RFC 9728), so that an MCP client can find out which authorization server protects the MCP endpoint:
curl https://your-casdoor.com/.well-known/oauth-protected-resource
The response names the authorization server:
{
"resource": "https://your-casdoor.com",
"authorization_servers": ["https://your-casdoor.com"],
"bearer_methods_supported": ["header"],
"scopes_supported": ["openid", "profile", "email"]
}
To get the metadata of a single application, put the application name in the path:
curl https://your-casdoor.com/.well-known/my-app/oauth-protected-resource
Use the application-specific endpoint when applications have different authorization requirements.
Authentication methods
| Method | Tools that the client can call | Use it for |
|---|---|---|
| Access token | The tools that the scopes of the token allow. See MCP authorization and scopes | Automation and MCP clients. This is the recommended method |
| Client ID and client secret | The tools that the application may use | Service accounts |
| Session cookie | All tools, without scope checks | Interactive use in the browser |
With an access token:
curl -X POST https://your-casdoor.com/api/mcp \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
With the client ID and client secret of an application:
curl -X POST https://your-casdoor.com/api/mcp \
-u "CLIENT_ID:CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Unauthenticated requests
Casdoor answers a request to /api/mcp that it doesn't authorize, for example a request without credentials, with HTTP 401 and the header:
WWW-Authenticate: Bearer realm="casdoor", resource_metadata="https://your-casdoor.com/.well-known/oauth-protected-resource"
resource_metadata is the URL of the protected resource metadata on the host of the request, including the base path of Casdoor. The scheme is http when the host contains no dot, such as localhost:8000, and https otherwise. An MCP client that follows the OAuth 2.0 specification reads the metadata from that URL and starts the authorization flow on its own.
The body of the response depends on the request:
| Request | Response |
|---|---|
A JSON-RPC request with an id | HTTP 401 with a JSON-RPC error, whose data gives the reason |
A JSON-RPC notification, without an id | HTTP 202 with an empty body |
A body that isn't JSON-RPC, such as a GET request | HTTP 401 with an empty body |
For example:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32001,
"message": "Unauthorized",
"data": "Unauthorized operation"
}
}
The proxy endpoint of an external MCP server, /api/server/<organization>/<server-name>, answers in the same way, for GET and POST requests.