merlyn/server/endpoints/mcpServers.js
Timothy Carambat 7a01298a8e
ModelContextProtocol (MCP) Full Compatibility (#3547)
* WIP MCP full compatibility layer

* implement MCP agent function wrapping and invocation methods

* Add `uvx` to docker bin for MCP executions

* dev build

* prune removed data

* Wrap MCP servers to lazy load items to not block the UI
Mobile bug fixes

* arm64 test build

* reset dev builder

* remove unused prop
2025-03-31 16:15:19 -05:00

101 lines
2.7 KiB
JavaScript

const { reqBody } = require("../utils/http");
const MCPCompatibilityLayer = require("../utils/MCP");
const {
flexUserRoleValid,
ROLES,
} = require("../utils/middleware/multiUserProtected");
const { validatedRequest } = require("../utils/middleware/validatedRequest");
function mcpServersEndpoints(app) {
if (!app) return;
app.get(
"/mcp-servers/force-reload",
[validatedRequest, flexUserRoleValid([ROLES.admin])],
async (_request, response) => {
try {
const mcp = new MCPCompatibilityLayer();
await mcp.reloadMCPServers();
return response.status(200).json({
success: true,
error: null,
servers: await mcp.servers(),
});
} catch (error) {
console.error("Error force reloading MCP servers:", error);
return response.status(500).json({
success: false,
error: error.message,
servers: [],
});
}
}
);
app.get(
"/mcp-servers/list",
[validatedRequest, flexUserRoleValid([ROLES.admin])],
async (_request, response) => {
try {
const servers = await new MCPCompatibilityLayer().servers();
return response.status(200).json({
success: true,
servers,
});
} catch (error) {
console.error("Error listing MCP servers:", error);
return response.status(500).json({
success: false,
error: error.message,
});
}
}
);
app.post(
"/mcp-servers/toggle",
[validatedRequest, flexUserRoleValid([ROLES.admin])],
async (request, response) => {
try {
const { name } = reqBody(request);
const result = await new MCPCompatibilityLayer().toggleServerStatus(
name
);
return response.status(200).json({
success: result.success,
error: result.error,
});
} catch (error) {
console.error("Error toggling MCP server:", error);
return response.status(500).json({
success: false,
error: error.message,
});
}
}
);
app.post(
"/mcp-servers/delete",
[validatedRequest, flexUserRoleValid([ROLES.admin])],
async (request, response) => {
try {
const { name } = reqBody(request);
const result = await new MCPCompatibilityLayer().deleteServer(name);
return response.status(200).json({
success: result.success,
error: result.error,
});
} catch (error) {
console.error("Error deleting MCP server:", error);
return response.status(500).json({
success: false,
error: error.message,
});
}
}
);
}
module.exports = { mcpServersEndpoints };