firewalla-mcp-server
Version:
Model Context Protocol (MCP) server for Firewalla MSP API - Provides real-time network monitoring, security analysis, and firewall management through 28 specialized tools compatible with any MCP client
130 lines • 4.25 kB
JavaScript
/**
* Unified Response Format for Solo Dev OSS Project
*
* Simple, consistent response format for all MCP tools.
* Focuses on practicality and maintainability over enterprise complexity.
*/
/**
* Create a successful unified response
*/
export function createSuccessResponse(data, toolName, options = {}) {
const count = Array.isArray(data) ? data.length : undefined;
return {
success: true,
data,
meta: {
timestamp: new Date().toISOString(),
tool: toolName,
request_id: options.requestId || generateRequestId(),
count,
execution_time_ms: options.executionTimeMs,
},
};
}
/**
* Create an error unified response
*/
export function createErrorResponse(error, toolName, options = {}) {
return {
success: false,
error,
meta: {
timestamp: new Date().toISOString(),
tool: toolName,
request_id: options.requestId || generateRequestId(),
},
};
}
/**
* Convert unified response to MCP CallToolResult format
*/
export function toCallToolResult(unifiedResponse) {
return {
content: [
{
type: 'text',
text: JSON.stringify(unifiedResponse, null, 2),
},
],
isError: !unifiedResponse.success,
};
}
/**
* Alias for toCallToolResult to maintain test compatibility
*/
export const toToolResponse = toCallToolResult;
/**
* Simple wrapper to convert any tool handler to use unified responses
*/
export function withUnifiedResponse(handler, toolName) {
return (async (...args) => {
const startTime = Date.now();
const requestId = generateRequestId();
try {
const result = await handler(...args);
// If it's already an error, convert to unified error format
if (result.isError === true) {
const errorText = result.content[0]?.text || 'Unknown error';
let errorData;
try {
if (typeof errorText === 'string') {
errorData = JSON.parse(errorText);
}
else {
errorData = { message: 'Unknown error' };
}
}
catch {
errorData = { message: errorText };
}
const unifiedError = createErrorResponse(errorData.message || errorData.error || 'Unknown error', toolName, { requestId });
return toCallToolResult(unifiedError);
}
// Convert successful response to unified format
let data;
try {
const textContent = result.content[0]?.text || '{}';
if (typeof textContent === 'string') {
data = JSON.parse(textContent);
}
else {
data = textContent || {};
}
}
catch {
data = result.content[0]?.text || {};
}
const executionTimeMs = Date.now() - startTime;
const unifiedSuccess = createSuccessResponse(data, toolName, {
executionTimeMs,
requestId,
});
return toCallToolResult(unifiedSuccess);
}
catch (error) {
const unifiedError = createErrorResponse(error instanceof Error ? error.message : 'Unknown error', toolName, { requestId });
return toCallToolResult(unifiedError);
}
});
}
/**
* Generate a simple request ID
*/
function generateRequestId() {
return `req_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
}
/**
* Type guard to check if a response is a unified response
*/
export function isUnifiedResponse(obj) {
if (!obj || typeof obj !== 'object' || typeof obj.success !== 'boolean') {
return false;
}
if (!obj.meta || typeof obj.meta !== 'object') {
return false;
}
return (typeof obj.meta.timestamp === 'string' &&
typeof obj.meta.tool === 'string' &&
typeof obj.meta.request_id === 'string');
}
//# sourceMappingURL=unified-response.js.map