Metadata-Version: 2.4
Name: a360-mcp
Version: 0.1.0
Summary: MCP server for Automation Anywhere Automation 360 (A360) Control Room — bot logic analysis and execution failure diagnostics
Project-URL: Homepage, https://github.com/jshsakura/a360-mcp
Project-URL: Issues, https://github.com/jshsakura/a360-mcp/issues
Project-URL: Changelog, https://github.com/jshsakura/a360-mcp/releases
Author: jshsakura
License:                                  Apache License
                                   Version 2.0, January 2004
                                http://www.apache.org/licenses/
        
           TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
        
           1. Definitions.
        
              "License" shall mean the terms and conditions for use, reproduction,
              and distribution as defined by Sections 1 through 9 of this document.
        
              "Licensor" shall mean the copyright owner or entity authorized by
              the copyright owner that is granting the License.
        
              "Legal Entity" shall mean the union of the acting entity and all
              other entities that control, are controlled by, or are under common
              control with that entity. For the purposes of this definition,
              "control" means (i) the power, direct or indirect, to cause the
              direction or management of such entity, whether by contract or
              otherwise, or (ii) ownership of fifty percent (50%) or more of the
              outstanding shares, or (iii) beneficial ownership of such entity.
        
              "You" (or "Your") shall mean an individual or Legal Entity
              exercising permissions granted by this License.
        
              "Source" form shall mean the preferred form for making modifications,
              including but not limited to software source code, documentation
              source, and configuration files.
        
              "Object" form shall mean any form resulting from mechanical
              transformation or translation of a Source form, including but
              not limited to compiled object code, generated documentation,
              and conversions to other media types.
        
              "Work" shall mean the work of authorship, whether in Source or
              Object form, made available under the License, as indicated by a
              copyright notice that is included in or attached to the work.
        
              "Derivative Works" shall mean any work, whether in Source or Object
              form, that is based on (or derived from) the Work and for which the
              editorial revisions, annotations, elaborations, or other modifications
              represent, as a whole, an original work of authorship.
        
              "Contribution" shall mean any work of authorship, including
              the original version of the Work and any modifications or additions
              to that Work or Derivative Works thereof, that is intentionally
              submitted to the Licensor for inclusion in the Work by the copyright
              owner or by an individual or Legal Entity authorized to submit on
              behalf of the copyright owner.
        
              "Contributor" shall mean Licensor and any individual or Legal Entity
              on behalf of whom a Contribution has been received by the Licensor and
              subsequently incorporated within the Work.
        
           2. Grant of Copyright License. Subject to the terms and conditions of
              this License, each Contributor hereby grants to You a perpetual,
              worldwide, non-exclusive, no-charge, royalty-free, irrevocable
              copyright license to reproduce, prepare Derivative Works of,
              publicly display, publicly perform, sublicense, and distribute the
              Work and such Derivative Works in Source or Object form.
        
           3. Grant of Patent License. Subject to the terms and conditions of
              this License, each Contributor hereby grants to You a perpetual,
              worldwide, non-exclusive, no-charge, royalty-free, irrevocable
              patent license to make, have made, use, offer to sell, sell, import,
              and otherwise transfer the Work.
        
           4. Redistribution. You may reproduce and distribute copies of the
              Work or Derivative Works thereof in any medium, with or without
              modifications, and in Source or Object form, provided that You
              meet the following conditions:
        
              (a) You must give any other recipients of the Work or
                  Derivative Works a copy of this License; and
        
              (b) You must cause any modified files to carry prominent notices
                  stating that You changed the files; and
        
              (c) You must retain, in the Source form of any Derivative Works
                  that You distribute, all copyright, patent, trademark, and
                  attribution notices from the Source form of the Work.
        
           5. Submission of Contributions. Unless You explicitly state otherwise,
              any Contribution intentionally submitted for inclusion in the Work
              by You to the Licensor shall be under the terms and conditions of
              this License, without any additional terms or conditions.
        
           6. Trademarks. This License does not grant permission to use the trade
              names, trademarks, service marks, or product names of the Licensor.
        
           7. Disclaimer of Warranty. Unless required by applicable law or
              agreed to in writing, Licensor provides the Work on an "AS IS" BASIS,
              WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
              implied, including, without limitation, any warranties or conditions
              of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
              PARTICULAR PURPOSE.
        
           8. Limitation of Liability. In no event and under no legal theory,
              shall any Contributor be liable to You for damages, including any
              direct, indirect, special, incidental, or consequential damages of
              any character arising as a result of this License or out of the use
              or inability to use the Work.
        
           9. Accepting Warranty or Additional Liability. While redistributing
              the Work or Derivative Works thereof, You may choose to offer,
              and charge a fee for, acceptance of support, warranty, indemnity,
              or other liability obligations and/or rights consistent with this
              License.
        
           END OF TERMS AND CONDITIONS
        
           Copyright 2025 jshsakura
        
           Licensed under the Apache License, Version 2.0 (the "License");
           you may not use this file except in compliance with the License.
           You may obtain a copy of the License at
        
               http://www.apache.org/licenses/LICENSE-2.0
        
           Unless required by applicable law or agreed to in writing, software
           distributed under the License is distributed on an "AS IS" BASIS,
           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
           See the License for the specific language governing permissions and
           limitations under the License.
License-File: LICENSE
Keywords: a360,automation-360,automation-anywhere,bot-diagnostics,control-room,mcp,model-context-protocol,rpa
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.11
Requires-Dist: anyio<5.0.0,>=4.0.0
Requires-Dist: mcp<2.0.0,>=1.0.0
Requires-Dist: orjson<4.0.0,>=3.9.0
Requires-Dist: pydantic-settings<3.0.0,>=2.0.0
Requires-Dist: pydantic<3.0.0,>=2.0.0
Requires-Dist: pyyaml<7.0,>=6.0
Requires-Dist: requests<3.0.0,>=2.31.0
Provides-Extra: browser
Requires-Dist: playwright<2.0.0,>=1.40.0; extra == 'browser'
Provides-Extra: dev
Requires-Dist: black>=23.0.0; extra == 'dev'
Requires-Dist: isort>=5.12.0; extra == 'dev'
Requires-Dist: mypy>=1.5.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
Requires-Dist: pytest>=7.4.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Requires-Dist: tiktoken>=0.5.0; extra == 'dev'
Requires-Dist: types-pyyaml; extra == 'dev'
Requires-Dist: types-requests; extra == 'dev'
Description-Content-Type: text/markdown

# a360-mcp

[![PyPI version](https://img.shields.io/pypi/v/a360-mcp.svg)](https://pypi.org/project/a360-mcp/)
[![Python Version](https://img.shields.io/pypi/pyversions/a360-mcp)](https://pypi.org/project/a360-mcp/)
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/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.

## 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`), bot logic walker, and snapshot store are
implemented and unit-tested (647 tests). Writes are opt-in and gated. **Not yet validated
against a live Control Room instance** — the A360 filter operator set and bot JSON node
schema are permissive parsers, awaiting field verification.

---

## 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.

```bash
# 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`:

```bash
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:

```powershell
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 |

### Claude Code

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

```json
{
  "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):

```toml
[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):

```json
{
  "$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 only** — `A360_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` | same as `core` | Audit/log reads (deeper reads land later) |
| `diagnose` | core + `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).

### 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.

---

## 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 instance** — `allow_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.

## 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

```bash
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:

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

## License

Apache-2.0. See [LICENSE](LICENSE).
