MCP Nexus Universal AI Tool Bridge

MCP Nexus Universal AI Tool Bridge

by tuguidragos

Connect AI agents to real data. MCP Nexus runs tools that fetch, extract, summarize, classify and crawl web content with caching, multi LLM support, H...

48 runs
5 users
Try This Actor

Opens on Apify.com

About MCP Nexus Universal AI Tool Bridge

Connect AI agents to real data. MCP Nexus runs tools that fetch, extract, summarize, classify and crawl web content with caching, multi LLM support, HMAC webhooks, circuit breakers and full observability in a stateless production ready Apify actor.

What does this actor do?

MCP Nexus Universal AI Tool Bridge is a web scraping and automation tool available on the Apify platform. It's designed to help you extract data and automate tasks efficiently in the cloud.

Key Features

  • Cloud-based execution - no local setup required
  • Scalable infrastructure for large-scale operations
  • API access for integration with your applications
  • Built-in proxy rotation and anti-blocking measures
  • Scheduled runs and webhooks for automation

How to Use

  1. Click "Try This Actor" to open it on Apify
  2. Create a free Apify account if you don't have one
  3. Configure the input parameters as needed
  4. Run the actor and download your results

Documentation

Apify Actor Node.js TypeScript Cheerio Playwright Zod OpenAI License: Proprietary

Fetch. Extract. Analyze. The Complete Web Data Layer for AI.

--- ## Quick Start ### Run on Apify Platform 1. Configure your input parameters 2. Click "Start" to run 3. View results in the Dataset tab ### 30-Second Tutorial Fetch and extract data from any webpage in three simple steps: Step 1: Select Tool Choose fetch_web from the tool dropdown Step 2: Configure json { "mode": "single", "tool": "fetch_web", "params": { "url": "https://example.com" } } Step 3: Run Click Start and view extracted content in the dataset ### One-Line API Call bash curl "https://api.apify.com/v2/acts/XBumCgXrn9KrcPzVJ/runs?token=YOUR_TOKEN" \ -X POST -H "Content-Type: application/json" \ -d '{"mode":"single","tool":"fetch_web","params":{"url":"https://example.com"}}' ### Legal & Compliance Note This actor respects robots.txt by default. Always review target site Terms of Service. Use proxies and rendering responsibly. You are responsible for compliance (GDPR/PII/ToS) in your jurisdiction. ### What MCP Nexus Can Do MCP Nexus provides 9 specialized tools for web data operations: 1. fetch_web - Fetch and extract content from web pages 2. extract - Extract specific data using CSS, XPath, or regex selectors 3. summarize - Generate AI summaries of text content 4. classify - Classify text into predefined categories using AI 5. transform - Transform JSON data with mapping operations 6. crawl_lite - Crawl multiple pages with depth and link following 7. extract_structured - Extract structured data using AI and JSON schemas 8. search_web - Parse sitemaps and RSS feeds for URL discovery 9. diff_text - Compare two texts and calculate semantic differences --- ## Table of Contents - Chapter 1: Core Concepts - Chapter 2: Getting Started - Chapter 3: Tools Reference - Chapter 4: Execution Modes - Chapter 5: AI/LLM Integration - Chapter 6: Performance & Optimization - Chapter 7: Security & Compliance - Chapter 8: Production Deployment - Chapter 9: API & Integration - Appendix A: Input Schema Reference - Appendix B: Output Schema Reference - Appendix C: Error Codes - Appendix D: Troubleshooting - Appendix E: FAQ - Appendix F: Changelog --- ## Chapter 1: Core Concepts ### What is MCP Nexus MCP Nexus is a universal AI tool bridge that connects AI agents, workflows, and applications to real-world web data. It provides a production-ready actor on the Apify platform that orchestrates nine specialized tools for web scraping, data extraction, AI-powered analysis, and content transformation. Key Characteristics: - Stateless: Each run is independent with no persistent state - Observable: Full metrics and logging for debugging and monitoring - Resilient: Built-in circuit breakers and retry logic - Scalable: Runs on Apify's cloud infrastructure - Compliant: Respects robots.txt and implements security best practices ### Architecture Overview ┌─────────────────────────────────────────────────────────┐ │ MCP Nexus Actor │ ├─────────────────────────────────────────────────────────┤ │ Input Validation (Zod) │ │ ├─ Single Mode / Batch Mode / DAG Mode │ │ └─ Budget Tracking & Quota Management │ ├─────────────────────────────────────────────────────────┤ │ Tool Router │ │ ├─ fetch_web ├─ crawl_lite │ │ ├─ extract ├─ extract_structured │ │ ├─ summarize ├─ search_web │ │ ├─ classify ├─ diff_text │ │ └─ transform │ ├─────────────────────────────────────────────────────────┤ │ Infrastructure Layer │ │ ├─ HTTP Client (caching, ETags, Last-Modified) │ │ ├─ Circuit Breakers (per-domain failure detection) │ │ ├─ Deduplication (URL/content/hybrid fingerprinting) │ │ ├─ LLM Client (OpenAI, Anthropic, Azure) │ │ ├─ Browser (Playwright minimal/full rendering) │ │ └─ Proxy Manager (Apify Proxy, custom rotation) │ ├─────────────────────────────────────────────────────────┤ │ Output & Storage │ │ ├─ Dataset (structured run reports) │ │ ├─ Key-Value Store (HTML, screenshots, text) │ │ └─ Webhook Delivery (HMAC-signed notifications) │ └─────────────────────────────────────────────────────────┘ ### How It Works 1. Input Processing: Validates JSON input against schema, applies defaults 2. Tool Selection: Routes to appropriate tool handler based on mode 3. Execution: Runs tool with context (config, tracking, storage) 4. Metric Collection: Records bytes, tokens, retries, cache hits 5. Result Assembly: Builds structured report with metadata 6. Output: Pushes to dataset, sends webhook if configured ### Key Features Performance: - HTTP caching with ETag/Last-Modified support - Request deduplication (URL, content, hybrid) - Per-domain circuit breakers - Browser rendering (none/minimal/full) - Proxy rotation AI/LLM: - Multi-provider support (OpenAI, Anthropic, Azure) - Cost tracking per request - Token usage monitoring - Structured JSON extraction Observability: - Per-tool execution metrics - Cache hit/miss ratios - Circuit breaker trip counts - Correlation IDs for request tracking - Detailed error messages Security: - HMAC webhook signatures - Robots.txt enforcement - Allow/deny list URL filtering - Log redaction for PII - Secret management via Apify --- ## Chapter 2: Getting Started ### Installation Option 1: Use on Apify Console (Recommended) 1. Open Actor 2. Click "Try for free" 3. Configure input via UI 4. Click "Start" Option 2: Deploy to Your Apify Account 1. Visit the Actor page 2. Click "Schedule" or "API" to integrate 3. Use Apify API or SDK to run programmatically ### Authentication Apify API Token: Get your token from Apify Console → Settings → Integrations LLM API Keys: Store as Apify secrets: 1. Go to Apify Console → Settings → Secrets 2. Add secret: OPENAI_API_KEY = sk-... 3. Reference in input: "apiKeySecret": "OPENAI_API_KEY" Or set as environment variables: bash export OPENAI_API_KEY=sk-... export ANTHROPIC_API_KEY=sk-ant-... ### Your First Run Example 1: Fetch a Web Page json { "mode": "single", "tool": "fetch_web", "params": { "url": "https://example.com", "stripBoilerplate": true } } Example 2: Summarize Text json { "mode": "single", "tool": "summarize", "params": { "text": "Long article text here...", "language": "en", "style": "concise" }, "llm": { "provider": "openai", "model": "gpt-4o-mini", "apiKeySecret": "OPENAI_API_KEY" } } Example 3: Extract Data json { "mode": "single", "tool": "extract", "params": { "source": "url", "input": "https://news.ycombinator.com", "selectors": [ { "name": "titles", "css": ".titleline > a" } ] } } ### Understanding Results All runs produce a structured RunReport: ```json { "correlationId": "abc-123", "schemaVersion": 1, "ok": true, "mode": "single", "toolsExecuted": 1, "usage": { "durationMs": 1234, "httpBytes": 45678, "llmTokens": 150, "retries": 0, "cacheHits": 0, "cacheMisses": 1, "circuitBreakerTrips": 0 }, "costEstimateUSD": 0.0002, "warnings": [], "errors": [], "timestamp": "2025-01-07T12:34:56.789Z", "result": { "status": 200, "url": "https://example.com", "contentText": "Extracted content here...", "htmlSnippet": "

...", "links": [] } } ``` **Key Fields:** - `ok`: Overall success indicator - `usage`: Resource consumption metrics - `costEstimateUSD`: Estimated LLM costs - `result`: Tool output (single mode) - `results`: Array of outputs (batch mode) ### Recommended Default Configuration For optimal performance and cost savings, use these defaults: ```json { "cache": { "enabled": true, "ttlSec": 3600 }, "dedupe": { "enabled": true, "strategy": "url", "ttlSec": 86400 }, "budgets": { "maxDurationSec": 60, "maxTotalBytes": 5242880, "maxTotalTokens": 20000 }, "security": { "redactLogs": true } } ``` **Why these defaults:** - Caching (1 hour) provides immediate ROI by avoiding duplicate fetches - URL deduplication (24 hours) prevents processing same pages multiple times - Budget limits prevent runaway costs - Log redaction protects sensitive data ### Conversion-Optimized Examples **Example 1: Batch Mix (fetch + extract + summarize)** ```json { "mode": "batch", "concurrency": 2, "dag": true, "calls": [ { "callId": "fetch", "tool": "fetch_web", "params": {"url": "https://example.com/article"} }, { "callId": "extract", "tool": "extract", "params": { "source": "text", "input": {"ref": "fetch.result.contentText"}, "selectors": [{"name": "title", "regex": "^#\\s+(.+)$"}] }, "dependsOn": ["fetch"] }, { "callId": "summarize", "tool": "summarize", "params": {"text": {"ref": "fetch.result.contentText"}}, "dependsOn": ["fetch"] } ], "llm": { "provider": "openai", "model": "gpt-4o-mini" } } ``` **Example 2: Structured Extract with Schema** ```json { "mode": "single", "tool": "extract_structured", "params": { "source": "url", "input": "https://example.com/pricing", "jsonSchema": { "type": "object", "properties": { "plans": { "type": "array", "items": { "type": "object", "properties": { "name": {"type": "string"}, "price": {"type": "number"} } } } } } }, "llm": { "provider": "openai", "model": "gpt-4o-mini" } } ``` **Example 3: Crawl with Storage** ```json { "mode": "single", "tool": "crawl_lite", "params": { "startUrl": "https://example.com", "maxPages": 10, "maxDepth": 2 }, "store": { "html": true, "text": true } } ``` --- ## Chapter 3: Tools Reference ### fetch_web **Purpose:** Download and parse web pages with smart content extraction **When to Use:** - Fetching article content - Downloading HTML for later processing - Extracting clean text from pages **Parameters:** ```typescript { url: string stripBoilerplate?: boolean headers?: Record timeoutMs?: number maxBytes?: number respectRobotsTxt?: boolean } ``` **Complete Example:** ```json { "mode": "single", "tool": "fetch_web", "params": { "url": "https://blog.example.com/article", "stripBoilerplate": true }, "cache": { "enabled": true, "ttlSec": 3600 } } ``` **Output:** ```json { "status": 200, "url": "https://blog.example.com/article", "contentText": "Clean article text...", "htmlSnippet": "...", "links": [ { "href": "/about", "text": "About Us" } ], "meta": { "finalUrl": "https://blog.example.com/article", "contentType": "text/html", "bytes": 25678, "language": "en", "rendered": false } } ``` **Advanced Usage:** Enable browser rendering for JavaScript-heavy sites: ```json { "mode": "single", "tool": "fetch_web", "params": { "url": "https://spa-example.com" }, "render": "minimal" } ``` Store artifacts: ```json { "mode": "single", "tool": "fetch_web", "params": { "url": "https://example.com" }, "store": { "html": true, "text": true, "screenshot": true } } ``` --- ### extract **Purpose:** Parse and extract data from HTML/text using selectors and patterns **When to Use:** - Scraping structured data from web pages - Extracting specific fields - Pattern matching with regex **Parameters:** ```typescript { source: 'url' | 'html' | 'text' input: string selectors?: Array<{ name: string css?: string xpath?: string regex?: string }> patterns?: Array<{ name: string regex: string group?: number }> } ``` **Complete Example:** ```json { "mode": "single", "tool": "extract", "params": { "source": "url", "input": "https://news.ycombinator.com", "selectors": [ { "name": "titles", "css": ".titleline > a" }, { "name": "scores", "css": ".score" } ], "patterns": [ { "name": "points", "regex": "(\\d+) points?", "group": 1 } ] } } ``` **Output:** ```json { "fields": { "titles": [ "Show HN: My New Project", "Ask HN: How do you...", "Tell HN: Something..." ], "scores": ["123 points", "45 points", "67 points"] }, "matches": { "points": ["123", "45", "67"] } } ``` **Advanced Usage:** Extract from HTML string: ```json { "mode": "single", "tool": "extract", "params": { "source": "html", "input": "

Title

Body

", "selectors": [ { "name": "headline", "css": "h1" }, { "name": "body", "css": "p" } ] } } ``` Use XPath for complex queries: ```json { "mode": "single", "tool": "extract", "params": { "source": "url", "input": "https://example.com", "selectors": [ { "name": "metadata", "xpath": "//meta[@property='og:title']/@content" } ] } } ``` --- ### summarize **Purpose:** AI-powered text summarization with language and style control **When to Use:** - Condensing long articles - Creating executive summaries - Generating TL;DR versions **Parameters:** ```typescript { text: string language?: string style?: string maxTokens?: number model?: string apiKeySecret?: string } ``` **Complete Example:** ```json { "mode": "single", "tool": "summarize", "params": { "text": "Long article about climate change spanning multiple paragraphs...", "language": "en", "style": "concise", "maxTokens": 200 }, "llm": { "provider": "openai", "model": "gpt-4o-mini", "apiKeySecret": "OPENAI_API_KEY" } } ``` **Output:** ```json { "summary": "Climate change is accelerating due to human activities. Key impacts include rising temperatures, extreme weather, and ecosystem disruption. Immediate action is needed.", "tokens": 150 } ``` **Advanced Usage:** Multi-language summarization: ```json { "mode": "single", "tool": "summarize", "params": { "text": "Article en français...", "language": "fr", "style": "detailed" }, "llm": { "provider": "anthropic", "model": "claude-3-5-sonnet-20241022" } } ``` Bullet-point summaries: ```json { "mode": "single", "tool": "summarize", "params": { "text": "Long technical document...", "style": "bullet" } } ``` --- ### classify **Purpose:** Categorize text into predefined labels using AI **When to Use:** - Support ticket routing - Content moderation - Sentiment analysis - Topic classification **Parameters:** ```typescript { text: string labels: string[] maxTokens?: number model?: string apiKeySecret?: string } ``` **Complete Example:** ```json { "mode": "single", "tool": "classify", "params": { "text": "My account was charged twice for the same purchase. How do I get a refund?", "labels": ["billing", "technical", "account", "general"] }, "llm": { "provider": "openai", "model": "gpt-4o-mini", "apiKeySecret": "OPENAI_API_KEY" } } ``` **Output:** ```json { "label": "billing", "confidence": 0.95, "tokens": 50 } ``` **Advanced Usage:** Sentiment classification: ```json { "mode": "single", "tool": "classify", "params": { "text": "This product exceeded my expectations!", "labels": ["positive", "neutral", "negative"] } } ``` --- ### transform **Purpose:** Transform and reshape JSON data with mapping rules **When to Use:** - Data normalization - API response transformation - Field mapping and renaming **Parameters:** ```typescript { inputJson: any mapping: Array<{ from?: string to: string op?: string value?: any }> } ``` **Complete Example:** ```json { "mode": "single", "tool": "transform", "params": { "inputJson": { "user": { "firstName": "John", "lastName": "Doe", "tags": ["vip", "beta"], "created": "2025-01-07" } }, "mapping": [ { "from": "user.firstName", "to": "customer.name" }, { "from": "user.tags", "to": "customer.segments", "op": "join", "value": "," }, { "from": "user.created", "to": "customer.joinDate", "op": "dateParse" } ] } } ``` **Output:** ```json { "customer": { "name": "John", "segments": "vip,beta", "joinDate": "2025-01-07T00:00:00.000Z" } } ``` **Available Operations:** - `copy`: Copy value as-is (default) - `const`: Set constant value - `join`: Join array elements with delimiter - `split`: Split string into array - `pick`: Extract nested value by path - `concat`: Concatenate values - `replace`: Replace text patterns - `dateParse`: Parse date strings - `numberParse`: Parse numeric values - `lookup`: Map values using dictionary - `pickByPath`: Extract by dot notation path --- ### crawl_lite **Purpose:** Lightweight web crawler with configurable depth and pagination **When to Use:** - Crawling small to medium sites - Following pagination - Discovering internal links **Parameters:** ```typescript { startUrl: string maxPages?: number maxDepth?: number sameOriginOnly?: boolean delayMs?: number } ``` **Complete Example:** ```json { "mode": "single", "tool": "crawl_lite", "params": { "startUrl": "https://blog.example.com", "maxPages": 10, "maxDepth": 2, "sameOriginOnly": true, "delayMs": 500 }, "dedupe": { "enabled": true, "strategy": "url" } } ``` **Output:** ```json { "pages": [ { "url": "https://blog.example.com", "status": 200, "bytes": 12345, "linksCount": 15, "cached": false }, { "url": "https://blog.example.com/about", "status": 200, "bytes": 8900, "linksCount": 5, "cached": false } ] } ``` **Advanced Usage:** Store crawled HTML: ```json { "mode": "single", "tool": "crawl_lite", "params": { "startUrl": "https://example.com", "maxPages": 20 }, "store": { "html": true } } ``` --- ### extract_structured **Purpose:** Extract data matching JSON schemas using AI **When to Use:** - Extracting complex structured data - Schema-driven extraction - Semi-structured content parsing **Parameters:** ```typescript { source: 'text' | 'html' | 'url' input: string jsonSchema: object llm?: { provider?: string model?: string apiKeySecret?: string maxTokens?: number } } ``` **Complete Example:** ```json { "mode": "single", "tool": "extract_structured", "params": { "source": "text", "input": "John Doe works as a Senior Engineer at Acme Corp. His email is john@acme.com and phone is +1-555-0123. He joined in January 2020.", "jsonSchema": { "type": "object", "properties": { "name": { "type": "string" }, "position": { "type": "string" }, "company": { "type": "string" }, "email": { "type": "string" }, "phone": { "type": "string" }, "joinDate": { "type": "string" } } } }, "llm": { "provider": "openai", "model": "gpt-4o", "apiKeySecret": "OPENAI_API_KEY" } } ``` **Output:** ```json { "data": { "name": "John Doe", "position": "Senior Engineer", "company": "Acme Corp", "email": "john@acme.com", "phone": "+1-555-0123", "joinDate": "January 2020" }, "confidence": 0.9, "tokens": 320 } ``` **Advanced Usage:** Extract arrays: ```json { "mode": "single", "tool": "extract_structured", "params": { "source": "text", "input": "We offer three plans: Basic ($9/mo), Pro ($29/mo), Enterprise ($99/mo)", "jsonSchema": { "type": "object", "properties": { "plans": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "price": { "type": "number" } } } } } } } } ``` --- ### search_web **Purpose:** Find URLs via sitemaps, RSS feeds, or search APIs **When to Use:** - Discovering content URLs - Sitemap parsing - RSS feed aggregation **Parameters:** ```typescript { query?: string sitemapUrl?: string rssUrl?: string maxResults?: number } ``` **Complete Example:** ```json { "mode": "single", "tool": "search_web", "params": { "sitemapUrl": "https://example.com/sitemap.xml", "maxResults": 50 } } ``` **Output:** ```json { "urls": [ "https://example.com/page1", "https://example.com/page2", "https://example.com/page3" ], "count": 3, "source": "sitemap" } ``` **Advanced Usage:** Parse RSS feeds: ```json { "mode": "single", "tool": "search_web", "params": { "rssUrl": "https://blog.example.com/feed", "maxResults": 20 } } ``` --- ### diff_text **Purpose:** Compare text with semantic or character-level differences **When to Use:** - Content change detection - Version comparison - Update monitoring **Parameters:** ```typescript { text1: string text2: string semantic?: boolean } ``` **Complete Example:** ```json { "mode": "single", "tool": "diff_text", "params": { "text1": "The quick brown fox jumps.", "text2": "The quick red fox leaps.", "semantic": true } } ``` **Output:** ```json { "additions": ["red", "leaps"], "deletions": ["brown", "jumps"], "changeScore": 0.286 } ``` **Advanced Usage:** Character-level diff: ```json { "mode": "single", "tool": "diff_text", "params": { "text1": "hello", "text2": "helo", "semantic": false } } ``` --- ## Chapter 4: Execution Modes ### Single Mode Execute one tool at a time. **Example:** ```json { "mode": "single", "tool": "fetch_web", "params": { "url": "https://example.com" } } ``` **When to Use:** - Simple one-off operations - Testing tools - API integrations ### Batch Mode Execute multiple tools in parallel with configurable concurrency. **Example:** ```json { "mode": "batch", "concurrency": 3, "calls": [ { "tool": "fetch_web", "params": { "url": "https://example.com/page1" } }, { "tool": "fetch_web", "params": { "url": "https://example.com/page2" } }, { "tool": "summarize", "params": { "text": "Long text..." } } ] } ``` **When to Use:** - Processing multiple URLs - Parallel data operations - Bulk transformations **Output:** ```json { "results": [ { "tool": "fetch_web", "ok": true, "output": { "status": 200, "contentText": "..." } }, { "tool": "fetch_web", "ok": true, "output": { "status": 200, "contentText": "..." } }, { "tool": "summarize", "ok": true, "output": { "summary": "...", "tokens": 150 } } ] } ``` ### DAG Dependencies Execute tools with dependencies using Directed Acyclic Graph resolution. **Example:** ```json { "mode": "batch", "dag": true, "calls": [ { "callId": "fetch", "tool": "fetch_web", "params": { "url": "https://example.com" } }, { "callId": "extract", "tool": "extract", "params": { "source": "html", "input": { "ref": "fetch.htmlSnippet" }, "selectors": [{ "name": "title", "css": "h1" }] }, "dependsOn": ["fetch"] }, { "callId": "summarize", "tool": "summarize", "params": { "text": { "ref": "fetch.contentText" } }, "dependsOn": ["fetch"] } ] } ``` **When to Use:** - Multi-step workflows - Chained transformations - Complex data pipelines **Reference Syntax:** - `{ "ref": "callId" }` - Reference entire result - `{ "ref": "callId.path.to.field" }` - Reference nested field - `{ "ref": "callId.array.0" }` - Reference array element ### Performance Tips **Optimize Concurrency:** - HTTP-only: 5-10 concurrent - With proxies: 2-5 concurrent - Browser rendering: 1-2 concurrent **Use Caching:** ```json { "cache": { "enabled": true, "ttlSec": 3600 } } ``` **Enable Deduplication:** ```json { "dedupe": { "enabled": true, "strategy": "url" } } ``` **Set Budgets:** ```json { "budgets": { "maxDurationSec": 300, "maxTotalBytes": 52428800, "maxTotalTokens": 100000 } } ``` --- ## Chapter 5: AI/LLM Integration ### Supported Providers **OpenAI:** - Models: `gpt-4o`, `gpt-4o-mini`, `gpt-4`, `gpt-3.5-turbo` - Best for: General purpose, structured extraction - Cost: Approximately $0.15-$10 per 1M tokens (subject to change) **Anthropic (Claude):** - Models: `claude-3-5-sonnet-20241022`, `claude-3-haiku-20240307` - Best for: Long-form content, complex reasoning - Cost: Approximately $0.25-$15 per 1M tokens (subject to change) **Azure OpenAI:** - Models: Same as OpenAI, deployed to Azure - Best for: Enterprise compliance, regional requirements - Cost: Similar to OpenAI, billed through Azure (subject to change) ### Model Selection **Configuration:** ```json { "llm": { "provider": "openai", "model": "gpt-4o-mini", "apiKeySecret": "OPENAI_API_KEY", "maxTokens": 4000 } } ``` **Choosing Models:** | Task | Recommended Model | Reason | |------|------------------|--------| | Summarization | `gpt-4o-mini` | Fast, cheap, accurate | | Classification | `gpt-4o-mini` | Low latency, cost-effective | | Structured extraction | `gpt-4o` | Better schema adherence | | Complex reasoning | `claude-3-5-sonnet` | Superior reasoning | | Bulk operations | `gpt-4o-mini` | Cost optimization | ### Cost Optimization **1. Use Cheaper Models:** ```json { "llm": { "provider": "openai", "model": "gpt-4o-mini" } } ``` **2. Limit Token Usage:** ```json { "llm": { "maxTokens": 500 }, "budgets": { "maxTotalTokens": 50000 } } ``` **3. Cache Results:** ```json { "cache": { "enabled": true, "ttlSec": 86400 } } ``` **4. Monitor Costs:** Check `costEstimateUSD` in run reports: ```json { "costEstimateUSD": 0.0045, "usage": { "llmTokens": 3000, "llmCosts": { "openai": 0.0045, "anthropic": 0.0000, "azure": 0.0000, "total": 0.0045 } } } ``` ### Automatic Cost Tracking MCP Nexus automatically tracks LLM costs per provider with detailed breakdowns. **How It Works:** - Costs are calculated automatically for each LLM call - Per-provider breakdown is maintained (OpenAI, Anthropic, Azure) - Costs are displayed in logs during execution - Final cost summary included in run report **Cost Tracking in Logs:** During execution, you'll see cost information for each LLM call: ``` [INFO] LLM cost: $0.0012 (openai, gpt-4o-mini, 450 tokens) [INFO] LLM cost: $0.0035 (anthropic, claude-3-5-sonnet-20241022, 890 tokens) ``` At the end of the run, a summary is displayed: ``` [INFO] LLM Costs: OpenAI $0.0024, Anthropic $0.0035, Azure $0.0000, Total $0.0059 ``` **Cost Breakdown in Output:** The `usage.llmCosts` field provides a detailed breakdown: ```json { "usage": { "llmTokens": 1340, "llmCosts": { "openai": 0.0024, "anthropic": 0.0035, "azure": 0.0000, "total": 0.0059 } }, "costEstimateUSD": 0.0059 } ``` **Per-Tool Cost Tracking:** Costs are tracked individually for each tool that uses LLM: - **summarize**: Full cost per summary generated - **classify**: Cost per classification - **extract_structured**: Cost per extraction **Multi-Provider Support:** If you use multiple LLM providers in a single run (e.g., OpenAI for classification and Anthropic for summarization), costs are tracked separately: ```json { "mode": "batch", "calls": [ { "tool": "classify", "params": {"text": "...", "labels": ["..."]}, "llm": {"provider": "openai", "model": "gpt-4o-mini"} }, { "tool": "summarize", "params": {"text": "..."}, "llm": {"provider": "anthropic", "model": "claude-3-5-sonnet-20241022"} } ] } ``` Result: ```json { "usage": { "llmCosts": { "openai": 0.0008, "anthropic": 0.0042, "total": 0.0050 } } } ``` **Benefits:** - **Transparency**: Know exactly what each LLM call costs - **Optimization**: Identify expensive operations and optimize - **Budgeting**: Track costs against allocated budgets - **Multi-Provider**: Compare costs across different providers ### Token Management **Token Limits by Model:** | Model | Input Limit | Output Limit | |-------|-------------|--------------| | gpt-4o | 128K | 16K | | gpt-4o-mini | 128K | 16K | | claude-3-5-sonnet | 200K | 8K | | claude-3-haiku | 200K | 4K | **Tracking Usage:** Every LLM tool returns token count: ```json { "summary": "...", "tokens": 450 } ``` Total tokens tracked in usage: ```json { "usage": { "llmTokens": 1250 } } ``` ### Structured Extraction Details Use `extract_structured` for complex data extraction: ```json { "mode": "single", "tool": "extract_structured", "params": { "source": "text", "input": "Product: iPhone 15 Pro\nPrice: $999\nColor: Blue", "jsonSchema": { "type": "object", "properties": { "product": { "type": "string" }, "price": { "type": "number" }, "color": { "type": "string" } }, "required": ["product", "price"] } }, "llm": { "provider": "openai", "model": "gpt-4o" } } ``` **Tips:** - Use detailed schemas with descriptions - Prefer `gpt-4o` over `gpt-4o-mini` for complex schemas - Validate extracted data in your application --- ## Chapter 6: Performance & Optimization ### HTTP Caching **How It Works:** MCP Nexus implements intelligent HTTP caching with: - ETag header support - Last-Modified header support - Configurable TTL - Per-URL cache entries **Configuration:** ```json { "cache": { "enabled": true, "ttlSec": 3600 } } ``` **Cache Metrics:** Monitor effectiveness: ```json { "usage": { "cacheHits": 15, "cacheMisses": 3 } } ``` Aim for >70% hit rate for repeated workloads. **TTL Guidelines:** | Content Type | Recommended TTL | |--------------|-----------------| | Static content | 86400 (24h) | | News/blogs | 3600 (1h) | | Product prices | 300 (5min) | | Stock data | 60 (1min) | | User content | 0 (disabled) | ### Request Deduplication **Strategies:** 1. **URL-based**: Same URL = duplicate 2. **Content-based**: Same content hash = duplicate 3. **Hybrid**: URL + content hash **Configuration:** ```json { "dedupe": { "enabled": true, "strategy": "hybrid", "ttlSec": 86400 } } ``` **When to Use:** - Crawling workflows - Batch processing - RSS/sitemap parsing - Not for real-time data fetching - Not for dynamic content **Example:** ```json { "mode": "single", "tool": "crawl_lite", "params": { "startUrl": "https://example.com", "maxPages": 100 }, "dedupe": { "enabled": true, "strategy": "url" } } ``` ### Circuit Breakers **Purpose:** Prevent cascading failures by detecting and isolating failing services. **How It Works:** 1. Track failures per domain 2. Open circuit after N failures 3. Half-open after cooldown period 4. Close after successful requests **Default Behavior:** - Failure threshold: 3 failures - Cooldown: 60-120 seconds (randomized) - Success threshold: 2 successes to close **Monitoring:** ```json { "usage": { "circuitBreakerTrips": 2 } } ``` High trip counts indicate: - Target site issues - Rate limiting - Network problems - Need for tuning **Best Practices:** - Monitor trip counts - Investigate domains with frequent trips - Adjust delays between requests - Use proxies for problematic domains ### Proxy Configuration **When to Use Proxies:** - Scraping rate-limited sites - Avoiding IP blocks - Geographic targeting - High-volume scraping **Apify Proxy (Recommended):** ```json { "proxy": { "useApifyProxy": true } } ``` Benefits: - Residential and datacenter IPs - Automatic rotation - Geographic targeting - Built-in retry logic Cost: Approximately $0.50 per GB (subject to change) **Custom Proxies:** ```json { "proxy": { "proxyUrls": [ "http://user:pass@proxy1.example.com:8000", "http://user:pass@proxy2.example.com:8000" ] } } ``` **User-Agent Rotation:** Automatic rotation through realistic browser User-Agents. No configuration needed. ### Browser Rendering **Modes:** **None (Default):** - HTTP-only fetching - Fastest (100-500ms per page) - No JavaScript execution - Use for static content **Minimal:** ```json { "render": "minimal" } ``` - Launches headless browser - Waits 2-3 seconds for JS - No screenshots - Use for light JavaScript sites **Full:** ```json { "render": "full" } ``` - Full browser rendering - Waits for network idle - Captures screenshots - Use for complex SPAs **Performance Impact:** | Mode | Speed | Memory | CPU | Cost | |------|-------|--------|-----|------| | None | 1x | 50MB | 1x | 1x | | Minimal | 20x slower | 300MB | 5x | 5x | | Full | 40x slower | 500MB | 10x | 10x | **When to Use:** - **None**: Static HTML, APIs, RSS feeds - **Minimal**: E-commerce, news sites with JS - **Full**: SPAs, React/Vue apps, complex UIs --- ## Chapter 7: Security & Compliance ### HMAC Webhook Verification **Overview:** All webhooks include HMAC-SHA256 signatures for verification. **Signature Format:** ``` X-Signature: sha256= X-Timestamp: X-Request-Id: ``` HMAC computed over: `timestamp + "." + body` **Node.js Verification:** ```javascript const crypto = require('crypto'); function verifyWebhook(body, timestamp, signature, secret) { const payload = `${timestamp}.${JSON.stringify(body)}`; const expectedSignature = crypto .createHmac('sha256', secret) .update(payload) .digest('hex'); const expected = Buffer.from(`sha256=${expectedSignature}`, 'utf8'); const actual = Buffer.from(signature, 'utf8'); if (expected.length !== actual.length) { return false; } return crypto.timingSafeEqual(expected, actual); } app.post('/webhook', (req, res) => { const secret = process.env.WEBHOOK_SECRET; const signature = req.headers['x-signature']; const timestamp = req.headers['x-timestamp']; if (!verifyWebhook(req.body, timestamp, signature, secret)) { return res.status(401).send('Invalid signature'); } console.log('Webhook verified:', req.body); res.status(200).send('OK'); }); ``` **Python Verification:** ```python import hmac import hashlib def verify_webhook(signature, timestamp, body, secret): expected = 'sha256=' + hmac.new( secret.encode('utf-8'), f'{timestamp}.{body}'.encode('utf-8'), hashlib.sha256 ).hexdigest() return hmac.compare_digest(signature, expected) @app.route('/webhook', methods=['POST']) def webhook(): signature = request.headers.get('X-Signature') timestamp = request.headers.get('X-Timestamp') body = request.get_data(as_text=True) secret = os.environ['WEBHOOK_SECRET'] if not verify_webhook(signature, timestamp, body, secret): return 'Invalid signature', 401 data = request.json print('Webhook verified:', data) return 'OK', 200 ``` **Replay Attack Prevention:** 1. Check timestamp (reject >5 minutes old) 2. Store and check idempotency keys 3. Use HTTPS only ### Robots.txt Respect **Default Behavior:** Respects robots.txt for all `fetch_web` and `crawl_lite` operations. **Features:** - Wildcard pattern support - Crawl-delay extraction - User-agent: * rules **Override Per Domain:** ```json { "security": { "ignoreRobotsFor": ["example.com", "api.example.com"] } } ``` **Legal Considerations:** - Respecting robots.txt is a best practice - Check Terms of Service of target sites - Public data ≠ permission to scrape at scale - Some countries have specific web scraping laws ### Domain Allow/Deny Lists **Allowlist (Whitelist):** Only process URLs matching patterns: ```json { "security": { "allowlist": [ "^https://example\\.com/.*", "^https://api\\.mysite\\.com/.*" ] } } ``` **Denylist (Blacklist):** Block specific patterns: ```json { "security": { "denylist": [ "^https://example\\.com/admin/.*", "^https://.*\\.gov/.*", "^https://.*\\.mil/.*" ] } } ``` **SSRF Protection:** Block internal networks: ```json { "security": { "denylist": [ "^https?://127\\.0\\.0\\.1/.*", "^https?://localhost/.*", "^https?://169\\.254\\..*", "^https?://10\\..*", "^https?://172\\.(1[6-9]|2[0-9]|3[0-1])\\..*", "^https?://192\\.168\\..*" ] } } ``` ### PII Redaction **Enable Log Redaction:** ```json { "security": { "redactLogs": true } } ``` **What Gets Redacted:** - Tool results in console logs - `result` field in single mode - `results` array in batch mode **What's NOT Redacted:** - Metadata (timing, tokens, errors) - Dataset outputs - Webhook payloads - Key-value store artifacts ### Secret Management **Using Apify Secrets:** 1. Go to Apify Console → Settings → Secrets 2. Add secret (e.g., `OPENAI_API_KEY`) 3. Reference in input: ```json { "llm": { "apiKeySecret": "OPENAI_API_KEY" } } ``` **Environment Variables:** ```bash export OPENAI_API_KEY=sk-... export ANTHROPIC_API_KEY=sk-ant-... export WEBHOOK_SECRET=your-secret ``` **Best Practices:** - Never commit secrets to repositories - Use different secrets for dev/staging/prod - Rotate secrets quarterly - Use minimal required permissions - Monitor secret usage - Delete unused secrets ### Content Security **Safe HTML Parsing:** - Uses `cheerio` and `jsdom` safely - No eval() or code execution - Sandboxed DOM operations - XSS-safe by design **PDF Parsing:** - Memory-limited parsing - No code execution - Timeout protection **XML Parsing:** - Entity expansion disabled - DTD processing disabled - XXE attack prevention --- ## Chapter 8: Production Deployment ### Rate Limits & Best Practices **Respecting Target Sites:** - Always respect robots.txt - Use appropriate delays (300ms minimum) - Implement exponential backoff for 429 responses - Monitor circuit breaker trips **Recommended Settings:** ```json { "budgets": { "maxDurationSec": 300, "maxCalls": 100, "maxPages": 50, "maxTotalBytes": 52428800, "maxTotalTokens": 100000 } } ``` **Rate Limiting Strategy:** 1. Per-domain circuit breakers (automatic) 2. HTTP caching (reduce requests) 3. Deduplication (avoid duplicates) 4. Delays in `crawl_lite` (300-1000ms) ### Anti-Bot Strategies **When to Use Proxies:** - Sites with strict rate limits - Many concurrent requests - IP blocking issues - Geographic targeting needed **User-Agent Rotation:** Automatic rotation through realistic browser User-Agents. **Additional Techniques:** 1. Random delays in `crawl_lite` 2. Respect crawl-delay from robots.txt 3. Use browser rendering for JS-heavy sites 4. Limit batch concurrency (2-5) **Example:** ```json { "mode": "single", "tool": "fetch_web", "params": { "url": "https://strict-site.com" }, "proxy": { "useApifyProxy": true }, "render": "minimal" } ``` ### When to Use Browser Rendering **Use "minimal" mode when:** - Site requires JavaScript but loads quickly - Need basic interactivity - Performance is a priority **Use "full" mode when:** - Complex JavaScript applications - Need to wait for async content - Screenshots required for verification - SPAs (Single Page Applications) **Avoid browser rendering when:** - Static HTML is sufficient - Performance is critical - Costs need minimization **Cost Comparison:** | Mode | Pages/Hour | Cost Multiplier | |------|-----------|-----------------| | HTTP-only | 3600 | 1x | | Minimal | 180 | 20x | | Full | 90 | 40x | ### LLM Provider Limits **OpenAI:** | Model | TPM Limit (Free) | Approx. Cost per 1M Tokens | |-------|------------------|-------------------| | gpt-4o | 10,000 | ~$2.50 input, ~$10 output | | gpt-4o-mini | 200,000 | ~$0.15 input, ~$0.60 output | **Anthropic:** | Model | TPM Limit | Approx. Cost per 1M Tokens | |-------|-----------|-------------------| | claude-3-5-sonnet | Varies | ~$3 input, ~$15 output | | claude-3-haiku | Higher | ~$0.25 input, ~$1.25 output | **Optimization Tips:** 1. Use cheaper models for simple tasks 2. Cache LLM results 3. Limit `maxTokens` 4. Use structured extraction sparingly 5. Monitor `costEstimateUSD` ### Circuit Breaker Tuning **Default Settings:** - Failure threshold: 3 failures - Cooldown: 60-120 seconds - Success threshold: 2 successes **Adjust For:** **Aggressive (Critical Production):** - Lower failure threshold (2) - Longer cooldown (180s) **Lenient (Flaky Sources):** - Higher failure threshold (5) - Shorter cooldown (30s) **Monitoring:** ```json { "usage": { "circuitBreakerTrips": 3 } } ``` High trips indicate: - Target site issues - Rate limiting - Network problems - Need for adjustment ### Cache TTL Guidelines **By Content Type:** | Type | TTL (seconds) | Rationale | |------|---------------|-----------| | Static content | 86400 | Changes rarely | | News/blogs | 3600 | Updated hourly | | Product prices | 300 | Frequent changes | | Stock data | 60 | Real-time needs | | User content | 0 | Always fresh | **Configuration:** ```json { "cache": { "enabled": true, "ttlSec": 3600 } } ``` **Monitor Effectiveness:** ```json { "usage": { "cacheHits": 85, "cacheMisses": 15 } } ``` Aim for >70% hit rate for repeated workloads. ### Cost Optimization Strategies **1. Tiered Approach:** ``` Try HTTP → Try minimal browser → Use full rendering ``` **2. Batch Similar Operations:** Group by domain to leverage cache and circuit breakers: ```json { "mode": "batch", "calls": [ {"tool": "fetch_web", "params": {"url": "https://example.com/page1"}}, {"tool": "fetch_web", "params": {"url": "https://example.com/page2"}}, {"tool": "fetch_web", "params": {"url": "https://example.com/page3"}} ] } ``` **3. Enable Deduplication:** ```json { "dedupe": { "enabled": true, "strategy": "url" } } ``` **4. Minimize LLM Usage:** - Use `extract` instead of `extract_structured` when possible - Cache LLM results - Use smaller models (gpt-4o-mini) - Set aggressive `maxTokens` limits **5. Optimize Concurrency:** | Scenario | Recommended Concurrency | |----------|------------------------| | HTTP-only | 5-10 | | With proxies | 2-5 | | Browser rendering | 1-2 | **6. Store Only What You Need:** ```json { "store": { "html": false, "screenshot": false, "text": true } } ``` --- ## Chapter 9: API & Integration ### Apify API Usage **Run Actor:** ```bash curl "https://api.apify.com/v2/acts/USERNAME~mcp-nexus/runs?token=YOUR_TOKEN" \ -X POST \ -H 'content-type: application/json' \ -d '{ "mode": "single", "tool": "fetch_web", "params": {"url": "https://example.com"} }' ``` **Get Run Status:** ```bash curl "https://api.apify.com/v2/acts/USERNAME~mcp-nexus/runs/RUN_ID?token=YOUR_TOKEN" ``` **Get Dataset Items:** ```bash curl "https://api.apify.com/v2/datasets/DATASET_ID/items?token=YOUR_TOKEN" ``` **Full Documentation:** [Apify API Reference](https://docs.apify.com/api/v2) ### Webhook Setup **Configuration:** ```json { "webhook": { "url": "https://api.example.com/webhook", "secret": "your-webhook-secret", "batching": true } } ``` **Webhook Payload:** Receives complete `RunReport`: ```json { "correlationId": "abc-123", "ok": true, "mode": "single", "result": {...}, "usage": {...} } ``` **Headers:** - `Content-Type: application/json` - `X-Signature: sha256=` - `X-Timestamp: ` - `X-Request-Id: ` **Verification:** See [HMAC Webhook Verification](#hmac-webhook-verification) for code examples. ### Webhook Batching **Overview:** Webhook batching groups simultaneous webhook updates in batch mode, reducing the number of webhook calls and improving efficiency. **How It Works:** - When multiple tool calls complete within a time window (500ms), their results are batched - A single webhook is sent with all grouped results - Only applies to batch mode execution - Maintains order and correlation **Enable Batching:** ```json { "mode": "batch", "calls": [ {"tool": "fetch_web", "params": {"url": "https://example.com/page1"}}, {"tool": "fetch_web", "params": {"url": "https://example.com/page2"}}, {"tool": "summarize", "params": {"text": "..."}} ], "webhook": { "url": "https://api.example.com/webhook", "secret": "your-secret", "batching": true } } ``` **Batched Webhook Payload:** When multiple updates are grouped, the webhook receives: ```json { "type": "batch", "count": 3, "items": [ { "tool": "fetch_web", "result": { "status": 200, "contentText": "..." } }, { "tool": "fetch_web", "result": { "status": 200, "contentText": "..." } }, { "tool": "summarize", "result": { "summary": "...", "tokens": 150 } } ] } ``` **Single vs. Batch Payload:** If only one update is in the batch window, it sends the regular format: ```json { "correlationId": "abc-123", "ok": true, "mode": "batch", "results": [...] } ``` **Logs:** During execution with batching enabled: ``` [INFO] Webhook batch: 3 updates grouped [INFO] Sending batched webhook ``` **Configuration Options:** | Field | Type | Default | Description | |-------|------|---------|-------------| | `batching` | `boolean` | `true` | Enable webhook batching for batch mode | **Disable Batching:** To send individual webhooks for each result: ```json { "webhook": { "url": "https://api.example.com/webhook", "secret": "your-secret", "batching": false } } ``` **Benefits:** - **Reduced Calls**: Fewer webhook requests to your endpoint - **Efficiency**: Lower network overhead and processing - **Grouping**: Related results arrive together - **Cost Savings**: Reduced webhook processing costs **Use Cases:** - **High-volume batch processing**: Process many tool calls efficiently - **API rate limits**: Reduce webhook endpoint load - **Correlated updates**: Group related results for easier processing - **Cost optimization**: Minimize webhook infrastructure costs **Important Notes:** - Batching only applies to batch mode (`"mode": "batch"`) - Single mode always sends individual webhooks - Batch window is 500ms (not configurable) - Empty batches are not sent - Default is enabled (`batching: true`) **Handling Batched Webhooks:** Your webhook endpoint should handle both regular and batched formats: ```javascript app.post('/webhook', (req, res) => { const payload = req.body; if (payload.type === 'batch') { console.log(`Received batch of ${payload.count} items`); payload.items.forEach(item => { console.log(`Tool: ${item.tool}`, item.result); }); } else { console.log('Received single result'); console.log(payload.result || payload.results); } res.status(200).send('OK'); }); ``` ### n8n Integration **Step 1: HTTP Request Node** Configure HTTP Request node: - Method: POST - URL: `https://api.apify.com/v2/acts/USERNAME~mcp-nexus/runs?token=YOUR_TOKEN` - Body: JSON **Step 2: Pass Input** ```json { "mode": "single", "tool": "fetch_web", "params": { "url": "{{$json.url}}" } } ``` **Step 3: Wait for Completion** Add Wait node or use webhooks for async notification. **Step 4: Process Results** Parse dataset output in subsequent nodes. ### REST API Examples **Example 1: Fetch and Summarize** ```bash curl "https://api.apify.com/v2/acts/USERNAME~mcp-nexus/runs?token=TOKEN" \ -H 'content-type: application/json' \ -d '{ "mode": "batch", "dag": true, "calls": [ { "callId": "fetch", "tool": "fetch_web", "params": {"url": "https://example.com/article"} }, { "callId": "summarize", "tool": "summarize", "params": { "text": {"ref": "fetch.contentText"} }, "dependsOn": ["fetch"] } ] }' ``` **Example 2: Crawl and Extract** ```bash curl "https://api.apify.com/v2/acts/USERNAME~mcp-nexus/runs?token=TOKEN" \ -H 'content-type: application/json' \ -d '{ "mode": "single", "tool": "crawl_lite", "params": { "startUrl": "https://example.com", "maxPages": 10 }, "store": {"html": true} }' ``` ### SDK Usage **JavaScript:** ```javascript import { ApifyClient } from 'apify-client' const client = new ApifyClient({ token: 'YOUR_TOKEN' }) const run = await client.actor('USERNAME/mcp-nexus').call({ mode: 'single', tool: 'fetch_web', params: { url: 'https://example.com' } }) const dataset = await client.dataset(run.defaultDatasetId).listItems() console.log(dataset.items[0]) ``` **Python:** ```python from apify_client import ApifyClient client = ApifyClient('YOUR_TOKEN') run = client.actor('USERNAME/mcp-nexus').call( run_input={ 'mode': 'single', 'tool': 'fetch_web', 'params': { 'url': 'https://example.com' } } ) dataset = client.dataset(run['defaultDatasetId']).list_items() print(dataset.items[0]) ``` --- ## Appendices ### Appendix A: Input Schema Reference **Top-Level Fields:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `mode` | `'single' \| 'batch'` | Yes | Execution mode | | `correlationId` | `string` | No | Tracking identifier | | `tool` | `ToolName` | Conditional | Tool name (single mode) | | `params` | `object` | Conditional | Tool parameters (single mode) | | `calls` | `array` | Conditional | Tool calls (batch mode) | | `dag` | `boolean` | No | Enable DAG execution | | `concurrency` | `number` | No | Batch concurrency (default: 2) | **Configuration Objects:** **`llm`:** ```typescript { provider: 'openai' | 'anthropic' | 'azure' model: string apiKeySecret?: string maxTokens?: number } ``` **`cache`:** ```typescript { enabled: boolean ttlSec: number } ``` **`dedupe`:** ```typescript { enabled: boolean ttlSec: number strategy: 'url' | 'content' | 'hybrid' } ``` **`render`:** ```typescript 'none' | 'minimal' | 'full' ``` **`store`:** ```typescript { html: boolean screenshot: boolean text: boolean } ``` **`proxy`:** ```typescript { useApifyProxy?: boolean proxyUrls?: string[] } ``` **`security`:** ```typescript { allowlist?: string[] denylist?: string[] ignoreRobotsFor?: string[] redactLogs?: boolean } ``` **`budgets`:** ```typescript { maxDurationSec?: number maxCalls?: number maxPages?: number maxTotalBytes?: number maxTotalTokens?: number maxLLMTokens?: number maxFetchBytes?: number } ``` **`webhook`:** ```typescript { url?: string secret?: string batching?: boolean } ``` ### Appendix B: Output Schema Reference **RunReport:** ```typescript { correlationId: string schemaVersion: number ok: boolean mode: 'single' | 'batch' toolsExecuted: number usage: { durationMs: number httpBytes: number llmTokens: number retries: number cacheHits: number cacheMisses: number circuitBreakerTrips: number llmCosts: { openai: number anthropic: number azure: number total: number } } costEstimateUSD: number warnings: string[] errors: string[] timestamp: string result?: any results?: Array<{ tool: string ok: boolean output?: any error?: string }> toolMetrics?: Record } ``` ### Appendix C: Error Codes **Common Errors:** | Error | Cause | Solution | |-------|-------|----------| | `Unsupported tool` | Invalid tool name | Check tool names in schema | | `LLM API key not found` | Missing API key | Set `apiKeySecret` or env var | | `Max total bytes quota exceeded` | Budget limit hit | Increase `maxTotalBytes` | | `Max total tokens quota exceeded` | Token budget exceeded | Increase `maxTotalTokens` | | `Circuit breaker open` | Domain failures | Wait for cooldown | | `Failed to execute` | Tool execution error | Check tool parameters | | `Circular dependency detected` | Invalid DAG | Fix `dependsOn` references | | `Reference to unknown call` | Invalid ref | Check `callId` values | ### Appendix D: Troubleshooting **Issue: Circuit Breaker Constantly Tripping** **Symptoms:** Many circuit breaker trips in usage **Solutions:** - Check if target site is up - Increase delay between requests - Use proxies - Check if IP is blocked **Issue: High LLM Costs** **Symptoms:** High `costEstimateUSD` values **Solutions:** - Use cheaper models (gpt-4o-mini) - Enable caching - Reduce `maxTokens` - Switch to rule-based extraction **Issue: Browser Rendering Timeouts** **Symptoms:** Errors with `render: "full"` **Solutions:** - Increase Actor timeout - Use "minimal" instead - Check if site loads locally - Consider HTTP-only approach **Issue: Low Cache Hit Rate** **Symptoms:** High cache misses, low hits **Solutions:** - Increase cache TTL - Check if URLs have unique parameters - Enable deduplication - Use canonical URLs **Issue: Webhooks Not Delivered** **Symptoms:** No webhook received **Solutions:** - Check webhook URL is accessible - Verify HMAC secret - Check for 429 responses - Review idempotency logs ### Appendix E: FAQ **Q: Can I run this without Apify?** No, MCP Nexus is designed as an Apify Actor and relies on the Apify platform infrastructure. **Q: How much does it cost?** Costs include: - Apify compute units (approximately $0.25/hour, subject to change) - LLM API calls (provider-dependent, subject to change) - Apify Proxy (if used, approximately $0.50/GB, subject to change) **Q: Can I use my own LLM API keys?** Yes, store them as Apify secrets and reference via `apiKeySecret`. **Q: Is there a rate limit?** Limits depend on: - Your Apify plan - LLM provider limits - Target site restrictions **Q: Can I scrape any website?** You should: - Respect robots.txt - Follow Terms of Service - Comply with local laws - Use responsibly **Q: How do I debug failed runs?** Check: - Error messages in output - Circuit breaker trips - Budget violations - Tool parameters **Q: What's the maximum execution time?** Default: 60 seconds (configurable via `maxDurationSec`) ### Appendix F: Changelog See [CHANGELOG.md](CHANGELOG.md) for complete version history. **Latest Version: 2.1.x** Major features: - Multi-provider LLM support - HTTP caching with ETags - Circuit breakers - Browser rendering - DAG execution mode - Structured extraction - 9 specialized tools ---

Built with 🩶 for the Apify community 🫡

Common Use Cases

Market Research

Gather competitive intelligence and market data

Lead Generation

Extract contact information for sales outreach

Price Monitoring

Track competitor pricing and product changes

Content Aggregation

Collect and organize content from multiple sources

Ready to Get Started?

Try MCP Nexus Universal AI Tool Bridge now on Apify. Free tier available with no credit card required.

Start Free Trial

Actor Information

Developer
tuguidragos
Pricing
Paid
Total Runs
48
Active Users
5
Apify Platform

Apify provides a cloud platform for web scraping, data extraction, and automation. Build and run web scrapers in the cloud.

Learn more about Apify

Need Professional Help?

Couldn't solve your problem? Hire a verified specialist on Fiverr to get it done quickly and professionally.

Find a Specialist

Trusted by millions | Money-back guarantee | 24/7 Support