combined-memory-mcp
Version:
MCP server for Combined Memory API - AI-powered chat with unlimited context, memory management, voice agents, and 500+ tool integrations
188 lines (187 loc) • 7.68 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.setupTestMcpServer = setupTestMcpServer;
exports.teardownTestMcpServer = teardownTestMcpServer;
exports.invokeToolForTest = invokeToolForTest;
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
// Create a simple mock transport for testing instead of using SDK's transport
const openapiProcessor_1 = require("../../src/openapiProcessor");
const mcpMapper_1 = require("../../src/mcpMapper");
const apiClient_1 = require("../../src/apiClient");
const path_1 = __importDefault(require("path"));
const test_config_1 = require("../fixtures/test-config");
// Mock for the API client to return test responses instead of making actual HTTP calls
jest.mock('../../src/apiClient', () => ({
executeApiCall: jest.fn().mockImplementation((apiCallDetails, input) => __awaiter(void 0, void 0, void 0, function* () {
var _a;
// Extract operationId from apiCallDetails if it exists, or from any custom property
const operationId = apiCallDetails.operationId ||
((_a = apiCallDetails.pathTemplate) === null || _a === void 0 ? void 0 : _a.split('/').pop()) ||
'unknown';
console.error(`Mock executeApiCall called with operationId: ${operationId}`);
if (operationId === 'listPets' || (operationId.includes('pets') && !operationId.includes('petId') && operationId !== 'createPet')) {
return {
success: true,
data: test_config_1.testConfig.mockResponses.listPets,
statusCode: 200,
};
}
else if (operationId === 'getPetById' || operationId.includes('petId')) {
return {
success: true,
data: test_config_1.testConfig.mockResponses.getPetById,
statusCode: 200,
};
}
else if (operationId === 'createPet') {
// Make sure we always return the createPet response for this operation
return {
success: true,
data: test_config_1.testConfig.mockResponses.createPet,
statusCode: 201,
};
}
else {
return {
success: false,
error: 'Operation not supported in tests',
statusCode: 400,
};
}
})),
}));
// Mock TestTransport class for MCP server
class MockTestTransport {
constructor() {
this.tools = {};
this.server = null;
}
connect(server) {
return __awaiter(this, void 0, void 0, function* () {
this.server = server;
// Store references to all registered tools
if (server.tools) {
for (const [name, handler] of Object.entries(server.tools)) {
if (typeof handler === 'function') {
this.tools[name] = handler;
}
}
}
return Promise.resolve();
});
}
// Method to invoke a tool by name
callTool(toolName, params) {
return __awaiter(this, void 0, void 0, function* () {
if (!this.tools[toolName]) {
return {
error: {
code: 'tool_not_found',
message: `Tool '${toolName}' not found`
}
};
}
try {
// Create a mock extra object similar to what MCP would provide
const extra = {
params,
request: { id: 'test-request-id' }
};
// Call the tool handler
return yield this.tools[toolName](extra);
}
catch (error) {
return {
error: {
code: error.code || 'tool_error',
message: error.message || 'Unknown error'
}
};
}
});
}
}
// Environment variable override for tests
process.env.OPENAPI_FILE_PATH = path_1.default.resolve(process.cwd(), test_config_1.testConfig.openApiFile);
process.env.API_BASE_URL = test_config_1.testConfig.baseUrl;
/**
* Create and set up an MCP server for testing
*/
function setupTestMcpServer() {
return __awaiter(this, void 0, void 0, function* () {
// Process the OpenAPI spec
const openapiSpec = yield (0, openapiProcessor_1.getProcessedOpenApi)();
// Map OpenAPI operations to MCP tools
const mappedTools = (0, mcpMapper_1.mapOpenApiToMcpTools)(openapiSpec);
// Create a server instance
const server = new mcp_js_1.McpServer({
name: "Test OpenAPI to MCP Server",
version: "1.0.0"
});
// Manually add tools property to server for test access
server.tools = {};
// Register the mapped tools
for (const tool of mappedTools) {
const { mcpToolDefinition, apiCallDetails } = tool;
// Store the handler function in the tools object for direct access in tests
const handler = (extra) => __awaiter(this, void 0, void 0, function* () {
const input = extra.params;
const result = yield (0, apiClient_1.executeApiCall)(apiCallDetails, input);
if (result.success) {
return {
content: [{
type: "text",
text: JSON.stringify(result.data, null, 2)
}]
};
}
else {
throw new Error(result.error || `API Error ${result.statusCode}`);
}
});
// Add to tools map for testing
if (server.tools) {
server.tools[mcpToolDefinition.name] = handler;
}
// Register with server
server.tool(mcpToolDefinition.name, mcpToolDefinition.description, handler);
}
// Use our mock transport for testing
const transport = new MockTestTransport();
yield transport.connect(server);
return { server, transport, mappedTools };
});
}
/**
* Clean up resources after testing
*/
function teardownTestMcpServer(server, transport) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield server.close();
}
catch (error) {
console.error('Error closing server:', error);
}
});
}
/**
* Invoke an MCP tool for testing
*/
function invokeToolForTest(transport, toolName, params) {
return __awaiter(this, void 0, void 0, function* () {
return yield transport.callTool(toolName, params);
});
}