@democratize-quality/mcp-server 1.1.9 → 1.2.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.
Files changed (62) hide show
  1. package/dist/server.d.ts +41 -0
  2. package/dist/server.d.ts.map +1 -0
  3. package/dist/server.js +225 -0
  4. package/dist/server.js.map +1 -0
  5. package/package.json +23 -24
  6. package/browserControl.js +0 -113
  7. package/cli.js +0 -228
  8. package/mcpServer.js +0 -335
  9. package/run-server.js +0 -140
  10. package/src/chatmodes//360/237/214/220 api-generator.chatmode.md" +0 -409
  11. package/src/chatmodes//360/237/214/220 api-healer.chatmode.md" +0 -494
  12. package/src/chatmodes//360/237/214/220 api-planner.chatmode.md" +0 -954
  13. package/src/config/environments/api-only.js +0 -53
  14. package/src/config/environments/development.js +0 -54
  15. package/src/config/environments/production.js +0 -69
  16. package/src/config/index.js +0 -341
  17. package/src/config/server.js +0 -41
  18. package/src/config/tools/api.js +0 -67
  19. package/src/config/tools/browser.js +0 -90
  20. package/src/config/tools/default.js +0 -32
  21. package/src/docs/Agent_README.md +0 -310
  22. package/src/docs/QUICK_REFERENCE.md +0 -111
  23. package/src/services/browserService.js +0 -325
  24. package/src/skills/api-planning/SKILL.md +0 -224
  25. package/src/skills/test-execution/SKILL.md +0 -777
  26. package/src/skills/test-generation/SKILL.md +0 -309
  27. package/src/skills/test-healing/SKILL.md +0 -405
  28. package/src/tools/api/api-generator.js +0 -1865
  29. package/src/tools/api/api-healer.js +0 -617
  30. package/src/tools/api/api-planner.js +0 -2598
  31. package/src/tools/api/api-project-setup.js +0 -313
  32. package/src/tools/api/api-request.js +0 -641
  33. package/src/tools/api/api-session-report.js +0 -1278
  34. package/src/tools/api/api-session-status.js +0 -395
  35. package/src/tools/api/prompts/README.md +0 -293
  36. package/src/tools/api/prompts/generation-prompts.js +0 -703
  37. package/src/tools/api/prompts/healing-prompts.js +0 -195
  38. package/src/tools/api/prompts/index.js +0 -25
  39. package/src/tools/api/prompts/orchestrator.js +0 -334
  40. package/src/tools/api/prompts/validation-rules.js +0 -339
  41. package/src/tools/base/ToolBase.js +0 -230
  42. package/src/tools/base/ToolRegistry.js +0 -269
  43. package/src/tools/browser/advanced/browser-console.js +0 -384
  44. package/src/tools/browser/advanced/browser-dialog.js +0 -319
  45. package/src/tools/browser/advanced/browser-evaluate.js +0 -337
  46. package/src/tools/browser/advanced/browser-file.js +0 -480
  47. package/src/tools/browser/advanced/browser-keyboard.js +0 -343
  48. package/src/tools/browser/advanced/browser-mouse.js +0 -332
  49. package/src/tools/browser/advanced/browser-network.js +0 -421
  50. package/src/tools/browser/advanced/browser-pdf.js +0 -407
  51. package/src/tools/browser/advanced/browser-tabs.js +0 -497
  52. package/src/tools/browser/advanced/browser-wait.js +0 -378
  53. package/src/tools/browser/click.js +0 -168
  54. package/src/tools/browser/close.js +0 -60
  55. package/src/tools/browser/dom.js +0 -70
  56. package/src/tools/browser/launch.js +0 -67
  57. package/src/tools/browser/navigate.js +0 -270
  58. package/src/tools/browser/screenshot.js +0 -351
  59. package/src/tools/browser/type.js +0 -174
  60. package/src/tools/index.js +0 -95
  61. package/src/utils/agentInstaller.js +0 -418
  62. package/src/utils/browserHelpers.js +0 -83
@@ -1,325 +0,0 @@
1
- const CDP = require('chrome-remote-interface');
2
- //const launchChrome = require('chrome-launcher').launch;
3
- const fs = require('fs');
4
- const path = require('path');
5
- const { findNodeBySelector, getElementClickCoordinates } = require('../utils/browserHelpers'); // Import helpers
6
- const config = require('../config');
7
-
8
- // A private in-memory store for our browser instances within the service
9
- // Each key will be a unique browserId, value will be { chromeInstance, cdpClient, userDataDir }
10
- const activeBrowsers = {};
11
-
12
- /**
13
- * Ensures a user data directory exists.
14
- * @param {string} dirPath - The absolute path to the user data directory.
15
- */
16
- function ensureUserDataDir(dirPath) {
17
- if (!fs.existsSync(dirPath)) {
18
- fs.mkdirSync(dirPath, { recursive: true });
19
- console.log(`[BrowserService] Created user data directory: ${dirPath}`);
20
- } else {
21
- console.log(`[BrowserService] Using existing user data directory: ${dirPath}`);
22
- }
23
- }
24
-
25
- /**
26
- * Retrieves a browser instance by ID.
27
- * @param {string} browserId - The ID of the browser instance.
28
- * @returns {object|null} - The browser instance object or null if not found.
29
- */
30
- function getBrowserInstance(browserId) {
31
- return activeBrowsers[browserId];
32
- }
33
-
34
- /**
35
- * Launches a new Chrome instance.
36
- * @param {boolean} headless - Whether to run Chrome in headless mode.
37
- * @param {number} port - The port for remote debugging.
38
- * @param {string|null} userDataDir - Path to the user data directory for persistent profiles.
39
- * @returns {Promise<object>} - Object containing browserId, port, and resolvedUserDataDir.
40
- */
41
- async function launchBrowser(headless, port, userDataDir) {
42
- let chrome;
43
- let client;
44
- const { launch: launchChrome } = await import('chrome-launcher');
45
- let resolvedUserDataDir = null;
46
-
47
- try {
48
- if (userDataDir) {
49
- resolvedUserDataDir = path.resolve(process.cwd(), userDataDir);
50
- ensureUserDataDir(resolvedUserDataDir);
51
- }
52
-
53
- console.log(`[BrowserService] Launching Chrome (headless: ${headless}, userDataDir: ${resolvedUserDataDir || 'temporary'})...`);
54
-
55
- const launchOptions = {
56
- port: port,
57
- userDataDir: resolvedUserDataDir, // Set userDataDir if provided
58
- chromeFlags: [
59
- headless ? '--headless=new' : '',
60
- '--disable-gpu',
61
- '--disable-setuid-sandbox',
62
- '--no-sandbox'
63
- ].filter(Boolean)
64
- };
65
-
66
- chrome = await launchChrome(launchOptions);
67
-
68
- // Generate browserId: profile-name if userDataDir is used, otherwise a unique timestamped ID
69
- const browserId = userDataDir ? `profile-${path.basename(resolvedUserDataDir)}` : `browser-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
70
-
71
- if (activeBrowsers[browserId]) {
72
- console.warn(`[BrowserService] Warning: Browser ID '${browserId}' already exists. Overwriting.`);
73
- // In a real scenario, you might want more sophisticated handling here,
74
- // e.g., error if ID exists, or try to attach to existing.
75
- // For now, we're assuming a new launch means a fresh start or overwrite.
76
- try { // Attempt to clean up old instance if it exists
77
- if (activeBrowsers[browserId].cdpClient) activeBrowsers[browserId].cdpClient.close();
78
- if (activeBrowsers[browserId].chromeInstance) await activeBrowsers[browserId].chromeInstance.kill();
79
- } catch (cleanupErr) {
80
- console.error(`[BrowserService] Error cleaning up old instance for ${browserId}:`, cleanupErr.message);
81
- }
82
- }
83
-
84
- activeBrowsers[browserId] = { chromeInstance: chrome, cdpClient: null, userDataDir: resolvedUserDataDir };
85
- console.log(`[BrowserService] Chrome launched on port ${chrome.port} with ID: ${browserId}`);
86
-
87
- client = await CDP({ port: chrome.port });
88
- activeBrowsers[browserId].cdpClient = client;
89
-
90
- const { Page, Runtime, DOM, Network, Security, Input } = client; // Enable Input domain here
91
- await Page.enable();
92
- await Runtime.enable();
93
- await DOM.enable();
94
- await Network.enable();
95
- await Security.enable();
96
- //await Input.enable(); // Enable Input domain
97
-
98
- console.log(`[BrowserService] CDP client connected and domains enabled for ${browserId}.`);
99
-
100
- return { browserId, port: chrome.port, userDataDir: resolvedUserDataDir };
101
-
102
- } catch (error) {
103
- console.error(`[BrowserService] Error launching browser:`, error);
104
- if (chrome && !client) { // If chrome launched but CDP connection failed
105
- try {
106
- await chrome.kill();
107
- console.log(`[BrowserService] Partially launched Chrome instance killed due to error.`);
108
- } catch (killError) {
109
- console.error(`[BrowserService] Error killing partially launched Chrome:`, killError);
110
- }
111
- }
112
- throw error; // Re-throw to be caught by the route handler
113
- }
114
- }
115
-
116
- /**
117
- * Navigates a specific browser instance to a URL.
118
- * @param {string} browserId - The ID of the browser instance.
119
- * @param {string} url - The URL to navigate to.
120
- * @returns {Promise<void>}
121
- */
122
- async function navigateBrowser(browserId, url) {
123
- const instance = getBrowserInstance(browserId);
124
- if (!instance) throw new Error(`Browser instance with ID '${browserId}' not found.`);
125
-
126
- const { cdpClient } = instance;
127
- console.log(`[BrowserService] Browser ${browserId} navigating to: ${url}`);
128
- await cdpClient.Page.navigate({ url: url });
129
- await cdpClient.Page.loadEventFired(); // Wait for page to load
130
- console.log(`[BrowserService] Browser ${browserId} successfully navigated to ${url}.`);
131
- }
132
-
133
- /**
134
- * Takes a screenshot of a specific browser page and can save it to disk.
135
- * @param {string} browserId - The ID of the browser instance.
136
- * @param {string} [fileName='screenshot.png'] - Optional: The name of the file to save the screenshot as.
137
- * @param {boolean} [saveToDisk=true] - Optional: Whether to save the screenshot to disk.
138
- * @returns {Promise<string>} - Base64 encoded screenshot data.
139
- */
140
- async function takeScreenshot(browserId, fileName = 'screenshot.png', saveToDisk = true) { // Added fileName and saveToDisk params
141
- const instance = getBrowserInstance(browserId);
142
- if (!instance) throw new Error(`Browser instance with ID '${browserId}' not found.`);
143
-
144
- const { cdpClient } = instance;
145
- console.log(`[BrowserService] Taking screenshot for browser ${browserId}...`);
146
- const screenshot = await cdpClient.Page.captureScreenshot({ format: 'png', quality: 80 });
147
-
148
- if (saveToDisk) {
149
- const screenshotBuffer = Buffer.from(screenshot.data, 'base64');
150
- // Ensure the output directory exists
151
- if (!fs.existsSync(config.OUTPUT_DIR)) {
152
- fs.mkdirSync(config.OUTPUT_DIR, { recursive: true });
153
- }
154
- const filePath = path.join(config.OUTPUT_DIR, fileName);
155
- fs.writeFileSync(filePath, screenshotBuffer);
156
- console.log(`[BrowserService] Screenshot saved to ${filePath}`);
157
- }
158
-
159
- console.log(`[BrowserService] Screenshot captured for browser ${browserId}.`);
160
- return screenshot.data; // Always return base64 data to the caller (e.g., AI agent)
161
- }
162
-
163
- /**
164
- * Gets the current DOM content of a specific browser page.
165
- * @param {string} browserId - The ID of the browser instance.
166
- * @returns {Promise<string>} - The outer HTML of the document.
167
- */
168
- async function getDomContent(browserId) {
169
- const instance = getBrowserInstance(browserId);
170
- if (!instance) throw new Error(`Browser instance with ID '${browserId}' not found.`);
171
-
172
- const { cdpClient } = instance;
173
- console.log(`[BrowserService] Getting DOM for browser ${browserId}...`);
174
- const documentNode = await cdpClient.DOM.getDocument({ depth: -1 });
175
- const outerHTML = await cdpClient.DOM.getOuterHTML({ nodeId: documentNode.root.nodeId });
176
- console.log(`[BrowserService] DOM content retrieved for browser ${browserId}.`);
177
- return outerHTML.outerHTML;
178
- }
179
-
180
- /**
181
- * Clicks an element identified by a locator.
182
- * @param {string} browserId - The ID of the browser instance.
183
- * @param {object} locator - { type: 'css'|'xpath', value: 'selector' }
184
- * @returns {Promise<object>} - Coordinates of the click.
185
- */
186
- async function clickElement(browserId, locator) {
187
- const instance = getBrowserInstance(browserId);
188
- if (!instance) throw new Error(`Browser instance with ID '${browserId}' not found.`);
189
-
190
- const { cdpClient } = instance;
191
- const { Input } = cdpClient;
192
-
193
- console.log(`[BrowserService] Browser ${browserId}: Attempting to click element with locator:`, locator);
194
-
195
- const nodeId = await findNodeBySelector(cdpClient, locator.type, locator.value);
196
- if (!nodeId) {
197
- throw new Error(`Element not found for locator: ${JSON.stringify(locator)}`);
198
- }
199
-
200
- const coords = await getElementClickCoordinates(cdpClient, nodeId);
201
- if (!coords) {
202
- throw new Error(`Could not determine click coordinates for element: ${JSON.stringify(locator)}`);
203
- }
204
-
205
- await Input.dispatchMouseEvent({
206
- type: 'mousePressed',
207
- button: 'left',
208
- x: coords.x,
209
- y: coords.y,
210
- clickCount: 1
211
- });
212
- await Input.dispatchMouseEvent({
213
- type: 'mouseReleased',
214
- button: 'left',
215
- x: coords.x,
216
- y: coords.y,
217
- clickCount: 1
218
- });
219
-
220
- console.log(`[BrowserService] Browser ${browserId}: Clicked element at x: ${coords.x}, y: ${coords.y}`);
221
- return coords;
222
- }
223
-
224
- /**
225
- * Types text into an element identified by a locator.
226
- * @param {string} browserId - The ID of the browser instance.
227
- * @param {object} locator - { type: 'css'|'xpath', value: 'selector' }
228
- * @param {string} text - The text to type.
229
- * @returns {Promise<void>}
230
- */
231
- async function typeIntoElement(browserId, locator, text) {
232
- const instance = getBrowserInstance(browserId);
233
- if (!instance) throw new Error(`Browser instance with ID '${browserId}' not found.`);
234
-
235
- const { cdpClient } = instance;
236
- const { DOM, Input } = cdpClient;
237
-
238
- console.log(`[BrowserService] Browser ${browserId}: Attempting to type "${text}" into element with locator:`, locator);
239
-
240
- const nodeId = await findNodeBySelector(cdpClient, locator.type, locator.value);
241
- if (!nodeId) {
242
- throw new Error(`Element not found for locator: ${JSON.stringify(locator)}`);
243
- }
244
-
245
- await DOM.focus({ nodeId: nodeId });
246
- await new Promise(resolve => setTimeout(resolve, 50)); // Small delay for focus
247
-
248
- // Clear existing text: Cmd/Ctrl+A then Backspace
249
- await Input.dispatchKeyEvent({ type: 'keyDown', text: 'a', modifiers: (process.platform === 'darwin' ? 4 : 2) }); // 4 for Meta (Cmd), 2 for Control
250
- await Input.dispatchKeyEvent({ type: 'keyUp', text: 'a', modifiers: (process.platform === 'darwin' ? 4 : 2) });
251
- await Input.dispatchKeyEvent({ type: 'keyDown', key: 'Backspace' });
252
- await Input.dispatchKeyEvent({ type: 'keyUp', key: 'Backspace' });
253
- await new Promise(resolve => setTimeout(resolve, 50)); // Small delay for clear
254
-
255
- for (const char of text) {
256
- await Input.dispatchKeyEvent({ type: 'keyDown', text: char, key: char });
257
- await Input.dispatchKeyEvent({ type: 'keyUp', text: char, key: char });
258
- await new Promise(resolve => setTimeout(resolve, 10)); // Small delay for realism
259
- }
260
-
261
- console.log(`[BrowserService] Browser ${browserId}: Typed "${text}" into element.`);
262
- }
263
-
264
- /**
265
- * Closes a specific browser instance.
266
- * @param {string} browserId - The ID of the browser instance.
267
- * @returns {Promise<void>}
268
- */
269
- async function closeBrowser(browserId) {
270
- const instance = getBrowserInstance(browserId);
271
- if (!instance) throw new Error(`Browser instance with ID '${browserId}' not found.`);
272
-
273
- const { chromeInstance, cdpClient, userDataDir } = instance;
274
-
275
- console.log(`[BrowserService] Closing browser ${browserId} (profile: ${userDataDir || 'temporary'})...`);
276
- if (cdpClient) {
277
- try {
278
- cdpClient.close();
279
- console.log(`[BrowserService] CDP client disconnected for ${browserId}.`);
280
- } catch (err) {
281
- console.warn(`[BrowserService] Error during CDP client close for ${browserId}:`, err.message);
282
- }
283
- }
284
- if (chromeInstance) {
285
- try {
286
- await chromeInstance.kill();
287
- console.log(`[BrowserService] Chrome instance ${browserId} killed.`);
288
- } catch (err) {
289
- console.warn(`[BrowserService] Error during Chrome instance kill for ${browserId}:`, err.message);
290
- }
291
- }
292
- delete activeBrowsers[browserId]; // Remove from our store
293
- console.log(`[BrowserService] Browser ${browserId} removed from active list.`);
294
- }
295
-
296
- /**
297
- * Shuts down all active browser instances. Used for graceful server shutdown.
298
- * @returns {Promise<void>}
299
- */
300
- async function shutdownAllBrowsers() {
301
- const browserIds = Object.keys(activeBrowsers);
302
- if (browserIds.length === 0) {
303
- console.log('[BrowserService] No active browsers to shut down.');
304
- return;
305
- }
306
- console.log(`[BrowserService] Shutting down ${browserIds.length} active browser(s)...`);
307
- await Promise.all(browserIds.map(id => closeBrowser(id).catch(err => {
308
- console.error(`[BrowserService] Failed to gracefully close browser ${id}:`, err.message);
309
- // Continue with other shutdowns even if one fails
310
- })));
311
- console.log('[BrowserService] All active browsers shut down.');
312
- }
313
-
314
-
315
- module.exports = {
316
- launchBrowser,
317
- navigateBrowser,
318
- getBrowserInstance,
319
- takeScreenshot,
320
- getDomContent,
321
- clickElement,
322
- typeIntoElement,
323
- closeBrowser,
324
- shutdownAllBrowsers // Export for server.js to use
325
- };
@@ -1,224 +0,0 @@
1
- ---
2
- name: api-planning
3
- description: Analyze API schemas (OpenAPI, Swagger, GraphQL) and create comprehensive test plans with realistic sample data and optional endpoint validation. Use when user mentions API testing, test plans, test coverage, API documentation, schema analysis, REST APIs, GraphQL APIs, test scenarios, or needs to plan API test strategy.
4
- ---
5
-
6
- # API Test Planning Skill
7
-
8
- Use this skill to analyze API schemas and generate comprehensive test plans with realistic, context-aware sample data.
9
-
10
- ## When to Use This Skill
11
-
12
- - User provides an API schema URL or file path
13
- - User mentions creating test plans for APIs
14
- - User needs to analyze API documentation
15
- - User wants to validate API endpoints
16
- - User requests test coverage analysis for REST or GraphQL APIs
17
-
18
- ## Core Workflow
19
-
20
- ### Step 1: Generate Test Plan with Realistic Samples
21
-
22
- When user provides a schema URL or file path, use the `api_planner` tool from the democratize-quality MCP server:
23
-
24
- ```javascript
25
- await tools.api_planner({
26
- schemaUrl: "https://api.example.com/swagger.json",
27
- // OR schemaPath: "./schema.graphql" for local files
28
- apiBaseUrl: "https://api.example.com",
29
- includeAuth: true,
30
- includeSecurity: true,
31
- includeErrorHandling: true,
32
- outputPath: "./api-test-plan.md",
33
- testCategories: ["functional", "security", "performance", "integration", "edge-cases"],
34
- validateEndpoints: false // Set to true for live validation
35
- })
36
- ```
37
-
38
- **Important Workflow Rules:**
39
- 1. Call `api_planner` tool ONCE to generate the test plan
40
- 2. Review the results and explain what was generated to the user
41
- 3. Answer questions based on the generated output
42
- 4. Only call api_planner again if user explicitly requests a new/different test plan
43
-
44
- ### Step 2: Optional Endpoint Validation
45
-
46
- When API is accessible, enable validation to verify schemas match reality:
47
-
48
- ```javascript
49
- await tools.api_planner({
50
- schemaUrl: "https://api.example.com/swagger.json",
51
- validateEndpoints: true,
52
- validationSampleSize: 3, // Default: 3, use -1 for all endpoints
53
- validationTimeout: 5000 // 5 seconds per request
54
- })
55
- ```
56
-
57
- **Validation Features:**
58
- - Real API testing with actual responses
59
- - Response time metrics
60
- - Success/failure indicators (✅/❌)
61
- - Validation summary with success rate
62
- - Graceful error handling
63
-
64
- ## What You Get
65
-
66
- ### Without Validation (Fast):
67
- - Test plan with realistic sample data
68
- - Context-aware field values (names, emails, dates)
69
- - Ready-to-use test data
70
-
71
- ### With Validation (Comprehensive):
72
- - Test plan with realistic samples
73
- - Validation summary (success rate, statistics)
74
- - Per-endpoint validation results
75
- - Actual API responses captured
76
- - Response time metrics for each endpoint
77
-
78
- ## Working with Schema Files
79
-
80
- ### GraphQL SDL Files (.graphql, .gql)
81
- **ALWAYS use `schemaPath` parameter for SDL files:**
82
-
83
- ```javascript
84
- await tools.api_planner({
85
- schemaPath: "./schema.graphql", // Tool reads full file, converts SDL to introspection
86
- outputPath: "./test-plan.md"
87
- })
88
- ```
89
-
90
- **What happens:**
91
- - Tool reads full file (no truncation)
92
- - Automatically converts SDL → Introspection JSON
93
- - Saves `schema.json` alongside `schema.graphql`
94
- - Generates test plan from introspection
95
-
96
- ### OpenAPI/Swagger Files
97
- - Use `schemaPath` for local files (`.json`, `.yaml`, `.yml`)
98
- - Use `schemaUrl` for remote URLs
99
-
100
- ## Realistic Sample Data Generation
101
-
102
- The tool generates context-aware sample data automatically:
103
-
104
- **50+ Field Patterns:**
105
- - Personal info: `firstName` → "John", `email` → "john.doe@example.com"
106
- - Contact: `phoneNumber` → "+1-555-0123", `city` → "New York"
107
- - Business: `company` → "Acme Corp", `jobTitle` → "Engineer"
108
- - Identifiers: `uuid` → valid UUID, `token` → realistic token
109
- - Content: `title` → "Report Title", `description` → meaningful text
110
- - Numeric: `price` → 19.99, `age` → 25, `rating` → 4.5
111
- - Dates: `createdAt` → "2026-02-15T10:30:00Z"
112
-
113
- ## Advanced Scenarios
114
-
115
- ### Scenario 1: Local Schema File
116
- ```javascript
117
- await tools.api_planner({
118
- schemaPath: "./openapi.json",
119
- apiBaseUrl: "https://staging-api.example.com",
120
- validateEndpoints: true
121
- })
122
- ```
123
-
124
- ### Scenario 2: GraphQL API
125
- ```javascript
126
- await tools.api_planner({
127
- schemaUrl: "https://api.example.com/graphql",
128
- schemaType: "graphql",
129
- testCategories: ["functional", "edge-cases"]
130
- })
131
- ```
132
-
133
- ### Scenario 3: Multiple Related Services
134
- ```javascript
135
- const services = [
136
- { url: "https://api1.example.com/swagger.json", name: "auth-service" },
137
- { url: "https://api2.example.com/swagger.json", name: "user-service" }
138
- ]
139
-
140
- for (const service of services) {
141
- await tools.api_planner({
142
- schemaUrl: service.url,
143
- outputPath: `./${service.name}-test-plan.md`
144
- })
145
- }
146
- ```
147
-
148
- ## Best Practices
149
-
150
- ### DO:
151
- - Use api_planner once per schema
152
- - Enable validation when API is accessible
153
- - Use schemaPath for local files (especially GraphQL SDL)
154
- - Review validation results for API issues
155
- - Save plans to files using outputPath parameter
156
- - Include security and edge case testing
157
-
158
- ### DON'T:
159
- - Don't call api_planner multiple times without user request
160
- - Don't regenerate plans just to answer questions
161
- - Don't skip validation if API is accessible
162
- - Don't ignore failed validations
163
- - Don't validate all endpoints for large APIs (use validationSampleSize)
164
-
165
- ## Parameter Reference
166
-
167
- **Required (one of):**
168
- - `schemaUrl` - URL to fetch schema
169
- - `schemaPath` - Local file path
170
-
171
- **Common Optional:**
172
- - `apiBaseUrl` - Override base URL from schema
173
- - `outputPath` - Save test plan to file
174
- - `includeAuth` - Include auth scenarios (default: false)
175
- - `includeSecurity` - Include security scenarios (default: false)
176
- - `includeErrorHandling` - Include error scenarios (default: false)
177
- - `testCategories` - Array of test types
178
-
179
- **Validation Optional:**
180
- - `validateEndpoints` - Enable actual API testing (default: false)
181
- - `validationSampleSize` - Number to validate (default: 3, -1 = all)
182
- - `validationTimeout` - Timeout in ms (default: 5000)
183
-
184
- ## Troubleshooting
185
-
186
- ### Issue: Validation Not Running
187
- - Ensure `validateEndpoints: true` is set explicitly
188
-
189
- ### Issue: All Validations Fail with 401/403
190
- - API requires authentication
191
- - Use api_request tool to test with proper auth headers
192
- - Document auth requirements in manual review
193
-
194
- ### Issue: Validation Timeout
195
- - Increase `validationTimeout` parameter (e.g., 10000 for 10s)
196
-
197
- ### Issue: Schema Parse Errors
198
- - Verify schema URL is accessible
199
- - Check schema format compatibility
200
- - Try using `schemaPath` for local files
201
-
202
- ## Additional Validation Tools
203
-
204
- If you need to validate specific endpoints manually:
205
-
206
- ```javascript
207
- await tools.api_request({
208
- sessionId: "validation-session",
209
- method: "GET",
210
- url: "https://api.example.com/endpoint",
211
- expect: { status: 200 }
212
- })
213
-
214
- // Check session status
215
- await tools.api_session_status({
216
- sessionId: "validation-session"
217
- })
218
-
219
- // Generate report
220
- await tools.api_session_report({
221
- sessionId: "validation-session",
222
- outputPath: "./validation-report.html"
223
- })
224
- ```