Skip to content

Development Setup

This guide will help you set up your development environment for contributing to Seed.

First Time Setup

If you haven't installed Seed yet, follow the Installation Guide first to get Node.js, Redis, and the repository set up.

Quick Start

Already have Node.js 24+ and Redis installed? Get started in 3 commands:

bash
# 1. Clone and enter directory
git clone git@gitlab.byterecursion.com:mcp-servers/seed.git && cd seed

# 2. Install dependencies
npm install

# 3. Start development server (no auth required)
AUTH_REQUIRED=false npm run dev

Development Environment

Prerequisites

Ensure you have completed the Installation steps:

  • Node.js 24.0.0+ with npm
  • Redis 6.0+ (or skip with AUTH_REQUIRED=false)
  • Git for version control

Initial Setup

1. Fork and clone the repository (if contributing):

bash
# Fork on GitLab first, then clone your fork
git clone git@gitlab.byterecursion.com:YOUR_USERNAME/seed.git
cd seed

# Add upstream remote
git remote add upstream git@gitlab.byterecursion.com:mcp-servers/seed.git

2. Install all dependencies:

bash
npm install

This installs both runtime and development dependencies:

  • Runtime: Express, MCP SDK, Redis client, JOSE
  • Development: TypeScript, Vitest, ESLint, Prettier, Supertest

3. Configure for development:

bash
cp .env.example .env

Minimal .env for local development:

bash
# Disable authentication for local development
AUTH_REQUIRED=false

# Optional: Customize port
PORT=3000

No Redis Required for Development

With AUTH_REQUIRED=false, you can develop without Redis running. Sessions and authentication are disabled, allowing you to test MCP functionality directly.

4. Verify setup:

bash
# Start dev server
npm run dev

# Test health endpoints in another terminal
curl http://localhost:3000/health
# Expected: {"status":"ok","version":"0.1.3"}

curl http://localhost:3000/health/ready
# Expected: {"status":"ready","version":"0.1.3","checks":{...}}

Production-Ready Features

Seed now includes production-ready features (2026-01-06):

  • Graceful shutdown - SIGTERM/SIGINT handling with proper cleanup
  • Health checks - Liveness (/health) and readiness (/health/ready) probes
  • Configuration validation - Startup validation prevents misconfiguration
  • Token revocation - RFC 7009 compliant /oauth/revoke endpoint
  • Redis resilience - Circuit breaker pattern for connection failures

Development Workflow

Project Structure

seed/
├── src/                      # Source code
│   ├── config/              # Configuration modules
│   ├── middleware/          # Express middleware (auth, CORS, etc.)
│   ├── mcp/                 # MCP server implementation
│   │   └── tools/          # MCP tool implementations
│   ├── routes/             # HTTP route handlers
│   ├── services/           # Business logic (Redis, JWKS, etc.)
│   ├── types/              # TypeScript type definitions
│   ├── app.ts              # Express app setup
│   └── index.ts            # Entry point
├── wiki/                    # Documentation (VitePress)
├── vitepress/              # VitePress configuration
├── dist/                   # Compiled output (gitignored)
├── coverage/               # Test coverage reports (gitignored)
└── node_modules/           # Dependencies (gitignored)

Available Scripts

ScriptCommandPurpose
Developmentnpm run devStart dev server with hot reload
Buildnpm run buildCompile TypeScript to dist/
Startnpm startRun compiled code from dist/
Testnpm testRun all tests once
Test Watchnpm run test:watchRun tests in watch mode
Test Coveragenpm run test:coverageRun tests with coverage report
Lintnpm run lintLint source code with ESLint
Formatnpm run formatFormat code with Prettier
Format Checknpm run format:checkCheck code formatting
Type Checknpm run typecheckCheck types without emitting files
Validatenpm run validateRun format + lint + typecheck + test:coverage
Docs Devnpm run docs:devStart documentation dev server
Docs Buildnpm run docs:buildBuild documentation

Development Server

The development server uses tsx for hot reloading:

bash
npm run dev

Features:

  • Automatic restart on file changes
  • TypeScript compilation on-the-fly
  • Source maps for debugging
  • No build step required

Watching:

  • All files in src/**/*.ts
  • Configuration changes require manual restart

Making Changes

1. Create a feature branch:

bash
git checkout -b feature/my-feature

2. Make your changes:

bash
# Edit files in src/
vim src/routes/my-route.ts

3. Run validation:

bash
npm run validate

This runs:

  • prettier --write src - Format code
  • eslint src - Lint code
  • tsc --noEmit - Type check
  • vitest run --coverage - Run tests with coverage

4. Commit your changes:

bash
git add .
git commit -m "feat: add new feature"

5. Push to GitLab:

bash
git push origin feature/my-feature

Docker Development

Production Docker Setup

For production deployment, see the Installation Guide which uses ./scripts/local for complete stack management.

Development with Hot Reload

Mount source code as a volume for live reloading without rebuilding:

Create docker-compose.dev.yml:

yaml
version: '3.8'

services:
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data

  seed:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      - PORT=3000
      - AUTH_REQUIRED=false
      - REDIS_URL=redis://redis:6379
      - NODE_ENV=development
    volumes:
      # Mount source for hot reload
      - ./src:/app/src:ro
      - ./package.json:/app/package.json:ro
      - ./tsconfig.json:/app/tsconfig.json:ro
      # Use named volume for node_modules
      - node_modules:/app/node_modules
    command: npm run dev
    depends_on:
      - redis

volumes:
  redis-data:
  node_modules:

Start development environment:

bash
docker-compose -f docker-compose.dev.yml up

Benefits:

  • Changes to src/ are reflected immediately via tsx watch
  • Redis included and properly networked
  • Isolated from host environment
  • Easy cleanup with docker-compose down

Building Test Images

Build and tag for testing:

bash
# Build with version tag
docker build -t seed:dev .

# Run with environment variables
docker run -d \
  --name seed-dev \
  -p 3000:3000 \
  -e AUTH_REQUIRED=false \
  seed:dev

IDE Setup

Visual Studio Code

Recommended extensions:

Workspace settings (.vscode/settings.json):

json
{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "typescript.tsdk": "node_modules/typescript/lib",
  "typescript.enablePromptUseWorkspaceTsdk": true,
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}

Debug configuration (.vscode/launch.json):

json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Seed Server",
      "runtimeExecutable": "npm",
      "runtimeArgs": ["run", "dev"],
      "skipFiles": ["<node_internals>/**"],
      "env": {
        "AUTH_REQUIRED": "false"
      }
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Current Test",
      "runtimeExecutable": "npm",
      "runtimeArgs": ["run", "test:watch"],
      "args": ["${file}"],
      "skipFiles": ["<node_internals>/**"],
      "console": "integratedTerminal"
    }
  ]
}

Other IDEs

WebStorm:

  • Enable ESLint: Settings → Languages & Frameworks → JavaScript → Code Quality Tools → ESLint
  • Enable Prettier: Settings → Languages & Frameworks → JavaScript → Prettier
  • Run Configurations: Add "npm" configuration with run dev script

Vim/Neovim:

  • Use coc.nvim with coc-eslint and coc-prettier
  • Or ale with ESLint and Prettier
  • Use nvim-dap for debugging

Debugging

Console Debugging

Add breakpoints using debugger statements:

typescript
export async function handleMcpRequest(req: Request, res: Response) {
  debugger; // Execution will pause here
  const sessionId = req.headers['mcp-session-id'];
  // ...
}

Run with Node.js inspector:

bash
node --inspect node_modules/.bin/tsx watch src/index.ts

Attach debugger:

  • Chrome: Open chrome://inspect
  • VS Code: Use "Attach to Node Process" configuration

Logging

Development logging is configured in src/config/logging.ts:

typescript
// Increase log level for debugging
LOG_LEVEL=debug npm run dev

// Log only errors
LOG_LEVEL=error npm run dev

Available levels: error, warn, info, debug

Example debug logging:

typescript
import { logger } from '../services/logger.js';

logger.debug('Session created', {
  sessionId,
  user: req.user,
  timestamp: Date.now()
});

Testing Individual Components

Test specific functionality in isolation:

bash
# Run single test file
npx vitest run src/middleware/auth.test.ts

# Run tests matching pattern
npx vitest run -t "should validate JWT"

# Watch mode for test-driven development
npx vitest watch src/middleware/auth.test.ts

Troubleshooting

Configuration Validation Errors

IMPLEMENTED (2026-01-06) - Server validates configuration at startup and exits with clear error messages if invalid.

bash
# Error: Configuration validation failed: ...

Common validation errors:

bash
# Missing required OIDC configuration when AUTH_REQUIRED=true
Error: OIDC_ISSUER is required when AUTH_REQUIRED is true

# Invalid URL format
Error: OIDC_ISSUER must be a valid HTTP/HTTPS URL

# Invalid port range
Error: PORT must be between 1 and 65535, got: 70000

# TTL too short
Error: MCP_SESSION_TTL_SECONDS must be at least 60 seconds

Solution: Fix the invalid configuration value in your .env file or environment variables. The error message will specify exactly which value is invalid and what the valid range/format is.

Benefits:

  • Fails fast during development instead of at runtime
  • Clear error messages guide you to the fix
  • Prevents deployment of misconfigured servers
  • 42 validation tests with 96.26% coverage

Port Already in Use

bash
# Error: EADDRINUSE: address already in use :::3000

Solution 1: Change port in .env:

bash
PORT=3001

Solution 2: Kill process using port 3000:

bash
# macOS/Linux
lsof -ti:3000 | xargs kill -9

# Or find and kill manually
lsof -i:3000
kill -9 <PID>

Redis Connection Failed

bash
# Error: connect ECONNREFUSED 127.0.0.1:6379

Solution:

bash
# Check if Redis is running
redis-cli ping

# Start Redis if not running
# macOS
brew services start redis

# Linux
sudo systemctl start redis

# Docker
docker start redis

Workaround for development: Set AUTH_REQUIRED=false to disable Redis dependency.

Module Not Found

bash
# Error: Cannot find module 'some-package'

Solution:

bash
# Clean install
rm -rf node_modules package-lock.json
npm install

TypeScript Errors in IDE

bash
# Error: Cannot find module or its type declarations

Solution:

bash
# Restart TypeScript server in VS Code
# Cmd/Ctrl + Shift + P → "TypeScript: Restart TS Server"

# Or rebuild
npm run build

Test Failures

bash
# Error: Tests failing locally

Solution:

bash
# Clear Vitest cache
npx vitest run --clearCache

# Update snapshots if needed
npx vitest run -u

Next Steps

Environment Variable Reference

Development Settings

bash
# Server
PORT=3000                    # Server port (default: 3000)

# Authentication
AUTH_REQUIRED=false          # Disable auth for local dev (default: true)

# Redis
REDIS_URL=redis://localhost:6379  # Redis connection (default: redis://redis:6379)

Full Configuration

See Configuration Reference for all environment variables including OIDC, OAuth, and DCR settings.

Released under the MIT License.