@uuv/mcp-server 0.1.3 → 0.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.
package/dist/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [0.1.3](https://github.com/e2e-test-quest/uuv/compare/mcp-server-v0.1.2...mcp-server-v0.1.3) (2025-11-21)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **mcp-server:** add requirements and claude code config ([a942847](https://github.com/e2e-test-quest/uuv/commit/a942847afe5c0af96adffdd7ec1d56852c53a119))
7
+
1
8
  ## [0.1.2](https://github.com/e2e-test-quest/uuv/compare/mcp-server-v0.1.1...mcp-server-v0.1.2) (2025-11-20)
2
9
 
3
10
 
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function createUUVServer(): McpServer;
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createUUVServer = createUUVServer;
4
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
5
+ const zod_1 = require("zod");
6
+ const sentence_service_1 = require("./services/sentence.service");
7
+ const prompt_retriever_service_1 = require("./services/prompt-retriever.service");
8
+ const dictionary_1 = require("@uuv/dictionary");
9
+ const expect_service_1 = require("./services/expect.service");
10
+ function handleElementTestGeneration(input) {
11
+ let result;
12
+ const service = (0, expect_service_1.getElementService)(input.serviceType);
13
+ if (input.accessibleName && input.accessibleRole) {
14
+ result = service.generateTestForElement(input);
15
+ }
16
+ else if (input.domSelector) {
17
+ result = service.generateTestForElement(input);
18
+ }
19
+ else {
20
+ throw new Error("You must provide either (accessibleRole AND accessibleName) or domSelector");
21
+ }
22
+ return {
23
+ content: [
24
+ {
25
+ type: "text",
26
+ text: result,
27
+ },
28
+ ],
29
+ };
30
+ }
31
+ function createUUVServer() {
32
+ const server = new mcp_js_1.McpServer({
33
+ name: "uuv-mcp-server",
34
+ version: "0.0.1-beta",
35
+ });
36
+ const FindElementInputSchema = {
37
+ baseUrl: zod_1.z.string().describe("The base URL of the page where the element is located."),
38
+ accessibleName: zod_1.z.string().optional().describe("Accessible name of the element"),
39
+ accessibleRole: zod_1.z.string().optional().describe("Accessible role of the element"),
40
+ domSelector: zod_1.z.string().optional().describe("Dom selector of the element"),
41
+ };
42
+ server.registerTool("retrieve_prompt", {
43
+ title: "Retrieve uuv prompt",
44
+ description: "Retrieve a uuv prompt template for a coding agent based on a prompt name and arguments.",
45
+ inputSchema: {
46
+ promptName: zod_1.z.enum([
47
+ prompt_retriever_service_1.UUV_PROMPT.GENERATE_TEST_EXPECT_TABLE,
48
+ prompt_retriever_service_1.UUV_PROMPT.GENERATE_TEST_EXPECT_ELEMENT,
49
+ prompt_retriever_service_1.UUV_PROMPT.GENERATE_TEST_CLICK_ELEMENT,
50
+ ]),
51
+ baseUrl: zod_1.z.string().describe("The base URL of the page"),
52
+ // generate_test_* Fields
53
+ accessibleName: zod_1.z.string().optional().describe("Accessible name (required for generate_role_and_name)"),
54
+ accessibleRole: zod_1.z.string().optional().describe("Accessible role (required for generate_role_and_name)"),
55
+ domSelector: zod_1.z.string().optional().describe("Dom selector of the element"),
56
+ },
57
+ }, async ({ ...args }) => {
58
+ return {
59
+ content: [
60
+ {
61
+ type: "text",
62
+ text: prompt_retriever_service_1.PromptRetrieverService.retrievePrompt(args),
63
+ },
64
+ ],
65
+ };
66
+ });
67
+ server.registerTool("available_sentences", {
68
+ title: "List Available UUV Sentences",
69
+ description:
70
+ // eslint-disable-next-line max-len
71
+ "List all available UUV test sentences/phrases in Gherkin format. Use this when the user asks about UUV syntax, available commands, what sentences/phrases are available for testing, or needs help with UUV sentence structure. Can be filtered by category (given/when/then) or ARIA role (button, textbox, etc.) to show specific test actions.",
72
+ inputSchema: {
73
+ category: zod_1.z
74
+ .enum(["general", "keyboard", "click", "contains", "type", "checkable"])
75
+ .optional()
76
+ .describe("Filters sentences based on the action type"),
77
+ role: zod_1.z.string().optional().describe("Filters sentences related to an accessible role"),
78
+ },
79
+ }, async ({ category, role }) => {
80
+ const sentenceService = new sentence_service_1.SentenceService((0, dictionary_1.getDefinedDictionary)("en"));
81
+ const allSentences = sentenceService.searchSentences({ category, role });
82
+ return {
83
+ content: [
84
+ {
85
+ type: "text",
86
+ text: JSON.stringify(allSentences, null, 2),
87
+ },
88
+ ],
89
+ };
90
+ });
91
+ server.registerTool("generate_test_expect_element", {
92
+ title: "Generate test that expects of html element with role and name",
93
+ description:
94
+ // eslint-disable-next-line max-len
95
+ "Generate a complete UUV test scenario (Gherkin format) to verify the presence of an element with specified accessible name and role or domSelector. Use this when the user asks to create/write/generate a UUV scenario or test for checking element visibility. DON'T USE IF ACCESSIBLE ROLE IS grid, treegrid, table, or form",
96
+ inputSchema: FindElementInputSchema,
97
+ }, ({ baseUrl, accessibleName, accessibleRole, domSelector }) => {
98
+ if (accessibleRole === "table" || accessibleRole === "grid" || accessibleRole === "treegrid") {
99
+ throw new Error("For role 'table/grid/treegrid', you must use generate_test_expect_table tool.");
100
+ }
101
+ return handleElementTestGeneration({ serviceType: expect_service_1.ElementServiceType.EXPECT, baseUrl, accessibleName, accessibleRole, domSelector });
102
+ });
103
+ server.registerTool("generate_test_click_element", {
104
+ title: "Generate test that clicks on html element with role and name",
105
+ description:
106
+ // eslint-disable-next-line max-len
107
+ "Generate a complete UUV test scenario (Gherkin format) to click on an element with specified accessible name and role or domSelector. Use this when the user asks to create/write/generate a UUV scenario or test for checking element visibility. DON'T USE IF ACCESSIBLE ROLE IS grid, treegrid, table, or form",
108
+ inputSchema: FindElementInputSchema,
109
+ }, async ({ baseUrl, accessibleName, accessibleRole, domSelector }) => {
110
+ return handleElementTestGeneration({ serviceType: expect_service_1.ElementServiceType.CLICK, baseUrl, accessibleName, accessibleRole, domSelector });
111
+ });
112
+ server.registerTool("generate_test_within_element", {
113
+ title: "Generate test that focus within an html element with role and name",
114
+ description:
115
+ // eslint-disable-next-line max-len
116
+ "Generate a complete UUV test scenario (Gherkin format) that focus within an html element with specified accessible name and role or domSelector. Use this when the user asks to create/write/generate a UUV scenario or test for checking element visibility. DON'T USE IF ACCESSIBLE ROLE IS grid, treegrid, table, or form",
117
+ inputSchema: FindElementInputSchema,
118
+ }, async ({ baseUrl, accessibleName, accessibleRole, domSelector }) => {
119
+ return handleElementTestGeneration({ serviceType: expect_service_1.ElementServiceType.WITHIN, baseUrl, accessibleName, accessibleRole, domSelector });
120
+ });
121
+ server.registerTool("generate_test_type_element", {
122
+ title: "Generate test that types a value into html element with role and name",
123
+ description:
124
+ // eslint-disable-next-line max-len
125
+ "Generate a complete UUV test scenario (Gherkin format) that types a value into an html element with specified accessible name and role or domSelector. Use this when the user asks to create/write/generate a UUV scenario or test for checking element visibility. DON'T USE IF ACCESSIBLE ROLE IS grid, treegrid, table, or form",
126
+ inputSchema: FindElementInputSchema,
127
+ }, async ({ baseUrl, accessibleName, accessibleRole, domSelector }) => {
128
+ return handleElementTestGeneration({ serviceType: expect_service_1.ElementServiceType.TYPE, baseUrl, accessibleName, accessibleRole, domSelector });
129
+ });
130
+ server.registerTool("generate_test_expect_table", {
131
+ title: "Generate test for html table or grid or treeGrid",
132
+ description:
133
+ // eslint-disable-next-line max-len
134
+ "Generate a complete UUV test scenario (Gherkin format) to verify the presence and the content of html table, grid or treegrid given innerHtml. ONLY USE IF ACCESSIBLE ROLE IS grid, treegrid, table, or form",
135
+ inputSchema: {
136
+ baseUrl: zod_1.z.string().describe("The base URL of the page where the table/grid/treegrid is located."),
137
+ innerHtmlFilePath: zod_1.z.string().describe("File path containing the raw innerHTML content of the table, grid, or treegrid element"),
138
+ },
139
+ }, async ({ baseUrl, innerHtmlFilePath }) => {
140
+ return {
141
+ content: [
142
+ {
143
+ type: "text",
144
+ text: await expect_service_1.ExpectTableService.generateExpectForTable(baseUrl, innerHtmlFilePath),
145
+ },
146
+ ],
147
+ };
148
+ });
149
+ return server;
150
+ }
@@ -1,102 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
4
3
  const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
5
- const zod_1 = require("zod");
6
- const sentence_service_1 = require("./services/sentence.service");
7
- const prompt_retriever_service_1 = require("./services/prompt-retriever.service");
8
- const expect_service_1 = require("./services/expect.service");
9
- const dictionary_1 = require("@uuv/dictionary");
10
- // Create an MCP server
11
- const server = new mcp_js_1.McpServer({
12
- name: "uuv-mcp-server",
13
- version: "0.0.1-beta",
14
- });
15
- server.registerTool("retrieve_prompt", {
16
- title: "Retrieve uuv prompt",
17
- description: "Retrieve a uuv prompt template for a coding agent based on a prompt name and arguments.",
18
- inputSchema: {
19
- promptName: zod_1.z.enum(["generate_table", "generate_role_and_name"]),
20
- baseUrl: zod_1.z.string().describe("The base URL of the page"),
21
- // generate_role_and_name Fields
22
- accessibleName: zod_1.z.string().optional().describe("Accessible name (required for generate_role_and_name)"),
23
- accessibleRole: zod_1.z.string().optional().describe("Accessible role (required for generate_role_and_name)")
24
- },
25
- }, async ({ ...args }) => {
26
- return {
27
- content: [
28
- {
29
- type: "text",
30
- text: prompt_retriever_service_1.PromptRetrieverService.retrievePrompt(args),
31
- },
32
- ],
33
- };
34
- });
35
- server.registerTool("available_sentences", {
36
- title: "List Available UUV Sentences",
37
- description:
38
- // eslint-disable-next-line max-len
39
- "List all available UUV test sentences/phrases in Gherkin format. Use this when the user asks about UUV syntax, available commands, what sentences/phrases are available for testing, or needs help with UUV sentence structure. Can be filtered by category (given/when/then) or ARIA role (button, textbox, etc.) to show specific test actions.",
40
- inputSchema: {
41
- category: zod_1.z
42
- .enum(["general", "keyboard", "click", "contains", "type", "checkable"])
43
- .optional()
44
- .describe("Filters sentences based on the action type"),
45
- role: zod_1.z.string().optional().describe("Filters sentences related to an accessible role"),
46
- },
47
- }, async ({ category, role }) => {
48
- const sentenceService = new sentence_service_1.SentenceService((0, dictionary_1.getDefinedDictionary)("en"));
49
- const allSentences = sentenceService.searchSentences({ category, role });
50
- return {
51
- content: [
52
- {
53
- type: "text",
54
- text: JSON.stringify(allSentences, null, 2),
55
- },
56
- ],
57
- };
58
- });
59
- server.registerTool("generate_role_and_name", {
60
- title: "Generate with role and name",
61
- description:
62
- // eslint-disable-next-line max-len
63
- "Generate a complete UUV test scenario (Gherkin format) to verify the presence of an element with specified accessible name and role. Use this when the user asks to create/write/generate a UUV scenario or test for checking element visibility. DON'T USE IF ACCESSIBLE ROLE IS grid, treegrid, table, or form",
64
- inputSchema: {
65
- baseUrl: zod_1.z.string().describe("The base URL of the page where the element is located."),
66
- accessibleName: zod_1.z.string().describe("Accessible name of the element"),
67
- accessibleRole: zod_1.z.string().describe("Accessible role of the element"),
68
- },
69
- }, async ({ baseUrl, accessibleName, accessibleRole }) => {
70
- if (accessibleRole === "table" || accessibleRole === "grid" || accessibleRole === "treegrid") {
71
- throw new Error("For role 'table/grid/treegrid', you must use generateExpectForTable.");
72
- }
73
- return {
74
- content: [
75
- {
76
- type: "text",
77
- text: expect_service_1.ExpectService.generateForAccessibleNameAndRole(baseUrl, accessibleName, accessibleRole),
78
- },
79
- ],
80
- };
81
- });
82
- server.registerTool("generate_table", {
83
- title: "Generate test for html table or grid or treeGrid",
84
- description:
85
- // eslint-disable-next-line max-len
86
- "Generate a complete UUV test scenario (Gherkin format) to verify the presence and the content of html table, grid or treegrid given innerHtml. ONLY USE IF ACCESSIBLE ROLE IS grid, treegrid, table, or form",
87
- inputSchema: {
88
- baseUrl: zod_1.z.string().describe("The base URL of the page where the table/grid/treegrid is located."),
89
- innerHtmlFilePath: zod_1.z.string().describe("File path containing the raw innerHTML content of the table, grid, or treegrid element"),
90
- },
91
- }, async ({ baseUrl, innerHtmlFilePath }) => {
92
- return {
93
- content: [
94
- {
95
- type: "text",
96
- text: await expect_service_1.ExpectService.generateForTable(baseUrl, innerHtmlFilePath),
97
- },
98
- ],
99
- };
100
- });
4
+ const mcp_server_factory_1 = require("./mcp-server-factory");
5
+ const server = (0, mcp_server_factory_1.createUUVServer)();
101
6
  const transport = new stdio_js_1.StdioServerTransport();
102
7
  server.connect(transport);
@@ -0,0 +1,6 @@
1
+ import { FindElementByDomSelector, FindElementByRoleAndName } from "../expect.service";
2
+ export declare abstract class AbstractElementService {
3
+ generateTestForElement(input: FindElementByRoleAndName | FindElementByDomSelector): string;
4
+ protected abstract generateTestForAccessibleNameAndRole(input: FindElementByRoleAndName): string;
5
+ protected abstract generateTestForDomSelector(input: FindElementByDomSelector): string;
6
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AbstractElementService = void 0;
4
+ class AbstractElementService {
5
+ generateTestForElement(input) {
6
+ if (input.accessibleName && input.accessibleRole) {
7
+ return this.generateTestForAccessibleNameAndRole(input);
8
+ }
9
+ else if (input.domSelector) {
10
+ return this.generateTestForDomSelector(input);
11
+ }
12
+ return "";
13
+ }
14
+ }
15
+ exports.AbstractElementService = AbstractElementService;
@@ -0,0 +1,6 @@
1
+ import { AbstractElementService } from "./abstract-element.service";
2
+ import { FindElementByDomSelector, FindElementByRoleAndName } from "../expect.service";
3
+ export declare class ClickElementService extends AbstractElementService {
4
+ generateTestForAccessibleNameAndRole(input: FindElementByRoleAndName): string;
5
+ generateTestForDomSelector(input: FindElementByDomSelector): string;
6
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ClickElementService = void 0;
4
+ const abstract_element_service_1 = require("./abstract-element.service");
5
+ const assistant_1 = require("@uuv/assistant");
6
+ class ClickElementService extends abstract_element_service_1.AbstractElementService {
7
+ generateTestForAccessibleNameAndRole(input) {
8
+ const translator = new assistant_1.ClickTranslator();
9
+ const result = translator.getSentenceFromAccessibleRoleAndName(input.accessibleRole, input.accessibleName);
10
+ return (0, assistant_1.buildResultingScript)("Your amazing feature name", "Action - An action", result.sentences, input.baseUrl);
11
+ }
12
+ generateTestForDomSelector(input) {
13
+ const translator = new assistant_1.ClickTranslator();
14
+ const result = translator.getSentenceFromDomSelector(input.domSelector);
15
+ return (0, assistant_1.buildResultingScript)("Your amazing feature name", "Action - An action", result.sentences, input.baseUrl);
16
+ }
17
+ }
18
+ exports.ClickElementService = ClickElementService;
@@ -0,0 +1,6 @@
1
+ import { AbstractElementService } from "./abstract-element.service";
2
+ import { FindElementByDomSelector, FindElementByRoleAndName } from "../expect.service";
3
+ export declare class ExpectElementService extends AbstractElementService {
4
+ generateTestForAccessibleNameAndRole(input: FindElementByRoleAndName): string;
5
+ generateTestForDomSelector(input: FindElementByDomSelector): string;
6
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExpectElementService = void 0;
4
+ const abstract_element_service_1 = require("./abstract-element.service");
5
+ const assistant_1 = require("@uuv/assistant");
6
+ class ExpectElementService extends abstract_element_service_1.AbstractElementService {
7
+ generateTestForAccessibleNameAndRole(input) {
8
+ const translator = new assistant_1.ExpectTranslator();
9
+ const result = translator.getSentenceFromAccessibleRoleAndName(input.accessibleRole, input.accessibleName);
10
+ return (0, assistant_1.buildResultingScript)("Your amazing feature name", "Action - An action", result.sentences, input.baseUrl);
11
+ }
12
+ generateTestForDomSelector(input) {
13
+ const translator = new assistant_1.ExpectTranslator();
14
+ const result = translator.getSentenceFromDomSelector(input.domSelector);
15
+ return (0, assistant_1.buildResultingScript)("Your amazing feature name", "Action - An action", result.sentences, input.baseUrl);
16
+ }
17
+ }
18
+ exports.ExpectElementService = ExpectElementService;
@@ -0,0 +1,6 @@
1
+ import { AbstractElementService } from "./abstract-element.service";
2
+ import { FindElementByDomSelector, FindElementByRoleAndName } from "../expect.service";
3
+ export declare class TypeElementService extends AbstractElementService {
4
+ generateTestForAccessibleNameAndRole(input: FindElementByRoleAndName): string;
5
+ generateTestForDomSelector(input: FindElementByDomSelector): string;
6
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TypeElementService = void 0;
4
+ const abstract_element_service_1 = require("./abstract-element.service");
5
+ const assistant_1 = require("@uuv/assistant");
6
+ class TypeElementService extends abstract_element_service_1.AbstractElementService {
7
+ generateTestForAccessibleNameAndRole(input) {
8
+ const translator = new assistant_1.TypeTranslator();
9
+ translator.useValueAsMockData = false;
10
+ const result = translator.getSentenceFromAccessibleRoleAndName(input.accessibleRole, input.accessibleName);
11
+ return (0, assistant_1.buildResultingScript)("Your amazing feature name", "Action - An action", result.sentences, input.baseUrl);
12
+ }
13
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
14
+ generateTestForDomSelector(input) {
15
+ throw Error("Not implemented yet");
16
+ }
17
+ }
18
+ exports.TypeElementService = TypeElementService;
@@ -0,0 +1,6 @@
1
+ import { AbstractElementService } from "./abstract-element.service";
2
+ import { FindElementByDomSelector, FindElementByRoleAndName } from "../expect.service";
3
+ export declare class WithinElementService extends AbstractElementService {
4
+ generateTestForAccessibleNameAndRole(input: FindElementByRoleAndName): string;
5
+ generateTestForDomSelector(input: FindElementByDomSelector): string;
6
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WithinElementService = void 0;
4
+ const abstract_element_service_1 = require("./abstract-element.service");
5
+ const assistant_1 = require("@uuv/assistant");
6
+ class WithinElementService extends abstract_element_service_1.AbstractElementService {
7
+ generateTestForAccessibleNameAndRole(input) {
8
+ const translator = new assistant_1.WithinTranslator();
9
+ const result = translator.getSentenceFromAccessibleRoleAndName(input.accessibleRole, input.accessibleName);
10
+ return (0, assistant_1.buildResultingScript)("Your amazing feature name", "Action - An action", result.sentences, input.baseUrl);
11
+ }
12
+ generateTestForDomSelector(input) {
13
+ const translator = new assistant_1.WithinTranslator();
14
+ const result = translator.getSentenceFromDomSelector(input.domSelector);
15
+ return (0, assistant_1.buildResultingScript)("Your amazing feature name", "Action - An action", result.sentences, input.baseUrl);
16
+ }
17
+ }
18
+ exports.WithinElementService = WithinElementService;
@@ -1,4 +1,21 @@
1
- export declare class ExpectService {
2
- static generateForAccessibleNameAndRole(baseUrl: string, accessibleName: string, accessibleRole: string): string;
3
- static generateForTable(baseUrl: string, innerHtmlFilePath: string): Promise<string>;
1
+ import { AbstractElementService } from "./element/abstract-element.service";
2
+ export type FindElementByRoleAndName = {
3
+ baseUrl: string;
4
+ accessibleName: string;
5
+ accessibleRole: string;
6
+ };
7
+ export type FindElementByDomSelector = {
8
+ baseUrl: string;
9
+ domSelector: string;
10
+ };
11
+ export type FindElement = FindElementByRoleAndName & FindElementByDomSelector;
12
+ export declare enum ElementServiceType {
13
+ EXPECT = 0,
14
+ CLICK = 1,
15
+ TYPE = 2,
16
+ WITHIN = 3
17
+ }
18
+ export declare function getElementService(serviceType: ElementServiceType): AbstractElementService;
19
+ export declare class ExpectTableService {
20
+ static generateExpectForTable(baseUrl: string, innerHtmlFilePath: string): Promise<string>;
4
21
  }
@@ -1,17 +1,37 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ExpectService = void 0;
3
+ exports.ExpectTableService = exports.ElementServiceType = void 0;
4
+ exports.getElementService = getElementService;
4
5
  const tslib_1 = require("tslib");
5
6
  const assistant_1 = require("@uuv/assistant");
6
7
  const jsdom_1 = require("jsdom");
7
8
  const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
8
- class ExpectService {
9
- static generateForAccessibleNameAndRole(baseUrl, accessibleName, accessibleRole) {
10
- const translator = new assistant_1.ExpectTranslator();
11
- const result = translator.getSentenceFromAccessibleRoleAndName(accessibleRole, accessibleName);
12
- return (0, assistant_1.buildResultingScript)("Your amazing feature name", "Action - An action", result.sentences, baseUrl);
9
+ const click_element_service_1 = require("./element/click-element.service");
10
+ const type_element_service_1 = require("./element/type-element.service");
11
+ const within_element_service_1 = require("./element/within-element.service");
12
+ const expect_element_service_1 = require("./element/expect-element.service");
13
+ var ElementServiceType;
14
+ (function (ElementServiceType) {
15
+ ElementServiceType[ElementServiceType["EXPECT"] = 0] = "EXPECT";
16
+ ElementServiceType[ElementServiceType["CLICK"] = 1] = "CLICK";
17
+ ElementServiceType[ElementServiceType["TYPE"] = 2] = "TYPE";
18
+ ElementServiceType[ElementServiceType["WITHIN"] = 3] = "WITHIN";
19
+ })(ElementServiceType || (exports.ElementServiceType = ElementServiceType = {}));
20
+ function getElementService(serviceType) {
21
+ switch (serviceType) {
22
+ case ElementServiceType.CLICK:
23
+ return new click_element_service_1.ClickElementService();
24
+ case ElementServiceType.TYPE:
25
+ return new type_element_service_1.TypeElementService();
26
+ case ElementServiceType.WITHIN:
27
+ return new within_element_service_1.WithinElementService();
28
+ case ElementServiceType.EXPECT:
29
+ default:
30
+ return new expect_element_service_1.ExpectElementService();
13
31
  }
14
- static async generateForTable(baseUrl, innerHtmlFilePath) {
32
+ }
33
+ class ExpectTableService {
34
+ static async generateExpectForTable(baseUrl, innerHtmlFilePath) {
15
35
  const tableAndGridService = new assistant_1.TableAndGridService();
16
36
  const dom = new jsdom_1.JSDOM(node_fs_1.default.readFileSync(innerHtmlFilePath, "utf8"));
17
37
  const element = dom.window.document.body.firstElementChild;
@@ -19,4 +39,4 @@ class ExpectService {
19
39
  return (0, assistant_1.buildResultingScript)("Your amazing feature name", "Action - Expect Array", result, baseUrl);
20
40
  }
21
41
  }
22
- exports.ExpectService = ExpectService;
42
+ exports.ExpectTableService = ExpectTableService;
@@ -1,10 +1,16 @@
1
1
  type PromptExtraArgs = Record<string, any>;
2
2
  export type PromptArgs = {
3
- promptName: string;
3
+ promptName: UUV_PROMPT;
4
4
  } | PromptExtraArgs;
5
+ export declare enum UUV_PROMPT {
6
+ GENERATE_TEST_EXPECT_TABLE = "generate_test_expect_table",
7
+ GENERATE_TEST_EXPECT_ELEMENT = "generate_test_expect_element",
8
+ GENERATE_TEST_CLICK_ELEMENT = "generate_test_click_element",
9
+ GENERATE_TEST_WITHIN_ELEMENT = "generate_test_within_element",
10
+ GENERATE_TEST_TYPE_ELEMENT = "generate_test_type_element"
11
+ }
5
12
  export declare class PromptRetrieverService {
6
13
  private static loadPromptTemplate;
7
- private static renderPrompt;
8
14
  private static generatePrompt;
9
15
  private static validatePromptGenerationRequest;
10
16
  static retrievePrompt(args: PromptArgs): string;
@@ -1,57 +1,69 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PromptRetrieverService = void 0;
3
+ exports.PromptRetrieverService = exports.UUV_PROMPT = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const path = tslib_1.__importStar(require("node:path"));
6
6
  const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
7
7
  const zod_1 = require("zod");
8
+ const mustache_1 = require("mustache");
9
+ var UUV_PROMPT;
10
+ (function (UUV_PROMPT) {
11
+ UUV_PROMPT["GENERATE_TEST_EXPECT_TABLE"] = "generate_test_expect_table";
12
+ UUV_PROMPT["GENERATE_TEST_EXPECT_ELEMENT"] = "generate_test_expect_element";
13
+ UUV_PROMPT["GENERATE_TEST_CLICK_ELEMENT"] = "generate_test_click_element";
14
+ UUV_PROMPT["GENERATE_TEST_WITHIN_ELEMENT"] = "generate_test_within_element";
15
+ UUV_PROMPT["GENERATE_TEST_TYPE_ELEMENT"] = "generate_test_type_element";
16
+ })(UUV_PROMPT || (exports.UUV_PROMPT = UUV_PROMPT = {}));
8
17
  class PromptRetrieverService {
9
18
  static loadPromptTemplate(promptName) {
10
19
  const templatePath = path.join(__dirname, "..", "prompts", `${promptName}.mustache`);
11
20
  return node_fs_1.default.readFileSync(templatePath, "utf8");
12
21
  }
13
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
- static renderPrompt(template, variables) {
15
- let result = template;
16
- for (const [key, value] of Object.entries(variables)) {
17
- if (Array.isArray(value)) {
18
- // Handle array values for Mustache-style list rendering
19
- const listItems = value.map(item => `{{#${key}}}${item}{{/${key}}}`).join("\n");
20
- result = result.replaceAll(`{{#${key}}}`, listItems);
21
- }
22
- else {
23
- result = result.replaceAll(`{{${key}}}`, value);
24
- }
25
- }
26
- return result;
27
- }
28
22
  static generatePrompt(args) {
29
23
  const template = this.loadPromptTemplate(args.promptName);
30
- return this.renderPrompt(template, args);
24
+ return (0, mustache_1.render)(template, args);
31
25
  }
32
26
  static validatePromptGenerationRequest(args) {
33
27
  const promptSchemas = zod_1.z.discriminatedUnion("promptName", [
34
28
  zod_1.z.object({
35
- promptName: zod_1.z.literal("generate_table"),
29
+ promptName: zod_1.z.literal(UUV_PROMPT.GENERATE_TEST_EXPECT_TABLE),
36
30
  baseUrl: zod_1.z.string().describe("The base URL of the page where the table/grid/treegrid is located."),
37
31
  }),
38
32
  zod_1.z.object({
39
- promptName: zod_1.z.literal("generate_role_and_name"),
33
+ promptName: zod_1.z.enum([
34
+ UUV_PROMPT.GENERATE_TEST_EXPECT_ELEMENT,
35
+ UUV_PROMPT.GENERATE_TEST_CLICK_ELEMENT,
36
+ UUV_PROMPT.GENERATE_TEST_WITHIN_ELEMENT,
37
+ UUV_PROMPT.GENERATE_TEST_TYPE_ELEMENT
38
+ ]),
40
39
  baseUrl: zod_1.z.string().describe("The base URL of the page where the element is located."),
41
- accessibleName: zod_1.z.string().describe("Accessible name of the element"),
42
- accessibleRole: zod_1.z.string().describe("Accessible role of the element"),
40
+ accessibleName: zod_1.z.string().optional().describe("Accessible name of the element"),
41
+ accessibleRole: zod_1.z.string().optional().describe("Accessible role of the element"),
42
+ domSelector: zod_1.z.string().optional().describe("Dom selector of the element"),
43
43
  }),
44
- ]);
44
+ ]).superRefine((data, ctx) => {
45
+ if (data.promptName === UUV_PROMPT.GENERATE_TEST_EXPECT_ELEMENT || data.promptName === UUV_PROMPT.GENERATE_TEST_CLICK_ELEMENT) {
46
+ const hasAccessibleSelector = data.accessibleRole && data.accessibleName;
47
+ const hasDomSelector = data.domSelector;
48
+ if (!hasAccessibleSelector && !hasDomSelector) {
49
+ ctx.addIssue({
50
+ code: zod_1.z.ZodIssueCode.custom,
51
+ message: "You must provide either (accessibleRole AND accessibleName) or domSelector",
52
+ });
53
+ }
54
+ }
55
+ });
45
56
  return promptSchemas.parse(args);
46
57
  }
47
58
  static retrievePrompt(args) {
48
59
  const validatedPrompt = PromptRetrieverService.validatePromptGenerationRequest(args);
49
60
  let prompt;
50
61
  switch (validatedPrompt.promptName) {
51
- case "generate_table":
52
- prompt = PromptRetrieverService.generatePrompt(args);
53
- break;
54
- case "generate_role_and_name":
62
+ case UUV_PROMPT.GENERATE_TEST_EXPECT_TABLE:
63
+ case UUV_PROMPT.GENERATE_TEST_EXPECT_ELEMENT:
64
+ case UUV_PROMPT.GENERATE_TEST_CLICK_ELEMENT:
65
+ case UUV_PROMPT.GENERATE_TEST_TYPE_ELEMENT:
66
+ case UUV_PROMPT.GENERATE_TEST_WITHIN_ELEMENT:
55
67
  prompt = PromptRetrieverService.generatePrompt(args);
56
68
  break;
57
69
  default:
@@ -1,4 +1,4 @@
1
- import { Dictionary } from "@uuv/dictionary";
1
+ import { BaseSentence, Dictionary } from "@uuv/dictionary";
2
2
  export type SentenceSearchQuery = {
3
3
  category?: string;
4
4
  role?: string;
@@ -8,5 +8,5 @@ export declare class SentenceService {
8
8
  constructor(dictionary: Dictionary);
9
9
  private getBaseSentences;
10
10
  private getSentencesByRole;
11
- searchSentences(query: SentenceSearchQuery): import("@uuv/dictionary").BaseSentence[];
11
+ searchSentences(query: SentenceSearchQuery): BaseSentence[];
12
12
  }
@@ -13,7 +13,10 @@ class SentenceService {
13
13
  return this.dictionary.getRoleBasedSentences().filter(r => !role || r.role === role);
14
14
  }
15
15
  searchSentences(query) {
16
- let sentences = [...this.getBaseSentences()];
16
+ let sentences = [];
17
+ if (!query.role && !query.category) {
18
+ sentences = [...this.getBaseSentences()];
19
+ }
17
20
  sentences.push(...this.getSentencesByRole(query.role));
18
21
  if (query.category) {
19
22
  sentences = sentences.filter(s => s.section === query.category);
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uuv/mcp-server",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "A Model Context Protocol (MCP) server for UUV - a solution to facilitate the writing and execution of E2E tests understandable by any human being(English or French) using cucumber(BDD) and cypress or playwright.",
5
5
  "author": "Louis Fredice NJAKO MOLOM (https://github.com/luifr10) & Stanley SERVICAL (https://github.com/stanlee974)",
6
6
  "license": "MIT",
@@ -40,6 +40,7 @@
40
40
  ],
41
41
  "scripts": {
42
42
  "start": "ts-node src/lib/mcp-server.ts",
43
+ "inspector": "npx @modelcontextprotocol/inspector --config test-mcp.json --server default-server",
43
44
  "lint": "npx eslint . --ext .js,.ts,.feature --fix",
44
45
  "tests": "jest --coverage --config=./jest.config.ts",
45
46
  "package": "npm pack --pack-destination=\"../../dist/packages\""
@@ -56,15 +57,21 @@
56
57
  },
57
58
  "dependencies": {
58
59
  "@modelcontextprotocol/sdk": "1.17.5",
60
+ "@types/mustache": "^4.2.6",
61
+ "@uuv/assistant": "2.73.2",
62
+ "@uuv/dictionary": "0.1.1",
59
63
  "jsdom": "26.1.0",
64
+ "mustache": "^4.2.0",
60
65
  "tsconfig-paths": "4.2.0",
61
66
  "tslib": "2.3.0",
62
- "@uuv/dictionary": "0.1.1",
63
- "@uuv/assistant": "2.73.2",
64
67
  "zod": "3.25.76"
65
68
  },
66
69
  "funding": {
67
70
  "type": "opencollective",
68
71
  "url": "https://opencollective.com/uuv"
72
+ },
73
+ "devDependencies": {
74
+ "@modelcontextprotocol/inspector": "^0.17.2",
75
+ "ts-node": "^10.9.2"
69
76
  }
70
77
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uuv/mcp-server",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "A Model Context Protocol (MCP) server for UUV - a solution to facilitate the writing and execution of E2E tests understandable by any human being(English or French) using cucumber(BDD) and cypress or playwright.",
5
5
  "author": "Louis Fredice NJAKO MOLOM (https://github.com/luifr10) & Stanley SERVICAL (https://github.com/stanlee974)",
6
6
  "license": "MIT",
@@ -40,6 +40,7 @@
40
40
  ],
41
41
  "scripts": {
42
42
  "start": "ts-node src/lib/mcp-server.ts",
43
+ "inspector": "npx @modelcontextprotocol/inspector --config test-mcp.json --server default-server",
43
44
  "lint": "npx eslint . --ext .js,.ts,.feature --fix",
44
45
  "tests": "jest --coverage --config=./jest.config.ts",
45
46
  "package": "npm pack --pack-destination=\"../../dist/packages\""
@@ -56,15 +57,21 @@
56
57
  },
57
58
  "dependencies": {
58
59
  "@modelcontextprotocol/sdk": "1.17.5",
60
+ "@types/mustache": "^4.2.6",
61
+ "@uuv/assistant": "2.74.0",
62
+ "@uuv/dictionary": "0.2.0",
59
63
  "jsdom": "26.1.0",
64
+ "mustache": "^4.2.0",
60
65
  "tsconfig-paths": "4.2.0",
61
66
  "tslib": "2.3.0",
62
- "@uuv/dictionary": "0.1.1",
63
- "@uuv/assistant": "2.73.2",
64
67
  "zod": "3.25.76"
65
68
  },
66
69
  "funding": {
67
70
  "type": "opencollective",
68
71
  "url": "https://opencollective.com/uuv"
72
+ },
73
+ "devDependencies": {
74
+ "@modelcontextprotocol/inspector": "^0.17.2",
75
+ "ts-node": "^10.9.2"
69
76
  }
70
77
  }