@qase/mcp-server 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +5 -4
  3. package/build/client/index.d.ts +2 -1
  4. package/build/client/index.d.ts.map +1 -1
  5. package/build/client/index.js +3 -1
  6. package/build/client/index.js.map +1 -1
  7. package/build/operations-v2/composites/ci-report.js +4 -1
  8. package/build/operations-v2/composites/ci-report.js.map +1 -1
  9. package/build/operations-v2/composites/triage-defect.js +4 -1
  10. package/build/operations-v2/composites/triage-defect.js.map +1 -1
  11. package/build/operations-v2/escape/api.js +2 -1
  12. package/build/operations-v2/escape/api.js.map +1 -1
  13. package/build/operations-v2/index.d.ts +1 -0
  14. package/build/operations-v2/index.d.ts.map +1 -1
  15. package/build/operations-v2/index.js +1 -0
  16. package/build/operations-v2/index.js.map +1 -1
  17. package/build/operations-v2/qql/index.js +15 -11
  18. package/build/operations-v2/qql/index.js.map +1 -1
  19. package/build/operations-v2/read/get.js +2 -0
  20. package/build/operations-v2/read/get.js.map +1 -1
  21. package/build/operations-v2/write/attachments.js +74 -16
  22. package/build/operations-v2/write/attachments.js.map +1 -1
  23. package/build/operations-v2/write/case-fields.d.ts.map +1 -1
  24. package/build/operations-v2/write/case-fields.js +8 -2
  25. package/build/operations-v2/write/case-fields.js.map +1 -1
  26. package/build/operations-v2/write/cases.js +3 -1
  27. package/build/operations-v2/write/cases.js.map +1 -1
  28. package/build/operations-v2/write/defects.js +4 -1
  29. package/build/operations-v2/write/defects.js.map +1 -1
  30. package/build/operations-v2/write/results.js +8 -2
  31. package/build/operations-v2/write/results.js.map +1 -1
  32. package/build/operations-v2/write/reviews.d.ts +15 -0
  33. package/build/operations-v2/write/reviews.d.ts.map +1 -0
  34. package/build/operations-v2/write/reviews.js +350 -0
  35. package/build/operations-v2/write/reviews.js.map +1 -0
  36. package/build/operations-v2/write/shared-steps.js +4 -1
  37. package/build/operations-v2/write/shared-steps.js.map +1 -1
  38. package/build/utils/output-schemas.d.ts +4 -0
  39. package/build/utils/output-schemas.d.ts.map +1 -1
  40. package/build/utils/output-schemas.js +51 -0
  41. package/build/utils/output-schemas.js.map +1 -1
  42. package/build/version.d.ts +1 -1
  43. package/build/version.js +1 -1
  44. package/docs/migration.md +1 -1
  45. package/docs/tools.md +29 -12
  46. package/docs/troubleshooting.md +22 -0
  47. package/package.json +2 -2
  48. package/server.json +2 -2
package/build/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // Auto-generated by prebuild script — do not edit manually
2
- export const VERSION = '2.1.0';
2
+ export const VERSION = '2.2.0';
3
3
  //# sourceMappingURL=version.js.map
package/docs/migration.md CHANGED
@@ -183,7 +183,7 @@ All 83 v1 tools mapped to their v2 equivalents.
183
183
  |---|---|---|
184
184
  | `list_attachments` | `qase_api` | Use escape hatch: `GET /attachment` |
185
185
  | `get_attachment` | `qase_get` with `entity="attachment"` | Pass hash as `id` |
186
- | `upload_attachment` | `qase_attachment_upload` | |
186
+ | `upload_attachment` | `qase_attachment_upload` | Pass `file_base64` (or `file_path` for a server running locally). The single `file` argument still works but is deprecated |
187
187
  | `delete_attachment` | `qase_attachment_delete` | — |
188
188
 
189
189
  ### Authors
package/docs/tools.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # Tool Reference
2
2
 
3
- The Qase MCP Server exposes **32 tools** across 6 groups: Read, QQL, Write, Composite, Escape hatch, and Meta.
3
+ The Qase MCP Server exposes **37 tools** across 6 groups: Read (2), QQL (2), Write (28, including 5 review tools), Composite (3), Escape hatch (1), and Meta (1).
4
4
 
5
5
  ## Discovery model
6
6
 
7
7
  To keep context-token usage low, tools are split into two visibility tiers:
8
8
 
9
- - **`core`** — always listed to the MCP client, no activation needed (13 tools).
10
- - **`discoverable`** — hidden by default; the LLM finds and activates them on demand via `qase_discover_tools`, which searches tool names/descriptions and activates matches for the rest of the session (19 tools, mostly deletes and secondary write operations).
9
+ - **`core`** — always listed to the MCP client, no activation needed (14 tools).
10
+ - **`discoverable`** — hidden by default; the LLM finds and activates them on demand via `qase_discover_tools`, which searches tool names/descriptions and activates matches for the rest of the session (23 tools, mostly deletes, review operations, and secondary write operations).
11
11
 
12
12
  If a tool you need isn't showing up in your client's tool list, call `qase_discover_tools` with a query (e.g. `"delete"`, `"milestone"`, `"attachment"`) to activate it first.
13
13
 
@@ -17,20 +17,20 @@ Every tool's schema uses "label or numeric ID" strings for Qase's configurable e
17
17
 
18
18
  | Tool | Description | Key params | Visibility |
19
19
  | --- | --- | --- | --- |
20
- | `qase_get` | Get any Qase entity by type and ID. Supports field projection via `fields`. `code` is required for project-scoped entities (case, suite, run, result, plan, defect, milestone, environment, shared_step, shared_parameter, configuration); optional for global entities (user, author, attachment, custom_field). Cases and runs automatically request their external issue links (`external_issues` / `external_issue`); override with `include`. | `entity` (enum: case, suite, run, result, plan, defect, milestone, environment, shared_step, shared_parameter, configuration, attachment, author, user, custom_field), `code` (optional), `id` (number or hash string), `fields` (optional string array — pass `["*"]` for all), `include` (optional string) | core |
21
- | `qase_project_context` | Get full project context in one call: project details, suites tree, milestones, environments, custom fields, and users. Cached for 5 minutes. Recommended as the first call when starting work with a project. | `code` | core |
20
+ | `qase_get` | Get any Qase entity by type and ID. Supports field projection via `fields`. `code` is required for project-scoped entities (case, suite, run, result, plan, defect, milestone, environment, shared_step, shared_parameter, configuration, review); optional for global entities (user, author, attachment, custom_field). Cases and runs automatically request their external issue links (`external_issues` / `external_issue`); override with `include`. | `entity` (enum: case, suite, run, result, plan, defect, milestone, environment, shared_step, shared_parameter, configuration, attachment, author, user, custom_field, review), `code` (optional), `id` (number or hash string), `fields` (optional string array — pass `["*"]` for all), `include` (optional string) | core |
21
+ | `qase_project_context` | Get full project context in one call: project details, suites tree, milestones, environments, custom fields, and users. Cached for 5 minutes. Recommended as the first call when starting work with a project. Each collection returns its first 100 entities by default — check the `coverage` field (`{ total, loaded, truncated }` per collection) before treating a list as complete, and pass `full: true` to page through everything. | `code`, `full` (optional bool, default false) | core |
22
22
 
23
23
  ## QQL tools
24
24
 
25
25
  | Tool | Description | Key params | Visibility |
26
26
  | --- | --- | --- | --- |
27
- | `qql_search` | Search entities using Qase Query Language (QQL) with powerful filtering and cross-project queries. | `query` (1-1000 chars, QQL expression), `limit` (optional, max 100, default 10), `offset` (optional) | core |
28
- | `qql_help` | Get help and examples for QQL syntax. | `topic` (optional enum: syntax, entities, operators, functions, examples omit for general overview) | core |
27
+ | `qql_search` | Search entities using Qase Query Language (QQL) with powerful filtering and cross-project queries. Aggregate with `SELECT (COUNT(id)) …` instead of paging rows to count — note `SELECT` comes **first**, before the conditions. | `query` (1-2000 chars, matching the REST limit), `limit` (optional, max 100, default 10), `offset` (optional) | core |
28
+ | `qql_help` | Get one section of the QQL reference. `topic` is **required** — the whole reference is large, so ask for the section you need. Read `entities` before querying an unfamiliar entity: field names are not uniform (only `case`/`defect`/`plan`/`requirement` have `created`; `run` has `started`/`ended`, `result` only `ended`). | `topic` (required enum: overview, syntax, entities, operators, functions, examples, aggregation, enumValues) | core |
29
29
 
30
30
  ## Write tools
31
31
 
32
32
  <details>
33
- <summary>Write tools (23)</summary>
33
+ <summary>Write tools (23, excluding review — see below)</summary>
34
34
 
35
35
  | Tool | Description | Key params | Visibility |
36
36
  | --- | --- | --- | --- |
@@ -54,7 +54,7 @@ Every tool's schema uses "label or numeric ID" strings for Qase's configurable e
54
54
  | `qase_shared_step_delete` | Delete a shared step by project code and hash. | `code`, `hash` | discoverable |
55
55
  | `qase_environment_upsert` | Create or update a test environment. If `id` is provided, updates the existing environment; if omitted, creates a new one. | `code`, `id` (optional), `title` (1-255 chars), `description`, `slug`, `host` | discoverable |
56
56
  | `qase_environment_delete` | Delete a test environment by project code and environment ID. | `code`, `id` | discoverable |
57
- | `qase_attachment_upload` | Upload a file attachment. Accepts the file as a base64 encoded string or an absolute path. Returns the attachment hash that can be referenced in test cases and results. | `code`, `file` (base64 string or absolute path), `filename` | discoverable |
57
+ | `qase_attachment_upload` | Upload a file and get back its hash, which every `attachments` field accepts. This is the only way to obtain such a hash the endpoint needs `multipart/form-data`, which `qase_api` cannot send. Use `file_base64` whenever the server is not on the same machine as the file, including the hosted connector, where it is the only option. | `code`, `filename`, `file_base64` (base64 content), `file_path` (absolute path, local servers only), `file` (deprecated alias accepting either) | **core** |
58
58
  | `qase_attachment_delete` | Delete an attachment by its hash. | `hash` | discoverable |
59
59
  | `qase_external_issue_link` | Link or unlink test cases and test runs to issues in an external tracker (Jira Cloud or Jira Server). A case can be linked to several issues; a run can have only one link, and attaching a new issue replaces the previous one. Detaching a run clears its link. Read linked issues back with `qase_get`. | `code`, `entity` (enum: case, run), `action` (enum: attach, detach), `type` (enum: jira-cloud, jira-server), `links` (array: `id`, `issues` — issue keys such as `PROJ-1234`) | discoverable |
60
60
 
@@ -62,6 +62,23 @@ Every tool's schema uses "label or numeric ID" strings for Qase's configurable e
62
62
 
63
63
  To insert a shared step into a test case, pass its hash as `shared` on a step object in `qase_case_upsert` or `qase_case_bulk_create`: `{"steps": [{"shared": "<hash>"}]}`. `action` is not required for such a step, and nesting is supported. The read side of the API reports the link as `shared_step_hash`; that spelling is accepted on write too and is translated automatically.
64
64
 
65
+ ### Review tools
66
+
67
+ Test case review is the pull-request workflow for test cases: an author proposes a new case or a change to an existing one, reviewers approve or request changes, and merging applies the proposal. All review tools require **"Test case review" to be enabled in the project settings** — otherwise every call fails, and the error points at that setting.
68
+
69
+ **Scope**: the public API covers authoring only. **Approving, requesting changes, merging, and declining have no API endpoints** — they exist only in the Qase UI (which does emit webhooks). No tool here can perform them; read the current state with `qase_review_list` or `qase_get`.
70
+
71
+ | Tool | Description | Key params | Visibility |
72
+ | --- | --- | --- | --- |
73
+ | `qase_review_create` | Open a review. With `case_id` it proposes changes to an existing case (an `edit` review — send only the fields that change); without it, a new-case draft (a `create` review — `title` required). Case fields are named and normalised exactly as in `qase_case_upsert`. Returns `{ review_id, type, case_id, status }`. | `code`, `case_id` (optional), `reviewers` (optional), plus any `qase_case_upsert` case field | discoverable |
74
+ | `qase_review_update` | Change the proposal, reassign reviewers, or both. **Changing the proposal resets every approval already given**; updating only `reviewers` keeps them. The result reports `approvals_reset`. | `code`, `id`, `reviewers` (optional — replaces the list; `[]` removes everyone), plus any case field | discoverable |
75
+ | `qase_review_list` | List reviews with filters, reporting `total` alongside `returned`. This is how review and per-reviewer approval status are read — QQL has no `review` entity. | `code`, `status` (optional enum: open, merged, declined), `type` (optional enum: create, edit), `case_id`, `author_uuid`, `reviewer_uuid`, `search`, `limit` (max 100, default 25), `offset` | discoverable |
76
+ | `qase_review_delete` | Delete a review. Merged reviews cannot be deleted. This removes the proposal — it does **not** decline it, which is UI-only. | `code`, `id` | discoverable |
77
+ | `qase_review_bulk_create` | Open several reviews at once. The API validates the batch as a whole, so one invalid item rejects all of them; items missing a required `title` are caught locally before anything is sent. Returns a flat `review_ids` list (the API nests them as `items[].review_id`). | `code`, `reviews` (array, min 1 — same fields as `qase_review_create` without `code`) | discoverable |
78
+
79
+ Reviewers are **author UUIDs**, not user IDs (`qase_get { entity: "author" }` or `GET /author`). Email addresses are accepted and resolved to UUIDs. A review cannot be reviewed by its author, and the review is created by whoever owns the API token — so that person cannot appear in `reviewers`; leave the list empty and assign in the UI if needed.
80
+
81
+ Read a single review, including its `proposed_case`, with `qase_get { entity: "review", code, id }`.
65
82
 
66
83
  ## Composite tools
67
84
 
@@ -71,13 +88,13 @@ Composite tools chain several underlying operations into one call, so an agent a
71
88
  | --- | --- | --- | --- |
72
89
  | `qase_ci_report` | Report CI/CD test results in one call: creates a run, records all results, and optionally completes the run. Replaces the 3-4 step manual workflow of create_run → bulk_create_results → complete_run. Designed for CI pipeline integration. | `code`, `title` (1-255 chars), `environment_id` (optional), `results` (array, min 1: `case_id`, `status` (enum: passed, failed, blocked, skipped, invalid), `comment`, `time_ms`, `stacktrace`, `defect`, `attachments`), `complete` (default true), `is_autotest` (default true) | core |
73
90
  | `qase_regression_run` | Set up a regression test run in one call. Accepts case selection by suite IDs, explicit case IDs, or plan ID. Creates the run and adds all matching cases. Replaces the multi-step workflow of find cases → create run → add cases. | `code`, `title` (1-255 chars), `description`, `environment_id`, `milestone_id`, `plan_id`, `suite_ids` (array), `include_cases` (array) | core |
74
- | `qase_triage_defect` | Create a defect from a test failure and optionally link it to failed results. Streamlines the triage workflow: create defect link to failing tests. | `code`, `title` (1-255 chars), `severity` (enum, see [below](#case-enum-values)), `actual_result`, `description`, `run_id` (optional, informational), `failed_result_ids` (result hashes, optional), `tags`, `attachments`, `custom_field` | core |
91
+ | `qase_triage_defect` | Create a defect from a test failure. `title`, `actual_result`, and `severity` are all required by the API. The API offers no way to attach runs or results to a defect — the `runs`/`results` arrays seen on a defect are populated by the test runner when a result is reported as a defect — so reference failing results in `actual_result` instead. (`run_id` and `failed_result_ids` were removed in 2.1.0: they were accepted and ignored.) | `code`, `title` (1-255 chars), `actual_result` (required), `severity` (required, enum, see [below](#case-enum-values)), `description`, `tags`, `attachments`, `custom_field` | core |
75
92
 
76
93
  ## Escape hatch
77
94
 
78
95
  | Tool | Description | Key params | Visibility |
79
96
  | --- | --- | --- | --- |
80
- | `qase_api` | Direct Qase REST API call for endpoints not covered by other tools. Pass the HTTP method, path (starting with `/v1/`), and optional body/query. Use this when the dedicated tools do not cover your use case. See [developers.qase.io](https://developers.qase.io) for the API reference. | `method` (enum: GET, POST, PUT, PATCH, DELETE — default GET), `path` (e.g. `/v1/project/DEMO/run`), `body` (optional object, for POST/PUT/PATCH), `query` (optional object) | core |
97
+ | `qase_api` | Direct Qase REST API call for endpoints not covered by other tools. Pass the HTTP method, path (starting with `/v1/`), and optional body/query. Use this when the dedicated tools do not cover your use case. **Sends JSON only** — it cannot upload files, which need `multipart/form-data`; use `qase_attachment_upload` for that. See [developers.qase.io](https://developers.qase.io) for the API reference. | `method` (enum: GET, POST, PUT, PATCH, DELETE — default GET), `path` (e.g. `/v1/project/DEMO/run`), `body` (optional object, for POST/PUT/PATCH), `query` (optional object) | core |
81
98
 
82
99
  ## Meta
83
100
 
@@ -89,7 +106,7 @@ Composite tools chain several underlying operations into one call, so an agent a
89
106
 
90
107
  Test case enum fields (`priority`, `severity`, `type`, `layer`, `behavior`, `status`, `automation`) are **workspace-configurable system fields**, not fixed literals in the tool schema — each Qase workspace can rename/reorder its own options. Tool calls accept either the field's label (e.g. `"high"`, `"blocker"`), its slug, or its numeric ID as a string; the server resolves the value against the workspace's live system-field configuration (fetched from the Qase API and cached for 5 minutes — see `src/utils/case-enums.ts`) before sending the request.
91
108
 
92
- The `automation` field is the one exception with a fixed, documented mapping (translated internally to the API's `isManual`/`isToBeAutomated` fields):
109
+ The `automation` field is the one exception with a fixed, documented mapping (translated internally to the API's `isManual`/`isToBeAutomated` fields for cases, and to `is_manual`/`is_to_be_automated` for review proposals, which is what the review endpoint expects):
93
110
 
94
111
  | Value | Meaning |
95
112
  | --- | --- |
@@ -128,6 +128,28 @@ To find your certificate:
128
128
  5. Check the MCP client logs for connection errors
129
129
  6. For self-run from source, verify the server is built: `npm run build`
130
130
 
131
+ ## "Upload isn't possible on this connector"
132
+
133
+ **Symptom**: the agent says attachments cannot be uploaded — often phrased as the endpoint requiring `multipart/form-data` while `qase_api` only sends JSON.
134
+
135
+ **Cause**: the agent did not see `qase_attachment_upload`. Before 2.2.0 it was a discoverable tool, hidden from the tool list until `qase_discover_tools` was called, so the agent fell back to the `qase_api` escape hatch — which genuinely cannot send `multipart/form-data`.
136
+
137
+ **Solution**:
138
+ 1. Update to 2.2.0 or later, where the upload tool is always listed: `npm update -g @qase/mcp-server` (the hosted connector always runs the latest version)
139
+ 2. On an older version, ask the agent to run `qase_discover_tools` with `"attachment"` first
140
+ 3. Pass the file as `file_base64`. `file_path` only works when the server runs on the same machine as the file — the hosted connector cannot read your filesystem
141
+ 4. To attach the result to a case, pass the returned hash in the `attachments` array of `qase_case_upsert` (or `qase_result_record`, `qase_ci_report`, `qase_defect_upsert`, `qase_triage_defect`)
142
+
143
+ ## Review tools fail or aren't listed
144
+
145
+ **Symptom**: `qase_review_*` tools are missing, or every call fails.
146
+
147
+ **Solution**:
148
+ 1. Review tools are discoverable — ask the agent to run `qase_discover_tools` with `"review"`
149
+ 2. Enable **Test case review** in the project settings; without it every review endpoint rejects the request
150
+ 3. Approving, requesting changes, merging, and declining are **UI-only** — the public API has no endpoints for them, so no tool can perform them
151
+ 4. `reviewers` takes author UUIDs (or emails, which are resolved). The review's author cannot be its own reviewer, and the author is whoever owns the API token
152
+
131
153
  ## Tool Not Found
132
154
 
133
155
  **Error**: `Unknown tool: tool_name`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qase/mcp-server",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "mcpName": "io.qase/mcp-server",
5
5
  "description": "Official MCP server for Qase Test Management Platform",
6
6
  "type": "module",
@@ -75,7 +75,7 @@
75
75
  "lru-cache": "^11.3.5",
76
76
  "neverthrow": "^8.2.0",
77
77
  "npm": "^12.0.2",
78
- "qase-api-client": "^1.1.13",
78
+ "qase-api-client": "^1.1.14",
79
79
  "zod": "^3.24.2",
80
80
  "zod-to-json-schema": "^3.24.3"
81
81
  },
package/server.json CHANGED
@@ -8,12 +8,12 @@
8
8
  "url": "https://github.com/qase-tms/qase-mcp-server",
9
9
  "source": "github"
10
10
  },
11
- "version": "2.1.0",
11
+ "version": "2.2.0",
12
12
  "packages": [
13
13
  {
14
14
  "registryType": "npm",
15
15
  "identifier": "@qase/mcp-server",
16
- "version": "2.1.0",
16
+ "version": "2.2.0",
17
17
  "transport": {
18
18
  "type": "stdio"
19
19
  },