You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/guides/audit-logging.md
+14-11Lines changed: 14 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -157,7 +157,7 @@ Add an `audit` section to `~/.config/mcp/servers.json`:
157
157
| Field | Default | Description |
158
158
|---|---|---|
159
159
|`enabled`|`true`| Enable/disable audit logging |
160
-
|`output`|`file` (global), auto-promoted in `mcp serve` to `file+stdout`(HTTP) or `file+stderr`(stdio) | Output destination: `file` (ChronDB, queryable), `stdout`, `stderr` (JSON lines), `file+stdout`, `file+stderr` (ChronDB **and** JSON lines), or `none`. The global default stays `file` so CLI subcommands (`mcp roam ...`, `mcp gh ...`) keep stdout clean for their results. `mcp serve` upgrades the default to a dual-sink mode so audit is visible in `docker logs`/`kubectl logs` without an extra command, while still persisting to ChronDB for `mcp logs` queries. Explicit user values are preserved as-is. |
160
+
|`output`|unset (→ `file` for CLI, `file+stdout`for `serve --http`, `file+stderr`for `serve`stdio) | Output destination: `file` (ChronDB, queryable), `stdout`, `stderr` (JSON lines), `file+stdout`, `file+stderr` (ChronDB **and** JSON lines), or `none`. Internally `Option<AuditOutput>` — leaving it unset means "use the per-context default" (CLI safety vs serve visibility). Any explicit value (including `"file"`) bypasses the auto-promotion in `mcp serve`. |
|`path`|`~/.config/mcp/audit/data`| ChronDB data directory |
163
163
|`index_path`|`~/.config/mcp/audit/index`| ChronDB index directory |
@@ -221,14 +221,16 @@ When disabled, the logger is a no-op and the database is not initialized — zer
221
221
222
222
The `output` field controls where audit entries go.
223
223
224
-
The **global default is `file`** — entries are persisted to ChronDB and the CLI stays silent on stdout (so `mcp roam ... | jq` and similar pipelines aren't corrupted by audit JSON interleaved with command output).
224
+
The configuration distinguishes **explicit values from absent ones**. Internally `output` is `Option<AuditOutput>`: missing from the config and unset in `MCP_AUDIT_OUTPUT` means `None` (default); a present value means `Some(...)` (explicit). The distinction is what lets `mcp serve` auto-promote the default without ever overwriting a deliberate operator choice.
225
225
226
-
In **`mcp serve` only**, the default is auto-promoted:
226
+
**CLI subcommands** (`mcp roam ...`, `mcp gh ...`, etc.) resolve `None` to `file` — entries are persisted to ChronDB and stdout stays clean (so pipelines like `mcp ... | jq` aren't corrupted by audit JSON interleaved with command output).
227
227
228
-
-**HTTP transport** (`mcp serve --http ...`): `file` → `file+stdout`. Audit is mirrored on stdout so it's visible in `docker logs`/`kubectl logs` without an extra command, while still persisting to ChronDB for `mcp logs` queries.
229
-
-**Stdio transport** (`mcp serve`): `file` → `file+stderr`. Stdout in stdio mode is the JSON-RPC channel, so the mirror goes to stderr instead.
228
+
**`mcp serve`** resolves `None` to a dual-sink mode:
230
229
231
-
Any explicit value in the config file or `MCP_AUDIT_OUTPUT` env var **bypasses** the auto-promotion — your choice is respected.
230
+
-**HTTP transport** (`mcp serve --http ...`): `None` → `file+stdout`. Audit is mirrored on stdout so it's visible in `docker logs`/`kubectl logs` without an extra command, while still persisting to ChronDB for `mcp logs` queries.
231
+
-**Stdio transport** (`mcp serve`): `None` → `file+stderr`. Stdout in stdio mode is the JSON-RPC channel, so the mirror goes to stderr instead.
232
+
233
+
Any explicit value in the config file or `MCP_AUDIT_OUTPUT` env var (**including `"file"`**) **bypasses** the auto-promotion. To force chrondb-only output in `mcp serve`, set `"output": "file"` explicitly — it survives the resolution untouched.
232
234
233
235
Each stdout/stderr line is a complete `AuditEntry` JSON object:
234
236
@@ -242,14 +244,15 @@ The mirror is emitted **before** the ChronDB write, so entries stay visible even
|_unset_ → `file` (CLI default) / `file+stdout` (serve http) / `file+stderr` (serve stdio) | varies | varies | varies | when ChronDB is active |
248
+
|`file` (explicit) | ✅ | — | — | ✅ |
249
+
|`file+stdout`| ✅ | ✅ | — | ✅ |
250
+
|`file+stderr`| ✅ | — | ✅ | ✅ |
248
251
|`stdout`| — | ✅ | — | — |
249
252
|`stderr`| — | — | ✅ | — |
250
253
|`none`| — | — | — | — |
251
254
252
-
Pick `file` explicitly if you want chrondb-only **even in `mcp serve`**(an explicit value skips the auto-promotion). Pick `stdout`/`stderr` only when you can't persist (read-only filesystem, ephemeral containers without a volume). Pick `file+stderr` if your transport is `stdio` or you want to keep stdout reserved for application output.
255
+
Pick `file` explicitly if you want chrondb-only **even in `mcp serve`**— explicit values skip the auto-promotion. Pick `stdout`/`stderr` only when you can't persist (read-only filesystem, ephemeral containers without a volume). Pick `file+stderr` if your transport is `stdio` or you want to keep stdout reserved for application output.
When using `stdout` or `stderr` alone (without `file`), `mcp logs` queries are not available — there's no database to query. Use your log aggregation pipeline instead.
263
266
264
-
> **stdio transport caveat**: in `mcp serve` without `--http` (stdio mode), stdout is the JSON-RPC channel. The default auto-promotion picks `file+stderr`. If the user explicitly picks `stdout` or `file+stdout`, it's rewritten to the stderr variant with a warning.
267
+
> **stdio transport caveat**: in `mcp serve` without `--http` (stdio mode), stdout is the JSON-RPC channel. The default auto-promotion picks `file+stderr`. If the operator explicitly picks `stdout` or `file+stdout`, it's rewritten to the stderr variant with a warning so the JSON-RPC channel stays clean.
265
268
266
269
Set `output` to `none` to disable audit entirely without touching the `enabled` flag.
|`MCP_LOG_FORMAT`|`text`| Log format: `text` or `json` (structured, for log drivers) |
180
180
|`MCP_AUDIT_ENABLED`|`false` (in Docker image) | Disable audit for read-only fs |
181
-
|`MCP_AUDIT_OUTPUT`|`file` (auto-promoted to `file+stdout` in `mcp serve --http`) |`stdout`/`stderr` for log driver only, `file` for ChronDB only (skips auto-promotion in serve), `file+stdout`/`file+stderr` for both, `none` to disable |
181
+
|`MCP_AUDIT_OUTPUT`|unset (→ `file+stdout` in `mcp serve --http`) |`stdout`/`stderr` for log driver only, `file` for ChronDB only (setting this env var is treated as explicit and skips auto-promotion in serve), `file+stdout`/`file+stderr` for both, `none` to disable |
182
182
|`MCP_AUDIT_PATH`|`~/.config/mcp/db/data`| Override audit data path |
183
183
|`MCP_AUDIT_INDEX_PATH`|`~/.config/mcp/db/index`| Override audit index path |
184
184
|`MCP_AUTH_CONFIG`| — | Inline `auth.json` content (read-only, writes are no-ops). Same idea as `MCP_SERVERS_CONFIG`. |
| `MCP_AUDIT_OUTPUT` | `file` (auto-promoted to `file+stdout` in `mcp serve --http`) | `stdout` for cluster log pipeline only, `file` for PVC only (skips auto-promotion), `file+stdout` for both PVC and pipeline (the auto-promoted default in serve), `none` to disable |
285
+
| `MCP_AUDIT_OUTPUT` | unset (→ `file+stdout` in `mcp serve --http`) | `stdout` for cluster log pipeline only, `file` for PVC only (setting this env var is treated as explicit and skips auto-promotion), `file+stdout` for both PVC and pipeline (the auto-promoted default in serve), `none` to disable |
Copy file name to clipboardExpand all lines: docs/reference/environment-variables.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,7 +14,7 @@ These variables configure `mcp` behavior:
14
14
|`MCP_PROXY_REQUEST_TIMEOUT`|`120`| (proxy mode) Hard upper bound, in seconds, that any single client request can spend inside `mcp serve` before the proxy returns a JSON-RPC error. Acts as a belt-and-suspenders boundary on top of the per-transport `MCP_TIMEOUT`. |
15
15
|`MCP_CLASSIFIER_CACHE`|`~/.config/mcp/tool-classification.json`| Path to the persistent tool read/write classification cache (see [`mcp acl classify`](./cli.md#mcp-acl-classify)). Override this in CI/containers that cannot write to `$HOME`. |
16
16
|`MCP_DISCOVERY_CONCURRENCY`|`10`| Max parallel `--help` calls during CLI subcommand discovery (see [CLI as MCP](../guides/cli-as-mcp.md)) |
17
-
|`MCP_AUDIT_OUTPUT`|`file` (global), auto-promoted in `mcp serve` to `file+stdout`(HTTP) / `file+stderr`(stdio) | Audit output destination: `file` (ChronDB, queryable via `mcp logs`), `stdout`, `stderr` (JSON lines for container log drivers), `file+stdout`, `file+stderr` (ChronDB **and** JSON lines for both `mcp logs` and a log driver), or `none` (disable). Global default is`file`so CLI subcommands keep stdout clean for command output. `mcp serve`upgrades to a dual-sink default so audit is visible in `docker logs`/`kubectl logs` without an extra command. Any explicit value (config or env) bypasses the auto-promotion. |
17
+
|`MCP_AUDIT_OUTPUT`|unset (→ `file` for CLI, `file+stdout`for `serve --http`, `file+stderr`for `serve`stdio) | Audit output destination: `file` (ChronDB, queryable via `mcp logs`), `stdout`, `stderr` (JSON lines for container log drivers), `file+stdout`, `file+stderr` (ChronDB **and** JSON lines for both `mcp logs` and a log driver), or `none` (disable). Setting this env var marks the value as **explicit** and skips the per-context auto-promotion (so `MCP_AUDIT_OUTPUT=file` reliably forces chrondb-only output, including in `mcp serve`). Leaving it unset (and the config field absent) lets each context pick its safe default —`file`for CLI to keep stdout clean for command output, dual-sink for `mcp serve` so audit shows up in `docker logs`/`kubectl logs`. |
18
18
|`MCP_AUDIT_ENABLED`|`true`| Set to `false` or `0` to disable audit logging and database initialization. Overrides `audit.enabled` in the config file. |
19
19
|`MCP_AUDIT_PATH`|`~/.config/mcp/db/data`| Override the ChronDB data directory. Overrides `audit.path` in the config file. |
20
20
|`MCP_AUDIT_INDEX_PATH`|`~/.config/mcp/db/index`| Override the ChronDB index directory. Overrides `audit.index_path` in the config file. |
0 commit comments