Skip to main content
Glama
jshsakura

a360-mcp

by jshsakura

a360-mcp

PyPI version Python Version License: Apache 2.0

MCP server for Automation Anywhere Automation 360 (A360) Control Room — bot logic analysis and execution failure diagnostics.

Community project. Not affiliated with or endorsed by Automation Anywhere, Inc. "Automation Anywhere" and "Automation 360" are trademarks of their respective owner.


What it is for

A bot ran. It died. Which action, why, and what was missing upstream?

This server pulls the failed execution from the Control Room, pulls the bot's logic, and maps one onto the other — so the answer is "action 37, Open Excel, file not found; there is no existence check before it and no error handler around it" rather than a status code.

Related MCP server: OEE Enterprise Agent

What it is not

Automation Anywhere ships MCP Inbound (https://<control-room>/mcp) from v.38, which exposes bots as tools so an assistant can run them. If running bots is what you need, use the vendor feature — it has RBAC, governance logging, and per-automation registration.

It does not read execution history, bot logic, WLM queues, or audit logs. That is this project's scope. The two are complementary.

Status

Beta. Diagnostic pipeline (diagnose_execution), audit correlation (correlate_failure), bot logic walker, and snapshot store are implemented and unit-tested (819 tests, 93% coverage). Writes are opt-in and gated. Not yet validated against a live Control Room instance — the A360 filter operator set, the audit field names, and the bot JSON node schema are permissive parsers, awaiting field verification. Everything unconfirmed is marked [UNVERIFIED] at its definition.


Requirements

  • Python 3.11+

  • An Automation 360 Control Room account with an API key (needs a custom role carrying Generate API-Key — no system role has it by default)

  • Read privileges on the bots you want to diagnose (View my bots)

Setup

The default is uvx — no separate install step, it just runs.

# Install uv (one-time)
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows PowerShell
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

# Verify the server runs
uvx --from a360-mcp a360-mcp --version

To update — uvx caches the last version; pull new releases with --refresh:

uvx --refresh --from a360-mcp a360-mcp --version

If uvx is blocked — pip

Windows Smart App Control blocks uvx (it unpacks an unsigned temporary executable on every run). Use pip instead:

pip install a360-mcp
python -m a360_mcp --version

Launch with python -m a360_mcp rather than the a360-mcp console script — that script is an unsigned .exe shim pip generates, and SAC blocks it too.


MCP client configuration

Add the server to your client's config file. The env block is identical no matter how you installed — only command / args differ.

Install

command

args

uvx (default)

uvx

["--from","a360-mcp","a360-mcp"]

pip

python

["-m","a360_mcp"]

Required env vars:

Variable

Meaning

A360_CONTROL_ROOM_URL

Control Room base URL (e.g. https://cr.example.com)

A360_USERNAME

Service account username

A360_API_KEY or A360_PASSWORD

One of the two — mutually exclusive

Optional env vars (all default to the safe value — set them only to change it):

Variable

Default

Meaning

A360_ALLOW_WRITES

0

Opt in to mutating tools. See Safety before setting it.

A360_WRITE_GUARDS_FAIL

open

Set to closed so a guard that cannot decide blocks instead of allowing.

A360_TOOL_PACKAGE

core

Which tool layer to expose: core, bot_read, log_read, diagnose, full.

A360_REQUEST_TIMEOUT

60

Per-request timeout, seconds.

Accepted truthy values are 1, true, yes, on (case-insensitive); anything else — including an unset or empty variable — reads as off. Every one of these also has a CLI flag (--allow-writes, --tool-package, …), and the flag wins over the environment.

Antigravity

.agents/mcp_config.json (project root) or ~/.gemini/config/mcp_config.json (global):

{
  "mcpServers": {
    "a360": {
      "command": "uvx",
      "args": ["--from", "a360-mcp", "a360-mcp"],
      "env": {
        "A360_CONTROL_ROOM_URL": "https://cr.example.com",
        "A360_USERNAME": "svc_mcp",
        "A360_API_KEY": "${A360_API_KEY}"
      }
    }
  }
}

Claude Code

.mcp.json (project root) or ~/.claude.json (global):

{
  "mcpServers": {
    "a360": {
      "command": "uvx",
      "args": ["--from", "a360-mcp", "a360-mcp"],
      "env": {
        "A360_CONTROL_ROOM_URL": "https://cr.example.com",
        "A360_USERNAME": "svc_mcp",
        "A360_API_KEY": "${A360_API_KEY}"
      }
    }
  }
}

Codex

.codex/config.toml (project) or ~/.codex/config.toml (global):

[mcp_servers.a360]
command = "uvx"
args = ["--from", "a360-mcp", "a360-mcp"]
# pip: command = "python"  /  args = ["-m", "a360_mcp"]

[mcp_servers.a360.env]
A360_CONTROL_ROOM_URL = "https://cr.example.com"
A360_USERNAME = "svc_mcp"
A360_API_KEY = "${A360_API_KEY}"

OpenCode

opencode.json (project root):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "a360": {
      "type": "local",
      "command": ["uvx", "--from", "a360-mcp", "a360-mcp"],
      "enabled": true,
      "environment": {
        "A360_CONTROL_ROOM_URL": "https://cr.example.com",
        "A360_USERNAME": "svc_mcp",
        "A360_API_KEY": "${A360_API_KEY}"
      }
    }
  }
}

${ENV} reference

The CLI expands ${VAR} as a full value onlyA360_API_KEY=${A360_API_KEY} resolves to the value of the A360_API_KEY env var at startup. Partial references like ${ENV}_suffix are rejected to prevent silent misconfiguration.


Tools

The server exposes a layered tool set, gated by A360_TOOL_PACKAGE (default core):

Package

Includes

Use case

core

get_execution, list_executions, get_bot_actions

Read-only triage

bot_read

same as core

Bot content reads (deeper reads land later)

log_read

core + list_audit_events, correlate_failure

"What changed?" investigations

diagnose

log_read + diagnose_execution

Default for most workflows

browser_read

diagnose + inspect_console / inspect_network / screenshot_debug / get_computed_style

Read-only browser diagnostics (Playwright optional)

browser

browser_read + open_debug_window / close_debug_window

Full browser layer (consumes a session slot)

full

everything

No gating

Set with A360_TOOL_PACKAGE=diagnose (env) or --tool-package diagnose (CLI).

Tool schemas are re-sent on every request, so each tier's cost is a standing tax. Measure it with python scripts/measure_tool_tokens.py (add --per-tool for the breakdown):

Package

Tools

Tokens/request

core

3

250

log_read

5

518

diagnose

6

609

full

12

1,013

Headline tool: diagnose_execution

Given an execution ID, returns a verdict-first diagnosis:

  1. Fetch the execution (GET /v3/activity/execution/{id}).

  2. If the status is not failure-family, return a one-line verdict immediately.

  3. Feature-detect the error key, fall back to parsing message.

  4. Fetch the bot logic (GET /v2/repository/files/{fileId}/content).

  5. Walk action nodes (iterative DFS, no recursion).

  6. Map the failure onto a node by line number.

  7. Pull upstream / downstream context and Try/Catch presence.

  8. If no Try/Catch, emit an instrumentation prescription ("place Catch with line number + exception message assignments, log to server, screen capture inside").

  9. Snapshot the diagnosis locally (90-day CR retention fallback).

Bot JSON never enters the model context — only the parsed action surface and a disk path.

The other half: correlate_failure

diagnose_execution says which action died. It cannot say why now — a bot that ran green for months and broke this morning did not rewrite its own logic. Something around it changed, and the audit log is the only API surface that records it.

correlate_failure(execution_id) bounds the audit log to a window around the failed run (24h before by default, through 5 minutes after it ended), keeps the mutations, and ranks them by how closely they relate to the run:

  • an event naming the bot or its fileId outranks everything else

  • among those, the closest in time wins (linear decay across the lookback window)

  • events after the run ended are never suspects — a change made afterwards cannot have broken it, and listing it is how a reader ends up chasing a rollback

  • an event whose timestamp will not parse is kept, but sorted last: dropping it would hide a change, ranking it would rank it on a guess

Every suspect carries a why_suspect string, and the verdict never claims causation — it says "closest change", not "cause". At this layer nothing distinguishes the redeploy that broke the bot from the redeploy that merely landed the same morning, and a confident wrong answer is the worst failure mode a diagnostic tool has.

The Control Room is remote and prunes silently. A window that predates the 180-day audit retention comes back as an empty list with HTTP 200 — indistinguishable from a window in which nothing happened. Past that horizon the response carries a retention_warning and the verdict says no conclusion can be drawn, never "no changes are recorded". Absence of evidence from a remote that deletes on a schedule is not evidence of absence.

list_audit_events is the browse counterpart — filter by user, action substring, or time range. Only the time bound is applied server-side; user and action are matched in process, because the audit field names are unverified and stacking three guesses turns a refinement into a 400 that looks like "no matching events".

Both tools are written for a tight output budget, since tool results are re-read on every turn: empty fields are dropped per row, lists switch to columnar {columns, data} past three rows (repeated keys are the single largest share of the bytes), and the limitations note — audit covers Control Room actions, not bot-internal logging; Log text to file is FILE_LOCAL and unreachable by any API; loop/branch/variable trajectory is exposed by no endpoint — is attached only when the result is empty and silence could be misread. A result that already lists what the audit log holds does not need to be told what it doesn't.


Authentication

The server uses POST /v2/authentication with the X-Authorization: <token> header (no Bearer prefix). Tokens live 20 minutes; refreshes are serialized under a mutex because refresh kills the previous token. An account may hold only 5 concurrent sessions — the token is cached and the optional debug browser window consumes one slot too.

API key is preferred for service accounts; password is supported but should be paired with a non-2FA role (the A360 v2 auth request has no mfaCode field).

Safety

  • Writes are opt-in per instanceallow_writes defaults to False. A missing flag never means "writable".

  • Mutating tools (deploy / publish / update / delete / create / cancel / stop / upload / rename / move / checkout / checkin, plus the browser window tools) require approve=true in the tool call.

  • Publish-grade tools (deploy / publish) require an additional confirm_environment=prod field, so a single confirmation cannot ship to production.

  • The browser layer never clicks. It observes console, network, screenshots, and computed CSS. inspect_* tools structurally cannot open a window — only open_debug_window can.

  • Fail-open by default for write guards; flip with A360_WRITE_GUARDS_FAIL=closed.

  • Diagnosed executions are snapshotted locally on first read — the 90-day cloud retention limit has no backup path otherwise.

Every refusal states the next action. Never refuses without a path forward.

Turning writes on

Writes are a per-instance setting, so you change them where you configured the server — no code change, no rebuild. Add to the env block of any client config above:

"env": {
  "A360_ALLOW_WRITES": "1",
  "A360_WRITE_GUARDS_FAIL": "closed"
}

or pass --allow-writes on the command line. Two things worth knowing before you do:

  • Pair it with A360_WRITE_GUARDS_FAIL=closed. Guards fail open by default, which is harmless while the server is read-only and much less so once it is not: a guard that cannot reach a determination would let the write through.

  • A blocked write costs zero network calls. The gate is checked before the request is built, so turning writes off can never leave a half-applied change behind.

Leaving both unset keeps the server strictly read-only, which is the intended default — diagnosis needs no writes, and bot execution is what the vendor's own MCP Inbound is for.

Cloud retention

Data

Retention

Execution history

90 days

Audit log

180 days (365 in some regions)

Diagnosed executions are cached under state_dir()/snapshots/{account_key}/ with the bot logic at time of diagnosis. Re-diagnosing an old execution reads from disk, not the Control Room, and the response is marked original_expired past 90 days.


Developer setup

git clone https://github.com/jshsakura/a360-mcp.git
cd a360-mcp
uv venv --python 3.12 .venv
uv pip install -e ".[dev]"

# Tests — always run pytest under the memory-cap wrapper, raw pytest has
# killed the local tmux session before.
saferun -m 4G .venv/bin/pytest tests/ -q

# Lint / format / type
.venv/bin/ruff check src tests
.venv/bin/black src tests
.venv/bin/isort src tests
.venv/bin/mypy src

Browser tests are mocked (Playwright is a soft dependency, lazy-imported). To exercise the real browser layer:

uv pip install -e ".[browser]"
playwright install chromium

License

Apache-2.0. See LICENSE.

Install Server
F
license - not found
B
quality
A
maintenance

Maintenance

Maintainers
Response time
Release cycle
1Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    -
    quality
    D
    maintenance
    Enterprise-grade MCP server for Jenkins CI/CD integration that enables AI assistants to diagnose build failures, analyze pipelines, and search logs through natural conversation.
    6
    GPL 3.0
  • F
    license
    -
    quality
    C
    maintenance
    MCP-based production monitoring agent for manufacturing OEE, providing real-time monitoring, downtime root-cause analysis, and automated alerts through integration with SQL Server, MES APIs, and incident management systems.
  • A
    license
    A
    quality
    A
    maintenance
    AI-powered Veeam Backup & Replication operations MCP server with tools for managing jobs, restores, sessions, and repositories, featuring built-in governance, audit logging, and safety controls.
    25
    MIT

View all related MCP servers

Related MCP Connectors

  • Autopilot MCP server for GEO analyses, reports, content, audits, memories and agents.

  • Remote MCP for A2A failure replay MCP, structured receipts, audit logs, and reviewer-ready evidence.

  • Hosted MCP for denial, prior auth, reimbursement, workflow validation, batch scoring, and feedback.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jshsakura/a360-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server