MCP integration
ShellWatch exposes a Model Context Protocol server over streamable HTTP at /mcp. Each MCP client connection gets an isolated AgentSession — agents can only see and control sessions they themselves created. The Web UI for the same account sees those sessions too (labelled (mcp)), so a human can watch an agent live — but visibility never crosses account boundaries.
Authentication
Section titled “Authentication”Authentication is OAuth 2.1 with Dynamic Client Registration, issued by Ory Hydra (the OAuth authority that ships with every ShellWatch deployment) and gated by your passkey. Point the client at the bare /mcp URL and the flow handles everything — there are no API keys to mint or paste.
Works in any MCP client (Claude Desktop, Claude Code, MCP Inspector, …). Just give the client the bare URL:
{ "mcpServers": { "shellwatch": { "type": "streamable-http", "url": "https://app.shellwatch.ai/mcp" } }}What happens under the hood:
- The client hits
/mcpunauthenticated → ShellWatch responds withWWW-Authenticatepointing at the OAuth discovery metadata (/.well-known/oauth-authorization-server). - The client registers itself at
/api/hydra/register(mediated DCR: ShellWatch validates the redirect URI and requested scope against local policy, then provisions a real per-clientclient_idin Hydra). - The client opens Hydra’s
/oauth2/authin your browser → Hydra redirects to ShellWatch’s passkey login page → you authenticate and consent to the requested scope. - The client exchanges the authorization code (PKCE) at
/oauth2/tokenfor anmcp-scoped access token plus a refresh token.
Access tokens are short-lived (30 minutes); the refresh token (30 days, rotating) lets the client renew silently, so you only see the browser once per client per month. To cut a client off, revoke its grant — log out / revoke sessions in ShellWatch — rather than hunting for a key to delete.
The flow is scope-aware: MCP clients get mcp; the same flow is how shellwatch-agent login enrols with agent scope. The ui scope is reserved for ShellWatch’s own web UI and is never grantable via DCR. The token authorises routing, not the privileged operation — opening a session still triggers a passkey approval. See Concepts → Security model.
On self-hosted instances, which redirect URIs may register is policy you control (hydra.dcr.redirectUriPatterns). The default is loopback-only — fine for the agent-client and local MCP tools, but a hosted client like Claude.ai (which registers an https://claude.ai/api/mcp/auth_callback redirect) is rejected until you add its pattern. See the Configuration reference for how to extend the list. (On app.shellwatch.ai the hosted Claude callbacks are already allowed.)
| Tool | Description |
|---|---|
shellwatch_create_session | Open a new terminal session against a configured endpoint. Returns a sessionId. |
shellwatch_list_sessions | List sessions owned by this agent connection. |
shellwatch_send_keys | Send keystrokes / text to a session. Keys are an array — ["text:ls -la", "enter"], ["ctrl:c"], ["text:hello", "tab"], etc. |
shellwatch_read_output | Read session output. afterOffset lets you do incremental reads — pass back the last endOffset you saw. |
shellwatch_close_session | Close a session. (Sessions also close automatically when the MCP transport disconnects.) |
shellwatch_manage_endpoints | List, create, update, or delete SSH endpoints. Useful when you want the agent to provision its own targets — most operators leave this scoped tightly. |
shellwatch_manage_keys | List available SSH keys. |
See the MCP tools reference for the exact schema of each tool.
Notifications
Section titled “Notifications”ShellWatch pushes two kinds of MCP notifications back to the agent:
output_available— new output is ready (debounced ~100ms). CarriessessionIdandoffset. The agent should follow up withshellwatch_read_output(sessionId, afterOffset=offset).session_status— session state changed (open, closed, errored). CarriessessionId,status,endpointId.
Notifications are scoped to the agent’s own sessions only.
Session isolation
Section titled “Session isolation”Each MCP client connection is one AgentSession. Two Claude Desktop instances connecting under the same account get two independent agent sessions and cannot see each other’s terminal sessions through the MCP tools. The Web UI for that same account sees both (labelled (mcp)) so the human owner of the account can observe their own agents — but visibility never crosses to another user’s account.
When the MCP transport disconnects, all owned terminal sessions are closed.
Worked example
Section titled “Worked example”A typical agent flow:
1. shellwatch_manage_endpoints → list endpoints, get an endpointId2. shellwatch_create_session(endpointId) → returns sessionId (the SSH handshake triggers a /sign/:id approval before the session opens)3. shellwatch_send_keys(sessionId, ["text:uname -a", "enter"])4. → output_available notification arrives5. shellwatch_read_output(sessionId, afterOffset=0) → reads "Linux ..."6. shellwatch_send_keys(sessionId, ["text:exit", "enter"])7. → session_status notification → closedIf you want a human to watch the agent live, open the matching session in the Web UI sidebar — the same buffer streams there in real time.