@qase/mcp-server 1.1.8 → 2.0.1
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.
- package/CHANGELOG.md +38 -0
- package/README.md +75 -542
- package/build/auth/client-context.d.ts +12 -0
- package/build/auth/client-context.d.ts.map +1 -0
- package/build/auth/client-context.js +12 -0
- package/build/auth/client-context.js.map +1 -0
- package/build/auth/jwks-verifier.d.ts +15 -0
- package/build/auth/jwks-verifier.d.ts.map +1 -0
- package/build/auth/jwks-verifier.js +31 -0
- package/build/auth/jwks-verifier.js.map +1 -0
- package/build/auth/mcp-guard.d.ts +15 -0
- package/build/auth/mcp-guard.d.ts.map +1 -0
- package/build/auth/mcp-guard.js +44 -0
- package/build/auth/mcp-guard.js.map +1 -0
- package/build/auth/oauth-config.d.ts +40 -0
- package/build/auth/oauth-config.d.ts.map +1 -0
- package/build/auth/oauth-config.js +34 -0
- package/build/auth/oauth-config.js.map +1 -0
- package/build/auth/proxy-provider.d.ts +31 -0
- package/build/auth/proxy-provider.d.ts.map +1 -0
- package/build/auth/proxy-provider.js +87 -0
- package/build/auth/proxy-provider.js.map +1 -0
- package/build/auth/token-type.d.ts +7 -0
- package/build/auth/token-type.d.ts.map +1 -0
- package/build/auth/token-type.js +10 -0
- package/build/auth/token-type.js.map +1 -0
- package/build/cache/circuit-breaker.d.ts +33 -0
- package/build/cache/circuit-breaker.d.ts.map +1 -0
- package/build/cache/circuit-breaker.js +68 -0
- package/build/cache/circuit-breaker.js.map +1 -0
- package/build/cache/index.d.ts +24 -0
- package/build/cache/index.d.ts.map +1 -0
- package/build/cache/index.js +86 -0
- package/build/cache/index.js.map +1 -0
- package/build/cache/keys.d.ts +25 -0
- package/build/cache/keys.d.ts.map +1 -0
- package/build/cache/keys.js +36 -0
- package/build/cache/keys.js.map +1 -0
- package/build/cache/layered.d.ts +31 -0
- package/build/cache/layered.d.ts.map +1 -0
- package/build/cache/layered.js +88 -0
- package/build/cache/layered.js.map +1 -0
- package/build/cache/memory.d.ts +32 -0
- package/build/cache/memory.d.ts.map +1 -0
- package/build/cache/memory.js +108 -0
- package/build/cache/memory.js.map +1 -0
- package/build/cache/metrics.d.ts +31 -0
- package/build/cache/metrics.d.ts.map +1 -0
- package/build/cache/metrics.js +95 -0
- package/build/cache/metrics.js.map +1 -0
- package/build/cache/prom-format.d.ts +7 -0
- package/build/cache/prom-format.d.ts.map +1 -0
- package/build/cache/prom-format.js +16 -0
- package/build/cache/prom-format.js.map +1 -0
- package/build/cache/redis-bus.d.ts +29 -0
- package/build/cache/redis-bus.d.ts.map +1 -0
- package/build/cache/redis-bus.js +50 -0
- package/build/cache/redis-bus.js.map +1 -0
- package/build/cache/redis.d.ts +32 -0
- package/build/cache/redis.d.ts.map +1 -0
- package/build/cache/redis.js +89 -0
- package/build/cache/redis.js.map +1 -0
- package/build/cache/types.d.ts +38 -0
- package/build/cache/types.d.ts.map +1 -0
- package/build/cache/types.js +2 -0
- package/build/cache/types.js.map +1 -0
- package/build/client/index.d.ts +10 -3
- package/build/client/index.d.ts.map +1 -1
- package/build/client/index.js +75 -50
- package/build/client/index.js.map +1 -1
- package/build/http/agent.d.ts +16 -0
- package/build/http/agent.d.ts.map +1 -0
- package/build/http/agent.js +16 -0
- package/build/http/agent.js.map +1 -0
- package/build/http/dedupe.d.ts +14 -0
- package/build/http/dedupe.d.ts.map +1 -0
- package/build/http/dedupe.js +69 -0
- package/build/http/dedupe.js.map +1 -0
- package/build/http/index.d.ts +6 -0
- package/build/http/index.d.ts.map +1 -0
- package/build/http/index.js +4 -0
- package/build/http/index.js.map +1 -0
- package/build/http/retry.d.ts +18 -0
- package/build/http/retry.d.ts.map +1 -0
- package/build/http/retry.js +52 -0
- package/build/http/retry.js.map +1 -0
- package/build/index.d.ts +1 -18
- package/build/index.d.ts.map +1 -1
- package/build/index.js +95 -63
- package/build/index.js.map +1 -1
- package/build/operations-v2/composites/ci-report.d.ts +2 -0
- package/build/operations-v2/composites/ci-report.d.ts.map +1 -0
- package/build/operations-v2/composites/ci-report.js +99 -0
- package/build/operations-v2/composites/ci-report.js.map +1 -0
- package/build/operations-v2/composites/regression-run.d.ts +2 -0
- package/build/operations-v2/composites/regression-run.d.ts.map +1 -0
- package/build/operations-v2/composites/regression-run.js +81 -0
- package/build/operations-v2/composites/regression-run.js.map +1 -0
- package/build/operations-v2/composites/triage-defect.d.ts +2 -0
- package/build/operations-v2/composites/triage-defect.d.ts.map +1 -0
- package/build/operations-v2/composites/triage-defect.js +67 -0
- package/build/operations-v2/composites/triage-defect.js.map +1 -0
- package/build/operations-v2/escape/api.d.ts +2 -0
- package/build/operations-v2/escape/api.d.ts.map +1 -0
- package/build/operations-v2/escape/api.js +34 -0
- package/build/operations-v2/escape/api.js.map +1 -0
- package/build/operations-v2/index.d.ts +21 -0
- package/build/operations-v2/index.d.ts.map +1 -0
- package/build/operations-v2/index.js +27 -0
- package/build/operations-v2/index.js.map +1 -0
- package/build/operations-v2/meta/discover.d.ts +9 -0
- package/build/operations-v2/meta/discover.d.ts.map +1 -0
- package/build/operations-v2/meta/discover.js +79 -0
- package/build/operations-v2/meta/discover.js.map +1 -0
- package/build/{operations/search.d.ts → operations-v2/qql/index.d.ts} +1 -1
- package/build/operations-v2/qql/index.d.ts.map +1 -0
- package/build/{operations/search.js → operations-v2/qql/index.js} +34 -9
- package/build/operations-v2/qql/index.js.map +1 -0
- package/build/operations-v2/read/get.d.ts +2 -0
- package/build/operations-v2/read/get.d.ts.map +1 -0
- package/build/operations-v2/read/get.js +115 -0
- package/build/operations-v2/read/get.js.map +1 -0
- package/build/operations-v2/read/project-context.d.ts +2 -0
- package/build/operations-v2/read/project-context.d.ts.map +1 -0
- package/build/operations-v2/read/project-context.js +102 -0
- package/build/operations-v2/read/project-context.js.map +1 -0
- package/build/operations-v2/write/attachments.d.ts +2 -0
- package/build/operations-v2/write/attachments.d.ts.map +1 -0
- package/build/operations-v2/write/attachments.js +58 -0
- package/build/operations-v2/write/attachments.js.map +1 -0
- package/build/operations-v2/write/case-fields.d.ts +206 -0
- package/build/operations-v2/write/case-fields.d.ts.map +1 -0
- package/build/operations-v2/write/case-fields.js +79 -0
- package/build/operations-v2/write/case-fields.js.map +1 -0
- package/build/operations-v2/write/cases-bulk.d.ts +2 -0
- package/build/operations-v2/write/cases-bulk.d.ts.map +1 -0
- package/build/operations-v2/write/cases-bulk.js +54 -0
- package/build/operations-v2/write/cases-bulk.js.map +1 -0
- package/build/operations-v2/write/cases.d.ts +2 -0
- package/build/operations-v2/write/cases.d.ts.map +1 -0
- package/build/operations-v2/write/cases.js +52 -0
- package/build/operations-v2/write/cases.js.map +1 -0
- package/build/operations-v2/write/defects.d.ts +2 -0
- package/build/operations-v2/write/defects.d.ts.map +1 -0
- package/build/operations-v2/write/defects.js +81 -0
- package/build/operations-v2/write/defects.js.map +1 -0
- package/build/operations-v2/write/environments.d.ts +2 -0
- package/build/operations-v2/write/environments.d.ts.map +1 -0
- package/build/operations-v2/write/environments.js +56 -0
- package/build/operations-v2/write/environments.js.map +1 -0
- package/build/operations-v2/write/external-issues.d.ts +2 -0
- package/build/operations-v2/write/external-issues.d.ts.map +1 -0
- package/build/operations-v2/write/external-issues.js +96 -0
- package/build/operations-v2/write/external-issues.js.map +1 -0
- package/build/operations-v2/write/milestones.d.ts +2 -0
- package/build/operations-v2/write/milestones.d.ts.map +1 -0
- package/build/operations-v2/write/milestones.js +56 -0
- package/build/operations-v2/write/milestones.js.map +1 -0
- package/build/operations-v2/write/plans.d.ts +2 -0
- package/build/operations-v2/write/plans.d.ts.map +1 -0
- package/build/operations-v2/write/plans.js +55 -0
- package/build/operations-v2/write/plans.js.map +1 -0
- package/build/operations-v2/write/results.d.ts +2 -0
- package/build/operations-v2/write/results.d.ts.map +1 -0
- package/build/operations-v2/write/results.js +72 -0
- package/build/operations-v2/write/results.js.map +1 -0
- package/build/operations-v2/write/runs.d.ts +2 -0
- package/build/operations-v2/write/runs.d.ts.map +1 -0
- package/build/operations-v2/write/runs.js +84 -0
- package/build/operations-v2/write/runs.js.map +1 -0
- package/build/operations-v2/write/shared-steps.d.ts +2 -0
- package/build/operations-v2/write/shared-steps.d.ts.map +1 -0
- package/build/operations-v2/write/shared-steps.js +60 -0
- package/build/operations-v2/write/shared-steps.js.map +1 -0
- package/build/operations-v2/write/suites.d.ts +2 -0
- package/build/operations-v2/write/suites.d.ts.map +1 -0
- package/build/operations-v2/write/suites.js +63 -0
- package/build/operations-v2/write/suites.js.map +1 -0
- package/build/prompts/index.d.ts +31 -0
- package/build/prompts/index.d.ts.map +1 -0
- package/build/prompts/index.js +229 -0
- package/build/prompts/index.js.map +1 -0
- package/build/transports/sse.d.ts.map +1 -1
- package/build/transports/sse.js +6 -0
- package/build/transports/sse.js.map +1 -1
- package/build/transports/streamableHttp.d.ts +6 -1
- package/build/transports/streamableHttp.d.ts.map +1 -1
- package/build/transports/streamableHttp.js +128 -16
- package/build/transports/streamableHttp.js.map +1 -1
- package/build/utils/auth-context.d.ts +8 -0
- package/build/utils/auth-context.d.ts.map +1 -1
- package/build/utils/auth-context.js +18 -0
- package/build/utils/auth-context.js.map +1 -1
- package/build/utils/case-enums.d.ts +5 -3
- package/build/utils/case-enums.d.ts.map +1 -1
- package/build/utils/case-enums.js +77 -59
- package/build/utils/case-enums.js.map +1 -1
- package/build/utils/output-schemas.d.ts +16 -0
- package/build/utils/output-schemas.d.ts.map +1 -0
- package/build/utils/output-schemas.js +82 -0
- package/build/utils/output-schemas.js.map +1 -0
- package/build/utils/registry.d.ts +42 -9
- package/build/utils/registry.d.ts.map +1 -1
- package/build/utils/registry.js +64 -11
- package/build/utils/registry.js.map +1 -1
- package/build/utils/response-shape.d.ts +23 -0
- package/build/utils/response-shape.d.ts.map +1 -0
- package/build/utils/response-shape.js +73 -0
- package/build/utils/response-shape.js.map +1 -0
- package/build/utils/rich-response.d.ts +58 -0
- package/build/utils/rich-response.d.ts.map +1 -0
- package/build/utils/rich-response.js +93 -0
- package/build/utils/rich-response.js.map +1 -0
- package/build/utils/server-context.d.ts +65 -0
- package/build/utils/server-context.d.ts.map +1 -0
- package/build/utils/server-context.js +67 -0
- package/build/utils/server-context.js.map +1 -0
- package/build/version.d.ts +1 -1
- package/build/version.js +1 -1
- package/docs/connect.md +81 -0
- package/docs/migration.md +351 -0
- package/docs/self-run.md +270 -0
- package/docs/tools.md +111 -0
- package/docs/troubleshooting.md +144 -0
- package/package.json +11 -2
- package/server.json +8 -2
- package/build/operations/attachments.d.ts +0 -8
- package/build/operations/attachments.d.ts.map +0 -1
- package/build/operations/attachments.js +0 -146
- package/build/operations/attachments.js.map +0 -1
- package/build/operations/authors.d.ts +0 -8
- package/build/operations/authors.d.ts.map +0 -1
- package/build/operations/authors.js +0 -70
- package/build/operations/authors.js.map +0 -1
- package/build/operations/cases.d.ts +0 -8
- package/build/operations/cases.d.ts.map +0 -1
- package/build/operations/cases.js +0 -370
- package/build/operations/cases.js.map +0 -1
- package/build/operations/configurations.d.ts +0 -10
- package/build/operations/configurations.d.ts.map +0 -1
- package/build/operations/configurations.js +0 -125
- package/build/operations/configurations.js.map +0 -1
- package/build/operations/custom-fields.d.ts +0 -8
- package/build/operations/custom-fields.d.ts.map +0 -1
- package/build/operations/custom-fields.js +0 -172
- package/build/operations/custom-fields.js.map +0 -1
- package/build/operations/defects.d.ts +0 -8
- package/build/operations/defects.d.ts.map +0 -1
- package/build/operations/defects.js +0 -256
- package/build/operations/defects.js.map +0 -1
- package/build/operations/environments.d.ts +0 -8
- package/build/operations/environments.d.ts.map +0 -1
- package/build/operations/environments.js +0 -154
- package/build/operations/environments.js.map +0 -1
- package/build/operations/milestones.d.ts +0 -8
- package/build/operations/milestones.d.ts.map +0 -1
- package/build/operations/milestones.js +0 -155
- package/build/operations/milestones.js.map +0 -1
- package/build/operations/plans.d.ts +0 -8
- package/build/operations/plans.d.ts.map +0 -1
- package/build/operations/plans.js +0 -158
- package/build/operations/plans.js.map +0 -1
- package/build/operations/projects.d.ts +0 -8
- package/build/operations/projects.d.ts.map +0 -1
- package/build/operations/projects.js +0 -192
- package/build/operations/projects.js.map +0 -1
- package/build/operations/results.d.ts +0 -8
- package/build/operations/results.d.ts.map +0 -1
- package/build/operations/results.js +0 -214
- package/build/operations/results.js.map +0 -1
- package/build/operations/runs.d.ts +0 -8
- package/build/operations/runs.d.ts.map +0 -1
- package/build/operations/runs.js +0 -224
- package/build/operations/runs.js.map +0 -1
- package/build/operations/search.d.ts.map +0 -1
- package/build/operations/search.js.map +0 -1
- package/build/operations/shared-parameters.d.ts +0 -10
- package/build/operations/shared-parameters.d.ts.map +0 -1
- package/build/operations/shared-parameters.js +0 -93
- package/build/operations/shared-parameters.js.map +0 -1
- package/build/operations/shared-steps.d.ts +0 -8
- package/build/operations/shared-steps.d.ts.map +0 -1
- package/build/operations/shared-steps.js +0 -160
- package/build/operations/shared-steps.js.map +0 -1
- package/build/operations/suites.d.ts +0 -8
- package/build/operations/suites.d.ts.map +0 -1
- package/build/operations/suites.js +0 -169
- package/build/operations/suites.js.map +0 -1
- package/build/operations/system-fields.d.ts +0 -10
- package/build/operations/system-fields.d.ts.map +0 -1
- package/build/operations/system-fields.js +0 -47
- package/build/operations/system-fields.js.map +0 -1
- package/build/operations/users.d.ts +0 -10
- package/build/operations/users.d.ts.map +0 -1
- package/build/operations/users.js +0 -78
- package/build/operations/users.js.map +0 -1
package/docs/tools.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Tool Reference
|
|
2
|
+
|
|
3
|
+
The Qase MCP Server exposes **32 tools** across 6 groups: Read, QQL, Write, Composite, Escape hatch, and Meta.
|
|
4
|
+
|
|
5
|
+
## Discovery model
|
|
6
|
+
|
|
7
|
+
To keep context-token usage low, tools are split into two visibility tiers:
|
|
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).
|
|
11
|
+
|
|
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
|
+
|
|
14
|
+
Every tool's schema uses "label or numeric ID" strings for Qase's configurable enum fields (`priority`, `severity`, `type`, `layer`, `behavior`, `status`, `automation` on cases); the server resolves labels against the workspace's actual system-field configuration at call time. See [Case enum values](#case-enum-values) below.
|
|
15
|
+
|
|
16
|
+
## Read tools
|
|
17
|
+
|
|
18
|
+
| Tool | Description | Key params | Visibility |
|
|
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 |
|
|
22
|
+
|
|
23
|
+
## QQL tools
|
|
24
|
+
|
|
25
|
+
| Tool | Description | Key params | Visibility |
|
|
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 |
|
|
29
|
+
|
|
30
|
+
## Write tools
|
|
31
|
+
|
|
32
|
+
<details>
|
|
33
|
+
<summary>Write tools (23)</summary>
|
|
34
|
+
|
|
35
|
+
| Tool | Description | Key params | Visibility |
|
|
36
|
+
| --- | --- | --- | --- |
|
|
37
|
+
| `qase_case_upsert` | Create or update a test case. If `id` is provided, updates the existing case; if omitted, creates a new one. Enum fields (priority, severity, type, etc.) accept both labels ("high", "blocker") and numeric IDs — the server normalizes automatically. | `code`, `id` (optional), `title` (1-255 chars), `description`, `preconditions`, `postconditions`, `severity`, `priority`, `type`, `layer`, `behavior`, `automation`, `status` (all label-or-ID strings), `is_flaky`, `suite_id`, `milestone_id`, `steps` (array, supports nesting), `steps_type` (enum: classic, gherkin), `tags`, `attachments`, `custom_field` | core |
|
|
38
|
+
| `qase_case_bulk_create` | Create up to 100 test cases in a single request. Use instead of calling `qase_case_upsert` repeatedly when importing or generating several cases at once. Enum fields accept labels or numeric IDs. Creates only — use `qase_case_upsert` with an `id` to update. Returns the IDs of the created cases in submission order. | `code`, `cases` (array, 1-100 — same fields as `qase_case_upsert` without `id`) | discoverable |
|
|
39
|
+
| `qase_case_delete` | Delete a test case by project code and case ID. | `code`, `id` | discoverable |
|
|
40
|
+
| `qase_defect_upsert` | Create or update a defect. If `id` is provided, updates (including status changes and resolve). If omitted, creates a new defect. Set `status: "resolved"` to resolve an existing defect. | `code`, `id` (optional), `title` (1-255 chars), `actual_result`, `severity` (enum, see [below](#case-enum-values)), `status` (enum: open, in_progress, resolved, invalid), `tags`, `attachments`, `custom_field` | core |
|
|
41
|
+
| `qase_defect_delete` | Delete a defect by project code and defect ID. | `code`, `id` | discoverable |
|
|
42
|
+
| `qase_run_upsert` | Create or update a test run. If `id` is provided, updates; if omitted, creates. | `code`, `id` (optional), `title` (1-255 chars), `description`, `environment_id`, `milestone_id`, `plan_id`, `cases` (case ID array), `tags`, `is_autotest`, `start_time`/`end_time` (RFC3339), `custom_field` | core |
|
|
43
|
+
| `qase_run_complete` | Mark a test run as complete. | `code`, `id` | discoverable |
|
|
44
|
+
| `qase_run_delete` | Delete a test run. | `code`, `id` | discoverable |
|
|
45
|
+
| `qase_result_record` | Record one or more test results into a run. A single entry uses the single-result API, multiple entries use bulk. Each result must include a status; `case_id` is recommended. | `code`, `run_id`, `results` (array, min 1) — each result: `case_id` (optional), `status` (enum: passed, failed, blocked, skipped, invalid), `comment`, `stacktrace`, `time_ms`, `defect` (bool), `steps` (array with `position`, `status`, `comment`, `attachments`), `attachments`, `custom_field` | core |
|
|
46
|
+
| `qase_result_delete` | Delete a test result by run ID and result hash. | `code`, `run_id`, `hash` | discoverable |
|
|
47
|
+
| `qase_suite_upsert` | Create or update a test suite. If `id` is provided, updates the existing suite; if omitted, creates a new one. | `code`, `id` (optional), `title` (1-255 chars), `description`, `preconditions`, `parent_id` (for nesting) | discoverable |
|
|
48
|
+
| `qase_suite_delete` | Delete a test suite. If `delete_cases` is true, removes all cases in the suite; if false or omitted, cases are moved to the parent suite. | `code`, `id`, `delete_cases` (optional bool) | discoverable |
|
|
49
|
+
| `qase_milestone_upsert` | Create or update a milestone. If `id` is provided, updates the existing milestone; if omitted, creates a new one. | `code`, `id` (optional), `title` (1-255 chars), `description`, `status` (enum: active, completed), `due_date` (Unix timestamp) | discoverable |
|
|
50
|
+
| `qase_milestone_delete` | Delete a milestone by project code and milestone ID. | `code`, `id` | discoverable |
|
|
51
|
+
| `qase_plan_upsert` | Create or update a test plan. If `id` is provided, updates the existing plan; if omitted, creates a new one. | `code`, `id` (optional), `title` (1-255 chars), `description`, `cases` (case ID array) | discoverable |
|
|
52
|
+
| `qase_plan_delete` | Delete a test plan by project code and plan ID. | `code`, `id` | discoverable |
|
|
53
|
+
| `qase_shared_step_upsert` | Create or update a shared step. If `hash` is provided, updates the existing shared step; if omitted, creates a new one. Shared steps are reusable steps included in multiple test cases. | `code`, `hash` (optional), `title` (1-255 chars), `steps` (array: `action`, `expected_result`, `data`, `attachments`) | discoverable |
|
|
54
|
+
| `qase_shared_step_delete` | Delete a shared step by project code and hash. | `code`, `hash` | discoverable |
|
|
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
|
+
| `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 |
|
|
58
|
+
| `qase_attachment_delete` | Delete an attachment by its hash. | `hash` | discoverable |
|
|
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
|
+
|
|
61
|
+
</details>
|
|
62
|
+
|
|
63
|
+
## Composite tools
|
|
64
|
+
|
|
65
|
+
Composite tools chain several underlying operations into one call, so an agent avoids multi-step round-trips for common workflows.
|
|
66
|
+
|
|
67
|
+
| Tool | Description | Key params | Visibility |
|
|
68
|
+
| --- | --- | --- | --- |
|
|
69
|
+
| `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 |
|
|
70
|
+
| `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 |
|
|
71
|
+
| `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 |
|
|
72
|
+
|
|
73
|
+
## Escape hatch
|
|
74
|
+
|
|
75
|
+
| Tool | Description | Key params | Visibility |
|
|
76
|
+
| --- | --- | --- | --- |
|
|
77
|
+
| `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 |
|
|
78
|
+
|
|
79
|
+
## Meta
|
|
80
|
+
|
|
81
|
+
| Tool | Description | Key params | Visibility |
|
|
82
|
+
| --- | --- | --- | --- |
|
|
83
|
+
| `qase_discover_tools` | Search for and activate additional Qase tools. By default, only core tools are visible. Use this to find tools for specific needs: deletions, milestone management, attachments, etc. Found tools are automatically activated and become available for use. | `query` (optional, matches tool name/description), `category` (optional enum: read, write, delete, composite, all), `activate` (optional bool, default true) | core |
|
|
84
|
+
|
|
85
|
+
## Case enum values
|
|
86
|
+
|
|
87
|
+
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.
|
|
88
|
+
|
|
89
|
+
The `automation` field is the one exception with a fixed, documented mapping (translated internally to the API's `isManual`/`isToBeAutomated` fields):
|
|
90
|
+
|
|
91
|
+
| Value | Meaning |
|
|
92
|
+
| --- | --- |
|
|
93
|
+
| `0` | Manual (not automated) |
|
|
94
|
+
| `1` | To be automated |
|
|
95
|
+
| `2` | Automated |
|
|
96
|
+
|
|
97
|
+
`priority` has a conventional (but still workspace-configurable) numeric mapping:
|
|
98
|
+
|
|
99
|
+
| Value | Meaning |
|
|
100
|
+
| --- | --- |
|
|
101
|
+
| `0` | Not set |
|
|
102
|
+
| `1` | High |
|
|
103
|
+
| `2` | Medium |
|
|
104
|
+
| `3` | Low |
|
|
105
|
+
|
|
106
|
+
Two tools use **fixed** (non-configurable) Zod enums instead of workspace system fields:
|
|
107
|
+
|
|
108
|
+
- **Defect `severity`** (`qase_defect_upsert`, `qase_triage_defect`): `undefined`, `blocker`, `critical`, `major`, `normal`, `minor`, `trivial`.
|
|
109
|
+
- **Defect `status`** (`qase_defect_upsert`): `open`, `in_progress`, `resolved`, `invalid`.
|
|
110
|
+
- **Result `status`** (`qase_result_record`, `qase_ci_report`): `passed`, `failed`, `blocked`, `skipped`, `invalid` (result *steps* use the same set minus `invalid`).
|
|
111
|
+
- **Milestone `status`** (`qase_milestone_upsert`): `active`, `completed`.
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
Issues are grouped by how you're connecting: the [hosted connector](connect.md) (OAuth, no local install) or a [self-run](self-run.md) server (your own `QASE_API_TOKEN`). If you're not sure which applies, most people using the hosted server at `https://mcp.qase.io/mcp` should look at the **Hosted Connector / OAuth** section first.
|
|
4
|
+
|
|
5
|
+
## Authentication Errors (Self-Run)
|
|
6
|
+
|
|
7
|
+
**Error**: `Authentication failed: Please check your QASE_API_TOKEN`
|
|
8
|
+
|
|
9
|
+
This means the server is running locally (self-run) and rejected the token it was given.
|
|
10
|
+
|
|
11
|
+
**Solution**:
|
|
12
|
+
1. Verify your API token is correct: https://app.qase.io/user/api/token
|
|
13
|
+
2. Ensure `QASE_API_TOKEN` is set in your environment or MCP client config's `env` section
|
|
14
|
+
3. Check for extra spaces or stray quotes around the token value
|
|
15
|
+
4. If you're on the hosted connector instead (no `QASE_API_TOKEN` involved), see [Hosted Connector / OAuth](#hosted-connector--oauth) below
|
|
16
|
+
|
|
17
|
+
## Hosted Connector / OAuth
|
|
18
|
+
|
|
19
|
+
These apply when connecting to the Qase-hosted server (`https://mcp.qase.io/mcp`) — see [Connect to the hosted Qase MCP](connect.md). There's no `QASE_API_TOKEN` here; authentication is a browser-based OAuth sign-in to your Qase account.
|
|
20
|
+
|
|
21
|
+
### Access denied / Enterprise plan required
|
|
22
|
+
|
|
23
|
+
The hosted Qase MCP is available on the **Enterprise** plan in Qase. If your workspace is on another plan, requests are rejected with an access/plan error — the connector may sign in but tool calls fail with a plan-related message.
|
|
24
|
+
|
|
25
|
+
**Solution**: upgrade to the Enterprise plan, or [run the server yourself](self-run.md) with your own `QASE_API_TOKEN` (works on any plan).
|
|
26
|
+
|
|
27
|
+
### Connector doesn't appear, or won't connect
|
|
28
|
+
|
|
29
|
+
**Solution**:
|
|
30
|
+
1. Confirm the server URL is exactly `https://mcp.qase.io/mcp` — no trailing slash variations, no surrounding quotes (see the clean-URL footgun below)
|
|
31
|
+
2. Confirm your MCP client supports remote (HTTP) servers with OAuth 2.1 — older clients or stdio-only integrations can't connect to a hosted URL
|
|
32
|
+
3. Restart your MCP client completely (close and reopen) after adding the server
|
|
33
|
+
4. Check that your network/firewall allows outbound HTTPS to `mcp.qase.io`
|
|
34
|
+
|
|
35
|
+
### "Auth required" or empty tool list after connecting
|
|
36
|
+
|
|
37
|
+
If you completed the browser sign-in but the client still reports the connector needs authorization, or shows zero tools:
|
|
38
|
+
|
|
39
|
+
**Solution**:
|
|
40
|
+
1. Make sure you actually completed the sign-in flow in the browser tab/window it opened — some clients silently fail if that tab is closed early
|
|
41
|
+
2. Try disconnecting and reconnecting the connector (not just refreshing the client)
|
|
42
|
+
3. If reconnecting doesn't help, follow the full remove-and-re-add steps below — a stale or partially-completed OAuth session is a common cause
|
|
43
|
+
4. Confirm you're signed in to the correct Qase account/workspace in your browser — if you have multiple Qase sessions, the wrong one may be active
|
|
44
|
+
|
|
45
|
+
### Clean-URL footgun: stray quote or `%22` breaks OAuth
|
|
46
|
+
|
|
47
|
+
A very common cause of persistent auth failures: the server URL got saved with an extra quote character around it, e.g. `"https://mcp.qase.io/mcp"` or its URL-encoded form `https://mcp.qase.io/mcp%22`. This can happen from copy-pasting a URL out of JSON, a table, or a chat message that included the quotes.
|
|
48
|
+
|
|
49
|
+
That stray character poisons the OAuth callback — it changes the client's registered redirect/resource identifiers, so the authorization server and the client end up disagreeing about the URL, and sign-in fails (or appears to succeed but leaves an empty tool list).
|
|
50
|
+
|
|
51
|
+
**This is not fixable by editing the URL in place.** Once a client has registered or cached an OAuth session against the bad URL, editing the field to remove the quote isn't enough — the client may still replay the old (poisoned) auth request from its cache.
|
|
52
|
+
|
|
53
|
+
**Solution**:
|
|
54
|
+
1. Fully **remove** the server entry from your MCP client (don't just edit it)
|
|
55
|
+
2. Re-**add** it as a new entry
|
|
56
|
+
3. Type the URL by hand: `https://mcp.qase.io/mcp` — no surrounding quotes, no extra characters
|
|
57
|
+
4. Complete the browser sign-in again from this fresh entry
|
|
58
|
+
|
|
59
|
+
### Browser sign-in is required
|
|
60
|
+
|
|
61
|
+
The hosted connector authenticates via OAuth in your default browser — there's no token to paste in. If your MCP client is running in an environment without a browser available (e.g. certain headless or remote setups), the sign-in step can't complete. Use a client/environment that can open a browser, or fall back to the [self-run guide](self-run.md) with your own `QASE_API_TOKEN`.
|
|
62
|
+
|
|
63
|
+
### Session expires after 7 days of inactivity
|
|
64
|
+
|
|
65
|
+
An active hosted-connector session stays valid for **7 days**. As long as you use the connector within any 7-day window, it keeps working with no re-authorization. If a full week passes with no activity, the session expires and you'll be asked to sign in again.
|
|
66
|
+
|
|
67
|
+
**Solution**: when the client reports that authorization is needed, re-run the sign-in flow — it opens your browser; complete the Qase login and the connector resumes. No need to remove and re-add the server.
|
|
68
|
+
|
|
69
|
+
## Connection Errors
|
|
70
|
+
|
|
71
|
+
**Error**: `Network error` or `ECONNREFUSED`
|
|
72
|
+
|
|
73
|
+
**Solution**:
|
|
74
|
+
1. Check your internet connection
|
|
75
|
+
2. Verify the API domain is correct (especially for enterprise customers)
|
|
76
|
+
3. Check if Qase is accessible: https://api.qase.io/v1/
|
|
77
|
+
|
|
78
|
+
## SSL Certificate Errors
|
|
79
|
+
|
|
80
|
+
**Error**: `unable to get local issuer certificate`
|
|
81
|
+
|
|
82
|
+
This error typically occurs in corporate environments with:
|
|
83
|
+
- SSL-intercepting proxy servers
|
|
84
|
+
- Self-signed certificates
|
|
85
|
+
- Internal Certificate Authorities (CA)
|
|
86
|
+
|
|
87
|
+
**Solution**: Add the `NODE_EXTRA_CA_CERTS` environment variable pointing to your CA certificate file:
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"mcpServers": {
|
|
92
|
+
"qase": {
|
|
93
|
+
"command": "npx",
|
|
94
|
+
"args": ["-y", "@qase/mcp-server"],
|
|
95
|
+
"env": {
|
|
96
|
+
"QASE_API_TOKEN": "your_api_token_here",
|
|
97
|
+
"NODE_EXTRA_CA_CERTS": "/path/to/your/certificate.pem"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
To find your certificate:
|
|
105
|
+
- **Corporate environments**: Contact your IT department for the CA certificate
|
|
106
|
+
- **macOS**: Export from Keychain Access (System Roots → your CA → Export as .pem)
|
|
107
|
+
- **Windows**: Export from Certificate Manager (certmgr.msc)
|
|
108
|
+
- **Linux**: Usually in `/etc/ssl/certs/` or `/etc/pki/tls/certs/`
|
|
109
|
+
|
|
110
|
+
## Custom Domain Issues
|
|
111
|
+
|
|
112
|
+
**Error**: `Invalid domain` or connection errors with custom domain
|
|
113
|
+
|
|
114
|
+
**Solution**:
|
|
115
|
+
1. Ensure `QASE_API_DOMAIN` is set to just the domain (e.g., `api.company.qase.io`)
|
|
116
|
+
2. Don't include `https://` or `/v1` in the domain
|
|
117
|
+
3. Verify with your Qase administrator
|
|
118
|
+
|
|
119
|
+
## No Tools Showing in MCP Client
|
|
120
|
+
|
|
121
|
+
**Error**: MCP client shows "no tools, prompts or resources" or 0 tools available
|
|
122
|
+
|
|
123
|
+
**Solution**:
|
|
124
|
+
1. Verify your MCP configuration has the correct command and arguments (self-run) or the correct URL (hosted)
|
|
125
|
+
2. For self-run: check that `QASE_API_TOKEN` is set in the `env` section
|
|
126
|
+
3. For the hosted connector: check the [Hosted Connector / OAuth](#hosted-connector--oauth) section above, especially the clean-URL footgun
|
|
127
|
+
4. Restart your MCP client completely (close and reopen)
|
|
128
|
+
5. Check the MCP client logs for connection errors
|
|
129
|
+
6. For self-run from source, verify the server is built: `npm run build`
|
|
130
|
+
|
|
131
|
+
## Tool Not Found
|
|
132
|
+
|
|
133
|
+
**Error**: `Unknown tool: tool_name`
|
|
134
|
+
|
|
135
|
+
**Solution**:
|
|
136
|
+
1. Ensure you're using the latest version: `npm update -g @qase/mcp-server` (self-run) — the hosted connector always runs the latest version
|
|
137
|
+
2. If upgrading from v1, tool names have changed — see [docs/migration.md](migration.md)
|
|
138
|
+
3. Restart your MCP client after updating
|
|
139
|
+
|
|
140
|
+
## Still stuck?
|
|
141
|
+
|
|
142
|
+
- **Documentation**: https://docs.qase.io/en/articles/14984302-qase-mcp-server
|
|
143
|
+
- **Email**: support@qase.io
|
|
144
|
+
- **GitHub Issues**: https://github.com/qase-tms/qase-mcp-server/issues
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qase/mcp-server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"mcpName": "io.qase/mcp-server",
|
|
5
5
|
"description": "Official MCP server for Qase Test Management Platform",
|
|
6
6
|
"type": "module",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"test": "jest",
|
|
55
55
|
"test:watch": "jest --watch",
|
|
56
56
|
"test:coverage": "jest --coverage",
|
|
57
|
+
"test:integration": "REDIS_TEST_URL=${REDIS_TEST_URL:-redis://localhost:6379} jest src/cache/layered.integration.test.ts",
|
|
57
58
|
"inspector": "npx @modelcontextprotocol/inspector node build/index.js",
|
|
58
59
|
"start": "node build/index.js",
|
|
59
60
|
"start:stdio": "node build/index.js --transport stdio",
|
|
@@ -70,8 +71,10 @@
|
|
|
70
71
|
"axios": "^1.13.5",
|
|
71
72
|
"express": "^4.18.2",
|
|
72
73
|
"form-data": "^4.0.5",
|
|
74
|
+
"jose": "^6.1.3",
|
|
75
|
+
"lru-cache": "^11.3.5",
|
|
73
76
|
"neverthrow": "^8.2.0",
|
|
74
|
-
"npm": "^
|
|
77
|
+
"npm": "^12.0.2",
|
|
75
78
|
"qase-api-client": "^1.1.10",
|
|
76
79
|
"zod": "^3.24.2",
|
|
77
80
|
"zod-to-json-schema": "^3.24.3"
|
|
@@ -80,8 +83,10 @@
|
|
|
80
83
|
"@types/express": "^4.17.21",
|
|
81
84
|
"@types/jest": "^29.5.12",
|
|
82
85
|
"@types/node": "^20.11.24",
|
|
86
|
+
"@types/supertest": "^6.0.3",
|
|
83
87
|
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
|
84
88
|
"@typescript-eslint/parser": "^8.26.1",
|
|
89
|
+
"axios-mock-adapter": "^2.1.0",
|
|
85
90
|
"eslint": "^9.22.0",
|
|
86
91
|
"eslint-config-prettier": "^10.1.1",
|
|
87
92
|
"eslint-plugin-prettier": "^5.2.3",
|
|
@@ -89,10 +94,14 @@
|
|
|
89
94
|
"jest": "^29.7.0",
|
|
90
95
|
"lint-staged": "^16.2.3",
|
|
91
96
|
"prettier": "^3.4.2",
|
|
97
|
+
"supertest": "^7.2.2",
|
|
92
98
|
"ts-jest": "^29.1.2",
|
|
93
99
|
"typescript": "^5.3.3"
|
|
94
100
|
},
|
|
95
101
|
"overrides": {
|
|
96
102
|
"js-yaml@3": "3.14.2"
|
|
103
|
+
},
|
|
104
|
+
"optionalDependencies": {
|
|
105
|
+
"ioredis": "^5.10.1"
|
|
97
106
|
}
|
|
98
107
|
}
|
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": "
|
|
11
|
+
"version": "2.0.1",
|
|
12
12
|
"packages": [
|
|
13
13
|
{
|
|
14
14
|
"registryType": "npm",
|
|
15
15
|
"identifier": "@qase/mcp-server",
|
|
16
|
-
"version": "
|
|
16
|
+
"version": "2.0.1",
|
|
17
17
|
"transport": {
|
|
18
18
|
"type": "stdio"
|
|
19
19
|
},
|
|
@@ -33,6 +33,12 @@
|
|
|
33
33
|
]
|
|
34
34
|
}
|
|
35
35
|
],
|
|
36
|
+
"remotes": [
|
|
37
|
+
{
|
|
38
|
+
"type": "streamable-http",
|
|
39
|
+
"url": "https://mcp.qase.io/mcp"
|
|
40
|
+
}
|
|
41
|
+
],
|
|
36
42
|
"_meta": {
|
|
37
43
|
"io.modelcontextprotocol.registry/publisher-provided": {
|
|
38
44
|
"privacyPolicyUrl": "https://qase.io/privacy"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../../src/operations/attachments.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Attachments Operations
|
|
3
|
-
*
|
|
4
|
-
* Implements all MCP tools for managing attachments in Qase.
|
|
5
|
-
* Attachments are files associated with test cases, steps, and results.
|
|
6
|
-
*/
|
|
7
|
-
import { z } from 'zod';
|
|
8
|
-
import { createReadStream, existsSync } from 'fs';
|
|
9
|
-
import { getApiClient } from '../client/index.js';
|
|
10
|
-
import { toolRegistry, ReadAnnotation, CreateAnnotation, DeleteAnnotation, } from '../utils/registry.js';
|
|
11
|
-
import { toResultAsync, createToolError } from '../utils/errors.js';
|
|
12
|
-
import { ProjectCodeSchema, HashSchema } from '../utils/validation.js';
|
|
13
|
-
// ============================================================================
|
|
14
|
-
// SCHEMAS
|
|
15
|
-
// ============================================================================
|
|
16
|
-
/**
|
|
17
|
-
* Schema for listing attachments
|
|
18
|
-
*/
|
|
19
|
-
const ListAttachmentsSchema = z.object({
|
|
20
|
-
limit: z
|
|
21
|
-
.number()
|
|
22
|
-
.int()
|
|
23
|
-
.positive()
|
|
24
|
-
.max(100)
|
|
25
|
-
.optional()
|
|
26
|
-
.default(10)
|
|
27
|
-
.describe('Maximum number of items (default: 10, max: 100)'),
|
|
28
|
-
offset: z.number().int().nonnegative().optional().describe('Number of items to skip'),
|
|
29
|
-
});
|
|
30
|
-
/**
|
|
31
|
-
* Schema for getting a specific attachment
|
|
32
|
-
*/
|
|
33
|
-
const GetAttachmentSchema = z.object({
|
|
34
|
-
hash: HashSchema.describe('Attachment hash identifier'),
|
|
35
|
-
});
|
|
36
|
-
/**
|
|
37
|
-
* Schema for uploading an attachment
|
|
38
|
-
*/
|
|
39
|
-
const UploadAttachmentSchema = z.object({
|
|
40
|
-
code: ProjectCodeSchema.describe('Project code'),
|
|
41
|
-
file: z.string().describe('File content as base64 encoded string or absolute file path'),
|
|
42
|
-
filename: z.string().describe('Original filename with extension'),
|
|
43
|
-
});
|
|
44
|
-
/**
|
|
45
|
-
* Schema for deleting an attachment
|
|
46
|
-
*/
|
|
47
|
-
const DeleteAttachmentSchema = z.object({
|
|
48
|
-
hash: HashSchema.describe('Attachment hash identifier'),
|
|
49
|
-
});
|
|
50
|
-
// ============================================================================
|
|
51
|
-
// HANDLERS
|
|
52
|
-
// ============================================================================
|
|
53
|
-
/**
|
|
54
|
-
* List all attachments
|
|
55
|
-
*/
|
|
56
|
-
async function listAttachments(args) {
|
|
57
|
-
const client = getApiClient();
|
|
58
|
-
const { limit, offset } = args;
|
|
59
|
-
const result = await toResultAsync(client.attachments.getAttachments(limit, offset));
|
|
60
|
-
return result.match((response) => response.data.result, (error) => {
|
|
61
|
-
throw createToolError(error, 'attachment operation');
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Get a specific attachment by hash
|
|
66
|
-
*/
|
|
67
|
-
async function getAttachment(args) {
|
|
68
|
-
const client = getApiClient();
|
|
69
|
-
const { hash } = args;
|
|
70
|
-
const result = await toResultAsync(client.attachments.getAttachment(hash));
|
|
71
|
-
return result.match((response) => response.data.result, (error) => {
|
|
72
|
-
throw createToolError(error, 'attachment operation');
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Prepare file data for upload.
|
|
77
|
-
* Accepts a base64-encoded string or an absolute file path.
|
|
78
|
-
* Returns an object compatible with the SDK's FormData append: { name, value }.
|
|
79
|
-
*/
|
|
80
|
-
function prepareFileData(file, filename) {
|
|
81
|
-
// If the string looks like a file path and exists on disk, stream it
|
|
82
|
-
if (file.startsWith('/') && existsSync(file)) {
|
|
83
|
-
return { name: filename, value: createReadStream(file) };
|
|
84
|
-
}
|
|
85
|
-
// Otherwise treat it as base64 content
|
|
86
|
-
const isBase64 = /^[A-Za-z0-9+/=\s]+$/.test(file);
|
|
87
|
-
return {
|
|
88
|
-
name: filename,
|
|
89
|
-
value: Buffer.from(file, isBase64 ? 'base64' : undefined),
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Upload a new attachment
|
|
94
|
-
*/
|
|
95
|
-
async function uploadAttachment(args) {
|
|
96
|
-
const client = getApiClient();
|
|
97
|
-
const { code, file, filename } = args;
|
|
98
|
-
const fileData = prepareFileData(file, filename);
|
|
99
|
-
const result = await toResultAsync(client.attachments.uploadAttachment(code, [fileData]));
|
|
100
|
-
return result.match((response) => response.data.result, (error) => {
|
|
101
|
-
throw createToolError(error, 'attachment operation');
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Delete an attachment
|
|
106
|
-
*/
|
|
107
|
-
async function deleteAttachment(args) {
|
|
108
|
-
const client = getApiClient();
|
|
109
|
-
const { hash } = args;
|
|
110
|
-
const result = await toResultAsync(client.attachments.deleteAttachment(hash));
|
|
111
|
-
return result.match((_response) => ({ success: true, hash }), (error) => {
|
|
112
|
-
throw createToolError(error, 'attachment operation');
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
// ============================================================================
|
|
116
|
-
// TOOL REGISTRATION
|
|
117
|
-
// ============================================================================
|
|
118
|
-
toolRegistry.register({
|
|
119
|
-
name: 'list_attachments',
|
|
120
|
-
description: 'Get all attachments with optional pagination',
|
|
121
|
-
schema: ListAttachmentsSchema,
|
|
122
|
-
handler: listAttachments,
|
|
123
|
-
annotations: ReadAnnotation,
|
|
124
|
-
});
|
|
125
|
-
toolRegistry.register({
|
|
126
|
-
name: 'get_attachment',
|
|
127
|
-
description: 'Get a specific attachment by hash, including download URL',
|
|
128
|
-
schema: GetAttachmentSchema,
|
|
129
|
-
handler: getAttachment,
|
|
130
|
-
annotations: ReadAnnotation,
|
|
131
|
-
});
|
|
132
|
-
toolRegistry.register({
|
|
133
|
-
name: 'upload_attachment',
|
|
134
|
-
description: 'Upload a new attachment (provide file as base64 encoded string)',
|
|
135
|
-
schema: UploadAttachmentSchema,
|
|
136
|
-
handler: uploadAttachment,
|
|
137
|
-
annotations: CreateAnnotation,
|
|
138
|
-
});
|
|
139
|
-
toolRegistry.register({
|
|
140
|
-
name: 'delete_attachment',
|
|
141
|
-
description: 'Delete an attachment by hash',
|
|
142
|
-
schema: DeleteAttachmentSchema,
|
|
143
|
-
handler: deleteAttachment,
|
|
144
|
-
annotations: DeleteAnnotation,
|
|
145
|
-
});
|
|
146
|
-
//# sourceMappingURL=attachments.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../src/operations/attachments.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"authors.d.ts","sourceRoot":"","sources":["../../src/operations/authors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Authors Operations
|
|
3
|
-
*
|
|
4
|
-
* Implements all MCP tools for managing test case authors in Qase.
|
|
5
|
-
* Authors are users who have created test cases.
|
|
6
|
-
*/
|
|
7
|
-
import { z } from 'zod';
|
|
8
|
-
import { getApiClient } from '../client/index.js';
|
|
9
|
-
import { toolRegistry, ReadAnnotation } from '../utils/registry.js';
|
|
10
|
-
import { toResultAsync, createToolError } from '../utils/errors.js';
|
|
11
|
-
import { IdSchema } from '../utils/validation.js';
|
|
12
|
-
// ============================================================================
|
|
13
|
-
// SCHEMAS
|
|
14
|
-
// ============================================================================
|
|
15
|
-
/**
|
|
16
|
-
* Schema for listing authors
|
|
17
|
-
*/
|
|
18
|
-
const ListAuthorsSchema = z.object({
|
|
19
|
-
limit: z.number().int().positive().max(100).optional().describe('Maximum number of items'),
|
|
20
|
-
offset: z.number().int().nonnegative().optional().describe('Number of items to skip'),
|
|
21
|
-
});
|
|
22
|
-
/**
|
|
23
|
-
* Schema for getting a specific author
|
|
24
|
-
*/
|
|
25
|
-
const GetAuthorSchema = z.object({
|
|
26
|
-
id: IdSchema,
|
|
27
|
-
});
|
|
28
|
-
// ============================================================================
|
|
29
|
-
// HANDLERS
|
|
30
|
-
// ============================================================================
|
|
31
|
-
/**
|
|
32
|
-
* List all authors
|
|
33
|
-
*/
|
|
34
|
-
async function listAuthors(args) {
|
|
35
|
-
const client = getApiClient();
|
|
36
|
-
const { limit, offset } = args;
|
|
37
|
-
const result = await toResultAsync(client.authors.getAuthors(undefined, undefined, limit, offset));
|
|
38
|
-
return result.match((response) => response.data.result, (error) => {
|
|
39
|
-
throw createToolError(error, 'author operation');
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Get a specific author
|
|
44
|
-
*/
|
|
45
|
-
async function getAuthor(args) {
|
|
46
|
-
const client = getApiClient();
|
|
47
|
-
const { id } = args;
|
|
48
|
-
const result = await toResultAsync(client.authors.getAuthor(id));
|
|
49
|
-
return result.match((response) => response.data.result, (error) => {
|
|
50
|
-
throw createToolError(error, 'author operation');
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
// ============================================================================
|
|
54
|
-
// TOOL REGISTRATION
|
|
55
|
-
// ============================================================================
|
|
56
|
-
toolRegistry.register({
|
|
57
|
-
name: 'list_authors',
|
|
58
|
-
description: 'Get all test case authors with optional pagination',
|
|
59
|
-
schema: ListAuthorsSchema,
|
|
60
|
-
handler: listAuthors,
|
|
61
|
-
annotations: ReadAnnotation,
|
|
62
|
-
});
|
|
63
|
-
toolRegistry.register({
|
|
64
|
-
name: 'get_author',
|
|
65
|
-
description: 'Get a specific author by ID',
|
|
66
|
-
schema: GetAuthorSchema,
|
|
67
|
-
handler: getAuthor,
|
|
68
|
-
annotations: ReadAnnotation,
|
|
69
|
-
});
|
|
70
|
-
//# sourceMappingURL=authors.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"authors.js","sourceRoot":"","sources":["../../src/operations/authors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E;;GAEG;AACH,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;IAC1F,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;CACtF,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,EAAE,EAAE,QAAQ;CACb,CAAC,CAAC;AAEH,+EAA+E;AAC/E,WAAW;AACX,+EAA+E;AAE/E;;GAEG;AACH,KAAK,UAAU,WAAW,CAAC,IAAuC;IAChE,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAE/B,MAAM,MAAM,GAAG,MAAM,aAAa,CAChC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,CAC/D,CAAC;IAEF,OAAO,MAAM,CAAC,KAAK,CACjB,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAClC,CAAC,KAAK,EAAE,EAAE;QACR,MAAM,eAAe,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;IACnD,CAAC,CACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,SAAS,CAAC,IAAqC;IAC5D,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC;IAEpB,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IAEjE,OAAO,MAAM,CAAC,KAAK,CACjB,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAClC,CAAC,KAAK,EAAE,EAAE;QACR,MAAM,eAAe,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;IACnD,CAAC,CACF,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E,YAAY,CAAC,QAAQ,CAAC;IACpB,IAAI,EAAE,cAAc;IACpB,WAAW,EAAE,oDAAoD;IACjE,MAAM,EAAE,iBAAiB;IACzB,OAAO,EAAE,WAAW;IACpB,WAAW,EAAE,cAAc;CAC5B,CAAC,CAAC;AAEH,YAAY,CAAC,QAAQ,CAAC;IACpB,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,6BAA6B;IAC1C,MAAM,EAAE,eAAe;IACvB,OAAO,EAAE,SAAS;IAClB,WAAW,EAAE,cAAc;CAC5B,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cases.d.ts","sourceRoot":"","sources":["../../src/operations/cases.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|