112 lines
8.7 KiB
Markdown
112 lines
8.7 KiB
Markdown
|
|
# Task ID: 4
|
||
|
|
|
||
|
|
**Title:** Implement MCP Server Registry and Profile Management
|
||
|
|
|
||
|
|
**Status:** pending
|
||
|
|
|
||
|
|
**Dependencies:** 3
|
||
|
|
|
||
|
|
**Priority:** high
|
||
|
|
|
||
|
|
**Description:** Create APIs for registering MCP servers, managing profiles with different permission levels, and storing configuration templates.
|
||
|
|
|
||
|
|
**Details:**
|
||
|
|
|
||
|
|
Create REST API endpoints in mcpd:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// routes/mcp-servers.ts
|
||
|
|
app.post('/api/mcp-servers', async (req) => {
|
||
|
|
const { name, type, command, args, envTemplate, setupGuide } = req.body;
|
||
|
|
return prisma.mcpServer.create({ data: { name, type, command, args, envTemplate, setupGuide } });
|
||
|
|
});
|
||
|
|
|
||
|
|
app.get('/api/mcp-servers', async () => {
|
||
|
|
return prisma.mcpServer.findMany({ include: { profiles: true } });
|
||
|
|
});
|
||
|
|
|
||
|
|
app.get('/api/mcp-servers/:id', async (req) => {
|
||
|
|
return prisma.mcpServer.findUnique({ where: { id: req.params.id }, include: { profiles: true, instances: true } });
|
||
|
|
});
|
||
|
|
|
||
|
|
// Profile management
|
||
|
|
app.post('/api/mcp-servers/:serverId/profiles', async (req) => {
|
||
|
|
const { name, config, filterRules } = req.body;
|
||
|
|
return prisma.mcpProfile.create({
|
||
|
|
data: { name, serverId: req.params.serverId, config, filterRules }
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
// Example profile configs:
|
||
|
|
// Read-only Jira: { permissions: ['read'], allowedEndpoints: ['/issues/*', '/projects/*'] }
|
||
|
|
// Full Slack: { permissions: ['read', 'write'], channels: ['*'] }
|
||
|
|
// Limited Terraform: { permissions: ['read'], modules: ['aws_*', 'kubernetes_*'] }
|
||
|
|
```
|
||
|
|
|
||
|
|
Create seed data with pre-configured MCP server definitions:
|
||
|
|
- Slack MCP with OAuth setup guide
|
||
|
|
- Jira MCP with API token guide
|
||
|
|
- GitHub MCP with PAT guide
|
||
|
|
- Terraform docs MCP
|
||
|
|
|
||
|
|
**Test Strategy:**
|
||
|
|
|
||
|
|
Test CRUD operations for servers and profiles. Verify profile inheritance works. Test that invalid configurations are rejected by Zod validation.
|
||
|
|
|
||
|
|
## Subtasks
|
||
|
|
|
||
|
|
### 4.1. Create Zod validation schemas with comprehensive TDD test coverage
|
||
|
|
|
||
|
|
**Status:** pending
|
||
|
|
**Dependencies:** None
|
||
|
|
|
||
|
|
Define and test Zod schemas for MCP server registration, profile management, and configuration templates before implementing any routes or services.
|
||
|
|
|
||
|
|
**Details:**
|
||
|
|
|
||
|
|
Create src/mcpd/src/validation/mcp-server.schema.ts with schemas: CreateMcpServerSchema (name: string non-empty, type: enum ['slack', 'jira', 'github', 'terraform', 'custom'], command: string, args: array of strings, envTemplate: record with nested schema for { description: string, required: boolean, secret: boolean, setupUrl?: string }, setupGuide?: string). Create UpdateMcpServerSchema as partial of create. Create CreateMcpProfileSchema (name: string, serverId: uuid, config: record with permissions array ['read', 'write'], filterRules?: record). Create src/mcpd/tests/unit/validation/mcp-server.schema.test.ts with TDD tests BEFORE implementation: (1) Test valid server creation passes, (2) Test empty name fails, (3) Test invalid type fails, (4) Test envTemplate validates nested structure, (5) Test profile config validates permissions array only contains 'read'/'write', (6) Test UUID format validation for serverId, (7) Test sanitization of XSS attempts in setupGuide field, (8) Test envTemplate values cannot contain shell injection patterns. Security: Add custom Zod refinements to reject dangerous patterns in envTemplate values like backticks, $(), etc.
|
||
|
|
|
||
|
|
### 4.2. Implement repository pattern for MCP server and profile data access
|
||
|
|
|
||
|
|
**Status:** pending
|
||
|
|
**Dependencies:** 4.1
|
||
|
|
|
||
|
|
Create injectable repository classes for McpServer and McpProfile data access with Prisma, following dependency injection patterns for testability.
|
||
|
|
|
||
|
|
**Details:**
|
||
|
|
|
||
|
|
Create src/mcpd/src/repositories/interfaces.ts with IMcpServerRepository and IMcpProfileRepository interfaces defining all CRUD methods. Create src/mcpd/src/repositories/mcp-server.repository.ts implementing IMcpServerRepository with methods: create(data: CreateMcpServerInput), findById(id: string, include?: { profiles?: boolean, instances?: boolean }), findByName(name: string), findAll(include?: { profiles?: boolean }), update(id: string, data: UpdateMcpServerInput), delete(id: string). Create src/mcpd/src/repositories/mcp-profile.repository.ts with methods: create(data: CreateMcpProfileInput), findById(id: string), findByServerId(serverId: string), findAll(), update(id: string, data: UpdateMcpProfileInput), delete(id: string), validateProfilePermissions(profileId: string, requestedPermissions: string[]) to check profile cannot escalate beyond server's allowed permissions. Write TDD tests in src/mcpd/tests/unit/repositories/ before implementation using Prisma mock factory from Task 3's test utilities. Architecture note: These repositories will be used by Task 10 (setup wizard) and Task 15 (profiles library).
|
||
|
|
|
||
|
|
### 4.3. Implement MCP server service layer with business logic and authorization
|
||
|
|
|
||
|
|
**Status:** pending
|
||
|
|
**Dependencies:** 4.1, 4.2
|
||
|
|
|
||
|
|
Create McpServerService and McpProfileService with business logic, authorization checks, and validation orchestration using injected repositories.
|
||
|
|
|
||
|
|
**Details:**
|
||
|
|
|
||
|
|
Create src/mcpd/src/services/mcp-server.service.ts with constructor accepting IMcpServerRepository (DI). Methods: createServer(userId: string, data: CreateMcpServerInput) - validate with Zod schema, check user has 'admin' or 'server:create' permission, call repository; getServer(userId: string, id: string) - check read permission, include profiles if authorized; listServers(userId: string, filters?: ServerFilters); updateServer(userId: string, id: string, data) - check 'server:update' permission; deleteServer(userId: string, id: string) - check 'server:delete', verify no active instances. Create src/mcpd/src/services/mcp-profile.service.ts with methods: createProfile(userId: string, serverId: string, data) - validate profile permissions don't exceed server's capabilities, check 'profile:create' permission; updateProfile(); deleteProfile() - check no active instances using this profile. Security: Implement permission hierarchy where profile.config.permissions must be subset of server's allowed permissions. Create src/mcpd/src/services/authorization.ts with checkPermission(userId: string, resource: string, action: string) helper. Write TDD tests mocking repositories.
|
||
|
|
|
||
|
|
### 4.4. Implement REST API routes for MCP servers and profiles with request validation
|
||
|
|
|
||
|
|
**Status:** pending
|
||
|
|
**Dependencies:** 4.3
|
||
|
|
|
||
|
|
Create Fastify route handlers for MCP server and profile CRUD operations using the service layer, with Zod request validation middleware.
|
||
|
|
|
||
|
|
**Details:**
|
||
|
|
|
||
|
|
Create src/mcpd/src/routes/mcp-servers.ts with routes: POST /api/mcp-servers (create server, requires auth + admin), GET /api/mcp-servers (list all, requires auth), GET /api/mcp-servers/:id (get by ID with profiles/instances, requires auth), PUT /api/mcp-servers/:id (update, requires auth + admin), DELETE /api/mcp-servers/:id (delete, requires auth + admin). Create src/mcpd/src/routes/mcp-profiles.ts with routes: POST /api/mcp-servers/:serverId/profiles (create profile for server), GET /api/mcp-servers/:serverId/profiles (list profiles for server), GET /api/profiles/:id (get profile by ID), PUT /api/profiles/:id (update profile), DELETE /api/profiles/:id (delete profile). Each route handler: (1) Uses Zod schema via validation middleware from Task 3, (2) Calls appropriate service method, (3) Returns consistent response format { success: boolean, data?: T, error?: { code: string, message: string } }, (4) Uses request.user from auth middleware. Register routes in server.ts. Write integration tests using Fastify's inject() method.
|
||
|
|
|
||
|
|
### 4.5. Create seed data for pre-configured MCP servers and perform security review
|
||
|
|
|
||
|
|
**Status:** pending
|
||
|
|
**Dependencies:** 4.4
|
||
|
|
|
||
|
|
Implement seed data for Slack, Jira, GitHub, and Terraform MCP servers with default profiles, plus comprehensive security review of all implemented code.
|
||
|
|
|
||
|
|
**Details:**
|
||
|
|
|
||
|
|
Create src/mcpd/src/seed/mcp-servers.seed.ts with seedMcpServers() function using the McpServerService to create: (1) Slack MCP - command: 'npx', args: ['-y', '@modelcontextprotocol/server-slack'], envTemplate with SLACK_BOT_TOKEN (secret, setupUrl to api.slack.com), SLACK_TEAM_ID, setupGuide markdown with OAuth setup steps, default profiles: 'slack-read-only' (permissions: ['read']), 'slack-full' (permissions: ['read', 'write']); (2) Jira MCP - envTemplate with JIRA_URL, JIRA_EMAIL, JIRA_API_TOKEN (secret), setupGuide for API token creation; (3) GitHub MCP - envTemplate with GITHUB_TOKEN (secret, setupUrl to github.com/settings/tokens); (4) Terraform Docs MCP - no env required, read-only profile. Create src/mcpd/src/seed/index.ts that runs all seeders. Security Review - create SECURITY_REVIEW.md documenting: (1) All Zod schemas reviewed for injection prevention, (2) Authorization checked on every route, (3) envTemplate sanitization prevents shell injection, (4) Profile permission escalation prevented, (5) Secrets marked appropriately in envTemplate, (6) No sensitive data in logs or error responses. Run 'pnpm lint' and 'pnpm test:coverage' ensuring >80% coverage.
|