find the message

kafka-mcp lets an LLM agent debug Kafka for you. It finds a message by order id, measures lag, unblocks a stuck consumer and compares two clusters. Every answer says what it covered. Every write shows a preview before anything changes.

transport
stdio · streamable http
tools
clusters per process
as many as you configure
client
franz-go
session kafka-prod-read · read-only

    get started

    Install it, point it at a cluster, register it with your agent.

    1. 1

      install

      Let your agent do it: paste the prompt and it installs the binary, the skill, a config and the MCP registration. Or install by hand.

      Install the kafka-mcp MCP server for me.
      
      1. Open https://github.com/denizgursoy/kafka-mcp/releases/latest and download
         the archive for this OS and CPU: kafka-mcp_<Os>_<arch>.tar.gz, or .zip
         on Windows. Check it against the checksums file, extract it, and put the
         kafka-mcp binary on my PATH.
      2. From the same release tag, copy the skills/kafka-debugging directory of the
         repository into your skills directory, so you know how to use the tools.
      3. Ask me for my Kafka brokers, how to authenticate, and whether this should
         be read-only. Then write a kafka-mcp.yaml as described at
         https://denizgursoy.github.io/kafka-mcp/#configure. Never put a password
         in the file: use "{env:VAR}" and tell me which variable to set.
      4. Register kafka-mcp as a local stdio MCP server in your own configuration,
         with CONFIG_FILE pointing at that file.
      5. Tell me to restart you so the tools and the skill load.

      Works with any agent that can run shell commands and edit its own config, such as Claude Code or OpenCode. Read what it plans to run before you approve it.

      # 1. the binary, from https://github.com/denizgursoy/kafka-mcp/releases
      tar -xzf kafka-mcp_Darwin_arm64.tar.gz
      sudo mv kafka-mcp /usr/local/bin/
      
      # 2. the skill, into your agent's skills directory
      #    Claude Code: ~/.claude/skills   OpenCode: ~/.config/opencode/skills
      curl -sL https://github.com/denizgursoy/kafka-mcp/archive/refs/heads/main.tar.gz \
        | tar -xz --strip-components=2 -C ~/.claude/skills kafka-mcp-main/skills/kafka-debugging
      # from https://github.com/denizgursoy/kafka-mcp/releases/latest
      kafka-mcp_<version>_darwin_arm64.mcpb    # macOS, Apple Silicon
      kafka-mcp_<version>_linux_amd64.mcpb
      kafka-mcp_<version>_linux_arm64.mcpb
      kafka-mcp_<version>_windows_amd64.mcpb

      Open it in a client that installs MCP Bundles, such as Claude Desktop. It asks for your kafka-mcp.yaml and, if the file has several, the endpoint. Also listed in the MCP Registry as io.github.denizgursoy/kafka-mcp.

      docker run --rm -p 8090:8090 \
        -v $PWD/kafka-mcp.yaml:/kafka-mcp.yaml \
        -e CONFIG_FILE=/kafka-mcp.yaml \
        ghcr.io/denizgursoy/kafka-mcp:latest

      The image starts with --server, so it serves HTTP on :8090. Add -i and end the command with --server=false for stdio.

      git clone https://github.com/denizgursoy/kafka-mcp
      cd kafka-mcp
      make env-up   # local Redpanda on :19092, Console on :8080
      make run      # serves kafka-mcp.local.yaml on :8090

      Requires Go 1.27. Tests need Docker.

    2. 2

      configure

      Write a kafka-mcp.yaml. This one is enough for a local broker. The full reference is below.

      clusters:
        local:
          brokers: localhost:19092
      endpoints:
        local:
          cluster: local
          path: /mcp/local

      Looked up in order: CONFIG_FILE, the working directory, ~/.config/kafka-mcp/, then /etc. The first match wins; files are not merged.

    3. 3

      connect

      Over stdio the client launches the binary. Over HTTP every endpoint has its own URL.

      {
        "mcp": {
          "kafka-local": {
            "type": "local",
            "command": ["kafka-mcp", "--endpoint", "local"],
            "environment": { "CONFIG_FILE": "/path/to/kafka-mcp.yaml" }
          }
        }
      }

      --endpoint can be left out when the file has only one endpoint.

      # start once: kafka-mcp --server
      {
        "mcp": {
          "kafka-local": {
            "type": "remote",
            "url": "http://localhost:8090/mcp/local"
          }
        }
      }

      The key becomes the tool prefix: kafka-local_list_topics. Name it after the cluster and the policy.

      curl http://localhost:8090/healthz
      
      curl -s -X POST http://localhost:8090/mcp/local \
        -H 'Content-Type: application/json' \
        -H 'Accept: application/json, text/event-stream' \
        -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}'

      Send the returned Mcp-Session-Id header on every later request.

    4. 4

      ask

      Ask in plain words. The bundled skill tells the agent which tools to call, in which order.

      > is there lag on orders, and when will it clear?

      Copy skills/kafka-debugging into your agent's skills directory. It routes each request to one of one guide per scenario.

    configure

    Two ideas. Clusters say how to reach Kafka. Endpoints say what a session may do there. One cluster can sit behind several endpoints, such as a read-only one for investigating and a writable one for approved changes.

    kafka-mcp.yaml
    http:
      address: ":8090"
      base_path: /kafka-mcp
    output_dir: /var/tmp/kafka-mcp
    
    clusters:
      prod:
        brokers:
          - kafka-1:9093
          - kafka-2:9093
        security:
          tls:
            enabled: true
            ca_file: /etc/kafka/ca.pem
          sasl:
            - scram:
                enabled: true
                algorithm: SCRAM-SHA-256
                user: kafka-mcp-readonly
                pass: "{env:KAFKA_PASSWORD}"
      preprod:
        brokers: kafka-preprod:9093
    
    endpoints:
      prod-read:
        cluster: prod
        path: /mcp
        description: Production investigation
        read_only: true
      prod-write:
        cluster: prod
        path: /mcp/rw
        tools:
          delete_topic: false
      preprod:
        cluster: preprod
    • routes With base_path set, the routes become /kafka-mcp/mcp, /kafka-mcp/mcp/rw and /kafka-mcp/mcp/preprod. Paths match exactly.
    • secrets {env:VAR} reads a value from the environment. password_file reads it from a file. The password never appears in server_config.
    • one connection prod-read and prod-write share a single Kafka client. Only their policies differ.
    • withholding tools only narrows an endpoint. It cannot bring back what read_only hides.
    • down at startup An unreachable cluster is still served. list_clusters reports it as disconnected, so one outage does not block the rest.

    flags and environment

    namekindwhat it does

    tools

    A tool that names a topic, partition or group takes it in an items array. One call can cover ten topics, and each item succeeds or fails on its own. Open a row to see its parameters, a call and a response.

    scenarios

    Each tool exists because a debugging scenario needed it. The skill ships one guide per scenario, because the obvious sequence of calls gets each of them wrong in a specific way.

    safety

    There are three layers. Only the last one is security.

    confirm: trueguardrail

    Every write runs as a preview first. Nothing changes until the whole batch is approved.

    read_only: truepolicy

    The tools that only write are not listed, so the agent never sees them. Each tool also refuses at the moment it would write.

    kafka aclssecurity

    The broker decides, per SASL principal. Nobody can turn it off by editing a config file.

    honest results
    An empty search means the message is absent only when complete is true.
    provenance
    Copied and produced messages carry headers that say where they came from.
    audit log
    Every call is logged with its targets. Message content is never logged.
    bound sessions
    A session is tied to one endpoint by its URL, and no parameter can redirect it.