# pi-satori-bridge

`pi-satori-bridge` connects a PI agent to Satori by exposing Satori's MCP tools inside PI and proxying every call through `satori-cli`.

Repository: https://github.com/ham-zax/satori

## How this helps PI agents

Without this extension, PI does not have Satori tools registered in its tool surface.

With this extension:

1. PI sees Satori tools as native extension tools.
2. The extension forwards tool calls to `satori-cli`.
3. `satori-cli` talks to Satori MCP and returns deterministic tool responses.

Connection flow:

```text
PI Agent -> pi-satori-bridge -> satori-cli -> Satori MCP
```

## Exposed tools

- `list_codebases`
- `manage_index`
- `search_codebase`
- `call_graph`
- `file_outline`
- `read_file`

Forwarding command shape:

```bash
satori-cli tool call <toolName> --args-json '<json>'
```

## Install and run

Install from npm:

```bash
pi install npm:pi-satori-bridge
```

Load local extension directly:

```bash
pi --no-extensions -e /absolute/path/to/satori-bridge
```

Health check inside PI:

```text
/satori-mcp
```

This runs `satori-cli tools list` and confirms connectivity/reflection.

Detailed diagnostics (resolved config/env/transport + quick health check):

```text
/satori-mcp-doctor
```

## Config resolution order

The bridge resolves config in this order:

1. `SATORI_CLI_CONFIG` (explicit config path)
2. `<cwd>/.pi/satori-bridge.json` (project local)
3. `~/.pi/agent/satori-bridge.json` (global legacy shortcut)
4. `~/.pi/agent/extensions/satori-bridge/config.json` (global extension path)

If `SATORI_CLI_CONFIG` is set to a missing file, the bridge now fails fast with a direct error that names the missing path.

## CLI resolution order

After config is loaded, the bridge resolves how to invoke `satori-cli` in this order:

1. Explicit command (`SATORI_CLI_COMMAND` or config `command`)
2. Local CLI path (`SATORI_CLI_LOCAL_PATH` / config `cliPath` / `localPath`, default `packages/mcp/dist/cli/index.js`)
3. npm fallback (`npx -y --package <npmPackage> satori-cli`)

Start from `config.example.json`:

```json
{
  "envFile": ".env.satori",
  "guardRecovery": "auto",
  "forceNpx": false,
  "npmPackage": "@zokizuan/satori-mcp@latest",
  "startupTimeoutMs": 180000,
  "callTimeoutMs": 600000,
  "debug": false
}
```

For source-checkout development, point to a local CLI command:

```json
{
  "command": "pnpm",
  "args": [
    "-C",
    "/absolute/path/to/satori/packages/mcp",
    "exec",
    "tsx",
    "src/cli/index.ts"
  ],
  "envFile": ".env.satori"
}
```

## Runtime behavior

- `path` tool arguments are absolute paths.
- If a model prepends `@` to path-like arguments, the bridge strips the leading `@` before forwarding.
- `file_outline.file` is repo-relative to the indexed codebase root.
- Missing `envFile` is non-fatal (bridge warns and continues).
- Bridge error messages include actionable hints (missing config path, command-not-found, likely missing env vars, stdout JSON guard hint), and redact likely secrets in diagnostics.
- Auto-recovery retries once (guard-off) only for protocol/transport failures.
- Valid tool-level non-ok responses (for example `not_ready` or `blocked`) are passed through, not retried.
- If `manage_index` returns `status=\"blocked\"` with `reason=\"unnecessary_reindex_ignore_only\"`, use `manage_index {\"action\":\"sync\",\"path\":\"...\"}`. Override only when explicitly intended via `allowUnnecessaryReindex=true`.
- Default timeouts are `startupTimeoutMs=180000` and `callTimeoutMs=600000`; `/satori-mcp` health check clamps both to `15000`.
- For reproducible behavior across teams, pin `npmPackage` to a specific `@zokizuan/satori-mcp@<version>` instead of `@latest`.

## Optional env vars

- `SATORI_CLI_COMMAND`
- `SATORI_CLI_ARGS_JSON`
- `SATORI_CLI_CWD`
- `SATORI_CLI_LOCAL_PATH`
- `SATORI_CLI_FORCE_NPX`
- `SATORI_CLI_NPM_PACKAGE`
- `SATORI_CLI_STARTUP_TIMEOUT_MS`
- `SATORI_CLI_CALL_TIMEOUT_MS`
- `SATORI_CLI_DEBUG`
- `SATORI_CLI_STDOUT_GUARD` (`drop` default, `redirect`, `off`)
- `SATORI_CLI_GUARD_RECOVERY` (`auto` default, `never`)
- `SATORI_CLI_CONFIG`

Satori runtime variables (embedding/vector/API keys) can be set via shell env or `envFile`.
