UNPKG

@flowfuse/flowfuse

Version:

An open source low-code development platform

199 lines (194 loc) • 7.41 kB
module.exports = async function (app) { app.addHook('preHandler', async (request, reply) => { if (request.params.teamId !== undefined || request.params.teamSlug !== undefined) { if (!request.team) { // For a :teamId route, we can now lookup the full team object request.team = await app.db.models.Team.byId(request.params.teamId) if (!request.team) { reply.code(404).send({ code: 'not_found', error: 'Not Found' }) } } } if (request.session.User) { request.sessionUser = true request.instanceTokenReq = false if (!request.teamMembership) { request.teamMembership = await request.session.User.getTeamMembership(request.team.id) } } else if (request.session.ownerType === 'project' || request.session.ownerType === 'device') { // this is a request from a project or device request.sessionUserReq = false request.instanceTokenReq = true } else { reply.code(403).send({ code: 'unauthorized', error: 'Unauthorized' }) throw new Error('Unauthorized') } }) /** * Get the MCP servers for a team * @name /api/v1/teams/:teamId/mcp * @static * @memberof forge.routes.api.team.mcp */ app.get('/', { preHandler: app.needsPermission('team:mcp:list'), schema: { summary: '', tags: ['MCP'], params: { type: 'object', properties: { teamId: { type: 'string' } } }, response: { 200: { type: 'object', properties: { count: { type: 'number' }, servers: { $ref: 'MCPRegistrationSummaryList' } } }, '4xx': { $ref: 'APIError' }, 500: { $ref: 'APIError' } } } }, async (request, reply) => { try { const mcpServers = await app.db.models.MCPRegistration.byTeam(request.params.teamId) const mcpServersView = app.db.views.MCPRegistrations.MCPRegistrationSummaryList(mcpServers) reply.send({ count: mcpServers.length, servers: mcpServersView }) } catch (err) { reply.status(500).send({ code: 'unexpected_error', error: 'Failed to find mcp entries for team' }) } }) app.post('/:type/:typeId/:nodeId', { preHandler: async (request, reply) => { if (request.session.ownerType === 'project' || request.session.ownerType === 'device') { // all good } else { reply.code(403).send({ code: 'unauthorized', error: 'Unauthorized' }) } }, schema: { summary: '', tags: ['MCP'], params: { type: 'object', properties: { teamId: { type: 'string' }, type: { type: 'string' }, typeId: { type: 'string' }, nodeId: { type: 'string' } } }, body: { type: 'object', properties: { name: { type: 'string' }, endpointRoute: { type: 'string' }, protocol: { type: 'string' }, title: { type: 'string' }, version: { type: 'string' }, description: { type: 'string' } } }, response: { 200: { type: 'object' }, 500: { $ref: 'APIError' } } } }, async (request, reply) => { try { let typeId = request.params.typeId if (request.params.type === 'device') { const device = await app.db.models.Device.byId(request.params.typeId) if (!device) { throw new Error(`Device '${request.params.typeId}' not found`) } typeId = device.id } else if (request.params.type === 'instance') { const project = await app.db.models.Project.byId(request.params.typeId) if (!project) { throw new Error(`Instance '${request.params.typeId}' not found`) } } else { throw new Error(`Unknown MCP target type '${request.params.type}'`) } await app.db.models.MCPRegistration.upsert({ targetType: request.params.type, targetId: typeId, nodeId: request.params.nodeId, title: request.body.title, version: request.body.version, description: request.body.description, name: request.body.name, endpointRoute: request.body.endpointRoute, protocol: request.body.protocol, TeamId: request.team.id }, { fields: ['name', 'endpointRoute', 'title', 'version', 'description'], conflictFields: ['TeamId', 'targetType', 'nodeId', 'targetId'] }) } catch (err) { app.log.error(`register MCP Server ${err.toString()}`) reply.status(500).send({ code: 'unexpected_error', error: 'Failed to create mcp entry' }) return } reply.send({}) }) app.delete('/:type/:typeId/:nodeId', { preHandler: async (request, reply) => { if (request.session.ownerType === 'project' || request.session.ownerType === 'device') { // all good } else { reply.code(403).send({ code: 'unauthorized', error: 'Unauthorized' }) } }, schema: { summary: '', tags: ['MCP'], params: { type: 'object', properties: { teamId: { type: 'string' }, type: { type: 'string' }, typeId: { type: 'string' }, nodeId: { type: 'string' } } }, response: { 200: { type: 'object' }, '4xx': { $ref: 'APIError' }, 500: { $ref: 'APIError' } } } }, async (request, reply) => { try { const mcpServer = await app.db.models.MCPRegistration.byTypeAndIDs(request.params.type, request.params.typeId, request.params.nodeId) if (mcpServer) { await mcpServer.destroy() reply.send({}) } else { reply.status(404).send({ code: 'not_found', error: 'MCP server not found' }) } } catch (err) { app.log.error(`delete MCP Server ${err.toString()}`) reply.status(500).send({ code: 'unexpected_error', error: 'Failed to delete mcp entry' }) } }) }