@qase/mcp-server 2.5.0 → 2.6.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.
- package/CHANGELOG.md +34 -0
- package/Dockerfile +5 -0
- package/README.md +3 -3
- package/build/operations-v2/composites/ci-report.js +7 -1
- package/build/operations-v2/composites/ci-report.js.map +1 -1
- package/build/operations-v2/composites/regression-run.js +14 -3
- package/build/operations-v2/composites/regression-run.js.map +1 -1
- package/build/operations-v2/composites/triage-defect.js +7 -3
- package/build/operations-v2/composites/triage-defect.js.map +1 -1
- package/build/operations-v2/escape/api.js +1 -0
- package/build/operations-v2/escape/api.js.map +1 -1
- package/build/operations-v2/meta/discover.js +12 -7
- package/build/operations-v2/meta/discover.js.map +1 -1
- package/build/operations-v2/qql/index.js +2 -0
- package/build/operations-v2/qql/index.js.map +1 -1
- package/build/operations-v2/read/get.js +1 -0
- package/build/operations-v2/read/get.js.map +1 -1
- package/build/operations-v2/read/project-context.js +1 -0
- package/build/operations-v2/read/project-context.js.map +1 -1
- package/build/operations-v2/write/attachments.js +2 -0
- package/build/operations-v2/write/attachments.js.map +1 -1
- package/build/operations-v2/write/case-fields.d.ts.map +1 -1
- package/build/operations-v2/write/case-fields.js +23 -9
- package/build/operations-v2/write/case-fields.js.map +1 -1
- package/build/operations-v2/write/cases-bulk.js +4 -1
- package/build/operations-v2/write/cases-bulk.js.map +1 -1
- package/build/operations-v2/write/cases.js +2 -0
- package/build/operations-v2/write/cases.js.map +1 -1
- package/build/operations-v2/write/custom-fields.js +2 -0
- package/build/operations-v2/write/custom-fields.js.map +1 -1
- package/build/operations-v2/write/defects.js +13 -4
- package/build/operations-v2/write/defects.js.map +1 -1
- package/build/operations-v2/write/environments.js +2 -0
- package/build/operations-v2/write/environments.js.map +1 -1
- package/build/operations-v2/write/external-issues.js +1 -0
- package/build/operations-v2/write/external-issues.js.map +1 -1
- package/build/operations-v2/write/milestones.js +2 -0
- package/build/operations-v2/write/milestones.js.map +1 -1
- package/build/operations-v2/write/plans.js +2 -0
- package/build/operations-v2/write/plans.js.map +1 -1
- package/build/operations-v2/write/projects.js +2 -0
- package/build/operations-v2/write/projects.js.map +1 -1
- package/build/operations-v2/write/results.js +2 -0
- package/build/operations-v2/write/results.js.map +1 -1
- package/build/operations-v2/write/reviews.js +5 -0
- package/build/operations-v2/write/reviews.js.map +1 -1
- package/build/operations-v2/write/runs.js +27 -7
- package/build/operations-v2/write/runs.js.map +1 -1
- package/build/operations-v2/write/shared-steps.js +2 -0
- package/build/operations-v2/write/shared-steps.js.map +1 -1
- package/build/operations-v2/write/suites.js +12 -3
- package/build/operations-v2/write/suites.js.map +1 -1
- package/build/prompts/index.d.ts +1 -0
- package/build/prompts/index.d.ts.map +1 -1
- package/build/prompts/index.js +6 -0
- package/build/prompts/index.js.map +1 -1
- package/build/server-instructions.d.ts +1 -1
- package/build/server-instructions.d.ts.map +1 -1
- package/build/server-instructions.js +3 -3
- package/build/server.d.ts.map +1 -1
- package/build/server.js +39 -5
- package/build/server.js.map +1 -1
- package/build/transports/json-parse-error.d.ts +12 -0
- package/build/transports/json-parse-error.d.ts.map +1 -0
- package/build/transports/json-parse-error.js +25 -0
- package/build/transports/json-parse-error.js.map +1 -0
- package/build/transports/sse.d.ts.map +1 -1
- package/build/transports/sse.js +2 -0
- package/build/transports/sse.js.map +1 -1
- package/build/transports/streamableHttp.d.ts.map +1 -1
- package/build/transports/streamableHttp.js +2 -0
- package/build/transports/streamableHttp.js.map +1 -1
- package/build/utils/registry.d.ts +20 -3
- package/build/utils/registry.d.ts.map +1 -1
- package/build/utils/registry.js +37 -6
- package/build/utils/registry.js.map +1 -1
- package/build/version.d.ts +1 -1
- package/build/version.js +1 -1
- package/docs/tools.md +10 -8
- package/docs/troubleshooting.md +12 -0
- package/package.json +1 -1
- package/server.json +2 -2
package/build/utils/registry.js
CHANGED
|
@@ -18,8 +18,16 @@ export class ToolRegistry {
|
|
|
18
18
|
handlers = new Map();
|
|
19
19
|
activeTools = new Set();
|
|
20
20
|
toolVisibility = new Map();
|
|
21
|
-
/**
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Listeners invoked when the active tool set changes (each wired to one
|
|
23
|
+
* Server's sendToolListChanged).
|
|
24
|
+
*
|
|
25
|
+
* A set rather than a single slot because the registry is a process-wide
|
|
26
|
+
* singleton while every HTTP session gets its own Server: with one slot each
|
|
27
|
+
* new session overwrote the previous one's callback, so only the newest
|
|
28
|
+
* session ever heard that discovery had activated a tool.
|
|
29
|
+
*/
|
|
30
|
+
toolsChangedListeners = new Set();
|
|
23
31
|
/**
|
|
24
32
|
* Register a new tool with the registry
|
|
25
33
|
*
|
|
@@ -29,6 +37,7 @@ export class ToolRegistry {
|
|
|
29
37
|
* ```typescript
|
|
30
38
|
* toolRegistry.register({
|
|
31
39
|
* name: 'list_projects',
|
|
40
|
+
* title: 'List projects',
|
|
32
41
|
* description: 'Get all projects',
|
|
33
42
|
* schema: z.object({ limit: z.number().optional() }),
|
|
34
43
|
* handler: async (args) => { ... },
|
|
@@ -37,7 +46,7 @@ export class ToolRegistry {
|
|
|
37
46
|
* ```
|
|
38
47
|
*/
|
|
39
48
|
register(definition) {
|
|
40
|
-
const { name, description, schema, handler, annotations, outputSchema } = definition;
|
|
49
|
+
const { name, title, description, schema, handler, annotations, outputSchema } = definition;
|
|
41
50
|
const visibility = definition.visibility ?? 'core';
|
|
42
51
|
// Convert Zod schema to JSON Schema for MCP protocol
|
|
43
52
|
// Using explicit type assertion to avoid TypeScript's deep type inference issues
|
|
@@ -70,6 +79,7 @@ export class ToolRegistry {
|
|
|
70
79
|
// Store tool definition
|
|
71
80
|
this.tools.set(name, {
|
|
72
81
|
name,
|
|
82
|
+
title,
|
|
73
83
|
description,
|
|
74
84
|
inputSchema,
|
|
75
85
|
...(annotations && { annotations }),
|
|
@@ -118,10 +128,21 @@ export class ToolRegistry {
|
|
|
118
128
|
return words.every((word) => haystack.includes(word));
|
|
119
129
|
});
|
|
120
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Subscribe to active-tool-set changes. Returns an unsubscribe function the
|
|
133
|
+
* caller must invoke when its session ends, or the listener — and the Server
|
|
134
|
+
* it closes over — outlives the connection.
|
|
135
|
+
*/
|
|
136
|
+
subscribeToolsChanged(listener) {
|
|
137
|
+
this.toolsChangedListeners.add(listener);
|
|
138
|
+
return () => {
|
|
139
|
+
this.toolsChangedListeners.delete(listener);
|
|
140
|
+
};
|
|
141
|
+
}
|
|
121
142
|
/**
|
|
122
143
|
* Activate tools by name, making them visible in getTools().
|
|
123
144
|
* Returns the list of newly activated tool names.
|
|
124
|
-
*
|
|
145
|
+
* Notifies every subscriber if any tools were activated.
|
|
125
146
|
*/
|
|
126
147
|
activateTools(names) {
|
|
127
148
|
const newlyActivated = [];
|
|
@@ -131,8 +152,17 @@ export class ToolRegistry {
|
|
|
131
152
|
newlyActivated.push(name);
|
|
132
153
|
}
|
|
133
154
|
}
|
|
134
|
-
if (newlyActivated.length > 0
|
|
135
|
-
this.
|
|
155
|
+
if (newlyActivated.length > 0) {
|
|
156
|
+
for (const listener of this.toolsChangedListeners) {
|
|
157
|
+
// One dead session's transport must not swallow the notification for
|
|
158
|
+
// every session subscribed after it.
|
|
159
|
+
try {
|
|
160
|
+
listener();
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
console.error('[Registry] Tool-list-changed listener failed:', err);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
136
166
|
}
|
|
137
167
|
return newlyActivated;
|
|
138
168
|
}
|
|
@@ -190,6 +220,7 @@ export class ToolRegistry {
|
|
|
190
220
|
this.handlers.clear();
|
|
191
221
|
this.activeTools.clear();
|
|
192
222
|
this.toolVisibility.clear();
|
|
223
|
+
this.toolsChangedListeners.clear();
|
|
193
224
|
}
|
|
194
225
|
}
|
|
195
226
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/utils/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/utils/registry.ts"],"names":[],"mappings":"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"}
|
package/build/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "2.
|
|
1
|
+
export declare const VERSION = "2.6.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/build/version.js
CHANGED
package/docs/tools.md
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
# Tool Reference
|
|
2
2
|
|
|
3
|
-
The Qase MCP Server exposes **
|
|
3
|
+
The Qase MCP Server exposes **41 tools** across 6 groups: Read (2), QQL (2), Write (32, 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 (
|
|
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 (
|
|
9
|
+
- **`core`** — always listed to the MCP client, no activation needed (17 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 (24 tools, mostly deletes, review operations, and secondary write operations).
|
|
11
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"`, `"
|
|
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"`, `"plan"`) to activate it first.
|
|
13
|
+
|
|
14
|
+
Activation makes the tool callable on the server immediately and the server announces it with `notifications/tools/list_changed`. A client that does not re-read `tools/list` on that notification will not offer the tool no matter how often discovery runs — it typically fails with something like `tools.<name> is not a function`. Nothing on the server side is broken there: use [`qase_api`](#escape-hatch) to reach the same endpoint, or ask for a client that supports the notification. Tools a core tool's own description recommends are never hidden, so this never blocks the main workflows.
|
|
13
15
|
|
|
14
16
|
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
17
|
|
|
@@ -35,16 +37,16 @@ Every tool's schema uses "label or numeric ID" strings for Qase's configurable e
|
|
|
35
37
|
| Tool | Description | Key params | Visibility |
|
|
36
38
|
| --- | --- | --- | --- |
|
|
37
39
|
| `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`, `is_flaky` (all label-or-ID strings; `is_flaky` is 0=No / 1=Yes and also accepts a boolean), `suite_id`, `milestone_id`, `steps` (array, supports nesting; a step may reference a shared step via `shared` — the shared step hash — instead of `action`), `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`, including `shared` step references) |
|
|
40
|
+
| `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`, including `shared` step references) | core |
|
|
39
41
|
| `qase_case_delete` | Delete a test case by project code and case ID. | `code`, `id` | discoverable |
|
|
40
42
|
| `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
43
|
| `qase_defect_delete` | Delete a defect by project code and defect ID. | `code`, `id` | discoverable |
|
|
42
44
|
| `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` |
|
|
45
|
+
| `qase_run_complete` | Mark a test run as complete. | `code`, `id` | core |
|
|
44
46
|
| `qase_run_delete` | Delete a test run. | `code`, `id` | discoverable |
|
|
45
47
|
| `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. **The bulk endpoint takes at most 200 results per request**, so a longer list is refused before anything is written — split it across consecutive calls. It is refused rather than split automatically because results are append-only: a batch that failed half way could not be unwound, and the natural retry would record the first 200 a second time and leave the run with a wrong pass rate. Use `qase_ci_report` for a finished run, which does split for you. | `code`, `run_id`, `results` (array, 1-200) — 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
48
|
| `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) |
|
|
49
|
+
| `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) | core |
|
|
48
50
|
| `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
51
|
| `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
52
|
| `qase_milestone_delete` | Delete a milestone by project code and milestone ID. | `code`, `id` | discoverable |
|
|
@@ -100,7 +102,7 @@ Composite tools chain several underlying operations into one call, so an agent a
|
|
|
100
102
|
|
|
101
103
|
| Tool | Description | Key params | Visibility |
|
|
102
104
|
| --- | --- | --- | --- |
|
|
103
|
-
| `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,
|
|
105
|
+
| `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, test plans, milestone management, case reviews, etc. Found tools are automatically activated and become available for use — the server announces the change with `notifications/tools/list_changed`, and clients that ignore that notification will not offer the tool until the session is reconnected. | `query` (optional, matches tool name/description), `category` (optional enum: read, write, delete, composite, all), `activate` (optional bool, default true) | core |
|
|
104
106
|
|
|
105
107
|
## Case enum values
|
|
106
108
|
|
package/docs/troubleshooting.md
CHANGED
|
@@ -177,6 +177,18 @@ Only `http` and `https` are recognised; any other value falls back to `https`, s
|
|
|
177
177
|
3. Approving, requesting changes, merging, and declining are **UI-only** — the public API has no endpoints for them, so no tool can perform them
|
|
178
178
|
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
|
|
179
179
|
|
|
180
|
+
## A discovered tool still isn't callable
|
|
181
|
+
|
|
182
|
+
**Symptom**: `qase_discover_tools` reports the tool as found and activated, but calling it fails inside the client — typically `TypeError: tools.mcp__qase__<tool_name> is not a function`, or the agent insisting the tool does not exist.
|
|
183
|
+
|
|
184
|
+
**Cause**: activation is a server-side state change, announced to the client with the `notifications/tools/list_changed` notification. Clients that build their tool list once when the session opens and never rebuild it on that notification keep dispatching against the list they cached at connect time, so the tool the server just switched on is missing from the client's own table. The server itself will run the tool fine — the call never reaches it.
|
|
185
|
+
|
|
186
|
+
**Solution**:
|
|
187
|
+
1. Update to 2.6.0 or later: the tools the server's own instructions and core descriptions recommend — `qase_case_bulk_create`, `qase_suite_upsert`, `qase_run_complete` — are now core and listed from the start, so the common workflows never depend on discovery (self-run: `npm update -g @qase/mcp-server`; the hosted connector always runs the latest version)
|
|
188
|
+
2. 2.6.0 also fixes notification delivery on the HTTP transports, where only the most recently opened session used to be notified — if several sessions or clients share one server process, older sessions previously never heard about an activation at all
|
|
189
|
+
3. For a tool that is still discoverable, start a new session (or reconnect) after activating it — the fresh `tools/list` includes it
|
|
190
|
+
4. As a last resort, call the same REST endpoint through `qase_api`, which is core and always listed
|
|
191
|
+
|
|
180
192
|
## Tool Not Found
|
|
181
193
|
|
|
182
194
|
**Error**: `Unknown tool: tool_name`
|
package/package.json
CHANGED
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.
|
|
11
|
+
"version": "2.6.0",
|
|
12
12
|
"packages": [
|
|
13
13
|
{
|
|
14
14
|
"registryType": "npm",
|
|
15
15
|
"identifier": "@qase/mcp-server",
|
|
16
|
-
"version": "2.
|
|
16
|
+
"version": "2.6.0",
|
|
17
17
|
"transport": {
|
|
18
18
|
"type": "stdio"
|
|
19
19
|
},
|