@qualitas-id/mcp 1.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/LICENSE +21 -0
- package/README.md +262 -0
- package/dist/constants.d.ts +18 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +18 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +82 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/common.d.ts +20 -0
- package/dist/schemas/common.d.ts.map +1 -0
- package/dist/schemas/common.js +10 -0
- package/dist/schemas/common.js.map +1 -0
- package/dist/schemas/flow.d.ts +358 -0
- package/dist/schemas/flow.d.ts.map +1 -0
- package/dist/schemas/flow.js +72 -0
- package/dist/schemas/flow.js.map +1 -0
- package/dist/schemas/project.d.ts +70 -0
- package/dist/schemas/project.d.ts.map +1 -0
- package/dist/schemas/project.js +26 -0
- package/dist/schemas/project.js.map +1 -0
- package/dist/schemas/run.d.ts +54 -0
- package/dist/schemas/run.d.ts.map +1 -0
- package/dist/schemas/run.js +20 -0
- package/dist/schemas/run.js.map +1 -0
- package/dist/schemas/variable.d.ts +91 -0
- package/dist/schemas/variable.d.ts.map +1 -0
- package/dist/schemas/variable.js +30 -0
- package/dist/schemas/variable.js.map +1 -0
- package/dist/services/api-client.d.ts +101 -0
- package/dist/services/api-client.d.ts.map +1 -0
- package/dist/services/api-client.js +184 -0
- package/dist/services/api-client.js.map +1 -0
- package/dist/services/flow-generator.d.ts +31 -0
- package/dist/services/flow-generator.d.ts.map +1 -0
- package/dist/services/flow-generator.js +638 -0
- package/dist/services/flow-generator.js.map +1 -0
- package/dist/shared-types.d.ts +579 -0
- package/dist/shared-types.d.ts.map +1 -0
- package/dist/shared-types.js +12 -0
- package/dist/shared-types.js.map +1 -0
- package/dist/tools/flows.d.ts +13 -0
- package/dist/tools/flows.d.ts.map +1 -0
- package/dist/tools/flows.js +458 -0
- package/dist/tools/flows.js.map +1 -0
- package/dist/tools/projects.d.ts +13 -0
- package/dist/tools/projects.d.ts.map +1 -0
- package/dist/tools/projects.js +381 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/runs.d.ts +9 -0
- package/dist/tools/runs.d.ts.map +1 -0
- package/dist/tools/runs.js +342 -0
- package/dist/tools/runs.js.map +1 -0
- package/dist/tools/utils.d.ts +12 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +144 -0
- package/dist/tools/utils.js.map +1 -0
- package/dist/tools/variables.d.ts +9 -0
- package/dist/tools/variables.d.ts.map +1 -0
- package/dist/tools/variables.js +316 -0
- package/dist/tools/variables.js.map +1 -0
- package/dist/types.d.ts +117 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/flow-layout.d.ts +34 -0
- package/dist/utils/flow-layout.d.ts.map +1 -0
- package/dist/utils/flow-layout.js +109 -0
- package/dist/utils/flow-layout.js.map +1 -0
- package/dist/utils/flow-validation.d.ts +74 -0
- package/dist/utils/flow-validation.d.ts.map +1 -0
- package/dist/utils/flow-validation.js +386 -0
- package/dist/utils/flow-validation.js.map +1 -0
- package/dist/utils/ocr.d.ts +25 -0
- package/dist/utils/ocr.d.ts.map +1 -0
- package/dist/utils/ocr.js +88 -0
- package/dist/utils/ocr.js.map +1 -0
- package/package.json +65 -0
- package/skills/qualitas.md +253 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Qualitas
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# Qualitas MCP Server
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@qualitas-id/mcp)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
MCP (Model Context Protocol) server for the [Qualitas](https://qualitas.id) test automation platform. Enables AI agents to create projects, generate test flows from natural language scenarios, execute tests, and manage environment variables.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **20 tools** for complete Qualitas platform interaction
|
|
11
|
+
- **Flow generation from scenarios** — describe a test in natural language, get a runnable flow
|
|
12
|
+
- **Auto-beautify layout** — nodes are automatically arranged in clean topological order
|
|
13
|
+
- **Fragment support** — create reusable flow fragments for common patterns
|
|
14
|
+
- **Full CRUD** for projects, flows, variables, and runs
|
|
15
|
+
- **API key authentication** — secure, workspace-scoped access via `qlt_live_*` tokens
|
|
16
|
+
- **OCR support** — extract text from test screenshots
|
|
17
|
+
- **Upload modes** — local file, URL, base64, and variable reference
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
### NPX (Recommended)
|
|
22
|
+
|
|
23
|
+
No installation needed! Use directly with npx:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx @qualitas-id/mcp
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Global Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install -g @qualitas-id/mcp
|
|
33
|
+
qualitas-mcp
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Local Development
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
git clone https://github.com/firdyfirdy/qualitas-mcp-server.git
|
|
40
|
+
cd qualitas-mcp-server
|
|
41
|
+
npm install
|
|
42
|
+
npm run build
|
|
43
|
+
npm start
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Configuration
|
|
47
|
+
|
|
48
|
+
| Variable | Required | Default | Description |
|
|
49
|
+
|---|---|---|---|
|
|
50
|
+
| `QUALITAS_API_KEY` | Yes | — | API key from Qualitas Developer Settings (`qlt_live_...`) |
|
|
51
|
+
| `QUALITAS_API_URL` | No | `https://api.qualitas.id` | Qualitas API base URL |
|
|
52
|
+
| `QUALITAS_APP_URL` | No | `https://qualitas.id` | Frontend URL for deep-links |
|
|
53
|
+
|
|
54
|
+
## IDE Setup
|
|
55
|
+
|
|
56
|
+
### OpenCode
|
|
57
|
+
|
|
58
|
+
Add to `opencode.json` or `opencode.jsonc`:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"$schema": "https://opencode.ai/config.json",
|
|
63
|
+
"mcp": {
|
|
64
|
+
"qualitas": {
|
|
65
|
+
"type": "local",
|
|
66
|
+
"command": ["npx", "-y", "@qualitas-id/mcp"],
|
|
67
|
+
"enabled": true,
|
|
68
|
+
"environment": {
|
|
69
|
+
"QUALITAS_API_KEY": "qlt_live_your_api_key_here"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Or use the OpenCode CLI:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
opencode mcp add qualitas -- npx -y @qualitas-id/mcp
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Claude Desktop
|
|
83
|
+
|
|
84
|
+
Add to `claude_desktop_config.json`:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"mcpServers": {
|
|
89
|
+
"qualitas": {
|
|
90
|
+
"command": "npx",
|
|
91
|
+
"args": ["-y", "@qualitas-id/mcp"],
|
|
92
|
+
"env": {
|
|
93
|
+
"QUALITAS_API_KEY": "qlt_live_your_api_key_here"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Claude Code
|
|
101
|
+
|
|
102
|
+
Use the Claude Code CLI:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
claude mcp add qualitas -- npx -y @qualitas-id/mcp
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Cursor
|
|
109
|
+
|
|
110
|
+
Add to `.cursor/mcp.json`:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"mcpServers": {
|
|
115
|
+
"qualitas": {
|
|
116
|
+
"command": "npx",
|
|
117
|
+
"args": ["-y", "@qualitas-id/mcp"],
|
|
118
|
+
"env": {
|
|
119
|
+
"QUALITAS_API_KEY": "qlt_live_your_api_key_here"
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Windsurf
|
|
127
|
+
|
|
128
|
+
Add to `~/.windsurf/mcp.json`:
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"mcpServers": {
|
|
133
|
+
"qualitas": {
|
|
134
|
+
"command": "npx",
|
|
135
|
+
"args": ["-y", "@qualitas-id/mcp"],
|
|
136
|
+
"env": {
|
|
137
|
+
"QUALITAS_API_KEY": "qlt_live_your_api_key_here"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### VS Code (GitHub Copilot)
|
|
145
|
+
|
|
146
|
+
Add to `.vscode/mcp.json`:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"servers": {
|
|
151
|
+
"qualitas": {
|
|
152
|
+
"command": "npx",
|
|
153
|
+
"args": ["-y", "@qualitas-id/mcp"],
|
|
154
|
+
"env": {
|
|
155
|
+
"QUALITAS_API_KEY": "qlt_live_your_api_key_here"
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Tools Reference
|
|
163
|
+
|
|
164
|
+
### Projects
|
|
165
|
+
|
|
166
|
+
| Tool | Description | Annotations |
|
|
167
|
+
|---|---|---|
|
|
168
|
+
| `list_projects` | List all projects with search/filter/sort | read-only |
|
|
169
|
+
| `get_project` | Get project details with stats | read-only |
|
|
170
|
+
| `create_project` | Create a new project | write |
|
|
171
|
+
| `update_project` | Update project settings | write, idempotent |
|
|
172
|
+
|
|
173
|
+
### Flows
|
|
174
|
+
|
|
175
|
+
| Tool | Description | Annotations |
|
|
176
|
+
|---|---|---|
|
|
177
|
+
| `list_flows` | List flows in a project | read-only |
|
|
178
|
+
| `get_flow` | Get flow details (nodes, edges, variables) | read-only |
|
|
179
|
+
| `create_flow` | Create a flow with explicit nodes/edges | write |
|
|
180
|
+
| `update_flow` | Update flow nodes/edges/variables | write, idempotent |
|
|
181
|
+
| `delete_flow` | Delete a flow permanently | write, destructive |
|
|
182
|
+
| `publish_flow` | Publish a flow/fragment (draft → active) | write |
|
|
183
|
+
| `generate_flow_from_scenario` | **Generate a flow from natural language** | write |
|
|
184
|
+
|
|
185
|
+
### Runs
|
|
186
|
+
|
|
187
|
+
| Tool | Description | Annotations |
|
|
188
|
+
|---|---|---|
|
|
189
|
+
| `run_flow` | Trigger flow execution | write |
|
|
190
|
+
| `get_run_status` | Get run status and step results | read-only |
|
|
191
|
+
| `list_runs` | List run history for a flow | read-only |
|
|
192
|
+
| `get_run_screenshot` | Get screenshot URLs for failed steps | read-only |
|
|
193
|
+
|
|
194
|
+
### Variables
|
|
195
|
+
|
|
196
|
+
| Tool | Description | Annotations |
|
|
197
|
+
|---|---|---|
|
|
198
|
+
| `list_variables` | List project environment variables | read-only |
|
|
199
|
+
| `create_variable` | Create environment variable | write |
|
|
200
|
+
| `update_variable` | Update environment variable | write, idempotent |
|
|
201
|
+
| `delete_variable` | Delete environment variable | write, destructive |
|
|
202
|
+
|
|
203
|
+
### Utility
|
|
204
|
+
|
|
205
|
+
| Tool | Description | Annotations |
|
|
206
|
+
|---|---|---|
|
|
207
|
+
| `extract_screenshot_text` | OCR from image URL, extract text and error messages | read-only |
|
|
208
|
+
|
|
209
|
+
## Flow Generation
|
|
210
|
+
|
|
211
|
+
The `generate_flow_from_scenario` tool is the core feature. Describe a test scenario in natural language and get a complete, runnable flow.
|
|
212
|
+
|
|
213
|
+
**Example scenario:**
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
1. Navigate to https://example.com/login
|
|
217
|
+
2. Fill #email with 'user@example.com'
|
|
218
|
+
3. Fill #password with {{flow.PASSWORD}}
|
|
219
|
+
4. Press Enter to submit
|
|
220
|
+
5. Wait 3 seconds
|
|
221
|
+
6. Verify URL is dashboard
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
**Supported node types:** 40 types including navigation, mouse actions, input, form, wait, assertions, API calls, loops, conditions, and more.
|
|
225
|
+
|
|
226
|
+
## Fragment Support
|
|
227
|
+
|
|
228
|
+
Create reusable fragments for common patterns (login, registration, etc.):
|
|
229
|
+
|
|
230
|
+
```json
|
|
231
|
+
{
|
|
232
|
+
"type": "fragment",
|
|
233
|
+
"name": "Login Fragment",
|
|
234
|
+
"nodes": [
|
|
235
|
+
{"id": "nav_login", "type": "navigate", ...},
|
|
236
|
+
{"id": "fill_email", "type": "fill", ...},
|
|
237
|
+
{"id": "submit", "type": "press", ...}
|
|
238
|
+
]
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
**Important:** Fragments MUST NOT have a `start` node. The fragment's nodes are inlined into the calling flow.
|
|
243
|
+
|
|
244
|
+
## Docker
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
docker pull ghcr.io/firdyfirdy/qualitas-mcp-server:latest
|
|
248
|
+
|
|
249
|
+
docker run -e QUALITAS_API_KEY=qlt_live_your_key ghcr.io/firdyfirdy/qualitas-mcp-server:latest
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Tech Stack
|
|
253
|
+
|
|
254
|
+
- TypeScript (strict mode)
|
|
255
|
+
- MCP SDK (`@modelcontextprotocol/sdk`)
|
|
256
|
+
- Zod (input validation)
|
|
257
|
+
- Axios (HTTP client)
|
|
258
|
+
- Tesseract.js (OCR)
|
|
259
|
+
|
|
260
|
+
## License
|
|
261
|
+
|
|
262
|
+
MIT
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Qualitas MCP Server - Constants
|
|
3
|
+
*/
|
|
4
|
+
/** Base URL for the Qualitas API */
|
|
5
|
+
export declare const API_BASE_URL: string;
|
|
6
|
+
/** Maximum response size in characters to prevent overwhelming LLM context */
|
|
7
|
+
export declare const CHARACTER_LIMIT = 25000;
|
|
8
|
+
/** Server version */
|
|
9
|
+
export declare const VERSION = "1.0.0";
|
|
10
|
+
/** Server name for MCP identification */
|
|
11
|
+
export declare const SERVER_NAME = "qualitas-mcp-server";
|
|
12
|
+
/** Default pagination limit */
|
|
13
|
+
export declare const DEFAULT_PAGE_LIMIT = 20;
|
|
14
|
+
/** Maximum pagination limit */
|
|
15
|
+
export declare const MAX_PAGE_LIMIT = 100;
|
|
16
|
+
/** Frontend app URL for deep-links */
|
|
17
|
+
export declare const APP_URL: string;
|
|
18
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,oCAAoC;AACpC,eAAO,MAAM,YAAY,QACkC,CAAC;AAE5D,8EAA8E;AAC9E,eAAO,MAAM,eAAe,QAAQ,CAAC;AAErC,qBAAqB;AACrB,eAAO,MAAM,OAAO,UAAU,CAAC;AAE/B,yCAAyC;AACzC,eAAO,MAAM,WAAW,wBAAwB,CAAC;AAEjD,+BAA+B;AAC/B,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,+BAA+B;AAC/B,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC,sCAAsC;AACtC,eAAO,MAAM,OAAO,QACmC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Qualitas MCP Server - Constants
|
|
3
|
+
*/
|
|
4
|
+
/** Base URL for the Qualitas API */
|
|
5
|
+
export const API_BASE_URL = process.env.QUALITAS_API_URL || "https://api.qualitas.id";
|
|
6
|
+
/** Maximum response size in characters to prevent overwhelming LLM context */
|
|
7
|
+
export const CHARACTER_LIMIT = 25000;
|
|
8
|
+
/** Server version */
|
|
9
|
+
export const VERSION = "1.0.0";
|
|
10
|
+
/** Server name for MCP identification */
|
|
11
|
+
export const SERVER_NAME = "qualitas-mcp-server";
|
|
12
|
+
/** Default pagination limit */
|
|
13
|
+
export const DEFAULT_PAGE_LIMIT = 20;
|
|
14
|
+
/** Maximum pagination limit */
|
|
15
|
+
export const MAX_PAGE_LIMIT = 100;
|
|
16
|
+
/** Frontend app URL for deep-links */
|
|
17
|
+
export const APP_URL = process.env.QUALITAS_APP_URL || "https://qualitas.id";
|
|
18
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,oCAAoC;AACpC,MAAM,CAAC,MAAM,YAAY,GACvB,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,yBAAyB,CAAC;AAE5D,8EAA8E;AAC9E,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AAErC,qBAAqB;AACrB,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,yCAAyC;AACzC,MAAM,CAAC,MAAM,WAAW,GAAG,qBAAqB,CAAC;AAEjD,+BAA+B;AAC/B,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAErC,+BAA+B;AAC/B,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAC;AAElC,sCAAsC;AACtC,MAAM,CAAC,MAAM,OAAO,GAClB,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,qBAAqB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Qualitas MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Enables AI agents to interact with the Qualitas test automation platform.
|
|
6
|
+
* Create projects, generate flows from natural language scenarios,
|
|
7
|
+
* execute tests, and manage environment variables.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;GAMG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Qualitas MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Enables AI agents to interact with the Qualitas test automation platform.
|
|
6
|
+
* Create projects, generate flows from natural language scenarios,
|
|
7
|
+
* execute tests, and manage environment variables.
|
|
8
|
+
*/
|
|
9
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
10
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
11
|
+
import { SERVER_NAME, VERSION, API_BASE_URL } from "./constants.js";
|
|
12
|
+
import { QualitasApiClient } from "./services/api-client.js";
|
|
13
|
+
import { registerProjectTools } from "./tools/projects.js";
|
|
14
|
+
import { registerFlowTools } from "./tools/flows.js";
|
|
15
|
+
import { registerRunTools } from "./tools/runs.js";
|
|
16
|
+
import { registerVariableTools } from "./tools/variables.js";
|
|
17
|
+
import { registerUtilityTools } from "./tools/utils.js";
|
|
18
|
+
// Create MCP server instance
|
|
19
|
+
const server = new McpServer({
|
|
20
|
+
name: SERVER_NAME,
|
|
21
|
+
version: VERSION,
|
|
22
|
+
});
|
|
23
|
+
// Lazy API client - initialized on first tool call
|
|
24
|
+
let _apiClient = null;
|
|
25
|
+
function getApiClient() {
|
|
26
|
+
if (!_apiClient) {
|
|
27
|
+
const apiKey = process.env.QUALITAS_API_KEY;
|
|
28
|
+
if (!apiKey) {
|
|
29
|
+
throw new Error("QUALITAS_API_KEY environment variable is required. " +
|
|
30
|
+
"Generate an API key from your Qualitas Developer Settings page.");
|
|
31
|
+
}
|
|
32
|
+
_apiClient = new QualitasApiClient(apiKey, API_BASE_URL);
|
|
33
|
+
}
|
|
34
|
+
return _apiClient;
|
|
35
|
+
}
|
|
36
|
+
// Create a proxy that lazily initializes the API client
|
|
37
|
+
const apiClientProxy = new Proxy({}, {
|
|
38
|
+
get(_target, prop) {
|
|
39
|
+
const client = getApiClient();
|
|
40
|
+
const value = client[prop];
|
|
41
|
+
if (typeof value === "function") {
|
|
42
|
+
return value.bind(client);
|
|
43
|
+
}
|
|
44
|
+
return value;
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
// Register all tool groups with the proxy
|
|
48
|
+
registerProjectTools(server, apiClientProxy);
|
|
49
|
+
registerFlowTools(server, apiClientProxy);
|
|
50
|
+
registerRunTools(server, apiClientProxy);
|
|
51
|
+
registerVariableTools(server, apiClientProxy);
|
|
52
|
+
registerUtilityTools(server, apiClientProxy);
|
|
53
|
+
// Register empty resource/prompt handlers to avoid -32601 errors
|
|
54
|
+
server.resource("qualitas", "qualitas://info", async () => ({
|
|
55
|
+
contents: [
|
|
56
|
+
{
|
|
57
|
+
uri: "qualitas://info",
|
|
58
|
+
text: "Qualitas MCP Server - 17 tools for test automation",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
}));
|
|
62
|
+
server.prompt("qualitas-help", "Get help with Qualitas MCP tools", async () => ({
|
|
63
|
+
messages: [
|
|
64
|
+
{
|
|
65
|
+
role: "user",
|
|
66
|
+
content: {
|
|
67
|
+
type: "text",
|
|
68
|
+
text: "You have access to 17 Qualitas tools for test automation. Use list_projects to see projects, generate_flow_from_scenario to create flows from natural language, and run_flow to execute tests.",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
}));
|
|
73
|
+
// Start transport
|
|
74
|
+
async function main() {
|
|
75
|
+
const transport = new StdioServerTransport();
|
|
76
|
+
await server.connect(transport);
|
|
77
|
+
}
|
|
78
|
+
main().catch((error) => {
|
|
79
|
+
process.stderr.write(`Server error: ${error}\n`);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const ResponseFormatSchema: z.ZodDefault<z.ZodEnum<["markdown", "json"]>>;
|
|
3
|
+
export declare const PaginationSchema: z.ZodObject<{
|
|
4
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
5
|
+
offset: z.ZodDefault<z.ZodNumber>;
|
|
6
|
+
}, "strict", z.ZodTypeAny, {
|
|
7
|
+
limit: number;
|
|
8
|
+
offset: number;
|
|
9
|
+
}, {
|
|
10
|
+
limit?: number | undefined;
|
|
11
|
+
offset?: number | undefined;
|
|
12
|
+
}>;
|
|
13
|
+
export declare const IdSchema: z.ZodObject<{
|
|
14
|
+
id: z.ZodString;
|
|
15
|
+
}, "strict", z.ZodTypeAny, {
|
|
16
|
+
id: string;
|
|
17
|
+
}, {
|
|
18
|
+
id: string;
|
|
19
|
+
}>;
|
|
20
|
+
//# sourceMappingURL=common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/schemas/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,oBAAoB,+CAA2I,CAAC;AAE7K,eAAO,MAAM,gBAAgB;;;;;;;;;EAGlB,CAAC;AAEZ,eAAO,MAAM,QAAQ;;;;;;EAEV,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const ResponseFormatSchema = z.enum(["markdown", "json"]).default("markdown").describe("Output format: 'markdown' for human-readable or 'json' for machine-readable");
|
|
3
|
+
export const PaginationSchema = z.object({
|
|
4
|
+
limit: z.number().int().min(1).max(100).default(20).describe("Maximum results to return (1-100)"),
|
|
5
|
+
offset: z.number().int().min(0).default(0).describe("Number of results to skip for pagination"),
|
|
6
|
+
}).strict();
|
|
7
|
+
export const IdSchema = z.object({
|
|
8
|
+
id: z.string().uuid("Invalid UUID format").describe("Resource ID"),
|
|
9
|
+
}).strict();
|
|
10
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/schemas/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,6EAA6E,CAAC,CAAC;AAE7K,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IACjG,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,0CAA0C,CAAC;CAChG,CAAC,CAAC,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC;CACnE,CAAC,CAAC,MAAM,EAAE,CAAC"}
|