Tokening Now Guards Stdio MCP Servers and Claude Desktop
Most MCP servers people actually run don’t listen on a port. The filesystem server, the GitHub server, the database servers: a client starts them as a command and talks to them over stdin and stdout. Until now Tokening could only sit in front of servers that speak HTTP, which left out most of them. Version 0.2 closes that gap.
A target can now be a command. When a grant allows a tool call, the gateway starts the server, sends that one call and stops it again, along with anything the server started itself. When the grant refuses a call, nothing starts at all. The server never sees the gateway’s environment either: it gets PATH, HOME and a few system variables, plus the variables you store as its credential, such as a GitHub token. The vault key and the admin token stay out.
Claude Desktop, One File
Claude Desktop only launches commands, so the other half is tokening connect. It relays what the desktop app sends to the gateway, with the grant taken from an environment variable:
{
"mcpServers": {
"notes": {
"command": "tokening",
"args": ["connect", "http://127.0.0.1:8080/mcp/notes"],
"env": { "TOKENING_GRANT": "GRANT_SECRET" }
}
}
}
We ran the released binary in front of the real filesystem server, version 2.1.0, with a grant for one file in a notes folder, and fed it the messages a desktop client sends. Reading todo.md worked and took 189 milliseconds, starting the server included. Reading passwords.md was refused. So were journal/../passwords.md, asking for only the first line of todo.md, listing the folder and writing to todo.md, each with a reason Claude can read and pass on. The server was started once in that whole session: for the one call that was allowed.
A second grant allowed one write to a new shopping list. It went through in 223 milliseconds. A second write to the same file came back “allowed 1 use and has none left”, and a write to todo.md was refused as the wrong path. todo.md was untouched afterwards. The flight log for both sessions verified intact, 22 entries. The full transcripts and the script that reruns them are in the repository.
What a Grant Doesn’t Cover
A grant narrows what the agent can ask the server to do. It doesn’t sandbox the server. The server runs as the user running Tokening, so a server that takes free-form paths or shell commands can reach whatever that user can. For servers like that, run Tokening as its own user with nothing else in its files, and pin the server’s version in the command. The reference has the details.
Two things we learned running it for real. npx asks the npm registry every time it starts a server, so it needs the network on every call, and behind a proxy it needs proxy variables the server doesn’t inherit. Installing the server once and naming its binary avoids both. And Windows needed its own way to stop a server started through npx, since node runs as a child of cmd.exe there: the server now joins a Job Object that takes everything down with it. The tests run on Windows in CI from this release on.
An independent review went through the code before release and found a hang when a server stops reading, no limit on how many servers one grant could start at once, and the example policy missing from the repository. All of that was fixed before 0.2.0 went out. Download it from the download page.