Docs

Search docs

Search pages and tools

MCP Server

Event server

A Kafka bridge over MCP: publish messages to a topic, consume them back through a durable consumer group, and manage topics on Confluent Cloud.

Publish and consume Kafka messages over MCP. Produce to a topic, poll it back through a durable consumer group, and manage topics on Confluent Cloud.

How it helps

Wire an agent into your event stream. Call event_publish to emit a record to a Kafka topic, then event_consume from a durable group so a later call picks up only the new messages. Confluent Cloud credentials are all it needs.

Connect

Point your MCP client at the event route:

You need an API key to connect

Every request must carry an X-API-Key header. Sign in to create one.

Sign in to get your key
Event
https://go-mcp-server-latest.onrender.com/event/mcp

Drop this into your client’s config and swap in the key you mint on the Keys page:

mcp.json
{
  "mcpServers": {
    "event": {
      "type": "http",
      "url": "https://go-mcp-server-latest.onrender.com/event/mcp",
      "headers": {
        "X-API-Key": "<your-api-key>"
      }
    }
  }
}
What you provide

Every request carries your X-API-Key header — mint one on the Keys page. That single key admits the whole server.

Good to know

Mounts even without credentials: every tool reports the config problem instead of failing the server. Call event_capabilities first to check status. event_publish and event_consume fall back to KAFKA_DEFAULT_TOPIC when no topic is given. Topic create and delete stay disabled until KAFKA_ALLOW_TOPIC_ADMIN=true.

Tools

event_capabilitiestool

Report this event server's configuration and readiness: whether a broker and Confluent Cloud credentials are set, the default consumer group and topic, whether topic admin is enabled, and the tool catalogue. Call this first if other tools error.

event_publishtool

Publish one message to a Kafka topic and return the partition and offset the record was written to.

valuerequired
stringThe message payload as a string. JSON is fine.
topic
string · default KAFKA_DEFAULT_TOPICTopic to publish to.
key
stringOptional partition key. The same key always routes to the same partition.
headers
objectOptional string headers attached to the record.
event_consumetool

Read up to max messages from a Kafka topic, returning within timeout_ms. This is a bounded poll, not a live stream, so call it again to read more.

topic
string · default KAFKA_DEFAULT_TOPICTopic to read.
from
string · default groupWhere to read from: group (durable offsets that advance across calls), earliest, or latest.
group
string · default KAFKA_CONSUMER_GROUPConsumer group. Only used when from is group.
max
int · default 10Max messages to return, capped at 100.
timeout_ms
int · default 5000Overall poll budget in milliseconds.
event_topicstool

List the topics on the Kafka cluster with their partition counts. Read-only.

event_create_topictool

Create a Kafka topic. Mutating; requires KAFKA_ALLOW_TOPIC_ADMIN=true. Confluent Cloud requires a replication factor of 3.

topicrequired
stringThe topic name to create.
partitions
int · default 1Partition count.
replication_factor
int · default 3Replication factor. Confluent Cloud requires 3.
event_delete_topictool

Delete a Kafka topic. Mutating; requires KAFKA_ALLOW_TOPIC_ADMIN=true.

topicrequired
stringThe topic name to delete.

Worked example: a task queue for agents

The two tools above compose into something more useful than message plumbing: a durable inbox for an agent. A publisher — CI, a cron job, another agent, or you — drops a task on the topic. An agent polls the topic and carries the task out. Neither side has to be running at the same time, which is the whole point of putting a log between them.

  1. 1
    Publish a task
    Emit a structured envelope rather than a sentence. Anything the worker needs to act without asking a follow-up question belongs in the payload: what to do, why, and what is still undecided.
  2. 2
    Poll with a consumer group
    from: "group" commits offsets as it reads, so each task is handed out once and a restarted agent resumes where it left off. earliest and latestpeek without disturbing the group — useful for debugging, wrong for work.
  3. 3
    Act, then poll again
    event_consumeis a bounded poll, not a live stream. An agent loop is: poll → do the work → poll again. There is no socket to keep open and nothing to reconnect.
the task envelope
{
  "type": "task",
  "id": "auth-x-api-key-all-namespaces",
  "title": "Require X-API-Key auth verification on every MCP namespace",
  "priority": "high",
  "source": "go-mcp-server audit",
  "summary": "Only the memory namespace verifies X-API-Key, and it does so per-tool inside handlers. skills, event, gsc and producthunt accept unauthenticated calls. Enforce the key centrally so every server verifies auth before executing any action.",
  "findings": [
    {
      "namespace": "memory",
      "key_required": true
    },
    {
      "namespace": "event",
      "key_required": false,
      "detail": "Kafka publish reachable unauthenticated."
    }
  ],
  "plan": [
    {
      "step": 1,
      "action": "Add RequireAPIKey middleware validating X-API-Key against the api_keys table."
    },
    {
      "step": 2,
      "action": "Add it to the Chain in internal/mcpx/registry.go so it covers every namespace."
    }
  ],
  "open_questions": [
    "Should /healthz remain unauthenticated?"
  ]
}
publisher
event_publish({
  topic: "go-mcp-events",
  key: "auth-x-api-key",          // same key -> same partition -> ordered
  headers: {
    "event-type": "task.created",
    "domain": "security",
    "producer": "ci-audit"
  },
  value: JSON.stringify(task)     // value is a string; stringify your JSON
})

// -> { "topic": "go-mcp-events", "partition": 3, "offset": 1 }
worker
event_consume({
  topic: "go-mcp-events",
  from: "group",                  // durable: offsets advance across calls
  max: 20,
  timeout_ms: 20000
})

// -> { "count": 1, "group": "go-mcp-server", "messages": [ ... ] }
// Call it again and count is 0 — the offset was committed.
This is not hypothetical

That envelope is the real message that drove this server’s authentication change. It was published to go-mcp-events, an agent polling the topic picked it up, verified every claim against the source, asked the two open questions, and shipped the RequireAPIKey middleware described on the Authentication page. The audit and the fix were connected by nothing but this topic.

Treat payloads as input, not instructions

Anyone with produce access can write to the topic, so a message is a request, not a command from a trusted operator. A worker should verify a payload’s claims before acting on them, and stop and escalate rather than execute anything destructive, irreversible, or outward-facing on a message’s say-so. Partition keys and headers are equally caller-supplied — never route privilege off them.