> ## Documentation Index
> Fetch the complete documentation index at: https://docs.toolshed.philo.ventures/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Server Overview

> Two MCP transports (stdio for CLI, HTTP for remote) and the tools each one exposes.

Toolshed ships **two MCP server surfaces**, with different tool sets tuned for the different transports.

| Transport                         | Where it lives                                  | Auth                | Tools exposed                                                                                                  |
| --------------------------------- | ----------------------------------------------- | ------------------- | -------------------------------------------------------------------------------------------------------------- |
| **stdio** (`toolshed serve`)      | CLI command, local-only                         | Local session token | [`run`](/mcp/run), [`search_tools`](/mcp/search-tools), [`read_tool`](/mcp/read-tool), [`resume`](/mcp/resume) |
| **HTTP** (`POST /api/mcp/:token`) | Remote connector for Claude Desktop, web agents | MCP token in URL    | [`search_tools`](/mcp/search-tools), [`read_tool`](/mcp/read-tool), [`call_tool`](/mcp/call-tool)              |

Both surfaces front the same plugin catalog. They differ in how the agent **executes** tools:

* **stdio path** lets the agent compose multiple calls inside a TypeScript sandbox (`run`) and pause for user approval mid-execution (`resume`).
* **HTTP path** (used by Claude Desktop's "Add custom connector") executes one tool per call via `call_tool`. There's no sandbox; approval happens upstream in the host UI.

## HTTP transport details

The remote endpoint at `POST /api/mcp/:token` uses Streamable HTTP transport (`@hono/mcp`'s `StreamableHTTPTransport`). Sessions are per-MCP-token and survive across requests:

1. First request: `initialize` JSON-RPC message. Server generates a session id and returns it in the `mcp-session-id` response header.
2. Subsequent requests: client must echo the session id in the `mcp-session-id` request header.
3. Each session caches a per-user `McpServer` instance with `availableTools` already filtered (see below).

**Per-user tool filtering.** When a session is created, the server computes which auth providers the user has connected (union of `tool_connections` rows, Better Auth `account` rows for OAuth, and env-backed API keys for built-ins). `search_tools` and `read_tool` only operate over tools whose effective `authProvider` is in that set, so the agent never sees a tool it can't actually call.

**Token resolution.** When `call_tool` runs a plugin handler, the plugin calls `ctx.auth.getToken("<provider>")`. The server's `resolveToken()` checks three sources in order: per-user `tool_connections` row → Better Auth's stored OAuth token (with auto-refresh) → `process.env["${UPPER}_API_KEY"]` for built-in tools.

## stdio transport details

The CLI's `toolshed serve` command runs an MCP server over stdio via `@toolshed/mcp-host`. It registers the four tools listed above against the runtime (local or Vercel) and the full tool catalog:

```typescript theme={null}
import { createMcpServer } from "@toolshed/mcp-host";

const server = createMcpServer({
  runtime,        // Runtime instance (local or Vercel)
  allTools,       // Full tool catalog
  searchTools,    // (query, limit) => ToolDefinition[]
  elicitation,    // Optional ElicitationEngine
  resumeRemote,   // Optional remote resume callback
});
```

The stdio surface does *not* filter by connected providers — the CLI flow assumes the local user has whatever credentials they need.

## Recommended agent workflow

Same pattern on both transports:

1. **Discover** — call `search_tools` with a keyword to find relevant tools.
2. **Inspect** — call `read_tool` to see the full input/output schema.
3. **Execute** — `call_tool` (HTTP) or `run` (stdio) to invoke the chosen tool.
4. **Approve** — only on stdio: if the result includes a `paused` field, call `resume`.
