> For the complete documentation index, see [llms.txt](https://docs.pipekit.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.pipekit.io/ai/security-and-transports.md).

# Security & Transports

## Transports

The CLI supports two transports:

* **stdio** *(default)*: the LLM client launches `pipekit mcp` as a subprocess and talks to it over stdin/stdout. This is the recommended path for local LLM-client integrations.
* **HTTP** *(opt-in)*: `pipekit mcp --transport=http` runs an HTTP server speaking [Streamable HTTP](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http) for clients that don't fork subprocesses.

### stdio transport

When a client launches `pipekit mcp` as a subprocess, there's no network surface to defend. All authentication flows through the local CLI token on disk.

### HTTP transport

The HTTP transport defaults to binding `127.0.0.1:8080` and **refuses to bind a non-loopback address unless you also pass `--allow-remote`**. This is a defense against accidentally exposing the MCP server to the LAN.

Every HTTP request must carry an `Authorization: Bearer <token>` header. The token is taken from `--token`, then from `$PIPEKIT_MCP_TOKEN`, otherwise the server generates a fresh 32-byte hex token at startup and prints it to stderr.

Loopback binds additionally apply a Host-header allowlist (matching the bind-side loopback rule) to defend against [DNS rebinding](https://en.wikipedia.org/wiki/DNS_rebinding_attack).

```bash
# loopback HTTP (default address; token is generated and printed)
pipekit mcp --transport=http

# explicit loopback IP and operator-supplied token
PIPEKIT_MCP_TOKEN=$(openssl rand -hex 32) pipekit mcp --transport=http --addr=127.0.0.1:9000

# bind a non-loopback interface (LAN/container); requires opt-in
pipekit mcp --transport=http --addr=0.0.0.0:8080 --allow-remote
```

## Authentication and identity

Tools call into the same Pipekit APIs the CLI itself uses. Each call runs with the identity of the user whose token is at `~/.pipekit/token` (or `$PIPEKIT_CONFIG_DIR/token` if that env var is set). If you switch organizations with `pipekit login`, subsequent tool calls reflect the new context.

Practical implications:

* The agent can do exactly what you can do, no more and no less.
* [Access Control](/concepts/access-control.md) bindings apply to MCP tool calls the same way they apply to CLI commands.
* If your token expires, MCP tool calls return `401 unauthorized` until you run `pipekit login` again. No server restart needed.

## Per-tool approval

There is no per-tool approval gate built into the stdio server itself. That policy lives in the LLM client.

Clients that honor MCP tool annotations prompt before calling tools annotated with `destructiveHint: true`. For the per-tool annotations and which tools are destructive, see [Tool Inventory](/ai/tool-inventory.md).

If your client doesn't surface MCP annotations, assume **every** tool the agent has access to is callable without prompting. Use HTTP transport with an explicit token (or a dedicated CLI token via `$PIPEKIT_CONFIG_DIR`) to bound what the agent can reach.
