13 KiB
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 tosrc/for cleaner separation of app source from project management filesdocker/renamed todeploy/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:
{
"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:
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:
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:
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+):
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:
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:
- Run 'pnpm audit' and verify no high/critical vulnerabilities
- Verify .gitignore excludes: .env, node_modules, dist, *.log
- Verify .env.example has no real secrets, only templates
- Ensure no API keys or secrets in any committed files
- Document security audit results in SECURITY_AUDIT.md
Architecture Review Checklist:
- Verify structure supports Task 2 (db package with prisma/)
- Verify structure supports Tasks 3-6 (mcpd with src/routes/, src/services/)
- Verify structure supports Tasks 7-10 (cli with src/commands/)
- Verify structure supports Tasks 11-13 (local-proxy with src/providers/)
- Verify tests/ directories exist at package and root level
- Verify dependency injection interfaces are defined in shared/src/types/
- Verify barrel exports in shared/src/index.ts
- Document architecture decisions in ARCHITECTURE.md