Skip to content

Commit c24c36b

Browse files
phrenesis3000claude
andcommitted
feat: add upload data pattern CSV tool
Add dedicated tool for /v1.0/{organization_name}/{project_name}/test-cases/{test_case_number}/start-upload-data-patterns/ endpoint with CSV validation and batch_task_id response handling. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 8f74f79 commit c24c36b

File tree

3 files changed

+115
-1
lines changed

3 files changed

+115
-1
lines changed

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { searchMagicpodArticles } from "./tools/search-magicpod-articles.js";
66
import { readMagicpodArticle } from "./tools/read-magicpod-article.js";
77
import { initMagicPodApiProxy } from "./tools/magicpod-web-api.js";
88
import { apiV1_0UploadFileCreate } from "./tools/api-v1-0-upload-file-create.js";
9+
import { apiV1_0UploadDataPatterns } from "./tools/api-v1-0-upload-data-patterns.js";
910

1011
const program = new Command();
1112
program.option("--api-token <key>", "MagicPod API token to use");
@@ -23,6 +24,7 @@ async function main() {
2324
const baseUrl = baseUrlEnvironmentVariable || "https://app.magicpod.com";
2425
const proxy = await initMagicPodApiProxy(baseUrl, options.apiToken, [
2526
apiV1_0UploadFileCreate(baseUrl, options.apiToken),
27+
apiV1_0UploadDataPatterns(baseUrl, options.apiToken),
2628
searchMagicpodArticles(),
2729
readMagicpodArticle(),
2830
]);
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { z } from "zod";
2+
import { OtherToolDefinition } from "../openapi-mcp-server/mcp/proxy.js";
3+
import fs from "fs";
4+
import path from "node:path";
5+
import axios from "axios";
6+
import FormData from "form-data";
7+
8+
export const apiV1_0UploadDataPatterns = (baseUrl: string, apiToken: string) => {
9+
return {
10+
name: "API-v1_0_upload-data-patterns_create",
11+
description:
12+
"Upload data pattern CSV to test case. The progress can be checked by BatchTask API.",
13+
inputSchema: z.object({
14+
organizationName: z
15+
.string()
16+
.describe("The organization name"),
17+
projectName: z.string().describe("The project name"),
18+
testCaseNumber: z
19+
.number()
20+
.int()
21+
.describe("The test case number"),
22+
localFilePath: z
23+
.string()
24+
.describe(
25+
"A local file path to upload CSV data pattern to MagicPod. Note that an absolute path is required. Its extension must be .csv",
26+
),
27+
overwrite: z
28+
.boolean()
29+
.optional()
30+
.default(false)
31+
.describe(
32+
"If true, overwrite the existing data pattern by the uploaded CSV file. If false, an error is raised if the data pattern already exists.",
33+
),
34+
}),
35+
handleRequest: async ({
36+
organizationName,
37+
projectName,
38+
testCaseNumber,
39+
localFilePath,
40+
overwrite = false
41+
}) => {
42+
try {
43+
if (!fs.existsSync(localFilePath)) {
44+
return {
45+
content: [
46+
{
47+
type: "text",
48+
text: "No such file exists. Note that an absolute path is required",
49+
},
50+
],
51+
};
52+
}
53+
54+
const fileExtension = path.extname(localFilePath).toLowerCase();
55+
if (fileExtension !== ".csv") {
56+
return {
57+
content: [
58+
{
59+
type: "text",
60+
text: "Invalid file extension. The file must be a CSV file (.csv)",
61+
},
62+
],
63+
};
64+
}
65+
66+
const formData = new FormData();
67+
const fileStream = fs.createReadStream(localFilePath);
68+
const fileName = path.basename(localFilePath);
69+
formData.append("file", fileStream, fileName);
70+
formData.append("overwrite", overwrite.toString());
71+
72+
const url = `${baseUrl}/api/v1.0/${organizationName}/${projectName}/test-cases/${testCaseNumber}/start-upload-data-patterns/`;
73+
const response = await axios.post(url, formData, {
74+
headers: {
75+
...formData.getHeaders(),
76+
Authorization: `Token ${apiToken}`,
77+
},
78+
});
79+
80+
if (response.status !== 200) {
81+
return {
82+
content: [
83+
{
84+
type: "text",
85+
text: "An error happened in uploading the data pattern CSV file",
86+
},
87+
],
88+
};
89+
}
90+
91+
return {
92+
content: [
93+
{
94+
type: "text",
95+
text: JSON.stringify({
96+
message: "Successfully started uploading data pattern CSV file",
97+
batch_task_id: response.data.batch_task_id,
98+
}),
99+
},
100+
],
101+
};
102+
} catch (error) {
103+
console.error(
104+
"Failed to upload the data pattern CSV file: ",
105+
error instanceof Error ? error.message : String(error),
106+
);
107+
throw error;
108+
}
109+
},
110+
} satisfies OtherToolDefinition<any>;
111+
};

src/tools/magicpod-web-api.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ const unsupportedPaths = [
3131
'/v1.0/{organization_name}/{project_name}/screenshots/{batch_task_id}/',
3232
'/v1.0/magicpod-clients/api/{os}/{tag_or_version}/',
3333
'/v1.0/magicpod-clients/local/{os}/{version}/',
34-
'/v1.0/{organization_name}/{project_name}/upload-file/'
34+
'/v1.0/{organization_name}/{project_name}/upload-file/',
35+
'/v1.0/{organization_name}/{project_name}/test-cases/{test_case_number}/start-upload-data-patterns/'
3536
];
3637

3738
export const initMagicPodApiProxy = async (

0 commit comments

Comments
 (0)