Jaeger MCP vs Heimdall MCP — MCP Server Comparison | AllMCPs
Side-by-Side Model Context Protocol Comparison
Jaeger MCP vs Heimdall MCP
In-depth architectural comparison of the Jaeger MCP and Heimdall MCP MCP servers. Compare execution transports, security boundaries, tool capabilities, quality scores, and ready-to-paste client installation snippets for Claude, Cursor, Windsurf, and VS Code.
At a Glance & Executive Verdict
Jaeger MCP
Monitoring · Local stdio
Quality: 57/100 (Good) | Auth: other
Heimdall MCP
Monitoring · Local stdio
Quality: 60/100 (Good) | Auth: No auth required
Verdict Summary: Choose Jaeger MCP if you need specialized Monitoring tools running via a local process. Choose Heimdall MCP if your workspace requires Monitoring integration with local subprocess execution. Both servers can be configured concurrently in your client's mcpServers manifest.
Which MCP Server Should You Choose?
Choose Jaeger MCP when:
You need dedicated capabilities in the Monitoring domain.
You prefer local stdio subprocess transport architecture.
Your security boundary fits: other (Free / Open Source).
List all services that Jaeger has observed traces for.
Wraps ``GET /api/services``. Jaeger returns all services at once — no
pagination. Output is capped at 500 services with a truncation hint.
Use this first to discover valid service names before calling
``jaeger_list_operations`` or ``jaeger_search_traces``.
Examples:
- Use when: "What services does Jaeger know about?"
→ call with no parameters; read the ``services`` list.
- Use when: "Is `payment-service` instrumented?"
→ check if `payment-service` appears in the services list.
- Use when: Starting a debugging session — list services first,
then pick one for ``jaeger_list_operations`` or
``jaeger_search_traces``.
- Don't use when: You already know the service name and want to
search its traces (call ``jaeger_search_traces`` directly).
- Don't use when: You want the dependency graph between services
(call ``jaeger_get_dependencies``).
Returns:
dict with keys ``services_count`` / ``truncated`` / ``services``.
jaeger_list_operations
List all operation names Jaeger has seen for a given service.
Wraps ``GET /api/services/{service}/operations``. Useful for discovering
which operation names to pass as filters to ``jaeger_search_traces``.
Output is capped at 500 operations.
Examples:
- Use when: "What HTTP endpoints does `order-service` expose in tracing?"
→ ``service='order-service'``.
- Use when: You want to search for a specific slow operation but need
the exact name — list operations first, then pass it to
``jaeger_search_traces``.
- Use when: Auditing which gRPC methods a service traces.
- Don't use when: You don't have a specific service — start with
``jaeger_list_services`` first.
- Don't use when: You want to search traces immediately (skip this
step if you already know the operation name).
Returns:
dict with ``service`` / ``operations_count`` / ``truncated`` /
``operations`` (sorted alphabetically).
Ready-to-Paste Client Configurations
Paste either (or both) of these JSON server blocks into your client config file (e.g. claude_desktop_config.json or ~/.cursor/mcp.json).
Jaeger MCP is categorized under Monitoring and uses a local stdio subprocess. In contrast, Heimdall MCP belongs to Monitoring using local stdio subprocess. Select Jaeger MCP when you need capabilities focused on monitoring and Heimdall MCP when you require tools for monitoring.
Search Jaeger traces with rich filters.
Wraps ``GET /api/traces``. Returns a list of trace summaries — use
``jaeger_get_trace`` to drill into a specific trace for span details.
The ``tags`` parameter accepts a JSON string so the LLM can construct
arbitrary tag filters. Durations (``min_duration``/``max_duration``) are
forwarded as-is to Jaeger (e.g. ``'100ms'``, ``'1.5s'``).
Examples:
- Use when: "Show me recent 500 errors in `order-service`"
→ ``service='order-service'``, ``tags='{"http.status_code":"500"}'``.
- Use when: "Find slow traces (>1s) for `checkout` endpoint"
→ ``service='checkout'``, ``operation='POST /checkout'``,
``min_duration='1s'``.
- Use when: "Give me the last 5 traces in the last hour"
→ ``limit=5``, set ``start`` to (now - 3600s) in microseconds.
- Don't use when: You already have a traceID and want full details
(call ``jaeger_get_trace`` directly — one fewer round trip).
- Don't use when: You want service dependency topology
(call ``jaeger_get_dependencies``).
Returns:
dict with ``service`` / ``operation`` / ``returned`` / ``truncated`` /
``traces`` (list of :class:`TraceSummary`).
jaeger_get_trace
Retrieve full trace detail with all spans, service breakdown, and execution tree.
Wraps ``GET /api/traces/{traceID}``. Returns every span in the trace,
per-service statistics, and a flat execution tree (each node lists its
child span IDs) that summarises the call hierarchy.
Error spans are identified by ``tags["error"] = "true"``.
Examples:
- Use when: "Why is trace `abc123...` slow — show me the span breakdown"
→ ``trace_id='abc123...'``; inspect ``services`` for the heaviest service
and ``execution_tree`` for the call hierarchy.
- Use when: "Which service caused the error in trace `xyz...`?"
→ check ``spans`` where ``is_error=true``.
- Use when: You found a slow/failed trace in ``jaeger_search_traces``
and need full detail.
- Don't use when: You don't have a specific traceID — use
``jaeger_search_traces`` to find one first.
- Don't use when: You only want aggregate data across many traces
(use ``jaeger_search_traces`` with filters instead).
Returns:
dict with ``trace_id`` / ``span_count`` / ``service_count`` /
``root_operation`` / ``root_service`` / ``start_time_us`` /
``total_duration_us`` / ``errors_count`` / ``services`` (per-service stats) /
``spans`` (all spans) / ``execution_tree``.
jaeger_get_dependencies
Retrieve the service-to-service call graph from Jaeger.
Wraps ``GET /api/dependencies``. Returns directed edges (parent → child)
with ``call_count`` — the number of spans where parent called child in
the lookback window.
Use this to understand service topology, find high fan-out services, or
verify that a new service is connected as expected.
Examples:
- Use when: "What services does `order-service` call?"
→ check edges where ``parent='order-service'``.
- Use when: "Map the full service dependency graph for the last 7 days"
→ ``lookback_hours=168``.
- Use when: "Which services are called most frequently?"
→ sort edges by ``call_count`` descending.
- Don't use when: You want detailed span timings (use
``jaeger_search_traces`` + ``jaeger_get_trace`` instead).
- Don't use when: You need real-time data — Jaeger's dependency graph
is aggregated and may lag by minutes.
Returns:
dict with ``end_ts_us`` / ``lookback_hours`` / ``edge_count`` /
``edges`` (list of ``{parent, child, call_count}``).
jaeger_compare_traces
Compare two traces structurally — find added, removed, and changed spans.
Fetches both traces from Jaeger and performs a structural diff by matching
spans on ``(operationName, serviceName, parentOperation)`` — not span IDs,
which differ across traces. Reports duration deltas and tag differences for
changed spans.
Examples:
- Use when: "What changed between a fast and slow request?"
→ pass the trace IDs of both requests; inspect ``changed_spans``
for duration deltas.
- Use when: "Did a deployment add new service calls?"
→ compare a pre-deploy trace with a post-deploy trace; check
``added_spans`` for new operations.
- Use when: "Are these two traces structurally identical?"
→ if ``added_spans``, ``removed_spans``, and ``changed_spans``
are all empty, the traces have the same structure.
- Don't use when: You want aggregate statistics across many traces
(use ``jaeger_span_statistics`` instead, once available).
- Don't use when: You only have one trace — use ``jaeger_get_trace``
for single-trace inspection.
Returns:
dict with ``trace_id_a`` / ``trace_id_b`` / ``added_spans`` /
``removed_spans`` / ``changed_spans`` (with duration + tag deltas) /
``unchanged_count``.
jaeger_span_statistics
Compute per-operation latency percentiles and error rates across recent traces.
Fetches up to ``limit`` traces for the given service (optionally filtered
by operation), then aggregates all spans by operation name. For each
operation reports: span count, p50/p95/p99 duration in microseconds,
error count, and error rate.
Duration values are in microseconds (integer). Error rate is
``error_count / span_count`` (float, 0.0–1.0).
Examples:
- Use when: "What are the p95 latencies for each endpoint in `order-service`?"
→ ``service='order-service'``; inspect each operation's ``p95_duration_us``.
- Use when: "How often does the `POST /checkout` endpoint error?"
→ ``service='checkout-svc'``, ``operation='POST /checkout'``; check
``error_rate`` in the stats.
- Use when: "Compare latency distributions across operations"
→ look at p50 vs p99 spread to identify high-variance operations.
- Use when: "Get a larger sample for more accurate stats"
→ ``limit=100`` for higher confidence percentiles.
- Don't use when: You want to compare two specific traces
(use ``jaeger_compare_traces`` instead).
- Don't use when: You want full span detail for a single trace
(use ``jaeger_get_trace`` instead).
Returns:
dict with ``service`` / ``operation`` / ``trace_count`` /
``stats`` (list of per-operation stats with count, p50/p95/p99
duration_us, error_count, error_rate).
jaeger_critical_path
Identify the critical path and top bottlenecks in a trace.
Finds the longest-duration span chain (critical path) from root to leaf,
and ranks spans by self-time to find actual performance bottlenecks.
Examples:
- Use when: "Why is this trace so slow?"
→ call with the slow trace ID; examine the critical_path_duration_us
and critical_path_percentage to see how much of the total time is
spent on the longest path.
- Use when: "Which operations are consuming the most CPU/self-time?"
→ check the bottlenecks list sorted by self_time_us descending.
- Use when: Debugging performance regressions — compare critical path
percentages before/after changes.
- Don't use when: You want aggregate statistics across many traces
(use jaeger_span_statistics for that).
- Don't use when: You need to compare two traces structurally
(use jaeger_compare_traces for that).
Returns:
dict with trace metadata, critical path spans, and bottleneck ranking.
jaeger_compare_windows
Compare aggregate trace behavior between two time periods for a service.
Fetches traces from both time windows, aggregates span statistics per operation,
then compares the aggregate behavior to detect performance changes.
Examples:
- Use when: "Did our latest deployment affect performance?"
→ compare pre-deploy and post-deploy time windows for the service.
- Use when: "Which operations got slower after the database upgrade?"
→ check the comparison_p95_us and p95_delta_pct columns for increases.
- Use when: "Are we seeing new error patterns?"
→ look for operations with increased error_rate_delta.
- Use when: "Did we add or remove any API endpoints?"
→ check added_count and removed_count in the summary.
- Don't use when: You want to compare two specific traces
(use jaeger_compare_traces instead).
- Don't use when: You want full span detail for a single trace
(use jaeger_get_trace instead).
Returns:
WindowComparisonOutput with per-operation diffs and summary statistics.
jaeger_detect_anomalies
Detect latency and error-rate anomalies for a service by comparing recent behavior to historical baseline.
Fetches traces from a historical baseline window and a recent observation window,
computes per-operation statistics for both, then identifies statistically significant
deviations that may indicate performance issues or reliability problems.
Examples:
- Use when: "Are there any new performance issues in `order-service`?"
→ `service='order-service'` (uses default 60-minute baseline, 5-minute current).
- Use when: "Be more sensitive to subtle changes"
→ set `sensitivity=1.5` (lower threshold).
- Use when: "Check for issues over the last 24 hours against previous week"
→ `baseline_duration_minutes=10080`, `current_duration_minutes=1440`.
- Don't use when: You want to compare two specific time periods
(use jaeger_compare_windows instead).
- Don't use when: You want full span detail for a single trace
(use jaeger_get_trace instead).
Returns:
AnomalyDetectionOutput with flagged operations and severity scores.
jaeger_find_test_traces
Find Jaeger traces matching the supplied tag query.
Accepts any tag key-value schema (Allure, pytest, custom) without
normalization. When service is omitted, searches all known services
concurrently (capped at 20). Results are sorted newest-first.
jaeger_regression_diff
Compare two Jaeger time windows and classify per-operation regressions.
Fetches traces from the baseline and comparison windows, then classifies
each operation as regressed, recovered, appeared, or removed. Results are
sorted by severity score (0-100) descending for easy triage.
+3 more tools listed on main page
Heimdall MCP Tools (14)
read_file
Read the complete contents of a file as text. DEPRECATED: Use read_text_file instead.
read_text_file
Read the complete contents of a file from the file system as text. Handles various text encodings and provides detailed error messages if the file cannot be read. Use this tool when you need to examine the contents of a single file. Use the 'head' parameter to read only the first N lines of a file, or the 'tail' parameter to read only the last N lines of a file. Operates on the file as text regardless of extension. Only works within allowed directories.
read_media_file
Read a file and return it as a base64-encoded content block with its MIME type. Image and audio files are returned as image/audio content; any other file type is returned as an embedded resource. Only works within allowed directories.
read_multiple_files
Read the contents of multiple files simultaneously. This is more efficient than reading files one by one when you need to analyze or compare multiple files. Each file's content is returned with its path as a reference. Failed reads for individual files won't stop the entire operation. Only works within allowed directories.
write_file
Create a new file or completely overwrite an existing file with new content. Use with caution as it will overwrite existing files without warning. Handles text content with proper encoding. Only works within allowed directories.
edit_file
Make line-based edits to a text file. Each edit replaces exact line sequences with new content. Returns a git-style diff showing the changes made. Only works within allowed directories.
create_directory
Create a new directory or ensure a directory exists. Can create multiple nested directories in one operation. If the directory already exists, this operation will succeed silently. Perfect for setting up directory structures for projects or ensuring required paths exist. Only works within allowed directories.
list_directory
Get a detailed listing of all files and directories in a specified path. Results clearly distinguish between files and directories with [FILE] and [DIR] prefixes. This tool is essential for understanding directory structure and finding specific files within a directory. Only works within allowed directories.
list_directory_with_sizes
Get a detailed listing of all files and directories in a specified path, including sizes. Results clearly distinguish between files and directories with [FILE] and [DIR] prefixes. This tool is useful for understanding directory structure and finding specific files within a directory. Only works within allowed directories.
directory_tree
Get a recursive tree view of files and directories as a JSON structure. Each entry includes 'name', 'type' (file/directory), and 'children' for directories. Files have no children array, while directories always have a children array (which may be empty). The output is formatted with 2-space indentation for readability. Only works within allowed directories.
move_file
Move or rename files and directories. Can move files between directories and rename them in a single operation. If the destination exists, the operation will fail. Works across different directories and can be used for simple renaming within the same directory. Both source and destination must be within allowed directories.
search_files
Recursively search for files and directories matching a pattern. The patterns should be glob-style patterns that match paths relative to the working directory. Use pattern like '*.ext' to match files in current directory, and '**/*.ext' to match files in all subdirectories. Returns full paths to all matching items. Great for finding files when you don't know their exact location. Only searches within allowed directories.
Transparent proxy for any MCP server that intercepts all JSON-RPC messages, measures latency, and stores traces in SQLite, PostgreSQL, or MySQL. Exports OpenTelemetry (OTLP) spans to Jaeger, Tempo, or Grafana. Supports stdio, HTTP, and SSE transports. npx @cardor/heimdall-mcp