411 lines
13 KiB
Markdown
411 lines
13 KiB
Markdown
|
|
# Task ID: 1
|
||
|
|
|
||
|
|
**Title:** Initialize Project Structure and Core Dependencies
|
||
|
|
|
||
|
|
**Status:** pending
|
||
|
|
|
||
|
|
**Dependencies:** None
|
||
|
|
|
||
|
|
**Priority:** high
|
||
|
|
|
||
|
|
**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:
|
||
|
|
|
||
|
|
```
|
||
|
|
mcpctl/
|
||
|
|
├── src/
|
||
|
|
│ ├── cli/ # mcpctl CLI tool
|
||
|
|
│ ├── mcpd/ # Backend daemon server
|
||
|
|
│ ├── shared/ # Shared types, utilities, constants
|
||
|
|
│ └── local-proxy/ # Local LLM proxy component
|
||
|
|
├── docker/
|
||
|
|
│ └── docker-compose.yml
|
||
|
|
├── package.json
|
||
|
|
├── tsconfig.base.json
|
||
|
|
└── pnpm-workspace.yaml
|
||
|
|
```
|
||
|
|
|
||
|
|
Dependencies to install:
|
||
|
|
- TypeScript 5.x
|
||
|
|
- Commander.js for CLI
|
||
|
|
- Express/Fastify for mcpd HTTP server
|
||
|
|
- Zod for schema validation
|
||
|
|
- Winston/Pino for logging
|
||
|
|
- Prisma or Drizzle for database ORM
|
||
|
|
|
||
|
|
Create base tsconfig.json with strict mode, ES2022 target, and module resolution settings. Set up shared ESLint config with TypeScript rules.
|
||
|
|
|
||
|
|
**Test Strategy:**
|
||
|
|
|
||
|
|
Verify project builds successfully with `pnpm build`. Ensure all packages compile without errors. Test workspace linking works correctly between packages.
|
||
|
|
|
||
|
|
## Subtasks
|
||
|
|
|
||
|
|
### 1.1. Initialize pnpm workspace monorepo with future-proof directory structure
|
||
|
|
|
||
|
|
**Status:** pending
|
||
|
|
**Dependencies:** None
|
||
|
|
|
||
|
|
Create the complete monorepo directory structure using pnpm workspaces that accommodates all 18 planned tasks without requiring future refactoring.
|
||
|
|
|
||
|
|
**Details:**
|
||
|
|
|
||
|
|
Create root package.json with pnpm workspaces configuration. Create pnpm-workspace.yaml defining all workspace packages. Initialize the following directory structure:
|
||
|
|
|
||
|
|
```
|
||
|
|
mcpctl/
|
||
|
|
├── src/
|
||
|
|
│ ├── cli/ # mcpctl CLI tool (Task 7-10)
|
||
|
|
│ │ ├── src/
|
||
|
|
│ │ ├── tests/
|
||
|
|
│ │ └── package.json
|
||
|
|
│ ├── mcpd/ # Backend daemon server (Task 3-6, 14, 16)
|
||
|
|
│ │ ├── src/
|
||
|
|
│ │ ├── tests/
|
||
|
|
│ │ └── package.json
|
||
|
|
│ ├── shared/ # Shared types, utils, constants, validation
|
||
|
|
│ │ ├── src/
|
||
|
|
│ │ │ ├── types/ # TypeScript interfaces/types
|
||
|
|
│ │ │ ├── utils/ # Utility functions
|
||
|
|
│ │ │ ├── constants/# Shared constants
|
||
|
|
│ │ │ ├── validation/ # Zod schemas
|
||
|
|
│ │ │ └── index.ts # Barrel export
|
||
|
|
│ │ ├── tests/
|
||
|
|
│ │ └── package.json
|
||
|
|
│ ├── local-proxy/ # Local LLM proxy (Task 11-13)
|
||
|
|
│ │ ├── src/
|
||
|
|
│ │ ├── tests/
|
||
|
|
│ │ └── package.json
|
||
|
|
│ └── db/ # Database package (Task 2)
|
||
|
|
│ ├── src/
|
||
|
|
│ ├── prisma/ # Schema and migrations
|
||
|
|
│ ├── seed/ # Seed data
|
||
|
|
│ ├── tests/
|
||
|
|
│ └── package.json
|
||
|
|
├── docker/
|
||
|
|
│ └── docker-compose.yml # Local dev services (postgres)
|
||
|
|
├── tests/
|
||
|
|
│ ├── e2e/ # End-to-end tests (Task 18)
|
||
|
|
│ └── integration/ # Integration tests
|
||
|
|
├── docs/ # Documentation (Task 18)
|
||
|
|
├── package.json # Root workspace config
|
||
|
|
├── pnpm-workspace.yaml
|
||
|
|
└── turbo.json # Optional: Turborepo for build orchestration
|
||
|
|
```
|
||
|
|
|
||
|
|
Each package should have:
|
||
|
|
- Empty src/index.ts with barrel export pattern ready
|
||
|
|
- Empty tests/ directory
|
||
|
|
- package.json with correct workspace dependencies (@mcpctl/shared, @mcpctl/db)
|
||
|
|
|
||
|
|
Use dependency injection patterns from the start by creating interfaces in shared/src/types/ for key services.
|
||
|
|
<info added on 2026-02-21T02:33:52.473Z>
|
||
|
|
CRITICAL STRUCTURAL CHANGE: The monorepo workspace packages directory has been renamed from `packages/` to `src/`. All path references in this subtask must use `src/` instead of `packages/`.
|
||
|
|
|
||
|
|
Updated directory structure to implement:
|
||
|
|
|
||
|
|
```
|
||
|
|
mcpctl/
|
||
|
|
├── src/ # All application source code (pnpm workspace packages)
|
||
|
|
│ ├── cli/ # @mcpctl/cli - CLI tool (Task 7-10)
|
||
|
|
│ │ ├── src/
|
||
|
|
│ │ ├── tests/
|
||
|
|
│ │ └── package.json
|
||
|
|
│ ├── mcpd/ # @mcpctl/mcpd - Backend daemon (Task 3-6, 14, 16)
|
||
|
|
│ │ ├── src/
|
||
|
|
│ │ ├── tests/
|
||
|
|
│ │ └── package.json
|
||
|
|
│ ├── shared/ # @mcpctl/shared - Shared types, utils, constants, validation
|
||
|
|
│ │ ├── src/
|
||
|
|
│ │ │ ├── types/ # TypeScript interfaces/types
|
||
|
|
│ │ │ ├── utils/ # Utility functions
|
||
|
|
│ │ │ ├── constants/ # Shared constants
|
||
|
|
│ │ │ ├── validation/ # Zod schemas
|
||
|
|
│ │ │ └── index.ts # Barrel export
|
||
|
|
│ │ ├── tests/
|
||
|
|
│ │ └── package.json
|
||
|
|
│ ├── local-proxy/ # @mcpctl/local-proxy - LLM proxy (Task 11-13)
|
||
|
|
│ │ ├── src/
|
||
|
|
│ │ ├── tests/
|
||
|
|
│ │ └── package.json
|
||
|
|
│ └── db/ # @mcpctl/db - Database/Prisma (Task 2)
|
||
|
|
│ ├── src/
|
||
|
|
│ ├── prisma/ # Schema and migrations
|
||
|
|
│ ├── seed/ # Seed data
|
||
|
|
│ ├── tests/
|
||
|
|
│ └── package.json
|
||
|
|
├── deploy/ # Deployment configs (docker-compose, k8s manifests)
|
||
|
|
│ ├── docker-compose.yml
|
||
|
|
│ ├── docker-compose.dev.yml
|
||
|
|
│ └── Dockerfile.*
|
||
|
|
├── docs/ # Documentation (Task 18)
|
||
|
|
├── tests/ # E2E and integration tests
|
||
|
|
│ ├── e2e/
|
||
|
|
│ └── integration/
|
||
|
|
├── package.json # Root workspace config
|
||
|
|
├── pnpm-workspace.yaml # Points to src/*
|
||
|
|
├── tsconfig.base.json
|
||
|
|
├── eslint.config.js
|
||
|
|
├── vitest.workspace.ts
|
||
|
|
└── turbo.json # Optional: Turborepo for build orchestration
|
||
|
|
```
|
||
|
|
|
||
|
|
The pnpm-workspace.yaml should contain: `packages: ["src/*"]`
|
||
|
|
|
||
|
|
Key differences from previous structure:
|
||
|
|
- `packages/` renamed to `src/` for cleaner separation of app source from project management files
|
||
|
|
- `docker/` renamed to `deploy/` with additional files (docker-compose.dev.yml, Dockerfile.*)
|
||
|
|
- Added root config files: eslint.config.js, vitest.workspace.ts
|
||
|
|
- All workspace package references in pnpm-workspace.yaml use `src/*` pattern
|
||
|
|
</info added on 2026-02-21T02:33:52.473Z>
|
||
|
|
|
||
|
|
### 1.2. Configure TypeScript with strict mode and project references
|
||
|
|
|
||
|
|
**Status:** pending
|
||
|
|
**Dependencies:** 1.1
|
||
|
|
|
||
|
|
Set up TypeScript configuration with strict mode, ES2022 target, and proper project references for monorepo build orchestration.
|
||
|
|
|
||
|
|
**Details:**
|
||
|
|
|
||
|
|
Create root tsconfig.base.json with shared compiler options:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"compilerOptions": {
|
||
|
|
"target": "ES2022",
|
||
|
|
"module": "NodeNext",
|
||
|
|
"moduleResolution": "NodeNext",
|
||
|
|
"lib": ["ES2022"],
|
||
|
|
"strict": true,
|
||
|
|
"esModuleInterop": true,
|
||
|
|
"skipLibCheck": true,
|
||
|
|
"forceConsistentCasingInFileNames": true,
|
||
|
|
"declaration": true,
|
||
|
|
"declarationMap": true,
|
||
|
|
"sourceMap": true,
|
||
|
|
"composite": true,
|
||
|
|
"incremental": true,
|
||
|
|
"noUnusedLocals": true,
|
||
|
|
"noUnusedParameters": true,
|
||
|
|
"noImplicitReturns": true,
|
||
|
|
"noFallthroughCasesInSwitch": true,
|
||
|
|
"exactOptionalPropertyTypes": true,
|
||
|
|
"noUncheckedIndexedAccess": true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
Create package-specific tsconfig.json in each package that extends the base and sets appropriate paths:
|
||
|
|
- cli/tsconfig.json: outDir: dist, references to shared and db
|
||
|
|
- mcpd/tsconfig.json: outDir: dist, references to shared and db
|
||
|
|
- shared/tsconfig.json: outDir: dist (no references, it's the base)
|
||
|
|
- local-proxy/tsconfig.json: references to shared
|
||
|
|
- db/tsconfig.json: references to shared
|
||
|
|
|
||
|
|
Create tsconfig.json at root with project references to all packages for unified builds.
|
||
|
|
|
||
|
|
Install TypeScript 5.x as devDependency in root package.json.
|
||
|
|
|
||
|
|
### 1.3. Set up Vitest testing framework with workspace configuration
|
||
|
|
|
||
|
|
**Status:** pending
|
||
|
|
**Dependencies:** 1.2
|
||
|
|
|
||
|
|
Configure Vitest as the test framework across all packages with proper workspace setup, coverage reporting, and test-driven development infrastructure.
|
||
|
|
|
||
|
|
**Details:**
|
||
|
|
|
||
|
|
Install Vitest and related packages at root level:
|
||
|
|
- vitest
|
||
|
|
- @vitest/coverage-v8
|
||
|
|
- @vitest/ui (optional, for visual test running)
|
||
|
|
|
||
|
|
Create root vitest.config.ts:
|
||
|
|
```typescript
|
||
|
|
import { defineConfig } from 'vitest/config';
|
||
|
|
|
||
|
|
export default defineConfig({
|
||
|
|
test: {
|
||
|
|
globals: true,
|
||
|
|
coverage: {
|
||
|
|
provider: 'v8',
|
||
|
|
reporter: ['text', 'json', 'html'],
|
||
|
|
exclude: ['**/node_modules/**', '**/dist/**', '**/*.config.*']
|
||
|
|
},
|
||
|
|
include: ['src/*/tests/**/*.test.ts', 'tests/**/*.test.ts'],
|
||
|
|
testTimeout: 10000
|
||
|
|
}
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
Create vitest.workspace.ts for workspace-aware testing:
|
||
|
|
```typescript
|
||
|
|
import { defineWorkspace } from 'vitest/config';
|
||
|
|
|
||
|
|
export default defineWorkspace([
|
||
|
|
'src/cli',
|
||
|
|
'src/mcpd',
|
||
|
|
'src/shared',
|
||
|
|
'src/local-proxy',
|
||
|
|
'src/db'
|
||
|
|
]);
|
||
|
|
```
|
||
|
|
|
||
|
|
Create per-package vitest.config.ts files that extend root config.
|
||
|
|
|
||
|
|
Add npm scripts to root package.json:
|
||
|
|
- "test": "vitest"
|
||
|
|
- "test:run": "vitest run"
|
||
|
|
- "test:coverage": "vitest run --coverage"
|
||
|
|
- "test:ui": "vitest --ui"
|
||
|
|
|
||
|
|
Create initial test file in src/shared/tests/index.test.ts to verify setup works:
|
||
|
|
```typescript
|
||
|
|
import { describe, it, expect } from 'vitest';
|
||
|
|
|
||
|
|
describe('shared package', () => {
|
||
|
|
it('should be configured correctly', () => {
|
||
|
|
expect(true).toBe(true);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
### 1.4. Configure ESLint with TypeScript rules and docker-compose for local development
|
||
|
|
|
||
|
|
**Status:** pending
|
||
|
|
**Dependencies:** 1.2
|
||
|
|
|
||
|
|
Set up shared ESLint configuration with TypeScript-aware rules, Prettier integration, and docker-compose.yml for local PostgreSQL database.
|
||
|
|
|
||
|
|
**Details:**
|
||
|
|
|
||
|
|
Install ESLint and plugins at root:
|
||
|
|
- eslint
|
||
|
|
- @typescript-eslint/parser
|
||
|
|
- @typescript-eslint/eslint-plugin
|
||
|
|
- eslint-config-prettier
|
||
|
|
- eslint-plugin-import
|
||
|
|
|
||
|
|
Create eslint.config.js (flat config, ESLint 9+):
|
||
|
|
```javascript
|
||
|
|
import tseslint from '@typescript-eslint/eslint-plugin';
|
||
|
|
import tsparser from '@typescript-eslint/parser';
|
||
|
|
|
||
|
|
export default [
|
||
|
|
{
|
||
|
|
files: ['src/*/src/**/*.ts'],
|
||
|
|
languageOptions: {
|
||
|
|
parser: tsparser,
|
||
|
|
parserOptions: {
|
||
|
|
project: ['./src/*/tsconfig.json'],
|
||
|
|
tsconfigRootDir: import.meta.dirname
|
||
|
|
}
|
||
|
|
},
|
||
|
|
plugins: { '@typescript-eslint': tseslint },
|
||
|
|
rules: {
|
||
|
|
'@typescript-eslint/explicit-function-return-type': 'error',
|
||
|
|
'@typescript-eslint/no-explicit-any': 'error',
|
||
|
|
'@typescript-eslint/no-unused-vars': 'error',
|
||
|
|
'@typescript-eslint/strict-boolean-expressions': 'error',
|
||
|
|
'no-console': ['warn', { allow: ['warn', 'error'] }]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
];
|
||
|
|
```
|
||
|
|
|
||
|
|
Create deploy/docker-compose.yml for local development:
|
||
|
|
```yaml
|
||
|
|
version: '3.8'
|
||
|
|
services:
|
||
|
|
postgres:
|
||
|
|
image: postgres:16-alpine
|
||
|
|
container_name: mcpctl-postgres
|
||
|
|
ports:
|
||
|
|
- "5432:5432"
|
||
|
|
environment:
|
||
|
|
POSTGRES_USER: mcpctl
|
||
|
|
POSTGRES_PASSWORD: mcpctl_dev
|
||
|
|
POSTGRES_DB: mcpctl
|
||
|
|
volumes:
|
||
|
|
- mcpctl-pgdata:/var/lib/postgresql/data
|
||
|
|
healthcheck:
|
||
|
|
test: ["CMD-SHELL", "pg_isready -U mcpctl"]
|
||
|
|
interval: 5s
|
||
|
|
timeout: 5s
|
||
|
|
retries: 5
|
||
|
|
|
||
|
|
volumes:
|
||
|
|
mcpctl-pgdata:
|
||
|
|
```
|
||
|
|
|
||
|
|
Add scripts to root package.json:
|
||
|
|
- "lint": "eslint src/*/src/**/*.ts"
|
||
|
|
- "lint:fix": "eslint src/*/src/**/*.ts --fix"
|
||
|
|
- "db:up": "docker-compose -f deploy/docker-compose.yml up -d"
|
||
|
|
- "db:down": "docker-compose -f deploy/docker-compose.yml down"
|
||
|
|
|
||
|
|
Create .env.example at root with DATABASE_URL template:
|
||
|
|
```
|
||
|
|
DATABASE_URL="postgresql://mcpctl:mcpctl_dev@localhost:5432/mcpctl"
|
||
|
|
```
|
||
|
|
|
||
|
|
### 1.5. Install core dependencies and perform security/architecture review
|
||
|
|
|
||
|
|
**Status:** pending
|
||
|
|
**Dependencies:** 1.1, 1.3, 1.4
|
||
|
|
|
||
|
|
Install all required production dependencies across packages, run security audit, and validate the directory structure supports all 18 planned tasks.
|
||
|
|
|
||
|
|
**Details:**
|
||
|
|
|
||
|
|
Install dependencies per package:
|
||
|
|
|
||
|
|
**src/cli/package.json:**
|
||
|
|
- commander (CLI framework)
|
||
|
|
- chalk (colored output)
|
||
|
|
- js-yaml (YAML parsing)
|
||
|
|
- inquirer (interactive prompts)
|
||
|
|
|
||
|
|
**src/mcpd/package.json:**
|
||
|
|
- fastify (HTTP server)
|
||
|
|
- @fastify/cors, @fastify/helmet, @fastify/rate-limit (middleware)
|
||
|
|
- zod (schema validation) - also add to shared
|
||
|
|
- pino (logging, built into Fastify)
|
||
|
|
|
||
|
|
**src/shared/package.json:**
|
||
|
|
- zod (shared validation schemas)
|
||
|
|
|
||
|
|
**src/db/package.json:**
|
||
|
|
- prisma (ORM)
|
||
|
|
- @prisma/client
|
||
|
|
|
||
|
|
**src/local-proxy/package.json:**
|
||
|
|
- @modelcontextprotocol/sdk (MCP protocol)
|
||
|
|
|
||
|
|
**Root devDependencies:**
|
||
|
|
- typescript
|
||
|
|
- vitest, @vitest/coverage-v8
|
||
|
|
- eslint and plugins (already specified)
|
||
|
|
- tsx (for running TypeScript directly)
|
||
|
|
- rimraf (cross-platform rm -rf for clean scripts)
|
||
|
|
|
||
|
|
**Security Review Checklist:**
|
||
|
|
1. Run 'pnpm audit' and verify no high/critical vulnerabilities
|
||
|
|
2. Verify .gitignore excludes: .env, node_modules, dist, *.log
|
||
|
|
3. Verify .env.example has no real secrets, only templates
|
||
|
|
4. Ensure no API keys or secrets in any committed files
|
||
|
|
5. Document security audit results in SECURITY_AUDIT.md
|
||
|
|
|
||
|
|
**Architecture Review Checklist:**
|
||
|
|
1. Verify structure supports Task 2 (db package with prisma/)
|
||
|
|
2. Verify structure supports Tasks 3-6 (mcpd with src/routes/, src/services/)
|
||
|
|
3. Verify structure supports Tasks 7-10 (cli with src/commands/)
|
||
|
|
4. Verify structure supports Tasks 11-13 (local-proxy with src/providers/)
|
||
|
|
5. Verify tests/ directories exist at package and root level
|
||
|
|
6. Verify dependency injection interfaces are defined in shared/src/types/
|
||
|
|
7. Verify barrel exports in shared/src/index.ts
|
||
|
|
8. Document architecture decisions in ARCHITECTURE.md
|