retestkit 1.4.1 → 1.5.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 (238) hide show
  1. package/README.md +59 -40
  2. package/dist/config.js +8 -8
  3. package/dist/config.js.map +1 -1
  4. package/dist/logger.js +1 -1
  5. package/dist/logger.js.map +1 -1
  6. package/dist/prompts/index.d.ts +1 -1
  7. package/dist/prompts/index.d.ts.map +1 -1
  8. package/dist/prompts/index.js +21 -21
  9. package/dist/prompts/index.js.map +1 -1
  10. package/dist/prompts/templates/mcp/retest-crawl.md +7 -0
  11. package/{src/prompts/templates/mcp/webtest-discover-flows.md → dist/prompts/templates/mcp/retest-discover-flows.md} +1 -1
  12. package/{src/prompts/templates/mcp/webtest-discover.md → dist/prompts/templates/mcp/retest-discover.md} +2 -2
  13. package/dist/prompts/templates/mcp/retest-full-workflow.md +12 -0
  14. package/{src/prompts/templates/mcp/webtest-generate-tests.md → dist/prompts/templates/mcp/retest-generate-tests.md} +1 -1
  15. package/{src/prompts/templates/mcp/webtest-run-test.md → dist/prompts/templates/mcp/retest-run-test.md} +1 -1
  16. package/{src/prompts/templates/mcp/webtest-start.md → dist/prompts/templates/mcp/retest-start.md} +1 -1
  17. package/{src → dist}/prompts/templates/sampling/system-prefix.md +1 -1
  18. package/dist/resources/index.js +7 -7
  19. package/dist/resources/index.js.map +1 -1
  20. package/dist/schemas/config.js +2 -2
  21. package/dist/schemas/config.js.map +1 -1
  22. package/dist/security/index.js +1 -1
  23. package/dist/security/index.js.map +1 -1
  24. package/dist/server.js +3 -3
  25. package/dist/server.js.map +1 -1
  26. package/dist/test-utils/mock-context.js +22 -22
  27. package/dist/test-utils/mock-context.js.map +1 -1
  28. package/dist/tools/index.d.ts +1 -1
  29. package/dist/tools/index.d.ts.map +1 -1
  30. package/dist/tools/index.js +5 -5
  31. package/dist/tools/index.js.map +1 -1
  32. package/dist/tools/retest/crawl.d.ts.map +1 -0
  33. package/dist/tools/{webtest → retest}/crawl.js +7 -7
  34. package/dist/tools/retest/crawl.js.map +1 -0
  35. package/dist/tools/retest/discover-features.d.ts.map +1 -0
  36. package/dist/tools/{webtest → retest}/discover-features.js +6 -6
  37. package/dist/tools/retest/discover-features.js.map +1 -0
  38. package/dist/tools/retest/discover-flows.d.ts.map +1 -0
  39. package/dist/tools/{webtest → retest}/discover-flows.js +6 -6
  40. package/dist/tools/retest/discover-flows.js.map +1 -0
  41. package/dist/tools/retest/generate-tests.d.ts.map +1 -0
  42. package/dist/tools/{webtest → retest}/generate-tests.js +5 -5
  43. package/dist/tools/retest/generate-tests.js.map +1 -0
  44. package/dist/tools/retest/index.d.ts.map +1 -0
  45. package/dist/tools/retest/index.js.map +1 -0
  46. package/dist/tools/retest/run-test-case.d.ts.map +1 -0
  47. package/dist/tools/{webtest → retest}/run-test-case.js +3 -3
  48. package/dist/tools/retest/run-test-case.js.map +1 -0
  49. package/dist/tools/retest/schemas.d.ts.map +1 -0
  50. package/dist/tools/retest/schemas.js.map +1 -0
  51. package/dist/tools/retest/start-analysis.d.ts.map +1 -0
  52. package/dist/tools/{webtest → retest}/start-analysis.js +5 -5
  53. package/dist/tools/retest/start-analysis.js.map +1 -0
  54. package/dist/workspace/index.js +8 -8
  55. package/dist/workspace/index.js.map +1 -1
  56. package/dist/workspace/types.d.ts +2 -2
  57. package/dist/workspace/types.d.ts.map +1 -1
  58. package/package.json +6 -2
  59. package/.claude/commands/openspec/apply.md +0 -23
  60. package/.claude/commands/openspec/archive.md +0 -27
  61. package/.claude/commands/openspec/proposal.md +0 -28
  62. package/.gemini/commands/openspec/apply.toml +0 -21
  63. package/.gemini/commands/openspec/archive.toml +0 -25
  64. package/.gemini/commands/openspec/proposal.toml +0 -26
  65. package/.github/prompts/openspec-apply.prompt.md +0 -22
  66. package/.github/prompts/openspec-archive.prompt.md +0 -26
  67. package/.github/prompts/openspec-proposal.prompt.md +0 -27
  68. package/.github/workflows/release.yml +0 -33
  69. package/.kilocode/workflows/openspec-apply.md +0 -17
  70. package/.kilocode/workflows/openspec-archive.md +0 -21
  71. package/.kilocode/workflows/openspec-proposal.md +0 -22
  72. package/.mcp.json +0 -23
  73. package/.opencode/command/openspec-apply.md +0 -25
  74. package/.opencode/command/openspec-archive.md +0 -28
  75. package/.opencode/command/openspec-proposal.md +0 -30
  76. package/.roo/commands/openspec-apply.md +0 -20
  77. package/.roo/commands/openspec-archive.md +0 -24
  78. package/.roo/commands/openspec-proposal.md +0 -25
  79. package/.vscode/mcp.json +0 -23
  80. package/AGENTS.md +0 -18
  81. package/CLAUDE.md +0 -18
  82. package/dist/tools/webtest/crawl.d.ts.map +0 -1
  83. package/dist/tools/webtest/crawl.js.map +0 -1
  84. package/dist/tools/webtest/discover-features.d.ts.map +0 -1
  85. package/dist/tools/webtest/discover-features.js.map +0 -1
  86. package/dist/tools/webtest/discover-flows.d.ts.map +0 -1
  87. package/dist/tools/webtest/discover-flows.js.map +0 -1
  88. package/dist/tools/webtest/generate-tests.d.ts.map +0 -1
  89. package/dist/tools/webtest/generate-tests.js.map +0 -1
  90. package/dist/tools/webtest/index.d.ts.map +0 -1
  91. package/dist/tools/webtest/index.js.map +0 -1
  92. package/dist/tools/webtest/run-test-case.d.ts.map +0 -1
  93. package/dist/tools/webtest/run-test-case.js.map +0 -1
  94. package/dist/tools/webtest/schemas.d.ts.map +0 -1
  95. package/dist/tools/webtest/schemas.js.map +0 -1
  96. package/dist/tools/webtest/start-analysis.d.ts.map +0 -1
  97. package/dist/tools/webtest/start-analysis.js.map +0 -1
  98. package/openspec/AGENTS.md +0 -456
  99. package/openspec/changes/archive/2025-12-18-add-hybrid-artifact-paths/proposal.md +0 -33
  100. package/openspec/changes/archive/2025-12-18-add-hybrid-artifact-paths/specs/webtest-resources/spec.md +0 -27
  101. package/openspec/changes/archive/2025-12-18-add-hybrid-artifact-paths/specs/webtest-tools/spec.md +0 -304
  102. package/openspec/changes/archive/2025-12-18-add-hybrid-artifact-paths/tasks.md +0 -43
  103. package/openspec/changes/archive/2025-12-18-add-mcp-server-foundation/design.md +0 -209
  104. package/openspec/changes/archive/2025-12-18-add-mcp-server-foundation/proposal.md +0 -41
  105. package/openspec/changes/archive/2025-12-18-add-mcp-server-foundation/specs/mcp-server-core/spec.md +0 -183
  106. package/openspec/changes/archive/2025-12-18-add-mcp-server-foundation/tasks.md +0 -112
  107. package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/design.md +0 -333
  108. package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/proposal.md +0 -66
  109. package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/mcp-server-core/spec.md +0 -129
  110. package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-lifecycle/spec.md +0 -138
  111. package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-logging/spec.md +0 -211
  112. package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-prompts/spec.md +0 -157
  113. package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-resources/spec.md +0 -213
  114. package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-sampling/spec.md +0 -257
  115. package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-tools/spec.md +0 -501
  116. package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/tasks.md +0 -264
  117. package/openspec/changes/archive/2025-12-18-allow-analysis-of-incomplete-crawls/proposal.md +0 -24
  118. package/openspec/changes/archive/2025-12-18-allow-analysis-of-incomplete-crawls/specs/webtest-tools/spec.md +0 -80
  119. package/openspec/changes/archive/2025-12-18-allow-analysis-of-incomplete-crawls/tasks.md +0 -8
  120. package/openspec/changes/archive/2025-12-18-fix-crawl-loop-stability/design.md +0 -90
  121. package/openspec/changes/archive/2025-12-18-fix-crawl-loop-stability/proposal.md +0 -28
  122. package/openspec/changes/archive/2025-12-18-fix-crawl-loop-stability/specs/webtest-sampling/spec.md +0 -90
  123. package/openspec/changes/archive/2025-12-18-fix-crawl-loop-stability/tasks.md +0 -33
  124. package/openspec/changes/archive/2025-12-18-use-markdown-artifacts/design.md +0 -558
  125. package/openspec/changes/archive/2025-12-18-use-markdown-artifacts/proposal.md +0 -119
  126. package/openspec/changes/archive/2025-12-18-use-markdown-artifacts/specs/webtest-resources/spec.md +0 -109
  127. package/openspec/changes/archive/2025-12-18-use-markdown-artifacts/specs/webtest-tools/spec.md +0 -121
  128. package/openspec/changes/archive/2025-12-18-use-markdown-artifacts/tasks.md +0 -133
  129. package/openspec/changes/extract-prompts-to-markdown/design.md +0 -86
  130. package/openspec/changes/extract-prompts-to-markdown/proposal.md +0 -50
  131. package/openspec/changes/extract-prompts-to-markdown/specs/webtest-prompts/spec.md +0 -74
  132. package/openspec/changes/extract-prompts-to-markdown/tasks.md +0 -40
  133. package/openspec/changes/refactor-webtest-naming/design.md +0 -95
  134. package/openspec/changes/refactor-webtest-naming/proposal.md +0 -66
  135. package/openspec/changes/refactor-webtest-naming/specs/webtest-prompts/spec.md +0 -79
  136. package/openspec/changes/refactor-webtest-naming/specs/webtest-resources/spec.md +0 -80
  137. package/openspec/changes/refactor-webtest-naming/specs/webtest-sampling/spec.md +0 -122
  138. package/openspec/changes/refactor-webtest-naming/specs/webtest-tools/spec.md +0 -113
  139. package/openspec/changes/refactor-webtest-naming/tasks.md +0 -119
  140. package/openspec/changes/rename-package-to-retest/proposal.md +0 -52
  141. package/openspec/changes/rename-package-to-retest/specs/mcp-server-core/spec.md +0 -53
  142. package/openspec/changes/rename-package-to-retest/specs/retest-lifecycle/spec.md +0 -68
  143. package/openspec/changes/rename-package-to-retest/specs/retest-logging/spec.md +0 -35
  144. package/openspec/changes/rename-package-to-retest/specs/retest-prompts/spec.md +0 -159
  145. package/openspec/changes/rename-package-to-retest/specs/retest-resources/spec.md +0 -251
  146. package/openspec/changes/rename-package-to-retest/specs/retest-sampling/spec.md +0 -99
  147. package/openspec/changes/rename-package-to-retest/specs/retest-tools/spec.md +0 -295
  148. package/openspec/changes/rename-package-to-retest/tasks.md +0 -71
  149. package/openspec/project.md +0 -31
  150. package/openspec/specs/mcp-server-core/spec.md +0 -178
  151. package/openspec/specs/webtest-lifecycle/spec.md +0 -136
  152. package/openspec/specs/webtest-logging/spec.md +0 -209
  153. package/openspec/specs/webtest-prompts/spec.md +0 -155
  154. package/openspec/specs/webtest-resources/spec.md +0 -248
  155. package/openspec/specs/webtest-sampling/spec.md +0 -344
  156. package/openspec/specs/webtest-tools/spec.md +0 -282
  157. package/release.config.js +0 -9
  158. package/src/config.test.ts +0 -96
  159. package/src/config.ts +0 -32
  160. package/src/elicitation/index.test.ts +0 -399
  161. package/src/elicitation/index.ts +0 -171
  162. package/src/elicitation/types.ts +0 -68
  163. package/src/index.ts +0 -83
  164. package/src/lifecycle/index.test.ts +0 -260
  165. package/src/lifecycle/index.ts +0 -101
  166. package/src/logger.redaction.test.ts +0 -322
  167. package/src/logger.test.ts +0 -123
  168. package/src/logger.ts +0 -229
  169. package/src/playwright-client/index.ts +0 -392
  170. package/src/playwright-client/types.ts +0 -99
  171. package/src/progress/index.test.ts +0 -327
  172. package/src/progress/index.ts +0 -170
  173. package/src/progress/types.ts +0 -25
  174. package/src/prompts/index.test.ts +0 -451
  175. package/src/prompts/index.ts +0 -246
  176. package/src/prompts/loader.test.ts +0 -100
  177. package/src/prompts/loader.ts +0 -59
  178. package/src/prompts/templates/mcp/webtest-crawl.md +0 -7
  179. package/src/prompts/templates/mcp/webtest-full-workflow.md +0 -12
  180. package/src/resources/index.ts +0 -250
  181. package/src/resources/subscriptions.ts +0 -37
  182. package/src/sampling/index.test.ts +0 -414
  183. package/src/sampling/index.ts +0 -286
  184. package/src/sampling/prompts.ts +0 -194
  185. package/src/sampling/types.ts +0 -60
  186. package/src/schemas/config.ts +0 -39
  187. package/src/security/index.test.ts +0 -441
  188. package/src/security/index.ts +0 -361
  189. package/src/security/security-scenarios.test.ts +0 -468
  190. package/src/server.ts +0 -211
  191. package/src/test-utils/index.ts +0 -6
  192. package/src/test-utils/mock-context.ts +0 -426
  193. package/src/test-utils/mock-playwright-client.ts +0 -422
  194. package/src/tools/index.ts +0 -11
  195. package/src/tools/webtest/crawl.test.ts +0 -834
  196. package/src/tools/webtest/crawl.ts +0 -901
  197. package/src/tools/webtest/discover-features.ts +0 -412
  198. package/src/tools/webtest/discover-flows.ts +0 -408
  199. package/src/tools/webtest/generate-tests.test.ts +0 -532
  200. package/src/tools/webtest/generate-tests.ts +0 -425
  201. package/src/tools/webtest/index.ts +0 -7
  202. package/src/tools/webtest/integration.test.ts +0 -536
  203. package/src/tools/webtest/run-test-case.test.ts +0 -659
  204. package/src/tools/webtest/run-test-case.ts +0 -508
  205. package/src/tools/webtest/schemas.ts +0 -201
  206. package/src/tools/webtest/start-analysis.test.ts +0 -151
  207. package/src/tools/webtest/start-analysis.ts +0 -158
  208. package/src/transports/http.ts +0 -19
  209. package/src/transports/index.ts +0 -30
  210. package/src/transports/stdio.ts +0 -7
  211. package/src/types/capabilities.test.ts +0 -193
  212. package/src/types/capabilities.ts +0 -50
  213. package/src/types/context.ts +0 -21
  214. package/src/types/tool.ts +0 -11
  215. package/src/workspace/index.ts +0 -945
  216. package/src/workspace/markdown.ts +0 -272
  217. package/src/workspace/types.ts +0 -186
  218. package/tests/integration/server.test.ts +0 -89
  219. package/tests/integration/tools.test.ts +0 -99
  220. package/tsconfig.json +0 -20
  221. package/vitest.config.ts +0 -9
  222. package/vitest.integration.config.ts +0 -10
  223. /package/{src → dist}/prompts/templates/sampling/crawl-action.md +0 -0
  224. /package/{src → dist}/prompts/templates/sampling/feature-discovery.md +0 -0
  225. /package/{src → dist}/prompts/templates/sampling/flow-discovery.md +0 -0
  226. /package/{src → dist}/prompts/templates/sampling/page-content-wrapper.md +0 -0
  227. /package/{src → dist}/prompts/templates/sampling/test-evaluation.md +0 -0
  228. /package/{src → dist}/prompts/templates/sampling/test-generation.md +0 -0
  229. /package/dist/tools/{webtest → retest}/crawl.d.ts +0 -0
  230. /package/dist/tools/{webtest → retest}/discover-features.d.ts +0 -0
  231. /package/dist/tools/{webtest → retest}/discover-flows.d.ts +0 -0
  232. /package/dist/tools/{webtest → retest}/generate-tests.d.ts +0 -0
  233. /package/dist/tools/{webtest → retest}/index.d.ts +0 -0
  234. /package/dist/tools/{webtest → retest}/index.js +0 -0
  235. /package/dist/tools/{webtest → retest}/run-test-case.d.ts +0 -0
  236. /package/dist/tools/{webtest → retest}/schemas.d.ts +0 -0
  237. /package/dist/tools/{webtest → retest}/schemas.js +0 -0
  238. /package/dist/tools/{webtest → retest}/start-analysis.d.ts +0 -0
@@ -1,151 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from "vitest";
2
- import { createStartAnalysisTool } from "./start-analysis.js";
3
- import {
4
- createMockContext,
5
- type MockContext,
6
- } from "../../test-utils/index.js";
7
-
8
- describe("webtest_init", () => {
9
- let context: MockContext;
10
- let tool: ReturnType<typeof createStartAnalysisTool>;
11
-
12
- beforeEach(() => {
13
- context = createMockContext();
14
- tool = createStartAnalysisTool(() => context as any);
15
- });
16
-
17
- describe("tool metadata", () => {
18
- it("has correct name", () => {
19
- expect(tool.name).toBe("webtest_init");
20
- });
21
-
22
- it("has a description", () => {
23
- expect(tool.description).toBeDefined();
24
- expect(tool.description.length).toBeGreaterThan(0);
25
- });
26
-
27
- it("has an input schema", () => {
28
- expect(tool.inputSchema).toBeDefined();
29
- });
30
- });
31
-
32
- describe("handler", () => {
33
- it("creates workspace for valid URL", async () => {
34
- const result = await tool.handler({
35
- url: "https://example.com",
36
- focus: "Test the login flow",
37
- });
38
-
39
- expect(result.isError).toBeFalsy();
40
- expect(context.workspaceManager.createWorkspace).toHaveBeenCalledWith(
41
- expect.objectContaining({
42
- url: "https://example.com",
43
- focus: "Test the login flow",
44
- })
45
- );
46
- });
47
-
48
- it("returns analysisId in response", async () => {
49
- const result = await tool.handler({
50
- url: "https://example.com",
51
- });
52
-
53
- expect(result.isError).toBeFalsy();
54
- const content = result.content[0];
55
- expect(content.type).toBe("text");
56
- expect(content.text).toContain("analysisId");
57
- });
58
-
59
- it("uses default limits from config", async () => {
60
- await tool.handler({
61
- url: "https://example.com",
62
- });
63
-
64
- expect(context.workspaceManager.createWorkspace).toHaveBeenCalledWith(
65
- expect.objectContaining({
66
- limits: expect.objectContaining({
67
- maxSteps: context.config.defaultMaxSteps,
68
- maxMinutes: context.config.defaultMaxMinutes,
69
- maxPages: context.config.defaultMaxPages,
70
- }),
71
- })
72
- );
73
- });
74
-
75
- it("respects custom limits", async () => {
76
- await tool.handler({
77
- url: "https://example.com",
78
- limits: {
79
- maxSteps: 10,
80
- maxMinutes: 5,
81
- maxPages: 3,
82
- },
83
- });
84
-
85
- expect(context.workspaceManager.createWorkspace).toHaveBeenCalledWith(
86
- expect.objectContaining({
87
- limits: expect.objectContaining({
88
- maxSteps: 10,
89
- maxMinutes: 5,
90
- maxPages: 3,
91
- }),
92
- })
93
- );
94
- });
95
-
96
- it("stores allowed domains from input URL", async () => {
97
- const result = await tool.handler({
98
- url: "https://shop.example.com/products",
99
- });
100
-
101
- expect(result.isError).toBeFalsy();
102
- // The domain should be extracted and stored
103
- const content = JSON.parse(result.content[0].text!);
104
- expect(content.domain).toBe("shop.example.com");
105
- });
106
-
107
- it("handles custom allowed domains", async () => {
108
- const result = await tool.handler({
109
- url: "https://shop.example.com",
110
- allowedDomains: ["shop.example.com", "api.example.com"],
111
- });
112
-
113
- expect(result.isError).toBeFalsy();
114
- const content = JSON.parse(result.content[0].text!);
115
- expect(content.allowedDomains).toContain("shop.example.com");
116
- expect(content.allowedDomains).toContain("api.example.com");
117
- });
118
-
119
- it("returns error for invalid URL", async () => {
120
- const result = await tool.handler({
121
- url: "not-a-valid-url",
122
- });
123
-
124
- expect(result.isError).toBe(true);
125
- expect(result.content[0].text).toContain("Error");
126
- });
127
-
128
- it("logs analysis start", async () => {
129
- await tool.handler({
130
- url: "https://example.com",
131
- focus: "Test flow",
132
- });
133
-
134
- expect(context.logger.info).toHaveBeenCalledWith(
135
- expect.stringContaining("analysis"),
136
- expect.any(Object)
137
- );
138
- });
139
-
140
- it("returns workspace URIs", async () => {
141
- const result = await tool.handler({
142
- url: "https://example.com",
143
- });
144
-
145
- expect(result.isError).toBeFalsy();
146
- const content = JSON.parse(result.content[0].text!);
147
- expect(content.workspaceRootUri).toContain("webtest://");
148
- expect(content.statusUri).toContain("webtest://");
149
- });
150
- });
151
- });
@@ -1,158 +0,0 @@
1
- import { z } from "zod";
2
- import type { McpTool, ToolResult } from "../../types/tool.js";
3
- import type { ServerContext } from "../../types/context.js";
4
- import { AnalysisLimitsSchema } from "./schemas.js";
5
-
6
- export const startAnalysisInputSchema = z.object({
7
- url: z.string().url("Must be a valid URL"),
8
- focus: z
9
- .string()
10
- .optional()
11
- .describe("Optional focus area for the analysis (e.g., 'checkout flow', 'user registration')"),
12
- limits: AnalysisLimitsSchema.optional().describe(
13
- "Optional limits for the analysis"
14
- ),
15
- allowedDomains: z
16
- .array(z.string())
17
- .optional()
18
- .describe("Additional domains to allow during crawling (target domain is always allowed)"),
19
- });
20
-
21
- export type StartAnalysisInput = z.infer<typeof startAnalysisInputSchema>;
22
-
23
- export function createStartAnalysisTool(
24
- getContext: () => ServerContext
25
- ): McpTool<StartAnalysisInput> {
26
- return {
27
- name: "webtest_init",
28
- description: `Initialize a new web testing analysis workspace.
29
-
30
- This tool creates a workspace for analyzing a web application. It:
31
- - Validates the target URL
32
- - Creates a workspace directory structure
33
- - Records analysis metadata and limits
34
- - Returns identifiers for subsequent operations
35
-
36
- Use this as the first step before crawling, analyzing, or testing.`,
37
-
38
- inputSchema: startAnalysisInputSchema,
39
-
40
- async handler(input: StartAnalysisInput): Promise<ToolResult> {
41
- const ctx = getContext();
42
- const { config, logger } = ctx;
43
-
44
- logger.info("Starting analysis", { url: input.url, focus: input.focus });
45
-
46
- // Validate and normalize URL
47
- let targetUrl: URL;
48
- try {
49
- targetUrl = new URL(input.url);
50
- } catch {
51
- return {
52
- content: [
53
- {
54
- type: "text",
55
- text: `Error: Invalid URL "${input.url}". Please provide a valid HTTP or HTTPS URL.`,
56
- },
57
- ],
58
- isError: true,
59
- };
60
- }
61
-
62
- if (!["http:", "https:"].includes(targetUrl.protocol)) {
63
- return {
64
- content: [
65
- {
66
- type: "text",
67
- text: `Error: URL must use HTTP or HTTPS protocol. Got: ${targetUrl.protocol}`,
68
- },
69
- ],
70
- isError: true,
71
- };
72
- }
73
-
74
- // Determine limits
75
- const limits = {
76
- maxSteps: input.limits?.maxSteps ?? config.defaultMaxSteps,
77
- maxMinutes: input.limits?.maxMinutes ?? config.defaultMaxMinutes,
78
- maxPages: input.limits?.maxPages ?? config.defaultMaxPages,
79
- };
80
-
81
- // Build allowed domains list
82
- const allowedDomains = new Set<string>([targetUrl.hostname]);
83
- if (input.allowedDomains) {
84
- for (const domain of input.allowedDomains) {
85
- allowedDomains.add(domain);
86
- }
87
- }
88
-
89
- // Create workspace using workspace manager from context
90
- // Note: We need to get this from an extended context that includes the workspace manager
91
- const workspaceManager = (ctx as any).workspaceManager;
92
- if (!workspaceManager) {
93
- return {
94
- content: [
95
- {
96
- type: "text",
97
- text: "Error: Workspace manager not available. Server may not be fully initialized.",
98
- },
99
- ],
100
- isError: true,
101
- };
102
- }
103
-
104
- try {
105
- const { analysisId, workspacePath } = await workspaceManager.createWorkspace({
106
- url: input.url,
107
- focus: input.focus,
108
- limits,
109
- });
110
-
111
- // Notify clients about new resource
112
- const resourceManager = (ctx as any).resourceManager;
113
- if (resourceManager) {
114
- await resourceManager.notifyListChanged();
115
- }
116
-
117
- const result = {
118
- analysisId,
119
- workspaceRootPath: workspacePath,
120
- workspaceRootUri: `webtest://${analysisId}`,
121
- statusUri: `webtest://${analysisId}/index.md`,
122
- domain: targetUrl.hostname,
123
- allowedDomains: Array.from(allowedDomains),
124
- limits,
125
- nextSteps: [
126
- `Use webtest_crawl_app with analysisId="${analysisId}" to explore the application`,
127
- "Set a goal describing what you want to explore or test",
128
- "After crawling, use webtest_analyze_app to analyze the application structure",
129
- ],
130
- };
131
-
132
- logger.info("Analysis workspace created", { analysisId, url: input.url });
133
-
134
- return {
135
- content: [
136
- {
137
- type: "text",
138
- text: JSON.stringify(result, null, 2),
139
- },
140
- ],
141
- };
142
- } catch (error) {
143
- const message = error instanceof Error ? error.message : "Unknown error";
144
- logger.error("Failed to create analysis workspace", { error: message });
145
-
146
- return {
147
- content: [
148
- {
149
- type: "text",
150
- text: `Error creating workspace: ${message}`,
151
- },
152
- ],
153
- isError: true,
154
- };
155
- }
156
- },
157
- };
158
- }
@@ -1,19 +0,0 @@
1
- import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
2
- import type { Logger } from "../logger.js";
3
-
4
- export interface HttpTransportOptions {
5
- port: number;
6
- }
7
-
8
- export function createHttpTransport(
9
- options: HttpTransportOptions,
10
- logger: Logger
11
- ): StreamableHTTPServerTransport {
12
- logger.info("Creating HTTP transport", { port: options.port });
13
-
14
- return new StreamableHTTPServerTransport({
15
- sessionIdGenerator: () => crypto.randomUUID(),
16
- });
17
- }
18
-
19
- export { StreamableHTTPServerTransport };
@@ -1,30 +0,0 @@
1
- import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
2
- import type { Config } from "../config.js";
3
- import type { Logger } from "../logger.js";
4
- import { createStdioTransport } from "./stdio.js";
5
- import {
6
- createHttpTransport,
7
- StreamableHTTPServerTransport,
8
- } from "./http.js";
9
-
10
- export type TransportResult =
11
- | { type: "stdio"; transport: Transport }
12
- | { type: "http"; transport: StreamableHTTPServerTransport; port: number };
13
-
14
- export function createTransport(config: Config, logger: Logger): TransportResult {
15
- switch (config.transport) {
16
- case "stdio":
17
- return {
18
- type: "stdio",
19
- transport: createStdioTransport(logger),
20
- };
21
- case "http":
22
- return {
23
- type: "http",
24
- transport: createHttpTransport({ port: config.port }, logger),
25
- port: config.port,
26
- };
27
- default:
28
- throw new Error(`Unknown transport type: ${config.transport}`);
29
- }
30
- }
@@ -1,7 +0,0 @@
1
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2
- import type { Logger } from "../logger.js";
3
-
4
- export function createStdioTransport(logger: Logger): StdioServerTransport {
5
- logger.info("Creating stdio transport");
6
- return new StdioServerTransport();
7
- }
@@ -1,193 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import {
3
- DEFAULT_CAPABILITIES,
4
- hasSampling,
5
- hasElicitation,
6
- hasLogging,
7
- hasProgress,
8
- hasResourcesListChanged,
9
- hasResourcesSubscribe,
10
- isElicitationSupported,
11
- type ClientCapabilities,
12
- } from "./capabilities.js";
13
-
14
- describe("capabilities", () => {
15
- describe("DEFAULT_CAPABILITIES", () => {
16
- it("has all capabilities disabled by default", () => {
17
- expect(DEFAULT_CAPABILITIES.sampling).toBe(false);
18
- expect(DEFAULT_CAPABILITIES.elicitation).toBe(false);
19
- expect(DEFAULT_CAPABILITIES.logging).toBe(false);
20
- expect(DEFAULT_CAPABILITIES.progress).toBe(false);
21
- expect(DEFAULT_CAPABILITIES.resourcesListChanged).toBe(false);
22
- expect(DEFAULT_CAPABILITIES.resourcesSubscribe).toBe(false);
23
- });
24
-
25
- it("has unknown protocol version by default", () => {
26
- expect(DEFAULT_CAPABILITIES.protocolVersion).toBe("unknown");
27
- });
28
- });
29
-
30
- describe("capability helper functions", () => {
31
- const enabledCaps: ClientCapabilities = {
32
- sampling: true,
33
- elicitation: true,
34
- logging: true,
35
- progress: true,
36
- resourcesListChanged: true,
37
- resourcesSubscribe: true,
38
- protocolVersion: "2025-06-18",
39
- };
40
-
41
- const disabledCaps: ClientCapabilities = {
42
- sampling: false,
43
- elicitation: false,
44
- logging: false,
45
- progress: false,
46
- resourcesListChanged: false,
47
- resourcesSubscribe: false,
48
- protocolVersion: "2024-01-01",
49
- };
50
-
51
- describe("hasSampling", () => {
52
- it("returns true when sampling is enabled", () => {
53
- expect(hasSampling(enabledCaps)).toBe(true);
54
- });
55
-
56
- it("returns false when sampling is disabled", () => {
57
- expect(hasSampling(disabledCaps)).toBe(false);
58
- });
59
- });
60
-
61
- describe("hasElicitation", () => {
62
- it("returns true when elicitation is enabled", () => {
63
- expect(hasElicitation(enabledCaps)).toBe(true);
64
- });
65
-
66
- it("returns false when elicitation is disabled", () => {
67
- expect(hasElicitation(disabledCaps)).toBe(false);
68
- });
69
- });
70
-
71
- describe("hasLogging", () => {
72
- it("returns true when logging is enabled", () => {
73
- expect(hasLogging(enabledCaps)).toBe(true);
74
- });
75
-
76
- it("returns false when logging is disabled", () => {
77
- expect(hasLogging(disabledCaps)).toBe(false);
78
- });
79
- });
80
-
81
- describe("hasProgress", () => {
82
- it("returns true when progress is enabled", () => {
83
- expect(hasProgress(enabledCaps)).toBe(true);
84
- });
85
-
86
- it("returns false when progress is disabled", () => {
87
- expect(hasProgress(disabledCaps)).toBe(false);
88
- });
89
- });
90
-
91
- describe("hasResourcesListChanged", () => {
92
- it("returns true when resourcesListChanged is enabled", () => {
93
- expect(hasResourcesListChanged(enabledCaps)).toBe(true);
94
- });
95
-
96
- it("returns false when resourcesListChanged is disabled", () => {
97
- expect(hasResourcesListChanged(disabledCaps)).toBe(false);
98
- });
99
- });
100
-
101
- describe("hasResourcesSubscribe", () => {
102
- it("returns true when resourcesSubscribe is enabled", () => {
103
- expect(hasResourcesSubscribe(enabledCaps)).toBe(true);
104
- });
105
-
106
- it("returns false when resourcesSubscribe is disabled", () => {
107
- expect(hasResourcesSubscribe(disabledCaps)).toBe(false);
108
- });
109
- });
110
- });
111
-
112
- describe("isElicitationSupported", () => {
113
- it("returns true when elicitation enabled and protocol version sufficient", () => {
114
- const caps: ClientCapabilities = {
115
- ...DEFAULT_CAPABILITIES,
116
- elicitation: true,
117
- protocolVersion: "2025-06-18",
118
- };
119
-
120
- expect(isElicitationSupported(caps)).toBe(true);
121
- });
122
-
123
- it("returns true for newer protocol versions", () => {
124
- const caps: ClientCapabilities = {
125
- ...DEFAULT_CAPABILITIES,
126
- elicitation: true,
127
- protocolVersion: "2025-12-01",
128
- };
129
-
130
- expect(isElicitationSupported(caps)).toBe(true);
131
- });
132
-
133
- it("returns false when protocol version is too old", () => {
134
- const caps: ClientCapabilities = {
135
- ...DEFAULT_CAPABILITIES,
136
- elicitation: true,
137
- protocolVersion: "2025-01-01",
138
- };
139
-
140
- expect(isElicitationSupported(caps)).toBe(false);
141
- });
142
-
143
- it("returns false when protocol version is unknown", () => {
144
- const caps: ClientCapabilities = {
145
- ...DEFAULT_CAPABILITIES,
146
- elicitation: true,
147
- protocolVersion: "unknown",
148
- };
149
-
150
- expect(isElicitationSupported(caps)).toBe(false);
151
- });
152
-
153
- it("returns false when elicitation is disabled", () => {
154
- const caps: ClientCapabilities = {
155
- ...DEFAULT_CAPABILITIES,
156
- elicitation: false,
157
- protocolVersion: "2025-06-18",
158
- };
159
-
160
- expect(isElicitationSupported(caps)).toBe(false);
161
- });
162
-
163
- it("returns false when both elicitation disabled and old protocol", () => {
164
- const caps: ClientCapabilities = {
165
- ...DEFAULT_CAPABILITIES,
166
- elicitation: false,
167
- protocolVersion: "2024-01-01",
168
- };
169
-
170
- expect(isElicitationSupported(caps)).toBe(false);
171
- });
172
-
173
- it("handles edge case protocol version exactly matching requirement", () => {
174
- const caps: ClientCapabilities = {
175
- ...DEFAULT_CAPABILITIES,
176
- elicitation: true,
177
- protocolVersion: "2025-06-18",
178
- };
179
-
180
- expect(isElicitationSupported(caps)).toBe(true);
181
- });
182
-
183
- it("handles protocol version one day before requirement", () => {
184
- const caps: ClientCapabilities = {
185
- ...DEFAULT_CAPABILITIES,
186
- elicitation: true,
187
- protocolVersion: "2025-06-17",
188
- };
189
-
190
- expect(isElicitationSupported(caps)).toBe(false);
191
- });
192
- });
193
- });
@@ -1,50 +0,0 @@
1
- export interface ClientCapabilities {
2
- sampling: boolean;
3
- elicitation: boolean;
4
- logging: boolean;
5
- progress: boolean;
6
- resourcesListChanged: boolean;
7
- resourcesSubscribe: boolean;
8
- protocolVersion: string;
9
- }
10
-
11
- export const DEFAULT_CAPABILITIES: ClientCapabilities = {
12
- sampling: false,
13
- elicitation: false,
14
- logging: false,
15
- progress: false,
16
- resourcesListChanged: false,
17
- resourcesSubscribe: false,
18
- protocolVersion: "unknown",
19
- };
20
-
21
- export function hasSampling(caps: ClientCapabilities): boolean {
22
- return caps.sampling;
23
- }
24
-
25
- export function hasElicitation(caps: ClientCapabilities): boolean {
26
- return caps.elicitation;
27
- }
28
-
29
- export function hasLogging(caps: ClientCapabilities): boolean {
30
- return caps.logging;
31
- }
32
-
33
- export function hasProgress(caps: ClientCapabilities): boolean {
34
- return caps.progress;
35
- }
36
-
37
- export function hasResourcesListChanged(caps: ClientCapabilities): boolean {
38
- return caps.resourcesListChanged;
39
- }
40
-
41
- export function hasResourcesSubscribe(caps: ClientCapabilities): boolean {
42
- return caps.resourcesSubscribe;
43
- }
44
-
45
- export function isElicitationSupported(caps: ClientCapabilities): boolean {
46
- // Elicitation requires protocol version 2025-06-18 or later
47
- const version = caps.protocolVersion;
48
- if (version === "unknown") return false;
49
- return version >= "2025-06-18" && caps.elicitation;
50
- }
@@ -1,21 +0,0 @@
1
- import type { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
- import type { Config } from "../schemas/config.js";
3
- import type { Logger } from "../logger.js";
4
- import type { ClientCapabilities } from "./capabilities.js";
5
- import type { PlaywrightClient } from "../playwright-client/index.js";
6
- import type { CancellationRegistry } from "../progress/index.js";
7
- import type { ResourceSubscriptions } from "../resources/subscriptions.js";
8
-
9
- export interface ServerContext {
10
- config: Config;
11
- logger: Logger;
12
- server: Server;
13
- capabilities: ClientCapabilities;
14
- playwrightClient: PlaywrightClient | null;
15
- cancellationRegistry: CancellationRegistry;
16
- resourceSubscriptions: ResourceSubscriptions;
17
- }
18
-
19
- export type ServerContextWithPlaywright = ServerContext & {
20
- playwrightClient: PlaywrightClient;
21
- };
package/src/types/tool.ts DELETED
@@ -1,11 +0,0 @@
1
- import type { z } from "zod";
2
- import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
-
4
- export type ToolResult = CallToolResult;
5
-
6
- export interface McpTool<TInput = unknown> {
7
- name: string;
8
- description: string;
9
- inputSchema: z.ZodType<TInput>;
10
- handler: (input: TInput) => Promise<ToolResult>;
11
- }