Skip to main content
Glama

fleetcheck-mcp

CI License: MIT Python 3.10+

An MCP server that gives Claude safe, read-only network & service diagnostics — ping, DNS, HTTP health, TLS expiry, single-port checks, traceroute, and whole-fleet sweeps.

Why this exists

My day job is keeping 890 retail stores' registers and networks online. When a store calls saying "the internet is down", there's a first-call ritual every ops person knows: ping the gateway, check DNS, hit the health endpoint, see if the VPN port answers, glance at the cert that's been quietly counting down to expiry. fleetcheck packages exactly those checks as MCP tools, so Claude can run the ritual for you — across one host or fifty — and tell you what's actually broken.

Related MCP server: netdiag-mcp

Tools

Tool

What it answers

Example question to ask Claude

ping_host

Is this machine reachable, and how lossy/slow is the path?

"Ping 10.1.42.1 and tell me the packet loss."

dns_lookup

Does this name resolve, to what, and how fast? (A/AAAA/CNAME/MX/TXT/NS)

"What do the MX records for example.com look like?"

http_health

Is this web endpoint up, how fast, and where do redirects land?

"Check https://portal.example.com/health and show the redirect chain."

tcp_port_check

Is the service listening on this one port?

"Is port 443 open on the store-042 gateway?"

tls_cert_check

Who issued this cert, which names does it cover, and when does it expire?

"Is the cert on vpn.example.com expiring soon?"

traceroute_host

Where along the path does traffic slow down or die?

"Traceroute to 8.8.8.8 and find the slow hop."

fleet_sweep

Which of my hosts are down right now, and which is slowest?

"Sweep these 5 store gateways and tell me which are down."

Every tool returns a structured dict. Failures — host down, DNS miss, timeout, bad input — come back as data ({"ok": false, "error": "..."}), never as a crashed tool call, so Claude can reason about why something failed.

Install

Requires Python 3.10+ and uv (for uvx), or plain pip.

Installs from this repo for now. A PyPI release is set up (trusted publishing, see .github/workflows/publish.yml) but hasn't been cut yet, so uvx fleetcheck-mcp and pip install fleetcheck-mcp won't resolve. Use the Git commands below — they install the same package.

Claude Code

claude mcp add fleetcheck -- uvx --from git+https://github.com/seifosmaan53/fleetcheck-mcp fleetcheck-mcp

Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "fleetcheck": {
      "command": "uvx",
      "args": [
        "--from",
        "git+https://github.com/seifosmaan53/fleetcheck-mcp",
        "fleetcheck-mcp"
      ]
    }
  }
}

With pip

pip install git+https://github.com/seifosmaan53/fleetcheck-mcp
fleetcheck-mcp   # runs the server over stdio

Example conversation

You: Claude, sweep these 5 store gateways and tell me which are down: 10.1.1.1, 10.1.2.1, 10.1.3.1, 10.1.4.1, 10.1.5.1

Claude: (calls fleet_sweep with check="ping") 4 of 5 gateways are up. 10.1.3.1 is down — 100% packet loss. Of the reachable ones, 10.1.5.1 is the slowest at 240 ms average RTT; the rest answer in under 20 ms. Want me to traceroute 10.1.3.1 to see where the path dies?

Other things that work well:

  • "Ping the store-042 gateway, and if it's up, check whether port 443 answers."

  • "Check every cert on this list and flag anything expiring inside 30 days."

  • "portal.example.com feels slow — check DNS resolution time, then HTTP latency, and tell me which one is the problem."

Safety

fleetcheck is a diagnostics tool, not a scanner, and it's built to stay that way:

  • Read-only. Every tool observes (ICMP echo, DNS query, HTTP GET, TCP connect, TLS handshake, traceroute). Nothing configures, writes to, or restarts anything.

  • Single-port checks only. tcp_port_check (and fleet_sweep with check="port") accepts exactly one integer port per call. Port ranges and lists are rejected by validation.

  • 50-host cap. fleet_sweep refuses lists longer than 50 hosts, and runs at most 10 checks concurrently.

  • Strict input validation. Hosts are whitelist-validated (hostname characters or parseable IPs); shell metacharacters and flag-like leading dashes are rejected. Subprocess arguments are always passed as lists — never through a shell. Every numeric input is clamped and every call has a timeout.

  • Use it on your own infrastructure. These checks are harmless individually, but you should only point them at systems you operate or have explicit permission to test.

Development

git clone https://github.com/seifosmaan53/fleetcheck-mcp
cd fleetcheck-mcp
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest

Tests run entirely against localhost and canned command output (macOS and Linux ping formats) — no external network required. CI runs the suite on Python 3.10–3.12; releases publish to PyPI via trusted publishing.

License

MIT — © 2026 Seif Osman

Available Tools

7 tools
dns_lookupA

Resolve DNS records for a name and report how long resolution took.

Answers: "Does this name resolve, to what, and is DNS itself slow or broken?" A/AAAA lookups go through the system resolver (socket.getaddrinfo) so they reflect what applications on this machine actually see; CNAME/MX/TXT/NS use dnspython.

Args: name: The DNS name to resolve (e.g. "vpn.example.com"). record_type: One of A, AAAA, CNAME, MX, TXT, NS (default "A").

Returns: On success: {"ok": true, "name", "record_type", "records": [...], "record_count", "resolution_time_ms"}. MX records are {"priority", "exchange"} dicts; other types are strings. On failure (NXDOMAIN, no answer, timeout): {"ok": false, "error": "..."}.

Inputs: name (required), record_type. Returns: object

fleet_sweepA

Run one diagnostic check across a whole fleet of hosts, concurrently.

The signature tool. Answers: "Which of my stores/gateways/servers are down right now, and which is the slowest?" Runs the chosen check on every host (up to 10 at a time) and returns a per-host results table plus an up/down summary.

Args: hosts: List of hostnames/IPs — capped at 50 per call; longer lists are rejected. For check="http", entries may be full URLs or bare hostnames (bare names are checked as https://). check: One of "ping" (2 ICMP probes per host), "port" (single TCP connect), or "http" (GET following redirects). Default "ping". port: Required when check="port": a single TCP port, integer 1..65535, used for every host. Ignored otherwise.

Returns: On success: {"ok": true, "check", "results": [{"host", "up", "latency_ms", "detail": }], "summary": {"up", "down", "total", "worst_latency_host"}}. A host that fails validation or its check counts as down, with the reason in its "detail". On bad input (too many hosts, missing port, unknown check): {"ok": false, "error": "..."}.

Inputs: hosts (required), port, check. Returns: object

http_healthA

GET an http(s) URL, following redirects, and report response health.

Answers: "Is this web endpoint up, how fast does it answer, and where do its redirects land?" Only http:// and https:// URLs are accepted.

Args: url: Full URL to check (e.g. "https://portal.example.com/health"). timeout: Total request timeout in seconds, clamped to 1..30 (default 10).

Returns: On success: {"ok": true, "url", "status_code", "healthy" (true when status is 2xx/3xx), "latency_ms", "final_url", "redirect_count", "redirect_chain": [{"status_code", "url", "location"}], "server", "content_type", "response_bytes"}. On failure (timeout, connection error, bad scheme): {"ok": false, "error": "..."}.

Inputs: url (required), timeout. Returns: object

ping_hostA

Ping a host with ICMP echo requests and report packet loss and latency.

Answers: "Is this machine reachable at the network level, and how lossy or slow is the path?" Uses the system ping binary (unprivileged), so it works out of the box on macOS and Linux.

Args: host: Hostname, IPv4, or IPv6 address (e.g. "store-042.example.com", "10.1.42.1"). Validated strictly; shell metacharacters rejected. count: Number of echo requests to send, clamped to 1..10 (default 4).

Returns: On success: {"ok": true, "host", "count", "reachable", "packets_sent", "packets_received", "packet_loss_percent", "rtt_ms": {"min", "avg", "max"} | null}. On failure (unknown host, timeout, ping missing): {"ok": false, "error": "..."}.

Inputs: host (required), count. Returns: object

tcp_port_checkA

Check whether ONE TCP port on a host accepts connections.

Answers: "Is the service listening?" — e.g. 443 on a payment gateway, 22 on a store server, 5432 on a database. This is deliberately a single-port diagnostic, not a scanner: exactly one integer port per call; ranges and lists are rejected.

Args: host: Hostname, IPv4, or IPv6 address. port: A single TCP port, integer 1..65535. timeout: Connect timeout in seconds, clamped to 1..30 (default 5).

Returns: On success: {"ok": true, "host", "port", "state": "open" | "closed" | "timeout", "latency_ms" (connect time for open/closed, null on timeout)}. On failure (unresolvable host, invalid port): {"ok": false, "error": "..."}.

Inputs: host (required), port (required), timeout. Returns: object

tls_cert_checkA

Inspect the TLS certificate a host serves and flag looming expiry.

Answers: "Is this cert about to expire, who issued it, and which names does it cover?" Performs a verified TLS handshake using the system trust store; a cert that fails verification (expired, self-signed, wrong chain) is reported as an error with the verification reason.

Args: host: Hostname or IP to connect to (SNI uses this hostname). port: TCP port, integer 1..65535 (default 443).

Returns: On success: {"ok": true, "host", "port", "subject" (CN), "issuer_org", "issuer_cn", "not_before", "not_after", "days_until_expiry", "expiring_soon" (true when fewer than 30 days remain), "sans": [...], "tls_version"}. On failure: {"ok": false, "error": "..."}.

Inputs: host (required), port. Returns: object

traceroute_hostA

Trace the network path to a host, hop by hop, with per-hop latency.

Answers: "Where along the path does traffic slow down or die?" Uses the system traceroute binary (one probe per hop, 2s wait). If neither traceroute nor tracert exists on this system, that is returned as an error in the result, not raised.

Args: host: Hostname, IPv4, or IPv6 address. max_hops: Maximum hops to probe, clamped to 1..30 (default 15).

Returns: On success: {"ok": true, "host", "max_hops", "hop_count", "hops": [{"hop", "host" (name/IP or null when the hop timed out), "address", "rtt_ms"}]}. On failure: {"ok": false, "error": "..."}.

Inputs: host (required), max_hops. Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.4/5.0

    Scored across 7 tools

    Disambiguation5/5

    Each tool targets a distinct diagnostic domain: ping for network reachability, DNS lookup, HTTP health, TCP port check, TLS certificate, traceroute, and a fleet sweep aggregator. There is no overlap or ambiguity, and descriptions are clear.

    Naming Consistency4/5

    Tool names are all lowercase with underscores, but the order varies: some are verb_noun (ping_host, traceroute_host), others noun_verb (dns_lookup, fleet_sweep), and some are noun_noun (http_health, tcp_port_check, tls_cert_check). While not perfectly consistent, the pattern is predictable and each name clearly conveys the tool's purpose.

    Tool Count5/5

    Seven tools is well-scoped for a network diagnostic server. Each tool serves a distinct need without redundancy, and the fleet_sweep tool adds value by aggregating checks. The count is neither too few nor too many for the stated purpose.

    Completeness4/5

    The tool set covers core network diagnostics: ping, DNS, HTTP, TCP port, TLS, traceroute, and an aggregator. Minor gaps exist, such as the lack of a multi-port check or support for UDP traceroute, but the set is sufficient for most fleet health checks.

    Related MCP Connectors

    Related MCP Servers