Jake Shore f3c4cd817b Add all MCP servers + factory infra to MCPEngine — 2026-02-06
=== NEW SERVERS ADDED (7) ===
- servers/closebot — 119 tools, 14 modules, 4,656 lines TS (Stage 7)
- servers/google-console — Google Search Console MCP (Stage 7)
- servers/meta-ads — Meta/Facebook Ads MCP (Stage 8)
- servers/twilio — Twilio communications MCP (Stage 8)
- servers/competitor-research — Competitive intel MCP (Stage 6)
- servers/n8n-apps — n8n workflow MCP apps (Stage 6)
- servers/reonomy — Commercial real estate MCP (Stage 1)

=== FACTORY INFRASTRUCTURE ADDED ===
- infra/factory-tools — mcp-jest, mcp-validator, mcp-add, MCP Inspector
  - 60 test configs, 702 auto-generated test cases
  - All 30 servers score 100/100 protocol compliance
- infra/command-center — Pipeline state, operator playbook, dashboard config
- infra/factory-reviews — Automated eval reports

=== DOCS ADDED ===
- docs/MCP-FACTORY.md — Factory overview
- docs/reports/ — 5 pipeline evaluation reports
- docs/research/ — Browser MCP research

=== RULES ESTABLISHED ===
- CONTRIBUTING.md — All MCP work MUST go in this repo
- README.md — Full inventory of 37 servers + infra docs
- .gitignore — Updated for Python venvs

TOTAL: 37 MCP servers + full factory pipeline in one repo.
This is now the single source of truth for all MCP work.
2026-02-06 06:32:29 -05:00
..

Meta Ads MCP Server

A production-grade Model Context Protocol (MCP) server for the Meta Marketing API with intelligent lazy-loading architecture.

🌟 Key Features

  • Lazy Loading Architecture: Core tools load immediately, advanced features load on-demand
  • Production-Ready: Comprehensive rate limiting, caching, and error handling
  • Type-Safe: Full TypeScript with strict mode and Zod validation
  • MCP Annotations: All tools include proper metadata (readOnly, destructive, idempotent hints)
  • Smart Rate Limiting: Tracks Meta's three-tier rate limits with exponential backoff
  • Token Management: Automatic validation, expiry tracking, and refresh support

📦 Installation

npm install
npm run build

⚙️ Configuration

Create a .env file from the example:

cp .env.example .env

Required environment variables:

  • META_ACCESS_TOKEN: Your Meta Marketing API access token
  • META_APP_ID: (Optional) Your Facebook App ID for enhanced security
  • META_APP_SECRET: (Optional) Your App Secret for appsecret_proof
  • META_API_VERSION: (Optional) API version, defaults to v21.0

Getting Access Tokens

  1. User Access Token: Via Facebook Graph API Explorer

    • Select your app
    • Request permissions: ads_read, ads_management, business_management
    • Generate token
  2. Long-Lived Token: Exchange short-lived for long-lived (60 days)

    • Requires App ID and App Secret
    • Server can auto-refresh using AuthManager.refreshToLongLivedToken()
  3. System User Token: Recommended for production

    • Created in Business Manager
    • Never expires (until revoked)
    • Most secure option

🚀 Usage

Development Mode

npm run dev

Production Mode

npm run build
npm start

As MCP Server

Add to your MCP client configuration (e.g., Claude Desktop):

{
  "mcpServers": {
    "meta-ads": {
      "command": "node",
      "args": ["/path/to/meta-ads-mcp/dist/index.js"],
      "env": {
        "META_ACCESS_TOKEN": "your_token_here"
      }
    }
  }
}

🏗️ Architecture

Lazy Loading System

The server uses a two-tier module loading strategy:

Tier 1: Core Modules (Load on Startup)

  • Account: list_ad_accounts, get_account_info, get_account_pages, get_business_info, get_pixel_list
  • Campaigns: list_campaigns, get_campaign, create_campaign, update_campaign, toggle_campaign, duplicate_campaign, delete_campaign
  • Ad Sets: list_ad_sets, get_ad_set, create_ad_set, update_targeting, update_ad_set_budget, update_schedule, toggle_ad_set
  • Ads: list_ads, get_ad, create_image_ad, create_video_ad, create_carousel_ad, create_dynamic_ad, preview_creative, upload_media, list_creatives

Tier 2: Advanced Modules (Lazy Loaded)

  • Analytics: Gateway tool analytics_tools loads full insights and reporting suite
  • Audiences: Gateway tool audiences_tools loads custom audience management
  • Budget: Gateway tool budget_tools loads optimization and recommendation tools

How Lazy Loading Works:

  1. Tier 2 modules register a single gateway tool (e.g., audience_tools)
  2. When called, the gateway loads the full module and re-registers all its tools
  3. Client sees: "Module loaded, please retry with specific tool"
  4. Subsequent calls use the now-loaded tools directly

Infrastructure Components

AuthManager (src/auth/oauth.ts)

  • Token validation via debug_token endpoint
  • HMAC-SHA256 appsecret_proof generation
  • Token expiry tracking
  • Long-lived token refresh

RateLimiter (src/client/rate-limiter.ts)

  • Parses Meta's three rate limit headers:
    • x-app-usage: App-level limits
    • x-business-use-case-usage: Business-level limits
    • x-ad-account-usage: Account-level limits (200 calls/hour)
  • Exponential backoff at 75% and 90% thresholds
  • Request queue with priority system
  • Configurable concurrency (default: 5)

MetaApiClient (src/client/meta-client.ts)

  • Generic get<T>(), post<T>(), delete<T>() methods
  • Automatic appsecret_proof injection
  • Cursor-based pagination: getAllPages<T>()
  • Typed error handling with MetaApiError
  • Media upload support (images and videos)

SimpleCache (src/client/cache.ts)

  • In-memory TTL-based caching
  • Prefix-based invalidation
  • getOrCompute() for cache-aside pattern
  • Max entries enforcement (LRU-style)

🛠️ Tool Annotations

Every tool includes MCP annotations:

annotations: {
  title: "Human-readable name",
  readOnlyHint: true,        // No state changes
  destructiveHint: false,    // Can't be undone
  idempotentHint: true,      // Safe to retry
  openWorldHint: false,      // Doesn't access external data
}

Tool Categories

Read-Only Tools: All list/get operations Idempotent Tools: Updates, toggles (safe to retry) Non-Destructive Creates: Campaign/ad set/ad creation Destructive Tools: Delete operations (require confirmation)

📊 Rate Limiting

Meta enforces three types of rate limits:

  1. App-Level: Calls per hour across all users
  2. Business Use Case: Per business, per hour
  3. Ad Account: 200 calls/hour per account ⚠️ Most restrictive

The RateLimiter automatically:

  • Monitors all three metrics
  • Throttles at 75% usage
  • Pauses at 90% usage
  • Applies exponential backoff
  • Respects estimatedTimeToRegainAccess headers

🔒 Security

  • appsecret_proof: HMAC signature on every request (when app secret provided)
  • Token Validation: Checks token validity on startup
  • No Token Logging: Credentials never logged
  • .env Support: Secrets in environment, not code

📝 TypeScript

Strict mode enabled with:

  • No implicit any
  • Strict null checks
  • Unused variable detection
  • Comprehensive type definitions in src/types/meta-api.ts

🧪 Example Workflows

Create a Campaign with Ad Set and Image Ad

// 1. List accounts
list_ad_accounts()

// 2. Create campaign
create_campaign({
  account_id: "act_123456",
  name: "Q1 2025 Campaign",
  objective: "OUTCOME_TRAFFIC",
  daily_budget: "5000", // $50
  status: "PAUSED"
})

// 3. Create ad set
create_ad_set({
  campaign_id: "123456789",
  name: "US Desktop Traffic",
  optimization_goal: "LINK_CLICKS",
  billing_event: "IMPRESSIONS",
  daily_budget: "2000", // $20
  targeting: {
    age_min: 25,
    age_max: 55,
    genders: [1, 2],
    geo_locations: { countries: ["US"] },
    publisher_platforms: ["facebook"],
    device_platforms: ["desktop"]
  }
})

// 4. Upload image (stub - needs file handling)
upload_media({
  account_id: "act_123456",
  file_path: "/path/to/image.jpg",
  media_type: "image"
})

// 5. Create ad
create_image_ad({
  account_id: "act_123456",
  adset_id: "987654321",
  name: "Homepage Ad",
  page_id: "111222333",
  image_hash: "abc123hash",
  link: "https://example.com",
  headline: "Shop Now",
  message: "Limited time offer!",
  call_to_action_type: "SHOP_NOW",
  status: "ACTIVE"
})

🐛 Debugging

Set NODE_ENV=development for verbose logging:

NODE_ENV=development npm run dev

Logs go to stderr (MCP convention):

  • [MCP] Module loaded: campaigns
  • [MCP] Registered tool: create_campaign
  • Rate limit warnings appear automatically

📚 API Documentation

🤝 Contributing

  1. Follow existing patterns for tool registration
  2. Use Zod schemas with .describe() on every field
  3. Include comprehensive MCP annotations
  4. Handle errors gracefully with typed responses
  5. Add JSDoc comments for complex logic

📄 License

MIT

🙏 Credits

Built for Clawdbot by the Meta Ads MCP team.