Audit Logs
Audit logs record what your agents do and what changes in MCPX. Each event is saved in a structured form, so you can review activity and configuration history. Logging is on by default. View recent events in the MCPX control plane, or read the JSONL files directly.
MCPX records five event types: tool_used, target_server_added, target_server_removed, agent_permission_updated, and catalog_updated.

Tool usage event (tool_used)
Triggered whenever an agent invokes a tool. Payload fields include:
toolName: the name of the tool calledtargetServerName: the server or service that handled the requestargs: the input arguments passed to the toolconsumerTag: optional tag identifying the consumer or agent
{"timestamp":"2025-10-28T13:52:46.201Z","createdAt":"2025-10-28T13:52:48.806Z","eventType":"tool_used","payload":{"toolName":"slack_list_channels","targetServerName":"slack","args":{"limit":20},"consumerTag":"Claude"}}
MCP server added (target_server_added)
Recorded when a new MCP server is added to your catalog. Payload fields:
name: the server that was added
{
"timestamp": "2025-10-29T10:05:44.132Z",
"createdAt": "2025-10-29T10:05:44.417Z",
"eventType": "target_server_added",
"payload": {
"name": "github"
}
}
MCP server removed (target_server_removed)
Recorded when an MCP server is removed from your catalog. Payload fields:
name: the server that was removed
{
"timestamp": "2025-10-29T10:59:05.063Z",
"createdAt": "2025-10-29T10:59:05.289Z",
"eventType": "target_server_removed",
"payload": {
"name": "slack"
}
}
Agent permission updated (agent_permission_updated)
Recorded when an identity's access changes. MCPX logs only the servers that were added or removed, not the full permission set. Payload fields:
name: the identity whose access changedidentityType:consumersorclientNamesaddedServers: servers the identity can now useremovedServers: servers the identity can no longer use
{
"timestamp": "2025-10-29T10:30:32.516Z",
"createdAt": "2025-10-29T10:30:33.525Z",
"eventType": "agent_permission_updated",
"payload": {
"name": "Claude",
"identityType": "consumers",
"addedServers": ["time"],
"removedServers": []
}
}
Catalog updated (catalog_updated)
Recorded when the catalog changes: servers are added or removed, or the approved tools on a server change. Payload fields:
addedServers: servers added to the catalogremovedServers: servers removed from the catalogapprovedToolsChanges: tool changes per server, each listing the server and which tools were added or removed
{
"timestamp": "2025-10-29T10:30:18.772Z",
"createdAt": "2025-10-29T10:30:23.529Z",
"eventType": "catalog_updated",
"payload": {
"addedServers": ["time"],
"removedServers": [],
"approvedToolsChanges": [
{
"serverName": "slack",
"addedTools": ["slack_post_message", "slack_reply_to_thread"],
"removedTools": []
}
]
}
}
Each entry includes two timestamps:
timestamp: when the event happenedcreatedAt: when MCPX saved it to disk
Viewing audit logs in the UI
The MCPX control plane includes an Audit Log page where you can browse recent events without opening the log files.
The page lists recent events in a table with Time, Event, and Details columns. Click any row to see the full event details. Use the filters at the top to show or hide each event type: MCP added, MCP removed, Agent permission updated, Catalog updated, and Tool used. Click Refresh to load the latest events.
The UI shows the most recent events. For long-term storage and use with other tools, the JSONL files in AUDIT_LOG_DIR remain the source of truth.
Configuration
Audit logging is controlled through the following environment variables:
ENABLE_AUDIT_LOG
Type: boolean or string ("true"/"false")
Default: true
Required: Yes
Enables or disables audit logging
AUDIT_LOG_FLUSH_INTERVAL_IN_SEC
Type: seconds
Default: 5
Required: No
Number of seconds to wait before flushing logs to disk
AUDIT_LOG_DIR
Type: path
Default: <cwd>/audit-logs
Required: No
Directory where logs are written. When running MCPX in Docker, the default file path is /lunar/packages/mcpx-server/audit-logs/audit-2025-10-29T10.jsonl. Audited events are automatically grouped by hour and written to separate files, meaning a new log file is generated each hour at the configured path.
AUDIT_LOG_RETENTION_HOURS
Type: num
Default: 336 (14 days)
Required: No
How long to retain log files before cleanup
Best practices
- Keep
ENABLE_AUDIT_LOG=truein production to maintain full visibility. - If you need tighter real-time tracking, reduce
AUDIT_LOG_FLUSH_INTERVAL_IN_SEC; if you want to reduce disk I/O, increase it. - When running in Docker, mount
AUDIT_LOG_DIRto a persistent volume so logs survive container restarts. - Set retention (
AUDIT_LOG_RETENTION_HOURS) according to your compliance and audit policy. - Consider shipping the JSONL file to your observability stack (for example : Loki, Splunk, or Elasticsearch) for centralized querying and alerting.
Example
Here is an example of a log file
{"timestamp":"2025-10-29T10:05:44.132Z","createdAt":"2025-10-29T10:05:44.417Z","eventType":"config_applied","payload":{"config":{"permissions":{"default":{"_type":"default-allow","block":[]},"consumers":{}},"toolGroups":[{"name":"Version_control_and_issue_management","services":{"github":["get_issue","create_issue","add_issue_comment","list_issues","update_issue","get_pull_request","list_pull_requests","merge_pull_request","get_pull_request_diff","create_pull_request","update_pull_request","delete_file","list_branches","push_files","search_repositories","create_repository","fork_repository","create_branch","run_workflow","get_workflow_run","get_workflow_run_logs","rerun_failed_jobs","rerun_workflow_run","cancel_workflow_run"],"slack":"*"}},{"name":"Browser_automation_and_UI_testing","services":{"duckduckgo":["search"],"playwright":["browser_snapshot","browser_click","browser_drag","browser_hover","browser_type","browser_select_option","browser_wait_for","browser_navigate","browser_tab_list","browser_tab_new","browser_tab_select","browser_press_key"]}},{"name":"Database_and_file_operations","services":{"supabase":["search_docs","list_tables","list_migrations","apply_migration","execute_sql","get_project_url","get_anon_key","generate_typescript_types"]}},{"name":"Code_development_and_refactoring","services":{"memory":["create_entities","create_relations","add_observations"],"serena":["create_text_file","activate_project","delete_memory","execute_shell_command","find_symbol","get_symbols_overview","insert_after_symbol","list_memories","list_dir","prepare_for_new_conversation","read_memory","read_file","search_for_pattern"]}},{"name":"Observability_and_debugging","services":{"grafana":["search_dashboards","query_prometheus","query_loki_logs","list_incidents"]}}],"auth":{"enabled":false},"toolExtensions":{"services":{}}},"version":1,"lastModified":"2025-10-29T10:05:44.132Z"}}
{"timestamp":"2025-10-29T10:30:18.772Z","createdAt":"2025-10-29T10:30:23.529Z","eventType":"config_applied","payload":{"config":{"permissions":{"default":{"_type":"default-allow","block":[]},"consumers":{}},"toolGroups":[{"name":"Version_control_and_issue_management","services":{"github":["get_issue","create_issue","add_issue_comment","list_issues","update_issue","get_pull_request","list_pull_requests","merge_pull_request","get_pull_request_diff","create_pull_request","update_pull_request","delete_file","list_branches","push_files","search_repositories","create_repository","fork_repository","create_branch","run_workflow","get_workflow_run","get_workflow_run_logs","rerun_failed_jobs","rerun_workflow_run","cancel_workflow_run"],"slack":["slack_list_channels","slack_post_message","slack_reply_to_thread","slack_add_reaction","slack_get_channel_history","slack_get_thread_replies","slack_get_users","slack_get_user_profile"]}},{"name":"Browser_automation_and_UI_testing","services":{"duckduckgo":["search"],"playwright":["browser_snapshot","browser_click","browser_drag","browser_hover","browser_type","browser_select_option","browser_wait_for","browser_navigate","browser_tab_list","browser_tab_new","browser_tab_select","browser_press_key"]}},{"name":"Database_and_file_operations","services":{"supabase":["search_docs","list_tables","list_migrations","apply_migration","execute_sql","get_project_url","get_anon_key","generate_typescript_types"]}},{"name":"Code_development_and_refactoring","services":{"memory":["create_entities","create_relations","add_observations"],"serena":["create_text_file","activate_project","delete_memory","execute_shell_command","find_symbol","get_symbols_overview","insert_after_symbol","list_memories","list_dir","prepare_for_new_conversation","read_memory","read_file","search_for_pattern"]}},{"name":"Observability_and_debugging","services":{"grafana":["search_dashboards","query_prometheus","query_loki_logs","list_incidents"]}},{"name":"time","services":{"time":["get_current_time","convert_time"]}}],"auth":{"enabled":false},"toolExtensions":{"services":{}}},"version":2,"lastModified":"2025-10-29T10:30:18.755Z"}}
{"timestamp":"2025-10-29T10:30:32.516Z","createdAt":"2025-10-29T10:30:33.525Z","eventType":"config_applied","payload":{"config":{"permissions":{"default":{"_type":"default-allow","block":[]},"consumers":{"Claude":{"_type":"default-block","consumerGroupKey":"claude-ai (via mcp-remote 0.1.21) Profile","allow":["time"]}}},"toolGroups":[{"name":"Version_control_and_issue_management","services":{"github":["get_issue","create_issue","add_issue_comment","list_issues","update_issue","get_pull_request","list_pull_requests","merge_pull_request","get_pull_request_diff","create_pull_request","update_pull_request","delete_file","list_branches","push_files","search_repositories","create_repository","fork_repository","create_branch","run_workflow","get_workflow_run","get_workflow_run_logs","rerun_failed_jobs","rerun_workflow_run","cancel_workflow_run"],"slack":"*"}},{"name":"Browser_automation_and_UI_testing","services":{"duckduckgo":["search"],"playwright":["browser_snapshot","browser_click","browser_drag","browser_hover","browser_type","browser_select_option","browser_wait_for","browser_navigate","browser_tab_list","browser_tab_new","browser_tab_select","browser_press_key"]}},{"name":"Database_and_file_operations","services":{"supabase":["search_docs","list_tables","list_migrations","apply_migration","execute_sql","get_project_url","get_anon_key","generate_typescript_types"]}},{"name":"Code_development_and_refactoring","services":{"memory":["create_entities","create_relations","add_observations"],"serena":["create_text_file","activate_project","delete_memory","execute_shell_command","find_symbol","get_symbols_overview","insert_after_symbol","list_memories","list_dir","prepare_for_new_conversation","read_memory","read_file","search_for_pattern"]}},{"name":"Observability_and_debugging","services":{"grafana":["search_dashboards","query_prometheus","query_loki_logs","list_incidents"]}},{"name":"time","services":{"time":"*"}}],"auth":{"enabled":false},"toolExtensions":{"services":{}}},"version":3,"lastModified":"2025-10-29T10:30:32.509Z"}}
{"timestamp":"2025-10-29T10:31:33.063Z","createdAt":"2025-10-29T10:31:33.598Z","eventType":"tool_used","payload":{"toolName":"get_current_time","targetServerName":"time","args":{"timezone":"Asia/Tokyo"},"consumerTag":"Claude"}}
{"timestamp":"2025-10-29T10:58:40.710Z","createdAt":"2025-10-29T10:58:45.207Z","eventType":"config_applied","payload":{"config":{"permissions":{"default":{"_type":"default-allow","block":[]},"consumers":{"Claude":{"_type":"default-block","consumerGroupKey":"claude-ai (via mcp-remote 0.1.21) Profile","allow":["time"]}}},"toolGroups":[{"name":"Browser_automation_and_UI_testing","services":{"duckduckgo":["search"],"playwright":["browser_snapshot","browser_click","browser_drag","browser_hover","browser_type","browser_select_option","browser_wait_for","browser_navigate","browser_tab_list","browser_tab_new","browser_tab_select","browser_press_key"]}},{"name":"Database_and_file_operations","services":{"supabase":["search_docs","list_tables","list_migrations","apply_migration","execute_sql","get_project_url","get_anon_key","generate_typescript_types"]}},{"name":"Code_development_and_refactoring","services":{"memory":["create_entities","create_relations","add_observations"],"serena":["create_text_file","activate_project","delete_memory","execute_shell_command","find_symbol","get_symbols_overview","insert_after_symbol","list_memories","list_dir","prepare_for_new_conversation","read_memory","read_file","search_for_pattern"]}},{"name":"Observability_and_debugging","services":{"grafana":["search_dashboards","query_prometheus","query_loki_logs","list_incidents"]}},{"name":"time","services":{"time":["get_current_time","convert_time"]}}],"auth":{"enabled":false},"toolExtensions":{"services":{}}},"version":4,"lastModified":"2025-10-29T10:58:40.698Z"}}
{"timestamp":"2025-10-29T10:59:05.063Z","createdAt":"2025-10-29T10:59:05.289Z","eventType":"config_applied","payload":{"config":{"permissions":{"default":{"_type":"default-allow","block":[]},"consumers":{"Claude":{"_type":"default-block","consumerGroupKey":"claude-ai (via mcp-remote 0.1.21) Profile","allow":["time"]}}},"toolGroups":[{"name":"Database_and_file_operations","services":{"supabase":["search_docs","list_tables","list_migrations","apply_migration","execute_sql","get_project_url","get_anon_key","generate_typescript_types"]}},{"name":"Observability_and_debugging","services":{"grafana":["search_dashboards","query_prometheus","query_loki_logs","list_incidents"]}},{"name":"time","services":{"time":["get_current_time","convert_time"]}}],"auth":{"enabled":false},"toolExtensions":{"services":{}}},"version":5,"lastModified":"2025-10-29T10:59:05.058Z"}}
{"timestamp":"2025-10-29T10:59:29.434Z","createdAt":"2025-10-29T10:59:30.309Z","eventType":"config_applied","payload":{"config":{"permissions":{"default":{"_type":"default-allow","block":[]},"consumers":{"Claude":{"_type":"default-block","consumerGroupKey":"claude-ai (via mcp-remote 0.1.21) Profile","allow":["time"]}}},"toolGroups":[{"name":"Database_and_file_operations","services":{"supabase":["search_docs","list_tables","list_migrations","apply_migration","execute_sql","get_project_url","get_anon_key","generate_typescript_types"]}},{"name":"Observability_and_debugging","services":{"grafana":["search_dashboards","query_prometheus","query_loki_logs","list_incidents"]}},{"name":"time","services":{"time":["get_current_time","convert_time"]}},{"name":"tool_group_name","services":{"duckduckgo":["search"],"github":["add_comment_to_pending_review","add_issue_comment","get_me"],"grafana":["fetch_pyroscope_profile"]}}],"auth":{"enabled":false},"toolExtensions":{"services":{}}},"version":6,"lastModified":"2025-10-29T10:59:29.428Z"}}
{"timestamp":"2025-10-29T10:59:40.881Z","createdAt":"2025-10-29T10:59:45.329Z","eventType":"config_applied","payload":{"config":{"permissions":{"default":{"_type":"default-allow","block":[]},"consumers":{"Claude":{"_type":"default-block","consumerGroupKey":"claude-ai (via mcp-remote 0.1.21) Profile","allow":["time"]}}},"toolGroups":[{"name":"Database_and_file_operations","services":{"supabase":["search_docs","list_tables","list_migrations","apply_migration","execute_sql","get_project_url","get_anon_key","generate_typescript_types"]}},{"name":"Observability_and_debugging","services":{"grafana":["search_dashboards","query_prometheus","query_loki_logs","list_incidents"]}},{"name":"time","services":{"time":["get_current_time","convert_time"]}},{"name":"tool_group_name","services":{"duckduckgo":["search"],"github":["add_comment_to_pending_review","add_issue_comment","get_me"],"grafana":["fetch_pyroscope_profile"]}},{"name":"tool group","services":{"duckduckgo":["search","fetch_content"]}}],"auth":{"enabled":false},"toolExtensions":{"services":{}}},"version":7,"lastModified":"2025-10-29T10:59:40.873Z"}}