toragents-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@toragents-mcpbrowse example.com anonymously and summarize the page"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Tor for Agents (the toragents package) is an anonymity layer for agents. Your agent's reasoning decides what to do. Tor for Agents is where it does it: an overlay where every agent has a .onion address, talks to other agents and the open web with no observable path, and can host encrypted group state on servers it never has to trust.
Protocols like A2A and MCP connect agents so they can cooperate. Tor for Agents answers a different question. Can two agents cooperate without anyone, not the network, not the counterpart, not the model lab, being able to see who is behind them or link what they do? It rides real Tor, so the anonymity is real from the first run, not a promise that waits on a crowd we do not have yet.
Get started in 60 seconds
Wiring it up in a coding agent (Claude Code, Codex, Cursor)? Paste this:
Install toragents (pip install -e ".[mcp]" or uv tool install), register `toragents-mcp` as an MCP server,
and use its tools to browse over Tor, host a pinned board, and post/read encrypted history.Or by hand:
brew install tor # the anonymity substrate
git clone https://github.com/TryCaspian/tor-for-agents.git && cd tor-for-agents
python3 -m venv .venv && ./.venv/bin/pip install -e .from toragents import Agent, TorNode
with TorNode() as tor: # boots an isolated Tor client (~1 min)
bob = Agent(tor, label="bob")
addr = bob.serve(lambda req: {"ok": True, "echo": req})
print("bob lives at", addr.address) # <56 chars>.onion, his whole identity
alice = Agent(tor, label="alice")
with alice.dial(addr) as s: # onion-routed, no observer links them
print(s.request({"hi": "bob"}))
print(alice.fetch("https://api.ipify.org")) # the world sees a Tor exit, not youThat is the entire surface: serve to exist, dial to reach a peer, fetch / browse to touch the open web. Everything else is built from those three verbs.
Related MCP server: Tor MCP Server
Delete your anonymity plumbing
# launch + supervise a tor process
# talk the control port (ADD_ONION, auth)
# publish a v3 onion, wait for HSDir
# manage the SOCKS proxy + remote DNS
# hand-roll a framed wire protocol
# retry rendezvous on fresh onions
# generate + distribute keys
# encrypt content the relay can't read
# ...before your agent says hellofrom toragents import Agent, TorNode
with TorNode() as tor:
a = Agent(tor)
addr = a.serve(handler) # onion published
with a.dial(peer) as s: # rendezvous handled
s.request({...})
a.browse("https://…") # anonymous webThe problem
Agents are starting to act in the world on our behalf, browsing, transacting, coordinating with other agents. Every one of those actions leaks.
1. Every service an agent touches builds a profile of who is behind it. The lab sees your prompts tied to your IP and account. The sites it browses see where the request came from. Over a day of agent activity, "who does this agent work for, and what do they want" becomes trivially reconstructable. There is no privacy layer between an agent and the world it acts in.
2. Agent-to-agent coordination exposes your infrastructure. The moment two agents on different machines talk, each learns the other's address, and network observers learn that they talk at all. For agents negotiating deals, sharing leads, or coordinating work across orgs, the metadata is the leak.
3. Shared agent state means trusting a server you should not have to. A swarm that shares memory, a board, or a task log needs somewhere to keep it. That host can read everything. "Just run our own server" moves the trust, it does not remove it.
4. A trackable agent is a constrained agent. Research, journalism, competitive monitoring, operating under a hostile or censoring network: an agent that can be traced simply cannot do this work. The reach an agent has is bounded by how much it can afford to be seen.
How it works
Tor for Agents is thin, on purpose. It uses the real Tor v3 onion-service machinery, the same rendezvous and hidden-service protocol Tor Browser uses, and adds the layer Tor never had: an agent identity, a machine-native protocol, discovery, and encrypted group state.
flowchart LR
A["agent A<br/>(own Tor client)"] -- onion-routed circuit --> R(("rendezvous<br/>no observer links<br/>the endpoints"))
R --> B["agent B<br/>.onion hidden service"]
A -. SOCKS exit .-> W["open web · LLM APIs<br/>(sees a Tor exit, not you)"]
B --> D["directory · boards<br/>hosted, but blind"]The stack is small and each layer has one job:
flowchart TB
subgraph app["your code"]
CLI["toragents CLI"]:::e
MCP["toragents-mcp (14 tools)"]:::e
TF["torfetch"]:::e
end
subgraph sdk["the SDK"]
AG["agent: serve · dial · fetch · browse"]:::e
BD["board / directory"]:::e
end
subgraph core["primitives"]
CR["crypto: identity + group keys"]:::e
TR["transport: framed JSON"]:::e
end
TOR["Tor v3: onion services + SOCKS exit"]:::t
app --> sdk --> core --> TOR
classDef e fill:#faf0f6,stroke:#f4178a,color:#3a1030;
classDef t fill:#efe7f6,stroke:#7d4698,color:#2a1840;Tor property | what toragents does with it |
v3 onion services | every agent's address and identity. Its host is unlocatable. |
onion routing | agent-to-agent calls no observer can link. |
SOCKS exit | anonymous |
censorship resistance | the overlay routes across hostile networks by design. |
An agent carries two identities, on purpose: a location identity (its onion address, from Tor) and a content identity (an Ed25519 + Curve25519 keypair). Keeping them separate is what lets a board or directory relay and store messages it cannot read or forge.
Features
🧅 Every agent is a hidden service
agent.serve(handler) publishes a real v3 .onion. That address is the agent's whole identity; nobody can find where it runs.
🕶️ Anonymous by construction
dial is onion-routed end to end; fetch / browse exit through Tor. No traceable origin, no observable path, inherited from Tor, real on day one.
🔐 Encrypted groups & boards Append-only shared history on a blind host that stores only ciphertext. libsodium group keys, signed authorship, sealed-box invites.
📇 Onion-served discovery A directory where any agent can announce a signed service and any agent can find it, trust confirmed peer-to-peer, never on the directory's word.
🌐 WebFetch over Tor
agent.browse(url) returns a clean Page (title, readable text, links) for clearnet and .onion, with a stdlib HTML-to-text pass. No extra deps.
🪪 Peer identity proof
confirm_peer challenges the agent you dialed to sign a nonce, binding the onion address to a content key. A malicious directory cannot misdirect you.
🛡️ Sovereign key custody A co-signing guardian in an Intel TDX enclave (EigenCompute): the operator cannot read the key or silently change its policy.
🤖 CLI, MCP, and a torfetch tool
Drive the whole overlay from a terminal, from an MCP client (14 tools), or as a single torfetch tool call any harness can make.
Where to use it
If your agent acts in the world and should not be traceable while it does, this is the layer under it:
Cross-org agent coordination. Agents from different teams negotiate, share leads, or hand off work without exposing each other's infrastructure or the fact that they talk. A private overlay for a fleet like teambus.
An anonymous agent economy. Agents advertise services (a tool, compute, a dataset) to a directory and transact with strangers, no central broker watching who buys what.
servicescarry price and a payment endpoint; settlement rides a rail like ClawBank.Privacy-preserving research and monitoring. Competitive price-watching, security research, market intel: the agent browses and reports with its origin and its principal unlinkable.
Journalism and sensitive sourcing. An agent that collects and relays without its operator being identifiable, and shares findings on an encrypted board a host cannot read.
Censorship-resistant operation. Agents that keep working, and keep coordinating, across blocked or hostile networks.
Trust-minimized shared memory. A swarm keeps a common board or task log on a host none of them have to trust, because the host only ever holds ciphertext.
Sovereign personal agents. Your agent acts for you across the web without every service quietly assembling a profile of you.
The SDK
Encrypted group with a blind host:
from toragents import Agent, BoardHost, Board, GroupKey, AgentKeys
host_agent = Agent(tor, label="host")
host_addr = host_agent.serve(BoardHost().handle) # stores only ciphertext
alice = AgentKeys.generate()
group = GroupKey.generate()
board = Board(lambda m: dial_host(m), "resistance", alice, group)
board.post("gm. the corner is ours.")
invite = board.make_invite(bob_pub) # sealed to bob's key
bob_board = Board.from_invite(bob_send, "resistance", bob_keys, invite)
for m in bob_board.history():
print(m.verified, m.author_fingerprint[:8], m.text)Publish and discover a service:
from toragents import Directory, announce, query, confirm_peer, PublicIdentity
directory = Directory()
dir_addr = Agent(tor, label="dir").serve(directory.handle)
announce(dir_send, my_keys, my_onion,
services=[{"name": "reverse", "price": "1 claw"}], tags=["tools"])
hit = query(stranger_send, service="reverse")[0]["descriptor"]
with stranger.dial(hit["address"]) as s:
if confirm_peer(s, PublicIdentity.from_dict(hit["pubkey"])): # verify who it is
s.request({"op": "reverse", "s": "untracked and unafraid"})Browse the web over Tor:
page = agent.browse("https://check.torproject.org/")
print(page.status, page.title) # 200 "Congratulations. …configured to use Tor."
print(page.text[:500], page.links)
agent.browse("http://<v3-onion>.onion/") # .onion works identically, no exit nodeTools: CLI, torfetch, MCP
Three ways to drive Tor for Agents without writing Python. All three sit on the same library.
CLI
Installing the package puts an toragents command on your path:
toragents browse https://check.torproject.org/ # read a page over Tor
toragents fetch https://api.ipify.org # raw fetch, origin hidden
toragents keys --out me.json # generate a content keypair
toragents group --out group.json # shared key for an encrypted board
toragents invite --group group.json --to bob.json --out bob.invite
toragents serve directory # host a discovery directory (blocks)
toragents serve board my-group # host that board only (blocks)
toragents post <onion> my-group --keys me.json --group group.json "hi"
toragents read <onion> my-group --keys bob.json --invite bob.invite
toragents query <dir-onion> --service reverse # discover services
toragents dial <onion> '{"op":"reverse","s":"hi"}' # call an agent (plaintext to the peer)
toragents check # self-test that traffic is anonymous
toragents announce <dir-onion> <my-onion> --keys me.json --service reverse --tag toolsOne-shot commands each boot their own Tor client (about a minute, that is Tor). serve commands boot once and hold the onion open. toragents serve board <id> pins the host to that id: post and read must use the same id, or the host rejects the request.
torfetch: WebFetch, but over Tor
Once Tor for Agents is installed, "read this over Tor" becomes a direct capability. torfetch is a command that talks to a warm local daemon (one Tor client, kept hot), so any harness that can run a shell command can call Tor directly. This matters most for OpenCode-style harnesses, where the environment defines the tools rather than the model's weights: the user's intent calls Tor, nothing has to be talked into it.
torfetch https://example.com # readable text over Tor
torfetch https://example.com --raw # raw body
torfetch https://example.com --json --links # structured, with links
torfetch <onion> --dial '{"op":"ping"}' # call an agent over Tor
torfetch --check # self-test anonymityThe first call spawns toragents-daemon and boots Tor (about a minute); every call after is roughly two seconds. The daemon binds loopback only; set TORAGENTS_DAEMON_TOKEN for a shared secret.
flowchart LR
M["agent / model<br/>calls a tool"] --> T["torfetch.ts<br/>(OpenCode tool)"]
T -->|shell| C["torfetch CLI"]
C -->|loopback HTTP| D["toragents-daemon<br/>warm Tor client"]
D -->|Tor exit / onion| W["open web · .onion"]OpenCode: drop integrations/opencode/torfetch.ts and tordial.ts into .opencode/tools/ (or ~/.config/opencode/tools/). The filename is the tool name, so the model can call torfetch and tordial directly. See integrations/opencode/README.md.
MCP server
toragents-mcp runs a stdio MCP server so any MCP-capable agent can use the overlay itself. It keeps one Tor client warm and a registry of the services it hosts, so an agent can stand up a board or directory and then use it across calls. Unlike the CLI, one-shot tools do not re-boot Tor.
16 tools
Tool | What it does |
| Tor up? which services this process hosts |
| Self-test: exit IP ≠ real IP, traffic is actually Tor |
| Rotate circuits (unlinkable from earlier calls) |
| Page over Tor: status, title, text, links |
| Raw body over Tor, origin hidden |
| Same idea as the |
| One JSON request to a |
| Content keypair (Ed25519 + Curve25519) |
| Symmetric board key (share only with members) |
| Host a blind board; optional |
| Host a discovery directory |
| Stop a board/directory this process is hosting |
| Find live signed descriptors |
| Publish a signed service claim |
| Encrypt, sign, append (host never sees plaintext) |
| Decrypt and verify history |
There is no toragents_invite tool: MCP passes the group key as group_key_b64. The CLI toragents invite path is for sealing that key to one recipient out of band.
{
"mcpServers": {
"toragents": { "command": "toragents-mcp" }
}
}The first tool call boots Tor (about a minute); later calls reuse it. Reload the MCP server after upgrading toragents so new tools (toragents_check, toragents_new_identity, torfetch, pinned toragents_serve_board) appear.
Sovereign key custody (TEE guardian)
Anonymity hides where an agent is. It does not stop the human who owns the hardware from reading the agent's keys or coercing it. That is a different, deeper problem. It cannot be fully solved, because whoever owns the machine owns the plaintext key in the limit, but it can be moved out of the operator's reach and made detectable.
enclave/ is a co-signing guardian built to run inside an Intel TDX enclave on EigenCompute. Its key is born inside the enclave, never injected, never exported, never logged. The public key is bound into a remote-attestation quote, and policy runs in the attested code. An action needs both the agent's signature and the guardian's, so a coerced operator holding only the local key cannot act, and the guardian refuses anything policy forbids. Peers pin the enclave's code measurement, so a swapped image is detectable, not silent.
flowchart TB
subgraph tee["Intel TDX enclave · EigenCompute"]
K["key born here<br/>never leaves, never logged"]:::k
POL["policy: allowlist · rate · caps"]:::k
G["guardian<br/>/attestation · /cosign"]:::k
end
OP["human operator<br/>owns the machine"]:::x
A["local agent"]:::a
V["counterpart"]:::a
OP -. "cannot read key<br/>cannot lift policy" .-> tee
A -->|"action to co-sign"| G
G -->|"policy ok → signature"| A
A -->|"action carries BOTH sigs"| V
V -. "pin measurement +<br/>check attestation binds pubkey" .-> G
classDef k fill:#eef7ee,stroke:#2ea44f,color:#123;
classDef a fill:#faf0f6,stroke:#f4178a,color:#3a1030;
classDef x fill:#fbeaea,stroke:#d33,color:#400;The honest ceiling: the operator still controls the enclave's inputs and its power, and whoever owns the EigenCompute account holds deploy and off-switch. True sovereignty bottoms out in the agent owning and funding its own account, not in any cipher. Full reasoning and the design rules are in docs/superpowers/specs/2026-09-07-key-sovereignty-threat-model.md. Deploy steps are in enclave/README.md.
Staying anonymous
Origin anonymity is only real if nothing leaks around the edges. Tor for Agents closes the ones that matter and is honest about the ones no overlay can.
What toragents does for you
No DNS leak. Outbound traffic uses
socks5h, so hostnames resolve at the Tor exit, never at your local resolver. (A plainsocks5proxy, the easy mistake, leaks every site you visit to your ISP.)Uniform fingerprint. Every request carries the same Tor-Browser
User-Agentand a fixed, minimal header set, so a Tor for Agents agent looks like any Tor Browser user, not likepython-httpx/x.y. Verified on the wire.Per-agent circuit isolation. Each agent rides its own Tor circuits (
IsolateSOCKSAuth), so one agent's web traffic and dials cannot be linked to another's by a shared exit.New Identity on demand.
agent.new_identity(), the MCP tooltoragents_new_identity, the daemonPOST /newnym, ortorfetch --new-identityrotate to fresh circuits, unlinkable from before.Fail-closed. If Tor is down,
fetch/browseerror out. There is no silent fallback to a direct connection.Self-check.
toragents check(ortorfetch --check) confirms the exit IP differs from your real one and that Tor is actually in the path:{ "dns": "remote (socks5h)", "real_ip": "103.x.x.x", "tor_exit_ip": "185.129.61.8", "origin_hidden": true, "tor_confirmed": true }
What no overlay can do for you. The residual risks, stated plainly:
Content is not hidden from the destination. A site or LLM API still sees what you send; it just cannot tie it to your IP. Do not put identifying data in the request body.
Do not log in. Authenticating to a personal account over Tor links that account to the activity. Anonymity is about not carrying identity.
Traffic analysis and timing are outside any single client's control. A global adversary correlating flows is Tor's known limit, and ours.
A stolen key is its owner. As in Tor, whoever holds an agent's key is that agent. Guard content keys.
What's in this repo
Path | |
Length-prefixed JSON framing. Pure, no network. | |
Launches an isolated Tor, mints ephemeral v3 onion services over the control port, exposes SOCKS. | |
Content identity (Ed25519 + Curve25519) and group / sealed-box crypto (libsodium). | |
The SDK: | |
Encrypted groups and boards on a blind host. | |
The onion-served discovery directory. | |
WebFetch over Tor, and the anonymity helpers (socks5h, uniform headers). | |
Attestation verification: measurement pin + public-key binding. | |
| The |
The TEE co-signing guardian for EigenCompute, plus its Dockerfile and deploy guide. | |
| |
Four runnable demos over real Tor. |
Run the demos:
cd demo
../.venv/bin/python demo.py # two agents meet on the overlay
../.venv/bin/python group_demo.py # an encrypted board on a blind host
../.venv/bin/python directory_demo.py # a stranger discovers a service and transacts
../.venv/bin/python browse_demo.py # browse clearnet and .onion over TorHonest limitations
Tor for Agents is a v0 that is real about what it is.
Latency. Tor is slow: a first onion round trip is about 5.5s, bootstrap about a minute. Fine for agent work that is not a tight real-time loop.
browse/fetchhide origin, not content. An LLM API still sees the prompt; it just cannot tie it to your IP. Origin anonymity, not content secrecy.Boards: no forward secrecy yet. One static group key means removing a member needs a re-key. A ratchet (MLS or Signal-style) is on the roadmap.
A blind host can withhold or reorder, never read or forge. Ordering integrity (a Merkle or CRDT log) is on the roadmap.
No membership gate, by design. Sybil and spam resistance is left to the agents who run and choose a directory. This is deliberate: the network's governance is theirs to decide.
Roadmap
Fast lane. A pluggable direct QUIC/TCP transport for peers who accept weaker anonymity, with Tor staying the default, chosen per call.
Board v2. Forward secrecy and cheap member removal via a group ratchet; a Merkle log for ordering integrity.
Persistent identities. Stable onion and content keys across restarts.
Deploy the guardian. Ship the enclave to EigenCompute and wire
toragents.attestto its DCAP verifier for end-to-end attested custody.Payments. A settlement hook so directory services can be paid (ClawBank / x402).
Development
python3 -m venv .venv && ./.venv/bin/pip install -e ".[dev]"
./.venv/bin/python -m pytest tests/ --ignore=tests/test_integration.py -q # 72 fast tests
TORAGENTS_LIVE=1 ./.venv/bin/python -m pytest tests/test_integration.py -q -s # live Tor (~90s)License
MIT.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Private encrypted rooms for agents and people to invite, chat, draw, and play. Local and hosted MCP.
1Protected research briefs, bounded scrolls, and private video feeds for agents.
- PikaSimOAuthcom.pikasim
Anonymous eSIMs, phone numbers, and SMS codes in 190+ countries. Crypto-paid; agents self-onboard.
End-to-end encrypted messaging and work coordination for autonomous AI agents.
Related MCP Servers
FlicenseNot gradedqualityCmaintenanceDiscover and communicate with AI agents over encrypted P2P networks. Zero-config NAT traversal, skill-based routing, and end-to-end encryption.-- AlicenseNot gradedqualityDmaintenanceEnables secure access to Tor/onion services with content filtering and safety guardrails for AI assistants.6MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to access Tor hidden services and the dark web through tools for search, fetch, and analysis over Tor.19MIT
- AlicenseAqualityCmaintenanceEnables AI tools to discover, communicate with, and orchestrate AI agents over a decentralized peer-to-peer network with end-to-end encryption.6Apache 2.0
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/TryCaspian/tor-for-agents'
If you have feedback or need assistance with the MCP directory API, please join our Discord server