mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-08 22:48:14 -05:00
* improvement(code-structure): move db into separate package * make db separate package * remake bun lock * update imports to not maintain two separate ones * fix CI for tests by adding dummy url * vercel build fix attempt * update bun lock * regenerate bun lock * fix mocks * remove db commands from apps/sim package json
93 lines
2.8 KiB
TypeScript
93 lines
2.8 KiB
TypeScript
import { db } from '@sim/db'
|
|
import { mcpServers } from '@sim/db/schema'
|
|
import { and, eq, isNull } from 'drizzle-orm'
|
|
import type { NextRequest } from 'next/server'
|
|
import { createLogger } from '@/lib/logs/console/logger'
|
|
import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware'
|
|
import { mcpService } from '@/lib/mcp/service'
|
|
import { validateMcpServerUrl } from '@/lib/mcp/url-validator'
|
|
import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils'
|
|
|
|
const logger = createLogger('McpServerAPI')
|
|
|
|
export const dynamic = 'force-dynamic'
|
|
|
|
/**
|
|
* PATCH - Update an MCP server in the workspace (requires write or admin permission)
|
|
*/
|
|
export const PATCH = withMcpAuth('write')(
|
|
async (
|
|
request: NextRequest,
|
|
{ userId, workspaceId, requestId },
|
|
{ params }: { params: { id: string } }
|
|
) => {
|
|
const serverId = params.id
|
|
|
|
try {
|
|
const body = getParsedBody(request) || (await request.json())
|
|
|
|
logger.info(`[${requestId}] Updating MCP server: ${serverId} in workspace: ${workspaceId}`, {
|
|
userId,
|
|
updates: Object.keys(body).filter((k) => k !== 'workspaceId'),
|
|
})
|
|
|
|
// Validate URL if being updated
|
|
if (
|
|
body.url &&
|
|
(body.transport === 'http' ||
|
|
body.transport === 'sse' ||
|
|
body.transport === 'streamable-http')
|
|
) {
|
|
const urlValidation = validateMcpServerUrl(body.url)
|
|
if (!urlValidation.isValid) {
|
|
return createMcpErrorResponse(
|
|
new Error(`Invalid MCP server URL: ${urlValidation.error}`),
|
|
'Invalid server URL',
|
|
400
|
|
)
|
|
}
|
|
body.url = urlValidation.normalizedUrl
|
|
}
|
|
|
|
// Remove workspaceId from body to prevent it from being updated
|
|
const { workspaceId: _, ...updateData } = body
|
|
|
|
const [updatedServer] = await db
|
|
.update(mcpServers)
|
|
.set({
|
|
...updateData,
|
|
updatedAt: new Date(),
|
|
})
|
|
.where(
|
|
and(
|
|
eq(mcpServers.id, serverId),
|
|
eq(mcpServers.workspaceId, workspaceId),
|
|
isNull(mcpServers.deletedAt)
|
|
)
|
|
)
|
|
.returning()
|
|
|
|
if (!updatedServer) {
|
|
return createMcpErrorResponse(
|
|
new Error('Server not found or access denied'),
|
|
'Server not found',
|
|
404
|
|
)
|
|
}
|
|
|
|
// Clear MCP service cache after update
|
|
mcpService.clearCache(workspaceId)
|
|
|
|
logger.info(`[${requestId}] Successfully updated MCP server: ${serverId}`)
|
|
return createMcpSuccessResponse({ server: updatedServer })
|
|
} catch (error) {
|
|
logger.error(`[${requestId}] Error updating MCP server:`, error)
|
|
return createMcpErrorResponse(
|
|
error instanceof Error ? error : new Error('Failed to update MCP server'),
|
|
'Failed to update MCP server',
|
|
500
|
|
)
|
|
}
|
|
}
|
|
)
|