@debugg-ai/debugg-ai-mcp 1.0.29 → 1.0.31
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 +21 -108
- package/dist/handlers/index.js +0 -5
- package/dist/handlers/testPageChangesHandler.js +23 -12
- package/dist/services/index.js +0 -7
- package/dist/services/workflows.js +21 -3
- package/dist/tools/index.js +0 -44
- package/dist/types/index.js +1 -73
- package/package.json +1 -1
- package/dist/handlers/e2eSuiteHandlers.js +0 -526
- package/dist/handlers/liveSessionHandlers.js +0 -272
- package/dist/services/browserSessions.js +0 -282
- package/dist/services/e2es.js +0 -290
- package/dist/tools/e2eSuites.js +0 -259
- package/dist/tools/liveSession.js +0 -217
- package/dist/tools/quickScreenshot.js +0 -203
package/README.md
CHANGED
|
@@ -1,42 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Debugg AI — MCP Server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
AI-powered browser testing via the [Model Context Protocol](https://modelcontextprotocol.io). Point it at any URL (or localhost) and describe what to test — an AI agent browses your app and returns pass/fail with screenshots.
|
|
4
4
|
|
|
5
5
|
<a href="https://glama.ai/mcp/servers/@debugg-ai/debugg-ai-mcp">
|
|
6
6
|
<img width="380" height="200" src="https://glama.ai/mcp/servers/@debugg-ai/debugg-ai-mcp/badge" alt="Debugg AI MCP server" />
|
|
7
7
|
</a>
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
## What it does
|
|
12
|
-
|
|
13
|
-
- **Run browser tests with natural language** — describe what to test, the AI agent clicks through your app and returns screenshots + results
|
|
14
|
-
- **Monitor live browser sessions** — capture console logs, network requests, and screenshots in real time
|
|
15
|
-
- **Manage test suites** — create, organize, and track E2E tests tied to features or commits
|
|
16
|
-
- **Seamless CI/CD** — view all results in your [Debugg.AI dashboard](https://app.debugg.ai)
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## Demo
|
|
21
|
-
|
|
22
|
-
### Prompt: "Test the ability to create an account and login"
|
|
23
|
-
|
|
24
|
-

|
|
25
|
-
|
|
26
|
-
**Result:**
|
|
27
|
-
- Duration: 86.80 seconds
|
|
28
|
-
- Status: Success — signed up and logged in with `alice.wonderland1234@example.com`
|
|
9
|
+
## Setup
|
|
29
10
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## Quick Setup
|
|
35
|
-
|
|
36
|
-
### 1. Get your API key
|
|
37
|
-
Create a free account at [debugg.ai](https://debugg.ai) and generate your API key.
|
|
38
|
-
|
|
39
|
-
### 2. Add to Claude Desktop
|
|
11
|
+
Get an API key at [debugg.ai](https://debugg.ai), then add to your MCP client config:
|
|
40
12
|
|
|
41
13
|
```json
|
|
42
14
|
{
|
|
@@ -52,101 +24,42 @@ Create a free account at [debugg.ai](https://debugg.ai) and generate your API ke
|
|
|
52
24
|
}
|
|
53
25
|
```
|
|
54
26
|
|
|
55
|
-
|
|
27
|
+
Or with Docker:
|
|
28
|
+
|
|
56
29
|
```bash
|
|
57
|
-
docker run -i --rm --init
|
|
58
|
-
-e DEBUGGAI_API_KEY=your_api_key \
|
|
59
|
-
quinnosha/debugg-ai-mcp
|
|
30
|
+
docker run -i --rm --init -e DEBUGGAI_API_KEY=your_api_key quinnosha/debugg-ai-mcp
|
|
60
31
|
```
|
|
61
32
|
|
|
62
|
-
|
|
33
|
+
## `check_app_in_browser`
|
|
63
34
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
### E2E Testing
|
|
67
|
-
| Tool | Description |
|
|
68
|
-
|------|-------------|
|
|
69
|
-
| `check_app_in_browser` | Run a browser test with a natural language description. Returns screenshots and pass/fail result. |
|
|
70
|
-
| `create_test_suite` | Generate a suite of browser tests for a feature or workflow |
|
|
71
|
-
| `create_commit_suite` | Auto-generate tests from recent git commits |
|
|
72
|
-
| `get_test_status` | Check progress and results of a running or completed test suite |
|
|
73
|
-
|
|
74
|
-
### Test Management
|
|
75
|
-
| Tool | Description |
|
|
76
|
-
|------|-------------|
|
|
77
|
-
| `list_tests` | List all E2E tests with filtering and pagination |
|
|
78
|
-
| `list_test_suites` | List all test suites |
|
|
79
|
-
| `list_commit_suites` | List all commit-based test suites |
|
|
80
|
-
|
|
81
|
-
### Live Session Monitoring
|
|
82
|
-
| Tool | Description |
|
|
83
|
-
|------|-------------|
|
|
84
|
-
| `start_live_session` | Launch a remote browser session with real-time monitoring |
|
|
85
|
-
| `stop_live_session` | Stop an active session and save captured data |
|
|
86
|
-
| `get_live_session_status` | Check session status, current URL, and uptime |
|
|
87
|
-
| `get_live_session_logs` | Retrieve console logs, network requests, and JS errors |
|
|
88
|
-
| `get_live_session_screenshot` | Capture a screenshot of what the browser currently shows |
|
|
89
|
-
|
|
90
|
-
### Quick Operations
|
|
91
|
-
| Tool | Description |
|
|
92
|
-
|------|-------------|
|
|
93
|
-
| `quick_screenshot` | Capture a screenshot of any URL — no session setup required |
|
|
35
|
+
Runs an AI browser agent against your app. The agent navigates, interacts, and reports back with screenshots.
|
|
94
36
|
|
|
95
|
-
|
|
37
|
+
| Parameter | Type | Description |
|
|
38
|
+
|-----------|------|-------------|
|
|
39
|
+
| `description` | string **required** | What to test (natural language) |
|
|
40
|
+
| `url` | string | Target URL — required if `localPort` not set |
|
|
41
|
+
| `localPort` | number | Local dev server port — tunnel created automatically |
|
|
42
|
+
| `environmentId` | string | UUID of a specific environment |
|
|
43
|
+
| `credentialId` | string | UUID of a specific credential |
|
|
44
|
+
| `credentialRole` | string | Pick a credential by role (e.g. `admin`, `guest`) |
|
|
45
|
+
| `username` | string | Username for login |
|
|
46
|
+
| `password` | string | Password for login |
|
|
96
47
|
|
|
97
48
|
## Configuration
|
|
98
49
|
|
|
99
50
|
```bash
|
|
100
|
-
# Required
|
|
101
51
|
DEBUGGAI_API_KEY=your_api_key
|
|
102
|
-
|
|
103
|
-
# Optional — provide defaults so you don't have to pass them every time
|
|
104
|
-
DEBUGGAI_LOCAL_PORT=3000 # Your app's local port
|
|
105
|
-
DEBUGGAI_LOCAL_REPO_NAME=your-org/repo # GitHub repo name
|
|
106
|
-
DEBUGGAI_LOCAL_REPO_PATH=/path/to/project # Absolute path to project root
|
|
107
|
-
DEBUGGAI_LOCAL_BRANCH_NAME=main # Current branch
|
|
108
|
-
|
|
109
|
-
# Override API endpoint (defaults to https://api.debugg.ai)
|
|
110
|
-
DEBUGGAI_API_URL=https://api.debugg.ai
|
|
111
52
|
```
|
|
112
53
|
|
|
113
|
-
---
|
|
114
|
-
|
|
115
|
-
## Usage examples
|
|
116
|
-
|
|
117
|
-
```
|
|
118
|
-
"Test the user login flow on my app running on port 3000"
|
|
119
|
-
|
|
120
|
-
"Check that the checkout process works end to end"
|
|
121
|
-
|
|
122
|
-
"Take a screenshot of localhost:3000 and tell me if anything looks broken"
|
|
123
|
-
|
|
124
|
-
"Create a test suite for the user authentication feature"
|
|
125
|
-
|
|
126
|
-
"Generate browser tests for my last 3 commits"
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
---
|
|
130
|
-
|
|
131
54
|
## Local Development
|
|
132
55
|
|
|
133
56
|
```bash
|
|
134
|
-
npm install
|
|
135
|
-
npm test
|
|
136
|
-
npm run build
|
|
137
|
-
|
|
138
|
-
# Test with MCP inspector
|
|
139
|
-
npx @modelcontextprotocol/inspector --config test-config.json --server debugg-ai
|
|
57
|
+
npm install && npm test && npm run build
|
|
140
58
|
```
|
|
141
59
|
|
|
142
|
-
---
|
|
143
|
-
|
|
144
60
|
## Links
|
|
145
61
|
|
|
146
|
-
|
|
147
|
-
- **Docs**: [debugg.ai/docs](https://debugg.ai/docs)
|
|
148
|
-
- **Issues**: [GitHub Issues](https://github.com/debugg-ai/debugg-ai-mcp/issues)
|
|
149
|
-
- **Discord**: [debugg.ai/discord](https://debugg.ai/discord)
|
|
62
|
+
[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)
|
|
150
63
|
|
|
151
64
|
---
|
|
152
65
|
|
package/dist/handlers/index.js
CHANGED
|
@@ -20,6 +20,9 @@ export async function testPageChangesHandler(input, context, progressCallback) {
|
|
|
20
20
|
const originalUrl = resolveTargetUrl(input);
|
|
21
21
|
let ctx = buildContext(originalUrl);
|
|
22
22
|
let ngrokKeyId;
|
|
23
|
+
const abortController = new AbortController();
|
|
24
|
+
const onStdinClose = () => abortController.abort();
|
|
25
|
+
process.stdin.once('close', onStdinClose);
|
|
23
26
|
try {
|
|
24
27
|
// --- Find workflow template ---
|
|
25
28
|
if (progressCallback) {
|
|
@@ -71,22 +74,29 @@ export async function testPageChangesHandler(input, context, progressCallback) {
|
|
|
71
74
|
logger.info(`Tunnel ready for ${originalUrl} (id: ${executionUuid})`);
|
|
72
75
|
}
|
|
73
76
|
// --- Poll ---
|
|
74
|
-
|
|
77
|
+
// nodeExecutions grows as each node completes: trigger → browser.setup → surfer.execute_task → browser.teardown
|
|
78
|
+
const NODE_PHASE_LABELS = {
|
|
79
|
+
0: 'Browser agent starting up...',
|
|
80
|
+
1: 'Browser ready, agent navigating...',
|
|
81
|
+
2: 'Agent evaluating app...',
|
|
82
|
+
3: 'Wrapping up...',
|
|
83
|
+
};
|
|
84
|
+
let lastNodeCount = 0;
|
|
75
85
|
const finalExecution = await client.workflows.pollExecution(executionUuid, async (exec) => {
|
|
76
|
-
const
|
|
77
|
-
if (
|
|
78
|
-
|
|
79
|
-
logger.info(`Execution status: ${exec.status},
|
|
86
|
+
const nodeCount = exec.nodeExecutions?.length ?? 0;
|
|
87
|
+
if (nodeCount !== lastNodeCount || exec.status !== 'pending') {
|
|
88
|
+
lastNodeCount = nodeCount;
|
|
89
|
+
logger.info(`Execution status: ${exec.status}, nodes completed: ${nodeCount}`);
|
|
80
90
|
}
|
|
81
91
|
if (progressCallback) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
92
|
+
// Map 0-4 completed nodes to progress 3-9 (3 reserved for tunnel setup)
|
|
93
|
+
const progress = Math.min(3 + nodeCount * 2, 9);
|
|
94
|
+
const message = exec.status === 'running'
|
|
95
|
+
? (NODE_PHASE_LABELS[nodeCount] ?? 'Agent working...')
|
|
96
|
+
: exec.status;
|
|
97
|
+
await progressCallback({ progress, total: 10, message });
|
|
88
98
|
}
|
|
89
|
-
});
|
|
99
|
+
}, abortController.signal);
|
|
90
100
|
const duration = Date.now() - startTime;
|
|
91
101
|
// --- Format result ---
|
|
92
102
|
const outcome = finalExecution.state?.outcome ?? finalExecution.status;
|
|
@@ -145,6 +155,7 @@ export async function testPageChangesHandler(input, context, progressCallback) {
|
|
|
145
155
|
throw handleExternalServiceError(error, 'DebuggAI', 'test execution');
|
|
146
156
|
}
|
|
147
157
|
finally {
|
|
158
|
+
process.stdin.removeListener('close', onStdinClose);
|
|
148
159
|
if (ngrokKeyId) {
|
|
149
160
|
client.revokeNgrokKey(ngrokKeyId).catch(err => logger.warn(`Failed to revoke ngrok key ${ngrokKeyId}: ${err}`));
|
|
150
161
|
}
|
package/dist/services/index.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { createE2esService } from "./e2es.js";
|
|
2
|
-
import { createBrowserSessionsService } from "./browserSessions.js";
|
|
3
1
|
import { createWorkflowsService } from "./workflows.js";
|
|
4
2
|
import { AxiosTransport } from "../utils/axiosTransport.js";
|
|
5
3
|
import { config } from "../config/index.js";
|
|
@@ -34,9 +32,6 @@ export class DebuggAIServerClient {
|
|
|
34
32
|
userApiKey;
|
|
35
33
|
tx;
|
|
36
34
|
url;
|
|
37
|
-
// Public "sub‑APIs"
|
|
38
|
-
e2es;
|
|
39
|
-
browserSessions;
|
|
40
35
|
workflows;
|
|
41
36
|
constructor(userApiKey) {
|
|
42
37
|
this.userApiKey = userApiKey;
|
|
@@ -46,8 +41,6 @@ export class DebuggAIServerClient {
|
|
|
46
41
|
const serverUrl = config.api.baseUrl;
|
|
47
42
|
this.url = new URL(serverUrl);
|
|
48
43
|
this.tx = new DebuggTransport({ baseUrl: serverUrl, apiKey: this.userApiKey, tokenType: config.api.tokenType });
|
|
49
|
-
this.e2es = createE2esService(this.tx);
|
|
50
|
-
this.browserSessions = createBrowserSessionsService(this.tx);
|
|
51
44
|
this.workflows = createWorkflowsService(this.tx);
|
|
52
45
|
}
|
|
53
46
|
/**
|
|
@@ -10,8 +10,15 @@ export const createWorkflowsService = (tx) => {
|
|
|
10
10
|
async findEvaluationTemplate() {
|
|
11
11
|
const response = await tx.get('api/v1/workflows/', { isTemplate: true });
|
|
12
12
|
const templates = response?.results ?? [];
|
|
13
|
+
if (templates.length === 0)
|
|
14
|
+
return null;
|
|
13
15
|
const evalTemplate = templates.find(t => t.name.toLowerCase().includes('app evaluation'));
|
|
14
|
-
|
|
16
|
+
if (!evalTemplate) {
|
|
17
|
+
throw new Error(`No "App Evaluation" workflow template found. ` +
|
|
18
|
+
`Available templates: ${templates.map(t => `"${t.name}"`).join(', ')}. ` +
|
|
19
|
+
`Ensure the backend has a template with "App Evaluation" in its name.`);
|
|
20
|
+
}
|
|
21
|
+
return evalTemplate;
|
|
15
22
|
},
|
|
16
23
|
async executeWorkflow(workflowUuid, contextData, env) {
|
|
17
24
|
const body = { contextData };
|
|
@@ -38,9 +45,12 @@ export const createWorkflowsService = (tx) => {
|
|
|
38
45
|
}
|
|
39
46
|
return response;
|
|
40
47
|
},
|
|
41
|
-
async pollExecution(executionUuid, onUpdate) {
|
|
48
|
+
async pollExecution(executionUuid, onUpdate, signal) {
|
|
42
49
|
const deadline = Date.now() + EXECUTION_TIMEOUT_MS;
|
|
43
50
|
while (Date.now() < deadline) {
|
|
51
|
+
if (signal?.aborted) {
|
|
52
|
+
throw new Error(`Polling cancelled for execution ${executionUuid}`);
|
|
53
|
+
}
|
|
44
54
|
const execution = await service.getExecution(executionUuid);
|
|
45
55
|
if (onUpdate) {
|
|
46
56
|
await onUpdate(execution).catch(() => { });
|
|
@@ -48,7 +58,15 @@ export const createWorkflowsService = (tx) => {
|
|
|
48
58
|
if (TERMINAL_STATUSES.has(execution.status)) {
|
|
49
59
|
return execution;
|
|
50
60
|
}
|
|
51
|
-
await new Promise(
|
|
61
|
+
await new Promise((resolve, reject) => {
|
|
62
|
+
const timer = setTimeout(resolve, POLL_INTERVAL_MS);
|
|
63
|
+
if (signal) {
|
|
64
|
+
signal.addEventListener('abort', () => {
|
|
65
|
+
clearTimeout(timer);
|
|
66
|
+
reject(new Error(`Polling cancelled for execution ${executionUuid}`));
|
|
67
|
+
}, { once: true });
|
|
68
|
+
}
|
|
69
|
+
});
|
|
52
70
|
}
|
|
53
71
|
throw new Error(`Execution ${executionUuid} timed out after ${EXECUTION_TIMEOUT_MS / 1000}s`);
|
|
54
72
|
}
|
package/dist/tools/index.js
CHANGED
|
@@ -1,61 +1,17 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool registry and exports
|
|
3
|
-
* Centralized location for all DebuggAI MCP tool definitions
|
|
4
|
-
*
|
|
5
|
-
* These tools provide AI agents with:
|
|
6
|
-
* - Live remote browser sessions for real-time monitoring
|
|
7
|
-
* - End-to-end testing with natural language descriptions
|
|
8
|
-
* - Browser console logs, network traffic, and screenshot capture
|
|
9
|
-
* - Test suite management and Git commit-based test generation
|
|
10
|
-
*/
|
|
11
1
|
import { testPageChangesTool, validatedTestPageChangesTool } from './testPageChanges.js';
|
|
12
|
-
import { startLiveSessionTool, stopLiveSessionTool, getLiveSessionStatusTool, getLiveSessionLogsTool, getLiveSessionScreenshotTool, validatedLiveSessionTools } from './liveSession.js';
|
|
13
|
-
import { listTestsTool, listTestSuitesTool, createTestSuiteTool, createCommitSuiteTool, listCommitSuitesTool, getTestStatusTool, validatedE2ESuiteTools } from './e2eSuites.js';
|
|
14
|
-
import { quickScreenshotTool, validatedQuickScreenshotTool } from './quickScreenshot.js';
|
|
15
|
-
/**
|
|
16
|
-
* All available tools for MCP server
|
|
17
|
-
*/
|
|
18
2
|
export const tools = [
|
|
19
3
|
testPageChangesTool,
|
|
20
|
-
startLiveSessionTool,
|
|
21
|
-
stopLiveSessionTool,
|
|
22
|
-
getLiveSessionStatusTool,
|
|
23
|
-
getLiveSessionLogsTool,
|
|
24
|
-
getLiveSessionScreenshotTool,
|
|
25
|
-
listTestsTool,
|
|
26
|
-
listTestSuitesTool,
|
|
27
|
-
createTestSuiteTool,
|
|
28
|
-
createCommitSuiteTool,
|
|
29
|
-
listCommitSuitesTool,
|
|
30
|
-
getTestStatusTool,
|
|
31
|
-
quickScreenshotTool,
|
|
32
4
|
];
|
|
33
|
-
/**
|
|
34
|
-
* All validated tools with handlers
|
|
35
|
-
*/
|
|
36
5
|
export const validatedTools = [
|
|
37
6
|
validatedTestPageChangesTool,
|
|
38
|
-
...validatedLiveSessionTools,
|
|
39
|
-
...validatedE2ESuiteTools,
|
|
40
|
-
validatedQuickScreenshotTool,
|
|
41
7
|
];
|
|
42
|
-
/**
|
|
43
|
-
* Tool registry for quick lookup
|
|
44
|
-
*/
|
|
45
8
|
export const toolRegistry = new Map();
|
|
46
|
-
// Initialize tool registry
|
|
47
9
|
for (const tool of validatedTools) {
|
|
48
10
|
toolRegistry.set(tool.name, tool);
|
|
49
11
|
}
|
|
50
|
-
/**
|
|
51
|
-
* Get tool by name
|
|
52
|
-
*/
|
|
53
12
|
export function getTool(name) {
|
|
54
13
|
return toolRegistry.get(name);
|
|
55
14
|
}
|
|
56
|
-
/**
|
|
57
|
-
* Check if tool exists
|
|
58
|
-
*/
|
|
59
15
|
export function hasToolTool(name) {
|
|
60
16
|
return toolRegistry.has(name);
|
|
61
17
|
}
|
package/dist/types/index.js
CHANGED
|
@@ -15,79 +15,7 @@ export const TestPageChangesInputSchema = z.object({
|
|
|
15
15
|
credentialRole: z.string().optional(),
|
|
16
16
|
username: z.string().optional(),
|
|
17
17
|
password: z.string().optional(),
|
|
18
|
-
});
|
|
19
|
-
/**
|
|
20
|
-
* E2E Suite Tool Schemas
|
|
21
|
-
*/
|
|
22
|
-
export const ListTestsInputSchema = z.object({
|
|
23
|
-
repoName: z.string().optional(),
|
|
24
|
-
branchName: z.string().optional(),
|
|
25
|
-
status: z.enum(['pending', 'running', 'completed', 'failed']).optional(),
|
|
26
|
-
page: z.number().int().positive().optional().default(1),
|
|
27
|
-
limit: z.number().int().min(1).max(100).optional().default(20),
|
|
28
|
-
});
|
|
29
|
-
export const ListTestSuitesInputSchema = z.object({
|
|
30
|
-
repoName: z.string().optional(),
|
|
31
|
-
branchName: z.string().optional(),
|
|
32
|
-
status: z.enum(['pending', 'running', 'completed', 'failed']).optional(),
|
|
33
|
-
page: z.number().int().positive().optional().default(1),
|
|
34
|
-
limit: z.number().int().min(1).max(100).optional().default(20),
|
|
35
|
-
});
|
|
36
|
-
export const CreateTestSuiteInputSchema = z.object({
|
|
37
|
-
description: z.string().min(1, 'Description is required'),
|
|
38
|
-
repoName: z.string().optional(),
|
|
39
|
-
branchName: z.string().optional(),
|
|
40
|
-
repoPath: z.string().optional(),
|
|
41
|
-
filePath: z.string().optional(),
|
|
42
|
-
});
|
|
43
|
-
export const CreateCommitSuiteInputSchema = z.object({
|
|
44
|
-
description: z.string().min(1, 'Description is required'),
|
|
45
|
-
repoName: z.string().optional(),
|
|
46
|
-
branchName: z.string().optional(),
|
|
47
|
-
repoPath: z.string().optional(),
|
|
48
|
-
filePath: z.string().optional(),
|
|
49
|
-
});
|
|
50
|
-
export const ListCommitSuitesInputSchema = z.object({
|
|
51
|
-
repoName: z.string().optional(),
|
|
52
|
-
branchName: z.string().optional(),
|
|
53
|
-
status: z.enum(['pending', 'running', 'completed', 'failed']).optional(),
|
|
54
|
-
page: z.number().int().positive().optional().default(1),
|
|
55
|
-
limit: z.number().int().min(1).max(100).optional().default(20),
|
|
56
|
-
});
|
|
57
|
-
export const GetTestStatusInputSchema = z.object({
|
|
58
|
-
suiteUuid: z.string().uuid('Invalid suite UUID'),
|
|
59
|
-
suiteType: z.enum(['test', 'commit']).optional().default('test'),
|
|
60
|
-
});
|
|
61
|
-
/**
|
|
62
|
-
* Live Session Tool Schemas
|
|
63
|
-
*/
|
|
64
|
-
export const StartLiveSessionInputSchema = z.object({
|
|
65
|
-
url: z.string().min(1, 'URL is required'),
|
|
66
|
-
localPort: z.number().int().min(1).max(65535).optional(),
|
|
67
|
-
sessionName: z.string().max(100).optional(),
|
|
68
|
-
monitorConsole: z.boolean().optional().default(true),
|
|
69
|
-
monitorNetwork: z.boolean().optional().default(true),
|
|
70
|
-
takeScreenshots: z.boolean().optional().default(false),
|
|
71
|
-
screenshotInterval: z.number().int().min(1).max(300).optional().default(10),
|
|
72
|
-
});
|
|
73
|
-
export const StopLiveSessionInputSchema = z.object({
|
|
74
|
-
sessionId: z.string().optional(),
|
|
75
|
-
});
|
|
76
|
-
export const GetLiveSessionStatusInputSchema = z.object({
|
|
77
|
-
sessionId: z.string().optional(),
|
|
78
|
-
});
|
|
79
|
-
export const GetLiveSessionLogsInputSchema = z.object({
|
|
80
|
-
sessionId: z.string().optional(),
|
|
81
|
-
logType: z.enum(['console', 'network', 'errors', 'all']).optional().default('all'),
|
|
82
|
-
since: z.string().datetime().optional(),
|
|
83
|
-
limit: z.number().int().min(1).max(1000).optional().default(100),
|
|
84
|
-
});
|
|
85
|
-
export const GetLiveSessionScreenshotInputSchema = z.object({
|
|
86
|
-
sessionId: z.string().optional(),
|
|
87
|
-
fullPage: z.boolean().optional().default(false),
|
|
88
|
-
quality: z.number().int().min(1).max(100).optional().default(90),
|
|
89
|
-
format: z.enum(['png', 'jpeg']).optional().default('png'),
|
|
90
|
-
});
|
|
18
|
+
}).refine((data) => data.url !== undefined || data.localPort !== undefined, { message: 'Provide a target via "url" (e.g. "https://example.com") or "localPort" for a local dev server' });
|
|
91
19
|
/**
|
|
92
20
|
* Error types
|
|
93
21
|
*/
|