@qase/mcp-server 1.1.7 → 2.0.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 +25 -0
- package/README.md +75 -551
- 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 -61
- 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 +19 -0
- package/build/operations-v2/index.d.ts.map +1 -0
- package/build/operations-v2/index.js +25 -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 +76 -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 +91 -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/cases.d.ts +2 -0
- package/build/operations-v2/write/cases.d.ts.map +1 -0
- package/build/operations-v2/write/cases.js +121 -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/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 +78 -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 +109 -0
- package/docs/troubleshooting.md +144 -0
- package/package.json +12 -3
- 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 -338
- 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
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server Context
|
|
3
|
+
*
|
|
4
|
+
* Provides access to the MCP Server instance within tool handlers
|
|
5
|
+
* via AsyncLocalStorage, following the same pattern as auth-context.ts.
|
|
6
|
+
*
|
|
7
|
+
* This enables features that require server-level access (elicitation,
|
|
8
|
+
* tool list notifications) without passing the server through handler signatures.
|
|
9
|
+
*/
|
|
10
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
11
|
+
/**
|
|
12
|
+
* Per-request server storage.
|
|
13
|
+
* Holds the Server instance for the current request context.
|
|
14
|
+
*/
|
|
15
|
+
export const serverStorage = new AsyncLocalStorage();
|
|
16
|
+
/**
|
|
17
|
+
* Get the Server instance from the current async context.
|
|
18
|
+
* Returns undefined if called outside of a serverStorage.run() scope.
|
|
19
|
+
*/
|
|
20
|
+
export function getServer() {
|
|
21
|
+
return serverStorage.getStore();
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Ask the user to confirm a destructive action via MCP elicitation.
|
|
25
|
+
*
|
|
26
|
+
* Graceful degradation:
|
|
27
|
+
* - No server in context → proceed (return true)
|
|
28
|
+
* - Client doesn't support elicitation → proceed
|
|
29
|
+
* - elicitInput() throws → proceed (log error)
|
|
30
|
+
* - User declines or cancels → return false
|
|
31
|
+
*/
|
|
32
|
+
export async function confirmDestructiveAction(toolName, args) {
|
|
33
|
+
const server = getServer();
|
|
34
|
+
if (!server)
|
|
35
|
+
return true;
|
|
36
|
+
// Check if the client supports elicitation
|
|
37
|
+
const caps = server.getClientCapabilities();
|
|
38
|
+
if (!caps?.elicitation)
|
|
39
|
+
return true;
|
|
40
|
+
try {
|
|
41
|
+
const argsPreview = Object.entries(args)
|
|
42
|
+
.map(([k, v]) => ` ${k}: ${JSON.stringify(v)}`)
|
|
43
|
+
.join('\n');
|
|
44
|
+
const result = await server.elicitInput({
|
|
45
|
+
message: `Confirm destructive action: ${toolName}\n\n${argsPreview}`,
|
|
46
|
+
requestedSchema: {
|
|
47
|
+
type: 'object',
|
|
48
|
+
properties: {
|
|
49
|
+
confirm: {
|
|
50
|
+
type: 'boolean',
|
|
51
|
+
title: 'Confirm deletion',
|
|
52
|
+
description: 'This will permanently delete the resource. Proceed?',
|
|
53
|
+
default: false,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
required: ['confirm'],
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
return result.action === 'accept' && result.content?.confirm === true;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
// Elicitation failed — graceful degradation: proceed without confirmation
|
|
63
|
+
console.error('[Server] Elicitation failed, proceeding without confirmation:', error);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=server-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-context.js","sourceRoot":"","sources":["../../src/utils/server-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGhD;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,iBAAiB,EAAU,CAAC;AAE7D;;;GAGG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,aAAa,CAAC,QAAQ,EAAE,CAAC;AAClC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,QAAgB,EAChB,IAA6B;IAE7B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,2CAA2C;IAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAC;IAC5C,IAAI,CAAC,IAAI,EAAE,WAAW;QAAE,OAAO,IAAI,CAAC;IAEpC,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;aACrC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;aAC/C,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC;YACtC,OAAO,EAAE,+BAA+B,QAAQ,OAAO,WAAW,EAAE;YACpE,eAAe,EAAE;gBACf,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,OAAO,EAAE;wBACP,IAAI,EAAE,SAAS;wBACf,KAAK,EAAE,kBAAkB;wBACzB,WAAW,EAAE,qDAAqD;wBAClE,OAAO,EAAE,KAAK;qBACf;iBACF;gBACD,QAAQ,EAAE,CAAC,SAAS,CAAC;aACtB;SACF,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACxE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,0EAA0E;QAC1E,OAAO,CAAC,KAAK,CAAC,+DAA+D,EAAE,KAAK,CAAC,CAAC;QACtF,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/build/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "
|
|
1
|
+
export declare const VERSION = "2.0.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/build/version.js
CHANGED
package/docs/connect.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Connect to the hosted Qase MCP
|
|
2
|
+
|
|
3
|
+
The quickest way to use Qase — no install and no API token. Connect to the Qase-hosted MCP server at `https://mcp.qase.io/mcp` and sign in with your Qase account. Any MCP client that supports remote servers (OAuth 2.1) works; the client handles the OAuth flow for you — Claude, Cursor, Codex, and VS Code are shown below.
|
|
4
|
+
|
|
5
|
+
> **Note:** The hosted Qase MCP is available on the **Enterprise** plan in Qase. On other plans you'll be denied access when connecting — [run the server yourself](self-run.md) with your own API token instead.
|
|
6
|
+
|
|
7
|
+
Prefer to run the server yourself with your own `QASE_API_TOKEN`? See [Self-Run Guide (Local / stdio)](self-run.md).
|
|
8
|
+
|
|
9
|
+
## Claude
|
|
10
|
+
|
|
11
|
+
Qase publishes an official **Qase Test Management** connector in Claude's directory:
|
|
12
|
+
|
|
13
|
+
1. In Claude, open **Settings → Connectors** and find **Qase Test Management**.
|
|
14
|
+
2. Click **Connect** and complete the Qase sign-in when prompted.
|
|
15
|
+
|
|
16
|
+
## Cursor
|
|
17
|
+
|
|
18
|
+
Add the hosted server by URL in `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project):
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"mcpServers": {
|
|
23
|
+
"qase": {
|
|
24
|
+
"url": "https://mcp.qase.io/mcp"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Cursor opens your browser to sign in to Qase; the tools appear once you've authorized.
|
|
31
|
+
|
|
32
|
+
## Codex
|
|
33
|
+
|
|
34
|
+
**ChatGPT / Codex app** — open **Settings → MCPs → Add server**, enter the URL `https://mcp.qase.io/mcp`, and click **Authenticate**.
|
|
35
|
+
|
|
36
|
+
**Codex CLI** — add to `~/.codex/config.toml`:
|
|
37
|
+
|
|
38
|
+
```toml
|
|
39
|
+
[mcp_servers.qase]
|
|
40
|
+
url = "https://mcp.qase.io/mcp"
|
|
41
|
+
auth = "oauth"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Then run `codex mcp login qase` and complete the Qase sign-in in your browser.
|
|
45
|
+
|
|
46
|
+
> **Note:** Enter the URL exactly as shown — without surrounding quotes. A stray quote (or its encoded form, `%22`) in the server URL breaks OAuth; if a connection ever fails to authenticate, remove the server entry and re-add it, typing the URL by hand.
|
|
47
|
+
|
|
48
|
+
## VS Code
|
|
49
|
+
|
|
50
|
+
Add the hosted server to `.vscode/mcp.json` (workspace-scoped):
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"servers": {
|
|
55
|
+
"qase": {
|
|
56
|
+
"type": "http",
|
|
57
|
+
"url": "https://mcp.qase.io/mcp"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Or run **MCP: Add Server** from the Command Palette (`⇧⌘P` / `Ctrl+Shift+P`), choose **HTTP**, and enter the URL. VS Code opens your browser to sign in to Qase; the tools appear once you've authorized.
|
|
64
|
+
|
|
65
|
+
## Other remote clients
|
|
66
|
+
|
|
67
|
+
Any MCP client that supports remote (HTTP) servers with OAuth 2.1 can connect the same way — point it at:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
https://mcp.qase.io/mcp
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
In every case the hosted server authenticates via your Qase login (OAuth) — no local installation or `QASE_API_TOKEN` needed.
|
|
74
|
+
|
|
75
|
+
## Active workspace
|
|
76
|
+
|
|
77
|
+
The connector operates on the workspace currently selected in your Qase UI. To work in a different workspace, just switch it in Qase — the connector automatically routes subsequent requests to the newly selected workspace, with no need to reconnect or re-authorize.
|
|
78
|
+
|
|
79
|
+
## Troubleshooting
|
|
80
|
+
|
|
81
|
+
Connector not appearing, empty tool list, or OAuth sign-in failing? See [Troubleshooting](troubleshooting.md).
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
# Migration Guide: v1 → v2
|
|
2
|
+
|
|
3
|
+
> **Breaking change**: v2 replaces all 83 v1 tool names with a consolidated set of 29 task-oriented tools (30 total, including the `qase_discover_tools` discovery tool).
|
|
4
|
+
> Every tool name has changed. Update your prompts, workflows, and any automation that references tool names.
|
|
5
|
+
|
|
6
|
+
## What changed at a glance
|
|
7
|
+
|
|
8
|
+
| Area | v1 | v2 |
|
|
9
|
+
|---|---|---|
|
|
10
|
+
| Tool count | 83 | 29 task-oriented (30 total) |
|
|
11
|
+
| Naming convention | snake_case verbs (`list_cases`, `create_run`) | `qase_` prefix + noun+verb (`qase_case_upsert`) |
|
|
12
|
+
| Read tools | One tool per entity type | `qase_get` handles all entity types |
|
|
13
|
+
| List/search | Separate `list_*` per entity | `qql_search` with `entity=` parameter |
|
|
14
|
+
| Metadata bootstrap | 6 separate list calls | `qase_project_context` (single call, cached) |
|
|
15
|
+
| CI reporting | 3–4 manual steps | `qase_ci_report` composite |
|
|
16
|
+
| Response format | Pretty-printed JSON, nulls included | Compact JSON (no indent), nulls stripped |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Tool mapping table
|
|
21
|
+
|
|
22
|
+
All 83 v1 tools mapped to their v2 equivalents.
|
|
23
|
+
|
|
24
|
+
### Projects
|
|
25
|
+
|
|
26
|
+
| v1 tool | v2 equivalent | Notes |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| `list_projects` | `qase_project_context` | Returns project + suites + milestones + envs + custom fields + users in one call |
|
|
29
|
+
| `get_project` | `qase_get` with `entity="project"` | No `code` required; pass project code as `id` |
|
|
30
|
+
| `create_project` | `qase_api` | Use escape hatch: `POST /project` |
|
|
31
|
+
| `delete_project` | `qase_api` | Use escape hatch: `DELETE /project/{code}` |
|
|
32
|
+
| `grant_project_access` | `qase_api` | Use escape hatch: `POST /project/{code}/access` |
|
|
33
|
+
| `revoke_project_access` | `qase_api` | Use escape hatch: `DELETE /project/{code}/access` |
|
|
34
|
+
|
|
35
|
+
### Test Cases
|
|
36
|
+
|
|
37
|
+
| v1 tool | v2 equivalent | Notes |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| `list_cases` | `qql_search` with `entity="case"` | Supports full QQL filters |
|
|
40
|
+
| `get_case` | `qase_get` with `entity="case"` | Supports `fields` projection |
|
|
41
|
+
| `create_case` | `qase_case_upsert` (omit `id`) | Pass all case fields; no `id` = create |
|
|
42
|
+
| `update_case` | `qase_case_upsert` (include `id`) | Include `id` to update existing case |
|
|
43
|
+
| `delete_case` | `qase_case_delete` | — |
|
|
44
|
+
| `bulk_create_cases` | `qase_case_upsert` (call per case) | Call once per case without `id` |
|
|
45
|
+
| `attach_external_issue` | `qase_api` | Use escape hatch: `POST /case/{code}/{id}/external-issues` |
|
|
46
|
+
| `detach_external_issue` | `qase_api` | Use escape hatch: `DELETE /case/{code}/{id}/external-issues` |
|
|
47
|
+
|
|
48
|
+
### Test Suites
|
|
49
|
+
|
|
50
|
+
| v1 tool | v2 equivalent | Notes |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| `list_suites` | `qase_project_context` | Suites tree is included in context response |
|
|
53
|
+
| `get_suite` | `qase_get` with `entity="suite"` | — |
|
|
54
|
+
| `create_suite` | `qase_suite_upsert` (omit `id`) | — |
|
|
55
|
+
| `update_suite` | `qase_suite_upsert` (include `id`) | — |
|
|
56
|
+
| `delete_suite` | `qase_suite_delete` | — |
|
|
57
|
+
|
|
58
|
+
### Test Runs
|
|
59
|
+
|
|
60
|
+
| v1 tool | v2 equivalent | Notes |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `list_runs` | `qql_search` with `entity="run"` | — |
|
|
63
|
+
| `get_run` | `qase_get` with `entity="run"` | — |
|
|
64
|
+
| `create_run` | `qase_run_upsert` (omit `id`) | Or use `qase_ci_report` / `qase_regression_run` composites |
|
|
65
|
+
| `delete_run` | `qase_run_delete` | — |
|
|
66
|
+
| `complete_run` | `qase_run_complete` | — |
|
|
67
|
+
| `get_run_public_link` | `qase_api` | Use escape hatch: `GET /run/{code}/{id}/public-link` |
|
|
68
|
+
| `delete_run_public_link` | `qase_api` | Use escape hatch: `DELETE /run/{code}/{id}/public-link` |
|
|
69
|
+
|
|
70
|
+
### Test Results
|
|
71
|
+
|
|
72
|
+
| v1 tool | v2 equivalent | Notes |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| `list_results` | `qql_search` with `entity="result"` | — |
|
|
75
|
+
| `get_result` | `qase_get` with `entity="result"` | — |
|
|
76
|
+
| `create_result` | `qase_result_record` | Accepts single result or array via `results` |
|
|
77
|
+
| `create_results_bulk` | `qase_result_record` | Same tool handles bulk via `results` array |
|
|
78
|
+
| `update_result` | `qase_api` | Use escape hatch: `PATCH /result/{code}/{id}` |
|
|
79
|
+
| `delete_result` | `qase_result_delete` | — |
|
|
80
|
+
|
|
81
|
+
### Test Plans
|
|
82
|
+
|
|
83
|
+
| v1 tool | v2 equivalent | Notes |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| `list_plans` | `qql_search` with `entity="plan"` | — |
|
|
86
|
+
| `get_plan` | `qase_get` with `entity="plan"` | — |
|
|
87
|
+
| `create_plan` | `qase_plan_upsert` (omit `id`) | — |
|
|
88
|
+
| `update_plan` | `qase_plan_upsert` (include `id`) | — |
|
|
89
|
+
| `delete_plan` | `qase_plan_delete` | — |
|
|
90
|
+
|
|
91
|
+
### Defects
|
|
92
|
+
|
|
93
|
+
| v1 tool | v2 equivalent | Notes |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| `list_defects` | `qql_search` with `entity="defect"` | — |
|
|
96
|
+
| `get_defect` | `qase_get` with `entity="defect"` | — |
|
|
97
|
+
| `create_defect` | `qase_defect_upsert` (omit `id`) | Or use `qase_triage_defect` composite |
|
|
98
|
+
| `update_defect` | `qase_defect_upsert` (include `id`) | — |
|
|
99
|
+
| `delete_defect` | `qase_defect_delete` | — |
|
|
100
|
+
| `resolve_defect` | `qase_defect_upsert` with `status="resolved"` | Pass `id` + `status` field |
|
|
101
|
+
| `update_defect_status` | `qase_defect_upsert` with `status` field | Pass `id` + desired `status` |
|
|
102
|
+
|
|
103
|
+
### Milestones
|
|
104
|
+
|
|
105
|
+
| v1 tool | v2 equivalent | Notes |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| `list_milestones` | `qase_project_context` | Milestones are included in context response |
|
|
108
|
+
| `get_milestone` | `qase_get` with `entity="milestone"` | — |
|
|
109
|
+
| `create_milestone` | `qase_milestone_upsert` (omit `id`) | — |
|
|
110
|
+
| `update_milestone` | `qase_milestone_upsert` (include `id`) | — |
|
|
111
|
+
| `delete_milestone` | `qase_milestone_delete` | — |
|
|
112
|
+
|
|
113
|
+
### Environments
|
|
114
|
+
|
|
115
|
+
| v1 tool | v2 equivalent | Notes |
|
|
116
|
+
|---|---|---|
|
|
117
|
+
| `list_environments` | `qase_project_context` | Environments are included in context response |
|
|
118
|
+
| `get_environment` | `qase_get` with `entity="environment"` | — |
|
|
119
|
+
| `create_environment` | `qase_environment_upsert` (omit `id`) | — |
|
|
120
|
+
| `update_environment` | `qase_environment_upsert` (include `id`) | — |
|
|
121
|
+
| `delete_environment` | `qase_environment_delete` | — |
|
|
122
|
+
|
|
123
|
+
### Shared Steps
|
|
124
|
+
|
|
125
|
+
| v1 tool | v2 equivalent | Notes |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| `list_shared_steps` | `qql_search` with `entity="shared_step"` | — |
|
|
128
|
+
| `get_shared_step` | `qase_get` with `entity="shared_step"` | — |
|
|
129
|
+
| `create_shared_step` | `qase_shared_step_upsert` (omit `id`) | — |
|
|
130
|
+
| `update_shared_step` | `qase_shared_step_upsert` (include `id`) | — |
|
|
131
|
+
| `delete_shared_step` | `qase_shared_step_delete` | — |
|
|
132
|
+
|
|
133
|
+
### Shared Parameters
|
|
134
|
+
|
|
135
|
+
| v1 tool | v2 equivalent | Notes |
|
|
136
|
+
|---|---|---|
|
|
137
|
+
| `list_shared_parameters` | `qql_search` with `entity="shared_parameter"` | — |
|
|
138
|
+
| `get_shared_parameter` | `qase_get` with `entity="shared_parameter"` | No `code` required |
|
|
139
|
+
|
|
140
|
+
### Attachments
|
|
141
|
+
|
|
142
|
+
| v1 tool | v2 equivalent | Notes |
|
|
143
|
+
|---|---|---|
|
|
144
|
+
| `list_attachments` | `qase_api` | Use escape hatch: `GET /attachment` |
|
|
145
|
+
| `get_attachment` | `qase_get` with `entity="attachment"` | Pass hash as `id` |
|
|
146
|
+
| `upload_attachment` | `qase_attachment_upload` | — |
|
|
147
|
+
| `delete_attachment` | `qase_attachment_delete` | — |
|
|
148
|
+
|
|
149
|
+
### Authors
|
|
150
|
+
|
|
151
|
+
| v1 tool | v2 equivalent | Notes |
|
|
152
|
+
|---|---|---|
|
|
153
|
+
| `list_authors` | `qase_api` | Use escape hatch: `GET /author` |
|
|
154
|
+
| `get_author` | `qase_get` with `entity="author"` | — |
|
|
155
|
+
|
|
156
|
+
### Custom Fields
|
|
157
|
+
|
|
158
|
+
| v1 tool | v2 equivalent | Notes |
|
|
159
|
+
|---|---|---|
|
|
160
|
+
| `list_custom_fields` | `qase_project_context` | Custom fields are included in context response |
|
|
161
|
+
| `get_custom_field` | `qase_get` with `entity="custom_field"` | — |
|
|
162
|
+
| `create_custom_field` | `qase_api` | Use escape hatch: `POST /custom-field` |
|
|
163
|
+
| `update_custom_field` | `qase_api` | Use escape hatch: `PATCH /custom-field/{id}` |
|
|
164
|
+
| `delete_custom_field` | `qase_api` | Use escape hatch: `DELETE /custom-field/{id}` |
|
|
165
|
+
|
|
166
|
+
### System Fields
|
|
167
|
+
|
|
168
|
+
| v1 tool | v2 equivalent | Notes |
|
|
169
|
+
|---|---|---|
|
|
170
|
+
| `list_system_fields` | `qase_api` | Use escape hatch: `GET /system-field` |
|
|
171
|
+
|
|
172
|
+
### Configurations
|
|
173
|
+
|
|
174
|
+
| v1 tool | v2 equivalent | Notes |
|
|
175
|
+
|---|---|---|
|
|
176
|
+
| `list_configurations` | `qase_get` with `entity="configuration"` | Returns all config groups for a project |
|
|
177
|
+
| `create_configuration_group` | `qase_api` | Use escape hatch: `POST /configuration/{code}` |
|
|
178
|
+
| `delete_configuration_group` | `qase_api` | Use escape hatch: `DELETE /configuration/{code}/{id}` |
|
|
179
|
+
|
|
180
|
+
### Users
|
|
181
|
+
|
|
182
|
+
| v1 tool | v2 equivalent | Notes |
|
|
183
|
+
|---|---|---|
|
|
184
|
+
| `list_users` | `qase_project_context` | Users are included in context response |
|
|
185
|
+
| `get_user` | `qase_get` with `entity="user"` | — |
|
|
186
|
+
|
|
187
|
+
### QQL Search
|
|
188
|
+
|
|
189
|
+
| v1 tool | v2 equivalent | Notes |
|
|
190
|
+
|---|---|---|
|
|
191
|
+
| `qql_search` | `qql_search` | Unchanged — same tool, same interface |
|
|
192
|
+
| `qql_help` | `qql_help` | Unchanged — same tool, same interface |
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Response format changes
|
|
197
|
+
|
|
198
|
+
In v1, responses were pretty-printed JSON with `null` values included:
|
|
199
|
+
|
|
200
|
+
```json
|
|
201
|
+
{
|
|
202
|
+
"id": 42,
|
|
203
|
+
"title": "Login test",
|
|
204
|
+
"description": null,
|
|
205
|
+
"preconditions": null,
|
|
206
|
+
"priority": 2
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
In v2, responses are compact JSON with `null` values stripped:
|
|
211
|
+
|
|
212
|
+
```json
|
|
213
|
+
{"id":42,"title":"Login test","priority":2}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
This reduces token usage significantly on large result sets. If your workflow parses response strings directly rather than using structured tool output, update your parsing logic accordingly.
|
|
217
|
+
|
|
218
|
+
Additionally, `qase_get` supports **field projection** via the `fields` parameter:
|
|
219
|
+
|
|
220
|
+
```json
|
|
221
|
+
{ "entity": "case", "code": "MYPROJECT", "id": 42, "fields": ["id", "title", "status"] }
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Pass `["*"]` to get all fields.
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## New composite tools
|
|
229
|
+
|
|
230
|
+
These tools combine multiple API calls into a single operation, reducing round-trips and LLM context usage.
|
|
231
|
+
|
|
232
|
+
### `qase_ci_report`
|
|
233
|
+
|
|
234
|
+
Replaces the 3–4 step workflow of `create_run → create_results_bulk → complete_run`.
|
|
235
|
+
|
|
236
|
+
Accepts a project code, run title, and an array of test results. Creates the run, records all results, and optionally completes it in one call.
|
|
237
|
+
|
|
238
|
+
### `qase_triage_defect`
|
|
239
|
+
|
|
240
|
+
Streamlines the defect triage workflow. Creates a defect from a test failure description and optionally links it to failed result hashes from a run.
|
|
241
|
+
|
|
242
|
+
Replaces: `create_defect` (then manual linking).
|
|
243
|
+
|
|
244
|
+
### `qase_regression_run`
|
|
245
|
+
|
|
246
|
+
Sets up a regression test run in one call. Accepts case selection by suite IDs, explicit case IDs, or plan ID. Creates the run and populates it with all matching cases.
|
|
247
|
+
|
|
248
|
+
Replaces: `list_cases` (per suite) → `create_run` → manually adding cases.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Before / after examples
|
|
253
|
+
|
|
254
|
+
### Example 1: Report CI results
|
|
255
|
+
|
|
256
|
+
**v1 (3 calls)**
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
1. create_run { code: "PROJ", title: "CI Build #42", cases: [101, 102, 103] }
|
|
260
|
+
→ { id: 7 }
|
|
261
|
+
|
|
262
|
+
2. create_results_bulk { code: "PROJ", id: 7, results: [...] }
|
|
263
|
+
|
|
264
|
+
3. complete_run { code: "PROJ", id: 7 }
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**v2 (1 call)**
|
|
268
|
+
|
|
269
|
+
```
|
|
270
|
+
qase_ci_report {
|
|
271
|
+
code: "PROJ",
|
|
272
|
+
title: "CI Build #42",
|
|
273
|
+
results: [
|
|
274
|
+
{ case_id: 101, status: "passed", time_ms: 1200 },
|
|
275
|
+
{ case_id: 102, status: "failed", stacktrace: "AssertionError..." },
|
|
276
|
+
{ case_id: 103, status: "skipped" }
|
|
277
|
+
]
|
|
278
|
+
}
|
|
279
|
+
→ { run_id: 7, run_status: "complete", results_recorded: 3 }
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
### Example 2: Get project metadata before creating a test case
|
|
285
|
+
|
|
286
|
+
**v1 (up to 6 calls)**
|
|
287
|
+
|
|
288
|
+
```
|
|
289
|
+
1. list_suites { code: "PROJ" }
|
|
290
|
+
2. list_milestones { code: "PROJ" }
|
|
291
|
+
3. list_environments { code: "PROJ" }
|
|
292
|
+
4. list_custom_fields {}
|
|
293
|
+
5. list_users {}
|
|
294
|
+
6. get_project { code: "PROJ" }
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**v2 (1 call)**
|
|
298
|
+
|
|
299
|
+
```
|
|
300
|
+
qase_project_context { code: "PROJ" }
|
|
301
|
+
→ {
|
|
302
|
+
project: { ... },
|
|
303
|
+
suites: { entities: [...] },
|
|
304
|
+
milestones: { entities: [...] },
|
|
305
|
+
environments: { entities: [...] },
|
|
306
|
+
custom_fields: { entities: [...] },
|
|
307
|
+
users: { entities: [...] }
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Result is cached for 5 minutes — subsequent calls within the same session return instantly.
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
### Example 3: Create or update a test case
|
|
316
|
+
|
|
317
|
+
**v1 (separate tools for create vs update)**
|
|
318
|
+
|
|
319
|
+
```
|
|
320
|
+
# Create:
|
|
321
|
+
create_case { code: "PROJ", title: "Login happy path", priority: "high" }
|
|
322
|
+
|
|
323
|
+
# Update:
|
|
324
|
+
update_case { code: "PROJ", id: 55, title: "Login happy path v2" }
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**v2 (single upsert tool)**
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
# Create (no id):
|
|
331
|
+
qase_case_upsert { code: "PROJ", title: "Login happy path", priority: "high" }
|
|
332
|
+
|
|
333
|
+
# Update (with id):
|
|
334
|
+
qase_case_upsert { code: "PROJ", id: 55, title: "Login happy path v2" }
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## Escape hatch for unsupported operations
|
|
340
|
+
|
|
341
|
+
For v1 operations that have no direct v2 equivalent (project management, configuration groups, system fields, etc.), use `qase_api`:
|
|
342
|
+
|
|
343
|
+
```
|
|
344
|
+
qase_api {
|
|
345
|
+
method: "GET",
|
|
346
|
+
path: "/system-field",
|
|
347
|
+
query: {}
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
This gives direct access to any Qase REST API endpoint. See the `qase_api` tool description for full parameter documentation.
|