# Foundation Build Agent Prompt

Build the foundation for the {{NAME}} MCP server at {{DIR}}.

## What to Build

### 1. `package.json`
```json
{
  "name": "@mcpengine/{{NAME}}",
  "version": "1.0.0",
  "type": "module",
  "main": "dist/main.js",
  "scripts": {
    "build": "tsc",
    "start": "node dist/main.js",
    "dev": "tsx watch src/main.ts"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.12.1",
    "axios": "^1.7.0",
    "zod": "^3.23.0"
  },
  "devDependencies": {
    "typescript": "^5.6.0",
    "tsx": "^4.19.0",
    "@types/node": "^22.0.0"
  }
}
```

### 2. `tsconfig.json`
```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "declaration": true,
    "resolveJsonModule": true,
    "forceConsistentCasingInFileNames": true,
    "noUncheckedIndexedAccess": true,
    "jsx": "react-jsx"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}
```

### 3. `src/types/index.ts`
- Define TypeScript interfaces for ALL API entities
- Use branded types for IDs: `type CustomerId = string & { __brand: 'CustomerId' }`
- Use discriminated unions for status fields
- Export everything

### 4. `src/clients/{{NAME}}.ts`
API client with:
- Auth: {{AUTH_TYPE}} (Bearer token / API key / OAuth2)
- Base URL: {{API_BASE}}
- Retry with exponential backoff (3 retries, 1s/2s/4s)
- Rate limit awareness (respect 429 + Retry-After header)
- Automatic pagination (abstract cursor/offset)
- Request interceptors for logging
- Response interceptors for error normalization
- Timeout: 30s default
- OAuth token auto-refresh if applicable

```typescript
import axios, { AxiosInstance, AxiosError } from 'axios';

export class {{PascalName}}Client {
  private client: AxiosInstance;
  private rateLimitRemaining = Infinity;
  private rateLimitReset = 0;

  constructor(config: { apiKey?: string; accessToken?: string; baseUrl?: string }) {
    this.client = axios.create({
      baseURL: config.baseUrl || '{{API_BASE}}',
      timeout: 30000,
      headers: { /* auth headers */ }
    });

    // Response interceptor for rate limiting
    this.client.interceptors.response.use(
      (res) => {
        this.rateLimitRemaining = parseInt(res.headers['x-ratelimit-remaining'] || 'Infinity');
        this.rateLimitReset = parseInt(res.headers['x-ratelimit-reset'] || '0');
        return res;
      },
      async (error: AxiosError) => {
        if (error.response?.status === 429) {
          const retryAfter = parseInt(error.response.headers['retry-after'] || '5');
          await this.sleep(retryAfter * 1000);
          return this.client.request(error.config!);
        }
        throw this.normalizeError(error);
      }
    );
  }

  // Paginated fetch helper
  async paginate<T>(endpoint: string, params?: Record<string, unknown>): Promise<T[]> { ... }

  // Retry with exponential backoff
  private async withRetry<T>(fn: () => Promise<T>, retries = 3): Promise<T> { ... }
}
```

### 5. `src/server.ts`
MCP server with:
- Lazy-loaded tool modules (dynamic import)
- Resource handlers for UI apps
- Structured error responses
- Request logging

```typescript
import { Server } from '@modelcontextprotocol/sdk/server/index.js';

// Lazy load tool modules
const toolModules = {
  'customers': () => import('./tools/customers-tools.js'),
  'orders': () => import('./tools/orders-tools.js'),
  // ... etc
};

// Tools loaded on first call
const loadedTools = new Map<string, any>();

async function getToolHandler(category: string) {
  if (!loadedTools.has(category)) {
    const mod = await toolModules[category]();
    loadedTools.set(category, mod);
  }
  return loadedTools.get(category);
}
```

### 6. `src/main.ts`
Entry point with:
- Environment validation (fail fast)
- Dual transport (stdio + HTTP/SSE)
- Graceful shutdown handlers
- Health check endpoint

### 7. `.env.example` + `.gitignore` + `README.md`

## Rules
- DO NOT create tool files or app files — only foundation
- TSC must compile clean with `strict: true`
- Run `npm install` and `npx tsc --noEmit` to verify
- Commit when done
