From zero to launched
The linear walkthrough. Take an application you already run, work through the five steps on the Applications screen, and finish with it serving 200s to the right callers and 403s to everyone else.
About 10 minutes the first time. Step 4 is the only one with real decisions.
Before you start
- An application reachable over HTTPS. MCP server, AI agent endpoint, or API. The examples use
https://mcp.acme.example/mcp; substitute your own URL. - Admin access to AuthSec. If the Applications screen loads, you're set.
- A few minutes to drop the SDK into your codebase. Python, Go, and TypeScript each ship a one-line wrapper.
No OAuth knowledge required -- the SDK and admin UI handle the dance.
Step 1 — Register the application
Open Applications in the admin UI → click Install protection. The side panel asks for:
- Name — human readable, shows up across the UI.
- Public Base URL — the externally reachable origin of your application, e.g.
https://mcp.acme.example. - Protected Path — defaults to
/mcp. The Resource URI is composed as<Public Base URL><Protected Path>.
Submit. AuthSec creates the application, generates a one-time introspection secret, and lands you on the application detail view. The application starts in the Discovered state ("Not launched") — none of the five steps have been completed yet.
Copy the introspection secret now. It is shown once. If you lose it, you'll rotate it later from the same detail panel.
The secret and the Resource URI are the two values you need for step 2. Everything else is derivable from your AuthSec base URL.
More detail: Register an application.
Step 2 — Install protection
Copy the credentials from the Setup tab, drop them into your environment, and mount the AuthSec SDK wrapper in your startup code. The SDK adds token validation, scope enforcement, and manifest publishing -- your tool code stays untouched.
Each language has a full walkthrough:
| Language | Guide |
|---|---|
| Python | Protect your MCP server — FastAPI + mount_mcp |
| Go | Go SDK — net/http + authsec.MountMCP |
| TypeScript | TypeScript SDK — Express + mountMCP |
Copy-paste env-var blocks for .env, bash, PowerShell, Docker, and
Kubernetes are in Environment setup.
After restarting, your application is wired up. Policy isn't live yet (step 5), but every request now flows through the SDK middleware.
Treat the introspection secret like a password -- secrets manager or env var, never source control.
More detail: Set up the environment and SDK.
Step 3 — Publish the tool manifest
The tool manifest lists the tools your application exposes. AuthSec needs it to display tools in the admin UI, map each to a scope, and enforce policy per tool at runtime. Two ways to land it:
From the SDK (recommended). Set publish_manifest=True (Python) or PublishManifest: true (Go) and the SDK pushes the inventory at startup. In Python, also set cfg.tool_inventory_provider to declare your tools -- required when mounting a FastMCP instance (details). Restart your app and refresh the Tools tab.
By scanning over the wire. Click Scan now on the Tools tab. AuthSec issues a synthetic JSON-RPC tools/list request against your Resource URI and stores the result. Useful when the tool list is dynamic.
More detail: What is a tool manifest? · Tool inventory and discovery (operator view).
Step 4 — Review tool access
This is the slow step. Everything else is mechanical; this one is design work.
4a. Define access labels
A scope is a named permission a user grants to an AI client -- the unit of consent that lets the client do one specific kind of thing. Open the Scopes tab. AuthSec seeds starter labels per application:
rs-<id>:tools:readrs-<id>:tools:writers-<id>:admin
Accept the defaults to start; add custom scopes (e.g. rs-<id>:repos:read) once patterns emerge in your tool surface. For the decision tree, see Scope design for MCP tools.
4b. Map each tool to a scope
Back on the Tools tab, for every tool pick one of:
- Map to a scope — the tool requires that scope on the caller's token. The common path.
- Mark Public — no auth required. Use sparingly. Health checks, capability discovery.
- Leave Unmapped — the tool stays in the inventory but no one can call it (denied at runtime). The safe default.
The header counters track mapped / public / unmapped in real time. Unmapped tools are launch blockers — Activate stays disabled until every tool is mapped or marked public.
For bulk patterns ("every actions_get_* is read scope"), use the API — see Map tools to scopes.
4c. Default access policy
Open the Access tab. Pick a default role (likely viewer, auto-created with no scopes) and enable the policy. Every first-time user gets this role.
Add a manual exception for yourself as admin -- otherwise you lock yourself out on first test. The exception table tags MANUAL_ADMIN for hand-added rows vs DEFAULT_POLICY for auto-grants, so overrides survive policy changes.
More detail: Define scopes · Map tools to scopes · Access policy.
Step 5 — Launch
Open the Overview tab. The action queue tracks the setup work you just did. When every blocker is gone, the Activate action lights up.
Click it. The application flips from "Not launched" to live. The SDK starts enforcing the policy on its next refresh (~5 minutes; restart your app to force it now).
Verify it works
Three calls. If all three behave correctly, you're done.
Unauthenticated → 401 with a working challenge.
curl -sv -X POST https://your-app/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Expected: 401, with header WWW-Authenticate: Bearer resource_metadata="https://your-app/.well-known/oauth-protected-resource/mcp".
Read-scoped token calling a write tool -- 403 insufficient_scope. Acquire a token via the OAuth flow with only the read scope (Claude Desktop is the easiest path), then call a write tool. Expected: 403, body lists the missing scope.
Properly-scoped token -- 200. Acquire a token with the write scope, call the same tool. Expected: 200 with the tool's response.
If anything is off, see Troubleshoot OAuth tokens -- the four-claim checklist (aud, iss, exp, scope) covers most cases.
More detail: Run the protection test · Launch the application.
What "launched" means on the Applications list
The Applications list updates immediately. Per app you now see:
- Readiness — whether the setup is still internally consistent.
- Risk — surfaced from drift events and unmapped tools.
- Last Signal — the most recent runtime or policy event.
- Next Action — the one thing AuthSec thinks you should look at.
This is your operational view going forward. The Next Action column is the closest thing to a TODO list.
After launch
- Add scopes as your tool surface grows. Per-tool updates are one click on the Tools tab.
- Watch for drift events. Any post-launch policy change (scope deleted, tool unmapped, secret rotated) surfaces in the Monitor tab. See Monitor drift and runtime.
- Onboard end users. End users self-onboard through OAuth consent. Manage them under End Users. See Manage end users.
- Add operators. Settings --> Team. Invite, suspend, or remove workspace members. See Manage workspace members.
When you outgrow the basics
- More than one application sharing a tool? Read Preventing confused-deputy attacks — the
audclaim is what makes that safe. - Latency-sensitive? Compare JWT vs token introspection.
- Org-scale operator counts? Move from per-user role bindings to group-mediated bindings. See Groups and role bindings.