Documentation · Operating
Setting up logging
Both the web console and every generated server write to the container’s stdout, so docker logs and any standard log driver or sidecar collect them. Generated-server lines are tagged
[mcp:<config>] and generation lines [gen:<config>]. The same output is kept per-runtime under the
config directory, which is what the Runtime page tails.
One line per tool call
MCP-CALL {"tool":"get_customer","outcome":"ok","ms":12,"args":["p_id"]}
Outcomes are ok, not-found, document-changed, pool-exhausted, database-error or error.
Argument names are recorded; argument values never are, because a model chose them and they can carry anything.
This is not an audit trail
The process being audited writes it, so it carries no durability or tamper-evidence guarantee. If you need a record you can rely on, configure a sink — see Setting up auditing, which covers both generated servers and the proxy’s own access records.
Choosing the backend at run time
DAO_LOG_TYPE is set when the code is generated, but the right backend depends on where it runs — a
console logger is fine on a desktop and corrupts the protocol stream over stdio; a file logger writes
to a disk that dies with the container.
-e MCPDBWIZARD_LOG_BACKEND=jul # console | jul | text | slf4j | log4j2, or any LogInterface class
Unset, the generated choice applies. A name that cannot be loaded stops the server, deliberately: silently falling back would leave you believing you had redirected the logs when you had not.
The stdio footgun
Over stdio, stdout carries the MCP protocol frames. Anything else written there corrupts the
stream, and the client’s error names nothing to do with logging. This cannot happen over HTTP, which
is the deployed shape — but if you launch a server over stdio, point logging at System.err.