@turbot/tailpipe-mcp
Version:
Tailpipe MCP server to query cloud and security logs using AI.
102 lines • 3.91 kB
JavaScript
import { execSync } from "node:child_process";
// Default buffer size (100MB)
const DEFAULT_BUFFER_SIZE_MB = 100;
// Convert MB to bytes and handle the environment variable
export const MAX_BUFFER_SIZE = process.env.TAILPIPE_MCP_MEMORY_MAX_MB
? parseInt(process.env.TAILPIPE_MCP_MEMORY_MAX_MB, 10) * 1024 * 1024 // Convert MB to bytes
: DEFAULT_BUFFER_SIZE_MB * 1024 * 1024;
export function executeCommand(cmd, options = {}) {
try {
const execOptions = {
encoding: 'utf-8',
env: options.env || process.env,
maxBuffer: options.maxBuffer || MAX_BUFFER_SIZE
};
const output = execSync(cmd, execOptions);
return output;
}
catch (error) {
// If it's an error from execSync, it will have stdout and stderr properties
if (error && typeof error === 'object') {
const execError = error;
const stderr = execError.stderr?.toString().trim() || '';
const stdout = execError.stdout?.toString().trim() || '';
const code = execError.code;
const signal = execError.signal;
// Create a detailed error object
const commandError = new Error();
commandError.cmd = cmd;
commandError.code = code;
commandError.signal = signal;
commandError.stdout = stdout;
commandError.stderr = stderr;
// Set an informative error message, excluding stdout to avoid verbosity
const details = [
stderr && `Error: ${stderr}`,
code && `Exit code: ${code}`,
signal && `Signal: ${signal}`,
`Command: ${cmd}`
].filter(Boolean).join('\n');
commandError.message = details || 'Command execution failed with no error details';
// Log the error details (including stdout for debugging purposes)
console.error('Command execution failed:', {
cmd,
stderr,
stdout,
code,
signal
});
throw commandError;
}
// Unknown errors
const errorMessage = error instanceof Error ? error.message : String(error);
console.error('Command execution failed:', {
cmd,
error: errorMessage
});
throw new Error(`Command execution failed: ${errorMessage}. Command: ${cmd}`);
}
}
export function formatCommandError(error, context) {
let errorMessage;
// JSON parsing errors
if (error instanceof SyntaxError) {
console.error('Failed to parse Tailpipe CLI output:', error.message);
errorMessage = `Failed to parse Tailpipe CLI output: ${error.message}${context ? `. Command: ${context}` : ''}`;
}
// Command execution errors
else if (error instanceof Error && isCommandError(error)) {
const cmdError = error;
const details = [
cmdError.stderr && `Error: ${cmdError.stderr}`,
cmdError.code && `Exit code: ${cmdError.code}`,
cmdError.signal && `Signal: ${cmdError.signal}`,
cmdError.cmd && `Command: ${cmdError.cmd}`
].filter(Boolean).join('\n');
errorMessage = `Failed to run Tailpipe CLI:\n${details}`;
}
// Other Error instances
else if (error instanceof Error) {
errorMessage = error.message;
}
// Unknown errors
else {
errorMessage = String(error);
}
return {
isError: true,
content: [{
type: "text",
text: errorMessage
}]
};
}
// Type guard to check if an Error is a CommandError
function isCommandError(error) {
return ('stderr' in error ||
'stdout' in error ||
'cmd' in error ||
'code' in error ||
'signal' in error);
}
//# sourceMappingURL=command.js.map