wopee-mcp 1.23.1 → 1.24.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.
@@ -6,6 +6,9 @@ import { wopeeDispatchAnalysis } from "./wopee_dispatch_analysis/index.js";
6
6
  import { wopeeCreateBlankSuite } from "./wopee_create_blank_suite/index.js";
7
7
  import { wopeeFetchAnalysisSuites } from "./wopee_fetch_analysis_suites/index.js";
8
8
  import { wopeeFetchExecutedTestCases } from "./wopee_fetch_executed_test_cases/index.js";
9
+ import { wopeeSendChatMessage } from "./wopee_send_chat_message/index.js";
10
+ import { wopeeReadChatHistory } from "./wopee_read_chat_history/index.js";
11
+ import { wopeeCreateGithubIssue } from "./wopee_create_github_issue/index.js";
9
12
  export const TOOLS = [
10
13
  wopeeCreateBlankSuite,
11
14
  wopeeFetchAnalysisSuites,
@@ -15,4 +18,7 @@ export const TOOLS = [
15
18
  wopeeFetchArtifact,
16
19
  wopeeUpdateArtifact,
17
20
  wopeeGenerateArtifact,
21
+ wopeeSendChatMessage,
22
+ wopeeReadChatHistory,
23
+ wopeeCreateGithubIssue,
18
24
  ];
@@ -215,3 +215,46 @@ export const CreateBlankAnalysisSuite = `
215
215
  }
216
216
  }
217
217
  `;
218
+ // Chat tools
219
+ export const SendChatMessage = `
220
+ mutation SendChatMessage($input: SendChatMessageInput!) {
221
+ sendChatMessage(input: $input) {
222
+ uuid
223
+ content
224
+ contentType
225
+ authorType
226
+ createdAt
227
+ }
228
+ }
229
+ `;
230
+ export const FetchChatMessages = `
231
+ query FetchChatMessages($roomUuid: ID!, $limit: Int) {
232
+ fetchChatMessages(roomUuid: $roomUuid, limit: $limit) {
233
+ uuid
234
+ authorType
235
+ authorName
236
+ content
237
+ contentType
238
+ sourcePlatform
239
+ createdAt
240
+ }
241
+ }
242
+ `;
243
+ export const FetchChatRoom = `
244
+ query FetchChatRoom($projectUuid: ID!) {
245
+ fetchChatRoom(projectUuid: $projectUuid) {
246
+ uuid
247
+ contextSummary
248
+ createdAt
249
+ }
250
+ }
251
+ `;
252
+ export const CreateGitHubIssue = `
253
+ mutation CreateGitHubIssue($projectUuid: ID!, $title: String!, $body: String!, $labels: [String!]) {
254
+ createGitHubIssue(projectUuid: $projectUuid, title: $title, body: $body, labels: $labels) {
255
+ url
256
+ number
257
+ title
258
+ }
259
+ }
260
+ `;
@@ -16,10 +16,12 @@ export const SuiteAnalysisConfigSchema = z.object({
16
16
  });
17
17
  export const GenerateAIDataHandlerInputSchema = z.object({
18
18
  type: z.nativeEnum(GenerateArtifactType, {
19
- description: "Chosen type of file(artifact) to generate",
19
+ description: "Type of test artifact to generate. One of: APP_CONTEXT, GENERAL_USER_STORIES, USER_STORIES_WITH_TEST_CASES, TEST_CASES, TEST_CASE_STEPS, REUSABLE_TEST_CASES, REUSABLE_TEST_CASE_STEPS. Start with APP_CONTEXT, then generate stories and test cases from it.",
20
20
  }),
21
21
  suiteUuid: z
22
- .string({ description: "UUID of the suite to generate file(artifact) for" })
22
+ .string({
23
+ description: "UUID of the analysis suite to generate artifacts for. Get this from wopee_create_blank_suite or wopee_fetch_analysis_suites.",
24
+ })
23
25
  .min(1, "Suite UUID is required"),
24
26
  });
25
27
  export const GenerateAIDataInputSchema = z.object({
@@ -34,14 +36,16 @@ export const GenerateAIDataInputSchema = z.object({
34
36
  });
35
37
  export const FetchArtifactHandlerInputSchema = z.object({
36
38
  type: z.nativeEnum(ArtifactType, {
37
- description: "Chosen file(artifact) to fetch",
39
+ description: "Type of test artifact to retrieve. One of: APP_CONTEXT (application description), GENERAL_USER_STORIES (stories without test cases), USER_STORIES (stories with test cases), PLAYWRIGHT_CODE (generated test code — requires identifier), PROJECT_CONTEXT (project-level context).",
38
40
  }),
39
41
  suiteUuid: z
40
- .string({ description: "UUID of the suite to fetch the file from" })
42
+ .string({
43
+ description: "UUID of the analysis suite to fetch artifacts from. Get this from wopee_fetch_analysis_suites.",
44
+ })
41
45
  .min(1, "Suite UUID is required"),
42
46
  identifier: z
43
47
  .string({
44
- description: "Identifier for the test case to fetch playwright code for, ex. `US004:TC006`, should be provided only for `PLAYWRIGHT_CODE` artifact type",
48
+ description: "Test case identifier in format 'US004:TC006'. Required only when type is PLAYWRIGHT_CODE. Ignored for all other artifact types.",
45
49
  })
46
50
  .optional(),
47
51
  });
@@ -67,17 +71,19 @@ export const FetchArtifactInputSchema = z.object({
67
71
  });
68
72
  export const UpdateArtifactHandlerInputSchema = z.object({
69
73
  type: z.nativeEnum(ArtifactType, {
70
- description: "Chosen file(artifact) to update",
74
+ description: "Type of test artifact to update. One of: APP_CONTEXT, GENERAL_USER_STORIES, USER_STORIES, PLAYWRIGHT_CODE (requires identifier), PROJECT_CONTEXT. Must match the type used when the artifact was generated.",
71
75
  }),
72
76
  content: z.string({
73
- description: "Content of the file(artifact) to update",
77
+ description: "The complete new content to replace the existing artifact. This is a destructive overwrite — the entire previous content is replaced. Pass the full updated content, not a partial diff.",
74
78
  }),
75
79
  suiteUuid: z
76
- .string({ description: "UUID of the suite to update the file for" })
80
+ .string({
81
+ description: "UUID of the analysis suite containing the artifact to update. Get this from wopee_fetch_analysis_suites.",
82
+ })
77
83
  .min(1, "Suite UUID is required"),
78
84
  identifier: z
79
85
  .string({
80
- description: "Identifier for the test case to update playwright code for, ex. `US004:TC006`, should be provided only for `PLAYWRIGHT_CODE` artifact type",
86
+ description: "Test case identifier in format 'US004:TC006'. Required only when type is PLAYWRIGHT_CODE. Ignored for all other artifact types.",
81
87
  })
82
88
  .optional(),
83
89
  });
@@ -8,6 +8,9 @@ export var ToolName;
8
8
  ToolName["WOPEE_FETCH_ARTIFACT"] = "wopee_fetch_artifact";
9
9
  ToolName["WOPEE_UPDATE_ARTIFACT"] = "wopee_update_artifact";
10
10
  ToolName["WOPEE_GENERATE_ARTIFACT"] = "wopee_generate_artifact";
11
+ ToolName["WOPEE_SEND_CHAT_MESSAGE"] = "wopee_send_chat_message";
12
+ ToolName["WOPEE_READ_CHAT_HISTORY"] = "wopee_read_chat_history";
13
+ ToolName["WOPEE_CREATE_GITHUB_ISSUE"] = "wopee_create_github_issue";
11
14
  })(ToolName || (ToolName = {}));
12
15
  export var GenerateArtifactType;
13
16
  (function (GenerateArtifactType) {
@@ -7,7 +7,7 @@ export const wopeeCreateBlankSuite = {
7
7
  name: ToolName.WOPEE_CREATE_BLANK_SUITE,
8
8
  config: {
9
9
  title: "Create blank analysis suite",
10
- description: "Create a new empty analysis suite in the current project. Use this as the first step when starting a new testing workflow — the returned suite UUID is required by generate, fetch, update, and dispatch tools. Takes no input parameters; uses the project configured via WOPEE_PROJECT_UUID. Returns the created suite object including its UUID and metadata.",
10
+ description: "Create a new empty analysis suite in the current project. Use this as the first step when you want to manually build a test suite — the returned suite UUID is needed by wopee_generate_artifact, wopee_fetch_artifact, wopee_update_artifact, and wopee_dispatch_agent. If you want to auto-analyze a web app instead, use wopee_dispatch_analysis which creates and populates a suite in one step. Takes no input parameters; uses WOPEE_PROJECT_UUID from environment. Not idempotent: each call creates a new suite. Returns the suite object with UUID, name, type, and status. Fails if WOPEE_PROJECT_UUID is not configured.",
11
11
  },
12
12
  handler: async () => {
13
13
  try {
@@ -0,0 +1,61 @@
1
+ import { z } from "zod";
2
+ import { getConfig } from "../../utils/getConfig.js";
3
+ import { requestClient } from "../../utils/requestClient.js";
4
+ import { _parseError } from "../shared/helpers.js";
5
+ import { ToolName } from "../shared/types.js";
6
+ import { CreateGitHubIssue } from "../shared/gql-queries.js";
7
+ const InputSchema = z.object({
8
+ title: z.string().describe("The title of the GitHub issue"),
9
+ body: z
10
+ .string()
11
+ .describe("The body/description of the GitHub issue (supports Markdown)"),
12
+ labels: z
13
+ .array(z.string())
14
+ .optional()
15
+ .describe("Optional labels to apply to the issue (e.g., ['bug', 'testing'])"),
16
+ });
17
+ export const wopeeCreateGithubIssue = {
18
+ name: ToolName.WOPEE_CREATE_GITHUB_ISSUE,
19
+ config: {
20
+ title: "Create GitHub issue",
21
+ description: "Create a new GitHub issue in the project's connected repository. Use this to report bugs found during testing, track test failures, or create action items from chat discussions. The issue will be created in the GitHub repository linked to the current project. Requires the project to have GitHub integration configured and WOPEE_PROJECT_UUID to be set.",
22
+ inputSchema: InputSchema.shape,
23
+ },
24
+ handler: async (input) => {
25
+ try {
26
+ const { WOPEE_PROJECT_UUID } = getConfig();
27
+ if (!WOPEE_PROJECT_UUID)
28
+ return {
29
+ content: [
30
+ { type: "text", text: "WOPEE_PROJECT_UUID is not set" },
31
+ ],
32
+ };
33
+ const result = await requestClient(CreateGitHubIssue, {
34
+ projectUuid: WOPEE_PROJECT_UUID,
35
+ title: input.title,
36
+ body: input.body,
37
+ labels: input.labels || [],
38
+ });
39
+ if (!result?.createGitHubIssue)
40
+ return {
41
+ content: [
42
+ {
43
+ type: "text",
44
+ text: "Failed to create GitHub issue. Make sure the project has GitHub integration configured.",
45
+ },
46
+ ],
47
+ };
48
+ return {
49
+ content: [
50
+ {
51
+ type: "text",
52
+ text: `GitHub issue created successfully:\n- Title: ${result.createGitHubIssue.title}\n- Number: #${result.createGitHubIssue.number}\n- URL: ${result.createGitHubIssue.url}`,
53
+ },
54
+ ],
55
+ };
56
+ }
57
+ catch (error) {
58
+ return _parseError(error);
59
+ }
60
+ },
61
+ };
@@ -9,7 +9,7 @@ export const wopeeDispatchAgent = {
9
9
  name: ToolName.WOPEE_DISPATCH_AGENT,
10
10
  config: {
11
11
  title: "Dispatch autonomous testing agent",
12
- description: "Run an autonomous AI testing agent on specific test cases within a suite. The agent navigates the web app, executes test steps, captures screenshots, and reports pass/fail results. Requires a suite UUID and test case ID (e.g. TC001) with its parent user story ID (e.g. US001). Use wopee_generate_artifact first to create test cases, then this tool to execute them. Rate limit: 10 seconds between dispatches per project; concurrent calls auto-retry with backoff. Returns executed test case results including status and agent report.",
12
+ description: "Execute a specific test case by dispatching an autonomous AI agent. The agent opens a real browser, navigates the web app, follows the test case steps, captures screenshots at each step, and reports pass/fail with detailed findings. Prerequisite: test cases must exist in the suite generate them first with wopee_generate_artifact (type USER_STORIES_WITH_TEST_CASES). Do NOT use this to analyze or crawl an app use wopee_dispatch_analysis for that. Side effects: creates execution records and screenshots on the Wopee.io platform. Rate limit: 10 seconds between dispatches per project; concurrent calls auto-retry with exponential backoff. On success, returns executed test case results. On failure (invalid suite/test case ID), returns an error message. Use wopee_fetch_executed_test_cases afterward to get full results.",
13
13
  inputSchema: WopeeDispatchAgentInputSchema.shape,
14
14
  },
15
15
  handler: async (input) => {
@@ -9,7 +9,7 @@ export const wopeeDispatchAnalysis = {
9
9
  name: ToolName.WOPEE_DISPATCH_ANALYSIS,
10
10
  config: {
11
11
  title: "Dispatch analysis crawl",
12
- description: "Create a new analysis suite and dispatch an AI crawling agent to explore and analyze a web application. The agent autonomously navigates the app starting from a given URL, discovers pages, and builds a sitemap. Optionally accepts login credentials, cookie preferences, custom variables, and additional instructions to guide the crawl. Use this instead of wopee_create_blank_suite when you want to auto-analyze a web app in one step. Rate limit: 10 seconds between dispatches per project; concurrent calls auto-retry with backoff. Returns the created analysis suite.",
12
+ description: "Create a new analysis suite AND dispatch an AI crawling agent in one step. The agent opens a real browser, navigates from the starting URL, discovers pages, and maps the application structure. Use this when you want to auto-analyze a web app — it combines suite creation and crawling. Use wopee_create_blank_suite instead if you want to manually populate the suite. Optionally accepts starting URL, login credentials, cookie preferences (ACCEPT_ALL, DECLINE_ALL, IGNORE), custom variables, and free-text instructions to guide the crawl. Not idempotent: each call creates a new suite and starts a new crawl. Side effects: creates a suite and execution records on the platform. Rate limit: 10 seconds between dispatches per project; concurrent calls auto-retry with exponential backoff. Returns the created suite object on success.",
13
13
  inputSchema: WopeeDispatchAnalysisInputSchema.shape,
14
14
  },
15
15
  handler: async (input) => {
@@ -7,7 +7,7 @@ export const wopeeFetchAnalysisSuites = {
7
7
  name: ToolName.WOPEE_FETCH_ANALYSIS_SUITES,
8
8
  config: {
9
9
  title: "List analysis suites",
10
- description: "List all analysis suites in the current project. Returns an array of suites with their UUIDs, names, types, and statuses. Use this to find existing suites before generating content or dispatching agents. Takes no input parameters; uses the project configured via WOPEE_PROJECT_UUID. Each suite UUID can be passed to other tools like wopee_generate_artifact, wopee_fetch_artifact, or wopee_dispatch_agent.",
10
+ description: "List all analysis suites in the current project. Returns an array of suite objects with UUIDs, names, types (ANALYSIS, AGENT, etc.), and running statuses (IDLE, IN_PROGRESS, FINISHED). Use this to discover existing suites before calling other tools — you need a suite UUID for wopee_generate_artifact, wopee_fetch_artifact, wopee_update_artifact, and wopee_dispatch_agent. Read-only: does not create or modify anything. Takes no input; uses WOPEE_PROJECT_UUID from environment. Returns an empty array if no suites exist. Fails if WOPEE_PROJECT_UUID is not configured.",
11
11
  },
12
12
  handler: async () => {
13
13
  try {
@@ -5,7 +5,7 @@ export const wopeeFetchArtifact = {
5
5
  name: ToolName.WOPEE_FETCH_ARTIFACT,
6
6
  config: {
7
7
  title: "Fetch test artifacts",
8
- description: "Retrieve test artifacts from a suite. Supported types: APP_CONTEXT (application description), GENERAL_USER_STORIES (user stories without test cases), USER_STORIES (user stories with test cases), PLAYWRIGHT_CODE (Playwright test code for a specific test case — requires identifier like 'US004:TC006'), PROJECT_CONTEXT (project-level context). Use after wopee_generate_artifact to review test artifacts, or to retrieve existing artifacts for editing with wopee_update_artifact.",
8
+ description: "Retrieve a specific test artifact from a suite. Returns the artifact content as text. Use this to review what wopee_generate_artifact created, or to retrieve existing artifacts before editing with wopee_update_artifact. Does NOT modify any data this is a read-only operation. If the requested artifact type has not been generated yet for this suite, returns an empty result. For PLAYWRIGHT_CODE, you must provide the test case identifier (e.g. 'US004:TC006'); omitting it returns an error. For all other types, the identifier parameter is ignored.",
9
9
  inputSchema: FetchArtifactHandlerInputSchema.shape,
10
10
  },
11
11
  handler: async (input) => await fetchArtifact(input),
@@ -8,7 +8,7 @@ export const wopeeFetchExecutedTestCases = {
8
8
  name: ToolName.WOPEE_FETCH_EXECUTED_TEST_CASES,
9
9
  config: {
10
10
  title: "Fetch test execution results",
11
- description: "Retrieve the results of test cases that have been executed by the autonomous agent. Returns each test case with its execution status (IN_PROGRESS, FINISHED, FAILED), agent report, and code report. Use this after wopee_dispatch_agent to check whether tests passed or failed and to review detailed findings. Requires the suite UUID; optionally accepts an analysis identifier (e.g. A068) to filter results.",
11
+ description: "Retrieve results of test cases executed by the autonomous agent. Returns each test case with its execution status (IN_PROGRESS, FINISHED, FAILED), agent report (natural language findings), and code report (technical details). Read-only: does not trigger any execution. Use this after wopee_dispatch_agent to check results if status is IN_PROGRESS, wait and call again. Requires suite UUID. Optionally accepts an analysis identifier (e.g. A068, found in suite data) to filter to a specific analysis run. Returns an empty array if no test cases have been executed in this suite. Do NOT use this to fetch test artifacts like user stories or code — use wopee_fetch_artifact for that.",
12
12
  inputSchema: WopeeFetchExecutedTestCasesInputSchema.shape,
13
13
  },
14
14
  handler: async (input) => {
@@ -5,7 +5,7 @@ export const wopeeGenerateArtifact = {
5
5
  name: ToolName.WOPEE_GENERATE_ARTIFACT,
6
6
  config: {
7
7
  title: "Generate test artifacts",
8
- description: "Generate AI-powered test artifacts for a suite. Supported types: APP_CONTEXT (analyze the application and create a description), GENERAL_USER_STORIES (generate user stories from app context), USER_STORIES_WITH_TEST_CASES (generate user stories with detailed test cases), TEST_CASES (generate test cases for existing user stories), TEST_CASE_STEPS (generate step-by-step instructions for test cases), REUSABLE_TEST_CASES (generate reusable/shared test cases), REUSABLE_TEST_CASE_STEPS (generate steps for reusable test cases). Typical workflow: generate APP_CONTEXT first, then USER_STORIES_WITH_TEST_CASES, then use wopee_dispatch_agent to execute them.",
8
+ description: "Generate AI-powered test artifacts for a suite using the Wopee.io AI engine. Each call creates one artifact type call multiple times for different types. Generation order matters: APP_CONTEXT must be generated before user stories, and user stories before test cases. If called out of order, the AI may produce lower quality results. On success, returns confirmation that generation started. Use wopee_fetch_artifact to retrieve the generated content once ready. Do NOT use this to update existing artifacts use wopee_update_artifact instead. Generating the same type again overwrites the previous version.",
9
9
  inputSchema: GenerateAIDataHandlerInputSchema.shape,
10
10
  },
11
11
  handler: async (input) => await generateAIDataFile(input),
@@ -0,0 +1,80 @@
1
+ import { z } from "zod";
2
+ import { getConfig } from "../../utils/getConfig.js";
3
+ import { requestClient } from "../../utils/requestClient.js";
4
+ import { _parseError } from "../shared/helpers.js";
5
+ import { ToolName } from "../shared/types.js";
6
+ import { FetchChatMessages, FetchChatRoom } from "../shared/gql-queries.js";
7
+ const InputSchema = z.object({
8
+ limit: z
9
+ .number()
10
+ .int()
11
+ .min(1)
12
+ .max(100)
13
+ .default(20)
14
+ .describe("Number of recent messages to fetch (default: 20, max: 100)"),
15
+ });
16
+ export const wopeeReadChatHistory = {
17
+ name: ToolName.WOPEE_READ_CHAT_HISTORY,
18
+ config: {
19
+ title: "Read chat history",
20
+ description: "Read recent messages from the current project's chat room. Returns the last N messages in chronological order, including sender info and timestamps. Use this to understand the conversation context or review what has been discussed. Requires WOPEE_PROJECT_UUID to be configured.",
21
+ inputSchema: InputSchema.shape,
22
+ },
23
+ handler: async (input) => {
24
+ try {
25
+ const { WOPEE_PROJECT_UUID } = getConfig();
26
+ if (!WOPEE_PROJECT_UUID)
27
+ return {
28
+ content: [
29
+ { type: "text", text: "WOPEE_PROJECT_UUID is not set" },
30
+ ],
31
+ };
32
+ // First fetch the chat room for this project
33
+ const roomResult = await requestClient(FetchChatRoom, {
34
+ projectUuid: WOPEE_PROJECT_UUID,
35
+ });
36
+ if (!roomResult?.fetchChatRoom)
37
+ return {
38
+ content: [
39
+ {
40
+ type: "text",
41
+ text: "No chat room found for this project",
42
+ },
43
+ ],
44
+ };
45
+ const result = await requestClient(FetchChatMessages, {
46
+ roomUuid: roomResult.fetchChatRoom.uuid,
47
+ limit: input.limit,
48
+ });
49
+ const messages = result?.fetchChatMessages || [];
50
+ if (messages.length === 0) {
51
+ return {
52
+ content: [
53
+ {
54
+ type: "text",
55
+ text: "No messages found in the chat room",
56
+ },
57
+ ],
58
+ };
59
+ }
60
+ const formatted = messages
61
+ .map((msg) => {
62
+ const author = msg.authorName || msg.authorType;
63
+ const time = new Date(msg.createdAt).toISOString();
64
+ return `[${time}] ${author}: ${msg.content}`;
65
+ })
66
+ .join("\n");
67
+ return {
68
+ content: [
69
+ {
70
+ type: "text",
71
+ text: `Chat history (${messages.length} messages):\n\n${formatted}`,
72
+ },
73
+ ],
74
+ };
75
+ }
76
+ catch (error) {
77
+ return _parseError(error);
78
+ }
79
+ },
80
+ };
@@ -0,0 +1,65 @@
1
+ import { z } from "zod";
2
+ import { getConfig } from "../../utils/getConfig.js";
3
+ import { requestClient } from "../../utils/requestClient.js";
4
+ import { _parseError } from "../shared/helpers.js";
5
+ import { ToolName } from "../shared/types.js";
6
+ import { SendChatMessage, FetchChatRoom } from "../shared/gql-queries.js";
7
+ const InputSchema = z.object({
8
+ content: z.string().describe("The message content to send to the chat room"),
9
+ contentType: z
10
+ .enum(["STATUS_UPDATE", "TEXT"])
11
+ .default("TEXT")
12
+ .describe("The type of message: TEXT for regular messages, STATUS_UPDATE for status notifications"),
13
+ });
14
+ export const wopeeSendChatMessage = {
15
+ name: ToolName.WOPEE_SEND_CHAT_MESSAGE,
16
+ config: {
17
+ title: "Send chat message",
18
+ description: "Send a message to the current project's chat room. Use this to post status updates (e.g., 'Test run started...', 'Analysis complete') or informational messages to the chat. The message will appear as a SYSTEM message in the chat room. Requires WOPEE_PROJECT_UUID to be configured.",
19
+ inputSchema: InputSchema.shape,
20
+ },
21
+ handler: async (input) => {
22
+ try {
23
+ const { WOPEE_PROJECT_UUID } = getConfig();
24
+ if (!WOPEE_PROJECT_UUID)
25
+ return {
26
+ content: [
27
+ { type: "text", text: "WOPEE_PROJECT_UUID is not set" },
28
+ ],
29
+ };
30
+ // First fetch the chat room for this project
31
+ const roomResult = await requestClient(FetchChatRoom, {
32
+ projectUuid: WOPEE_PROJECT_UUID,
33
+ });
34
+ if (!roomResult?.fetchChatRoom)
35
+ return {
36
+ content: [
37
+ {
38
+ type: "text",
39
+ text: "No chat room found for this project",
40
+ },
41
+ ],
42
+ };
43
+ await requestClient(SendChatMessage, {
44
+ input: {
45
+ roomUuid: roomResult.fetchChatRoom.uuid,
46
+ content: input.content,
47
+ contentType: input.contentType,
48
+ sourcePlatform: "CMD",
49
+ authorType: "SYSTEM",
50
+ },
51
+ });
52
+ return {
53
+ content: [
54
+ {
55
+ type: "text",
56
+ text: `Message sent successfully to chat room.`,
57
+ },
58
+ ],
59
+ };
60
+ }
61
+ catch (error) {
62
+ return _parseError(error);
63
+ }
64
+ },
65
+ };
@@ -5,7 +5,7 @@ export const wopeeUpdateArtifact = {
5
5
  name: ToolName.WOPEE_UPDATE_ARTIFACT,
6
6
  config: {
7
7
  title: "Update test artifacts",
8
- description: "Update previously generated content in a suite. Use this to refine user stories, test cases, app context, or Playwright code after reviewing them with wopee_fetch_artifact. Requires the content type (APP_CONTEXT, GENERAL_USER_STORIES, USER_STORIES, PLAYWRIGHT_CODE, or PROJECT_CONTEXT), the suite UUID, and the new content as a string. For PLAYWRIGHT_CODE, also provide the test case identifier (e.g. 'US004:TC006'). This enables an iterative workflow: generate review update dispatch.",
8
+ description: "Replace the content of a previously generated test artifact in a suite. This is a destructive overwrite the full content is replaced, not patched. Use this after reviewing artifacts with wopee_fetch_artifact to fix incorrect user stories, refine test case steps, or edit generated Playwright code. Do NOT use this to create new artifacts use wopee_generate_artifact instead. Prerequisite: the artifact must already exist (generated via wopee_generate_artifact). On success, returns confirmation. On failure (e.g. invalid suite UUID, missing artifact), returns an error message. Idempotent: calling with the same content multiple times produces the same result.",
9
9
  inputSchema: UpdateArtifactHandlerInputSchema.shape,
10
10
  },
11
11
  handler: async (input) => await updateArtifact(input),
@@ -2,9 +2,11 @@ export const getConfig = () => {
2
2
  const WOPEE_API_URL = process.env.WOPEE_API_URL ?? "https://api.wopee.io";
3
3
  const WOPEE_API_KEY = process.env.WOPEE_API_KEY ?? null;
4
4
  const WOPEE_PROJECT_UUID = process.env.WOPEE_PROJECT_UUID ?? null;
5
+ const WOPEE_AUTH_TOKEN = process.env.WOPEE_AUTH_TOKEN ?? null;
5
6
  return {
6
7
  WOPEE_API_URL,
7
8
  WOPEE_API_KEY,
8
9
  WOPEE_PROJECT_UUID,
10
+ WOPEE_AUTH_TOKEN,
9
11
  };
10
12
  };
@@ -23,20 +23,26 @@ function classifyGraphQLErrors(errors) {
23
23
  return new RequestError(combined, "GRAPHQL_ERROR");
24
24
  }
25
25
  export const requestClient = async (query, variables) => {
26
- const { WOPEE_API_URL, WOPEE_API_KEY } = getConfig();
27
- if (!WOPEE_API_KEY) {
28
- throw new RequestError("WOPEE_API_KEY is not set", "AUTH_ERROR");
26
+ const { WOPEE_API_URL, WOPEE_API_KEY, WOPEE_AUTH_TOKEN } = getConfig();
27
+ if (!WOPEE_API_KEY && !WOPEE_AUTH_TOKEN) {
28
+ throw new RequestError("WOPEE_API_KEY or WOPEE_AUTH_TOKEN must be set", "AUTH_ERROR");
29
29
  }
30
30
  const headers = {
31
- api_key: WOPEE_API_KEY,
32
31
  "Content-Type": "application/json",
33
32
  };
33
+ if (WOPEE_AUTH_TOKEN) {
34
+ headers.authorization = `Bearer ${WOPEE_AUTH_TOKEN}`;
35
+ }
36
+ else if (WOPEE_API_KEY) {
37
+ headers.api_key = WOPEE_API_KEY;
38
+ }
34
39
  let response;
35
40
  try {
36
41
  response = await fetch(`${WOPEE_API_URL}`, {
37
42
  method: "POST",
38
43
  headers,
39
44
  body: JSON.stringify({ query, variables }),
45
+ signal: AbortSignal.timeout(30000),
40
46
  });
41
47
  }
42
48
  catch (error) {
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "bin": {
5
5
  "wopee-mcp": "./build/index.js"
6
6
  },
7
- "version": "1.23.1",
7
+ "version": "1.24.0",
8
8
  "mcpName": "io.github.Wopee-io/wopee-mcp",
9
9
  "description": "Wopee.io MCP server for autonomous testing platform",
10
10
  "main": "./build/index.js",