- Add createHttpAgent() for proxy/CA support via undici - Thread dispatcher through all registry sources - Add collectMetrics() for SRE metrics exposure - Add caPath to RegistryClientConfig - Add category field to RegistryServer with Glama extraction - Add category filtering in client search - Add pr.sh for Gitea PR creation 63 tests passing (13 new). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
781 lines
60 KiB
JSON
781 lines
60 KiB
JSON
{
|
|
"master": {
|
|
"tasks": [
|
|
{
|
|
"id": "1",
|
|
"title": "Initialize Project Structure and Core Dependencies",
|
|
"description": "Set up the monorepo structure for mcpctl with CLI client, mcpd server, and shared libraries. Configure TypeScript, ESLint, and build tooling.",
|
|
"details": "Create a monorepo using pnpm workspaces or npm workspaces with the following structure:\n\n```\nmcpctl/\n├── src/\n│ ├── cli/ # mcpctl CLI tool\n│ ├── mcpd/ # Backend daemon server\n│ ├── shared/ # Shared types, utilities, constants\n│ └── local-proxy/ # Local LLM proxy component\n├── deploy/\n│ └── docker-compose.yml\n├── package.json\n├── tsconfig.base.json\n└── pnpm-workspace.yaml\n```\n\nDependencies to install:\n- TypeScript 5.x\n- Commander.js for CLI\n- Express/Fastify for mcpd HTTP server\n- Zod for schema validation\n- Winston/Pino for logging\n- Prisma or Drizzle for database ORM\n\nCreate base tsconfig.json with strict mode, ES2022 target, and module resolution settings. Set up shared ESLint config with TypeScript rules.",
|
|
"testStrategy": "Verify project builds successfully with `pnpm build`. Ensure all packages compile without errors. Test workspace linking works correctly between packages.",
|
|
"priority": "high",
|
|
"dependencies": [],
|
|
"status": "done",
|
|
"subtasks": [
|
|
{
|
|
"id": 1,
|
|
"title": "Initialize pnpm workspace monorepo with future-proof directory structure",
|
|
"description": "Create the complete monorepo directory structure using pnpm workspaces that accommodates all 18 planned tasks without requiring future refactoring.",
|
|
"dependencies": [],
|
|
"details": "Create root package.json with pnpm workspaces configuration. Create pnpm-workspace.yaml defining all workspace packages. Initialize the following directory structure:\n\n```\nmcpctl/\n├── src/\n│ ├── cli/ # mcpctl CLI tool (Task 7-10)\n│ │ ├── src/\n│ │ ├── tests/\n│ │ └── package.json\n│ ├── mcpd/ # Backend daemon server (Task 3-6, 14, 16)\n│ │ ├── src/\n│ │ ├── tests/\n│ │ └── package.json\n│ ├── shared/ # Shared types, utils, constants, validation\n│ │ ├── src/\n│ │ │ ├── types/ # TypeScript interfaces/types\n│ │ │ ├── utils/ # Utility functions\n│ │ │ ├── constants/# Shared constants\n│ │ │ ├── validation/ # Zod schemas\n│ │ │ └── index.ts # Barrel export\n│ │ ├── tests/\n│ │ └── package.json\n│ ├── local-proxy/ # Local LLM proxy (Task 11-13)\n│ │ ├── src/\n│ │ ├── tests/\n│ │ └── package.json\n│ └── db/ # Database package (Task 2)\n│ ├── src/\n│ ├── prisma/ # Schema and migrations\n│ ├── seed/ # Seed data\n│ ├── tests/\n│ └── package.json\n├── deploy/\n│ └── docker-compose.yml # Local dev services (postgres)\n├── tests/\n│ ├── e2e/ # End-to-end tests (Task 18)\n│ └── integration/ # Integration tests\n├── docs/ # Documentation (Task 18)\n├── package.json # Root workspace config\n├── pnpm-workspace.yaml\n└── turbo.json # Optional: Turborepo for build orchestration\n```\n\nThe pnpm-workspace.yaml should contain: `packages: [\"src/*\"]`",
|
|
"status": "done",
|
|
"testStrategy": "Write Vitest tests that verify: (1) All expected directories exist, (2) All package.json files are valid JSON with correct workspace protocol dependencies, (3) pnpm-workspace.yaml correctly includes all packages, (4) Running 'pnpm install' succeeds and creates correct node_modules symlinks between packages. Run 'pnpm ls' to verify workspace linking.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 2,
|
|
"title": "Configure TypeScript with strict mode and project references",
|
|
"description": "Set up TypeScript configuration with strict mode, ES2022 target, and proper project references for monorepo build orchestration.",
|
|
"dependencies": [
|
|
1
|
|
],
|
|
"details": "Create root tsconfig.base.json with shared compiler options. Create package-specific tsconfig.json in each package that extends the base and sets appropriate paths.",
|
|
"status": "done",
|
|
"testStrategy": "Write Vitest tests that verify tsconfig.base.json exists and has strict: true, each package tsconfig.json extends base correctly.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 3,
|
|
"title": "Set up Vitest testing framework with workspace configuration",
|
|
"description": "Configure Vitest as the test framework across all packages with proper workspace setup, coverage reporting, and test-driven development infrastructure.",
|
|
"dependencies": [
|
|
2
|
|
],
|
|
"details": "Install Vitest and related packages at root level. Create root vitest.config.ts and vitest.workspace.ts for workspace-aware testing pointing to src/cli, src/mcpd, src/shared, src/local-proxy, src/db.",
|
|
"status": "done",
|
|
"testStrategy": "Run 'pnpm test:run' and verify Vitest discovers and runs tests, coverage report is generated.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 4,
|
|
"title": "Configure ESLint with TypeScript rules and docker-compose for local development",
|
|
"description": "Set up shared ESLint configuration with TypeScript-aware rules, Prettier integration, and docker-compose.yml for local PostgreSQL database.",
|
|
"dependencies": [
|
|
2
|
|
],
|
|
"details": "Install ESLint and plugins at root. Create eslint.config.js (flat config, ESLint 9+). Create deploy/docker-compose.yml for local development with PostgreSQL service.",
|
|
"status": "done",
|
|
"testStrategy": "Write Vitest tests that verify eslint.config.js exists and exports valid config, deploy/docker-compose.yml is valid YAML and defines postgres service.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 5,
|
|
"title": "Install core dependencies and perform security/architecture review",
|
|
"description": "Install all required production dependencies across packages, run security audit, and validate the directory structure supports all 18 planned tasks.",
|
|
"dependencies": [
|
|
1,
|
|
3,
|
|
4
|
|
],
|
|
"details": "Install dependencies per package in src/cli, src/mcpd, src/shared, src/db, src/local-proxy. Perform security and architecture review.",
|
|
"status": "done",
|
|
"testStrategy": "Verify each package.json has required dependencies, run pnpm audit, verify .gitignore contains required patterns.",
|
|
"parentId": "undefined"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "2",
|
|
"title": "Design and Implement Database Schema",
|
|
"description": "Create the database schema for storing MCP server configurations, projects, profiles, user sessions, and audit logs. Use PostgreSQL for production readiness.",
|
|
"details": "Design PostgreSQL schema using Prisma ORM with models: User, McpServer, McpProfile, Project, ProjectMcpProfile, McpInstance, AuditLog, Session. Create migrations and seed data for common MCP servers (slack, jira, github, terraform).",
|
|
"testStrategy": "Run Prisma migrations against test database. Verify all relations work correctly with seed data. Test CRUD operations for each model using Prisma client.",
|
|
"priority": "high",
|
|
"dependencies": [
|
|
"1"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": [
|
|
{
|
|
"id": 1,
|
|
"title": "Set up Prisma ORM and PostgreSQL test infrastructure with docker-compose",
|
|
"description": "Initialize Prisma in the db package with PostgreSQL configuration, create docker-compose.yml for local development with separate test database.",
|
|
"dependencies": [],
|
|
"details": "Create src/db/prisma directory structure. Install Prisma dependencies. Configure deploy/docker-compose.yml with two PostgreSQL services: mcpctl-postgres (port 5432) for development and mcpctl-postgres-test (port 5433) for testing.",
|
|
"status": "pending",
|
|
"testStrategy": "Write Vitest tests that verify docker-compose creates both postgres services, setupTestDb() successfully connects and pushes schema.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 2,
|
|
"title": "Write TDD tests for all Prisma models before implementing schema",
|
|
"description": "Create comprehensive Vitest test suites for all 8 models testing CRUD operations, relations, constraints, and edge cases.",
|
|
"dependencies": [
|
|
1
|
|
],
|
|
"details": "Create src/db/tests/models directory with separate test files for each model. Tests will initially fail (TDD red phase) until schema is implemented.",
|
|
"status": "pending",
|
|
"testStrategy": "Tests are expected to fail initially (TDD red phase). After schema implementation, all tests should pass.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 3,
|
|
"title": "Implement Prisma schema with all models and security considerations",
|
|
"description": "Create the complete Prisma schema with all 8 models, proper relations, indexes for audit queries, and security-conscious field design.",
|
|
"dependencies": [
|
|
2
|
|
],
|
|
"details": "Implement src/db/prisma/schema.prisma with all models. Add version Int field and updatedAt DateTime for git-based backup support.",
|
|
"status": "pending",
|
|
"testStrategy": "Run TDD tests from subtask 2 - all should now pass (TDD green phase). Verify npx prisma validate passes.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 4,
|
|
"title": "Create seed data functions with unit tests for common MCP servers",
|
|
"description": "Implement seed functions for common MCP server configurations (Slack, Jira, GitHub, Terraform) with comprehensive unit tests.",
|
|
"dependencies": [
|
|
3
|
|
],
|
|
"details": "Create src/db/seed directory with server definitions and seeding functions for Slack, Jira, GitHub, Terraform MCP servers.",
|
|
"status": "pending",
|
|
"testStrategy": "Write unit tests BEFORE implementing seed functions (TDD). Verify seedMcpServers() creates exactly 4 servers with idempotent behavior.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 5,
|
|
"title": "Create database migrations and perform security/architecture review",
|
|
"description": "Generate initial Prisma migration, create migration helper utilities with tests, and conduct comprehensive security and architecture review.",
|
|
"dependencies": [
|
|
3,
|
|
4
|
|
],
|
|
"details": "Run npx prisma migrate dev --name init. Create src/db/src/migration-helpers.ts. Document security and architecture findings.",
|
|
"status": "pending",
|
|
"testStrategy": "Verify migration files exist, migration helper tests pass, SECURITY_REVIEW.md covers all security checkpoints.",
|
|
"parentId": "undefined"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "3",
|
|
"title": "Implement mcpd Core Server Framework",
|
|
"description": "Build the mcpd daemon server with Express/Fastify, including middleware for authentication, logging, and error handling. Design for horizontal scalability.",
|
|
"details": "Create mcpd server in src/mcpd/src/ with Fastify, health check endpoint, auth middleware, and audit logging. Design for statelessness and scalability.",
|
|
"testStrategy": "Unit test middleware functions. Integration test health endpoint. Load test with multiple concurrent requests. Verify statelessness by running two instances.",
|
|
"priority": "high",
|
|
"dependencies": [
|
|
"1",
|
|
"2"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": [
|
|
{
|
|
"id": 1,
|
|
"title": "Set up mcpd package structure with clean architecture layers and TDD infrastructure",
|
|
"description": "Create the src/mcpd directory structure following clean architecture principles with separate layers for routes, controllers, services, and repositories.",
|
|
"dependencies": [],
|
|
"details": "Create src/mcpd/src/ with routes/, controllers/, services/, repositories/, middleware/, config/, types/, utils/ directories.",
|
|
"status": "pending",
|
|
"testStrategy": "Write initial Vitest tests that verify all required directories exist, package.json has required dependencies.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 2,
|
|
"title": "Implement Fastify server core with health endpoint and database connectivity verification",
|
|
"description": "Create the core Fastify server with health check endpoint that verifies PostgreSQL database connectivity.",
|
|
"dependencies": [
|
|
1
|
|
],
|
|
"details": "Create src/mcpd/src/server.ts with Fastify instance factory function. Implement config validation with Zod and health endpoint.",
|
|
"status": "pending",
|
|
"testStrategy": "TDD approach - write tests first for config validation, health endpoint returns correct structure.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 3,
|
|
"title": "Implement authentication middleware with JWT validation and session management",
|
|
"description": "Create authentication preHandler hook that validates Bearer tokens against the Session table in PostgreSQL.",
|
|
"dependencies": [
|
|
2
|
|
],
|
|
"details": "Create src/mcpd/src/middleware/auth.ts with authMiddleware factory function using dependency injection.",
|
|
"status": "pending",
|
|
"testStrategy": "TDD - write all tests before implementation for 401 responses, token validation, request decoration.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 4,
|
|
"title": "Implement security middleware stack with CORS, Helmet, rate limiting, and input sanitization",
|
|
"description": "Configure and register security middleware including CORS policy, Helmet security headers, rate limiting.",
|
|
"dependencies": [
|
|
2
|
|
],
|
|
"details": "Create src/mcpd/src/middleware/security.ts with registerSecurityPlugins function. Create sanitization and validation utilities.",
|
|
"status": "pending",
|
|
"testStrategy": "TDD tests for CORS headers, Helmet security headers, rate limiting returns 429, input validation.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 5,
|
|
"title": "Implement error handling, audit logging middleware, and graceful shutdown",
|
|
"description": "Create global error handler, audit logging onResponse hook, and graceful shutdown handling with connection draining.",
|
|
"dependencies": [
|
|
2,
|
|
3,
|
|
4
|
|
],
|
|
"details": "Create error-handler.ts, audit.ts middleware, and shutdown.ts utilities in src/mcpd/src/.",
|
|
"status": "pending",
|
|
"testStrategy": "TDD for all components: error handler HTTP codes, audit middleware creates records, graceful shutdown handles SIGTERM.",
|
|
"parentId": "undefined"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "4",
|
|
"title": "Implement MCP Server Registry and Profile Management",
|
|
"description": "Create APIs for registering MCP servers, managing profiles with different permission levels, and storing configuration templates.",
|
|
"details": "Create REST API endpoints in mcpd for MCP server and profile CRUD operations with seed data for common servers.",
|
|
"testStrategy": "Test CRUD operations for servers and profiles. Verify profile inheritance works. Test that invalid configurations are rejected by Zod validation.",
|
|
"priority": "high",
|
|
"dependencies": [
|
|
"3"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": [
|
|
{
|
|
"id": 1,
|
|
"title": "Create Zod validation schemas with comprehensive TDD test coverage",
|
|
"description": "Define and test Zod schemas for MCP server registration, profile management, and configuration templates before implementing any routes.",
|
|
"dependencies": [],
|
|
"details": "Create src/mcpd/src/validation/mcp-server.schema.ts with CreateMcpServerSchema, UpdateMcpServerSchema, CreateMcpProfileSchema.",
|
|
"status": "pending",
|
|
"testStrategy": "TDD approach - write all tests first, then implement schemas. Tests verify valid inputs pass, invalid inputs fail.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 2,
|
|
"title": "Implement repository pattern for MCP server and profile data access",
|
|
"description": "Create injectable repository classes for McpServer and McpProfile data access with Prisma, following dependency injection patterns.",
|
|
"dependencies": [
|
|
1
|
|
],
|
|
"details": "Create src/mcpd/src/repositories/interfaces.ts with IMcpServerRepository and IMcpProfileRepository interfaces.",
|
|
"status": "pending",
|
|
"testStrategy": "TDD - write tests before implementation with mocked PrismaClient. Verify all repository methods are covered.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 3,
|
|
"title": "Implement MCP server service layer with business logic and authorization",
|
|
"description": "Create McpServerService and McpProfileService with business logic, authorization checks, and validation orchestration.",
|
|
"dependencies": [
|
|
1,
|
|
2
|
|
],
|
|
"details": "Create src/mcpd/src/services/mcp-server.service.ts and mcp-profile.service.ts with DI and authorization checks.",
|
|
"status": "pending",
|
|
"testStrategy": "TDD - write tests first mocking repositories and authorization. Verify authorization checks are called for every method.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 4,
|
|
"title": "Implement REST API routes for MCP servers and profiles with request validation",
|
|
"description": "Create Fastify route handlers for MCP server and profile CRUD operations using the service layer.",
|
|
"dependencies": [
|
|
3
|
|
],
|
|
"details": "Create src/mcpd/src/routes/mcp-servers.ts and mcp-profiles.ts with all CRUD endpoints.",
|
|
"status": "pending",
|
|
"testStrategy": "Write integration tests before implementation using Fastify.inject(). Test with docker-compose postgres.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 5,
|
|
"title": "Create seed data for pre-configured MCP servers and perform security review",
|
|
"description": "Implement seed data for Slack, Jira, GitHub, and Terraform MCP servers with default profiles, plus security review.",
|
|
"dependencies": [
|
|
4
|
|
],
|
|
"details": "Create src/mcpd/src/seed/mcp-servers.seed.ts with seedMcpServers() function and SECURITY_REVIEW.md.",
|
|
"status": "pending",
|
|
"testStrategy": "Write unit tests for seed functions. Security tests for injection prevention, authorization checks.",
|
|
"parentId": "undefined"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "5",
|
|
"title": "Implement Project Management APIs",
|
|
"description": "Create APIs for managing MCP projects that group multiple MCP profiles together for easy assignment to Claude sessions.",
|
|
"details": "Create project management endpoints with generateMcpConfig function for .mcp.json format output.",
|
|
"testStrategy": "Test project CRUD operations. Verify profile associations work correctly. Test MCP config generation produces valid .mcp.json format.",
|
|
"priority": "high",
|
|
"dependencies": [
|
|
"4"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": [
|
|
{
|
|
"id": 1,
|
|
"title": "Write TDD tests for project Zod validation schemas and generateMcpConfig function",
|
|
"description": "Create comprehensive Vitest test suites for project validation schemas and generateMcpConfig function BEFORE implementing any code.",
|
|
"dependencies": [],
|
|
"details": "Create tests for CreateProjectSchema, UpdateProjectSchema, UpdateProjectProfilesSchema, and generateMcpConfig with security tests.",
|
|
"status": "pending",
|
|
"testStrategy": "TDD red phase - all tests should fail initially. Verify generateMcpConfig security tests check secret env vars are excluded.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 2,
|
|
"title": "Implement project repository and generateMcpConfig service with security filtering",
|
|
"description": "Create the project repository and generateMcpConfig function that strips sensitive credentials from output.",
|
|
"dependencies": [
|
|
1
|
|
],
|
|
"details": "Create src/mcpd/src/repositories/project.repository.ts and src/mcpd/src/services/mcp-config-generator.ts.",
|
|
"status": "pending",
|
|
"testStrategy": "Run TDD tests from subtask 1. Verify output must NOT contain secret values.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 3,
|
|
"title": "Implement project service layer with authorization and profile validation",
|
|
"description": "Create ProjectService with business logic including authorization checks and profile existence validation.",
|
|
"dependencies": [
|
|
2
|
|
],
|
|
"details": "Create src/mcpd/src/services/project.service.ts with DI accepting IProjectRepository and IMcpProfileRepository.",
|
|
"status": "pending",
|
|
"testStrategy": "TDD - write tests before implementation. Verify authorization and profile validation.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 4,
|
|
"title": "Implement REST API routes for project CRUD and mcp-config endpoint",
|
|
"description": "Create Fastify route handlers for all project management endpoints including /api/projects/:name/mcp-config.",
|
|
"dependencies": [
|
|
3
|
|
],
|
|
"details": "Create src/mcpd/src/routes/projects.ts with all CRUD routes and mcp-config endpoint.",
|
|
"status": "pending",
|
|
"testStrategy": "Integration tests using Fastify.inject(). Verify mcp-config returns valid structure WITHOUT secret env vars.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 5,
|
|
"title": "Create integration tests and security review for project APIs",
|
|
"description": "Write comprehensive integration tests and security review documenting credential handling.",
|
|
"dependencies": [
|
|
4
|
|
],
|
|
"details": "Create src/mcpd/tests/integration/projects.test.ts with end-to-end scenarios and SECURITY_REVIEW.md section.",
|
|
"status": "pending",
|
|
"testStrategy": "Run full integration test suite. Verify coverage >85% for project-related files.",
|
|
"parentId": "undefined"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "6",
|
|
"title": "Implement Docker Container Management for MCP Servers",
|
|
"description": "Create the container orchestration layer for running MCP servers as Docker containers, with support for docker-compose deployment.",
|
|
"details": "Create Docker management module with ContainerManager class using dockerode. Create deploy/docker-compose.yml template.",
|
|
"testStrategy": "Test container creation, start, stop, and removal. Integration test with actual Docker daemon. Verify network isolation.",
|
|
"priority": "high",
|
|
"dependencies": [
|
|
"3",
|
|
"4"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": [
|
|
{
|
|
"id": 1,
|
|
"title": "Define McpOrchestrator interface and write TDD tests for ContainerManager",
|
|
"description": "Define the McpOrchestrator abstraction interface for Docker and Kubernetes orchestrators. Write comprehensive unit tests.",
|
|
"dependencies": [],
|
|
"details": "Create src/mcpd/src/services/orchestrator.ts interface and TDD tests for ContainerManager methods.",
|
|
"status": "pending",
|
|
"testStrategy": "Run tests to verify they exist and fail with expected errors. Coverage target: 100% of interface methods.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 2,
|
|
"title": "Implement ContainerManager class with DockerOrchestrator strategy pattern",
|
|
"description": "Implement the ContainerManager class as a DockerOrchestrator implementation using dockerode.",
|
|
"dependencies": [
|
|
1
|
|
],
|
|
"details": "Create src/mcpd/src/services/docker/container-manager.ts implementing McpOrchestrator interface.",
|
|
"status": "pending",
|
|
"testStrategy": "Run unit tests from subtask 1. Verify TypeScript compilation and resource limits.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 3,
|
|
"title": "Create docker-compose.yml template with mcpd, PostgreSQL, and test MCP server",
|
|
"description": "Create the production-ready deploy/docker-compose.yml template for local development.",
|
|
"dependencies": [],
|
|
"details": "Create deploy/docker-compose.yml with mcpd, postgres, and test-mcp-server services with proper networking.",
|
|
"status": "pending",
|
|
"testStrategy": "Validate with docker-compose config. Run docker-compose up -d and verify all services start.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 4,
|
|
"title": "Write integration tests with real Docker daemon",
|
|
"description": "Create integration test suite that tests ContainerManager against a real Docker daemon.",
|
|
"dependencies": [
|
|
2,
|
|
3
|
|
],
|
|
"details": "Create src/mcpd/src/services/docker/__tests__/container-manager.integration.test.ts.",
|
|
"status": "pending",
|
|
"testStrategy": "Run integration tests with pnpm --filter @mcpctl/mcpd test:integration. Verify containers are created/destroyed.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 5,
|
|
"title": "Implement container network isolation and resource management",
|
|
"description": "Add network segmentation utilities and resource management capabilities for container isolation.",
|
|
"dependencies": [
|
|
2
|
|
],
|
|
"details": "Create src/mcpd/src/services/docker/network-manager.ts with network isolation and resource management.",
|
|
"status": "pending",
|
|
"testStrategy": "Unit tests for network creation. Integration test: verify container network isolation.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 6,
|
|
"title": "Conduct security review of Docker socket access and container configuration",
|
|
"description": "Perform comprehensive security review of all Docker-related code with security controls documentation.",
|
|
"dependencies": [
|
|
2,
|
|
3,
|
|
5
|
|
],
|
|
"details": "Create src/mcpd/docs/DOCKER_SECURITY_REVIEW.md documenting risks and mitigations.",
|
|
"status": "pending",
|
|
"testStrategy": "Review DOCKER_SECURITY_REVIEW.md covers all 6 security areas. Run security unit tests.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 7,
|
|
"title": "Implement container logs streaming and health monitoring",
|
|
"description": "Add log streaming capabilities and health monitoring to ContainerManager for observability.",
|
|
"dependencies": [
|
|
2
|
|
],
|
|
"details": "Extend ContainerManager with getLogs, getHealthStatus, attachToContainer, and event subscriptions.",
|
|
"status": "pending",
|
|
"testStrategy": "Unit tests for getLogs. Integration test: run container, tail logs, verify output.",
|
|
"parentId": "undefined"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "7",
|
|
"title": "Build mcpctl CLI Core Framework",
|
|
"description": "Create the CLI tool foundation using Commander.js with kubectl-inspired command structure, configuration management, and server communication.",
|
|
"details": "Create CLI in src/cli/src/ with Commander.js, configuration management at ~/.mcpctl/config.json, and API client for mcpd.",
|
|
"testStrategy": "Test CLI argument parsing. Test configuration persistence. Mock API calls and verify request formatting.",
|
|
"priority": "high",
|
|
"dependencies": [
|
|
"1"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": [
|
|
{
|
|
"id": 1,
|
|
"title": "Set up CLI package structure with TDD infrastructure and command registry pattern",
|
|
"description": "Create src/cli directory structure with Commander.js foundation, Vitest test configuration, and extensible command registry.",
|
|
"dependencies": [],
|
|
"details": "Create src/cli/src/ with commands/, config/, client/, formatters/, utils/, types/ directories and registry pattern.",
|
|
"status": "pending",
|
|
"testStrategy": "TDD approach - write tests first. Tests verify CLI shows version, help, CommandRegistry works.",
|
|
"parentId": "undefined"
|
|
},
|
|
{
|
|
"id": 2,
|
|
"title": "Implement secure configuration management with encrypted credential storage",
|
|
"description": "Create configuration loader/saver with ~/.mcpctl/config.json and encrypted credentials storage.",
|
|
"dependencies": [
|
|
1
|
|
],
|
|
"details": "Implement config management with proxy settings, custom CA certificates support, and Zod validation.",
|
|
"status": "pending",
|
|
"testStrategy": "TDD tests for config loading, saving, validation, and credential encryption.",
|
|
"parentId": "undefined"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "8",
|
|
"title": "Implement mcpctl get and describe Commands",
|
|
"description": "Create kubectl-style get and describe commands for viewing MCP servers, profiles, projects, and instances.",
|
|
"details": "Implement get command with table/json/yaml output formats and describe command for detailed views.",
|
|
"testStrategy": "Test output formatting for each resource type. Test filtering and sorting options.",
|
|
"priority": "medium",
|
|
"dependencies": [
|
|
"7"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": []
|
|
},
|
|
{
|
|
"id": "9",
|
|
"title": "Implement mcpctl apply and setup Commands",
|
|
"description": "Create apply command for declarative configuration and setup wizard for interactive MCP server configuration.",
|
|
"details": "Implement apply command for YAML/JSON config files and interactive setup wizard with credential prompts.",
|
|
"testStrategy": "Test YAML/JSON parsing. Test interactive prompts with mock inputs. Verify credentials are stored securely.",
|
|
"priority": "medium",
|
|
"dependencies": [
|
|
"7",
|
|
"4"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": []
|
|
},
|
|
{
|
|
"id": "10",
|
|
"title": "Implement mcpctl claude and project Commands",
|
|
"description": "Create commands for managing Claude MCP configuration and project assignments.",
|
|
"details": "Implement claude command for managing .mcp.json files and project command for project management.",
|
|
"testStrategy": "Test .mcp.json file generation. Test project switching. Verify file permissions are correct.",
|
|
"priority": "medium",
|
|
"dependencies": [
|
|
"7",
|
|
"5"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": []
|
|
},
|
|
{
|
|
"id": "11",
|
|
"title": "Design Local LLM Proxy Architecture",
|
|
"description": "Design the architecture for the local LLM proxy that enables Claude to use MCP servers through a local intermediary.",
|
|
"details": "Design proxy architecture in src/local-proxy/ with MCP protocol handling and request/response transformation.",
|
|
"testStrategy": "Architecture review. Document security considerations. Create proof-of-concept for MCP protocol handling.",
|
|
"priority": "medium",
|
|
"dependencies": [
|
|
"1"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": []
|
|
},
|
|
{
|
|
"id": "12",
|
|
"title": "Implement Local LLM Proxy Core",
|
|
"description": "Build the core local proxy server that handles MCP protocol communication between Claude and MCP servers.",
|
|
"details": "Implement proxy server in src/local-proxy/src/ with MCP SDK integration and request routing.",
|
|
"testStrategy": "Test MCP protocol parsing. Test request routing. Integration test with actual MCP server.",
|
|
"priority": "medium",
|
|
"dependencies": [
|
|
"11"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": []
|
|
},
|
|
{
|
|
"id": "13",
|
|
"title": "Implement LLM Provider Strategy Pattern",
|
|
"description": "Create pluggable LLM provider support with strategy pattern for different providers (OpenAI, Anthropic, local models).",
|
|
"details": "Implement provider strategy pattern in src/local-proxy/src/providers/ with adapters for different LLM APIs.",
|
|
"testStrategy": "Test each provider adapter. Test provider switching. Mock API responses for testing.",
|
|
"priority": "low",
|
|
"dependencies": [
|
|
"12"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": []
|
|
},
|
|
{
|
|
"id": "14",
|
|
"title": "Implement Audit Logging and Compliance",
|
|
"description": "Create comprehensive audit logging system for tracking all MCP operations for compliance and debugging.",
|
|
"details": "Implement audit logging in src/mcpd/src/services/ with structured logging, retention policies, and query APIs.",
|
|
"testStrategy": "Test audit log creation. Test query APIs. Verify log retention works correctly.",
|
|
"priority": "medium",
|
|
"dependencies": [
|
|
"3"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": []
|
|
},
|
|
{
|
|
"id": "15",
|
|
"title": "Create MCP Profiles Library",
|
|
"description": "Build a library of pre-configured MCP profiles for common use cases with best practices baked in.",
|
|
"details": "Create profile library in src/shared/src/profiles/ with templates for common MCP server configurations.",
|
|
"testStrategy": "Test profile templates are valid. Test profile application. Document each profile's use case.",
|
|
"priority": "low",
|
|
"dependencies": [
|
|
"4"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": []
|
|
},
|
|
{
|
|
"id": "16",
|
|
"title": "Implement MCP Instance Lifecycle Management",
|
|
"description": "Create APIs and CLI commands for managing the full lifecycle of MCP server instances.",
|
|
"details": "Implement instance lifecycle management in src/mcpd/src/services/ with start, stop, restart, logs commands.",
|
|
"testStrategy": "Test instance state transitions. Test concurrent instance management. Integration test with Docker.",
|
|
"priority": "medium",
|
|
"dependencies": [
|
|
"6"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": []
|
|
},
|
|
{
|
|
"id": "17",
|
|
"title": "Add Kubernetes Deployment Support",
|
|
"description": "Extend the orchestration layer to support Kubernetes deployments for production environments.",
|
|
"details": "Implement KubernetesOrchestrator in src/mcpd/src/services/k8s/ implementing McpOrchestrator interface.",
|
|
"testStrategy": "Test Kubernetes manifest generation. Test with kind/minikube. Verify resource limits and security contexts.",
|
|
"priority": "low",
|
|
"dependencies": [
|
|
"6"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": []
|
|
},
|
|
{
|
|
"id": "18",
|
|
"title": "Documentation and Testing",
|
|
"description": "Create comprehensive documentation and end-to-end test suite for the entire mcpctl system.",
|
|
"details": "Create documentation in docs/ and e2e tests in tests/e2e/ covering all major workflows.",
|
|
"testStrategy": "Review documentation for completeness. Run e2e test suite. Test installation instructions.",
|
|
"priority": "medium",
|
|
"dependencies": [
|
|
"7",
|
|
"8",
|
|
"9",
|
|
"10"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": []
|
|
},
|
|
{
|
|
"id": "19",
|
|
"title": "CANCELLED - Auth middleware",
|
|
"description": "Merged into Task 3 subtasks",
|
|
"details": null,
|
|
"testStrategy": null,
|
|
"priority": "low",
|
|
"dependencies": [],
|
|
"status": "cancelled",
|
|
"subtasks": [],
|
|
"updatedAt": "2026-02-21T02:21:03.958Z"
|
|
},
|
|
{
|
|
"id": "20",
|
|
"title": "CANCELLED - Duplicate project management",
|
|
"description": "Merged into Task 5",
|
|
"details": null,
|
|
"testStrategy": null,
|
|
"priority": "low",
|
|
"dependencies": [],
|
|
"status": "cancelled",
|
|
"subtasks": [],
|
|
"updatedAt": "2026-02-21T02:21:03.966Z"
|
|
},
|
|
{
|
|
"id": "21",
|
|
"title": "CANCELLED - Duplicate audit logging",
|
|
"description": "Merged into Task 14",
|
|
"details": null,
|
|
"testStrategy": null,
|
|
"priority": "low",
|
|
"dependencies": [],
|
|
"status": "cancelled",
|
|
"subtasks": [],
|
|
"updatedAt": "2026-02-21T02:21:03.972Z"
|
|
},
|
|
{
|
|
"id": "22",
|
|
"title": "Implement Health Monitoring Dashboard",
|
|
"description": "Create a monitoring dashboard for tracking MCP server health, resource usage, and system metrics.",
|
|
"details": "Implement health monitoring endpoints in src/mcpd/src/routes/ and optional web dashboard.",
|
|
"testStrategy": "Test health check endpoints. Test metrics collection. Verify dashboard displays correct data.",
|
|
"priority": "low",
|
|
"dependencies": [
|
|
"6",
|
|
"14"
|
|
],
|
|
"status": "cancelled",
|
|
"subtasks": [],
|
|
"updatedAt": "2026-02-21T03:23:02.572Z"
|
|
},
|
|
{
|
|
"id": "23",
|
|
"title": "Implement Backup and Restore",
|
|
"description": "Create backup and restore functionality for mcpctl configuration and state.",
|
|
"details": "Implement git-based backup in src/mcpd/src/services/backup/ with encrypted secrets and restore capability.",
|
|
"testStrategy": "Test backup creation. Test restore from backup. Verify secrets are encrypted.",
|
|
"priority": "low",
|
|
"dependencies": [
|
|
"2",
|
|
"5"
|
|
],
|
|
"status": "cancelled",
|
|
"subtasks": [],
|
|
"updatedAt": "2026-02-21T03:23:02.575Z"
|
|
},
|
|
{
|
|
"id": "24",
|
|
"title": "CI/CD Pipeline Setup",
|
|
"description": "Set up continuous integration and deployment pipelines for the mcpctl project.",
|
|
"details": "Create GitHub Actions workflows in .github/workflows/ for testing, building, and releasing.",
|
|
"testStrategy": "Test CI pipeline runs successfully. Test release automation. Verify artifacts are published.",
|
|
"priority": "medium",
|
|
"dependencies": [
|
|
"1"
|
|
],
|
|
"status": "cancelled",
|
|
"subtasks": [],
|
|
"updatedAt": "2026-02-21T03:23:02.583Z"
|
|
},
|
|
{
|
|
"id": "25",
|
|
"title": "Complete MCP Registry Client with Proxy, Metrics Exposure, and HTTP/CA Support",
|
|
"description": "Finalize the registry client implementation by adding HTTP proxy support, custom CA certificates for enterprise environments, and exposing SRE metrics via a dedicated metrics interface. The core client with strategy pattern, caching, deduplication, and ranking is already implemented.",
|
|
"details": "The registry client foundation already exists in src/cli/src/registry/ with:\n- RegistryClient class with search(), caching, metrics tracking\n- OfficialRegistrySource, GlamaRegistrySource, SmitheryRegistrySource\n- Deduplication by npm package/repo URL\n- Ranking by relevance, popularity, verified status\n- Zod validation of API responses\n- sanitizeString() for XSS prevention\n\nRemaining implementation:\n\n1. **HTTP Proxy & Custom CA Support** (src/cli/src/registry/http-agent.ts):\n```typescript\nimport { Agent } from 'undici';\nimport { ProxyAgent } from 'undici';\nimport fs from 'node:fs';\n\nexport function createHttpAgent(config: {\n httpProxy?: string;\n httpsProxy?: string;\n caPath?: string;\n}): Agent | ProxyAgent | undefined {\n const proxy = config.httpsProxy ?? config.httpProxy;\n if (proxy) {\n const ca = config.caPath ? fs.readFileSync(config.caPath) : undefined;\n return new ProxyAgent({ uri: proxy, connect: { ca } });\n }\n if (config.caPath) {\n const ca = fs.readFileSync(config.caPath);\n return new Agent({ connect: { ca } });\n }\n return undefined;\n}\n```\n\n2. **Update fetch calls** in each source to accept dispatcher option:\n```typescript\n// In retry.ts or each source\nconst agent = createHttpAgent(config);\nconst response = await fetch(url, { dispatcher: agent });\n```\n\n3. **Metrics Exposure Interface** (src/cli/src/registry/metrics.ts):\n```typescript\nexport interface RegistryMetrics {\n queryLatencyMs: { source: string; latencies: number[] }[];\n cacheHitRatio: number;\n cacheHits: number;\n cacheMisses: number;\n errorCounts: { source: string; count: number }[];\n}\n\nexport function collectMetrics(client: RegistryClient): RegistryMetrics {\n const cacheMetrics = client.getCacheMetrics();\n return {\n queryLatencyMs: Array.from(client.getQueryLatencies().entries())\n .map(([source, latencies]) => ({ source, latencies })),\n cacheHitRatio: cacheMetrics.ratio,\n cacheHits: cacheMetrics.hits,\n cacheMisses: cacheMetrics.misses,\n errorCounts: Array.from(client.getErrorCounts().entries())\n .map(([source, count]) => ({ source, count })),\n };\n}\n```\n\n4. **Update RegistryClientConfig** to include caPath:\n```typescript\nexport interface RegistryClientConfig {\n registries?: RegistryName[];\n cacheTTLMs?: number;\n smitheryApiKey?: string;\n httpProxy?: string;\n httpsProxy?: string;\n caPath?: string; // ADD THIS\n}\n```\n\n5. **Add data platform category filter** - update SearchOptions:\n```typescript\ncategory?: 'devops' | 'data-platform' | 'analytics' | 'communication' | 'development' | string;\n```\n\nTDD approach:\n- Write tests for createHttpAgent() with proxy, CA, and combined configs\n- Write tests for metrics collection interface\n- Write tests for category filtering in search results\n- All tests should be written BEFORE implementation",
|
|
"testStrategy": "1. Unit tests for http-agent.ts: verify ProxyAgent created with correct proxy URI, verify custom CA loaded from file path, verify combined proxy+CA configuration\n2. Unit tests for metrics.ts: verify collectMetrics() returns correct structure, verify latency arrays are captured per-source\n3. Integration test: mock HTTP server with self-signed cert, verify client connects with custom CA\n4. Test category filtering returns only servers matching category\n5. Run existing test suite to ensure no regressions: pnpm --filter @mcpctl/cli test",
|
|
"priority": "high",
|
|
"dependencies": [],
|
|
"status": "done",
|
|
"subtasks": [],
|
|
"updatedAt": "2026-02-21T03:52:54.909Z"
|
|
},
|
|
{
|
|
"id": "26",
|
|
"title": "Implement mcpctl discover Command with Interactive Mode",
|
|
"description": "Create the `mcpctl discover` CLI command that lets users search for MCP servers across all configured registries with rich filtering, table/JSON/YAML output, and an interactive browsing mode using inquirer.",
|
|
"details": "Create src/cli/src/commands/discover.ts with Commander.js:\n\n```typescript\nimport { Command } from 'commander';\nimport { RegistryClient, type SearchOptions, type RegistryServer } from '../registry/index.js';\nimport { getConfig } from '../config/index.js';\nimport inquirer from 'inquirer';\nimport chalk from 'chalk';\n\nexport function createDiscoverCommand(): Command {\n return new Command('discover')\n .description('Search for MCP servers across registries')\n .argument('<query>', 'Search query (e.g., \"slack\", \"database\", \"terraform\")')\n .option('-c, --category <category>', 'Filter by category (devops, data-platform, analytics)')\n .option('-v, --verified', 'Only show verified servers')\n .option('-t, --transport <type>', 'Filter by transport (stdio, sse)', undefined)\n .option('-r, --registry <registry>', 'Query specific registry (official, glama, smithery, all)', 'all')\n .option('-l, --limit <n>', 'Maximum results', '20')\n .option('-o, --output <format>', 'Output format (table, json, yaml)', 'table')\n .option('-i, --interactive', 'Interactive browsing mode')\n .action(async (query, options) => {\n const config = await getConfig();\n const client = new RegistryClient({\n smitheryApiKey: config.smitheryApiKey,\n httpProxy: config.httpProxy,\n httpsProxy: config.httpsProxy,\n caPath: config.caPath,\n });\n\n const searchOpts: SearchOptions = {\n query,\n limit: parseInt(options.limit, 10),\n verified: options.verified,\n transport: options.transport,\n category: options.category,\n registries: options.registry === 'all' \n ? undefined \n : [options.registry],\n };\n\n const results = await client.search(searchOpts);\n\n if (results.length === 0) {\n console.log('No servers found matching your query.');\n process.exitCode = 2;\n return;\n }\n\n if (options.interactive) {\n await runInteractiveMode(results);\n } else {\n outputResults(results, options.output);\n }\n });\n}\n\nfunction outputResults(results: RegistryServer[], format: string): void {\n switch (format) {\n case 'json':\n console.log(JSON.stringify(results, null, 2));\n break;\n case 'yaml':\n // Use yaml library\n import('yaml').then(yaml => console.log(yaml.stringify(results)));\n break;\n default:\n printTable(results);\n }\n}\n\nfunction printTable(results: RegistryServer[]): void {\n console.log('NAME'.padEnd(30) + 'DESCRIPTION'.padEnd(50) + 'PACKAGE'.padEnd(35) + 'TRANSPORT VERIFIED POPULARITY');\n console.log('-'.repeat(140));\n for (const s of results) {\n const pkg = s.packages.npm ?? s.packages.pypi ?? s.packages.docker ?? '-';\n const verified = s.verified ? chalk.green('✓') : '-';\n console.log(\n s.name.slice(0, 28).padEnd(30) +\n s.description.slice(0, 48).padEnd(50) +\n pkg.slice(0, 33).padEnd(35) +\n s.transport.padEnd(11) +\n verified.padEnd(10) +\n String(s.popularityScore)\n );\n }\n console.log(`\\nRun 'mcpctl install <name>' to set up a server.`);\n}\n\nasync function runInteractiveMode(results: RegistryServer[]): Promise<void> {\n const { selected } = await inquirer.prompt([{\n type: 'list',\n name: 'selected',\n message: 'Select an MCP server to install:',\n choices: results.map(s => ({\n name: `${s.name} - ${s.description.slice(0, 60)}`,\n value: s,\n })),\n }]);\n\n const { action } = await inquirer.prompt([{\n type: 'list',\n name: 'action',\n message: `What would you like to do with ${selected.name}?`,\n choices: [\n { name: 'Install and configure', value: 'install' },\n { name: 'View details', value: 'details' },\n { name: 'Cancel', value: 'cancel' },\n ],\n }]);\n\n if (action === 'install') {\n // Invoke install command programmatically\n const { execSync } = await import('node:child_process');\n execSync(`mcpctl install ${selected.name}`, { stdio: 'inherit' });\n } else if (action === 'details') {\n console.log(JSON.stringify(selected, null, 2));\n }\n}\n```\n\nRegister command in src/cli/src/commands/index.ts.\n\nExit codes for scripting:\n- 0: Results found\n- 1: Error occurred\n- 2: No results found\n\nTDD: Write all tests BEFORE implementation:\n- Test command parsing with all options\n- Test table output formatting\n- Test JSON/YAML output\n- Test exit codes\n- Mock inquirer for interactive mode tests",
|
|
"testStrategy": "1. Unit tests (src/cli/tests/commands/discover.test.ts):\n - Test argument parsing: verify query is required, options have defaults\n - Test table output: mock RegistryClient, verify correct columns printed\n - Test JSON output: verify valid JSON with all fields\n - Test YAML output: verify valid YAML structure\n - Test --verified filter is passed to client\n - Test --registry parses correctly\n2. Integration tests:\n - Mock registry sources, run full discover command, verify output\n - Test exit code 2 when no results\n - Test exit code 1 on network error\n3. Interactive mode tests:\n - Mock inquirer responses, verify correct server selected\n - Verify install command invoked with correct name\n4. Run: pnpm --filter @mcpctl/cli test",
|
|
"priority": "high",
|
|
"dependencies": [
|
|
"25"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": []
|
|
},
|
|
{
|
|
"id": "27",
|
|
"title": "Implement mcpctl install with LLM-Assisted Auto-Configuration",
|
|
"description": "Create the `mcpctl install <server-name>` command that uses a local LLM (Claude Code session, Ollama, or configured provider) to automatically analyze MCP server READMEs, generate envTemplate and setup guides, walk users through configuration, and register the server in mcpd.",
|
|
"details": "Create src/cli/src/commands/install.ts:\n\n```typescript\nimport { Command } from 'commander';\nimport { RegistryClient, type RegistryServer, type EnvVar } from '../registry/index.js';\nimport { getConfig } from '../config/index.js';\nimport { z } from 'zod';\nimport inquirer from 'inquirer';\n\n// Zod schema for validating LLM-generated envTemplate\nconst LLMEnvVarSchema = z.object({\n name: z.string().min(1),\n description: z.string(),\n isSecret: z.boolean(),\n setupUrl: z.string().url().optional(),\n defaultValue: z.string().optional(),\n});\n\nconst LLMConfigResponseSchema = z.object({\n envTemplate: z.array(LLMEnvVarSchema),\n setupGuide: z.array(z.string()),\n defaultProfiles: z.array(z.object({\n name: z.string(),\n permissions: z.array(z.string()),\n })).optional().default([]),\n});\n\nexport type LLMConfigResponse = z.infer<typeof LLMConfigResponseSchema>;\n\nexport function createInstallCommand(): Command {\n return new Command('install')\n .description('Install and configure an MCP server')\n .argument('<servers...>', 'Server name(s) from discover results')\n .option('--non-interactive', 'Use env vars for credentials (no prompts)')\n .option('--profile-name <name>', 'Name for the created profile')\n .option('--project <name>', 'Add to existing project after install')\n .option('--dry-run', 'Show configuration without applying')\n .option('--skip-llm', 'Skip LLM analysis, use registry metadata only')\n .action(async (servers, options) => {\n for (const serverName of servers) {\n await installServer(serverName, options);\n }\n });\n}\n\nasync function installServer(serverName: string, options: {\n nonInteractive?: boolean;\n profileName?: string;\n project?: string;\n dryRun?: boolean;\n skipLlm?: boolean;\n}): Promise<void> {\n const config = await getConfig();\n const client = new RegistryClient(config);\n\n // Step 1: Fetch server metadata from registry\n console.log(`Searching for ${serverName}...`);\n const results = await client.search({ query: serverName, limit: 10 });\n const server = results.find(s => \n s.name.toLowerCase() === serverName.toLowerCase() ||\n s.packages.npm?.includes(serverName)\n );\n\n if (!server) {\n console.error(`Server \"${serverName}\" not found. Run 'mcpctl discover ${serverName}' to search.`);\n process.exitCode = 1;\n return;\n }\n\n console.log(`Found: ${server.name} (${server.packages.npm ?? server.packages.docker ?? 'N/A'})`);\n\n // Step 2: Determine envTemplate\n let envTemplate: EnvVar[] = server.envTemplate;\n let setupGuide: string[] = [];\n\n // Step 3: If envTemplate incomplete and LLM not skipped, use LLM\n if (envTemplate.length === 0 && !options.skipLlm && server.repositoryUrl) {\n console.log('Registry metadata incomplete. Analyzing README with LLM...');\n const llmConfig = await analyzeWithLLM(server.repositoryUrl, config);\n if (llmConfig) {\n envTemplate = llmConfig.envTemplate;\n setupGuide = llmConfig.setupGuide;\n }\n }\n\n // Step 4: Show setup guide if available\n if (setupGuide.length > 0) {\n console.log('\\n📋 Setup Guide:');\n setupGuide.forEach((step, i) => console.log(` ${i + 1}. ${step}`));\n console.log('');\n }\n\n if (options.dryRun) {\n console.log('Dry run - would configure:');\n console.log(JSON.stringify({ server, envTemplate }, null, 2));\n return;\n }\n\n // Step 5: Collect credentials\n const credentials: Record<string, string> = {};\n if (!options.nonInteractive) {\n for (const env of envTemplate) {\n const { value } = await inquirer.prompt([{\n type: env.isSecret ? 'password' : 'input',\n name: 'value',\n message: `${env.name}${env.description ? ` (${env.description})` : ''}:`,\n default: env.defaultValue,\n }]);\n credentials[env.name] = value;\n }\n } else {\n // Use environment variables\n for (const env of envTemplate) {\n credentials[env.name] = process.env[env.name] ?? env.defaultValue ?? '';\n }\n }\n\n // Step 6: Register with mcpd (mock for now until mcpd integration)\n console.log(`\\nRegistering ${server.name} with mcpd...`);\n // TODO: POST to mcpd /api/mcp-servers when mcpd is implemented\n // For now, write to local config\n await saveServerConfig(server, credentials, options.profileName ?? server.name);\n\n // Step 7: Add to project if specified\n if (options.project) {\n console.log(`Adding to project: ${options.project}`);\n // TODO: Call mcpd project API\n }\n\n console.log(`\\n✅ ${server.name} installed successfully!`);\n console.log(`Run 'mcpctl get servers' to see installed servers.`);\n}\n\nasync function analyzeWithLLM(repoUrl: string, config: any): Promise<LLMConfigResponse | null> {\n try {\n // Fetch README from GitHub\n const readmeUrl = convertToRawReadmeUrl(repoUrl);\n const response = await fetch(readmeUrl);\n if (!response.ok) {\n console.warn('Could not fetch README.');\n return null;\n }\n const readme = await response.text();\n\n // Sanitize README - prevent prompt injection\n const sanitizedReadme = sanitizeReadme(readme);\n\n // Use configured LLM provider (Ollama, OpenAI, etc. from Task 12)\n // For Claude Code integration, output prompt for user to paste\n const prompt = buildLLMPrompt(sanitizedReadme);\n \n // TODO: Integrate with actual LLM provider from Task 12\n // For now, attempt Ollama if configured\n const llmResponse = await callLLM(prompt, config);\n \n // Parse and validate response\n const parsed = JSON.parse(llmResponse);\n return LLMConfigResponseSchema.parse(parsed);\n } catch (error) {\n console.warn('LLM analysis failed, using registry metadata only.');\n return null;\n }\n}\n\nfunction buildLLMPrompt(readme: string): string {\n return `Analyze this MCP server README and extract configuration requirements.\n\nRETURN ONLY VALID JSON matching this schema:\n{\n \"envTemplate\": [{ \"name\": string, \"description\": string, \"isSecret\": boolean, \"setupUrl\"?: string }],\n \"setupGuide\": [\"Step 1...\", \"Step 2...\"],\n \"defaultProfiles\": [{ \"name\": string, \"permissions\": string[] }]\n}\n\nREADME content (trusted, from official repository):\n${readme.slice(0, 8000)}\n\nJSON output:`;\n}\n\nfunction sanitizeReadme(readme: string): string {\n // Remove potential prompt injection patterns\n return readme\n .replace(/ignore.*instructions/gi, '')\n .replace(/disregard.*above/gi, '')\n .replace(/system.*prompt/gi, '');\n}\n\nfunction convertToRawReadmeUrl(repoUrl: string): string {\n // Convert GitHub repo URL to raw README URL\n const match = repoUrl.match(/github\\.com\\/([^/]+)\\/([^/]+)/);\n if (match) {\n return `https://raw.githubusercontent.com/${match[1]}/${match[2]}/main/README.md`;\n }\n return repoUrl;\n}\n\nasync function callLLM(prompt: string, config: any): Promise<string> {\n // Try Ollama first if available\n if (config.ollamaUrl) {\n const response = await fetch(`${config.ollamaUrl}/api/generate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: config.ollamaModel ?? 'llama3',\n prompt,\n stream: false,\n }),\n });\n const data = await response.json();\n return data.response;\n }\n throw new Error('No LLM provider configured. Set OLLAMA_URL or use --skip-llm.');\n}\n\nasync function saveServerConfig(server: RegistryServer, credentials: Record<string, string>, profileName: string): Promise<void> {\n // Save to ~/.mcpctl/servers/<name>.json\n const fs = await import('node:fs/promises');\n const path = await import('node:path');\n const os = await import('node:os');\n \n const configDir = path.join(os.homedir(), '.mcpctl', 'servers');\n await fs.mkdir(configDir, { recursive: true });\n \n await fs.writeFile(\n path.join(configDir, `${profileName}.json`),\n JSON.stringify({ server, credentials, createdAt: new Date().toISOString() }, null, 2)\n );\n}\n```\n\nSecurity considerations:\n- sanitizeReadme() removes prompt injection patterns\n- LLM responses validated against Zod schema before use\n- Never auto-execute commands suggested by LLM\n- Credentials stored in separate secure config (encrypted via Task 7.2)\n\nTDD: Write comprehensive tests BEFORE implementation.",
|
|
"testStrategy": "1. Unit tests (src/cli/tests/commands/install.test.ts):\n - Test server lookup from registry results\n - Test LLMConfigResponseSchema validates correct JSON\n - Test LLMConfigResponseSchema rejects invalid JSON\n - Test sanitizeReadme() removes injection patterns\n - Test buildLLMPrompt() generates valid prompt structure\n - Test convertToRawReadmeUrl() for various GitHub URL formats\n - Test --dry-run outputs config without saving\n - Test --non-interactive uses env vars\n - Test batch install: multiple servers processed sequentially\n2. Security tests:\n - Test sanitizeReadme blocks 'ignore all instructions'\n - Test LLM response with extra fields is safely parsed\n - Test credentials are not logged\n3. Integration tests:\n - Mock registry client and LLM endpoint\n - Full install flow with mocked dependencies\n - Verify server config file created with correct structure\n4. Run: pnpm --filter @mcpctl/cli test",
|
|
"priority": "high",
|
|
"dependencies": [
|
|
"25",
|
|
"26"
|
|
],
|
|
"status": "pending",
|
|
"subtasks": []
|
|
}
|
|
],
|
|
"metadata": {
|
|
"version": "1.0.0",
|
|
"lastModified": "2026-02-21T03:52:54.909Z",
|
|
"taskCount": 27,
|
|
"completedCount": 2,
|
|
"tags": [
|
|
"master"
|
|
]
|
|
}
|
|
}
|
|
} |