PrefectHQ/fastmcp · error · AuthorizationError
Authorization failed for tool '{tool_name}': insufficient pe
Error message
Authorization failed for tool '{tool_name}': insufficient permissions What it means
Fallback branch of the global auth check in on_call_tool: the auth checks rejected the request but produced no specific scope shortfall, so a generic AuthorizationError is raised instead of InsufficientScopeError. Denial came from non-scope logic in the auth provider (role checks, custom predicates, audience validation, etc.).
Source
Thrown at fastmcp_slim/fastmcp/server/middleware/authorization.py:250
f"Authorization failed for tool '{tool_name}': "
"not found or not authorized"
)
# Global auth check
token = get_access_token()
ctx = AuthContext(token=token, component=tool)
authorized, missing = await run_auth_checks_with_shortfall(self.auth, ctx)
if not authorized:
if missing:
missing = self._chain_shortfall(missing, ctx, fastmcp.fastmcp)
raise InsufficientScopeError(
missing,
message=(
f"Authorization failed for tool '{tool_name}': "
f"insufficient scope (required: {', '.join(missing)})"
),
)
raise AuthorizationError(
f"Authorization failed for tool '{tool_name}': insufficient permissions"
)
return await call_next(context)
async def on_list_resources(
self,
context: MiddlewareContext[mt.ListResourcesRequest],
call_next: CallNext[mt.ListResourcesRequest, Sequence[Resource]],
) -> Sequence[Resource]:
"""Filter resources/list response based on auth checks."""
resources = await call_next(context)
# STDIO has no auth concept, skip filtering
from fastmcp.server.context import _current_transport
if _current_transport.get() == "stdio":
return resourcesView on GitHub (pinned to 1f02114297)
Solutions
- Inspect your auth provider's checks — any check that returns False must either raise with a reason or report the missing scopes so the middleware can produce a shortfall.
- Decode the access token and compare its claims (roles, scopes, aud, iss) against what the tool's auth policy expects.
- Fix the token: obtain one with the required roles/claims, or correct the provider's claim mapping.
- Review global vs component auth policy so the request isn't denied by an unintended default-deny rule.
Example fix
# before
class RoleCheck(AuthCheck):
async def check(self, ctx): return False # denial with no shortfall -> generic error
# after
class RoleCheck(AuthCheck):
async def check(self, ctx):
if 'admin' not in ctx.token.roles:
raise AuthorizationError('missing admin role')
return True Defensive patterns
Strategy: try-catch
Validate before calling
claims = decode_jwt(token)
assert claims.get('aud') == expected_audience, 'audience mismatch will cause generic denial'
assert required_roles.issubset(set(claims.get('roles', []))), 'token missing roles' Try / catch
from fastmcp.exceptions import AuthorizationError
try:
result = await client.call_tool('my_tool', args)
except AuthorizationError as e:
if 'insufficient permissions' in str(e):
logger.error('Denied without scope shortfall; check custom auth checks and token claims')
else:
raise Prevention
- Make custom AuthChecks raise specific errors or report shortfalls instead of returning bare False.
- Validate JWT audience/issuer/claims mapping in your provider config.
- Test auth policies with an explicitly scoped test token before production.
- Log denials server-side to distinguish policy vs token problems.
When it happens
Trigger: run_auth_checks_with_shortfall returns authorized=False with an empty `missing` list for the tool's AuthContext — a custom auth check returning False without reporting a shortfall, role/permission checks failing, JWT audience/issuer mismatch, or an unintended default-deny policy.
Common situations: Custom auth providers whose check() returns False silently; tokens lacking required roles/claims (as opposed to scopes); audience/issuer mismatch on the JWT; deny-all policy accidentally applying to tools.
Related errors
- Authorization failed for resource '{uri}': insufficient perm
- Authorization failed for tool '{tool_name}': not found or no
- Authorization failed for resource '{uri}': not found or not
- Authorization failed for tool '{tool_name}': missing context
- Authorization failed for resource '{uri}': missing context
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/60fa42c42bdecabb.
Report an issue: GitHub.