Skip to main content
Glama
parajiholkar

Multi-Container Log Correlator MCP Server

by parajiholkar

Multi-Container Log Correlator MCP Server

An MCP (Model Context Protocol) server that continuously ingests logs from all running Docker containers, indexes them by trace/request ID, and exposes a clean tools so an LLM can debug distributed transactions without ever switching terminal windows.


How it works

Docker daemon
  Windows  →  //./pipe/docker_engine  (named pipe, auto-detected)
  Linux/Mac →  /var/run/docker.sock   (Unix socket, auto-detected)
  Custom   →  DOCKER_HOST=tcp://...   (TCP via env var)
        │  (multiplexed stdout/stderr streams)
        ▼
  DockerLogWatcher  ──►  LogParser  ──►  TraceIndexedRingBuffer
  (per-container)         (zero-copy         (10 000 lines/container +
   log streams)            parsing)           O(1) trace_id index)
                                                      │
                                                      ▼
                                            MCP stdio transport
                                                      │
                                                      ▼
                                              LLM tool calls

The ring buffer retains the last 10 000 log lines per container. A secondary Map<traceId, Set<slotKey>> index lets search_by_trace_id resolve cross-service timelines in O(1) time regardless of buffer size.


Related MCP server: log-mcp-server

Exposed MCP Tools

The server exposes 7 tools. Use them in the order shown below for a typical debugging session start with topology, narrow to errors, then correlate by trace ID.


1. list_active_containers

Lists all Docker containers currently being monitored by the server.

Use this first to understand the service topology before calling any other tool it tells you the exact service names you will need to pass as arguments.

Argument

Type

Required

Description

project_name

string

No

Filter by Docker Compose project name. Omit to list all running containers.

Returns: Service name, short container ID (12-char), Docker image, running status, and Compose project for each container.

Example:

list_active_containers()
→ api-gateway      (id: a1b2c3d4e5f6, image: nginx:latest,   Up 3 hours)
→ checkout-worker  (id: b2c3d4e5f6a1, image: node:20,        Up 3 hours)
→ inventory-db     (id: c3d4e5f6a1b2, image: postgres:16,    Up 3 hours)

2. search_by_trace_id — Primary debug tool

The core power tool. Takes a trace/request/correlation ID and returns a chronologically merged timeline of every log event across all containers that share that ID resolved in O(1) time using the in-memory trace index.

This is the tool that turns a 500 error into a root cause in seconds. A single call spans every service that touched the request.

Argument

Type

Required

Description

trace_id

string

Yes

The correlation ID to search for e.g. req-998877, a W3C traceparent hex, or an X-Request-ID value.

limit

number

No

Maximum log events to return. Default 200, max 500.

Returns: A merged, chronologically sorted list of log lines from all services that logged this trace ID, including the service name, timestamp, log level, and full message for each event.

Example:

search_by_trace_id({ trace_id: "req-998877" })
→ 14:03:21.001  [api-gateway]      INFO   POST /checkout received
→ 14:03:21.045  [checkout-worker]  INFO   Reserving 2x item #42
→ 14:03:22.100  [inventory-db]     ERROR  Deadlock detected on stock_reservations
→ 14:03:22.441  [checkout-worker]  ERROR  DB timeout after 1400ms
→ 14:03:22.443  [api-gateway]      ERROR  Responding 500 to client

3. tail_service_errors

Retrieves the most recent ERROR and FATAL log lines from a specific container. The fastest way to find an initial failure point when you do not yet have a trace ID grab the error, extract its trace ID, then pass it to search_by_trace_id.

Argument

Type

Required

Description

service_name

string

Yes

Docker container name or Compose service name (e.g. checkout-worker).

limit

number

No

Number of most-recent error lines to return. Default 50, max 500.

include_warnings

boolean

No

Also include WARN-level lines alongside errors. Default false.

Returns: The N most-recent ERROR/FATAL (and optionally WARN) log lines from the named service in chronological order.

Detected levels: FATAL, CRITICAL, ERROR and optionally WARN / WARNING.

Example:

tail_service_errors({ service_name: "checkout-worker", limit: 10, include_warnings: true })
→ 14:03:22.441  ERROR  DB timeout after 1400ms trace_id=req-998877
→ 14:03:19.100  WARN   Slow query detected (980ms) trace_id=req-998800

4. tail_service_logs

Retrieves the N most-recent log lines from a specific container with optional level filtering. Use this to get general context around a service see what it was doing before or after an event without restricting to errors only.

Argument

Type

Required

Description

service_name

string

Yes

Docker container name or Compose service name.

limit

number

No

Number of most-recent lines to return. Default 100, max 500.

level_filter

string[]

No

Restrict to specific levels: TRACE, DEBUG, INFO, WARN, ERROR, FATAL, UNKNOWN. Omit for all levels.

Returns: The most-recent matching log lines in chronological order with timestamp, service name, level, and message.

Example:

tail_service_logs({ service_name: "api-gateway", limit: 50, level_filter: ["INFO", "ERROR"] })
→ Returns the last 50 INFO and ERROR lines from api-gateway

5. search_logs

Case-insensitive full-text search across the buffered log lines of one or all containers. Useful when you know part of an error message but not which service threw it, or when hunting for a specific SQL query, function name, or stack trace snippet that does not carry a trace ID.

Argument

Type

Required

Description

query

string

Yes

Case-insensitive substring to match against log messages (e.g. "connection refused", "NullPointerException").

service_name

string

No

Restrict search to one container. Omit to search all containers simultaneously.

limit

number

No

Maximum matching lines to return. Default 100, max 500.

level_filter

string[]

No

Restrict results to specific log levels.

Returns: All matching log lines in chronological order annotated with service name, timestamp, and level. Indicates when results are truncated.

Example:

search_logs({ query: "connection refused", limit: 20 })
→ Finds every "connection refused" line across all running containers

6. get_container_stats

Returns buffer statistics for one or all containers at a glance: total lines buffered, error/warn counts, a sample of known trace IDs, and the oldest/newest log timestamps. Useful for a quick system health overview or to verify the buffer is actively filling with live data.

Argument

Type

Required

Description

service_name

string

No

A specific container to inspect. Omit to get stats for all running containers.

Returns per container:

  • Lines buffered (ring buffer holds up to 10,000 lines per container)

  • Error count and warning count

  • Oldest and newest log timestamps in the buffer

  • Sample of known trace IDs seen in that container's logs

Example:

get_container_stats()
→ checkout-worker:  4,821 lines | Errors: 12 | Warnings: 34 | Traces: req-998877, req-998800 …
→ inventory-db:     2,103 lines | Errors: 3  | Warnings: 1  | Traces: req-998877 …
→ api-gateway:      9,441 lines | Errors: 12 | Warnings: 89 | Traces: req-998877, req-998800 …

7. list_trace_ids

Lists all trace/request IDs currently held in the in-memory buffer. Use this when a user reports "something went wrong" with no trace ID browse the available IDs, pick the one closest to the reported time, and feed it directly into search_by_trace_id.

Argument

Type

Required

Description

service_name

string

No

Only list trace IDs seen in this specific service. Omit for all services.

limit

number

No

Maximum number of trace IDs to return. Default 50, max 1000.

Returns: A numbered list of trace ID strings currently in the buffer.

Example:

list_trace_ids({ service_name: "checkout-worker", limit: 5 })
→ 1. req-998877
→ 2. req-998800
→ 3. req-998741
→ 4. req-998603
→ 5. req-998512

Trace ID Detection

The parser automatically extracts trace identifiers from:

  • JSON fields: trace_id, traceId

  • W3C traceparent header values embedded in logs

  • X-Request-ID, X-Trace-ID, requestid, request_id key-value pairs

  • req-XXXXX style short IDs (common in Node.js / Express apps)

  • OpenTelemetry trace_id=<hex32> fields

  • OpenTelemetry span_id / spanId for span-level correlation


Prerequisites

  • Node.js 18+

  • Docker running locally (or accessible socket)

  • Windows: Docker Desktop running uses //./pipe/docker_engine automatically

  • Linux/Mac: Read access to /var/run/docker.sock


Installation & Usage

npm install
node index.js

Environment variables

The server auto-detects the Docker connection for your platform no configuration needed in most cases.

Variable

Default

Description

DOCKER_HOST

(auto)

Override with tcp://localhost:2375 for TCP mode (useful on Windows if named pipe access is blocked)

DOCKER_SOCKET_PATH

/var/run/docker.sock

Linux/Mac only override the Unix socket path

Windows tip: If the server cannot find containers, enable "Expose daemon on tcp://localhost:2375" in Docker Desktop → Settings → General, then set DOCKER_HOST=tcp://localhost:2375 in your MCP config (see below).


Claude Desktop / Cursor config

Add this to your claude_desktop_config.json:

Config file location

  • Windows: C:\Users\<you>\AppData\Roaming\Claude\claude_desktop_config.json

  • Mac: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Linux: ~/.config/Claude/claude_desktop_config.json

Linux / Mac

{
  "mcpServers": {
    "multi-container-log-correlator-mcp-server": {
      "command": "node",
      "args": ["/absolute/path/to/multi-container-log-correlator-mcp-server/index.js"]
    }
  }
}

Windows (named pipe works out of the box with Docker Desktop)

{
  "mcpServers": {
    "multi-container-log-correlator-mcp-server": {
      "command": "node",
      "args": ["C:\\path\\to\\multi-container-log-correlator-mcp-server\\index.js"]
    }
  }
}

Windows (TCP fallback if named pipe does not work, enable TCP in Docker Desktop → Settings → General first)

{
  "mcpServers": {
    "multi-container-log-correlator-mcp-server": {
      "command": "node",
      "args": ["C:\\path\\to\\multi-container-log-correlator-mcp-server\\index.js"],
      "env": {
        "DOCKER_HOST": "tcp://localhost:2375"
      }
    }
  }
}

Typical debugging session

User: "The frontend is throwing a 500 error on checkout. Trace ID is req-998877. What happened?"

LLM:
  1. list_active_containers()             → sees api-gateway, checkout-worker, inventory-db
  2. search_by_trace_id("req-998877")     → gets merged timeline across all 3 services
  3. Reads the timeline, spots the DB deadlock in inventory-db at 14:03:22.441
  4. Reports: "inventory-db hit a deadlock on the stock reservation table,
     which caused checkout-worker to time out, propagating a 500 to api-gateway."

Project structure

src/
├── constants.js              # Buffer sizes, regex patterns, socket path
├── services/
│   ├── ringBuffer.js         # TraceIndexedRingBuffer (core data structure)
│   ├── dockerClient.js       # DockerLogWatcher streams from daemon
│   ├── logParser.js          # Stateless line parser (timestamps, levels, trace IDs)
│   └── formatter.js          # Human-readable output helpers
├── schemas/
│   └── toolSchemas.js        # Zod input schemas for every MCP tool
└── tools/
    └── containerTools.js     # All 7 MCP tool registrations
── index.js                  # Entry point wires everything together

Available Tools

7 tools
get_container_statsGet Container StatsA
Read-onlyIdempotent

Return buffer statistics for one or all containers: total lines buffered, error/warn counts, known trace IDs, and oldest/newest timestamps.

Args:

  • service_name (string, optional): A specific service to inspect. Omit for all.

Returns: Per-container stats including line counts by level and a sample of known trace IDs. Useful for a quick health overview before deeper investigation.

ParametersJSON Schema
NameRequiredDescriptionDefault
service_nameNoContainer name or Compose service name. Omit to get stats for all containers.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish the tool as read-only, idempotent, and non-destructive, so the description only needs to add behavioral context beyond safety. It adds that the result includes 'a sample of known trace IDs' rather than an exhaustive list, and that stats are per-container with oldest/newest timestamps. This gives the agent an accurate model of what the call will and will not reveal, with no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with the most important information: what the tool returns and its scope. The Args/Returns sections are slightly redundant with the opening sentence and the schema, but the overall structure is easy to scan and contains no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With one optional parameter, a clear summary of return contents, and annotations covering the read-only safety profile, the description is complete for an agent to invoke the tool correctly. There is no output schema, but the description explicitly lists the per-container stats returned, so no critical context is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already fully documents the single optional service_name parameter with an identical explanation ('Omit to get stats for all containers'). The description repeats this guidance but adds no new semantic detail beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description begins with a specific verb and resource: 'Return buffer statistics for one or all containers,' and then enumerates exactly what those statistics are (line counts, error/warn counts, trace IDs, timestamps). This clearly distinguishes the tool from siblings like search_logs or list_active_containers by describing an aggregated snapshot rather than a list or log search.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear usage context: it is 'useful for a quick health overview before deeper investigation,' implying this is the first-look tool before using more targeted tools. It stops short of naming specific alternatives or saying when not to use it, so it earns a 4 rather than a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_active_containersList Active ContainersA
Read-onlyIdempotent

List all currently running Docker containers being monitored.

Returns the container name, short ID, Docker image, status, and the Compose project it belongs to (if any).

Args: - project_name (string, optional): Filter by Docker Compose project name. Omit to list all.

Returns: A formatted list of containers with: serviceName, containerId (12-char), image, status, project.

Use this first to understand the service topology before issuing other queries.

ParametersJSON Schema
NameRequiredDescriptionDefault
project_nameNoDocker Compose project name to filter by. return to list all containers.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint, idempotentHint, and destructiveHint annotations already cover safety, and the description adds useful behavioral scope: only monitored Docker containers, optional Compose-project filtering, and the exact return format. It also clarifies the 12-char container ID detail, which is beyond the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded, with the purpose stated first and usage guidance at the end. The Returns section partly duplicates the earlier prose listing fields, which costs a small amount of conciseness, but the added field-name mapping and 12-char detail justify most of the repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple list tool with one optional parameter and no output schema, the description is complete: it specifies the return shape, the optional filter, the monitored-container scope, and the intended position in the workflow. An agent has enough information to call it correctly without further inference.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already provides 100% coverage for the single optional parameter, and the description only repeats the same filter behavior ('Filter by Docker Compose project name. Omit to list all.'). It adds no new semantic information beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific action ('List all currently running Docker containers being monitored') and identifies the returned fields. This distinguishes it from the sibling tracing/logging tools, making its purpose unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly instructs to use this tool first to understand service topology before issuing other queries, which provides clear context. It does not name specific alternatives or exclusions, but the guidance is sufficient for the simple listing use case.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_trace_idsList Known Trace IDsA
Read-onlyIdempotent

List all trace/request IDs currently in the in-memory buffer.

Useful when you don't already know a trace ID — browse available ones and pick the suspicious one to investigate with search_by_trace_id.

Args:

  • service_name (string, optional): Only list trace IDs seen in this service's logs.

  • limit (number, 1-1000): Max IDs to return. Default 50.

Returns: A list of trace ID strings, most-recently seen first.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of trace IDs to return (default 50).
service_nameNoFilter trace IDs seen in a specific service. Omit for all services.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, covering the safety profile. The description adds meaningful behavioral context: the buffer is in-memory and the trace IDs are ordered most-recently seen first, which goes beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured into purpose, use-case, Args, and Returns, with no filler. The core purpose is front-loaded in the first sentence, and every line adds useful information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description correctly supplies the return shape: 'a list of trace ID strings, most-recently seen first'. It also covers both optional parameters and gives a clear usage workflow, so nothing needed to invoke the tool correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both limit and service_name are already fully documented in the input schema. The description essentially repeats the schema information without adding new parameter-level meaning beyond the output ordering.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states 'List all trace/request IDs currently in the in-memory buffer', giving a specific verb, resource, and scope. It also frames the tool as a browsing step before investigating with search_by_trace_id, which distinguishes it from the lookup sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an explicit usage condition: 'Useful when you don't already know a trace ID'. It names search_by_trace_id as the follow-up, clearly explaining where this tool fits in the investigation workflow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_by_trace_idSearch by Trace IDA
Read-onlyIdempotent

Return a chronologically merged timeline of all log events across every container that share a specific trace / request ID.

This is the primary debugging tool. It correlates distributed transactions in O(1) time using the in-memory trace index.

Args:

  • trace_id (string): The correlation ID to search for (e.g. "req-998877", a W3C traceparent trace hex).

  • limit (number, 1-500): Maximum events to return. Default 200.

Returns: A chronological list of log lines across all services tagged with this trace_id, showing the full distributed call path — ideal for pinpointing cascading failures.

Example: search_by_trace_id({ trace_id: "req-998877" })

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of log events to return (default 200).
trace_idYesThe trace/request/correlation identifier to search for (e.g. 'req-998877', a W3C traceparent hex ID).

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, and non-destructive behavior. The description adds valuable behavioral context by explaining the chronological merging across all containers, the O(1) in-memory trace index, and the return of the full distributed call path. This goes well beyond the annotations and helps the agent understand expected behavior and performance.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized with a front-loaded purpose sentence, followed by context, parameters, return value, and an example. Each section earns its place and there is no redundant filler. The information is dense but scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Although there is no output schema, the description explicitly explains the return value as a chronological list of log lines across all services showing the distributed call path. It also states parameter constraints, defaults, and provides an example invocation. For a two-parameter read-only tool with full schema coverage, this is complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already fully documents both parameters. The Arg descriptions in the tool description largely duplicate the schema, with the only added value being a concrete example call and the embedded format examples for trace_id. Since the schema carries the semantic load, a baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Return a chronologically merged timeline of all log events across every container that share a specific trace / request ID.' This clearly states what the tool does and the scope. It also positions itself as 'the primary debugging tool,' which helps distinguish it from more generic siblings like search_logs.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'This is the primary debugging tool' provides clear context for when to use it, and the emphasis on correlating distributed transactions signals its intended use case. However, it does not explicitly name alternatives or state when not to use it, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_logsSearch LogsA
Read-onlyIdempotent

Full-text search across all (or a specific) container's buffered log lines.

Useful for finding specific error messages, stack trace snippets, SQL queries, or any freeform string that doesn't have a structured trace ID.

Args:

  • query (string): Case-insensitive substring to search for in log messages.

  • service_name (string, optional): Restrict search to this container. Omit to search all.

  • limit (number, 1-500): Max matching lines to return. Default 100.

  • level_filter (string[], optional): Restrict to specific log levels.

Returns: Matching log lines in chronological order with their service name, timestamp, and level.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of matching lines to return (default 100).
queryYesCase-insensitive substring or simple pattern to search in log messages.
level_filterNoRestrict results to these log levels.
service_nameNoRestrict search to this container/service. Omit to search all containers.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the tool read-only, idempotent, and non-destructive. The description adds useful behavioral context beyond that: it searches buffered lines, returns results in chronological order, and specifies the returned fields. It does not mention rate limits or buffer retention, but these are not critical for a read-only search tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded and the description is compact, with a useful use-case sentence and a clear return-value sentence. The Args block is somewhat redundant with the schema, but it is well organized and easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description explicitly covers the return shape: chronological log lines with service name, timestamp, and level. It also covers scope, optional service restriction, level filtering, limit behavior, and the intended use case, making it sufficient for correct tool selection and invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides 100% parameter coverage with clear descriptions, so the schema already explains every parameter and constraint. The Args section restates the same meanings without adding new semantic information, which meets the baseline but does not exceed it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific action (full-text search) and resource (container's buffered log lines) with an explicit optional scope. It also distinguishes itself from structured trace-ID lookup by emphasizing freeform strings, so an agent can tell it apart from search_by_trace_id.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a clear use case: finding error messages, stack traces, SQL queries, or freeform strings without a structured trace ID. This implies when to prefer this tool over structured-ID search, though it does not explicitly name sibling alternatives or state exclusion conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tail_service_errorsTail Service ErrorsB
Read-onlyIdempotent

Retrieve the most recent ERROR and FATAL log lines = require(a specific container — the fastest way to find the initial failure point before diving into a full trace.

Args:

  • service_name (string): Docker container name or Compose service name (e.g. "checkout-worker").

  • limit (number, 1–500): How many error lines to return. Default 50.

  • include_warnings (boolean): Also include WARN-level lines. Default false.

Returns: The N most-recent ERROR/FATAL (and optionally WARN) log lines = require(the named service, in chronological order.

Error Handling:

  • Returns an error message if the service_name does not match any running container.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoNumber of most-recent ERROR/FATAL log lines to return (default 50).
service_nameYesDocker container name or Compose service name to inspect.
include_warningsNoIf true, also include WARN-level log lines alongside errors.

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes beyond the annotations (readOnlyHint=true, idempotentHint=true) by disclosing chronological ordering, the optional inclusion of WARN lines, and the error behavior when the service_name doesn't match a running container. This adds useful behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The text is organized into Args/Returns/Error Handling, but it contains the repeated corrupted token '= require(' which disrupts readability and looks like an accidental code snippet. This is a structural quality issue that prevents a higher score.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given there is no output schema, the description does explain the return shape (N most-recent, chronological order) and error handling, which is good. Still, it lacks explicit routing to alternatives and the corrupted wording makes it less complete for an agent to confidently invoke.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema coverage is 100%, so the description adds little new semantic value. It provides an example value and restates the limit/warnings meaning, but does not meaningfully extend the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Retrieve') and resource ('most recent ERROR and FATAL log lines from a specific container'), and gives a clear use case ('find the initial failure point'). However, the literal text contains a corrupted token '= require(' which undermines clarity, and it does not explicitly differentiate itself from the sibling tool tail_service_logs.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'the fastest way to find the initial failure point before diving into a full trace' implies when to use this tool, but it never names alternatives like tail_service_logs or search_logs, nor does it state when not to use it. The guidance is only implicit and contextual.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tail_service_logsTail Service LogsA
Read-onlyIdempotent

Retrieve the N most-recent log lines = require(a specific container, with optional level filtering.

Args:

  • service_name (string): Container name or Compose service name.

  • limit (number, 1-500): Lines to return. Default 100.

  • level_filter (string[], optional): One or more of TRACE, DEBUG, INFO, WARN, ERROR, FATAL, UNKNOWN. return for all levels.

Returns: The most-recent matching log lines in chronological order. Use this to get general context around a service before narrowing to a trace ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoNumber of most-recent log lines to return (default 100).
level_filterNoOptional list of log levels to include. Omit to return all levels.
service_nameYesContainer name or Compose service name.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this tool read-only, idempotent, and non-destructive, so the behavior bar is lower. The description adds useful behavioral detail beyond annotations: returned logs are the most recent matching lines, in chronological order, and omitting level_filter returns all levels. No contradiction with annotations was found.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is organized with Args and Returns and is reasonably compact. However, the first sentence contains a stray '= require(' artifact and 'return for all levels' is grammatically incomplete, which makes it less polished than it could be.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter read-only tool with full schema coverage and strong annotations, the description adequately covers what is returned, ordering, filtering behavior, and when to use it. The malformed opening sentence and lack of explicit error/edge-case behavior prevent a perfect score.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already explains service_name, limit defaults and bounds, and level_filter values. The description mostly restates these details without adding new semantic information beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action: retrieve the N most-recent log lines for a specific container or service, with optional level filtering. It also positions this tool as a way to get general context before narrowing to a trace ID, which helps differentiate it from search_by_trace_id. However, the phrase '= require(a specific container' is malformed and slightly obscures the intended meaning.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear usage context by suggesting it be used to get general service context before narrowing to a trace ID. This implies when it is appropriate relative to trace-focused siblings, but it does not explicitly state when not to use it or name alternatives such as tail_service_errors or search_logs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 7 tool updatesv1.0.0
    • First observedget_container_stats
    • First observedlist_active_containers
    • First observedlist_trace_ids
    • First observedsearch_by_trace_id
    • First observedsearch_logs
    • First observedtail_service_errors
    • First observedtail_service_logs

TDQS

A4/5.0
Disambiguation4/5

Most tools have clearly distinct purposes, with the main overlap being tail_service_errors and tail_service_logs when level_filter includes ERROR/FATAL. The descriptions mitigate this by positioning tail_service_errors as the fast error-spotting tool, but an agent could still reasonably confuse which to call.

Naming Consistency5/5

All tool names follow a consistent snake_case verb-first pattern: list, search, get, tail. The naming style is predictable and makes it easy to infer what each tool does before reading its description.

Tool Count5/5

Seven tools is a well-scoped count for a log correlation server. Each tool covers a distinct aspect of the debugging workflow without feeling bloated or too sparse.

Completeness4/5

The set covers container discovery, stats, error tailing, general log tailing, full-text search, trace ID listing, and trace-correlated timelines. A notable minor gap is the lack of explicit time-range based log queries, but the core distributed debugging workflow is well supported.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • -
    license
    Not graded
    quality
    Not graded
    maintenance
    Provides comprehensive logging and monitoring capabilities for MCP services with real-time log tailing, advanced search, error analysis, and anomaly detection. Enables centralized log aggregation, correlation tracking, and health monitoring across all MCP ecosystem services.
    -
  • F
    license
    B
    quality
    D
    maintenance
    A log analysis MCP server that enables tailing, searching, filtering, and summarizing logs from local files and Docker containers.
    7
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Exposes configured log files as MCP tools, enabling agents to list, query, and follow logs from local and SSH sources.
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables querying and searching logs from Kibana (ELK stack) via MCP, with support for project-based data views, trace ID correlation, and log expansion.
    -

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/parajiholkar/multi-container-log-correlator-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server