MCP server for Fleet device management and osquery live querying on managed endpoints. Enables host inventory lookups, compliance policies, vulnerability assessment, software inventory, and live SQL queries against enrolled macOS, Windows, and Linux devices.
Fleet MCP demonstrates strong definition quality with comprehensive descriptions, good naming conventions following verb_noun patterns, and well-structured schemas. All 19 tools are explicitly registered with mcp.NewTool() in mcp_tools_*.go files. Descriptions are detailed and contextual (averaging 250-400 chars, well above the 194 baseline), with explicit guidance on when to use each tool and how to combine them. Parameter schemas are fully typed with JSON Schema (strings, enums where appropriate). However, some parameters lack explicit enum constraints where values are bounded (e.g., 'platform' accepts 'macos'|'windows'|'linux' but is defined as generic string), and output schemas are not formally documented. Error handling is present but inconsistent, some tools validate inputs (e.g., policy_response constraint check in get_endpoints), while others rely on Fleet API responses. Tool composition is excellent: tools chain naturally (e.g., get_labels → get_endpoints, get_policies → get_policy_hosts), and most tools accept both human-readable identifiers and IDs.
Get the count of systems aggregated by platform (macOS, Windows, Linux)
Get a list of hosts/endpoints enrolled in Fleet with full server-side filtering. All filters compose: combine fleet+platform+label+policy_id+policy_response+status+query in one call to narrow precisely instead of paginating client-side. The `query` parameter alone covers user / IP / hostname / serial / hardware model / IdP group as a case-insensitive substring — reach for it before paginating. Use get_host for full details on one host, get_host_policies for one host's compliance, get_policy_hosts for hosts grouped by policy result. Do NOT call this tool repeatedly with per_page=1 just to count — use get_total_system_count instead.
Get all Fleet teams/fleets. Use to discover team names for filtering in other tools.
Get full details for a single host including its labels, fleet, and platform info. Accepts a numeric `host_id` (most precise), or an `identifier` (exact hostname / UUID / hardware serial, OR a substring to fuzzy-match). If the substring matches exactly one host, full details are returned. If multiple match — for example two hosts share a hostname — a candidate list is returned with each host's id, hostname, display_name, hardware_serial, primary_ip, and team so you can pick the right one and re-call with `host_id`. IMPORTANT: substring matching covers hostname / serial / IP / model / user inventory but NOT display_name. If the host you want has only a custom display_name (a user-set computer name that does not appear in any indexed string field), use `host_id` from a candidate list. Use get_endpoints when you need many hosts; use get_host_policies when you need a host's policy compliance.
Parameter value enums not formally constrained, 'platform' accepts 'macos'/'windows'/'linux' but is defined as generic string type, requiring LLMs to guess valid values or hallucinate. Similarly 'status' accepts only 'online'/'offline'/'new'/'mia', 'policy_response' only 'passing'/'failing', but lack enum schema constraints.
Output schemas not formally documented. While tool descriptions explain what fields are returned (e.g., 'id, hostname, display_name, hardware_serial, primary_ip, team' for get_host candidate lists), no explicit JSON Schema document is provided. This forces LLMs to parse description text rather than following a structured contract.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | B | 75 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 0 | - | v1 |
List OS-local user accounts on a single host as inventoried by osquery (uid, username, type, groupname, shell). Returned from Fleet's stored host detail — works even when the host is currently offline. Use this for 'which accounts exist on host X?', 'is there a user named X on this host?', or to enumerate service accounts. IDENTIFIER GUIDANCE: pass `host_id` (numeric) when known — unambiguous. `host_identifier` accepts an exact hostname / UUID / serial OR a substring (same disambiguation as get_host). On collision returns a candidate list — re-call with `host_id` from the candidate you want. Optional `query` substring filters the returned users array client-side against username / uid / groupname / shell.
Get all available Fleet labels. Use to discover label names for filtering in get_endpoints and other host-filtering tools.
Get the osquery table schema for a given platform (macos / windows / linux / chromeos / all). The schema is a JSON structure mapping table names to their columns and types. Use this BEFORE writing run_live_query SQL to verify column NAMES and TYPES — many osquery columns are TEXT despite numeric-looking values.
Get all Fleet policies with their pass/fail host counts. Focus on passing_host_count and failing_host_count to assess compliance — that is what matters. Do not comment on enforcement status.
Get pass/fail counts for a specific policy. By default returns global counts. Pass `fleet` to scope counts to a single fleet (e.g. compliance numbers shown on the fleet's Policies tab in the Fleet UI). For host-level breakdowns, use get_policy_hosts.
List the hosts that pass or fail a given policy, optionally narrowed by fleet / platform / label / status / substring. Use this to answer 'which Linux hosts are failing policy 42' or 'which hosts in the engineering fleet are non-compliant with policy 17'. Use get_policies first to discover the numeric policy_id. All filter dimensions compose server-side.
Get a list of all saved queries in Fleet
List software/packages from Fleet's stored host inventory (refreshed on each host check-in — works even when hosts are offline). Two modes, picked automatically: - PER-HOST mode (when host_id OR host_identifier is set): every package installed on that host, including version, source, install paths, and any matching CVEs. Use this for 'what's on host X?' questions. - CROSS-HOST mode (no host arg): software TITLES seen across hosts, optionally scoped by fleet/platform/vulnerability. Use this for 'do we have python on any Workstation?' or 'every npm package across the fleet'. The `source` arg is the osquery source-table name (e.g. 'npm_packages', 'python_packages', 'apps', 'deb_packages', 'rpm_packages', 'chrome_extensions', 'vscode_extensions', 'homebrew_packages') and is matched client-side case-insensitively. Use `query` for a substring match on software name OR a CVE id ('CVE-2026-12345') — server-side, fast. Prefer this tool over run_live_query for inventory lookups: the cached data is always-available and doesn't burn host CPU.
Get the total count of active systems enrolled in Fleet
Get the library of 100% vetted, production-safe CIS-8.1 policy queries for macOS, Windows, and Linux. Always use these as a reference or starting point for creating new policies — they have been tested and use the correct table schemas for each platform.
List the specific hosts impacted by a CVE, optionally narrowed by fleet / platform / label / status / substring. Use this — NOT get_vulnerability_impact — when the question is 'which of my hosts are affected by CVE-X' or 'are any prod servers vulnerable to CVE-Y'. get_vulnerability_impact returns only an aggregate count; this tool returns the actual host list. Composes server-side via Fleet's affected-software lookup.
Check the amount of systems impacted by a specific vulnerability (CVE). Returns an aggregate count only — for the actual list of affected hosts (with optional filtering), use get_vulnerability_hosts.
Step 1 of 2 for running a live query. RESOLVES THE EXACT TARGET HOST SET using the same intersection semantics as get_endpoints — every dimension you set is AND-ed: fleet AND platform/label AND status AND query AND policy AND cve. Returns (a) the resolved target list (id, hostname, display_name, platform, team) so you can verify scope before firing, and (b) the osquery schema for the targeted platform. Explicit hostnames / host_ids combine with filter dimensions as an intersection — 'these named hosts that ALSO match the filters'. Use this — NOT a wide live-query — to pinpoint exactly what's in scope. Example: fleet='Workstations' + platform='linux' resolves to ONLY the Linux Workstations hosts (e.g. 2 hosts), not all 100 Workstations hosts. Example: cve_id='CVE-2025-12345' + fleet='Workstations' resolves to the host(s) actually impacted by that CVE in the team.
Force a refresh of the osquery schema from the canonical upstream source (https://raw.githubusercontent.com/fleetdm/fleet/main/schema/osquery_fleet_schema.json). By default the schema is refreshed periodically in the background, but use this if you suspect a schema mismatch or if Fleet's tables have recently changed.
Step 2 of 2. MUST call get_osquery_schema(platform=<target>) (or prepare_live_query, which embeds the schema response) BEFORE writing the sql argument. This verifies column NAMES and TYPES against the canonical schema — many osquery columns are TEXT despite numeric-looking values (e.g. windows_update_history.result_code is TEXT 'Succeeded'/'Failed', not an integer). Skipping the schema check produces queries that run but silently return zero rows. Resolve targets and run an osquery SQL statement against Fleet devices. Accepts the SAME filter dimensions as prepare_live_query (intersection across fleet, platform, label, status, query, policy, CVE, hostnames, host_ids). Resolved target set is included in the response so the caller sees exactly which hosts were queried. Team scoping: when `fleet` is set, only hosts in that team are targeted. When the user mentions a team (e.g. 'Workstations'), pass it as `fleet`; do not run queries Globally and rely on host filters alone. Use the smallest target set that answers the question. Example: a CVE remediation check should target only hosts impacted by that CVE — pass cve_id + fleet, not platform=all.
Incomplete parameter descriptions for filter boundaries. 'per_page' states 'default 50, max 200' inline, but this is not enforced at the schema level. No minimum specified, and no clear guidance on what happens if per_page exceeds max or is 0. (Minor: this is validated server-side per code, but LLMs benefit from explicit schema constraints.)
Error handling guidance inconsistent across tools. Some tools (e.g., get_endpoints) validate inputs and return clear error messages ('policy_response must be passing or failing'). Others rely on Fleet API error responses, which may be cryptic or unactionable for LLMs (e.g., 'Invalid CVE format' without suggesting valid format).
Parameter naming for identifiers could be more precise. 'host_identifier' and 'identifier' are used generically to mean 'hostname OR UUID OR serial OR substring', but the code comments clarify this better than the schema. Parameter descriptions could split into separate fields (e.g., 'host_id' for numeric ID, 'host_name' for hostname, 'host_serial' for serial) to match the type suffixing pattern (user_id, user_name, user_email).