Skip to main content
For auth providers, credential vault, and scope challenges, see the Authentication overview.

Overview

The Authorities system provides declarative, built-in authorization on tools, resources, prompts, and skills. Instead of writing imperative access-control checks inside every handler, you declare who can access what directly in decorator metadata. Authorities supports four authorization paradigms: These paradigms can be composed using allOf, anyOf, and not combinators to express complex policies. The system consists of two packages:
  • @frontmcp/auth — Core types, evaluation engine, registries, and errors
  • @frontmcp/sdk — Built-in flow stages (checkEntryAuthorities, filterByAuthorities) for enforcement, configured via @FrontMcp({ authorities }) metadata
No plugin required — authorities is a first-class framework feature.

Quick Start

Add the authorities config to your @FrontMcp() decorator and set authorities on any entry.
If a user without the required role calls delete_user, the checkEntryAuthorities flow stage throws an AuthorityDeniedError with MCP error code -32003 before the handler executes.
Boot-time fail-fast. If any entry — a tool, resource, prompt, agent, or skill — declares authorities but the server has no authorities engine configured (no @FrontMcp({ authorities: { … } })), startup fails with an AuthConfigurationError. This prevents a silent bypass where an entry looks protected but is actually open to everyone. Either add the authorities config or remove authorities from the entry. Servers with no authorities config and no gated entries are unaffected.

JWT Claims Mapping

Every identity provider stores roles and permissions in different JWT claim paths. The claimsMapping option tells the engine where to find them.
Auth0 uses namespaced custom claims for roles and the standard permissions claim.
The claimsMapping supports dot-path traversal (e.g., realm_access.roles) and also direct key lookup for namespaced claims containing dots (e.g., https://myapp.com/roles).

Custom Claims Resolver

For more complex scenarios, provide a claimsResolver function instead of (or in addition to) claimsMapping. It takes precedence when both are configured.

Authority Profiles

Profiles are named, reusable authorization policies registered at the server or app level. They let you write authorities: 'admin' instead of repeating the full policy object on every entry.

Registering Profiles

Using Profiles on Entries

When an array of profiles is provided, they are evaluated with AND semantics — every profile must pass for access to be granted.

RBAC

Role-based access control checks the user’s roles and permissions against required values.

Roles

Permissions

Permission checks follow the same all/any semantics as roles.

Combining Roles and Permissions

When both roles and permissions are specified in the same policy, they are combined with AND by default.

ABAC

Attribute-based access control evaluates conditions against a context envelope with four namespaces:

Simple Match

The match field provides simple equality checks. All pairs must match (AND semantics).

Advanced Conditions

The conditions field supports a rich set of operators for more complex checks.

Operator Reference

Dynamic Value References

Condition values can reference runtime data instead of using static literals.
fromInput is only meaningful for entries that receive request input at call time — tools and agents. @Resource and @Prompt do not pass tool-style input into the authorities evaluation, so a fromInput reference (in an ABAC condition or a ReBAC resourceId) has nothing to resolve against on those entries. Gate resources and prompts with role / permission / claims (fromClaims) policies instead.

ReBAC

Relationship-based access control delegates checks to an external authorization backend (e.g., SpiceDB, OpenFGA, or a custom database query).

Configuring a Relationship Resolver

First, implement the RelationshipResolver interface and pass it in the authorities config.

Using ReBAC on Entries

Multiple Relationships (AND)

Pass an array of relationship checks. All must pass.

Resource ID Sources

Combinators

For complex authorization requirements, compose policies using allOf, anyOf, not, and the operator field.

allOf (AND)

All nested policies must pass.

anyOf (OR)

At least one nested policy must pass.

not (Negation)

Invert a nested policy.

operator: ‘OR’

By default, top-level fields in a single policy object are combined with AND. Set operator: 'OR' to use OR instead.

Nested Composition

Combinators nest freely for arbitrarily complex policies.

Custom Evaluators

Extend the authorities system with your own evaluators for domain-specific checks.

Defining an Evaluator

Implement the AuthoritiesEvaluator interface.

Registering Evaluators

Using Custom Evaluators in Policies

Reference evaluators under the custom field. The key must match the evaluator name.
If a referenced custom evaluator is not registered, the policy is denied with the message custom evaluator '<name>' is not registered.

Discovery Filtering

List and discovery flows automatically filter entries based on the caller’s authorities via the built-in filterByAuthorities stage. When a client calls tools/list, resources/list, or prompts/list, entries the user is not authorized to access are silently removed from the results.
This ensures AI agents only see tools they can actually call, preventing wasted context and failed invocations.
Discovery filtering runs without request input. filterByAuthorities evaluates each entry’s policy against the caller’s identity (roles / permissions / claims) only — there is no tool input at list time. As a result, a policy that depends on fromInput (an ABAC condition or a ReBAC resourceId resolved from input) cannot be satisfied at discovery time and is treated as denied for everyone, so the entry is filtered out of tools/list (and the skill/resource/prompt discovery surfaces) for all callers — even users who would pass the check at call time. Gate discovery visibility with role / permission / claims-only policies; reserve fromInput/ReBAC-by-input policies for call-time enforcement (checkEntryAuthorities), where the input is available.

Skill Discovery Filtering

Skills are filtered on every discovery surface so a caller never sees a skill they are not authorized to load:
List-time filtering is role/permission/claims-only. Discovery runs without request input, so input-dependent policies — ABAC conditions using { fromInput: '…' } or ReBAC resourceId: { fromInput: '…' } — cannot be evaluated when filtering a list and will exclude the skill from discovery. Use role-, permission-, or claims-based authorities (e.g. authorities: 'admin' or { roles: { any: ['admin'] } }) for skills that must stay discoverable. Input-dependent policies are still enforced correctly at load time (see below), where the request input is available. The same limitation applies to tools, resources, and prompts.
HTTP skills discovery is fail-closed. The Skills HTTP API (GET /skills) authenticates with a binary api-key/bearer gate that does not surface JWT claims, so authority-gated skills are hidden from HTTP discovery and denied on HTTP load (GET /skills/{id}) regardless of the bearer. Serve gated skills over an MCP transport (where the full claims context is available) for claims-based access. Skills without authorities are served over HTTP exactly as before.

Hooking into Authority Checks

Authority enforcement runs as native flow stages, not plugin hooks. This means developers can hook into them with Will, Did, and Around decorators — just like any other flow stage.

Flow Stages Reference

Skills are enforced across multiple serving surfaces rather than a single flow stage (MCP custom-method handlers + SEP-2640 skill:// resources + the HTTP Skills API), but the behaviour mirrors the table above: deny on direct load/read (AuthorityDeniedError, code -32003) and filter on discovery. See Skill Discovery Filtering.

Will Hook — Run Before the Authority Check

Use Will to add custom pre-checks, logging, or feature-flag gates that run before the built-in authority evaluation.

Did Hook — Run After the Authority Check

Use Did to audit authority decisions or emit metrics after the check completes (whether it passed or threw).

Around Hook — Replace the Entire Authority Check

Use Around to wrap or completely replace the built-in authority evaluation with custom logic. This is useful for integrating external policy engines like OPA or Cedar.

Hooking into List Filtering

Error Handling

When an authorities check fails at execution time (as opposed to list filtering), the checkEntryAuthorities stage throws an AuthorityDeniedError.

AuthorityDeniedError

JSON-RPC Error Format

The error serializes to a standard JSON-RPC error for MCP transport:

Denial Reasons

The deniedBy field provides actionable feedback:

Type-Safe Profiles

Use the FrontMcpAuthorityProfiles global interface augmentation to get autocomplete and compile-time checks for profile names.

Declaring Profiles

Create a type declaration file (e.g., authorities.d.ts) in your project:

Autocomplete in Decorators

Once declared, TypeScript provides autocomplete when using string profile references:

Metadata Augmentation

The @frontmcp/auth authorities module automatically augments all entry metadata interfaces to accept the authorities field:
This means authorities is accepted on @Tool(), @Resource(), @ResourceTemplate(), @Prompt(), and @Skill() decorators without any additional configuration.