@debugg-ai/debugg-ai-mcp 2.9.3 → 3.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 +29 -0
- package/README.md +61 -22
- package/dist/handlers/environmentHandler.js +27 -0
- package/dist/handlers/executionsHandler.js +9 -0
- package/dist/handlers/index.js +7 -2
- package/dist/handlers/projectHandler.js +14 -0
- package/dist/handlers/testCaseHandler.js +22 -0
- package/dist/handlers/testSuiteHandler.js +34 -0
- package/dist/handlers/triggerCrawlHandler.js +1 -2
- package/dist/services/workflows.js +23 -10
- package/dist/tools/environment.js +54 -0
- package/dist/tools/executions.js +34 -0
- package/dist/tools/index.js +21 -46
- package/dist/tools/project.js +41 -0
- package/dist/tools/testCase.js +40 -0
- package/dist/tools/testSuite.js +50 -0
- package/dist/tools/triggerCrawl.js +0 -4
- package/dist/types/index.js +55 -1
- package/dist/utils/confirmDestructive.js +48 -0
- package/package.json +5 -1
- package/dist/handlers/deleteProjectHandler.js +0 -39
- package/dist/handlers/updateProjectHandler.js +0 -45
- package/dist/tools/createEnvironment.js +0 -46
- package/dist/tools/createProject.js +0 -27
- package/dist/tools/deleteEnvironment.js +0 -23
- package/dist/tools/deleteProject.js +0 -22
- package/dist/tools/searchEnvironments.js +0 -35
- package/dist/tools/searchExecutions.js +0 -31
- package/dist/tools/searchProjects.js +0 -30
- package/dist/tools/testSuiteTools.js +0 -183
- package/dist/tools/updateEnvironment.js +0 -74
- package/dist/tools/updateProject.js +0 -24
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { TestSuiteInputSchema } from '../types/index.js';
|
|
2
|
+
import { testSuiteHandler } from '../handlers/testSuiteHandler.js';
|
|
3
|
+
const DESCRIPTION = `Manage and run test suites. Identify a suite by suiteUuid, or suiteName + a project identifier (projectUuid|projectName). Pass an "action":
|
|
4
|
+
- "list" {projectUuid|projectName, search?, page?, pageSize?} → paginated suites with status/pass-rate.
|
|
5
|
+
- "create" {name, description, projectUuid|projectName} → create a suite.
|
|
6
|
+
- "run" {suiteUuid|(suiteName+project), targetUrl?} → run all tests async. Poll with action:"results".
|
|
7
|
+
- "results" {suiteUuid|(suiteName+project)} → suite + per-test outcomes.
|
|
8
|
+
- "delete" {suiteUuid|(suiteName+project), confirm?} → soft-delete (DESTRUCTIVE; requires confirmation).`;
|
|
9
|
+
const PROJECT_PROPS = {
|
|
10
|
+
projectUuid: { type: 'string', description: 'Project UUID (or projectName).' },
|
|
11
|
+
projectName: { type: 'string', description: 'Project name (or projectUuid).' },
|
|
12
|
+
};
|
|
13
|
+
const SUITE_PROPS = {
|
|
14
|
+
suiteUuid: { type: 'string', description: 'Test suite UUID.' },
|
|
15
|
+
suiteName: { type: 'string', description: 'Test suite name (requires a project identifier).' },
|
|
16
|
+
};
|
|
17
|
+
export function buildTestSuiteTool() {
|
|
18
|
+
return {
|
|
19
|
+
name: 'test_suite',
|
|
20
|
+
title: 'Test Suite',
|
|
21
|
+
description: DESCRIPTION,
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
action: { type: 'string', enum: ['list', 'create', 'run', 'results', 'delete'], description: 'Operation to perform.' },
|
|
26
|
+
...SUITE_PROPS,
|
|
27
|
+
...PROJECT_PROPS,
|
|
28
|
+
name: { type: 'string', description: '[create] Suite name.' },
|
|
29
|
+
description: { type: 'string', description: '[create] Suite description.' },
|
|
30
|
+
search: { type: 'string', description: '[list] Text filter over name/description.' },
|
|
31
|
+
page: { type: 'number', description: '[list] Page (1-indexed).' },
|
|
32
|
+
pageSize: { type: 'number', description: '[list] Page size (1..100).' },
|
|
33
|
+
targetUrl: { type: 'string', description: '[run] Override the default test target (full URL).' },
|
|
34
|
+
confirm: { type: 'boolean', description: '[delete] Set true to confirm deletion (when the client cannot prompt).' },
|
|
35
|
+
},
|
|
36
|
+
required: ['action'],
|
|
37
|
+
oneOf: [
|
|
38
|
+
{ properties: { action: { const: 'list' } }, required: ['action'] },
|
|
39
|
+
{ properties: { action: { const: 'create' } }, required: ['action', 'name', 'description'] },
|
|
40
|
+
{ properties: { action: { const: 'run' } }, required: ['action'] },
|
|
41
|
+
{ properties: { action: { const: 'results' } }, required: ['action'] },
|
|
42
|
+
{ properties: { action: { const: 'delete' } }, required: ['action'] },
|
|
43
|
+
],
|
|
44
|
+
additionalProperties: false,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export function buildValidatedTestSuiteTool() {
|
|
49
|
+
return { ...buildTestSuiteTool(), inputSchema: TestSuiteInputSchema, handler: testSuiteHandler };
|
|
50
|
+
}
|
|
@@ -71,10 +71,6 @@ export function buildTriggerCrawlTool(ctx) {
|
|
|
71
71
|
type: 'string',
|
|
72
72
|
description: 'The real password for the username above. Do NOT guess.',
|
|
73
73
|
},
|
|
74
|
-
headless: {
|
|
75
|
-
type: 'boolean',
|
|
76
|
-
description: 'Run the browser in headless mode. Defaults to backend configuration.',
|
|
77
|
-
},
|
|
78
74
|
timeoutSeconds: {
|
|
79
75
|
type: 'number',
|
|
80
76
|
description: 'Maximum wall-time the crawl may run, in seconds (1..1800). Backend enforces this per workflow execution.',
|
package/dist/types/index.js
CHANGED
|
@@ -25,7 +25,7 @@ export const TriggerCrawlInputSchema = z.object({
|
|
|
25
25
|
credentialRole: z.string().optional(),
|
|
26
26
|
username: z.string().optional(),
|
|
27
27
|
password: z.string().optional(),
|
|
28
|
-
headless
|
|
28
|
+
// headless is intentionally NOT accepted — the MCP always runs headless (D7).
|
|
29
29
|
timeoutSeconds: z.number().int().positive().max(1800, 'timeoutSeconds cannot exceed 1800 (30 min)').optional(),
|
|
30
30
|
repoName: z.string().optional(),
|
|
31
31
|
}).strict();
|
|
@@ -220,3 +220,57 @@ export const GetTestSuiteResultsInputSchema = z.object({
|
|
|
220
220
|
...suiteIdentifier,
|
|
221
221
|
...projectIdentifier,
|
|
222
222
|
}).strict();
|
|
223
|
+
// ── Consolidated action-based tool schemas (epic yg7o6: 20 → 8 tools) ─────────
|
|
224
|
+
// Each entity tool takes a required `action` discriminator; params validate
|
|
225
|
+
// per-action. Delete branches carry an optional `confirm` (guarded by D2).
|
|
226
|
+
const _page = z.number().int().min(1).optional();
|
|
227
|
+
const _pageSize = z.number().int().min(1).optional();
|
|
228
|
+
export const ProjectInputSchema = z.discriminatedUnion('action', [
|
|
229
|
+
z.object({ action: z.literal('get'), uuid: z.string().uuid() }).strict(),
|
|
230
|
+
z.object({ action: z.literal('list'), q: z.string().min(1).optional(), page: _page, pageSize: _pageSize }).strict(),
|
|
231
|
+
z.object({
|
|
232
|
+
action: z.literal('create'),
|
|
233
|
+
name: z.string().min(1),
|
|
234
|
+
platform: z.string().min(1),
|
|
235
|
+
teamUuid: z.string().uuid().optional(),
|
|
236
|
+
teamName: z.string().min(1).optional(),
|
|
237
|
+
repoUuid: z.string().uuid().optional(),
|
|
238
|
+
repoName: z.string().min(1).optional(),
|
|
239
|
+
}).strict(),
|
|
240
|
+
]).superRefine((v, ctx) => {
|
|
241
|
+
if (v.action === 'create') {
|
|
242
|
+
if (v.teamUuid && v.teamName)
|
|
243
|
+
ctx.addIssue({ code: 'custom', message: 'Provide teamUuid OR teamName, not both.' });
|
|
244
|
+
if (v.repoUuid && v.repoName)
|
|
245
|
+
ctx.addIssue({ code: 'custom', message: 'Provide repoUuid OR repoName, not both.' });
|
|
246
|
+
if (!v.teamUuid && !v.teamName)
|
|
247
|
+
ctx.addIssue({ code: 'custom', message: 'Must provide teamUuid or teamName.' });
|
|
248
|
+
if (!v.repoUuid && !v.repoName)
|
|
249
|
+
ctx.addIssue({ code: 'custom', message: 'Must provide repoUuid or repoName.' });
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
export const EnvironmentInputSchema = z.discriminatedUnion('action', [
|
|
253
|
+
z.object({ action: z.literal('get'), uuid: z.string().uuid(), projectUuid: z.string().uuid().optional() }).strict(),
|
|
254
|
+
z.object({ action: z.literal('list'), projectUuid: z.string().uuid().optional(), q: z.string().min(1).optional(), page: _page, pageSize: _pageSize }).strict(),
|
|
255
|
+
z.object({ action: z.literal('create'), name: z.string().min(1), url: z.string().url('url is required for standard environments'), description: z.string().optional(), projectUuid: z.string().uuid().optional(), credentials: z.array(CredentialSeedSchema).optional() }).strict(),
|
|
256
|
+
z.object({ action: z.literal('update'), uuid: z.string().uuid(), name: z.string().min(1).optional(), url: z.string().url().optional(), description: z.string().optional(), projectUuid: z.string().uuid().optional(), addCredentials: z.array(CredentialSeedSchema).optional(), updateCredentials: z.array(CredentialUpdateSchema).optional(), removeCredentialIds: z.array(z.string().uuid()).optional() }).strict(),
|
|
257
|
+
z.object({ action: z.literal('delete'), uuid: z.string().uuid(), projectUuid: z.string().uuid().optional(), confirm: z.boolean().optional() }).strict(),
|
|
258
|
+
]);
|
|
259
|
+
export const TestSuiteInputSchema = z.discriminatedUnion('action', [
|
|
260
|
+
z.object({ action: z.literal('list'), ...projectIdentifier, search: z.string().optional(), page: _page, pageSize: z.number().int().min(1).max(100).optional() }).strict(),
|
|
261
|
+
z.object({ action: z.literal('create'), name: z.string().min(1), description: z.string().min(1), ...projectIdentifier }).strict(),
|
|
262
|
+
z.object({ action: z.literal('run'), ...suiteIdentifier, ...projectIdentifier, targetUrl: z.string().url().optional() }).strict(),
|
|
263
|
+
z.object({ action: z.literal('results'), ...suiteIdentifier, ...projectIdentifier }).strict(),
|
|
264
|
+
z.object({ action: z.literal('delete'), ...suiteIdentifier, ...projectIdentifier, confirm: z.boolean().optional() }).strict(),
|
|
265
|
+
]);
|
|
266
|
+
export const TestCaseInputSchema = z.discriminatedUnion('action', [
|
|
267
|
+
z.object({ action: z.literal('create'), name: z.string().min(1), description: z.string().min(1), agentTaskDescription: z.string().min(1), ...suiteIdentifier, ...projectIdentifier, relativeUrl: z.string().regex(/^\//, 'Must start with /').optional(), maxSteps: z.number().int().min(1).max(100).optional() }).strict(),
|
|
268
|
+
z.object({ action: z.literal('update'), testUuid: z.string().uuid(), name: z.string().min(1).optional(), description: z.string().min(1).optional(), agentTaskDescription: z.string().min(1).optional() }).strict(),
|
|
269
|
+
z.object({ action: z.literal('delete'), testUuid: z.string().uuid(), confirm: z.boolean().optional() }).strict(),
|
|
270
|
+
]);
|
|
271
|
+
// NOTE: D6 (recency sort) deferred — the backend listExecutions has no ordering
|
|
272
|
+
// param; threading real sort needs a backend change. Tracked, not shipped here.
|
|
273
|
+
export const ExecutionsInputSchema = z.discriminatedUnion('action', [
|
|
274
|
+
z.object({ action: z.literal('get'), uuid: z.string().uuid() }).strict(),
|
|
275
|
+
z.object({ action: z.literal('list'), projectUuid: z.string().uuid().optional(), status: z.string().min(1).optional(), page: _page, pageSize: _pageSize }).strict(),
|
|
276
|
+
]);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Destructive-action guard (epic debugg_ai_mcp-yg7o6, decision D2).
|
|
3
|
+
*
|
|
4
|
+
* Consolidated entity tools expose a `delete` action. Before any delete runs we
|
|
5
|
+
* require confirmation:
|
|
6
|
+
* - If the client supports elicitation (ctx.elicit present), prompt for it.
|
|
7
|
+
* - Otherwise fall back to a required `confirm: true` argument.
|
|
8
|
+
*
|
|
9
|
+
* This keeps deletes safe on EVERY client without depending on the elicitation
|
|
10
|
+
* epic — that epic only has to populate `ctx.elicit`; the confirm-arg path here
|
|
11
|
+
* ships standalone.
|
|
12
|
+
*/
|
|
13
|
+
/** Action names treated as destructive. Currently just `delete`. */
|
|
14
|
+
export const DESTRUCTIVE_ACTIONS = new Set(['delete']);
|
|
15
|
+
export function isDestructiveAction(action) {
|
|
16
|
+
return DESTRUCTIVE_ACTIONS.has(action);
|
|
17
|
+
}
|
|
18
|
+
function refusal(error, message) {
|
|
19
|
+
return {
|
|
20
|
+
content: [{ type: 'text', text: JSON.stringify({ error, message }, null, 2) }],
|
|
21
|
+
isError: true,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Gate a destructive action.
|
|
26
|
+
*
|
|
27
|
+
* @returns `null` to proceed, or a `ToolResponse` (isError) to abort the call.
|
|
28
|
+
*/
|
|
29
|
+
export async function ensureConfirmed(action, label, input, ctx) {
|
|
30
|
+
if (!isDestructiveAction(action))
|
|
31
|
+
return null;
|
|
32
|
+
if (ctx.elicit) {
|
|
33
|
+
const res = await ctx.elicit({
|
|
34
|
+
message: `Delete ${label}? This cannot be undone.`,
|
|
35
|
+
requestedSchema: {
|
|
36
|
+
type: 'object',
|
|
37
|
+
properties: { confirm: { type: 'boolean', description: 'Confirm deletion of ' + label } },
|
|
38
|
+
required: ['confirm'],
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
if (res.action === 'accept' && res.content?.confirm === true)
|
|
42
|
+
return null;
|
|
43
|
+
return refusal('confirmation_declined', `Deletion of ${label} was not confirmed.`);
|
|
44
|
+
}
|
|
45
|
+
if (input.confirm === true)
|
|
46
|
+
return null;
|
|
47
|
+
return refusal('confirmation_required', `Refusing to delete ${label} without confirmation. Pass confirm:true, or use an elicitation-capable client.`);
|
|
48
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@debugg-ai/debugg-ai-mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Zero-Config, Fully AI-Managed End-to-End Testing for all code gen platforms.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -48,6 +48,10 @@
|
|
|
48
48
|
],
|
|
49
49
|
"author": "Quinn Osha",
|
|
50
50
|
"license": "Apache-2.0",
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "git+https://github.com/debugg-ai/debugg-ai-mcp.git"
|
|
54
|
+
},
|
|
51
55
|
"homepage": "https://debugg.ai",
|
|
52
56
|
"bugs": "https://github.com/debugg-ai/debugg-ai-mcp/issues",
|
|
53
57
|
"changelog": "https://github.com/debugg-ai/debugg-ai-mcp/CHANGELOG.md",
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { Logger } from '../utils/logger.js';
|
|
2
|
-
import { handleExternalServiceError } from '../utils/errors.js';
|
|
3
|
-
import { DebuggAIServerClient } from '../services/index.js';
|
|
4
|
-
import { config } from '../config/index.js';
|
|
5
|
-
const logger = new Logger({ module: 'deleteProjectHandler' });
|
|
6
|
-
function notFound(uuid) {
|
|
7
|
-
return {
|
|
8
|
-
content: [{ type: 'text', text: JSON.stringify({
|
|
9
|
-
error: 'NotFound',
|
|
10
|
-
message: `Project ${uuid} not found.`,
|
|
11
|
-
uuid,
|
|
12
|
-
}, null, 2) }],
|
|
13
|
-
isError: true,
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
export async function deleteProjectHandler(input, _context) {
|
|
17
|
-
const start = Date.now();
|
|
18
|
-
logger.toolStart('delete_project', { uuid: input.uuid });
|
|
19
|
-
try {
|
|
20
|
-
const client = new DebuggAIServerClient(config.api.key);
|
|
21
|
-
await client.init();
|
|
22
|
-
try {
|
|
23
|
-
await client.deleteProject(input.uuid);
|
|
24
|
-
logger.toolComplete('delete_project', Date.now() - start);
|
|
25
|
-
return {
|
|
26
|
-
content: [{ type: 'text', text: JSON.stringify({ deleted: true, uuid: input.uuid }, null, 2) }],
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
catch (err) {
|
|
30
|
-
if (err?.statusCode === 404 || err?.response?.status === 404)
|
|
31
|
-
return notFound(input.uuid);
|
|
32
|
-
throw err;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
catch (error) {
|
|
36
|
-
logger.toolError('delete_project', error, Date.now() - start);
|
|
37
|
-
throw handleExternalServiceError(error, 'DebuggAI', 'delete_project');
|
|
38
|
-
}
|
|
39
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { Logger } from '../utils/logger.js';
|
|
2
|
-
import { handleExternalServiceError } from '../utils/errors.js';
|
|
3
|
-
import { DebuggAIServerClient } from '../services/index.js';
|
|
4
|
-
import { config } from '../config/index.js';
|
|
5
|
-
const logger = new Logger({ module: 'updateProjectHandler' });
|
|
6
|
-
function notFound(uuid) {
|
|
7
|
-
return {
|
|
8
|
-
content: [{ type: 'text', text: JSON.stringify({
|
|
9
|
-
error: 'NotFound',
|
|
10
|
-
message: `Project ${uuid} not found.`,
|
|
11
|
-
uuid,
|
|
12
|
-
}, null, 2) }],
|
|
13
|
-
isError: true,
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
export async function updateProjectHandler(input, _context) {
|
|
17
|
-
const start = Date.now();
|
|
18
|
-
logger.toolStart('update_project', {
|
|
19
|
-
uuid: input.uuid,
|
|
20
|
-
patchKeys: Object.keys(input).filter(k => k !== 'uuid'),
|
|
21
|
-
});
|
|
22
|
-
try {
|
|
23
|
-
const client = new DebuggAIServerClient(config.api.key);
|
|
24
|
-
await client.init();
|
|
25
|
-
try {
|
|
26
|
-
const project = await client.updateProject(input.uuid, {
|
|
27
|
-
name: input.name,
|
|
28
|
-
description: input.description,
|
|
29
|
-
});
|
|
30
|
-
logger.toolComplete('update_project', Date.now() - start);
|
|
31
|
-
return {
|
|
32
|
-
content: [{ type: 'text', text: JSON.stringify({ updated: true, project }, null, 2) }],
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
catch (err) {
|
|
36
|
-
if (err?.statusCode === 404 || err?.response?.status === 404)
|
|
37
|
-
return notFound(input.uuid);
|
|
38
|
-
throw err;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
logger.toolError('update_project', error, Date.now() - start);
|
|
43
|
-
throw handleExternalServiceError(error, 'DebuggAI', 'update_project');
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { CreateEnvironmentInputSchema } from '../types/index.js';
|
|
2
|
-
import { createEnvironmentHandler } from '../handlers/createEnvironmentHandler.js';
|
|
3
|
-
const DESCRIPTION = `Create a new environment under a DebuggAI project. Both name and url are required (backend rejects standard environments without a URL). Optional description. Defaults to the project resolved from the current git repo; pass projectUuid to target a different project (get UUIDs via search_projects).
|
|
4
|
-
|
|
5
|
-
OPTIONAL credentials seed: pass \`credentials: [{label, username, password, role?}]\` to create login credentials alongside the environment in a single call. Each cred is created best-effort; failures go to \`credentialWarnings\` without blocking env creation. Passwords are write-only and NEVER returned.
|
|
6
|
-
|
|
7
|
-
Returns the created environment's uuid (and the seeded credentials, if any). Reference the env uuid when running check_app_in_browser.`;
|
|
8
|
-
export function buildCreateEnvironmentTool() {
|
|
9
|
-
return {
|
|
10
|
-
name: 'create_environment',
|
|
11
|
-
title: 'Create Project Environment',
|
|
12
|
-
description: DESCRIPTION,
|
|
13
|
-
inputSchema: {
|
|
14
|
-
type: 'object',
|
|
15
|
-
properties: {
|
|
16
|
-
name: {
|
|
17
|
-
type: 'string',
|
|
18
|
-
description: 'Short label for the environment (e.g. "staging", "production"). Required.',
|
|
19
|
-
minLength: 1,
|
|
20
|
-
},
|
|
21
|
-
url: {
|
|
22
|
-
type: 'string',
|
|
23
|
-
description: 'Base URL for the environment (e.g. https://staging.example.com). Required.',
|
|
24
|
-
},
|
|
25
|
-
description: {
|
|
26
|
-
type: 'string',
|
|
27
|
-
description: 'Optional: free-text description.',
|
|
28
|
-
},
|
|
29
|
-
projectUuid: {
|
|
30
|
-
type: 'string',
|
|
31
|
-
description: 'Optional: UUID of the target project. Defaults to the project resolved from the current git repo.',
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
required: ['name', 'url'],
|
|
35
|
-
additionalProperties: false,
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
export function buildValidatedCreateEnvironmentTool() {
|
|
40
|
-
const tool = buildCreateEnvironmentTool();
|
|
41
|
-
return {
|
|
42
|
-
...tool,
|
|
43
|
-
inputSchema: CreateEnvironmentInputSchema,
|
|
44
|
-
handler: createEnvironmentHandler,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { CreateProjectInputSchema } from '../types/index.js';
|
|
2
|
-
import { createProjectHandler } from '../handlers/createProjectHandler.js';
|
|
3
|
-
const DESCRIPTION = `Create a new DebuggAI project. Required: name, platform (e.g. "web"), plus a team and a repo. Team and repo each accept EITHER a UUID or a name: pass teamUuid OR teamName, and repoUuid OR repoName. Name resolution does a backend search with case-insensitive exact match (returns AmbiguousMatch with candidates on multiple hits, NotFound on no hit). The repo must be GitHub-linked to the account. Returns {created: true, project: {uuid, name, slug, platform, repoName, ...}}.`;
|
|
4
|
-
export function buildCreateProjectTool() {
|
|
5
|
-
return {
|
|
6
|
-
name: 'create_project',
|
|
7
|
-
title: 'Create Project',
|
|
8
|
-
description: DESCRIPTION,
|
|
9
|
-
inputSchema: {
|
|
10
|
-
type: 'object',
|
|
11
|
-
properties: {
|
|
12
|
-
name: { type: 'string', description: 'Project name. Required.', minLength: 1 },
|
|
13
|
-
platform: { type: 'string', description: 'Platform (e.g. "web"). Required.', minLength: 1 },
|
|
14
|
-
teamUuid: { type: 'string', description: 'Team UUID. Provide teamUuid OR teamName, not both.' },
|
|
15
|
-
teamName: { type: 'string', description: 'Team name (backend-resolved, case-insensitive exact match). Provide teamUuid OR teamName, not both.' },
|
|
16
|
-
repoUuid: { type: 'string', description: 'GitHub repo UUID. Provide repoUuid OR repoName, not both. Repo must be GitHub-linked.' },
|
|
17
|
-
repoName: { type: 'string', description: 'GitHub repo name, e.g. "org/repo" (backend-resolved, case-insensitive exact match). Provide repoUuid OR repoName, not both.' },
|
|
18
|
-
},
|
|
19
|
-
required: ['name', 'platform'],
|
|
20
|
-
additionalProperties: false,
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
export function buildValidatedCreateProjectTool() {
|
|
25
|
-
const tool = buildCreateProjectTool();
|
|
26
|
-
return { ...tool, inputSchema: CreateProjectInputSchema, handler: createProjectHandler };
|
|
27
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { DeleteEnvironmentInputSchema } from '../types/index.js';
|
|
2
|
-
import { deleteEnvironmentHandler } from '../handlers/deleteEnvironmentHandler.js';
|
|
3
|
-
const DESCRIPTION = `Delete an environment by UUID. Returns {deleted: true, uuid}. Destructive — cascades per backend behavior (credentials under the env are typically removed). Defaults to the project resolved from the current git repo; pass projectUuid to target a different project. Returns isError:true with NotFound when the uuid doesn't exist or was already deleted.`;
|
|
4
|
-
export function buildDeleteEnvironmentTool() {
|
|
5
|
-
return {
|
|
6
|
-
name: 'delete_environment',
|
|
7
|
-
title: 'Delete Environment',
|
|
8
|
-
description: DESCRIPTION,
|
|
9
|
-
inputSchema: {
|
|
10
|
-
type: 'object',
|
|
11
|
-
properties: {
|
|
12
|
-
uuid: { type: 'string', description: 'UUID of the environment to delete. Required.' },
|
|
13
|
-
projectUuid: { type: 'string', description: 'Optional: UUID of the target project. Defaults to git-auto-detect.' },
|
|
14
|
-
},
|
|
15
|
-
required: ['uuid'],
|
|
16
|
-
additionalProperties: false,
|
|
17
|
-
},
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
export function buildValidatedDeleteEnvironmentTool() {
|
|
21
|
-
const tool = buildDeleteEnvironmentTool();
|
|
22
|
-
return { ...tool, inputSchema: DeleteEnvironmentInputSchema, handler: deleteEnvironmentHandler };
|
|
23
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { DeleteProjectInputSchema } from '../types/index.js';
|
|
2
|
-
import { deleteProjectHandler } from '../handlers/deleteProjectHandler.js';
|
|
3
|
-
const DESCRIPTION = `Delete a project by UUID. Returns {deleted:true, uuid}. **DESTRUCTIVE** — removes the project and its associated environments, credentials, and test history. No undo. Returns isError:true + NotFound when already deleted or uuid doesn't exist.`;
|
|
4
|
-
export function buildDeleteProjectTool() {
|
|
5
|
-
return {
|
|
6
|
-
name: 'delete_project',
|
|
7
|
-
title: 'Delete Project',
|
|
8
|
-
description: DESCRIPTION,
|
|
9
|
-
inputSchema: {
|
|
10
|
-
type: 'object',
|
|
11
|
-
properties: {
|
|
12
|
-
uuid: { type: 'string', description: 'UUID of the project to delete. Required.' },
|
|
13
|
-
},
|
|
14
|
-
required: ['uuid'],
|
|
15
|
-
additionalProperties: false,
|
|
16
|
-
},
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
export function buildValidatedDeleteProjectTool() {
|
|
20
|
-
const tool = buildDeleteProjectTool();
|
|
21
|
-
return { ...tool, inputSchema: DeleteProjectInputSchema, handler: deleteProjectHandler };
|
|
22
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { SearchEnvironmentsInputSchema } from '../types/index.js';
|
|
2
|
-
import { searchEnvironmentsHandler } from '../handlers/searchEnvironmentsHandler.js';
|
|
3
|
-
const DESCRIPTION = `Search or look up environments, with credentials expanded inline per environment.
|
|
4
|
-
|
|
5
|
-
Two modes:
|
|
6
|
-
- uuid mode: {"uuid": "<env-uuid>"} → single env with full detail + its credentials. NotFound if the uuid doesn't exist.
|
|
7
|
-
- filter mode: omit uuid, optionally {"q": "<keyword>", "projectUuid", "page", "pageSize"} → paginated envs, each with its credentials.
|
|
8
|
-
|
|
9
|
-
Project resolution: if projectUuid is omitted, the current git repo's origin is auto-resolved to a DebuggAI project. Returns {error:"NoProjectResolved", environments:[]} if neither is available.
|
|
10
|
-
|
|
11
|
-
Credentials are returned inline per env as {uuid, label, username, role}. Password is NEVER returned — the handler defensively strips it regardless of what the service layer provides.
|
|
12
|
-
|
|
13
|
-
Response: {project, filter, pageInfo, environments[]} — each environment includes a credentials[] array.`;
|
|
14
|
-
export function buildSearchEnvironmentsTool() {
|
|
15
|
-
return {
|
|
16
|
-
name: 'search_environments',
|
|
17
|
-
title: 'Search Environments',
|
|
18
|
-
description: DESCRIPTION,
|
|
19
|
-
inputSchema: {
|
|
20
|
-
type: 'object',
|
|
21
|
-
properties: {
|
|
22
|
-
uuid: { type: 'string', description: 'Environment UUID. Returns single env with credentials inline. Mutually exclusive with projectUuid/q filter params.' },
|
|
23
|
-
projectUuid: { type: 'string', description: 'Override the auto-detected project. Used in filter mode.' },
|
|
24
|
-
q: { type: 'string', description: 'Free-text search over environment name. Mutually exclusive with uuid.' },
|
|
25
|
-
page: { type: 'number', description: 'Page number (1-indexed).' },
|
|
26
|
-
pageSize: { type: 'number', description: 'Page size (1..200). Default 20.' },
|
|
27
|
-
},
|
|
28
|
-
additionalProperties: false,
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
export function buildValidatedSearchEnvironmentsTool() {
|
|
33
|
-
const tool = buildSearchEnvironmentsTool();
|
|
34
|
-
return { ...tool, inputSchema: SearchEnvironmentsInputSchema, handler: searchEnvironmentsHandler };
|
|
35
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { SearchExecutionsInputSchema } from '../types/index.js';
|
|
2
|
-
import { searchExecutionsHandler } from '../handlers/searchExecutionsHandler.js';
|
|
3
|
-
const DESCRIPTION = `Search or look up workflow executions (history of check_app_in_browser, trigger_crawl, and other workflow runs).
|
|
4
|
-
|
|
5
|
-
Two modes:
|
|
6
|
-
- uuid mode: {"uuid": "<execution-uuid>"} → single execution with FULL detail including nodeExecutions, state, errorInfo. NotFound if the uuid doesn't exist.
|
|
7
|
-
- filter mode: {"status": "completed"|"running"|"failed"|"cancelled", "projectUuid": "...", "page", "pageSize"} → paginated summaries.
|
|
8
|
-
|
|
9
|
-
Response shape: {filter, pageInfo, executions[]}. Summary items have outcome/status/durationMs/timestamps; uuid-mode items additionally have nodeExecutions + state + errorInfo.`;
|
|
10
|
-
export function buildSearchExecutionsTool() {
|
|
11
|
-
return {
|
|
12
|
-
name: 'search_executions',
|
|
13
|
-
title: 'Search Workflow Executions',
|
|
14
|
-
description: DESCRIPTION,
|
|
15
|
-
inputSchema: {
|
|
16
|
-
type: 'object',
|
|
17
|
-
properties: {
|
|
18
|
-
uuid: { type: 'string', description: 'Execution UUID. Returns single execution with full detail. Mutually exclusive with projectUuid/status filters.' },
|
|
19
|
-
projectUuid: { type: 'string', description: 'Filter by project UUID.' },
|
|
20
|
-
status: { type: 'string', description: 'Filter by status: completed | running | failed | cancelled | pending.' },
|
|
21
|
-
page: { type: 'number', description: 'Page number (1-indexed).' },
|
|
22
|
-
pageSize: { type: 'number', description: 'Page size (1..200). Default 20.' },
|
|
23
|
-
},
|
|
24
|
-
additionalProperties: false,
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
export function buildValidatedSearchExecutionsTool() {
|
|
29
|
-
const tool = buildSearchExecutionsTool();
|
|
30
|
-
return { ...tool, inputSchema: SearchExecutionsInputSchema, handler: searchExecutionsHandler };
|
|
31
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { SearchProjectsInputSchema } from '../types/index.js';
|
|
2
|
-
import { searchProjectsHandler } from '../handlers/searchProjectsHandler.js';
|
|
3
|
-
const DESCRIPTION = `Search or look up projects.
|
|
4
|
-
|
|
5
|
-
Two modes:
|
|
6
|
-
- uuid mode: pass {"uuid": "<project-uuid>"} → returns that project with the curated detail view (uuid, name, slug, platform, repoName, description, status, language, framework, timestamp, lastMod), or isError:true NotFound.
|
|
7
|
-
- filter mode: omit uuid, optionally pass {"q": "<keyword>", "page": 1, "pageSize": 20} → returns a paginated list of summaries (uuid, name, slug, repoName).
|
|
8
|
-
|
|
9
|
-
Response shape is always {filter, pageInfo, projects[]}. uuid mode returns exactly one project; filter mode returns summaries.`;
|
|
10
|
-
export function buildSearchProjectsTool() {
|
|
11
|
-
return {
|
|
12
|
-
name: 'search_projects',
|
|
13
|
-
title: 'Search Projects',
|
|
14
|
-
description: DESCRIPTION,
|
|
15
|
-
inputSchema: {
|
|
16
|
-
type: 'object',
|
|
17
|
-
properties: {
|
|
18
|
-
uuid: { type: 'string', description: 'Project UUID. When provided, returns exactly that project with full detail. Mutually exclusive with q.' },
|
|
19
|
-
q: { type: 'string', description: 'Free-text search (backend-side). Mutually exclusive with uuid.' },
|
|
20
|
-
page: { type: 'number', description: 'Page number (1-indexed). Default 1.' },
|
|
21
|
-
pageSize: { type: 'number', description: 'Page size (1..200). Default 20.' },
|
|
22
|
-
},
|
|
23
|
-
additionalProperties: false,
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
export function buildValidatedSearchProjectsTool() {
|
|
28
|
-
const tool = buildSearchProjectsTool();
|
|
29
|
-
return { ...tool, inputSchema: SearchProjectsInputSchema, handler: searchProjectsHandler };
|
|
30
|
-
}
|