mesh
Click on "Deploy 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., "@meshshow me the agents on gpu-box"
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.
paseo-mesh
A Paseo plugin that lets agents on one Paseo host see and drive agents on your other hosts.
Paseo's built-in orchestration (create_agent, send_agent_prompt, finish notifications) works inside one daemon. paseo-mesh extends it across machines: an agent on your laptop can list the agents on your GPU box, read their timelines, start new agents there, send follow-ups, answer their permission requests, and get a message when they finish.

laptop (paseo-mesh installed) gpu-box, office-mac (plain Paseo)
┌────────────────────────────────────┐
│ agent ── mesh MCP tools ──► plugin │── relay (E2EE) or direct WebSocket ──► daemon
│ │ │──────────────────────────────────────► daemon
│ ◄── "agent X finished" ┘ │
└────────────────────────────────────┘Only the orchestrating host needs the plugin. Peers are ordinary Paseo daemons you can pair with.
Features
Mesh tools for agents. New agents on the host get a
meshMCP server withmesh_list_hosts,mesh_list_workspaces,mesh_list_agents,mesh_get_agent,mesh_read_timeline,mesh_list_providers,mesh_create_agent,mesh_send_prompt,mesh_wait_agent,mesh_respond_permission,mesh_stop_agentandmesh_archive_agent.Finish notifications across hosts. When an agent starts or prompts a remote agent, it receives a message when that agent finishes, errors or asks for permission, in the same format as Paseo's own notifications.
Any connection Paseo supports. Pairing offer URLs and
relay://URIs (end-to-end encrypted through the Paseo relay, no open ports), or directhost:port/ws:///wss://with an optional daemon password (Tailscale, LAN, reverse proxy).Per-host access control. Each peer is read-only or read-write, optionally limited to allowed paths: agents can only create, prompt, stop, archive or answer permissions for agents under those paths.
App screens. A Mesh screen with host status and agents across hosts, and a Peers settings screen to add, edit and remove peers.
Headless management. A
paseo-meshCLI for daemons without the app.
Related MCP server: AgentBridge
Requirements
Paseo daemon 0.11.0 or newer on the orchestrating host, with plugins enabled.
Peers: any Paseo daemon the orchestrating host can reach through the relay or directly.
Node.js and npm on the orchestrating host for Git installs (Paseo runs
npm ci --omit=devto install the plugin's dependencies).
Install
Plugins run unsandboxed with the daemon user's access. Install only code you trust.
Enable plugins on the orchestrating host: Settings → Plugins → Enable plugins in the app, or set
"pluginsEnabled": truein~/.paseo/config.jsonand runpaseo reload.Install from the Paseo plugin directory, which installs the reviewed revision:
paseo plugin add jtsang4/meshor straight from GitHub (
paseo plugin add git:jtsang4/paseo-mesh) or from npm:paseo plugin install npm:paseo-meshCheck it is running:
paseo plugin ls paseo plugin logs mesh
Update later with paseo plugin update mesh.
Connect your hosts
Agents can only reach the hosts in mesh's peer list. There are two ways to fill it.
Sync the hosts from the app
Under Settings → Plugins → mesh → Peers → Sync hosts from this app, turn on Keep peers in step with this app's hosts. While the Paseo desktop or web app is open, mesh then keeps its peers in step with the app's Hosts list: hosts you add to the app become peers, connection changes follow, and hosts you remove from the app are removed again. Peers you added by hand are never touched, and a synced peer you remove by hand is not synced back until you ask for it. Synced peers get the access you choose for the sync (read by default).
Every host that runs mesh syncs its own peers this way, including headless servers: the app you use to reach a Linux box keeps that box's mesh in step too. For each host, mesh picks a connection that works from the daemon doing the connecting:
the app's relay connection (pairing link),
the host's own pairing link, published by its mesh when its relay is on (this is how a headless server reaches the laptop the app runs on),
a direct
host:portthe daemon can route to (loopback addresses only count for daemons on the app's machine),SSH, using the daemon user's own SSH keys and config.
Hosts with no usable connection are listed under Not synced with the reason.
The sync reads the app's stored host list, which Paseo does not expose to plugins, so it works only in the desktop and web apps, and a future Paseo version could change that storage; mesh then stops syncing and reports the problem instead of guessing. Passwords stored in the app are copied into mesh's peer config on each daemon.
Add peers yourself
Get a pairing link for each machine, either in the app (Settings → that host → Pair device) or on the machine:
paseo daemon pair # prints https://app.paseo.sh/#offer=...Treat the link like a password: it lets its holder control that daemon. Then add the peer in the app (Settings → Plugins → mesh → Peers → Add a peer) or from a terminal:
npx paseo-mesh peers add gpu-box 'https://app.paseo.sh/#offer=...' --write
npx paseo-mesh peers add office-mac 100.64.0.7:6767 --password-stdin < password.txt
npx paseo-mesh peers add devbox 'ssh://dev@devbox-cn?daemonPort=6767'
npx paseo-mesh statusConnection | Use it when |
| The peer can reach the internet. Works behind NAT and firewalls; traffic is end-to-end encrypted. Self-hosted relays work too: the offer carries the relay address. |
| The hosts share a network (Tailscale, LAN, VPN, reverse proxy). Set a daemon password on the peer and give it to mesh. |
| You already SSH into the machine. Mesh runs |
Peers default to read access. Grant write to let agents create and control agents there, and add allowed paths to keep them in specific directories.
Use it
Agents created after installation have the mesh tools. Ask them in plain language:
Start a codex agent on gpu-box in /srv/models/llm to run the eval suite, and tell me the summary when it's done.
What are the agents on office-mac doing right now?
Read the last messages of the review agent on gpu-box and send it my comments.
The agent calls mesh_create_agent and gets on with other work. When the remote agent finishes, the caller receives a message like:
[paseo-mesh] Agent 3f2c… (eval-suite) on host gpu-box (srv_…) finished.
<agent-response>
All 412 cases passed …
</agent-response>Here an agent on the laptop runs a release check on gpu-box. It looks up the hosts, sees what else is running there, starts a test agent, and gets on with other work. When the remote agent finishes, its report arrives as a message and the laptop agent gives a go/no-go:

Open Mesh in the app sidebar to see every host and its agents. Agents on hosts that the app is also connected to open directly.
Agents talking across hosts
Messages sent with mesh_send_prompt or mesh_create_agent start with a header naming the sender and how to answer:
[paseo-mesh] Message from agent 3f2c… on host MacBook Pro, srv_….
To reply, call mesh_send_prompt with host "srv_…" and agentId "3f2c…".When both hosts run mesh and list each other as peers, the receiving agent can answer with mesh_send_prompt, so agents on two machines can hold a conversation. The reply address uses the sender's daemon serverId, which works whatever name the other host gave the peer. Pass includeSender: false to send the bare prompt. If the sender asked to be notified, the header tells the receiver its final response already reaches the sender, to avoid duplicate replies.
Tools
Tool | Access | Purpose |
| read | Hosts, status, identity and access level |
| read | Workspaces and paths on a host |
| read | Agents on one host or all hosts; unreachable hosts are reported, not fatal |
| read | Status, pending permissions, last assistant message |
| read | Recent messages and tool calls |
| read | Providers, models and modes available on a host |
| read | Block until a turn finishes, with a timeout |
| write | Start an agent on a host with a first task |
| write | Send a follow-up (steer or interrupt a running turn) |
| write | Allow or deny a remote permission request |
| write | Cancel a remote agent's running turn |
| write | Archive an agent on a host |
Hosts are addressed by name, peer id or daemon serverId; local is the orchestrating host. Agents are identified by (host, agentId). Read-only tools run without a permission prompt for Claude, Codex and OpenCode; write tools follow the agent's normal permission mode.
How it behaves when hosts change
Event | Behavior |
Peer renamed | Connection stays up. Pending notifications follow the peer and use the new name. Old names stop resolving; peer ids and server ids keep working. |
Connection, password or enablement changed | The peer reconnects with the new settings. |
Peer offline, daemon restarted, network drop | Exponential backoff reconnect (1 s to 30 s with jitter). Pending notifications wait and resume after the reconnect; turns that ended in the meantime are reported. |
Peer removed | Pending notifications are kept. If the same daemon is added back under any name within 24 hours, they resume. Otherwise the caller is told why they stopped. |
Remote agent deleted | The caller is told the agent no longer exists. |
Calling agent archived or deleted | The notification is dropped. |
Peer points back to this daemon | Rejected as a self loop. |
Two peers reach the same daemon | The second is flagged as a duplicate until the first is removed. |
Wrong offer for a daemon | Rejected: the handshake's server id must match the offer. |
Plugin reloaded or daemon restarted | Peers reconnect, pending notifications are restored from disk, and the MCP endpoint keeps the same port and token so existing agents keep their tools. |
| Applied on save. Peers without an id get one. An invalid file is reported in status and the last valid config stays active. |
Security
Trust boundary. A pairing offer or daemon password gives full control of that daemon. Paseo does not issue scoped credentials yet, so mesh enforces read/write access and allowed paths itself. They are guardrails for agents, not a sandbox: symlinks on the peer are not resolved.
App host sync reads the Paseo app's stored host list from inside the app, beyond the plugin API, and copies relay keys, endpoints and passwords to the daemons running mesh. It is off until you turn it on.
Secrets stay on the host. Offers and passwords live in
$PASEO_HOME/paseo-mesh/config.json(mode 0600). RPCs and the status screen never return them.Local endpoint. The MCP server listens on
127.0.0.1with a random bearer token stored in$PASEO_HOME/paseo-mesh/server.json(0600). It is injected into agents' MCP config, which Paseo keeps in the agent record.Relay. Relay traffic uses Paseo's end-to-end encryption; the relay sees only metadata. See Paseo's security model.
Configuration
Everything is editable in the app. The underlying file is $PASEO_HOME/paseo-mesh/config.json:
{
"version": 1,
"localAccess": "write",
"injection": {
"enabled": true,
"excludeProviders": ["pi"],
"preapproveReadOnlyTools": true,
"preapproveProviders": ["claude", "codex", "opencode"]
},
"peers": [
{
"name": "gpu-box",
"connection": "https://app.paseo.sh/#offer=...",
"access": "write",
"allowedPaths": ["/srv/models"],
"enabled": true
}
]
}Setting | Meaning |
| What mesh tools may do on the orchestrating host itself |
| Give new agents the mesh MCP server |
| Providers that cannot take MCP servers (Pi rejects them) |
| Skip permission prompts for read-only mesh tools |
| Providers that support exact MCP tool preapproval |
Set PASEO_MESH_HOME to move the data directory.
CLI
paseo-mesh status
paseo-mesh peers add <name> <connection> [--write] [--password-stdin] [--allow <path>]...
paseo-mesh peers set <peer> [--name <name>] [--connection <c>] [--read|--write] [--enable|--disable]
[--password-stdin|--clear-password] [--allow <path>]...
paseo-mesh peers remove <peer>
paseo-mesh peers retry <peer>
paseo-mesh settings [--inject|--no-inject] [--preapprove|--no-preapprove] [--local-access read|write]Run it with npx paseo-mesh <command>. Target another daemon with --home <path> or --host <host:port> (password from PASEO_PASSWORD). Add --json for machine-readable output.
Limitations
Agents created before mesh was installed do not have the tools. Create a new agent to use them.
App host sync needs the desktop or web app to be open, and the phone app cannot sync.
Files are not shared between hosts. Hand work over through git or messages.
Stopping turns on the local host is left to Paseo's own
cancel_agenttool.Running two installations of mesh on the same daemon is not supported; they would share one data directory.
When the stored MCP port is taken by another program at startup, mesh moves to a new port and agents created earlier lose their mesh tools.
Development
npm install
npm run typecheck
npm run lint
npm test # unit tests
npm run test:e2e # starts isolated daemons from @getpaseo/cli; never touches ~/.paseo
MESH_E2E_RELAY=1 npm run test:e2e # also exercise relay.paseo.shThe end-to-end suite runs real daemons with a deterministic echo provider (test/fixtures/echo-provider), so it needs no model credentials. See docs/architecture.md for internals and CONTRIBUTING.md for the workflow.
To try a working copy on a disposable daemon (a fresh home defaults to port 6767, so pick another one first):
npx paseo daemon config set daemon.listen 127.0.0.1:7777 --home /tmp/mesh-dev
npx paseo daemon config set pluginsEnabled true --home /tmp/mesh-dev
npx paseo daemon start --home /tmp/mesh-dev
npx paseo --home /tmp/mesh-dev plugin install "$PWD"
npx paseo --home /tmp/mesh-dev plugin reload mesh # after edits
npx paseo daemon stop --home /tmp/mesh-devLicense
This server cannot be deployed
Maintenance
Related MCP Connectors
Discover willing agents, request permission, hand off durable tasks, and recover private results.
Discover, search, invoke, and rate A2A (Agent-to-Agent) protocol agents.
Securely control computers you explicitly pair through files, terminals, processes, screenshots, desktop UI/input, clipboard, browser automation, diagnostics, and document tools.
Agent-native collaboration network: orchestrate a team of long-running agents from any MCP client.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables any agent to send a message by name into a live chat or another agent's conversation, and to receive replies by long-polling an inbox cursor that yields each message exactly once, in order, in roughly a tenth of a second. Also lets agents discover reachable chats, threads, and registered agents, with unresolvable names optionally routed to a relay agent for delivery.1 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables a coding agent to ask another person's coding agent questions across different machines, networks, and subscriptions, with revocable directional permission and a locked-down responder session enforced by configuration.MIT
- AlicenseAqualityAmaintenanceLets your AI agent talk directly to another person's agent on a different machine. One pairing code connects them through an end-to-end encrypted relay (hosted or self-hosted), with no public IP needed; it also sends files and invites saved contacts by name.146Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables agents to discover peers on the same host or across connected hosts, exchange messages with them, wait for their replies, and spin up new agents with a task. Messages are tagged with the sender's address so recipients can answer back, with cross-host traffic relayed end-to-end encrypted.MIT