@skyramp/mcp 0.4.3 → 0.4.4-rc.2
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/build/index.js +239 -210
- package/build/playwright/PlaywrightTraceService.d.ts +1 -1
- package/build/playwright/blueprintDigestStore.d.ts +1 -1
- package/build/playwright/registerPlaywrightTools.d.ts +1 -1
- package/build/playwright/traceRecordingPrompt.d.ts +1 -1
- package/build/playwright/traceRecordingPrompt.js +4 -3
- package/build/prompts/local-dev/local-dev-prompts.d.ts +1 -1
- package/build/prompts/local-dev/local-dev-prompts.js +2 -2
- package/build/prompts/orderAssertionRule.d.ts +9 -0
- package/build/prompts/orderAssertionRule.js +9 -0
- package/build/prompts/startTraceCollectionPrompts.d.ts +1 -1
- package/build/prompts/startTraceCollectionPrompts.js +2 -3
- package/build/prompts/test-maintenance/driftAnalysisShared.js +2 -0
- package/build/prompts/test-recommendation/registerRecommendTestsPrompt.d.ts +1 -1
- package/build/prompts/test-recommendation/registerRecommendTestsPrompt.js +2 -2
- package/build/prompts/testbot/testbot-prompts.d.ts +1 -1
- package/build/prompts/testbot/testbot-prompts.js +9 -9
- package/build/recommendation/answers.d.ts +3 -3
- package/build/recommendation/answers.js +3 -2
- package/build/recommendation/verifierContracts.d.ts +4 -4
- package/build/recommendation/verifierContracts.js +6 -5
- package/build/recommendation/verifiers/coverage.js +25 -25
- package/build/recommendation/verifiers/deliveredMatchesPlan.js +3 -3
- package/build/resources/analysisResources.d.ts +1 -1
- package/build/resources/analysisResources.js +1 -1
- package/build/resources/progressResource.d.ts +1 -1
- package/build/resources/sutSetupResource.d.ts +1 -1
- package/build/resources/sutSetupResource.js +1 -1
- package/build/resources/testbotResource.d.ts +1 -1
- package/build/resources/testbotResource.js +1 -1
- package/build/services/AnalyticsService.d.ts +1 -1
- package/build/services/FleetExecutionService.d.ts +130 -0
- package/build/services/FleetExecutionService.js +391 -0
- package/build/services/ModularizationService.d.ts +1 -1
- package/build/services/TestExecutionService.d.ts +7 -0
- package/build/services/TestExecutionService.js +21 -0
- package/build/services/TestGenerationService.d.ts +1 -1
- package/build/tool-phases.js +2 -0
- package/build/tools/auth/loginTool.d.ts +1 -1
- package/build/tools/auth/loginTool.js +2 -2
- package/build/tools/auth/logoutTool.d.ts +1 -1
- package/build/tools/auth/logoutTool.js +2 -2
- package/build/tools/code-refactor/alignAssertionsTool.d.ts +1 -1
- package/build/tools/code-refactor/alignAssertionsTool.js +1 -1
- package/build/tools/code-refactor/assertionSkillTools.d.ts +1 -1
- package/build/tools/code-refactor/assertionSkillTools.js +2 -2
- package/build/tools/code-refactor/codeReuseTool.d.ts +1 -1
- package/build/tools/code-refactor/codeReuseTool.js +2 -2
- package/build/tools/code-refactor/enhanceAssertionsTool.d.ts +1 -1
- package/build/tools/code-refactor/enhanceAssertionsTool.js +1 -1
- package/build/tools/code-refactor/modularizationTool.d.ts +1 -1
- package/build/tools/code-refactor/modularizationTool.js +2 -2
- package/build/tools/enrichTestWithMocksTool.d.ts +1 -1
- package/build/tools/enrichTestWithMocksTool.js +2 -2
- package/build/tools/executeFleetTool.d.ts +28 -0
- package/build/tools/executeFleetTool.js +107 -0
- package/build/tools/executeSkyrampTestTool.d.ts +8 -5
- package/build/tools/executeSkyrampTestTool.js +13 -5
- package/build/tools/fixErrorTool.d.ts +1 -1
- package/build/tools/fixErrorTool.js +1 -1
- package/build/tools/generate-tests/batchMockGenerationTool.d.ts +6 -57
- package/build/tools/generate-tests/batchMockGenerationTool.js +3 -3
- package/build/tools/generate-tests/generateBatchScenarioRestTool.d.ts +9 -45
- package/build/tools/generate-tests/generateBatchScenarioRestTool.js +29 -11
- package/build/tools/generate-tests/generateContractRestTool.d.ts +1 -2
- package/build/tools/generate-tests/generateContractRestTool.js +1 -1
- package/build/tools/generate-tests/generateE2ERestTool.d.ts +2 -2
- package/build/tools/generate-tests/generateE2ERestTool.js +10 -2
- package/build/tools/generate-tests/generateFuzzRestTool.d.ts +1 -1
- package/build/tools/generate-tests/generateFuzzRestTool.js +1 -1
- package/build/tools/generate-tests/generateIntegrationRestTool.d.ts +1 -2
- package/build/tools/generate-tests/generateIntegrationRestTool.js +1 -1
- package/build/tools/generate-tests/generateLoadRestTool.d.ts +1 -2
- package/build/tools/generate-tests/generateLoadRestTool.js +2 -1
- package/build/tools/generate-tests/generateMockRestTool.d.ts +1 -2
- package/build/tools/generate-tests/generateMockRestTool.js +3 -3
- package/build/tools/generate-tests/generateSmokeRestTool.d.ts +1 -1
- package/build/tools/generate-tests/generateSmokeRestTool.js +1 -1
- package/build/tools/generate-tests/generateUILoadRestTool.d.ts +64 -0
- package/build/tools/generate-tests/generateUILoadRestTool.js +512 -0
- package/build/tools/generate-tests/generateUIRestTool.d.ts +8 -7
- package/build/tools/generate-tests/generateUIRestTool.js +10 -2
- package/build/tools/generate-tests/loadTestSchema.d.ts +15 -15
- package/build/tools/generate-tests/trace-reuse-guard.d.ts +1 -1
- package/build/tools/generateEnrichedIntegrationTestTool.d.ts +1 -2
- package/build/tools/generateEnrichedIntegrationTestTool.js +1 -1
- package/build/tools/localDevWorkerComposeTool.d.ts +1 -1
- package/build/tools/localDevWorkerComposeTool.js +2 -2
- package/build/tools/one-click/oneClickTool.d.ts +1 -1
- package/build/tools/one-click/oneClickTool.js +1 -1
- package/build/tools/preflightMockCheckTool.d.ts +1 -1
- package/build/tools/preflightMockCheckTool.js +3 -3
- package/build/tools/queryProxyMocksTool.d.ts +1 -1
- package/build/tools/queryProxyMocksTool.js +3 -3
- package/build/tools/submitReportTool.d.ts +111 -414
- package/build/tools/submitReportTool.js +88 -38
- package/build/tools/test-management/actionsTool.d.ts +1 -1
- package/build/tools/test-management/actionsTool.js +7 -7
- package/build/tools/test-management/analyzeChangesTool.d.ts +22 -118
- package/build/tools/test-management/analyzeChangesTool.js +4 -4
- package/build/tools/test-management/analyzeTestHealthTool.d.ts +1 -1
- package/build/tools/test-management/analyzeTestHealthTool.js +4 -4
- package/build/tools/test-management/registerTestPlanTool.d.ts +107 -733
- package/build/tools/test-management/registerTestPlanTool.js +12 -12
- package/build/tools/test-management/resolveScreenTool.d.ts +1 -1
- package/build/tools/test-management/resolveScreenTool.js +6 -2
- package/build/tools/trace/startTraceCollectionTool.d.ts +1 -1
- package/build/tools/trace/startTraceCollectionTool.js +4 -4
- package/build/tools/trace/stopTraceCollectionTool.d.ts +1 -1
- package/build/tools/trace/stopTraceCollectionTool.js +2 -2
- package/build/tools/verifyTestDependenciesTool.d.ts +1 -1
- package/build/tools/verifyTestDependenciesTool.js +1 -1
- package/build/tools/workspace/initScanWorkspaceTool.d.ts +1 -1
- package/build/tools/workspace/initScanWorkspaceTool.js +1 -1
- package/build/tools/workspace/initializeWorkspaceTool.d.ts +1 -1
- package/build/tools/workspace/initializeWorkspaceTool.js +1 -1
- package/build/types/RepositoryAnalysis.d.ts +164 -1170
- package/build/types/RepositoryAnalysis.js +12 -10
- package/build/types/StepMethod.d.ts +24 -1
- package/build/types/StepMethod.js +1 -1
- package/build/types/TestTypes.d.ts +41 -133
- package/build/types/TestTypes.js +25 -3
- package/build/types/TestbotReport.d.ts +4 -1
- package/build/utils/assertion-verify/metrics.js +12 -0
- package/build/utils/docker.d.ts +29 -7
- package/build/utils/docker.js +83 -27
- package/build/utils/findUp.d.ts +20 -0
- package/build/utils/findUp.js +59 -0
- package/build/utils/initAgent.d.ts +3 -3
- package/build/utils/initAgent.js +58 -26
- package/build/utils/language-helper.js +1 -1
- package/build/utils/progress.d.ts +3 -4
- package/build/utils/progress.js +4 -4
- package/build/utils/repoSdkVersion.d.ts +16 -0
- package/build/utils/repoSdkVersion.js +88 -0
- package/build/utils/testDependencyPolicy.d.ts +20 -0
- package/build/utils/testDependencyPolicy.js +64 -4
- package/build/utils/utils-verify/typecheck.js +3 -18
- package/build/utils/utils.d.ts +1 -1
- package/build/utils/versions.d.ts +3 -3
- package/build/utils/versions.js +1 -1
- package/build/workspace/workspace.d.ts +117 -538
- package/build/workspace/workspace.js +2 -2
- package/node_modules/playwright/lib/mcp/skyramp/assertOrder.js +66 -0
- package/node_modules/playwright/lib/mcp/skyramp/assertTool.js +12 -3
- package/node_modules/playwright/lib/mcp/skyramp/common/liveReadError.js +40 -0
- package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +21 -0
- package/node_modules/playwright/lib/mcp/skyramp/skyRampImport.js +2 -1
- package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +96 -16
- package/node_modules/playwright/lib/mcp/test/skyRampExport.js +10 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/server/codegen/skyramp/jsonlReader.js +1 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/recorderRunner.js +22 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/utils/isomorphic/elementOrder.js +57 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/utils.js +2 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{index.uiPTFncY.js → index.0MJW0uG7.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +1 -1
- package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/server/codegen/skyramp/jsonlReader.ts +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/recorderRunner.ts +26 -1
- package/node_modules/playwright/node_modules/playwright-core/src/utils/isomorphic/elementOrder.ts +83 -0
- package/node_modules/playwright/node_modules/playwright-core/src/utils.ts +1 -0
- package/node_modules/playwright/package.json +1 -1
- package/package.json +9 -6
- package/plugin/prompts/plan-tests.md +9 -17
- package/plugin/skills/enhance-assertions/reference/shared-rules.md +1 -1
- package/plugin/skills/enhance-assertions/reference/ui.md +2 -2
- package/plugin/skills/fix-test-import-errors/SKILL.md +1 -1
- package/plugin/skills/repair-staged-files/SKILL.md +17 -0
package/build/index.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/server";
|
|
3
4
|
import { runnableLanguagesText } from "./types/TestTypes.js";
|
|
4
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
5
|
import { registerStartTraceCollectionPrompt } from "./prompts/startTraceCollectionPrompts.js";
|
|
6
6
|
import { registerTraceTool } from "./tools/trace/startTraceCollectionTool.js";
|
|
7
7
|
import { registerTraceStopTool } from "./tools/trace/stopTraceCollectionTool.js";
|
|
8
8
|
import { registerExecuteSkyrampTestTool } from "./tools/executeSkyrampTestTool.js";
|
|
9
|
+
import { registerExecuteFleetTool } from "./tools/executeFleetTool.js";
|
|
9
10
|
import { AUTH_PLACEHOLDER_TOKEN } from "./types/TestTypes.js";
|
|
10
11
|
import { AUTH_CONFLICT_ERROR_MSG } from "./prompts/test-recommendation/recommendationSections.js";
|
|
11
12
|
import { logger } from "./utils/logger.js";
|
|
12
13
|
import { registerUITestTool } from "./tools/generate-tests/generateUIRestTool.js";
|
|
14
|
+
import { registerUILoadTestTool } from "./tools/generate-tests/generateUILoadRestTool.js";
|
|
13
15
|
import { registerSmokeTestTool } from "./tools/generate-tests/generateSmokeRestTool.js";
|
|
14
16
|
import { registerFuzzTestTool } from "./tools/generate-tests/generateFuzzRestTool.js";
|
|
15
17
|
import { registerContractTestTool } from "./tools/generate-tests/generateContractRestTool.js";
|
|
@@ -83,220 +85,249 @@ If the workspace root is a git repo AND \`.skyramp/workspace.yml\` does not exis
|
|
|
83
85
|
3. Proceed with the originally requested tool, if it is not one of the two workspace-init tools above.
|
|
84
86
|
Skip only if: not a git repo, \`.skyramp/workspace.yml\` already exists, or user explicitly declines.
|
|
85
87
|
`;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Builds one fully-registered server. `serveStdio` calls this per connection,
|
|
90
|
+
* so every registration must happen here rather than at module load.
|
|
91
|
+
*/
|
|
92
|
+
async function createServer({ era }) {
|
|
93
|
+
const server = new McpServer({
|
|
94
|
+
name: "Skyramp MCP Server",
|
|
95
|
+
version: "1.0.0",
|
|
96
|
+
}, {
|
|
97
|
+
capabilities: {
|
|
98
|
+
tools: {
|
|
99
|
+
listChanged: true,
|
|
100
|
+
},
|
|
101
|
+
prompts: {
|
|
102
|
+
listChanged: true,
|
|
103
|
+
},
|
|
104
|
+
resources: {
|
|
105
|
+
listChanged: true,
|
|
106
|
+
},
|
|
93
107
|
},
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
${workspaceInitInstructions}
|
|
103
|
-
## Rules
|
|
104
|
-
- NEVER show CLI commands. NEVER attempt to install or configure the Skyramp CLI. ALWAYS use the MCP tools provided.
|
|
105
|
-
- For UI and E2E tests, there are TWO recording modes:
|
|
106
|
-
1. **AI-driven recording** (default): Use the browser_* tools (browser_navigate, browser_click, etc.) to record interactions, then call skyramp_export_zip to export the trace, then call skyramp_ui_test_generation with the zip path.
|
|
107
|
-
2. **Manual recording**: ONLY when the user explicitly says "manual recording", "record myself", "I will interact", or "Docker trace" — use skyramp_start_trace_collection / skyramp_stop_trace_collection to let the user interact with the browser themselves.
|
|
108
|
-
- To capture an authentication session for re-use (e.g. "save session", "store login", "record auth state"): call \`skyramp_start_trace_collection\` (\`playwrightSaveStoragePath\` defaults to saving the session in \`outputDir\` — no need to set it). Tell the user to log in once and then call \`skyramp_stop_trace_collection\` IMMEDIATELY after login completes. The saved file can be passed back as \`playwrightStoragePath\` on later trace runs, or referenced as \`storageState\` in generated tests.${oneClickInstructions}
|
|
108
|
+
instructions: `Skyramp MCP Server — generates and executes API tests (fuzz, contract, integration, E2E, UI).
|
|
109
|
+
${workspaceInitInstructions}
|
|
110
|
+
## Rules
|
|
111
|
+
- NEVER show CLI commands. NEVER attempt to install or configure the Skyramp CLI. ALWAYS use the MCP tools provided.
|
|
112
|
+
- For UI and E2E tests, there are TWO recording modes:
|
|
113
|
+
1. **AI-driven recording** (default): Use the browser_* tools (browser_navigate, browser_click, etc.) to record interactions, then call skyramp_export_zip to export the trace, then call skyramp_ui_test_generation with the zip path.
|
|
114
|
+
2. **Manual recording**: ONLY when the user explicitly says "manual recording", "record myself", "I will interact", or "Docker trace" — use skyramp_start_trace_collection / skyramp_stop_trace_collection to let the user interact with the browser themselves.
|
|
115
|
+
- To capture an authentication session for re-use (e.g. "save session", "store login", "record auth state"): call \`skyramp_start_trace_collection\` (\`playwrightSaveStoragePath\` defaults to saving the session in \`outputDir\` — no need to set it). Tell the user to log in once and then call \`skyramp_stop_trace_collection\` IMMEDIATELY after login completes. The saved file can be passed back as \`playwrightStoragePath\` on later trace runs, or referenced as \`storageState\` in generated tests.${oneClickInstructions}
|
|
109
116
|
|
|
110
|
-
## Test Management Flow
|
|
111
|
-
Use \`skyramp_analyze_changes\` as the single entry point for both test recommendations and test health analysis.
|
|
117
|
+
## Test Management Flow
|
|
118
|
+
Use \`skyramp_analyze_changes\` as the single entry point for both test recommendations and test health analysis.
|
|
112
119
|
|
|
113
|
-
### Recommendations (2-step)
|
|
114
|
-
1. Call \`skyramp_analyze_changes\` with \`repositoryPath\` and \`scope\` → scans endpoints, computes branch diff, discovers existing tests → returns a \`stateFile\` **and** inline ranked test recommendations.
|
|
115
|
-
2. (Optional) Use the \`skyramp_recommend_tests\` prompt with \`stateFile\` in Cursor/IDE chat for a focused recommendation view.
|
|
120
|
+
### Recommendations (2-step)
|
|
121
|
+
1. Call \`skyramp_analyze_changes\` with \`repositoryPath\` and \`scope\` → scans endpoints, computes branch diff, discovers existing tests → returns a \`stateFile\` **and** inline ranked test recommendations.
|
|
122
|
+
2. (Optional) Use the \`skyramp_recommend_tests\` prompt with \`stateFile\` in Cursor/IDE chat for a focused recommendation view.
|
|
116
123
|
|
|
117
|
-
### Health Analysis (5-step)
|
|
118
|
-
1. Call \`skyramp_analyze_changes\` with \`repositoryPath\` and \`scope\` → returns a \`stateFile\`.
|
|
119
|
-
2. Run each external test in ${runnableLanguagesText()} with \`skyramp_execute_test\`, \`phase: "before"\`, and \`stateFile\` → the server runs your command and writes the verdict back to stateFile. The tool takes no other language, and the gate in step 3 does not ask for those.
|
|
120
|
-
3. Call \`skyramp_analyze_test_health\` with \`stateFile\` → runs drift analysis + health scoring + LLM semantic assessment. It refuses until step 2 has run.
|
|
121
|
-
4. (Optional) Run Skyramp-generated tests with \`skyramp_execute_test\` and \`stateFile\` → writes each verdict back for health scoring.
|
|
122
|
-
5. Call \`skyramp_actions\` with \`stateFile\` → executes UPDATE/REGENERATE/ADD recommendations (with execution-aware prioritization if step 4 ran).
|
|
124
|
+
### Health Analysis (5-step)
|
|
125
|
+
1. Call \`skyramp_analyze_changes\` with \`repositoryPath\` and \`scope\` → returns a \`stateFile\`.
|
|
126
|
+
2. Run each external test in ${runnableLanguagesText()} with \`skyramp_execute_test\`, \`phase: "before"\`, and \`stateFile\` → the server runs your command and writes the verdict back to stateFile. The tool takes no other language, and the gate in step 3 does not ask for those.
|
|
127
|
+
3. Call \`skyramp_analyze_test_health\` with \`stateFile\` → runs drift analysis + health scoring + LLM semantic assessment. It refuses until step 2 has run.
|
|
128
|
+
4. (Optional) Run Skyramp-generated tests with \`skyramp_execute_test\` and \`stateFile\` → writes each verdict back for health scoring.
|
|
129
|
+
5. Call \`skyramp_actions\` with \`stateFile\` → executes UPDATE/REGENERATE/ADD recommendations (with execution-aware prioritization if step 4 ran).
|
|
123
130
|
|
|
124
|
-
After \`skyramp_analyze_changes\`, inspect enriched data via MCP Resources (use the \`sessionId\` returned in the output):
|
|
125
|
-
- \`skyramp://analysis/{sessionId}/summary\` — high-level overview
|
|
126
|
-
- \`skyramp://analysis/{sessionId}/endpoints\` — compact endpoint listing
|
|
127
|
-
- \`skyramp://analysis/{sessionId}/endpoints/{path}\` — full path detail
|
|
128
|
-
- \`skyramp://analysis/{sessionId}/endpoints/{path}/{method}\` — single method detail
|
|
129
|
-
- \`skyramp://analysis/{sessionId}/scenarios\` — drafted scenarios
|
|
130
|
-
- \`skyramp://analysis/{sessionId}/diff\` — branch diff context
|
|
131
|
+
After \`skyramp_analyze_changes\`, inspect enriched data via MCP Resources (use the \`sessionId\` returned in the output):
|
|
132
|
+
- \`skyramp://analysis/{sessionId}/summary\` — high-level overview
|
|
133
|
+
- \`skyramp://analysis/{sessionId}/endpoints\` — compact endpoint listing
|
|
134
|
+
- \`skyramp://analysis/{sessionId}/endpoints/{path}\` — full path detail
|
|
135
|
+
- \`skyramp://analysis/{sessionId}/endpoints/{path}/{method}\` — single method detail
|
|
136
|
+
- \`skyramp://analysis/{sessionId}/scenarios\` — drafted scenarios
|
|
137
|
+
- \`skyramp://analysis/{sessionId}/diff\` — branch diff context
|
|
131
138
|
|
|
132
|
-
## Workspace Defaults for Test Generation (MANDATORY)
|
|
133
|
-
Before calling ANY test generation tool, you MUST follow this flow:
|
|
139
|
+
## Workspace Defaults for Test Generation (MANDATORY)
|
|
140
|
+
Before calling ANY test generation tool, you MUST follow this flow:
|
|
134
141
|
|
|
135
|
-
1. **Read** the .skyramp/workspace.yml file to get the configured defaults.
|
|
136
|
-
2. **Extract** the \`language\`, \`framework\`, \`testDirectory\`, \`api.baseUrl\`, \`api.authHeader\`, and \`api.authType\` from the matching service in the services section.
|
|
137
|
-
3. **Use those values** as defaults for the test generation tool call. Pass the service \`testDirectory\` as the generation tool \`outputDir\`. Do NOT ask the user for these values if they are already configured in the workspace file.
|
|
138
|
-
4. **CRITICAL — endpointURL**: The \`endpointURL\` parameter MUST be the full URL to the specific endpoint being tested, NOT just the base URL. Construct it by combining \`api.baseUrl\` with the endpoint path. Example: if \`api.baseUrl\` is \`http://localhost:8000\` and the endpoint is \`/api/v1/products\`, pass \`endpointURL: "http://localhost:8000/api/v1/products"\`. NEVER pass just the base URL (e.g. \`http://localhost:8000\`) as \`endpointURL\`.
|
|
139
|
-
5. **CRITICAL — scenario generation**: When calling \`skyramp_batch_scenario_test_generation\`, ALWAYS pass:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
6. **CRITICAL — integration test from scenario**: When calling \`skyramp_integration_test_generation\` with a \`scenarioFile\`:
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
7. **If the workspace file does not exist**, or the needed values (language, framework, testDirectory) are missing from the workspace config, ASK the user which language, framework, and outputDir they want before calling the tool.
|
|
149
|
-
8. The user can always override workspace defaults by explicitly specifying values in their request.
|
|
150
|
-
`,
|
|
151
|
-
});
|
|
152
|
-
// Register prompts
|
|
153
|
-
logger.info("Starting prompt registration process");
|
|
154
|
-
const prompts = [
|
|
155
|
-
registerStartTraceCollectionPrompt,
|
|
156
|
-
registerRecommendTestsPrompt,
|
|
157
|
-
registerTraceRecordingPrompt,
|
|
158
|
-
];
|
|
159
|
-
if (isTestbotEnabled()) {
|
|
160
|
-
prompts.push(registerTestbotPrompt);
|
|
161
|
-
registerTestbotResource(server);
|
|
162
|
-
logger.info("Testbot prompt enabled via SKYRAMP_FEATURE_TESTBOT");
|
|
163
|
-
registerSutSetupResource(server);
|
|
164
|
-
logger.info("Testbot SUT setup resource enabled via SKYRAMP_FEATURE_TESTBOT");
|
|
165
|
-
}
|
|
166
|
-
if (isLocalDevEnabled()) {
|
|
167
|
-
prompts.push(registerLocalDevPrompt);
|
|
168
|
-
logger.info("Local-dev prompt enabled via SKYRAMP_FEATURE_LOCAL_DEV");
|
|
169
|
-
}
|
|
170
|
-
prompts.forEach((registerPrompt) => registerPrompt(server));
|
|
171
|
-
logger.info("All prompts registered successfully");
|
|
172
|
-
// Register test generation tools
|
|
173
|
-
const testGenerationTools = [
|
|
174
|
-
registerSmokeTestTool,
|
|
175
|
-
registerFuzzTestTool,
|
|
176
|
-
registerContractTestTool,
|
|
177
|
-
registerLoadTestTool,
|
|
178
|
-
registerIntegrationTestTool,
|
|
179
|
-
registerE2ETestTool,
|
|
180
|
-
registerUITestTool,
|
|
181
|
-
registerBatchScenarioTestTool,
|
|
182
|
-
registerMockTool,
|
|
183
|
-
registerBatchMockTool,
|
|
184
|
-
];
|
|
185
|
-
testGenerationTools.forEach((registerTool) => registerTool(server));
|
|
186
|
-
// Register modularization and code quality tools
|
|
187
|
-
const codeQualityTools = [
|
|
188
|
-
registerModularizationTool,
|
|
189
|
-
registerCodeReuseTool,
|
|
190
|
-
registerEnhanceAssertionsTool,
|
|
191
|
-
registerAssertionVerifyTool,
|
|
192
|
-
registerVerifyTestDependenciesTool,
|
|
193
|
-
];
|
|
194
|
-
// With the Skyramp plugin loaded the agent already has the
|
|
195
|
-
// fix-test-import-errors skill; the tool would be a second copy of
|
|
196
|
-
// the same text (SKYR-4296).
|
|
197
|
-
if (!isSkillsLoaded()) {
|
|
198
|
-
// Same reasoning as fix-test-import-errors: with the plugin loaded the agent
|
|
199
|
-
// has the validate-assertion-alignment-post-execution skill directly; this
|
|
200
|
-
// tool exists so an agent without skill support still gets the same
|
|
201
|
-
// procedure, rendered from the same markdown with real arguments filled in.
|
|
202
|
-
codeQualityTools.push(registerFixErrorTool, registerAlignAssertionsTool);
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
// The enhance-assertions skill drives its own snapshot step itself (SKYR-4310).
|
|
206
|
-
codeQualityTools.push(registerAssertionSnapshotTool);
|
|
207
|
-
}
|
|
208
|
-
codeQualityTools.forEach((registerTool) => registerTool(server));
|
|
209
|
-
// Register analysis resources (MCP Resources for enriched data access)
|
|
210
|
-
registerAnalysisResources(server);
|
|
211
|
-
registerProgressResource(server);
|
|
212
|
-
// Register unified test-management tools (replaces separate test-maintenance tools)
|
|
213
|
-
registerAnalyzeChangesTool(server);
|
|
214
|
-
registerAnalyzeTestHealthTool(server);
|
|
215
|
-
registerActionsTool(server);
|
|
216
|
-
registerRegisterTestPlanTool(server);
|
|
217
|
-
registerResolveScreenTool(server);
|
|
218
|
-
// Register workspace management tools
|
|
219
|
-
registerInitScanWorkspaceTool(server);
|
|
220
|
-
registerInitializeWorkspaceTool(server);
|
|
221
|
-
// Register one-click orchestrated workflows
|
|
222
|
-
if (oneClickEnabled || localDevEnabled) {
|
|
223
|
-
registerOneClickTool(server);
|
|
224
|
-
logger.info("One-click tools enabled", {
|
|
225
|
-
enabledBy: {
|
|
226
|
-
SKYRAMP_FEATURE_ONE_CLICK: oneClickEnabled,
|
|
227
|
-
SKYRAMP_FEATURE_LOCAL_DEV: localDevEnabled,
|
|
228
|
-
},
|
|
142
|
+
1. **Read** the .skyramp/workspace.yml file to get the configured defaults.
|
|
143
|
+
2. **Extract** the \`language\`, \`framework\`, \`testDirectory\`, \`api.baseUrl\`, \`api.authHeader\`, and \`api.authType\` from the matching service in the services section.
|
|
144
|
+
3. **Use those values** as defaults for the test generation tool call. Pass the service \`testDirectory\` as the generation tool \`outputDir\`. Do NOT ask the user for these values if they are already configured in the workspace file.
|
|
145
|
+
4. **CRITICAL — endpointURL**: The \`endpointURL\` parameter MUST be the full URL to the specific endpoint being tested, NOT just the base URL. Construct it by combining \`api.baseUrl\` with the endpoint path. Example: if \`api.baseUrl\` is \`http://localhost:8000\` and the endpoint is \`/api/v1/products\`, pass \`endpointURL: "http://localhost:8000/api/v1/products"\`. NEVER pass just the base URL (e.g. \`http://localhost:8000\`) as \`endpointURL\`.
|
|
146
|
+
5. **CRITICAL — scenario generation**: When calling \`skyramp_batch_scenario_test_generation\`, ALWAYS pass:
|
|
147
|
+
- \`baseURL\`: The full base URL from \`api.baseUrl\` (e.g., \`http://localhost:3000\`). This determines the scheme, host, and port in the generated trace. Without it, the trace defaults to https:443 which is almost always wrong for local development.
|
|
148
|
+
- \`authHeader\`: Which HTTP header carries the auth credential. Get it from \`api.authHeader\` in workspace config. Examples: \`Authorization\` (Bearer/Token auth), \`X-Api-Key\` (API key auth), \`Cookie\` (session/cookie auth like NextAuth). Pass \`""\` to document the endpoint as unauthenticated in the generated test's assertions (unauthenticated endpoints or \`api.authType: "none"\`).
|
|
149
|
+
- \`authScheme\`: Only when \`authHeader\` is \`Authorization\`. The prefix before the token (e.g., \`"Bearer"\` → \`Authorization: Bearer <token>\`). **Derive from**: (1) OpenAPI spec \`securitySchemes\`/\`securityDefinitions\`, (2) source code auth middleware, (3) workspace \`api.authType\`. **Do NOT guess.**
|
|
150
|
+
- \`authToken\`: The full header value, used verbatim. When omitted, \`SKYRAMP_PLACEHOLDER_TOKEN\` is auto-generated. Only provide when the header needs a specific format (e.g., \`"session=${AUTH_PLACEHOLDER_TOKEN}"\` for Cookie). **Do NOT fabricate token values.**
|
|
151
|
+
- \`apiSchema\` is OPTIONAL — omit it for code-first apps without OpenAPI specs.
|
|
152
|
+
6. **CRITICAL — integration test from scenario**: When calling \`skyramp_integration_test_generation\` with a \`scenarioFile\`:
|
|
153
|
+
- If workspace has \`api.authType\` set: omit auth params entirely — passing auth here alongside workspace \`authType\` causes "${AUTH_CONFLICT_ERROR_MSG}".
|
|
154
|
+
- If workspace has no \`api.authType\`: pass \`authHeader\` only (no \`authScheme\`).
|
|
155
|
+
7. **If the workspace file does not exist**, or the needed values (language, framework, testDirectory) are missing from the workspace config, ASK the user which language, framework, and outputDir they want before calling the tool.
|
|
156
|
+
8. The user can always override workspace defaults by explicitly specifying values in their request.
|
|
157
|
+
`,
|
|
229
158
|
});
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
//
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
159
|
+
// Register prompts
|
|
160
|
+
logger.info("Starting prompt registration process");
|
|
161
|
+
const prompts = [
|
|
162
|
+
registerStartTraceCollectionPrompt,
|
|
163
|
+
registerRecommendTestsPrompt,
|
|
164
|
+
registerTraceRecordingPrompt,
|
|
165
|
+
];
|
|
166
|
+
if (isTestbotEnabled()) {
|
|
167
|
+
prompts.push(registerTestbotPrompt);
|
|
168
|
+
registerTestbotResource(server);
|
|
169
|
+
logger.info("Testbot prompt enabled via SKYRAMP_FEATURE_TESTBOT");
|
|
170
|
+
registerSutSetupResource(server);
|
|
171
|
+
logger.info("Testbot SUT setup resource enabled via SKYRAMP_FEATURE_TESTBOT");
|
|
172
|
+
}
|
|
173
|
+
if (isLocalDevEnabled()) {
|
|
174
|
+
prompts.push(registerLocalDevPrompt);
|
|
175
|
+
logger.info("Local-dev prompt enabled via SKYRAMP_FEATURE_LOCAL_DEV");
|
|
176
|
+
}
|
|
177
|
+
prompts.forEach((registerPrompt) => registerPrompt(server));
|
|
178
|
+
logger.info("All prompts registered successfully");
|
|
179
|
+
// Register test generation tools
|
|
180
|
+
const testGenerationTools = [
|
|
181
|
+
registerSmokeTestTool,
|
|
182
|
+
registerFuzzTestTool,
|
|
183
|
+
registerContractTestTool,
|
|
184
|
+
registerLoadTestTool,
|
|
185
|
+
registerIntegrationTestTool,
|
|
186
|
+
registerE2ETestTool,
|
|
187
|
+
registerUITestTool,
|
|
188
|
+
registerUILoadTestTool,
|
|
189
|
+
registerBatchScenarioTestTool,
|
|
190
|
+
registerMockTool,
|
|
191
|
+
registerBatchMockTool,
|
|
192
|
+
];
|
|
193
|
+
testGenerationTools.forEach((registerTool) => registerTool(server));
|
|
194
|
+
// Register modularization and code quality tools
|
|
195
|
+
const codeQualityTools = [
|
|
196
|
+
registerModularizationTool,
|
|
197
|
+
registerCodeReuseTool,
|
|
198
|
+
registerEnhanceAssertionsTool,
|
|
199
|
+
registerAssertionVerifyTool,
|
|
200
|
+
registerVerifyTestDependenciesTool,
|
|
201
|
+
];
|
|
202
|
+
// With the Skyramp plugin loaded the agent already has the
|
|
203
|
+
// fix-test-import-errors skill; the tool would be a second copy of
|
|
204
|
+
// the same text (SKYR-4296).
|
|
205
|
+
if (!isSkillsLoaded()) {
|
|
206
|
+
// Same reasoning as fix-test-import-errors: with the plugin loaded the agent
|
|
207
|
+
// has the validate-assertion-alignment-post-execution skill directly; this
|
|
208
|
+
// tool exists so an agent without skill support still gets the same
|
|
209
|
+
// procedure, rendered from the same markdown with real arguments filled in.
|
|
210
|
+
codeQualityTools.push(registerFixErrorTool, registerAlignAssertionsTool);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
// The enhance-assertions skill drives its own snapshot step itself (SKYR-4310).
|
|
214
|
+
codeQualityTools.push(registerAssertionSnapshotTool);
|
|
215
|
+
}
|
|
216
|
+
codeQualityTools.forEach((registerTool) => registerTool(server));
|
|
217
|
+
// Register analysis resources (MCP Resources for enriched data access)
|
|
218
|
+
registerAnalysisResources(server);
|
|
219
|
+
registerProgressResource(server);
|
|
220
|
+
// Register unified test-management tools (replaces separate test-maintenance tools)
|
|
221
|
+
registerAnalyzeChangesTool(server);
|
|
222
|
+
registerAnalyzeTestHealthTool(server);
|
|
223
|
+
registerActionsTool(server);
|
|
224
|
+
registerRegisterTestPlanTool(server);
|
|
225
|
+
registerResolveScreenTool(server);
|
|
226
|
+
// Register workspace management tools
|
|
227
|
+
registerInitScanWorkspaceTool(server);
|
|
228
|
+
registerInitializeWorkspaceTool(server);
|
|
229
|
+
// Register one-click orchestrated workflows
|
|
230
|
+
if (oneClickEnabled || localDevEnabled) {
|
|
231
|
+
registerOneClickTool(server);
|
|
232
|
+
logger.info("One-click tools enabled", {
|
|
233
|
+
enabledBy: {
|
|
234
|
+
SKYRAMP_FEATURE_ONE_CLICK: oneClickEnabled,
|
|
235
|
+
SKYRAMP_FEATURE_LOCAL_DEV: localDevEnabled,
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
// Register other Skyramp tools
|
|
240
|
+
const infrastructureTools = [
|
|
241
|
+
registerLoginTool,
|
|
242
|
+
registerLogoutTool,
|
|
243
|
+
registerExecuteSkyrampTestTool,
|
|
244
|
+
registerExecuteFleetTool,
|
|
245
|
+
registerTraceTool,
|
|
246
|
+
registerTraceStopTool,
|
|
247
|
+
];
|
|
248
|
+
if (isLocalDevEnabled()) {
|
|
249
|
+
infrastructureTools.push(registerEnrichTestWithMocksTool, registerPreflightMockCheckTool, registerGenerateEnrichedIntegrationTestTool, registerLocalDevWorkerComposeTool, registerQueryProxyMocksTool);
|
|
250
|
+
logger.info("Local-dev tools enabled via SKYRAMP_FEATURE_LOCAL_DEV");
|
|
251
|
+
}
|
|
252
|
+
if (isTestbotEnabled()) {
|
|
253
|
+
infrastructureTools.push(registerSubmitReportTool);
|
|
254
|
+
logger.info("Testbot tools enabled via SKYRAMP_FEATURE_TESTBOT");
|
|
255
|
+
}
|
|
256
|
+
infrastructureTools.forEach((registerTool) => registerTool(server));
|
|
257
|
+
// Register Playwright browser tools (trace recording via browser automation).
|
|
258
|
+
//
|
|
259
|
+
// Tell the capture which attribute this repository uses for test ids. Without
|
|
260
|
+
// it the capture assumes Playwright's `data-testid`, and a repo using anything
|
|
261
|
+
// else gets no test-id anchor and a positional xpath for every element — which
|
|
262
|
+
// resolves at capture time and breaks later, so the miss never announces itself
|
|
263
|
+
// (SKYR-4136). This server is the only component that knows which repository it
|
|
264
|
+
// is running against.
|
|
265
|
+
//
|
|
266
|
+
// A declared `use.testIdAttribute` is authoritative. Failing that, the
|
|
267
|
+
// repository's own tests name the attribute whenever they select on it, so read
|
|
268
|
+
// it out of their selectors rather than guessing from a list of popular names.
|
|
269
|
+
// Never fatal: no answer leaves the capture on Playwright's default.
|
|
270
|
+
//
|
|
271
|
+
// Awaited, and worth the wait: `PlaywrightTraceService.initialize()` is 206ms
|
|
272
|
+
// of it and the browser tools come out of that service, so nothing can
|
|
273
|
+
// register them earlier. Running it in the background instead delays every
|
|
274
|
+
// connection's first response by nothing but leaves the client holding 27
|
|
275
|
+
// tools of 52 — Claude Code does not re-list on `tools/list_changed`, so all
|
|
276
|
+
// 23 `browser_*` tools stay invisible for the whole run.
|
|
277
|
+
await (async () => {
|
|
278
|
+
let testIdAttribute;
|
|
279
|
+
try {
|
|
280
|
+
const root = await findRoot(process.cwd());
|
|
281
|
+
testIdAttribute = await readTestIdAttribute(root);
|
|
272
282
|
if (testIdAttribute) {
|
|
273
|
-
|
|
274
|
-
// attribute wins, and a wrong pick should be visible here rather than
|
|
275
|
-
// showing up later as brittle selectors.
|
|
276
|
-
logger.info(`testIdAttribute discovered from test selectors: ${testIdAttribute}`, { counts: discovered.counts, filesScanned: discovered.filesScanned });
|
|
283
|
+
logger.info(`testIdAttribute declared by the Playwright config: ${testIdAttribute}`);
|
|
277
284
|
}
|
|
278
285
|
else {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
286
|
+
const discovered = await discoverTestIdAttribute(root);
|
|
287
|
+
testIdAttribute = discovered.attribute;
|
|
288
|
+
if (testIdAttribute) {
|
|
289
|
+
// Log the runner-up counts: on a part-migrated repo the most-used
|
|
290
|
+
// attribute wins, and a wrong pick should be visible here rather than
|
|
291
|
+
// showing up later as brittle selectors.
|
|
292
|
+
logger.info(`testIdAttribute discovered from test selectors: ${testIdAttribute}`, {
|
|
293
|
+
counts: discovered.counts,
|
|
294
|
+
filesScanned: discovered.filesScanned,
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
// No name rule can reach an arbitrary convention like `xyz-id`, so name
|
|
299
|
+
// what the selectors did contain and the variable that overrides it.
|
|
300
|
+
// Editing the repo's own Playwright config is the wrong instruction: a
|
|
301
|
+
// suite may have several, and none of them at the root.
|
|
302
|
+
logger.info("No testIdAttribute declared or discovered — capture stays on Playwright's data-testid. " +
|
|
303
|
+
"Set PLAYWRIGHT_MCP_TEST_ID_ATTRIBUTE to override.", {
|
|
304
|
+
attributesSeenInSelectors: discovered.observed,
|
|
305
|
+
filesScanned: discovered.filesScanned,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
288
308
|
}
|
|
289
309
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
310
|
+
catch (err) {
|
|
311
|
+
logger.warning("Could not determine this repository's testIdAttribute", {
|
|
312
|
+
error: err,
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
await registerPlaywrightTools(server, { testIdAttribute });
|
|
316
|
+
})().catch((err) => {
|
|
317
|
+
logger.error("Failed to register Playwright tools", { error: err });
|
|
318
|
+
});
|
|
319
|
+
const runInitTrigger = () => {
|
|
320
|
+
registerInitTriggerOnMCPInitialized().catch((err) => {
|
|
321
|
+
logger.error("Failed to run MCP initialized trigger", { error: err });
|
|
294
322
|
});
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
323
|
+
};
|
|
324
|
+
server.server.oninitialized = runInitTrigger;
|
|
325
|
+
// A 2026-07-28 connection has no `initialize` exchange, so `oninitialized`
|
|
326
|
+
// never fires on it.
|
|
327
|
+
if (era === "modern")
|
|
328
|
+
runInitTrigger();
|
|
329
|
+
return server;
|
|
330
|
+
}
|
|
300
331
|
// Global error handlers for crash telemetry
|
|
301
332
|
process.on("uncaughtException", async (error) => {
|
|
302
333
|
// Don't send analytics for EPIPE errors
|
|
@@ -350,13 +381,11 @@ process.on("unhandledRejection", async (reason) => {
|
|
|
350
381
|
});
|
|
351
382
|
// Start MCP server
|
|
352
383
|
async function main() {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
};
|
|
359
|
-
await server.connect(transport);
|
|
384
|
+
// `serveStdio` owns the era decision: it reads the opening exchange and pins
|
|
385
|
+
// one instance from the factory for the connection. `StdioServerTransport`
|
|
386
|
+
// serves the 2025 handshake only, so the 2026-07-28 revision is unreachable
|
|
387
|
+
// through it however the client asks.
|
|
388
|
+
const handle = serveStdio(createServer);
|
|
360
389
|
logger.info("MCP Server started successfully");
|
|
361
390
|
// Listen for stdin closure (parent process disconnected)
|
|
362
391
|
// Using multiple events for robustness across different disconnection scenarios
|
|
@@ -372,7 +401,7 @@ async function main() {
|
|
|
372
401
|
? playwrightService.shutdown().catch(() => { })
|
|
373
402
|
: Promise.resolve();
|
|
374
403
|
cleanupPlaywright.finally(() => {
|
|
375
|
-
|
|
404
|
+
handle.close().finally(() => {
|
|
376
405
|
process.exit(0);
|
|
377
406
|
});
|
|
378
407
|
});
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* The Playwright fork is CJS; this project is ESM. We use createRequire
|
|
6
6
|
* to bridge the module systems.
|
|
7
7
|
*/
|
|
8
|
-
import type { CallToolResult } from "@modelcontextprotocol/
|
|
8
|
+
import type { CallToolResult } from "@modelcontextprotocol/server";
|
|
9
9
|
interface McpTool {
|
|
10
10
|
name: string;
|
|
11
11
|
description?: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CallToolResult } from "@modelcontextprotocol/
|
|
1
|
+
import type { CallToolResult } from "@modelcontextprotocol/server";
|
|
2
2
|
import type { BlueprintCaptureDigest } from "../types/BlueprintDigest.js";
|
|
3
3
|
/** A run that takes more captures than this has a browsing problem of its own;
|
|
4
4
|
* the cap is here so a runaway loop cannot grow the process without bound. */
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
* tools in the Skyramp MCP server, delegating calls to PlaywrightTraceService.
|
|
4
4
|
*/
|
|
5
5
|
import { PlaywrightTraceService, type PlaywrightTraceOptions } from "./PlaywrightTraceService.js";
|
|
6
|
-
import type { McpServer } from "@modelcontextprotocol/
|
|
6
|
+
import type { McpServer } from "@modelcontextprotocol/server";
|
|
7
7
|
export declare function getPlaywrightTraceService(): PlaywrightTraceService | null;
|
|
8
8
|
export declare function registerPlaywrightTools(server: McpServer, options?: PlaywrightTraceOptions): Promise<void>;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* MCP prompt that guides the LLM through the Playwright-based trace recording
|
|
3
3
|
* and Skyramp test generation flow.
|
|
4
4
|
*/
|
|
5
|
-
import type { McpServer } from "@modelcontextprotocol/
|
|
5
|
+
import type { McpServer } from "@modelcontextprotocol/server";
|
|
6
6
|
export interface TraceRecordingPromptOpts {
|
|
7
7
|
/** Directory where zip files should be written. Defaults to same dir as test file. */
|
|
8
8
|
outputDir?: string;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { logger } from "../utils/logger.js";
|
|
7
7
|
import { getPersonaPrefix } from "../prompts/personas.js";
|
|
8
|
+
import { ORDER_ASSERTION_RULE } from "../prompts/orderAssertionRule.js";
|
|
8
9
|
export function getTraceRecordingPromptText(opts) {
|
|
9
10
|
const outputDir = opts?.outputDir;
|
|
10
11
|
const modularize = opts?.modularize ?? true;
|
|
@@ -65,7 +66,7 @@ Call \`browser_assert\` when assertions are needed. Provide \`expected\` for eve
|
|
|
65
66
|
|
|
66
67
|
**Visual / screenshot assertions.** When the instruction asks to take a screenshot, capture a baseline, or verify how a page/element/region *looks* (as opposed to its text or value), call \`browser_visual_snapshot\` — it records a \`toHaveScreenshot()\` assertion so the generated test pixel-compares against a baseline image on every run.
|
|
67
68
|
|
|
68
|
-
**When the change under test is how something looks** — a colour, class or attribute the diff changes — assert it directly with \`browser_assert\` \`type: css/class/attribute\` on the element that OWNS the property (the flex container for \`flex-direction\`, not its children); if it has no stable ref, note a recording gap rather than assert the wrong element.
|
|
69
|
+
**When the change under test is how something looks** — a colour, class or attribute the diff changes — assert it directly with \`browser_assert\` \`type: css/class/attribute\` on the element that OWNS the property (the flex container for \`flex-direction\`, not its children); if it has no stable ref, note a recording gap rather than assert the wrong element. ${ORDER_ASSERTION_RULE} \`browser_visual_snapshot\` only for a look no property expresses (image, gradient, chart).
|
|
69
70
|
|
|
70
71
|
Do NOT use \`browser_take_screenshot\` to record a visual check: it only captures a throwaway image, is dropped at export (it produces no assertion), and will NOT appear in the generated test. Use it only to view the page yourself while recording. \`filename\` is optional on \`browser_visual_snapshot\`: if the instruction names a baseline file (e.g. \`page-001.png\`) pass it as \`filename\`, otherwise omit it and one is auto-generated per \`snapshotType\` (\`page-NNN.png\` for a page, \`el-NNN.png\` for an element, \`region-NNN.png\` for a region).
|
|
71
72
|
|
|
@@ -81,7 +82,7 @@ export function registerTraceRecordingPrompt(server) {
|
|
|
81
82
|
logger.info("Registering trace recording prompt");
|
|
82
83
|
server.registerPrompt("skyramp_trace_recording_prompt", {
|
|
83
84
|
description: "Guide for recording browser interactions as a Skyramp trace and generating UI tests",
|
|
84
|
-
argsSchema: {
|
|
85
|
+
argsSchema: z.object({
|
|
85
86
|
outputDir: z
|
|
86
87
|
.string()
|
|
87
88
|
.optional()
|
|
@@ -91,7 +92,7 @@ export function registerTraceRecordingPrompt(server) {
|
|
|
91
92
|
.default(true)
|
|
92
93
|
.optional()
|
|
93
94
|
.describe("Whether to run skyramp_modularization after generation. Default: true. Set to false in CI."),
|
|
94
|
-
},
|
|
95
|
+
}),
|
|
95
96
|
}, (args) => ({
|
|
96
97
|
messages: [
|
|
97
98
|
{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { McpServer } from "@modelcontextprotocol/
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/server";
|
|
2
2
|
import { type Service } from "../../workspace/workspace.js";
|
|
3
3
|
export declare function getLocalDevPrompt(baseCommit: string, repositoryPath: string, repository: string, sandboxWorkerUrl?: string, maxRecommendations?: number, maxGenerate?: number, services?: Service[], stateOutputFile?: string, servicesToMock?: string[], realServices?: string[], mockProtocols?: string[], proxyKubeconfig?: string, proxyNamespace?: string): string;
|
|
4
4
|
export declare function registerLocalDevPrompt(server: McpServer): void;
|
|
@@ -121,7 +121,7 @@ export function registerLocalDevPrompt(server) {
|
|
|
121
121
|
logger.info("Registering local-dev prompt");
|
|
122
122
|
server.registerPrompt("skyramp_local_dev", {
|
|
123
123
|
description: "Run Skyramp local-dev workflow: diff from a base commit, discover downstream dependencies, document mock requirements, generate mocks and backend tests, execute them against a local environment, and report results.",
|
|
124
|
-
argsSchema: {
|
|
124
|
+
argsSchema: z.object({
|
|
125
125
|
baseCommit: z
|
|
126
126
|
.string()
|
|
127
127
|
.describe("Base commit reference to diff against — accepts a branch name (e.g. 'main'), a commit SHA (e.g. 'abc123f'), or a tag (e.g. 'v1.2.0'). The diff is computed between this ref and the current working tree (committed plus uncommitted changes)."),
|
|
@@ -167,7 +167,7 @@ export function registerLocalDevPrompt(server) {
|
|
|
167
167
|
.string()
|
|
168
168
|
.optional()
|
|
169
169
|
.describe("Comma-separated list of downstream service names that are already running locally and should receive real traffic (e.g. 'postgres,redis,envoy'). These will NOT be mocked."),
|
|
170
|
-
},
|
|
170
|
+
}),
|
|
171
171
|
}, async (args) => {
|
|
172
172
|
const services = await readWorkspaceServices(args.repositoryPath);
|
|
173
173
|
// skyramp_analyze_changes and skyramp_execute_test both name their repository
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* When to record a swap, move or reorder as an order assertion. It lives in the
|
|
3
|
+
* trace-recording prompt, which the testbot flow includes; the top-level testbot
|
|
4
|
+
* prompt does not repeat test-type details. The type's parameters are
|
|
5
|
+
* documented by browser_assert's own description, and the pairing rule (two
|
|
6
|
+
* sibling blocks, not a block and something inside it) is enforced and
|
|
7
|
+
* explained by the tool, so neither is repeated here.
|
|
8
|
+
*/
|
|
9
|
+
export declare const ORDER_ASSERTION_RULE = "**A swap, move or reorder** (left/right columns swapped, a sidebar moved, blocks reordered) is recorded with `browser_assert` `type: \"order\"` on two blocks (`ref` and `otherRef`), so the test fails if the swap is undone; `flex-direction` alone is not enough when the diff reorders markup.";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* When to record a swap, move or reorder as an order assertion. It lives in the
|
|
3
|
+
* trace-recording prompt, which the testbot flow includes; the top-level testbot
|
|
4
|
+
* prompt does not repeat test-type details. The type's parameters are
|
|
5
|
+
* documented by browser_assert's own description, and the pairing rule (two
|
|
6
|
+
* sibling blocks, not a block and something inside it) is enforced and
|
|
7
|
+
* explained by the tool, so neither is repeated here.
|
|
8
|
+
*/
|
|
9
|
+
export const ORDER_ASSERTION_RULE = '**A swap, move or reorder** (left/right columns swapped, a sidebar moved, blocks reordered) is recorded with `browser_assert` `type: "order"` on two blocks (`ref` and `otherRef`), so the test fails if the swap is undone; `flex-direction` alone is not enough when the diff reorders markup.';
|