Logging
How does Hermes MCP handle the logging capabilities defined in the MCP protocol? Let's explore both the MCP logging features and how to configure Hermes's own internal logging.
MCP Logging Capability
When building MCP clients, you'll often need to receive and process log messages from servers. How might you handle these structured messages in your Elixir application?
Controlling Server Verbosity
{:ok, _} = MyApp.MCPClient.set_log_level("info")
What happens behind the scenes? This sends a logging/setLevel
request to the server, telling it to only send logs at "info" level or higher. The server will respect this preference when deciding which notifications to send your way.
Processing Incoming Logs
Ever wondered how to handle those log notifications when they arrive? You have two approaches:
# Register a custom handler
MyApp.MCPClient.register_log_callback(fn level, data, logger ->
# Send to your monitoring service?
# Transform the format?
# Filter by logger name?
end)
# When done, clean up
MyApp.MCPClient.unregister_log_callback()
What's happening by default though? Hermes automatically forwards all MCP log messages to Elixir's Logger, mapping the levels appropriately. This means your existing log infrastructure just works - no additional setup required.
Configuring Hermes Library Logs
Now, what about the logs that Hermes itself generates? How do you control the verbosity of the library's internal logging?
Fine-Grained Control
config :hermes_mcp, :logging,
client_events: :info,
server_events: :debug,
transport_events: :warning,
protocol_messages: :debug
What do these categories mean for your debugging experience?
client_events
: Client lifecycle and operationsserver_events
: Server request handling and responsestransport_events
: Connection and transport layer activityprotocol_messages
: Raw MCP message exchanges
Global Toggle
Need to silence Hermes completely? Perhaps for performance testing or production deployments?
config :hermes_mcp, log: false
This disables all library-emitted logs, regardless of individual category settings.
MCP Server Logging
What if you're building an MCP server? How do you send logs to connected clients? Let's explore the server-side capabilities.
Declaring Logging Support
defmodule MyServer do
use Hermes.Server,
name: "my-server",
version: "1.0.0",
capabilities: [:logging] # Enable logging capability
end
What does this capability tell clients? It signals that your server can receive logging/setLevel
requests and will respect the client's verbosity preferences when sending log notifications.
Sending Log Messages
How do you actually send logs from your server to clients? You have a straightforward API:
# From within your server callbacks
send_log_message(server, "info", "Processing started", "worker")
# Or without a logger name
send_log_message(server, "error", "Connection failed")
What happens when you send these? They become notifications/message
events that clients process according to their configured handlers. The client's minimum log level (set via set_log_level/1
) filters what they receive.
Progress Notifications
Need to report progress on long-running operations? How might this improve user experience?
# Start an operation with progress tracking
send_progress(server, "import-123", 0, 100, "Starting import...")
# Update as you go
send_progress(server, "import-123", 45, 100, "Processing records...")
# Complete
send_progress(server, "import-123", 100, 100, "Import complete!")
Practical Considerations
How might you configure logging for different environments? Consider starting with :debug
everywhere during development, then adjusting based on what you learn:
- Keep
protocol_messages
at:debug
unless debugging protocol issues - Set
transport_events
to:warning
once your transport is stable - Use
:info
for client and server events in production
What patterns emerge from your logs? Which categories provide the most value for your use case?