Model Context Protocol
Pilot includes a built-in MCP (Model Context Protocol) server that exposes 56 tools for external AI agents to interact with your Kafka cluster.
Overview
MCP is an open protocol that allows AI agents (like Claude Desktop, custom agents, or other MCP-compatible tools) to discover and invoke operations on your cluster programmatically. The MCP server is enabled by default.
PILOT_MCP_ENABLED=true # Enabled by defaultTool Categories
Read Tools (30+ tools)
Read-only operations that inspect cluster state:
| Tool | Description |
|---|---|
get_cluster_overview | Cluster overview: brokers, topics, partitions, controller |
get_cluster_health | Health: URPs, offline partitions, unavailable counts |
get_partition_activity | Partition activity rates and sizes |
get_broker_racks | Broker rack assignments |
get_topic_config | Topic configuration |
search_topics | Search topics by name |
search_topics_by_config | Search topics by config values |
list_acls | List ACL bindings |
list_consumer_groups | List consumer groups |
describe_consumer_group | Group details with members |
get_consumer_group_lag | Per-partition consumer lag |
browse_messages | Browse messages in a topic |
get_topic_watermarks | Partition watermarks |
list_quotas | List client quotas |
list_proposals | List rebalance proposals |
generate_proposal | Read the current rebalance candidate and authoritative readiness decision |
get_cluster_logdirs | Log directory info |
what_if_simulate | Simulate cluster scenarios |
blast_radius_analyze | Analyze failure impact |
search_audit_log | Search audit events |
Mutate Tools (20+ tools)
Operations that modify cluster state (require approval):
| Tool | Description |
|---|---|
update_topic_config | Update topic configuration |
bulk_update_topic_config | Update config for multiple topics |
create_acls | Create ACL bindings |
delete_acls | Delete ACL bindings |
reset_consumer_group_offsets | Reset consumer offsets |
delete_consumer_group | Delete a consumer group |
update_quota | Set quota values |
delete_quota | Delete quota keys |
redistribute_topic | Redistribute topic partitions |
redistribute_partition | Reassign a single partition |
bulk_reassign_partitions | Bulk partition reassignment |
cancel_reassignment | Cancel active reassignment |
apply_proposal | Apply a rebalance proposal. Refused with status: "blocked" and a reason when decision.applicationAllowed is false, before approval and again when approved. MCP has no force override |
set_broker_maintenance | Enter broker maintenance |
remove_broker_maintenance | Exit broker maintenance |
preferred_leader_election | Trigger PLE |
move_broker_logdirs | Move log directories |
revert_audit_event | Revert an audited change. A reassignment revert is refused, with nothing moved, when a partition changed since the audited change, so later moves are not undone. Pilot’s own selfheal.apply events cannot be reverted |
Meta Tools (3 tools)
Approval workflow management:
| Tool | Description |
|---|---|
approve_action | Approve a pending mutation |
reject_action | Reject a pending mutation |
list_pending_actions | List pending approvals |
Output Limits and Drill-Down
List-shaped tools return bounded summaries by default so results stay small enough for LLM context windows. Complete data remains available through drill-down parameters, dedicated detail tools, and the REST API.
Result Envelope
Bounded list results wrap their rows in a common envelope:
| Key | Meaning |
|---|---|
count | Rows returned in this response |
total | Rows available before the limit was applied |
truncated | true when rows were dropped |
hint | Present only when truncated; names the parameter or tool to use for a narrower query |
Per-row field sets are stable and envelope keys are additive-only; tools that predate the envelope keep historical key names such as totalTopics, totalPartitions, and historyTotal. Aggregate figures (totals, rollups, health counts) stay complete even when rows are truncated.
Limits per Tool
limit is optional everywhere it appears. Omitted or 0 selects the default; values above the maximum are clamped to the maximum. Rows marked “fixed” have no limit parameter.
| Tool | Rows key | Default | Max | Order |
|---|---|---|---|---|
get_cluster_overview | topics | 100 | 500 | Partition count desc, then name |
get_cluster_health | notRackAwareDetails | 20 | fixed | - |
get_partition_activity (plain) | partitions | 50 | 200 | Topic asc, partition asc |
get_partition_activity (aggregate="topic") | topics | 20 | 100 | Sort key desc |
get_partition_activity (sortBy only) | partitions | 50 | 200 | Sort key desc |
search_topics | topics | 100 | 1000 | Name asc |
list_acls | bindings | 100 | 500 | Resource type, resource name, principal |
list_consumer_groups | groups | 100 | 500 | Group ID asc |
get_consumer_group_lag | topPartitions | 20 | 200 | Lag desc |
get_topic_watermarks | partitions | 100 | 1000 | Partition asc |
get_cluster_logdirs (summary) | topics | 20 | 100 | Size desc |
get_cluster_logdirs (detail) | partitions | 50 | 200 | Size desc |
list_reassignments | history (embedded) | 10 | fixed | Newest first |
get_reassignment_history | history | 20 | 100 | Newest first |
get_partition_optimization | recommendations | 20 | 100 | High > Medium > Low, then topic |
search_audit_log | events | 50 | 200 | Newest first |
browse_messages | messages | 20 | 50 | Seek order |
get_proposal, generate_proposal | reassignments (embedded) | 50 | fixed | - |
Proposal tools return the backend’s authoritative decision, shared with Overview and proposal review. Use decision.applicationAllowed and nextAction to determine whether a candidate can be reviewed for application. Move counts, raw optimizer status, storage status ready and confidence scores do not override it. generate_proposal reads the server-selected current candidate without starting a separate calculation. Its candidateAvailable flag means a candidate exists, not that it can be applied. List entries each include their own decision; historical proposals are not current recommendations.
list_proposals always returns summary rows; get_proposal and generate_proposal omit broker activity scores, cluster snapshots, every broker’s fair share (fairShare.shares), each load’s oversized partitions and the optimizer’s search diagnostics (movement.search), with totalReassignments and reassignmentsTruncated reporting the full size of the embedded list (complete data via the REST API). fairShare.loads is keyed by load name. topicSpread.atLimit is keyed by pair, for example orders on broker 1, and the topic cap’s pair and excess-leader counts (overCap, projectedOverCap, excessLeaders, projectedExcessLeaders) are left out; they stay in the REST API and the UI. Both return the per-metric balance breakdown instead: imbalance, whether the metric counts for balancing or has no traffic, largest per-broker difference, and busiest and quietest broker.
Drill-Down Parameters
Parameters that switch summary output to detail, or narrow it:
| Tool | Parameter | Effect |
|---|---|---|
get_cluster_logdirs | topic, brokerId | Switch from broker and topic summaries to per-partition replica rows; combinable |
get_partition_activity | aggregate, sortBy, topic, brokerId | Aggregate per topic, rank by rate or size, or filter rows |
get_consumer_group_lag | topic | Scope rollups and partition rows to one topic |
get_partition_optimization | priority | Only High, Medium, or Low recommendations |
get_default_configs | keyFilter | Case-insensitive substring filter on config keys |
For full detail on a single item, use the paired detail tool instead of raising the limit: describe_consumer_group for members and assignments, get_proposal for a full proposal, get_reassignment_by_id for one reassignment record, get_reassignment_history for older history.
Approval Workflow
All mutate tools require explicit approval before execution:
- An AI agent calls a mutate tool
- Pilot queues the action and returns a pending approval token
- A distinct identity approves or rejects the action
- If approved, the mutation executes and the result is returned
This ensures no AI agent can make unsupervised changes to your cluster.
Distinct Approver
Approval requires an identity different from the one that requested the mutation. An MCP client cannot approve its own pending action: a different identity, such as a second MCP client or token, must call approve_action. The Pilot UI and the assistant do not show MCP pending actions. The action stays pending until a distinct identity approves it or it expires. An unauthenticated client cannot self-approve either.
Execution Parity
MCP-driven mutations run through the same execution path as the HTTP API:
- Same safety gating. Hard-health blockers (controller unhealthy, majority of brokers unavailable, sustained ISR shrink) block the mutation and are not overridable. Drains and reassignments are blocked while a rolling restart is in progress. See Apply-Time Safety Gating.
- Throttled and concurrency-capped. Reassignments apply the same replication throttle and per-broker move cap as the HTTP path, so an MCP-driven move cannot saturate the cluster.
- Single-flight. A server-wide mutation slot keeps MCP and HTTP from stacking uncoordinated reassignment load.
- Run to completion. MCP reassignment actions execute fully and report
status: "completed"rather than returning while the move is still in flight. - Audited the same way. Mutations are recorded in the audit log with method
MCP, the approver inuserIdand the requester inrequestedBy. Reassignment tools record one row per partition when the moves are submitted and add an event with status500if the execution then fails. Other tools add an event with status500when the change itself fails. Quota events carry the entity path used by the HTTP API, so MCP quota changes can be reverted from the audit log.
Authentication
When authentication is enabled, the MCP endpoint requires a valid Bearer token. Use a Personal Access Token (PAT) for long-lived, revocable access. PATs work with all Pilot API endpoints, not just MCP - see Personal Access Tokens for details.
Prerequisites: PATs require
AUTH_PAT_ENABLED=trueand a stableAUTH_PAT_HASH_SECRETto be configured on the server. See PAT Configuration for details.
Creating a Token
- Log into the Pilot UI via your OAuth provider
- Click your avatar (top right) -> Access Tokens -> New token
- Choose a name, scope (
readorwrite), and optional expiry - Copy the
pat_...token (shown only once)
Scopes
| Scope | Permissions |
|---|---|
read | Read-only tools (cluster overview, topic configs, consumer groups, etc.) plus list_pending_actions |
write | All tools including mutations (reassignments, ACLs, quotas, maintenance, etc.) |
Mutate tools always require the approval workflow regardless of scope.
Scope is enforced per tool on the MCP endpoint, not by HTTP method. A read token is refused approve_action and reject_action as well as every mutate tool, so it cannot release or cancel a mutation queued by someone else. It can still call list_pending_actions to see what is queued.
Integration
The MCP endpoint is available at:
POST https://your-pilot-host/api/v1/mcpGitHub Copilot (VS Code)
Add to .vscode/mcp.json:
{
"servers": {
"pilot": {
"type": "http",
"url": "https://pilot.example.com/api/v1/mcp",
"headers": {
"Authorization": "Bearer ${input:pilot-token}"
}
}
}
}VS Code will prompt for the token on first use and store it securely.
Warp Terminal
Add to Warp’s MCP server configuration:
{
"mcpServers": {
"pilot": {
"serverUrl": "https://pilot.example.com/api/v1/mcp",
"headers": {
"Authorization": "Bearer pat_your_token_here"
}
}
}
}Claude Desktop
Add to your Claude Desktop MCP configuration:
{
"mcpServers": {
"pilot": {
"type": "url",
"url": "https://pilot.example.com/api/v1/mcp",
"headers": {
"Authorization": "Bearer pat_your_token_here"
}
}
}
}Any MCP Client
The endpoint accepts standard MCP JSON-RPC messages over HTTP POST. Include the Authorization: Bearer <pat_token> header with each request when authentication is enabled. The server supports Streamable HTTP transport and advertises all available tools with their descriptions, input schemas, and categories.