diff --git a/.github/workflows/ci-mcp-server.yml b/.github/workflows/ci-mcp-server.yml new file mode 100644 index 00000000..432e7ecf --- /dev/null +++ b/.github/workflows/ci-mcp-server.yml @@ -0,0 +1,34 @@ +# CI for mcp-server (TypeScript only) +# Triggers on changes to mcp-server or its workspace package dependencies +name: CI — MCP Server + +on: + push: + branches: [main] + paths: + - 'services/mcp-server/**' + - 'packages/errors/**' + - 'packages/config/**' + - 'packages/auth/**' + - 'packages/fastify-core/**' + - 'packages/logger/**' + pull_request: + branches: [main] + paths: + - 'services/mcp-server/**' + - 'packages/errors/**' + - 'packages/config/**' + - 'packages/auth/**' + - 'packages/fastify-core/**' + +jobs: + typescript: + name: TypeScript (build + test + typecheck) + uses: ./.github/workflows/reusable-pnpm-workspace.yml + with: + node-version: '22' + pnpm-version: '10' + command: | + pnpm -r --filter @bytelyst/mcp-server... build + pnpm --filter @bytelyst/mcp-server test + pnpm --filter @bytelyst/mcp-server exec tsc --noEmit diff --git a/docker-compose.yml b/docker-compose.yml index ed67daaa..b9ad8f5c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -108,6 +108,37 @@ services: timeout: 10s retries: 3 + # ── MCP Server (Fastify + TypeScript) ──────────────────────── + # Exposes tool namespaces: platform.telemetry.*, platform.diagnostics.*, + # extraction.*, support.* — consumed by AI agents + admin tooling + mcp-server: + build: + context: . + dockerfile: services/mcp-server/Dockerfile + ports: + - '4007:4007' + env_file: + - .env + environment: + - PORT=4007 + - PLATFORM_SERVICE_URL=http://platform-service:4003 + - EXTRACTION_SERVICE_URL=http://extraction-service:4005 + depends_on: + platform-service: + condition: service_healthy + extraction-service: + condition: service_healthy + labels: + - 'traefik.enable=true' + - 'traefik.http.routers.mcp.rule=PathPrefix(`/api/tools`)' + - 'traefik.http.services.mcp.loadbalancer.server.port=4007' + restart: unless-stopped + healthcheck: + test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4007/health'] + interval: 30s + timeout: 10s + retries: 3 + # ── Volumes ─────────────────────────────────────────────────────── volumes: loki-data: diff --git a/services/mcp-server/.env.example b/services/mcp-server/.env.example index 107c5e35..441a71fc 100644 --- a/services/mcp-server/.env.example +++ b/services/mcp-server/.env.example @@ -1,5 +1,5 @@ -# MCP Server — port 4006 -PORT=4006 +# MCP Server — port 4007 +PORT=4007 HOST=0.0.0.0 LOG_LEVEL=info diff --git a/services/mcp-server/Dockerfile b/services/mcp-server/Dockerfile new file mode 100644 index 00000000..5fab0ec4 --- /dev/null +++ b/services/mcp-server/Dockerfile @@ -0,0 +1,39 @@ +# Build context: repo root (docker compose sets context: .) +FROM node:22-alpine AS builder +RUN npm install -g pnpm@10 +WORKDIR /app + +# Copy workspace config + lockfile for dependency resolution +COPY package.json pnpm-workspace.yaml pnpm-lock.yaml tsconfig.base.json ./ + +# Copy all relevant package.json files (pnpm needs these for workspace resolution) +COPY packages/errors/package.json packages/errors/ +COPY packages/config/package.json packages/config/ +COPY packages/auth/package.json packages/auth/ +COPY packages/fastify-core/package.json packages/fastify-core/ +COPY packages/logger/package.json packages/logger/ +COPY packages/monitoring/package.json packages/monitoring/ +COPY packages/testing/package.json packages/testing/ +COPY services/mcp-server/package.json services/mcp-server/ + +# Install all workspace deps +RUN pnpm install --frozen-lockfile + +# Copy source +COPY packages/ packages/ +COPY services/mcp-server/tsconfig.json services/mcp-server/ +COPY services/mcp-server/src/ services/mcp-server/src/ + +# Build packages first, then service +RUN pnpm -r --filter @bytelyst/mcp-server... build + +# Deploy to isolated directory (production deps only) +RUN pnpm --filter @bytelyst/mcp-server deploy --legacy /app/deploy + +# ── Production ───────────────────────────────────────────── +FROM node:22-alpine +WORKDIR /app +COPY --from=builder /app/deploy ./ +ENV NODE_ENV=production +EXPOSE 4007 +CMD ["node", "dist/server.js"] diff --git a/services/mcp-server/src/lib/config.ts b/services/mcp-server/src/lib/config.ts index 6d59b653..99351442 100644 --- a/services/mcp-server/src/lib/config.ts +++ b/services/mcp-server/src/lib/config.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; const envSchema = z.object({ - PORT: z.coerce.number().default(4006), + PORT: z.coerce.number().default(4007), HOST: z.string().default('0.0.0.0'), NODE_ENV: z.enum(['development', 'production', 'test']).default('development'), CORS_ORIGIN: z.string().optional(),