PrefectHQ/fastmcp · error · AuthorizationError
Authorization failed for tool '{tool_name}': not found or no
Error message
Authorization failed for tool '{tool_name}': not found or not authorized What it means
AuthMiddleware.on_call_tool looks the tool up with `fastmcp.get_tool(tool_name, version=version)` and denies the request when it returns None. Because component-level auth can also make get_tool return None, the message deliberately does not distinguish a missing tool from one the caller is not allowed to see, to avoid leaking tool existence.
Source
Thrown at fastmcp_slim/fastmcp/server/middleware/authorization.py:231
fastmcp = context.fastmcp_context
if fastmcp is None:
# Fail closed: deny access when context is missing
logger.warning(
f"AuthMiddleware: fastmcp_context is None for tool '{tool_name}'. "
"Denying access for security."
)
raise AuthorizationError(
f"Authorization failed for tool '{tool_name}': missing context"
)
# get_tool returns None both when the tool does not exist and when
# component-level auth denied access, so the two cases are
# indistinguishable here. Keep the message ambiguous to avoid
# disclosing existence of tools the caller is not authorized to see.
version = _requested_version(context.message.meta)
tool = await fastmcp.fastmcp.get_tool(tool_name, version=version)
if tool is None:
raise AuthorizationError(
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)})"
),
)View on GitHub (pinned to 1f02114297)
Solutions
- Verify the exact tool name by listing tools as the authorized client (`session.list_tools()`) or via `await mcp.get_tool(name)`; fix typos/renames.
- Check the requested version in the call's `_meta` matches a registered tool version, or drop the version to get the default.
- If component-level auth is intended to hide the tool, grant the caller's token the required scopes/roles configured on the tool.
- Confirm the tool is registered on the same FastMCP instance the client connects to (not a different server object).
Example fix
# before
result = await client.call_tool('get_weahter', {'city': 'SF'}) # typo
# after
tools = await client.list_tools()
assert any(t.name == 'get_weather' for t in tools)
result = await client.call_tool('get_weather', {'city': 'SF'}) Defensive patterns
Strategy: validation
Validate before calling
names = {t.name for t in await client.list_tools()}
assert 'my_tool' in names, 'tool not visible to this caller; check name or auth' Try / catch
from fastmcp.exceptions import AuthorizationError
try:
result = await client.call_tool('my_tool', args)
except AuthorizationError as e:
if 'not found or not authorized' in str(e):
available = await client.list_tools()
logger.warning('tool unavailable; visible: %s', [t.name for t in available])
else:
raise Prevention
- Verify tool names with list_tools() before calling, especially after renames.
- Keep client and server deployments in sync on tool names and versions.
- Remember the message is intentionally ambiguous — check both existence and your token's permissions.
- Omit _meta version fields unless you know the versioned variant exists.
When it happens
Trigger: Client calls tools/call with a name that is not registered, a typo'd or renamed tool, a version requested via `_meta` with no matching tool variant, or the tool exists but component-level auth rejected this caller so get_tool hides it.
Common situations: Client SDK out of sync with the server after a tool rename; calling a tool behind an auth provider that filters it for this token; requesting a versioned tool variant that was removed; staging vs production servers with different tool sets.
Related errors
- Authorization failed for tool '{tool_name}': insufficient pe
- Authorization failed for resource '{uri}': not found or not
- Authorization failed for resource '{uri}': insufficient perm
- 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/677cf02e7d85395d.
Report an issue: GitHub.