mcpipe
Version:
Decorate stdio MCP servers with debugging and other capabilities.
90 lines (89 loc) • 3.45 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformServerToClientMessage = transformServerToClientMessage;
exports.transformClientToServerMessage = transformClientToServerMessage;
/**
* Type guard to check if an object is a potential JSON-RPC message.
*/
function isJsonMessage(obj) {
return typeof obj === 'object' && obj !== null && !Array.isArray(obj);
}
// Type guards for specific MCP message types
function isListToolsResult(message) {
return message.jsonrpc === "2.0" &&
isJsonMessage(message.result) &&
Array.isArray(message.result.tools);
}
function isCallToolResult(message) {
return message.jsonrpc === "2.0" &&
isJsonMessage(message.result) &&
(typeof message.result.content !== 'undefined' || typeof message.result.toolName === 'string');
}
function isCallToolRequest(message) {
return message.jsonrpc === "2.0" &&
message.method === "tools/call" &&
isJsonMessage(message.params) &&
typeof message.params.name === 'string';
}
// Message transformation functions
function transformListToolsResult(message, prefix) {
if (!isJsonMessage(message.result) || !Array.isArray(message.result.tools)) {
return { message, isModified: false };
}
let isModified = false;
message.result.tools.forEach(tool => {
if (isJsonMessage(tool) && typeof tool.name === 'string') {
tool.name = prefix + tool.name;
isModified = true;
}
});
return { message, isModified };
}
function transformCallToolResult(message, prefix) {
if (!isJsonMessage(message.result)) {
return { message, isModified: false };
}
let isModified = false;
// Handle legacy toolName field for backwards compatibility with protocol versions <= 2024-10-07
// Note: Current MCP protocol (2025-03-26+) does not include toolName in CallToolResult
if (typeof message.result.toolName === 'string') {
message.result.toolName = prefix + message.result.toolName;
isModified = true;
}
// Current protocol versions don't include tool names in CallToolResult,
// so no transformation is needed for modern servers
return { message, isModified };
}
function transformCallToolRequest(message, prefix) {
if (!isJsonMessage(message.params) || typeof message.params.name !== 'string') {
return { message, isModified: false };
}
let isModified = false;
const originalFullName = message.params.name;
if (originalFullName.startsWith(prefix)) {
message.params.name = originalFullName.substring(prefix.length);
isModified = true;
}
return { message, isModified };
}
// transformation dispatcher for server->client messages
function transformServerToClientMessage(message, prefix) {
if (isJsonMessage(message)) {
if (isListToolsResult(message)) {
return transformListToolsResult(message, prefix);
}
if (isCallToolResult(message)) {
return transformCallToolResult(message, prefix);
}
}
return { message, isModified: false };
}
// transformation dispatcher for client->server messages
function transformClientToServerMessage(message, prefix) {
if (isJsonMessage(message)) {
if (isCallToolRequest(message)) {
return transformCallToolRequest(message, prefix);
}
}
return { message, isModified: false };
}