An MCP in production is a black box from the end client's point of view. The agent decides, invokes, reads the result, decides again. when something goes wrong, the only way to understand what happened is the log trace you left behind.
If you log nothing, in 3 days you'll have a ticket: "the agent didn't assign Em's shift to the rendezvous". And you won't know:
Good logging answers all of those in 30 seconds.
tool.start on entry. records name, params, correlation request_id.tool.success right before the happy-path return. records key result, duration.tool.error on each error path. records code, params, duration.async function handle(params) {
const request_id = crypto.randomUUID();
const startedAt = Date.now();
logger.info("tool.start", { tool: "assign_shift", request_id, params });
// ... logic ...
if (failure) {
logger.warn("tool.error", {
tool: "assign_shift",
request_id,
duration_ms: Date.now() - startedAt,
code: "...",
params,
});
return { ok: false, error: { code, message } };
}
logger.info("tool.success", {
tool: "assign_shift",
request_id,
duration_ms: Date.now() - startedAt,
result_summary: { assignment_id },
});
return { ok: true, assignment_id };
}request_id: what makes the log usableWithout request_id, the logs from concurrent invocations interleave and you can't reconstruct any trace. With request_id (generated at the start and propagated through the handler), a grep request_id=abc123 brings you the entire story of that specific invocation.
Advanced bonus: if your system has distributed tracing (OpenTelemetry, etc.), request_id can be a trace_id that connects with logs from your downstream services (DB, external APIs). That correlation is the holy grail of debugging in distributed systems.
params, redact them: { token: "***" }.On the right you have assign_shift with validations but no logging. Add start, success, and error logs on each path. Use a correlation request_id.
A handler with no logs is a handler you'll have to rewrite as soon as it fails in production. Low cost, high benefit, do it from day 1.