MCP Logging
May 11, 2026 · View on GitHub
The server supports the MCP logging capability, allowing clients to receive debugging information via structured log messages.
Server Log Output
By default, server logs (startup messages, errors, debug output) go to stdout in HTTP mode and are silenced in stdio mode (stdout is reserved for the MCP protocol).
Use log_file to redirect server logs to a file, which works in both modes:
log_level = 2
log_file = "/var/log/kubernetes-mcp-server.log"
Or via CLI flag:
kubernetes-mcp-server --log-file /var/log/kubernetes-mcp-server.log --log-level 2
| Setting | Description |
|---|---|
log_file | Path to the log file. Created if it does not exist; opened in append mode (O_APPEND). Use the special value stderr to route logs to stderr without opening a file. |
log_level | Verbosity level 0-9 (default 0). Higher values produce more output. See the verbosity reference below for details. |
Note for stdio mode: server-side diagnostic logs are silenced by default under the STDIO transport because stdout is the MCP protocol channel. Set log_file to a path on disk, or to the special value stderr (the MCP spec permits stderr in stdio mode), to recover them.
Verbosity Reference
| Level | What is logged |
|---|---|
0 | Default level - Critical system errors and failures. |
1 | Level 1 - MCP server configuration reloads, OAuth provider changes, OpenTelemetry initialization, authentication failures, well-known proxy failures. |
2 | Level 2 - Workspace watching/polling, KCP workspace discovery, HTTP request handling, OpenTelemetry sampler selection, OTLP exporter creation. |
3 | Level 3 - Detailed workspace discovery, workspace polling results, KCP client creation failures. |
4 | Level 4 - TLS handshake errors (health checks), JWT client assertion details, OpenTelemetry resource creation. |
5 | Level 5 - HTTP request logging with method, path, status, and duration. |
6 | Level 6 - MCP protocol logging (incoming/outgoing method calls, parameters, results, errors), trace context extraction. |
7 | Level 7 - MCP tool call headers, GetMeta() panic recovery. |
Warning
Treat log_file as a credential when log_level >= 6. Level 6 dumps
full MCP request/response parameters and results, and level 7 dumps
tool-call request headers. Tools that accept manifests
(resources_create_or_update, helm_install, apply_resource, etc.)
routinely carry Secret contents, kubeconfig bytes, OIDC bearer tokens,
and OAuth refresh tokens — anything that lands in these payloads.
The server applies two layers of redaction before writing:
- Header name denylist —
Authorization,Proxy-Authorization,Cookie,X-Api-Key,X-Auth-Token, andKubernetes-Authorizationare dropped entirely at V(7). - Content sanitization — every V(6) param/result dump and the V(7)
header buffer pass through a regex pass that redacts inline
Bearer/Basiccredentials, JWTs, JSON"token"/"secret"/"password"/"api_key"fields, AWS/GitHub/GitLab/GCP/Azure/OpenAI/ Anthropic key shapes, PEM private-key blocks, and DB connection strings (postgres/mysql/mongodb).
Both layers are best-effort denylists. Secret material that doesn't match a known shape — for example, raw YAML keys in a kubeconfig manifest argument, or a custom vendor token format — will pass through unchanged.
Recommended posture: leave log_level at 0–5 for production, store
log_file on a filesystem with the same access-control posture as your
kubeconfig, and avoid sharing rotated log files outside of trusted
incident-response channels.
For Clients
Clients can control log verbosity by sending a logging/setLevel request:
{
"method": "logging/setLevel",
"params": { "level": "info" }
}
Available log levels (in order of increasing severity):
debug- Detailed debugging informationinfo- General informational messages (default)notice- Normal but significant eventswarning- Warning messageserror- Error conditionscritical- Critical conditionsalert- Action must be taken immediatelyemergency- System is unusable
For Developers
Automatic Kubernetes Error Logging
Kubernetes API errors returned by tool handlers are automatically logged to MCP clients.
When a tool handler returns a ToolCallResult with a non-nil error that is a Kubernetes API error (StatusError), the server categorizes it and sends an appropriate log message.
This means toolset authors do not need to call any logging functions for standard K8s error handling.
Simply return the error in the ToolCallResult and the server handles the rest:
ret, err := client.CoreV1().Pods(namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return api.NewToolCallResult("", fmt.Errorf("failed to get pod: %w", err)), nil
}
The following Kubernetes error types are automatically categorized:
| Error Type | Log Level | Message |
|---|---|---|
| Not Found | info | Resource not found - it may not exist or may have been deleted |
| Forbidden | error | Permission denied - check RBAC permissions for {tool} |
| Unauthorized | error | Authentication failed - check cluster credentials |
| Already Exists | warning | Resource already exists |
| Invalid | error | Invalid resource specification - check resource definition |
| Bad Request | error | Invalid request - check parameters |
| Conflict | error | Resource conflict - resource may have been modified |
| Timeout | error | Request timeout - cluster may be slow or overloaded |
| Server Timeout | error | Server timeout - cluster may be slow or overloaded |
| Service Unavailable | error | Service unavailable - cluster may be unreachable |
| Too Many Requests | warning | Rate limited - too many requests to the cluster |
| Other K8s API errors | error | Operation failed - cluster may be unreachable or experiencing issues |
Non-Kubernetes errors (e.g., input validation errors) are not logged to MCP clients.
Manual Logging
For custom messages beyond automatic K8s error handling, use SendMCPLog directly:
import "github.com/containers/kubernetes-mcp-server/pkg/mcplog"
mcplog.SendMCPLog(ctx, mcplog.LevelError, "Operation failed - check permissions")
Security
- Authentication failures send generic messages to clients (no security info leaked)
- Sensitive data is automatically redacted before being sent to clients, covering:
- Generic fields (password, token, secret, api_key, etc.)
- Authorization headers (Bearer, Basic)
- Cloud credentials (AWS, GCP, Azure)
- API tokens (GitHub, GitLab, OpenAI, Anthropic)
- Cryptographic keys (JWT, SSH, PGP, RSA)
- Database connection strings (PostgreSQL, MySQL, MongoDB)
- Uses a dedicated named logger (
logger="mcp") for complete separation from server logs - Server logs (klog) remain detailed and unaffected