wopee-mcp 1.23.2 → 1.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/tools/index.js +6 -0
- package/build/tools/shared/gql-queries.js +43 -0
- package/build/tools/shared/types.js +3 -0
- package/build/tools/wopee_create_github_issue/index.js +61 -0
- package/build/tools/wopee_read_chat_history/index.js +80 -0
- package/build/tools/wopee_send_chat_message/index.js +74 -0
- package/build/utils/getConfig.js +2 -0
- package/build/utils/requestClient.js +10 -4
- package/package.json +1 -1
package/build/tools/index.js
CHANGED
|
@@ -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
|
+
`;
|
|
@@ -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) {
|
|
@@ -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
|
+
};
|
|
@@ -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,74 @@
|
|
|
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
|
+
const result = 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
|
+
if (!result?.sendChatMessage)
|
|
53
|
+
return {
|
|
54
|
+
content: [
|
|
55
|
+
{
|
|
56
|
+
type: "text",
|
|
57
|
+
text: "Failed to send message to chat room",
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
return {
|
|
62
|
+
content: [
|
|
63
|
+
{
|
|
64
|
+
type: "text",
|
|
65
|
+
text: `Message sent successfully to chat room.`,
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
return _parseError(error);
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
};
|
package/build/utils/getConfig.js
CHANGED
|
@@ -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
|
|
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