Files
mcpctl/src/db/prisma/schema.prisma
Michal 467357c2c6
Some checks failed
CI / lint (pull_request) Has been cancelled
CI / typecheck (pull_request) Has been cancelled
CI / test (pull_request) Has been cancelled
CI / build (pull_request) Has been cancelled
CI / package (pull_request) Has been cancelled
feat: kubectl-style CLI + Deployment/Pod model for servers/instances
Server = Deployment (defines what to run + desired replicas)
Instance = Pod (ephemeral, auto-created by reconciliation)

Backend:
- Add replicas field to McpServer schema
- Add reconcile() to InstanceService (scales instances to match replicas)
- Remove manual start/stop/restart - instances are auto-managed
- Cascade: deleting server stops all containers then cascades DB
- Server create/update auto-triggers reconciliation

CLI:
- Add top-level delete command (servers, instances, profiles, projects)
- Add top-level logs command
- Remove instance compound command (use get/delete/logs instead)
- Clean up project command (list/show/delete → top-level get/describe/delete)
- Enhance describe for instances with container inspect info
- Add replicas to apply command's ServerSpec

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 13:30:46 +00:00

178 lines
3.9 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// ── Users ──
model User {
id String @id @default(cuid())
email String @unique
name String?
passwordHash String
role Role @default(USER)
version Int @default(1)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
sessions Session[]
auditLogs AuditLog[]
projects Project[]
@@index([email])
}
enum Role {
USER
ADMIN
}
// ── Sessions ──
model Session {
id String @id @default(cuid())
token String @unique
userId String
expiresAt DateTime
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([token])
@@index([userId])
@@index([expiresAt])
}
// ── MCP Servers ──
model McpServer {
id String @id @default(cuid())
name String @unique
description String @default("")
packageName String?
dockerImage String?
transport Transport @default(STDIO)
repositoryUrl String?
externalUrl String?
command Json?
containerPort Int?
replicas Int @default(1)
envTemplate Json @default("[]")
version Int @default(1)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
profiles McpProfile[]
instances McpInstance[]
@@index([name])
}
enum Transport {
STDIO
SSE
STREAMABLE_HTTP
}
// ── MCP Profiles ──
model McpProfile {
id String @id @default(cuid())
name String
serverId String
permissions Json @default("[]")
envOverrides Json @default("{}")
version Int @default(1)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
server McpServer @relation(fields: [serverId], references: [id], onDelete: Cascade)
projects ProjectMcpProfile[]
@@unique([name, serverId])
@@index([serverId])
}
// ── Projects ──
model Project {
id String @id @default(cuid())
name String @unique
description String @default("")
ownerId String
version Int @default(1)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade)
profiles ProjectMcpProfile[]
@@index([name])
@@index([ownerId])
}
// ── Project <-> Profile join table ──
model ProjectMcpProfile {
id String @id @default(cuid())
projectId String
profileId String
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
profile McpProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
@@unique([projectId, profileId])
@@index([projectId])
@@index([profileId])
}
// ── MCP Instances (running containers) ──
model McpInstance {
id String @id @default(cuid())
serverId String
containerId String?
status InstanceStatus @default(STOPPED)
port Int?
metadata Json @default("{}")
version Int @default(1)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
server McpServer @relation(fields: [serverId], references: [id], onDelete: Cascade)
@@index([serverId])
@@index([status])
}
enum InstanceStatus {
STARTING
RUNNING
STOPPING
STOPPED
ERROR
}
// ── Audit Logs ──
model AuditLog {
id String @id @default(cuid())
userId String
action String
resource String
resourceId String?
details Json @default("{}")
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
@@index([action])
@@index([resource])
@@index([createdAt])
}