fleetalert-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@fleetalert-mcpList the FleetAlert alerts and summarize the trace for the one awaiting confirmation"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
fleetalert-mcp
An MCP server for FleetAlert AI, the agentic alert-investigation demo in mbgolden/fleetalert-ai. It lets Claude Code, Claude Desktop or any MCP client read FleetAlert's alerts and investigation traces, start investigations, and confirm or reject a proposed fix, with the same safety tiers FleetAlert enforces internally, plus the bearer-token auth and rate limits the public demo API does not have itself.
Built on the MCP Python SDK v2 (protocol 2026-07-28), Python 3.12.
What it demonstrates
Typed tools, structured output | Every tool has a JSON Schema input (from type hints) and a JSON Schema output (from pydantic models). |
Safety tiers carried through the protocol | Tools are tagged |
Human approval, structurally |
|
The server is the auth boundary | Over Streamable HTTP, requests need a bearer token ( |
Rate limits that protect the upstream budget | FleetAlert caps itself at 50 investigations or $1.25 a day. This server adds per-principal buckets (all tools, and a tighter one for tools that spend budget) and a global bucket in front of the upstream API. A refusal is a tool result the model can read ("retry in 12 s"), not a protocol error it never sees. |
Audit and metrics | One JSON line per tool call: principal, tier, tool, outcome, duration. |
Tested without the network | The SDK's in-memory client drives the real server against a mocked FleetAlert API, including the elicitation round-trip for |
Related MCP server: MCP Enterprise Tool Gateway
Tools
Tool | Tier | What it does |
| read_only | Every demo alert with machine, severity and status |
| read_only | One alert's status, proposed fix, confidence and root-cause summary |
| read_only | Investigation history, one summary per round |
| read_only | Raw spans with full input and output, filterable by kind |
| read_only | Today's spend against the daily cost guard |
| read_only | Recent cross-alert activity feed |
| proposes_action | Start an agent round on an open alert (spends budget) |
| proposes_action | Deliver the demo's seeded maintenance email |
| proposes_action | Run the rule-based detector once |
| executes_action | Ask the human, then confirm the proposed fix upstream |
| executes_action | Reject the proposed fix with a reason |
Also: resources fleetalert://alerts and fleetalert://alerts/{alert_id}/trace,
and a triage_alert prompt that walks a model through reviewing one alert's
evidence and recommending confirm, reject or wait.
Quick start
Claude Code, read-only, straight from GitHub:
claude mcp add fleetalert -- uvx --from git+https://github.com/mbgolden/fleetalert-mcp fleetalert-mcpTo allow actions, set the tier (the tools appear only when you do):
claude mcp add fleetalert -e FLEETALERT_MCP_TIER=executes_action -- uvx --from git+https://github.com/mbgolden/fleetalert-mcp fleetalert-mcpClaude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"fleetalert": {
"command": "uvx",
"args": ["--from", "git+https://github.com/mbgolden/fleetalert-mcp", "fleetalert-mcp"],
"env": { "FLEETALERT_MCP_TIER": "read_only" }
}
}
}Then ask: "List the FleetAlert alerts and summarise the trace for the one awaiting confirmation."
Configuration
All settings are FLEETALERT_MCP_* environment variables (a .env file in
the working directory is honoured; see .env.example).
Variable | Default | Meaning |
|
| Highest tier of tool to register: |
| the live demo | FleetAlert API base URL |
| empty | HTTP mode bearer tokens: |
|
| Public URL of this server in HTTP mode (for the protected-resource metadata) |
|
| Run HTTP mode without tokens, loopback only |
|
| Per principal, every tool |
|
| Per principal, tools above read_only |
|
| Across all principals |
|
|
HTTP mode
export FLEETALERT_MCP_TIER=executes_action
export FLEETALERT_MCP_TOKENS="ops:executes_action:$(openssl rand -hex 24),ci:read_only:$(openssl rand -hex 24)"
fleetalert-mcp --transport http --host 0.0.0.0 --port 8000POST /mcpis the MCP endpoint. Without a validAuthorization: Bearerheader it answers401with aWWW-Authenticateheader pointing at/.well-known/oauth-protected-resource/mcp.The
citoken above sees every tool the server registers but is refused on anything aboveread_only, with a message the model can read.GET /healthzandGET /metricsare unauthenticated and JSON.
The server refuses to start in HTTP mode without tokens unless
FLEETALERT_MCP_ALLOW_ANONYMOUS_HTTP=1 and the host is loopback.
How confirm_fix works
model: confirm_fix(alert_id="ALERT-1007")
server: GET /status -> awaiting_confirmation? (else: tool error, nothing sent)
server: elicit -> client shows the human the proposed fix, confidence, root cause
human: approve=true human: approve=false / decline / cancel
server: GET /status -> token server: result "not_confirmed", nothing sent
server: POST /confirm {token}
model: result "confirmed" (the token is not in it)If the client did not advertise elicitation, the tool is refused before any upstream call, with a message pointing the human at the FleetAlert web UI.
Development
uv sync --group dev
uv run ruff check . && uv run ruff format --check .
uv run mypy src
uv run bandit -q -r src
uv run pytest
FLEETALERT_MCP_LIVE=1 uv run pytest tests/test_live.py # read-only, against the real demoRun locally over stdio with uv run fleetalert-mcp, or over HTTP as above.
uv run mcp dev src/fleetalert_mcp/cli.py is not supported (the server is
built by build_server() from settings); use the MCP Inspector against the
HTTP endpoint instead.
Repo layout
src/fleetalert_mcp/
server.py tools, resources, prompt; build_server(settings)
tiers.py the three tiers and their ordering
guard.py middleware: principal, tier check, rate limits, audit log, metrics
auth.py static bearer tokens as a TokenVerifier
ratelimit.py token buckets
upstream.py typed httpx client for the FleetAlert API
summarize.py spans -> per-round summary
config.py FLEETALERT_MCP_* settings
cli.py stdio / HTTP entry point, /healthz, /metrics
tests/ in-memory client against a mocked API; one live smoke test
docs/decisions/ ADR log
docs/BACKLOG.md follow-ups, with the evidence that raised themDecisions
ADR-0001: a standalone repo on the Python SDK v2, not a folder in fleetalert-ai
ADR-0002: tiers decide which tools exist, default read-only, tokens narrow only
ADR-0003: confirm_fix asks the human through elicitation; the token never reaches the model
ADR-0004: this server is the auth and rate-limit boundary; static tokens now, OAuth later; refusals as tool results
License
MIT.
Available Tools
6 toolsget_activityBRead-onlyIdempotent
Recent cross-alert activity: end states, guardrail decisions, human confirm/reject actions and proposals, newest first.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | |
| events | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and closed-world, so safety is covered. The description adds real context beyond that: 'cross-alert' scope and 'newest first' ordering. It does not say how much history is retained or that the limit caps the window, which matters for a log-style read.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One tight fragment with zero filler, and the ordering constraint is placed at the end where it is easy to scan. The missing verb makes it read as a label rather than an instruction, costing a point.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return shape need not be explained, and annotations cover safety. For a single-optional-param read, listing the included record types plus ordering is close to sufficient; only the meaning of the limit window is left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must carry parameter meaning, and it only conveys ordering ('newest first'), not what limit does or its default of 20 / max of 100. The bounds live in the schema, so the agent can still call it, but the description adds little parameter help.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific resource and enumerates its contents (end states, guardrail decisions, confirm/reject actions, proposals) plus ordering, which is far more informative than 'get activity' alone. It lacks an explicit verb and never differentiates itself from siblings like get_trace or list_alerts, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No statement of when to call this versus get_trace, list_alerts, or get_usage — the agent must infer from the content list. There are no exclusions or prerequisites given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_alertARead-onlyIdempotent
One alert's current status and, once investigated, the proposed fix, the agent's confidence and its root-cause summary. For email- or detector-raised alerts, the inbound email or detection rule too.
| Name | Required | Description | Default |
|---|---|---|---|
| alert_id | Yes | FleetAlert alert id, e.g. ALERT-1001. |
Output Schema
| Name | Required | Description |
|---|---|---|
| source | No | |
| status | Yes | |
| alert_id | Yes | |
| detection | No | |
| confidence | No | |
| proposed_fix | No | |
| inbound_email | No | |
| root_cause_summary | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly and idempotent, so the bar is lower, and the description still adds real behavioral nuance: some fields exist only 'once investigated', and inbound email/detection-rule content appears only for email- or detector-raised alerts. That conditional-population detail is not derivable from the annotations or parameter schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short clauses, front-loaded with the core contents, and each clause contributes new information about what is returned. The line break mid-sentence is cosmetic noise but not wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be enumerated, and the description covers the conditional cases an agent would otherwise be surprised by. Nothing essential for correct invocation is missing, though a note on behavior for an unknown/expired alert_id would complete it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With a single parameter at 100% schema coverage including a format example ('ALERT-1001'), the schema does the work and the description adds nothing about alert_id. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('One alert's current status') plus the payload contents (proposed fix, confidence, root-cause summary), which clearly distinguishes it from list_alerts and get_usage. It stops short of naming a sibling, so it is clear but not maximally differentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the singular 'One alert's' framing — an agent can infer this is for a known alert_id rather than browsing. There is no explicit when-to-use, when-not-to-use, or pointer to list_alerts for discovery.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_raw_spansARead-onlyIdempotent
Raw trace spans for an alert, newest last, with full input and output. Large; prefer get_trace unless you need the detail.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Filter by span kind. | all |
| limit | No | Most recent spans to return. | |
| alert_id | Yes | FleetAlert alert id, e.g. ALERT-1001. |
Output Schema
| Name | Required | Description |
|---|---|---|
| spans | Yes | |
| total | Yes | |
| alert_id | Yes | |
| returned | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a safe, read-only, idempotent operation. The description adds useful behavioral context beyond those annotations: results are ordered newest last, include full input and output, and are large enough that the lighter sibling should usually be preferred.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the resource and immediately followed by the practical usage constraint. There is no wasted text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With rich annotations, full schema coverage, and an output schema present, the description supplies the remaining decision-relevant context: size, ordering, detail level, and when to prefer the sibling tool. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so alert_id, kind, and limit are already documented in the input schema. The description mentions the alert scope but does not add syntax or filtering semantics beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific resource and scope: raw trace spans for an alert, with full input and output. It also distinguishes this tool from the sibling get_trace by framing itself as the detailed option.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly names the preferred alternative, get_trace, and gives the condition for choosing this tool instead: only when you need the detail. This is direct routing guidance an agent can act on.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_traceARead-onlyIdempotent
The investigation history of an alert, one entry per round: entry point, outcome, proposed fix, model calls, tokens, cost, and the ordered steps (model calls, capability calls, guardrail decisions, human actions). Use get_raw_spans for full inputs and outputs.
| Name | Required | Description | Default |
|---|---|---|---|
| alert_id | Yes | FleetAlert alert id, e.g. ALERT-1001. |
Output Schema
| Name | Required | Description |
|---|---|---|
| rounds | Yes | |
| alert_id | Yes | |
| span_count | Yes | |
| total_cost_usd | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/closed-world, so the safety profile is covered. The description adds genuinely useful structure: one entry per round, the fields carried per round, and that steps are ordered — context the annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences; the core purpose and the per-round content are front-loaded, and the sibling pointer lands last as a natural follow-up. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and annotations covering the safety profile, the description supplies everything needed to call it correctly. A minor gap is that it doesn't say whether the trace is bounded/paginated for long-running alerts, but that is largely covered by the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter and schema coverage is 100%, with the schema itself showing the alert id format and example. The description adds nothing about alert_id, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('investigation history of an alert') and enumerates the exact contents per round (entry point, outcome, proposed fix, model calls, tokens, cost, ordered steps). This clearly delineates it from siblings like get_alert or get_raw_spans.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent to get_raw_spans for full inputs/outputs, which is the key decision point between the two. It doesn't cover the get_alert boundary, but the differentiator that matters (raw vs. summarized trace) is stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_usageARead-onlyIdempotent
Today's investigations and model spend against the demo's daily cost cap. When exhausted, action tools will be refused upstream.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| day | Yes | |
| cost_usd | Yes | |
| exhausted | Yes | |
| resets_at | Yes | |
| cost_cap_usd | Yes | |
| investigations | Yes | |
| investigation_cap | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint, idempotentHint, and openWorldHint=false, so the safety profile is covered. The description adds meaningful behavioral context: the usage is scoped to today and exhaustion causes upstream refusal of action tools.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences carry the full meaning: the first states what is returned, and the second states the operational consequence of exhaustion. There is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-parameter read tool with annotations covering safety and an output schema covering return structure, the description is complete enough. It explains the scope, the cap comparison, and the upstream refusal behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4. The description does not need to explain parameter semantics, and the empty schema is consistent with a no-argument read.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the resource: today's investigations and model spend measured against the demo's daily cost cap. It does not use an explicit retrieval verb, but the tool name and phrasing make the purpose unambiguous and distinct from the alert/trace/activity siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides implied usage context by explaining that action tools will be refused upstream when the cap is exhausted. However, it does not explicitly say to call get_usage before actions, nor does it name alternatives or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_alertsARead-onlyIdempotent
List every demo alert with its machine, severity and current status.
Statuses: open, queued, investigating, awaiting_confirmation,
resolved, rejected, routed_to_support, failed.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | |
| alerts | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true and openWorldHint=false, so the safety profile is covered. The description adds genuine domain context by enumerating the eight possible status values, but says nothing about result size, ordering, or whether the response is bounded — relevant given 'every' alert.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the action and the returned fields, followed by the status vocabulary. The status list spans multiple lines but each value earns its place as domain vocabulary the agent cannot get from the empty schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-shape details are not needed in prose, and a zero-parameter list tool is simple. The remaining gap is the absence of any statement about volume/ordering or routing to get_alert for single-record lookups.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline for a parameterless tool applies. The status enumeration it does provide is a bonus rather than a parameter explanation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('List every demo alert') and names the fields returned (machine, severity, status), so the agent knows exactly what it gets. It does not explicitly contrast with the singular sibling get_alert, so differentiation is inferred from the plural 'every' rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied: call this to enumerate all alerts, versus get_alert presumably for one. There is no explicit when/when-not guidance, no note that the list is unfiltered and unpaginated, and no pointer to the singular sibling as the alternative.
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.
6 tool updates
v0.1.0- First observed
get_activity - First observed
get_alert - First observed
get_raw_spans - First observed
get_trace - First observed
get_usage - First observed
list_alerts
TDQS
Scored across 6 tools
The tools mostly target distinct needs: usage, alert listing, single alert summary, trace history, raw spans, and cross-alert activity. The main potential overlap is between get_trace and get_raw_spans, but the descriptions explicitly distinguish them by detail level and recommend get_trace by default.
All tools follow a clear verb_noun convention using get_ or list_ prefixes. The naming is predictable and readable throughout.
Six tools is well-scoped for an alert inspection/observability server. Each tool covers a distinct layer of information without excessive surface area.
Read-only inspection is well covered: alerts, investigation traces, raw spans, activity, and usage. However, the alert lifecycle includes statuses and human actions such as confirm/reject/resolve, but there are no action tools to mutate or progress an alert, which is a notable gap for the stated domain.
Maintenance
Related MCP Connectors
Read-only MCP server for AIStatusDashboard status, incidents, metrics, and fallback recommendations.
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
MCP server for mandates, delegation, policy-gated execution, credential grants, and audit.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceMCP server for the Production Master incident-investigation service, enabling any MCP client to drive investigations via tool calls with pass-through authentication.MIT
- AlicenseNot gradedqualityCmaintenanceGoverned MCP server for bank-grade agent tool access with RBAC, PII redaction, rate limiting, and audit logging.MIT
- AlicenseNot gradedqualityAmaintenanceAn MCP server exposing scoped, read-only enterprise operations tools with fail-closed credential handling. It returns opaque approval IDs for mutations and requires a separate operator approval command to release one-time capabilities.MIT
- AlicenseNot gradedqualityBmaintenanceEnables production-hardened MCP tool serving with OAuth 2.1 audience-restricted tokens, purpose-bound tools, human-in-the-loop approvals, containment, and audit trails for AI agents.Apache 2.0