# JUJU 0.7.1 — Compact Tool Surface for remote clients

Upgrade:

```bash
npm install -g juju-mcp@0.7.1
```

Restart the running `juju`/`juju stdio` process, then make the client rescan
its tools (ChatGPT: refresh/recreate the MCP app; Codex/Claude Code: reconnect).
No OAuth re-login, client re-registration, ACL, trust, desktop-consent or
schedule change is required.

## What changed

- **HTTP now serves a compact 19-tool surface by default** (ChatGPT and other
  remote connectors): `project_overview`, `juju_discover`, and 17 domain
  gateways covering every one of the 74 capabilities. Serialized tool-list
  payload drops from ~236 KB to ~47 KB (−80.3%).
- **STDIO keeps the full 74-tool catalog by default** — Codex, Claude Code,
  Cursor and existing local integrations are unchanged.
- Overrides: `toolSurface: "compact" | "full"` in the global config, or
  `juju start --tools full` / `juju stdio --tools compact` per run. Exposure
  only; permissions, scopes, trust, approvals and guards are unchanged.
- `juju_discover` finds operations (`query`/`domain`) and returns one
  operation's exact input JSON Schema with a deterministic `schemaHash`.
- New startup diagnostic proves what is being served:
  `[juju] mcp tool surface | transport=http | surface=compact | tools=19 | schemaBytes=…`.
- `schemas/tools.compact.json` ships next to the unchanged `schemas/tools.json`.
- `project_overview` (compact only) reports `toolSurface`,
  `compactToolCount`, `fullToolCount`.

## Using the compact surface

```text
project_overview
juju_discover  { query: "edit a TypeScript file" }
juju_read      { operation: "read_files",  args: { files: [{ path: "src/example.ts" }] } }
juju_write     { operation: "edit_file",   args: { path: "src/example.ts", edits: [...], expectedHash: "…" } }
juju_read      { operation: "read_files",  args: { files: [{ path: "src/example.ts" }] } }
```

Media example:

```text
juju_discover  { query: "transcribe local video" }
juju_media     { operation: "media_open",       args: { path: "clip.mp4", idempotencyKey: "open-1" } }
juju_media     { operation: "media_transcribe", args: { mediaId: "…", idempotencyKey: "asr-1" } }
```

Rules the model must follow: `workspaceId`/`workspaceEpoch` go at the TOP level
of the gateway call, never inside `args`; reuse the same `idempotencyKey` when
retrying the same effectful call; call `juju_discover` with
`operation="<name>"` when unsure of a schema.

## Security

A gateway grants nothing. Every dispatch re-runs the target operation's own
checks through the same pipeline as a direct call: OAuth scope of the TARGET,
workspace ACL, workspaceId/epoch, strict original input schema, trust-mode
policy and local approvals (bound to the target operation), path/secret
guards, hash conflicts, idempotency and audit. A `juju:read`-only token cannot
write or execute through any gateway; `inspect` mode still requires per-action
owner approval. See ADR-029 and SECURITY.md.

## Why (write/edit investigation)

Server-side write/edit was verified healthy on 0.7.0 (real HTTP+OAuth and
STDIO fixtures; live audit shows 112/91 successful write/edit calls in 48 h).
The 0.7.0-specific change a remote client sees is the 74-tool catalog it must
ingest at scan time; the compact surface removes that load. A hard per-client
tool limit is NOT claimed. Re-testing through the real ChatGPT UI is a manual
gate — see MANUAL_ACCEPTANCE.md.

## Release gate (2026-09-10, macOS arm64, Node v22.23.2)

`npm run build && npm run test:all` exit 0 — **412/412 tests in 50 files**
(400 core + 12 packaging), typecheck and lint clean, no skipped tests in the
recorded run. `npm audit --omit=dev`: see release evidence. Fresh-registry
install verification is recorded in `release-evidence/0.7.1/`.
