clawdbot-workspace/mcp-factory-v3/templates/AGENT-PROMPT-FOUNDATION.md

4.1 KiB

Foundation Build Agent Prompt

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

What to Build

1. package.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

{
  "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
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
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