@debugg-ai/debugg-ai-mcp 1.0.54 → 1.0.56
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/README.md +57 -6
- package/dist/handlers/cancelExecutionHandler.js +41 -0
- package/dist/handlers/createCredentialHandler.js +60 -0
- package/dist/handlers/createEnvironmentHandler.js +54 -0
- package/dist/handlers/deleteCredentialHandler.js +51 -0
- package/dist/handlers/deleteEnvironmentHandler.js +51 -0
- package/dist/handlers/deleteProjectHandler.js +39 -0
- package/dist/handlers/getCredentialHandler.js +49 -0
- package/dist/handlers/getEnvironmentHandler.js +49 -0
- package/dist/handlers/getExecutionHandler.js +37 -0
- package/dist/handlers/getProjectHandler.js +37 -0
- package/dist/handlers/index.js +17 -0
- package/dist/handlers/listCredentialsHandler.js +71 -0
- package/dist/handlers/listEnvironmentsHandler.js +59 -0
- package/dist/handlers/listExecutionsHandler.js +31 -0
- package/dist/handlers/listProjectsHandler.js +30 -0
- package/dist/handlers/testPageChangesHandler.js +4 -1
- package/dist/handlers/updateCredentialHandler.js +70 -0
- package/dist/handlers/updateEnvironmentHandler.js +59 -0
- package/dist/handlers/updateProjectHandler.js +45 -0
- package/dist/index.js +2 -19
- package/dist/services/index.js +243 -0
- package/dist/services/projectContext.js +42 -26
- package/dist/services/workflows.js +26 -0
- package/dist/tools/cancelExecution.js +22 -0
- package/dist/tools/createCredential.js +52 -0
- package/dist/tools/createEnvironment.js +42 -0
- package/dist/tools/deleteCredential.js +24 -0
- package/dist/tools/deleteEnvironment.js +23 -0
- package/dist/tools/deleteProject.js +22 -0
- package/dist/tools/getCredential.js +24 -0
- package/dist/tools/getEnvironment.js +23 -0
- package/dist/tools/getExecution.js +22 -0
- package/dist/tools/getProject.js +22 -0
- package/dist/tools/index.js +61 -5
- package/dist/tools/listCredentials.js +40 -0
- package/dist/tools/listEnvironments.js +32 -0
- package/dist/tools/listExecutions.js +22 -0
- package/dist/tools/listProjects.js +28 -0
- package/dist/tools/updateCredential.js +28 -0
- package/dist/tools/updateEnvironment.js +26 -0
- package/dist/tools/updateProject.js +24 -0
- package/dist/types/index.js +82 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,20 +30,67 @@ Or with Docker:
|
|
|
30
30
|
docker run -i --rm --init -e DEBUGGAI_API_KEY=your_api_key quinnosha/debugg-ai-mcp
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
##
|
|
33
|
+
## Tools
|
|
34
|
+
|
|
35
|
+
The server exposes **18** tools. The headline one is `check_app_in_browser`; the rest manage projects, environments, credentials, and workflow execution history.
|
|
36
|
+
|
|
37
|
+
### `check_app_in_browser`
|
|
34
38
|
|
|
35
39
|
Runs an AI browser agent against your app. The agent navigates, interacts, and reports back with screenshots.
|
|
36
40
|
|
|
37
41
|
| Parameter | Type | Description |
|
|
38
42
|
|-----------|------|-------------|
|
|
39
43
|
| `description` | string **required** | What to test (natural language) |
|
|
40
|
-
| `url` | string | Target URL —
|
|
41
|
-
| `localPort` | number | Local dev server port — tunnel created automatically |
|
|
44
|
+
| `url` | string **required** | Target URL — a localhost URL (`http://localhost:3000`) is auto-tunneled via ngrok |
|
|
42
45
|
| `environmentId` | string | UUID of a specific environment |
|
|
43
46
|
| `credentialId` | string | UUID of a specific credential |
|
|
44
47
|
| `credentialRole` | string | Pick a credential by role (e.g. `admin`, `guest`) |
|
|
45
|
-
| `username` | string | Username for login |
|
|
46
|
-
| `password` | string | Password for login |
|
|
48
|
+
| `username` | string | Username for login (ephemeral — not persisted) |
|
|
49
|
+
| `password` | string | Password for login (ephemeral — not persisted) |
|
|
50
|
+
| `repoName` | string | Override auto-detected git repo name (e.g. `my-org/my-repo`) |
|
|
51
|
+
|
|
52
|
+
### Project management
|
|
53
|
+
|
|
54
|
+
| Tool | Purpose |
|
|
55
|
+
|------|---------|
|
|
56
|
+
| `list_projects` | List projects accessible to your API key. Optional `q` for name/repo search. |
|
|
57
|
+
| `get_project` | Fetch a project by `uuid`. Simplified shape (no team/runner internals). |
|
|
58
|
+
| `update_project` | PATCH a project's `name` or `description`. |
|
|
59
|
+
| `delete_project` | Destructive delete. Cascades envs, creds, and history. |
|
|
60
|
+
|
|
61
|
+
### Environment management (scoped to a project)
|
|
62
|
+
|
|
63
|
+
| Tool | Purpose |
|
|
64
|
+
|------|---------|
|
|
65
|
+
| `list_environments` | List envs for a project. Optional `q`, `projectUuid`. |
|
|
66
|
+
| `create_environment` | Create a new env. Requires `name` + `url`. |
|
|
67
|
+
| `get_environment` | Fetch an env by `uuid`. |
|
|
68
|
+
| `update_environment` | PATCH `name` / `url` / `description`. |
|
|
69
|
+
| `delete_environment` | Destructive delete. |
|
|
70
|
+
|
|
71
|
+
### Credential management (scoped to an environment)
|
|
72
|
+
|
|
73
|
+
| Tool | Purpose |
|
|
74
|
+
|------|---------|
|
|
75
|
+
| `list_credentials` | List creds. Optional `environmentId`, `q`, `role` (server-side filter). **Never returns passwords.** |
|
|
76
|
+
| `create_credential` | Create a cred. Requires `environmentId`, `label`, `username`, `password`; optional `role`. |
|
|
77
|
+
| `get_credential` | Fetch by `uuid` + `environmentId`. |
|
|
78
|
+
| `update_credential` | Partial PATCH. Pass `password` to rotate — it is never echoed back. |
|
|
79
|
+
| `delete_credential` | Destructive delete. |
|
|
80
|
+
|
|
81
|
+
### Workflow execution history
|
|
82
|
+
|
|
83
|
+
| Tool | Purpose |
|
|
84
|
+
|------|---------|
|
|
85
|
+
| `list_executions` | Paginated history. Optional `status`, `limit`. |
|
|
86
|
+
| `get_execution` | Full detail for a single execution including node-level state. |
|
|
87
|
+
| `cancel_execution` | Cancel an in-flight execution. |
|
|
88
|
+
|
|
89
|
+
### Security invariants
|
|
90
|
+
|
|
91
|
+
- Passwords are write-only. They never appear in any response body from any tool.
|
|
92
|
+
- Tunnel URLs (`*.ngrok.debugg.ai`) are stripped from all browser-agent responses, including agent-authored text.
|
|
93
|
+
- 404s from the backend surface as `isError: true` with `{error: 'NotFound', ...}`, never as thrown exceptions.
|
|
47
94
|
|
|
48
95
|
## Configuration
|
|
49
96
|
|
|
@@ -54,9 +101,13 @@ DEBUGGAI_API_KEY=your_api_key
|
|
|
54
101
|
## Local Development
|
|
55
102
|
|
|
56
103
|
```bash
|
|
57
|
-
npm install
|
|
104
|
+
npm install
|
|
105
|
+
npm run build
|
|
106
|
+
npm run test:e2e # real end-to-end evals against the backend
|
|
58
107
|
```
|
|
59
108
|
|
|
109
|
+
The eval suite spawns the built MCP server as a subprocess, exercises every tool against a real backend, and writes per-flow artifacts to `scripts/evals/artifacts/<timestamp>/`. See `scripts/evals/flows/` for the individual scenarios.
|
|
110
|
+
|
|
60
111
|
## Links
|
|
61
112
|
|
|
62
113
|
[Dashboard](https://app.debugg.ai) · [Docs](https://debugg.ai/docs) · [Issues](https://github.com/debugg-ai/debugg-ai-mcp/issues) · [Discord](https://debugg.ai/discord)
|
|
@@ -0,0 +1,41 @@
|
|
|
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: 'cancelExecutionHandler' });
|
|
6
|
+
function errorResponse(error, message, uuid) {
|
|
7
|
+
return {
|
|
8
|
+
content: [{ type: 'text', text: JSON.stringify({ error, message, uuid }, null, 2) }],
|
|
9
|
+
isError: true,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export async function cancelExecutionHandler(input, _context) {
|
|
13
|
+
const start = Date.now();
|
|
14
|
+
logger.toolStart('cancel_execution', { uuid: input.uuid });
|
|
15
|
+
try {
|
|
16
|
+
const client = new DebuggAIServerClient(config.api.key);
|
|
17
|
+
await client.init();
|
|
18
|
+
try {
|
|
19
|
+
await client.workflows.cancelExecution(input.uuid);
|
|
20
|
+
logger.toolComplete('cancel_execution', Date.now() - start);
|
|
21
|
+
return {
|
|
22
|
+
content: [{ type: 'text', text: JSON.stringify({ cancelled: true, uuid: input.uuid }, null, 2) }],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
const status = err?.statusCode ?? err?.response?.status;
|
|
27
|
+
const detail = err?.responseData?.error ?? err?.message ?? '';
|
|
28
|
+
if (status === 404) {
|
|
29
|
+
return errorResponse('NotFound', `Execution ${input.uuid} not found.`, input.uuid);
|
|
30
|
+
}
|
|
31
|
+
if (status === 409 || /already|completed|cannot.?cancel/i.test(detail)) {
|
|
32
|
+
return errorResponse('AlreadyCompleted', detail || `Execution ${input.uuid} cannot be cancelled.`, input.uuid);
|
|
33
|
+
}
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
logger.toolError('cancel_execution', error, Date.now() - start);
|
|
39
|
+
throw handleExternalServiceError(error, 'DebuggAI', 'cancel_execution');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
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
|
+
import { detectRepoName } from '../utils/gitContext.js';
|
|
6
|
+
const logger = new Logger({ module: 'createCredentialHandler' });
|
|
7
|
+
export async function createCredentialHandler(input, _context) {
|
|
8
|
+
const start = Date.now();
|
|
9
|
+
logger.toolStart('create_credential', {
|
|
10
|
+
environmentId: input.environmentId,
|
|
11
|
+
label: input.label,
|
|
12
|
+
hasRole: !!input.role,
|
|
13
|
+
projectUuid: input.projectUuid,
|
|
14
|
+
});
|
|
15
|
+
try {
|
|
16
|
+
const client = new DebuggAIServerClient(config.api.key);
|
|
17
|
+
await client.init();
|
|
18
|
+
let projectUuid = input.projectUuid;
|
|
19
|
+
if (!projectUuid) {
|
|
20
|
+
const repoName = detectRepoName();
|
|
21
|
+
if (!repoName) {
|
|
22
|
+
return {
|
|
23
|
+
content: [{ type: 'text', text: JSON.stringify({
|
|
24
|
+
error: 'NoProjectResolved',
|
|
25
|
+
message: 'No git repo detected and no projectUuid provided. Pass projectUuid (get it from list_projects) or invoke from a directory with a git origin.',
|
|
26
|
+
}, null, 2) }],
|
|
27
|
+
isError: true,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const project = await client.findProjectByRepoName(repoName);
|
|
31
|
+
if (!project) {
|
|
32
|
+
return {
|
|
33
|
+
content: [{ type: 'text', text: JSON.stringify({
|
|
34
|
+
error: 'NoProjectResolved',
|
|
35
|
+
message: `No DebuggAI project found for repo "${repoName}". Pass projectUuid explicitly.`,
|
|
36
|
+
}, null, 2) }],
|
|
37
|
+
isError: true,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
projectUuid = project.uuid;
|
|
41
|
+
}
|
|
42
|
+
const cred = await client.createCredential(projectUuid, input.environmentId, {
|
|
43
|
+
label: input.label,
|
|
44
|
+
username: input.username,
|
|
45
|
+
password: input.password,
|
|
46
|
+
role: input.role,
|
|
47
|
+
});
|
|
48
|
+
const payload = {
|
|
49
|
+
created: true,
|
|
50
|
+
projectUuid,
|
|
51
|
+
credential: cred,
|
|
52
|
+
};
|
|
53
|
+
logger.toolComplete('create_credential', Date.now() - start);
|
|
54
|
+
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
logger.toolError('create_credential', error, Date.now() - start);
|
|
58
|
+
throw handleExternalServiceError(error, 'DebuggAI', 'create_credential');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
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
|
+
import { detectRepoName } from '../utils/gitContext.js';
|
|
6
|
+
const logger = new Logger({ module: 'createEnvironmentHandler' });
|
|
7
|
+
export async function createEnvironmentHandler(input, _context) {
|
|
8
|
+
const start = Date.now();
|
|
9
|
+
logger.toolStart('create_environment', {
|
|
10
|
+
name: input.name,
|
|
11
|
+
hasUrl: !!input.url,
|
|
12
|
+
projectUuid: input.projectUuid,
|
|
13
|
+
});
|
|
14
|
+
try {
|
|
15
|
+
const client = new DebuggAIServerClient(config.api.key);
|
|
16
|
+
await client.init();
|
|
17
|
+
let projectUuid = input.projectUuid;
|
|
18
|
+
if (!projectUuid) {
|
|
19
|
+
const repoName = detectRepoName();
|
|
20
|
+
if (!repoName) {
|
|
21
|
+
const payload = {
|
|
22
|
+
error: 'NoProjectResolved',
|
|
23
|
+
message: 'No git repo detected and no projectUuid provided. Pass projectUuid (get it from list_projects) or invoke from a directory with a git origin.',
|
|
24
|
+
};
|
|
25
|
+
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }], isError: true };
|
|
26
|
+
}
|
|
27
|
+
const project = await client.findProjectByRepoName(repoName);
|
|
28
|
+
if (!project) {
|
|
29
|
+
const payload = {
|
|
30
|
+
error: 'NoProjectResolved',
|
|
31
|
+
message: `No DebuggAI project found for repo "${repoName}". Pass projectUuid explicitly.`,
|
|
32
|
+
};
|
|
33
|
+
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }], isError: true };
|
|
34
|
+
}
|
|
35
|
+
projectUuid = project.uuid;
|
|
36
|
+
}
|
|
37
|
+
const env = await client.createEnvironment(projectUuid, {
|
|
38
|
+
name: input.name,
|
|
39
|
+
url: input.url,
|
|
40
|
+
description: input.description,
|
|
41
|
+
});
|
|
42
|
+
const payload = {
|
|
43
|
+
created: true,
|
|
44
|
+
projectUuid,
|
|
45
|
+
environment: env,
|
|
46
|
+
};
|
|
47
|
+
logger.toolComplete('create_environment', Date.now() - start);
|
|
48
|
+
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
logger.toolError('create_environment', error, Date.now() - start);
|
|
52
|
+
throw handleExternalServiceError(error, 'DebuggAI', 'create_environment');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
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
|
+
import { detectRepoName } from '../utils/gitContext.js';
|
|
6
|
+
const logger = new Logger({ module: 'deleteCredentialHandler' });
|
|
7
|
+
function notFound(uuid, context) {
|
|
8
|
+
return {
|
|
9
|
+
content: [{ type: 'text', text: JSON.stringify({
|
|
10
|
+
error: 'NotFound',
|
|
11
|
+
message: `Credential ${uuid} not found (${context}).`,
|
|
12
|
+
uuid,
|
|
13
|
+
}, null, 2) }],
|
|
14
|
+
isError: true,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export async function deleteCredentialHandler(input, _context) {
|
|
18
|
+
const start = Date.now();
|
|
19
|
+
logger.toolStart('delete_credential', { uuid: input.uuid, environmentId: input.environmentId });
|
|
20
|
+
try {
|
|
21
|
+
const client = new DebuggAIServerClient(config.api.key);
|
|
22
|
+
await client.init();
|
|
23
|
+
let projectUuid = input.projectUuid;
|
|
24
|
+
if (!projectUuid) {
|
|
25
|
+
const repoName = detectRepoName();
|
|
26
|
+
if (!repoName)
|
|
27
|
+
return notFound(input.uuid, 'no git repo and no projectUuid');
|
|
28
|
+
const project = await client.findProjectByRepoName(repoName);
|
|
29
|
+
if (!project)
|
|
30
|
+
return notFound(input.uuid, `no project for repo "${repoName}"`);
|
|
31
|
+
projectUuid = project.uuid;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
await client.deleteCredential(projectUuid, input.environmentId, input.uuid);
|
|
35
|
+
logger.toolComplete('delete_credential', Date.now() - start);
|
|
36
|
+
return {
|
|
37
|
+
content: [{ type: 'text', text: JSON.stringify({ deleted: true, uuid: input.uuid }, null, 2) }],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
if (err?.statusCode === 404 || err?.response?.status === 404) {
|
|
42
|
+
return notFound(input.uuid, `backend 404 for env ${input.environmentId}`);
|
|
43
|
+
}
|
|
44
|
+
throw err;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
logger.toolError('delete_credential', error, Date.now() - start);
|
|
49
|
+
throw handleExternalServiceError(error, 'DebuggAI', 'delete_credential');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
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
|
+
import { detectRepoName } from '../utils/gitContext.js';
|
|
6
|
+
const logger = new Logger({ module: 'deleteEnvironmentHandler' });
|
|
7
|
+
function notFound(uuid, context) {
|
|
8
|
+
return {
|
|
9
|
+
content: [{ type: 'text', text: JSON.stringify({
|
|
10
|
+
error: 'NotFound',
|
|
11
|
+
message: `Environment ${uuid} not found (${context}).`,
|
|
12
|
+
uuid,
|
|
13
|
+
}, null, 2) }],
|
|
14
|
+
isError: true,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export async function deleteEnvironmentHandler(input, _context) {
|
|
18
|
+
const start = Date.now();
|
|
19
|
+
logger.toolStart('delete_environment', { uuid: input.uuid, projectUuid: input.projectUuid });
|
|
20
|
+
try {
|
|
21
|
+
const client = new DebuggAIServerClient(config.api.key);
|
|
22
|
+
await client.init();
|
|
23
|
+
let projectUuid = input.projectUuid;
|
|
24
|
+
if (!projectUuid) {
|
|
25
|
+
const repoName = detectRepoName();
|
|
26
|
+
if (!repoName)
|
|
27
|
+
return notFound(input.uuid, 'no git repo detected and no projectUuid provided');
|
|
28
|
+
const project = await client.findProjectByRepoName(repoName);
|
|
29
|
+
if (!project)
|
|
30
|
+
return notFound(input.uuid, `no project found for repo "${repoName}"`);
|
|
31
|
+
projectUuid = project.uuid;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
await client.deleteEnvironment(projectUuid, input.uuid);
|
|
35
|
+
logger.toolComplete('delete_environment', Date.now() - start);
|
|
36
|
+
return {
|
|
37
|
+
content: [{ type: 'text', text: JSON.stringify({ deleted: true, uuid: input.uuid }, null, 2) }],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
if (err?.statusCode === 404 || err?.response?.status === 404) {
|
|
42
|
+
return notFound(input.uuid, `backend returned 404 for project ${projectUuid}`);
|
|
43
|
+
}
|
|
44
|
+
throw err;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
logger.toolError('delete_environment', error, Date.now() - start);
|
|
49
|
+
throw handleExternalServiceError(error, 'DebuggAI', 'delete_environment');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
import { detectRepoName } from '../utils/gitContext.js';
|
|
6
|
+
const logger = new Logger({ module: 'getCredentialHandler' });
|
|
7
|
+
function notFound(uuid, context) {
|
|
8
|
+
return {
|
|
9
|
+
content: [{ type: 'text', text: JSON.stringify({
|
|
10
|
+
error: 'NotFound',
|
|
11
|
+
message: `Credential ${uuid} not found (${context}).`,
|
|
12
|
+
uuid,
|
|
13
|
+
}, null, 2) }],
|
|
14
|
+
isError: true,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export async function getCredentialHandler(input, _context) {
|
|
18
|
+
const start = Date.now();
|
|
19
|
+
logger.toolStart('get_credential', { uuid: input.uuid, environmentId: input.environmentId, projectUuid: input.projectUuid });
|
|
20
|
+
try {
|
|
21
|
+
const client = new DebuggAIServerClient(config.api.key);
|
|
22
|
+
await client.init();
|
|
23
|
+
let projectUuid = input.projectUuid;
|
|
24
|
+
if (!projectUuid) {
|
|
25
|
+
const repoName = detectRepoName();
|
|
26
|
+
if (!repoName)
|
|
27
|
+
return notFound(input.uuid, 'no git repo and no projectUuid');
|
|
28
|
+
const project = await client.findProjectByRepoName(repoName);
|
|
29
|
+
if (!project)
|
|
30
|
+
return notFound(input.uuid, `no project for repo "${repoName}"`);
|
|
31
|
+
projectUuid = project.uuid;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const credential = await client.getCredential(projectUuid, input.environmentId, input.uuid);
|
|
35
|
+
logger.toolComplete('get_credential', Date.now() - start);
|
|
36
|
+
return { content: [{ type: 'text', text: JSON.stringify({ credential }, null, 2) }] };
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
if (err?.statusCode === 404 || err?.response?.status === 404) {
|
|
40
|
+
return notFound(input.uuid, `backend 404 for env ${input.environmentId}`);
|
|
41
|
+
}
|
|
42
|
+
throw err;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
logger.toolError('get_credential', error, Date.now() - start);
|
|
47
|
+
throw handleExternalServiceError(error, 'DebuggAI', 'get_credential');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
import { detectRepoName } from '../utils/gitContext.js';
|
|
6
|
+
const logger = new Logger({ module: 'getEnvironmentHandler' });
|
|
7
|
+
function notFound(uuid, context) {
|
|
8
|
+
return {
|
|
9
|
+
content: [{ type: 'text', text: JSON.stringify({
|
|
10
|
+
error: 'NotFound',
|
|
11
|
+
message: `Environment ${uuid} not found (${context}).`,
|
|
12
|
+
uuid,
|
|
13
|
+
}, null, 2) }],
|
|
14
|
+
isError: true,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export async function getEnvironmentHandler(input, _context) {
|
|
18
|
+
const start = Date.now();
|
|
19
|
+
logger.toolStart('get_environment', { uuid: input.uuid, projectUuid: input.projectUuid });
|
|
20
|
+
try {
|
|
21
|
+
const client = new DebuggAIServerClient(config.api.key);
|
|
22
|
+
await client.init();
|
|
23
|
+
let projectUuid = input.projectUuid;
|
|
24
|
+
if (!projectUuid) {
|
|
25
|
+
const repoName = detectRepoName();
|
|
26
|
+
if (!repoName)
|
|
27
|
+
return notFound(input.uuid, 'no git repo detected and no projectUuid provided');
|
|
28
|
+
const project = await client.findProjectByRepoName(repoName);
|
|
29
|
+
if (!project)
|
|
30
|
+
return notFound(input.uuid, `no project found for repo "${repoName}"`);
|
|
31
|
+
projectUuid = project.uuid;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const environment = await client.getEnvironment(projectUuid, input.uuid);
|
|
35
|
+
logger.toolComplete('get_environment', Date.now() - start);
|
|
36
|
+
return { content: [{ type: 'text', text: JSON.stringify({ environment }, null, 2) }] };
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
if (err?.statusCode === 404 || err?.response?.status === 404) {
|
|
40
|
+
return notFound(input.uuid, `backend returned 404 for project ${projectUuid}`);
|
|
41
|
+
}
|
|
42
|
+
throw err;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
logger.toolError('get_environment', error, Date.now() - start);
|
|
47
|
+
throw handleExternalServiceError(error, 'DebuggAI', 'get_environment');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
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: 'getExecutionHandler' });
|
|
6
|
+
function notFound(uuid) {
|
|
7
|
+
return {
|
|
8
|
+
content: [{ type: 'text', text: JSON.stringify({
|
|
9
|
+
error: 'NotFound',
|
|
10
|
+
message: `Execution ${uuid} not found.`,
|
|
11
|
+
uuid,
|
|
12
|
+
}, null, 2) }],
|
|
13
|
+
isError: true,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export async function getExecutionHandler(input, _context) {
|
|
17
|
+
const start = Date.now();
|
|
18
|
+
logger.toolStart('get_execution', { uuid: input.uuid });
|
|
19
|
+
try {
|
|
20
|
+
const client = new DebuggAIServerClient(config.api.key);
|
|
21
|
+
await client.init();
|
|
22
|
+
try {
|
|
23
|
+
const execution = await client.workflows.getExecution(input.uuid);
|
|
24
|
+
logger.toolComplete('get_execution', Date.now() - start);
|
|
25
|
+
return { content: [{ type: 'text', text: JSON.stringify({ execution }, null, 2) }] };
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
if (err?.statusCode === 404 || err?.response?.status === 404)
|
|
29
|
+
return notFound(input.uuid);
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
logger.toolError('get_execution', error, Date.now() - start);
|
|
35
|
+
throw handleExternalServiceError(error, 'DebuggAI', 'get_execution');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
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: 'getProjectHandler' });
|
|
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 getProjectHandler(input, _context) {
|
|
17
|
+
const start = Date.now();
|
|
18
|
+
logger.toolStart('get_project', { uuid: input.uuid });
|
|
19
|
+
try {
|
|
20
|
+
const client = new DebuggAIServerClient(config.api.key);
|
|
21
|
+
await client.init();
|
|
22
|
+
try {
|
|
23
|
+
const project = await client.getProject(input.uuid);
|
|
24
|
+
logger.toolComplete('get_project', Date.now() - start);
|
|
25
|
+
return { content: [{ type: 'text', text: JSON.stringify({ project }, null, 2) }] };
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
if (err?.statusCode === 404 || err?.response?.status === 404)
|
|
29
|
+
return notFound(input.uuid);
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
logger.toolError('get_project', error, Date.now() - start);
|
|
35
|
+
throw handleExternalServiceError(error, 'DebuggAI', 'get_project');
|
|
36
|
+
}
|
|
37
|
+
}
|
package/dist/handlers/index.js
CHANGED
|
@@ -1 +1,18 @@
|
|
|
1
1
|
export * from './testPageChangesHandler.js';
|
|
2
|
+
export * from './listEnvironmentsHandler.js';
|
|
3
|
+
export * from './listCredentialsHandler.js';
|
|
4
|
+
export * from './listProjectsHandler.js';
|
|
5
|
+
export * from './createEnvironmentHandler.js';
|
|
6
|
+
export * from './createCredentialHandler.js';
|
|
7
|
+
export * from './getEnvironmentHandler.js';
|
|
8
|
+
export * from './updateEnvironmentHandler.js';
|
|
9
|
+
export * from './deleteEnvironmentHandler.js';
|
|
10
|
+
export * from './getCredentialHandler.js';
|
|
11
|
+
export * from './updateCredentialHandler.js';
|
|
12
|
+
export * from './deleteCredentialHandler.js';
|
|
13
|
+
export * from './getProjectHandler.js';
|
|
14
|
+
export * from './updateProjectHandler.js';
|
|
15
|
+
export * from './deleteProjectHandler.js';
|
|
16
|
+
export * from './listExecutionsHandler.js';
|
|
17
|
+
export * from './getExecutionHandler.js';
|
|
18
|
+
export * from './cancelExecutionHandler.js';
|
|
@@ -0,0 +1,71 @@
|
|
|
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
|
+
import { detectRepoName } from '../utils/gitContext.js';
|
|
6
|
+
const logger = new Logger({ module: 'listCredentialsHandler' });
|
|
7
|
+
export async function listCredentialsHandler(input, _context) {
|
|
8
|
+
const start = Date.now();
|
|
9
|
+
logger.toolStart('list_credentials', {
|
|
10
|
+
environmentId: input.environmentId,
|
|
11
|
+
projectUuid: input.projectUuid,
|
|
12
|
+
q: input.q,
|
|
13
|
+
role: input.role,
|
|
14
|
+
});
|
|
15
|
+
try {
|
|
16
|
+
const client = new DebuggAIServerClient(config.api.key);
|
|
17
|
+
await client.init();
|
|
18
|
+
let projectUuid = input.projectUuid;
|
|
19
|
+
if (!projectUuid) {
|
|
20
|
+
const repoName = detectRepoName();
|
|
21
|
+
if (!repoName) {
|
|
22
|
+
const payload = {
|
|
23
|
+
error: 'NoProjectResolved',
|
|
24
|
+
message: 'No git repo detected and no projectUuid provided. Pass projectUuid (get it from list_projects) or invoke from a directory with a git origin.',
|
|
25
|
+
credentials: [],
|
|
26
|
+
};
|
|
27
|
+
logger.toolComplete('list_credentials', Date.now() - start);
|
|
28
|
+
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
|
|
29
|
+
}
|
|
30
|
+
const project = await client.findProjectByRepoName(repoName);
|
|
31
|
+
if (!project) {
|
|
32
|
+
const payload = {
|
|
33
|
+
error: 'NoProjectResolved',
|
|
34
|
+
message: `No DebuggAI project found for repo "${repoName}". Pass projectUuid explicitly.`,
|
|
35
|
+
credentials: [],
|
|
36
|
+
};
|
|
37
|
+
logger.toolComplete('list_credentials', Date.now() - start);
|
|
38
|
+
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
|
|
39
|
+
}
|
|
40
|
+
projectUuid = project.uuid;
|
|
41
|
+
}
|
|
42
|
+
let credentials = [];
|
|
43
|
+
if (input.environmentId) {
|
|
44
|
+
credentials = await client.listCredentialsForEnvironment(projectUuid, input.environmentId, input.q, input.role);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// No environment filter — iterate all envs for the project
|
|
48
|
+
const envs = await client.listEnvironmentsForProject(projectUuid);
|
|
49
|
+
for (const env of envs) {
|
|
50
|
+
const credsForEnv = await client.listCredentialsForEnvironment(projectUuid, env.uuid, input.q, input.role);
|
|
51
|
+
credentials.push(...credsForEnv);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const payload = {
|
|
55
|
+
project: { uuid: projectUuid },
|
|
56
|
+
filter: {
|
|
57
|
+
environmentId: input.environmentId ?? null,
|
|
58
|
+
q: input.q ?? null,
|
|
59
|
+
role: input.role ?? null,
|
|
60
|
+
},
|
|
61
|
+
count: credentials.length,
|
|
62
|
+
credentials,
|
|
63
|
+
};
|
|
64
|
+
logger.toolComplete('list_credentials', Date.now() - start);
|
|
65
|
+
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
logger.toolError('list_credentials', error, Date.now() - start);
|
|
69
|
+
throw handleExternalServiceError(error, 'DebuggAI', 'list_credentials');
|
|
70
|
+
}
|
|
71
|
+
}
|