Here's a custom MCP tool I use to run commands and parse stdout / stderr all the time:
try {
const execPromise = promisify(exec);
const { stdout, stderr } = await execPromise(command);
if (stderr) {
return {
content: [{
type: "text",
text: `Error: ${stderr}`
}],
isError: true
};
}
return {
content: [{
type: "text",
text: stdout
}],
isError: false
};
} catch (error: any) {
return {
content: [{
type: "text",
text: `Error executing command: ${error.message}`
}],
isError: true
};
}
Yeah, if you want to be super technical, it's Node that does the actual command running, but in my opinion, that's as good as saying the MCP client is...