thunderclient-mcp
Version:
Thunder Client MCP Server
89 lines (88 loc) • 3.43 kB
JavaScript
import { exec } from "child_process";
import { promisify } from "util";
import * as fs from "fs";
import pkg from '../package.json' with { type: 'json' };
const version = pkg.version;
const execAsync = promisify(exec);
// Support multiple data flags in curl
function normalizeCurlInputForWindows(curlInput) {
return curlInput.replace(/(-d|--data(?:-raw)?)\s+(['"])([\s\S]*?)\2/g, (_, flag, _quote, rawBody) => {
const escapedBody = rawBody
.replace(/\\/g, '\\\\')
.replace(/"/g, '\\"');
return `${flag} "${escapedBody}"`;
});
}
export class ThunderClient {
validateProjectDir(projectDir) {
if (!fs.existsSync(projectDir)) {
return {
valid: false,
error: `Invalid project directory: ${projectDir}`,
};
}
return { valid: true };
}
async execCommand(command, cwd) {
try {
const { stdout, stderr } = await execAsync(command, { cwd });
let succeeded = true;
let errorMessage = stderr ? stderr.trim() : undefined;
if ((stderr && stderr.trim()) || stdout?.trim().toLowerCase().includes("error")) {
succeeded = false;
if (stdout?.trim().toLowerCase().includes("error")) {
errorMessage = stdout?.trim();
}
}
return { success: succeeded, result: stdout?.trim(), error: errorMessage };
}
catch (error) {
return {
success: false,
error: error?.message || "Unknown error",
};
}
}
async runHelp(projectDir) {
const check = this.validateProjectDir(projectDir);
if (!check.valid)
return { success: false, error: check.error, projectDir, version };
const result = await this.execCommand("tc --help", projectDir);
return { ...result, projectDir, version };
}
async runDebug(projectDir) {
const check = this.validateProjectDir(projectDir);
if (!check.valid)
return { success: false, error: check.error, projectDir, version };
const result = await this.execCommand("tc --debug", projectDir);
return { ...result, projectDir, version, };
}
async runCurl({ curlInput, name, collection, folder, projectDir, }) {
const check = this.validateProjectDir(projectDir);
if (!check.valid)
return { success: false, error: check.error, version };
const trimmedInput = curlInput.trim();
if (!trimmedInput.toLowerCase().startsWith("curl ")) {
return { success: false, error: "Input must start with 'curl '", version };
}
let curlArgs = trimmedInput.slice(5).trim();
if (process.platform === "win32") {
curlArgs = normalizeCurlInputForWindows(curlArgs);
}
let cmd = `tc curl ${curlArgs}`;
if (name)
cmd += ` --name "${name}"`;
if (collection)
cmd += ` --col "${collection}"`;
if (folder)
cmd += ` --fol "${folder}"`;
cmd += ` --mcp`;
const result = await this.execCommand(cmd, projectDir);
if (result.success) {
return { ...result, projectDir, version }; // ✅ Return only success: true
}
else {
return { ...result, projectDir, version };
}
}
}