Audit Logging
- reference
Record tool calls, authorization denials, and guardrail blocks in an audit log.
The MCP server writes audit records separately from the CB_MCP_LOG_* operational logs.
Audit logging is off by default.
It applies to both stdio and Streamable HTTP transport modes.
Authorization events occur only on Streamable HTTP.
Enabling Audit Logging
Set CB_MCP_AUDIT_LOG_ENABLED=true.
By default, the server writes audit records to stderr, which is the console sink.
Under stdio, the console sink never writes to stdout, because stdout carries the protocol messages.
To keep the records, add the file sink and set a path:
CB_MCP_AUDIT_LOG_ENABLED=true
CB_MCP_AUDIT_LOG_SINKS=console,file
CB_MCP_AUDIT_LOG_FILE_PATH=/var/log/couchbase-mcp/audit.log
If you list the file sink without a path, the server still starts.
It drops the file sink and records an error.
Configuration
| Environment Variable | CLI Argument | Default | Description |
|---|---|---|---|
|
|
|
Turns audit logging on. |
|
|
|
Comma-separated list of sinks. Allowed values are |
|
|
None |
Path of the audit log file. Needed when |
|
|
|
Size in MB that the live audit file can reach before the server rotates it. |
|
|
|
Age that the live audit file can reach before the server rotates it. |
|
|
|
Number of rotated backups to keep for each audit file, not counting the live file. |
|
|
|
Includes tool arguments in audit records. See Capturing Tool Arguments. |
|
|
None |
Numeric event IDs to turn off, as a comma-separated list or a path to a file. See Audit Events. |
Log Rotation
The server supports both time-based and size-based rotation of the audit file. The two settings are independent. The server rotates the file when either one falls due first.
Time-based rotation uses the format <value><unit>.
The unit is d for 24 hours or w for 7 days.
Examples are 1d, 30d, 1w, and 8w.
The server compresses rotated files with gzip and names them with the UTC rotation time.
It keeps the number of backups that CB_MCP_AUDIT_LOG_RETENTION_MAX_BACKUPS sets.
With 0, the server keeps no backups and truncates the live file at each rotation.
Setting both the size and the interval to 0 gives a single file with no limit.
If a value is unusable, the server falls back to the default and logs a warning at startup.
Retention and Per-Process Files
Each server process writes its own audit file.
The server inserts the hostname and process ID before the extension, so audit.log becomes audit.myhost.1234.log.
Under stdio, this is required.
Each client starts its own server process, so several processes often run at once.
Without per-process names, they would write to one file and interleave records.
Per-process files have consequences for retention that you need to plan for:
-
Retention applies to one file, not to the directory:
CB_MCP_AUDIT_LOG_RETENTION_MAX_BACKUPSbounds the rotated copies of the file that the running process owns. A process never prunes the files of another process. Nothing removes the files of processes that have exited. -
Rotation happens only while a process runs: A
stdiosession that lasts an hour never reaches a one-day interval, so the server never rotates its file. The file stays on disk as a single file after the client disconnects. -
Files accumulate with the number of server starts: Under
stdio, this is normal use, not an error case. Every client session and every restart leaves a file behind. Total disk use grows over time, even when each file stays within its configured size.
To keep audit storage bounded:
-
Size the volume for the number of sessions you expect, not for one file.
-
Remove old
audit..logfiles with a scheduled job on the host, after you collect the records you need to keep. -
Forward records off the host with a log shipper if you need long retention. This also protects the records against local file deletion.
-
Prefer the Streamable HTTP transport, where one long-lived process serves all clients. Rotation and retention then behave as configured, because the process lives long enough to apply them.
| Do not delete an audit file that a running server still has open. Collect or forward the records before you delete anything. Audit retention can be a compliance requirement, and you cannot recover a deleted file. |
Reused Process IDs
An operating system reuses process IDs, so a new server process can find an audit file that an earlier process with the same ID created. The server handles this. When it opens an existing file, it anchors the rotation interval to the last modification time of that file, not to the current time. The file from the earlier process is already past the rotation interval, so the server rotates it to a backup on the first record it writes. The server preserves the earlier records in the backup, and the new process starts a clean file. Two processes never append to the same file.
Capturing Tool Arguments
By default, audit records exclude the following:
-
Tool arguments
-
Query text
-
Document bodies
-
Results
-
Raw tokens
Set CB_MCP_AUDIT_LOG_TOOL_ARGS=true to add the tool arguments to each record.
The server has no redaction.
It writes argument values verbatim, including SQL++ text and the full document bodies that document-write tools receive.
| Tool arguments can contain sensitive information. Keep audit files apart from the operational log files, and limit who can read them. Do not send audit records to the same destination as your operational logs. |
Audit Events
Each event has a numeric ID.
The server records all events by default.
You can turn off some of the events with CB_MCP_AUDIT_LOG_DISABLED_EVENTS.
The tables show which ones.
The server ignores an unknown ID and logs a warning.
For example, CB_MCP_AUDIT_LOG_DISABLED_EVENTS=61490,61492 turns off the document read and index read events.
The server always records write events, security events, and the query and search events.
It refuses a request to turn them off and logs a warning.
Event ID Blocks
The IDs fall into three blocks. The Couchbase Server tools and the Operational Insights tools each have their own block for tool calls.
| Block Starts At | Covers |
|---|---|
57344 |
Events that both servers share: server lifecycle, sessions, authorization, and guardrails. |
61440 |
Tool calls of the Couchbase Server tools. This page lists them. |
65536 |
Tool calls of the Operational Insights tools. See Operational Insights Audit Logging. |
Some event names appear in more than one block.
For example, schema read is 61489 for the Couchbase Server tools and 65585 for the Operational Insights tools.
Write alert rules against the numeric ID, not the name.
Within a tool-call block, the ID range shows the kind of event:
| Offset From the Block Start | Kind of Event | Can Be Turned Off |
|---|---|---|
+48 to +63 |
Read |
Yes |
+64 to +79 |
Single event ( |
No |
+80 to +95 |
Write |
No |
An event outside the read range cannot be turned off, but that no longer means the event is a write. The tables on this page show which events you can turn off.
Server, Session, Authorization, and Guardrail Events
| ID | Event | Description | Can Be Turned Off |
|---|---|---|---|
57344 |
server started |
The MCP server started. |
No |
57345 |
server stopped |
The MCP server stopped cleanly. |
No |
57346 |
server configuration |
The resolved configuration at startup, including read-only mode and the tools the server withheld or turned off. |
No |
57360 |
session initialized |
An MCP client finished the initialize handshake. |
Yes |
57376 |
token rejected |
The server rejected a bearer token during verification. |
No |
57377 |
scope check denied |
The token did not carry a scope that the tool requires. |
No |
57488 |
write blocked (read-only mode) |
The server refused a SQL++ statement that modifies data or structure, because read-only mode is on. |
No |
57490 |
confirmation declined |
The user rejected the confirmation request for a tool that requires confirmation. |
No |
57491 |
confirmation skipped |
A tool that requires confirmation ran without it, because the client does not support elicitation. |
No |
A missing server stopped record means the server did not stop cleanly.
Tool Call Events
Each tool call produces one record.
Most categories have a read event and a write event, and the server classifies each call as one or the other.
The query and search categories have one event each.
See Single-Event Categories.
| ID | Event | Description | Tools | Can Be Turned Off |
|---|---|---|---|---|
61488 |
cluster read |
Reads cluster information, health, or statistics. |
|
Yes |
61489 |
schema read |
Reads buckets, scopes, collections, or schemas. |
|
Yes |
61490 |
document read |
Reads a document. |
|
Yes |
61492 |
index read |
Reads index definitions or recommendations. |
|
Yes |
61493 |
performance read |
Reads query performance data or in-flight requests. |
|
Yes |
61495 |
config read |
Reads the server configuration or reference data. |
|
Yes |
61507 |
query |
Runs or explains a SQL++ query, or runs a vector query. One event for every call, whatever the call does. |
|
No |
61510 |
search |
Queries or manages Search indexes. One event for every call, whatever the call does. |
|
No |
61520 |
cluster write |
Changes the cluster. |
No tool today |
No |
61521 |
schema write |
Creates or deletes scopes or collections. |
|
No |
61522 |
document write |
Creates, changes, or deletes a document. |
|
No |
61524 |
index write |
Creates, builds, or drops an index. |
|
No |
61525 |
performance write |
Cancels an in-flight query request. |
|
No |
61527 |
config write |
Changes the server configuration. |
No tool today |
No |
The server records a tool that has no classification as a write.
That record carries unclassified: true, and you cannot turn it off.
Single-Event Categories
The query and search categories are each recorded as one event.
The server does not record whether the operation read or wrote.
For queries, turn on CB_MCP_AUDIT_LOG_TOOL_ARGS to capture the statement text, after you read Capturing Tool Arguments.
For search, a search query and a change to a Search index share one event ID.
The tool_name field on each record identifies the tool that ran.
You cannot turn off either event. A single event covers the writes of its category as well as the reads, so turning it off would remove the record of a statement that modified data, or of a Search index being deleted.
Read-only mode is not affected. The server enforces it separately, and it does not depend on this classification.
Record Format
Records use JSON Lines format, with one record per line. The field names match Couchbase Server and Sync Gateway audit logs. The server omits any field that has no value.
| Field | Description |
|---|---|
|
Numeric event ID. |
|
Event name. |
|
Event description. |
|
UTC time with millisecond precision, such as |
|
The caller, as |
|
The MCP server |
|
A server-generated UUID4 that identifies one MCP request. Every record produced while handling that request shares the same |
|
|
|
Present when the outcome is not |
|
The tool that the request called. Present on tool call and guardrail records. |
|
The OAuth scope that the tool requires, |
|
The keyspace that the call targeted. |
|
The Couchbase user that the server connects as. |
|
The OAuth client ID from the token. Present on |
|
The scopes in the token of the caller. Present on |
|
The scopes that the tool needs and the token lacks. Present on refusals for a missing scope. |
|
The result of the confirmation request, for a tool that requires confirmation. |
|
The MCP protocol version that the client and server agreed on. Present on |
|
The name of the MCP client, such as Claude Desktop or Cursor. Present on |
|
The version of the MCP client. Present on |
|
The tool arguments. Present only when |
|
|
Example Records
A document read that failed, from a stdio client:
{
"id": 61490,
"name": "document read",
"description": "A document read operation was requested through a tool",
"timestamp": "2026-10-12T08:07:21.603Z",
"real_userid": { "domain": "local", "user": "root" },
"server": { "version": "1.0.2rc4", "host": "vm" },
"cid": "ffbf8f99-a96e-4b65-8dfb-1c4e720ed5b7",
"outcome": "error",
"reason": "execution_error",
"tool_name": "get_document_by_id",
"required_scope": "read",
"ks": "travel-sample.inventory.airline",
"cb_userid": "test-user"
}
A write that the server denied because the token has only the read scope, from a Streamable HTTP client:
{
"id": 57377,
"name": "scope check denied",
"description": "A required OAuth scope was not granted by the presented token",
"timestamp": "2026-08-05T09:15:02.101Z",
"real_userid": { "domain": "oauth", "user": "agent-svc-7" },
"server": { "version": "1.1.0", "host": "vm" },
"cid": "req-7c19",
"outcome": "denied",
"client_id": "agent-svc-7",
"scopes": ["couchbase-mcp:read"],
"tool_name": "upsert_document_by_id",
"required_scope": "write",
"reason": "missing_scope"
}
Reliability
Audit logging never interferes with serving requests.
If the server cannot write a record, the request still proceeds.
The server counts the records it wrote, dropped, and failed to write, and reports the counts through the get_server_configuration_status tool.
Each sink writes through a bounded in-memory queue of 10,000 records and a background writer thread. When the queue is full, the server drops records and counts them. On shutdown, the server flushes the queue within a bounded wait. The server drops the records that are still queued when that wait expires, and counts them.
The file sink writes to the local filesystem only.
The server has no syslog output and does not forward records to the Couchbase Server audit daemon.