Skip to main content

Verify access from your application

Once your roles, scopes, and bindings are set up, your protected Application (MCP server, API, AI agent) needs to ask AuthSec whether each incoming request is allowed.

You almost never write the introspection call by hand. Install the AuthSec SDK and let the wrapper handle token validation, scope resolution, and the deny taxonomy. The example below is the minimum manual path — useful for debugging or for runtimes the SDK doesn't cover yet.

Manual check (Python)

from authsec_sdk import HybridValidator, ScopeMatrixClient, Config

config = Config.from_env() # reads AUTHSEC_RESOURCE_URI, AUTHSEC_ISSUER, AUTHSEC_JWKS_URL, AUTHSEC_INTROSPECTION_*
validator = HybridValidator(config)
scopes = ScopeMatrixClient(config)

async def can_call_tool(bearer_token: str, tool_id: str) -> bool:
principal = await validator.validate(bearer_token)
if not principal.active:
return False
policy = await scopes.lookup_tool(tool_id)
return principal.has_any_scope(policy.required_any)

What the wrapper does for you

When you use mount_mcp() (Python), MountMCP() (Go), or mountMCP() (TypeScript), this entire flow is automatic:

  1. Extracts the bearer token from Authorization: Bearer ….
  2. Validates it (JWT signature + JWKS, or RFC 7662 introspection, depending on validation_mode).
  3. Looks up the tool in the scope matrix.
  4. Checks the token's scopes against the tool's required scopes.
  5. Returns the right denial code (step_up_required, consent_required, policy_denied, scope_insufficient, …) so the AI client knows how to recover.

See the SDK guides for the 5-line wrapper that protects your Application end-to-end.

Debug a specific denial

If you want to see why a specific request was denied, paste the request's decision_id (returned in the denial body) into Effective Access in the admin UI. It shows every binding evaluated, every condition checked, and the first reason that failed.