action1-mcp-server

action1-mcp-server

A production-grade MCP server that wraps the entire Action1 REST API, enabling Claude or any MCP host to manage endpoints, run scripts, deploy updates, and more via natural language with safety guards.

Category
Visit Server

README

action1-mcp-server

License: MIT Node Coverage Tools Tests

A production-grade Model Context Protocol (MCP) server for the Action1 RMM REST API. Wraps the entire Action1 API surface so that Claude (or any other MCP host) can run PowerShell on Windows, Bash on macOS, deploy updates, reboot endpoints, search audit trails, build CVE remediation plans, and more — all via natural language and with a three-layer destructive guard so the LLM cannot accidentally mutate production state.

Status: v0.5.0 — 100 % coverage of the pinned Action1 OpenAPI 3.1.0 spec, exposed as 166 tools (33 curated incl. 6 workflow wrappers + 133 auto-generated) with pinned SHA, hybrid architecture, three-layer destructive guard, stdio and Streamable HTTP transports, MCPB bundle, CI. Full conformance pass against the Anthropic mcp-builder skill best practices (server name, tool annotations, response_format, output schemas, Markdown rendering, character limits, evaluation suite).

Why this project

Action1 has a clean REST API but a thick layer of LLM-unfriendly quirks that, if unhandled, silently produce wrong results:

  • macOS Bash actions need a ten-field run_script payload the API returns not applicable to Mac platform for any field that is missing.
  • Windows PowerShell actions need a non-empty success_exit_codes.
  • last_seen is YYYY-MM-DD_HH-MM-SS (UTC), not ISO-8601 — Date.parse returns NaN (we render it human-readable in Markdown output).
  • The self URL of a list-endpoint includes a /general segment that is not a real REST resource.
  • The script-output stream is interleaved with Starting / Waiting / Completed lifecycle markers that need to be filtered.
  • OS is upper-case, platform is lower-case, both can carry the platform string; we normalise via a single detector.

This server encodes all of those. See docs/api-coverage-gaps.md §"Cross-repo comparison" for what other Action1 MCP projects miss.

Highlights

  • 100 % API coverage — every operation in the pinned Action1 OpenAPI 3.1.0 spec is reachable through exactly one MCP tool. Mapping in docs/api-coverage.md. The pin is enforced by a unit test (tests/unit/specSha.test.ts) so an upstream spec change fails the build instead of silently rotting the surface.
  • Hybrid architecture — hand-curated tools that encode the quirks above + auto-generated tools from the spec + high-level workflow wrappers (CVE remediation plan, audit log search, software inventory, recurring schedules, report export, group resolver).
  • MCP-protocol completeness — beyond tools, the server also ships:
    • 7 Resources (action1://me, ://orgs, ://templates, ://reports, ://endpoints/{orgId}, ://groups/{orgId}, ://vulnerabilities/{orgId}) for hosts that pre-fetch context. All list-shaped resources are capped to fit the 1 MB host limit and emit a truncation note when the cap fires.
    • 6 Slash-Prompts (/patch-windows-fleet, /audit-vulnerabilities, /triage-offline-endpoints, /run-script-fleetwide, /software-inventory-sweep, /check-my-permissions) for one-click workflows.
    • logging/setLevel — clients can dynamically bump or lower verbosity at runtime.
    • Cancellation propagation — long-running tools (auto_paginate, wait_for_automation, execute_and_wait) honour the host's AbortSignal.
    • outputSchema declared on every list-shaped read tool for client-side validation.
  • Skill-conformant tools — every tool emits response_format (markdown default, json opt-in), a structured description with Args / Returns / Examples / Error Handling sections, all four annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) explicitly set, and total / count / next_cursor / has_more on every paginated response.
  • Markdown rendering with humanised values — Action1 timestamps (YYYY-MM-DD_HH-MM-SS) render as YYYY-MM-DD HH:MM:SS UTC; ID columns lead the table; per-tool CHARACTER_LIMIT = 25_000 keeps agent context lean.
  • Three-layer destructive guardACTION1_ALLOW_DESTRUCTIVE env switch + per-call confirm: "YES" + dry_run: true (default). The LLM cannot accidentally mutate production state. Optional ACTION1_DESTRUCTIVE_AUTO_CONFIRM for isolated single-operator setups (still requires the env switch).
  • Sound auth — OAuth2 client-credentials with proactive 5-minute refresh, in-flight deduplication of concurrent token requests, and refresh_token-first fallback when re-acquiring.
  • Robust transport — retry with exponential backoff for DNS hiccups, HTTP 5xx, and 429 (honors Retry-After). Pagination walks limit/from transparently with caller-supplied caps.
  • Both transports — stdio (default; for local Claude Code / Cursor / Claude Desktop) + Streamable HTTP, stateless (for hosted Claude.ai custom connectors / team setups). HTTP transport supports bearer-token auth via MCP_HTTP_TOKEN (constant-time compare), a 1 MB body limit, and hard-fails on non-loopback bind without an Origin allowlist.
  • Distribution — MCPB bundle for Claude Desktop one-click install, npm publish-ready.
  • Observability — structured JSON-line logs to stderr with auto-redaction of Bearer …, api-key-…, and any property whose key looks sensitive (authorization, *_token, *_secret, password, …). Stdout reserved for MCP JSON-RPC.
  • Strict TypeScript with Zod input schemas on every tool. 527 tests across 4 categories (unit / integration / security / performance).

Quickstart

git clone https://github.com/mguttmann/action1-mcp.git
cd action1-mcp
npm install
cp .env.example .env             # edit with your Action1 credentials
npm run build
npm run inspector                # opens MCP Inspector against the built server

Or attach directly to Claude Code:

claude mcp add action1 -- node --env-file=$(pwd)/.env $(pwd)/dist/index.js

For the full installation walkthrough — including Claude Desktop, Claude.ai, Cursor, Continue.dev, and Cody — see docs/INSTALLATION.md.

Architecture

┌──────────────────────────────────────────────────────────────────────┐
│ Curated tools + Workflow wrappers                                     │
│ • script execution (Win + Mac + OS-aware)                             │
│ • execute_and_wait (POST + poll + filtered output)                    │
│ • get_endpoint with /general → canonical path + list-fallback         │
│ • CVE remediation plan, audit log search, software inventory, …      │
├──────────────────────────────────────────────────────────────────────┤
│ Auto-generated tools                                                  │
│ • one tool per remaining spec operation, verb-first snake_case names  │
│ • shared runtime: pagination, destructive guard, error mapping        │
│ • Action1 OpenAPI 3.1.0 pinned at SHA af75f1cc…                       │
├──────────────────────────────────────────────────────────────────────┤
│ Shared infrastructure                                                  │
│ • Action1Client (auth, retry, pagination, error mapping)               │
│ • TokenProvider (refresh_token fallback, 5-min proactive refresh)      │
│ • OrgResolver (fuzzy name match, session cache)                        │
│ • Three-layer destructive guard (env + confirm + dry_run)              │
│ • Structured stderr logger with auto-key redaction                     │
│ • Markdown auto-table renderer (humanises Action1 timestamps)          │
│ • Per-tool CHARACTER_LIMIT = 25_000 + WIRE_LIMIT_BYTES = 400_000       │
└──────────────────────────────────────────────────────────────────────┘

When a curated tool and an auto-generated tool address the same path, the curated one wins by name and the auto-generated one is suppressed via src/codegen/curated-overrides.ts. See docs/api-coverage.md for the full mapping.

Configuration

All configuration is via environment variables; copy .env.example to .env and fill in.

Variable Required Default Description
ACTION1_BASE_URL yes Region-specific instance, e.g. https://app.eu.action1.com/api/3.0.
ACTION1_CLIENT_ID yes OAuth2 client id from Action1 → Settings → API Credentials.
ACTION1_CLIENT_SECRET yes OAuth2 client secret. Shown once at credential creation.
ACTION1_ORG_ID recommended Default org UUID. Each tool can override via org_id.
ACTION1_DEFAULT_TIMEOUT_MINUTES no 10 Per-action timeout (PowerShell, etc.).
ACTION1_DEFAULT_RETRY_MINUTES no 1440 Window during which Action1 retries when an endpoint is offline.
ACTION1_LOG_LEVEL no info One of debug, info, notice, warn, warning, error, critical, alert, emergency.
ACTION1_LAST_SEEN_STALE_MINUTES no 10 Minutes since last_seen before an endpoint is treated as offline (range 1–1440). Tune up for fleets that check in infrequently.
ACTION1_ALLOW_DESTRUCTIVE no false Set to true / 1 / yes to allow tools with destructiveHint: true to mutate state.
ACTION1_DESTRUCTIVE_AUTO_CONFIRM no false Single-operator only: waives the per-call confirm: "YES" requirement. dry_run still defaults to true — pass dry_run: false to actually execute. Still requires ACTION1_ALLOW_DESTRUCTIVE=true.
PORT no 3000 HTTP transport port.
HOST no 127.0.0.1 HTTP transport host.
MCP_HTTP_TOKEN no unset Required Authorization: Bearer <token> on /mcp when set. Strongly recommended for any non-loopback bind.
MCP_HTTP_ALLOWED_ORIGINS no unset Comma-separated allowlist for browser Origin headers. Required when binding to a non-loopback host — the server hard-fails to start otherwise.
TRUST_PROXY no false Reverse-proxy hop trust for correct client IPs in rate-limiting. One of false / true / loopback / a CIDR. Enable only for trusted upstream proxies.

Connecting to MCP hosts

Host Transport Doc
Claude Code (CLI) stdio INSTALLATION § Claude Code
Claude Desktop (macOS / Windows) stdio INSTALLATION § Claude Desktop
Claude.ai (web) Streamable HTTP INSTALLATION § Claude.ai
Cursor stdio INSTALLATION § Cursor
Continue.dev / Cody stdio INSTALLATION § generic

Tools

See docs/USAGE.md for the full tool reference and docs/EXAMPLES.md for end-to-end recipes.

A summary of the curated layer (the auto-generated layer is the long tail and is documented operation-by-operation in docs/api-coverage.md):

Discovery (read-only)

action1_list_organizations, action1_list_endpoints, action1_endpoints_summary (server-side aggregation: ~1 KB regardless of fleet size), action1_get_endpoint (with /general → canonical path fallback, plus derived platform and connectivity.online), action1_search_endpoints (substring filter on hostname / user / OS / status), action1_list_action_templates, action1_get_action_template, action1_list_missing_updates, action1_list_vulnerabilities (graceful 403 if scope absent), action1_list_recent_automations, action1_automations_summary.

Execution (destructive — guard required)

action1_run_powershell (Windows; auto-fills success_exit_codes), action1_run_bash_macos (macOS; auto-fills the ten run_script fields), action1_run_script (auto-routes by OS), action1_reboot_endpoint, action1_deploy_update (spec-conformant {scope, packages, reboot_options}), action1_deploy_package, action1_uninstall_program, action1_run_data_collection. All accept target_type: "Endpoint" (default) or "EndpointGroup" for bulk fan-out.

Polling / results (read-only)

action1_get_automation_status, action1_get_automation_results, action1_get_automation_output (filters Starting/Waiting/Completed), action1_wait_for_automation.

Workflows (destructive)

action1_execute_and_wait — start an action, poll until it terminates, return the filtered output. Auto-routes by OS for mode: "script" or runs a named template for mode: "template".

High-level wrappers

action1_endpoint_groups_resolve (fuzzy name → UUID), action1_software_inventory_for_endpoint, action1_recurring_schedules, action1_audit_log_search, action1_report_export, action1_cve_remediation_plan.

Auto-generated

Every remaining Action1 API operation as a verb-first snake_case tool. See docs/api-coverage.md. All input parameter names are normalised to snake_case for consistency with the curated layer.

Resources

Seven MCP resources for hosts that pre-fetch context:

URI Purpose
action1://me The authenticated identity / role / permissions. Use this as a startup probe to know which tool families will 403.
action1://orgs All visible organizations.
action1://templates Action template catalog.
action1://reports Report catalog.
action1://endpoints/{orgId} Live endpoint snapshot per org. Pass default to use ACTION1_ORG_ID.
action1://groups/{orgId} Endpoint groups.
action1://vulnerabilities/{orgId} Org-wide CVE rollup. May 403 if the role lacks view_vulnerabilities.

All list-shaped resources are capped at ~400 KB and emit a truncation note when the cap fires; the equivalent paginated tool gives unbounded data via cursor chaining.

Slash-prompts

Six host-surfaced workflows for the most common day-to-day jobs:

Prompt Args What it does
/patch-windows-fleet group_query Resolves the group, lists missing updates, previews and (after confirmation) deploys.
/audit-vulnerabilities top_n? Surveys org-wide vulnerabilities, ranks the worst, presents a remediation plan.
/triage-offline-endpoints stale_minutes? Walks the inventory, surfaces endpoints whose status or last_seen are stale.
/run-script-fleetwide group_query, script_text Validates the script is read-only, dispatches via OS-aware routing, streams output.
/software-inventory-sweep software_name Searches every endpoint's installed software for a substring match.
/check-my-permissions Reads action1://me and reports which tool families will 403 with the current role.

Destructive guard

Every tool flagged destructiveHint: true enforces three independent gates:

ACTION1_ALLOW_DESTRUCTIVE=true   ← server env, restart-required
        AND
confirm: "YES"                    ← exact, case-sensitive
        AND
dry_run: false                    ← default is true → preview-only
// Preview only (default)
{ "tool": "action1_run_powershell",
  "arguments": { "endpoint_id": "<uuid>", "script_text": "Get-Date" } }
// → returns { "dry_run": true, "would_send": { method, path, body } }

// Actually execute (server env: ACTION1_ALLOW_DESTRUCTIVE=true)
{ "tool": "action1_run_powershell",
  "arguments": { "endpoint_id": "<uuid>", "script_text": "Get-Date",
                 "dry_run": false, "confirm": "YES" } }

Single-operator setups can opt into ACTION1_DESTRUCTIVE_AUTO_CONFIRM=true, which waives only the per-call confirm: "YES" requirement — dry_run still defaults to true, so a bare call is still a preview; pass dry_run: false to execute. The env switch is still required, and the server logs a loud warning at start-up when this mode is on.

See docs/SECURITY.md for the full threat model.

Examples

Three quick workflows; many more in docs/EXAMPLES.md:

# 1. Fleet health check
> "How many endpoints are online and how many need a reboot?"

  agent → action1_endpoints_summary
  result → { total: 1247, fresh_last_seen: 1130, reboot_required: 38, ... }

# 2. Run a read-only PowerShell on a specific Win11 host
> "What's the OS build of <hostname>? Run `Get-ComputerInfo OsBuildNumber`."

  agent → action1_search_endpoints { query: "<hostname>", fields: ["hostname"] }
  agent → action1_run_powershell {
            endpoint_id: <uuid>,
            script_text: "Get-ComputerInfo OsBuildNumber",
            dry_run: false, confirm: "YES" }
  agent → action1_wait_for_automation { instance_id: <id>, endpoint_id: <uuid> }

# 3. Build a CVE remediation plan
> "What's needed to remediate CVE-2024-XXXX?"

  agent → action1_cve_remediation_plan { cve_id: "CVE-2024-XXXX" }
  result → { plan: [{ cve, affected_endpoints, candidate_packages }], ... }
  agent → action1_deploy_update { ... } (after operator confirmation)

Rate limits

Action1's REST API does not publish a hard rate-limit ceiling. In practice we observe ~10 requests per second sustained without 429s on the EU instance. If you do hit 429:

  • The retry wrapper honours Retry-After automatically.
  • Token-bucket-style throttling on auto_paginate calls keeps a multi-page list walk under ~5 RPS.
  • For mass-fan-out actions, prefer target_type: "EndpointGroup" over individual per-endpoint POSTs — Action1 fans out server-side.

The server does NOT pre-emptively cache list responses; consecutive calls always hit the API. See src/client/retry.ts for the retry policy.

Required Action1 permissions

The MCP server's tool surface respects whatever role the API key carries. Common scopes:

Tool family Required permission
Discovery (orgs, endpoints, templates, automations) view_endpoints, view_organizations, view_action_templates
Software inventory view_installed_software
Missing updates view_endpoints (often suffices)
Vulnerabilities view_vulnerabilities (commonly missing on automation-only keys)
Audit log view_audit
Reports view_reports
Execute scripts / deploy / reboot manage_actions, manage_endpoints
Manage schedules manage_schedules

Use action1://me or the /check-my-permissions slash prompt to confirm what the configured key can do before the agent starts attempting destructive operations.

Documentation

File What it covers
docs/INSTALLATION.md Step-by-step for every supported MCP host, plus install FAQ.
docs/FAQ.md Cross-topic FAQ + how-to recipes.
docs/USAGE.md Tool reference for curated + wrapper layers, plus Resources, Prompts, output-format, cancellation, logging.
docs/EXAMPLES.md End-to-end recipes (patching, triage, CVE remediation, etc.).
docs/DEPLOYMENT.md stdio / HTTP / systemd / MCPB / Cloudflare Workers, plus the production checklist.
docs/SECURITY.md Threat model, destructive guard, credential rotation, redaction, rate limits.
docs/TROUBLESHOOTING.md Common failure modes and fixes.
docs/CONTRIBUTING.md Codegen workflow, test layout, commit conventions.
docs/api-coverage.md The full operation-to-tool mapping (166 tools over the pinned spec).
docs/api-coverage-gaps.md Cross-repo comparison and capability gaps.
docs/403-investigation.md Why /general is not a real path.
evals/ Skill-format evaluation suite (12 multi-hop questions, harness-runnable).
TESTING.md Unit / integration / security / performance tests, smoke tests, live-run results (anonymised).

Development

npm run dev               # tsx watch (stdio)
npm run typecheck
npm run lint
npm test                  # 527 tests across all categories
npm run test:unit         # 37 files
npm run test:integration  # MCP-protocol round-trip tests
npm run test:security     # destructive-guard truth table, redaction matrix
npm run test:performance  # capItemList / markdownTable scaling
npm run codegen           # regenerate src/tools/generated/index.ts from the spec
npm run inspector         # MCP Inspector against the built stdio server

The macOS payload-builder unit tests are intentionally strict — they protect against silent regressions of the reverse-engineered field set. If you change the payload, update the snapshot.

Roadmap

Tracked in docs/api-coverage-gaps.md § "Recommended second-wave roadmap":

  • Endpoint groups CRUD + targeting (mostly delivered via auto-gen + the target_type parameter on curated tools).
  • Reports surface (delivered via the auto-gen + action1_report_export wrapper).
  • Software inventory per endpoint (delivered via action1_software_inventory_for_endpoint).
  • CVE-based remediation builder (delivered via action1_cve_remediation_plan).
  • Recurring automations CRUD (delivered via auto-gen).

Open candidates:

  • Streamable HTTP "Sampling" / "Elicitation" support if user demand appears.
  • Cloudflare Workers reference deployment.
  • Bundle the generated _coverage_table.md into the npm package.

Security

See docs/SECURITY.md. Report vulnerabilities via the private security advisory at https://github.com/mguttmann/action1-mcp/security/advisories/new.

License

MIT © 2026 mguttmann

Acknowledgements

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured