Metadata-Version: 2.4
Name: zephyr-squad-server-mcp
Version: 1.0.0
Summary: MCP server for Zephyr Squad Server/Data Center — drive ZAPI test management from an AI agent.
Project-URL: Homepage, https://github.com/alejandroviera/zephyr-squad-server-mcp
Project-URL: Repository, https://github.com/alejandroviera/zephyr-squad-server-mcp
Project-URL: Issues, https://github.com/alejandroviera/zephyr-squad-server-mcp/issues
Author-email: Alejandro Viera <alejandro.viera@gmail.com>
License: MIT
License-File: LICENSE
Keywords: jira,llm,mcp,test-management,zapi,zephyr
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: mcp[cli]>=1.2.0
Requires-Dist: pydantic-settings>=2.0
Description-Content-Type: text/markdown

# zephyr-squad-server-mcp

An [MCP](https://modelcontextprotocol.io) server that lets an AI agent drive
**Zephyr for Jira — Server / Data Center (ZAPI)**, the test-management suite for
Jira. It exposes the most common test-management operations (cycles, folders,
executions, test steps, step results, ZQL search) as well-described tools over
**stdio**, so it plugs into Claude Desktop, Claude Code, and any other MCP client.

> This targets the **Server/DC** flavor (`/rest/zapi/latest`). It is **not** for
> Zephyr Squad **Cloud**, which uses a different JWT-signed API.

## Install

The server is published on PyPI and is easiest to run with
[`uv`](https://docs.astral.sh/uv/):

```bash
uvx zephyr-squad-server-mcp        # run directly, no install
# or
uv tool install zephyr-squad-server-mcp
# or, in a venv
pip install zephyr-squad-server-mcp
```

## Configuration

The connection rides on your Jira instance's authentication (shared by ZAPI and
the Jira core REST API). Configure via environment variables or a `.env` file
(see [`.env.example`](.env.example)):

| Variable | Required | Default | Description |
|---|---|---|---|
| `JIRA_BASE_URL` | ✅ | — | Jira base URL, e.g. `https://jira.company.com` (no `/rest` suffix). |
| `JIRA_PAT` | one of | — | Personal Access Token → `Authorization: Bearer …` (**recommended for DC**). |
| `JIRA_USERNAME` + `JIRA_PASSWORD` | one of | — | Basic-auth fallback (password or API token). Used only if `JIRA_PAT` is empty. |
| `ZEPHYR_API_PATH` | | `/rest/zapi/latest` | ZAPI base path on the Jira host. |
| `ZEPHYR_TIMEOUT` | | `30` | Per-request timeout (seconds). |
| `ZEPHYR_VERIFY_SSL` | | `true` | Verify TLS certs. Set `false` only for trusted internal self-signed hosts. |

The server fails fast with a clear error if the base URL or authentication is
missing.

## Client configuration (stdio)

Add to your MCP client config (e.g. Claude Desktop `claude_desktop_config.json`
or Claude Code `.mcp.json`):

```json
{
  "mcpServers": {
    "zephyr-squad": {
      "command": "uvx",
      "args": ["zephyr-squad-server-mcp"],
      "env": {
        "JIRA_BASE_URL": "https://jira.company.com",
        "JIRA_PAT": "your-personal-access-token"
      }
    }
  }
}
```

For local development against a checkout, point `command` at `uv`:

```json
{
  "mcpServers": {
    "zephyr-squad": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/zephyr-squad-server-mcp", "zephyr-squad-server-mcp"],
      "env": { "JIRA_BASE_URL": "https://jira.company.com", "JIRA_PAT": "…" }
    }
  }
}
```

## Tools

All id-bearing tools accept **either** a numeric id **or** a human-friendly
key/name for `project` (key like `SONY` or its name), `version` (name like
`Version 1.0`, or `-1`/`Unscheduled`), and `issue` (key like `SONY-1386`).
Resolved ids are cached for the session, so the first call does the lookup and
later calls reuse it.

> **Full reference:** see [`docs/tools.md`](docs/tools.md) for every tool's
> arguments, types, defaults, the exact ZAPI endpoint it calls, and sync/async
> behavior. The table below is a quick index.

| Tool | What it does |
|---|---|
| `list_cycles` | List test cycles for a project/version. |
| `get_cycle` | Get one cycle's details (id `-1` = the Ad hoc cycle). |
| `create_cycle` | Create a test cycle. |
| `update_cycle` | Update a cycle's fields (id is sent in the body). |
| `delete_cycle` | Delete a cycle (async; auto-polls to completion by default). |
| `export_cycle` | Get a CSV download link for a cycle's executions. |
| `copy_executions_to_cycle` | Copy executions into a cycle (async; auto-polls to completion by default). |
| `move_executions_to_folder` | Move executions from a cycle into a folder (async; auto-polls to completion by default). |
| `list_cycle_folders` | List folders within a cycle. |
| `create_folder` | Create a folder under a cycle. |
| `update_folder` | Update a folder's name/description. |
| `delete_folder` | Delete a folder from a cycle (async; auto-polls to completion by default). |
| `list_executions` | List executions in a cycle (optionally a folder). |
| `update_execution` | Set an execution's status (PASS/FAIL/WIP/BLOCKED/…). |
| `list_test_steps` | List the test steps of a test issue. |
| `create_test_step` | Add a test step to a test issue. |
| `list_step_results` | List per-step results for an execution. |
| `search_executions` | Run a ZQL query and return matching executions. |
| `get_execution_status_counts` | Status-count rollup for a project/version (by cycle). |
| `get_execution_status_counts_by_assignee` | Per-assignee status counts for cycle(s). |
| `list_executions_by_issue` | A single test's executions across all cycles. |
| `list_execution_defects` | Defects linked to an execution. |
| `get_tests_by_requirement` | Tests covering requirement(s); flags orphans. |
| `get_executions_by_test` | Executions for a test (coverage history). |
| `get_executions_by_defect` | Executions linked to a defect. |
| `get_defect_statistics` | Per-defect execution/req/test rollups. |
| `update_test_step` | Edit a test step's action/data/result. |
| `delete_test_step` | Delete a test step. |
| `create_execution` | Schedule a test into a cycle. |
| `add_tests_to_cycle_from_list` | Bulk-add an explicit list of tests to a cycle as new UNEXECUTED executions (async). |
| `add_tests_to_cycle_from_filter` | Bulk-add tests matched by a saved ZQL filter to a cycle as new UNEXECUTED executions (async). |
| `add_tests_to_cycle_from_cycle` | Add tests from another cycle as new UNEXECUTED executions (async). |
| `update_step_result` | Set a step result's status/comment. |
| `link_execution_defects` | Link Jira defects to executions (async). |
| `assign_execution` | Assign an execution to a user. |
| `delete_execution` | Delete an execution by id. |
| `get_job_progress` *(helper)* | Manually poll any async job by token. |
| `list_projects` *(helper)* | List projects (name → id discovery). |
| `list_versions` *(helper)* | List a project's versions (name → id discovery). |
| `get_zephyr_test_issue_type` *(helper)* | Discover the Zephyr Test issue-type id per project (use case 1.1). |

Dates use Jira's `dd/MMM/yy` format (e.g. `4/Dec/12`). Execution-status codes:
`-1=UNEXECUTED, 1=PASS, 2=FAIL, 3=WIP, 4=BLOCKED, 5=PENDING, 6=APPROVED, 7=CANCELLED`.

## Development

```bash
uv sync                  # create venv + install deps (incl. dev group)
uv run pytest            # unit tests (httpx mocked with respx — no live Jira needed)
uv run ruff check        # lint
uv run mcp dev src/zephyr_squad_server_mcp/server.py   # MCP Inspector smoke test
```

[`docs/getzephyr.apib`](docs/getzephyr.apib) is the ZAPI API Blueprint used as the
reference for request/response shapes during development. It was retrieved from the
official public documentation at <https://getzephyr.docs.apiary.io/> (© SmartBear
Software). An older version is also available in the
[zfjdeveloper/zapi-docs](https://github.com/zfjdeveloper/zapi-docs) repository.

The Inspector (`mcp dev`) launches the MCP Inspector via `npx`, so it needs
**Node.js / npx** on your PATH. The tool list loads without any Jira config, but
*invoking* a tool builds the client on first use — so set `JIRA_BASE_URL` and
auth (a `.env` is read automatically) before running tools.

## Publishing to PyPI

```bash
uv build                                  # produces wheel + sdist in dist/
uv publish --token "$UV_PUBLISH_TOKEN"    # or set UV_PUBLISH_TOKEN in the env
```

Test against TestPyPI first:

```bash
uv publish --publish-url https://test.pypi.org/legacy/ --token "$TESTPYPI_TOKEN"
```

## License

MIT — see [LICENSE](LICENSE).
