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

  1. 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.
  2. Check the requested version in the call's `_meta` matches a registered tool version, or drop the version to get the default.
  3. If component-level auth is intended to hide the tool, grant the caller's token the required scopes/roles configured on the tool.
  4. 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

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


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/677cf02e7d85395d. Report an issue: GitHub.