Quick Start
This page takes you from nothing to an AI agent making one allowed call through Tokening. Allow about fifteen minutes. If you only want to see it work first, step through the recorded demo or run it yourself in step 1.
1. Run the demo on your machine
You need Git, Docker Compose v2 and Python 3. Nothing here touches a real website.
git clone https://github.com/softdevstudio/tokening.git
cd tokening
make demo
The script starts a throwaway WordPress, issues two grants, runs a scripted agent against them and checks the posts afterwards. Then it deletes everything it made. The replay and decision log land in test/results/local/demo/. Open replay.html in a browser to step through your own run.
2. Install Tokening
Download the archive for your system, check it against SHA256SUMS and put the tokening binary somewhere on your PATH. The commands below assume you can type tokening.
3. Write a policy
The policy file says which APIs Tokening can reach and what shapes of permission it may hand out. Copy examples/wordpress.json from the archive and change the URL to your own WordPress MCP endpoint. The important part is the template:
"wp.edit-post-text": {
"target": "demo-wp",
"tool": "wp_update_post",
"args": {
"id": { "bind": "required" },
"title": { "type": "string", "max_len": 200 },
"content": { "type": "string", "max_bytes": 32768 }
},
"additional_args": "refuse",
"max_uses": 3,
"max_ttl": "30m"
}
Read it as: this template can update a post, the post ID gets fixed when a grant is issued, only title and content can change, and any other field is refused. The tool name has to match what your WordPress MCP plugin actually offers. The demo adds wp_update_post with a small plugin you’ll find in demo/wordpress/. Check the file before you start:
tokening check tokening.json
4. Start the gateway
Keep its state in a private folder. Use a different random secret for the vault and for the admin API.
umask 077
mkdir tokening-state && cd tokening-state
tokening keygen > vault.key
tokening keygen > admin.token
export TOKENING_ADMIN_TOKEN="$(cat admin.token)"
tokening serve --policy ../tokening.json --db tokening.db --key-file vault.key
The agent port is 127.0.0.1:8080 and the admin port is 127.0.0.1:8081. Agents talk to the first one only. Back up vault.key somewhere safe, away from the database.
5. Store the real credential and issue a grant
In a second terminal with the same TOKENING_ADMIN_TOKEN, hand Tokening the WordPress application password. It goes into the encrypted vault and is never shown again.
cat > wordpress-credential.json <<'JSON'
{"username": "editor", "password": "xxxx xxxx xxxx xxxx xxxx xxxx"}
JSON
tokening target add demo-wp --cred-file wordpress-credential.json
rm wordpress-credential.json
Now issue a grant for one task:
tokening grant issue wp.edit-post-text \
--bind id=4812 --uses 1 --ttl 15m \
--to my-agent --by me --reason "fix the title of post 4812"
The reply holds a grant ID (g_...) and a secret. The secret is shown once. It’s the only thing your agent gets.
6. Connect your agent
Point your MCP client at http://127.0.0.1:8080/mcp/demo-wp and send the grant secret as a bearer token. Replace GRANT_SECRET below with the secret from step 5.
Claude Code
claude mcp add --transport http tokening http://127.0.0.1:8080/mcp/demo-wp \
--header "Authorization: Bearer GRANT_SECRET"
Cursor, in ~/.cursor/mcp.json:
{
"mcpServers": {
"tokening": {
"url": "http://127.0.0.1:8080/mcp/demo-wp",
"headers": { "Authorization": "Bearer ${env:TOKENING_GRANT}" }
}
}
}
Set TOKENING_GRANT in your environment and restart Cursor.
Claude Desktop, in claude_desktop_config.json, through the mcp-remote bridge:
{
"mcpServers": {
"tokening": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://127.0.0.1:8080/mcp/demo-wp",
"--header", "Authorization:${TOKENING_AUTH}"],
"env": { "TOKENING_AUTH": "Bearer GRANT_SECRET" }
}
}
}
These are the standard settings for an HTTP MCP server with a bearer token. Tokening 0.1 is tested end to end with its own scripted agent; testing with these clients is planned for 0.2. If a client misbehaves, tell us.
When the agent connects it sees one tool, wp_update_post. Ask it to fix the title. The first call goes through. Anything else comes back refused with a reason the agent can read, and so can you.
7. Watch what happened
tokening grant inspect g_... # uses left, expiry, every decision
tokening log --follow # live decisions
tokening grant revoke g_... --by me
Or open http://127.0.0.1:8081/admin/panel, paste the admin token and the grant ID, and watch decisions arrive. The panel is read-only.
Three things to get right
- The real key lives only in Tokening. If the agent can also read the WordPress password from a file or an environment variable, it can go around the grant. Run
tokening doctorin the agent’s environment to look for common credential variables. - The admin port stays private. Whoever reaches it can issue grants.
- A spent use stays spent. Tokening spends the use before it forwards the call, even if WordPress then fails. Check the post before you issue a new grant for a retry.
For the full list of constraints, refusal codes and endpoints, see the reference.