# Agents
> Four tools locally, and one agent calling another device's tools through the pairing.
> Source: https://jvoltci.github.io/sparsh/docs/agents/

There are two separate things here and they are easy to confuse.

**Locally**, Sparsh gives your agent four tools for moving files to devices you
have paired with. **Remotely**, Sparsh carries MCP itself, so an agent on one
machine can call the tools a server on another machine exposes, with no port, no
VPN and no account.

## Locally: four tools

```bash
claude mcp add sparsh -- sparsh mcp-tools
```

`sparsh_status`, `sparsh_devices`, `sparsh_send` and `sparsh_inbox`. The
[reference](/reference/mcp) is generated from the running server, so it cannot
drift from what your agent actually sees.

Two rules shape them:

**Tools return paths, never bytes.** That is the MCP maintainers' own position
and it is obvious at these sizes: a 1.59 GB file base64'd into a tool result is
a context-window fire, not a feature.

**There is no pairing tool.** An agent must never pair itself, and the surest
way to guarantee that is to give it no verb for it.

Sending a file from inside the working directory goes straight through. Anything
outside it asks you first, because `send(path)` is "read any file and ship it",
which is exactly what a prompt-injected agent reaches for. `SPARSH_ALLOWED_ROOTS`
widens what counts as inside.

## Remotely: MCP over the wire

On the device that has the server, a human grants one pairing the right to drive
one command:

```bash
sparsh expose "Mac · Claude Code" -- npx -y @modelcontextprotocol/server-filesystem ~/Documents
```

On the device that wants it:

```bash
claude mcp add homebox -- sparsh mcp "Home box"
```

That is all. The real MCP client and the real MCP server now talk to each other.

### How it actually works

The two daemons are a **transparent bridge**, not a proxy. A fourth data channel
opens on the session that is already warm, carrying MCP's own stdio framing:
newline-delimited JSON-RPC, exactly what a local server speaks. Neither end
knows Sparsh is there, so protocol negotiation, resources, prompts, progress and
cancellation all pass through unchanged, now and in the next spec revision.

Measured: a `tools/call` through the whole chain is
**0.67** ms median, p95 **1.15** ms, on
loopback. The raw channel round trip is **0.21** ms, so the
four process hops cost about half a millisecond between them.

### Who may

**Identity is the connection.** The peer is the key its SDP was signed with, and
WebRTC checks the DTLS certificate against the fingerprint inside that SDP. There
is no token to steal and no header to forge.

**Authorisation is one grant, made by a human.** No pairing has it by default.
The grant names one server, not a shell. `sparsh unexpose <device>` takes it back
and closes any live channel immediately.

**Two requests never cross toward you.** `sampling/createMessage`, so a remote
server cannot spend your model, and `roots/list`, so it cannot read your project
layout.

Every call leaves one audit line with the peer, the tool and the size. Never the
arguments: those are your data and routinely contain secrets.

### What it cannot protect you from

A remote server's replies are text in your agent's context, exactly as with any
third-party MCP server. The device is authenticated; the agent on it may still
be prompt-injected. Your MCP client's own approval prompts are the human in the
loop, and they apply here as anywhere.

Read [Security](/security) before exposing anything.
