ExMCP.Authorization.ScopeValidator (ex_mcp v0.9.2)
View SourceMaps MCP operations to required OAuth scopes and validates them.
This module provides a centralized way to manage scope requirements for
different MCP methods. It defines a standard set of scopes following the
mcp:<domain>:<action> convention and offers functions to retrieve required
scopes for a method and validate them against the scopes granted in a token.
Standard Scopes
The following standard scopes are defined. More specific scopes can be satisfied
by granting a less specific, "wildcard" scope. For example, a token with the
mcp:tools:execute scope can access any tool, satisfying the more specific
mcp:tools:execute:<tool_name> requirement.
Tools
mcp:tools:list: Allows listing available tools (tools/list).mcp:tools:get: Allows retrieving the definition of a specific tool (tools/get).mcp:tools:execute: Allows executing any tool. This is a wildcard scope.mcp:tools:execute:<tool_name>: Allows executing a specific tool (tools/execute).
Resources
mcp:resources:list: Allows listing available resources (resources/list).mcp:resources:get: Allows retrieving any specific resource (resources/get).mcp:resources:create: Allows creating any new resource (resources/create).mcp:resources:update: Allows updating any existing resource (resources/update).mcp:resources:delete: Allows deleting any resource (resources/delete).- More granular resource scopes (e.g.,
mcp:resources:get:<resource_id>) can be implemented with a custom mapper.
Prompts
mcp:prompts:execute: Allows executing a prompt (prompts/execute).
Usage
To get the required scopes for an MCP request:
request = %{"method" => "tools/list"}
ExMCP.Authorization.ScopeValidator.get_required_scopes(request)
#=> ["mcp:tools:list"]
execute_request = %{
"method" => "tools/execute",
"params" => %{"tool_name" => "my_calculator"}
}
ExMCP.Authorization.ScopeValidator.get_required_scopes(execute_request)
#=> ["mcp:tools:execute:my_calculator"]To validate scopes from a token:
token_scopes = ["mcp:tools:execute"]
required_scopes = ["mcp:tools:execute:my_calculator"]
ExMCP.Authorization.ScopeValidator.validate(token_scopes, required_scopes)
#=> :ok
token_scopes = ["mcp:tools:list", "mcp:tools:get"]
required_scopes = ["mcp:tools:execute:my_calculator"]
ExMCP.Authorization.ScopeValidator.validate(token_scopes, required_scopes)
#=> {:error, :insufficient_scope}Extensibility
The scope mapping can be extended by passing a custom mapping function
to get_required_scopes/2. This function receives the request map and should
return a list of required scopes. If it returns nil, the standard mapping
is used as a fallback.
my_mapper = fn
%{"method" => "custom/op"} -> ["my:custom:scope"]
%{"method" => "resources/get", "params" => %{"id" => resource_id}} ->
["mcp:resources:get:" <> resource_id]
_ ->
nil # Fallback to default for other methods
end
ExMCP.Authorization.ScopeValidator.get_required_scopes(request, my_mapper)
Summary
Functions
Returns a list of all standard, statically-defined MCP scopes.
Retrieves the list of required OAuth scopes for a given MCP request.
Validates that a set of token scopes satisfies a set of required scopes.
Types
@type custom_mapper() :: (request() -> required_scopes() | nil)
@type request() :: map()
@type required_scopes() :: [String.t()]
@type token_scopes() :: [String.t()]
Functions
@spec get_all_static_scopes() :: [String.t()]
Returns a list of all standard, statically-defined MCP scopes.
This is useful for advertising supported scopes, for example in a
.well-known/oauth-protected-resource endpoint. Note that this list does not
include dynamically generated scopes like mcp:tools:execute:<tool_name>.
@spec get_required_scopes(request(), custom_mapper()) :: required_scopes()
Retrieves the list of required OAuth scopes for a given MCP request.
This function inspects the method and params of the request to determine
the necessary scopes. It can be extended with a custom mapping function.
@spec validate(token_scopes(), required_scopes()) :: :ok | {:error, :insufficient_scope}
Validates that a set of token scopes satisfies a set of required scopes.
This function checks if for every required scope, either the scope itself or a more general "wildcard" scope exists in the token scopes.
For example, if required_scopes is ["mcp:tools:execute:calculator"], this
function will return :ok if token_scopes contains either
"mcp:tools:execute:calculator" or "mcp:tools:execute".