MCP Documentation Assistant

MCP Documentation Assistant

Stable Release
TypeScript Cloudflare Workers AI MCP

Overview

A powerful Cloudflare Worker that combines web scraping and AI to provide intelligent answers about documentation and web content. Built using the Workers MCP framework, FireCrawl SDK, and Google's Gemini AI, this service transforms complex documentation queries into clear, contextual responses with proper citations.

The MCP Documentation Assistant intelligently analyzes the complexity of queries and automatically expands its search to related documentation pages when necessary, ensuring comprehensive answers that draw from multiple relevant sources. It implements efficient caching strategies to optimize performance and reduce API calls.

Key Features

Smart Content Scraping

  • Automatically detects and scrapes documentation pages and related content
  • Intelligent filtering of relevant documentation links
  • Context-aware scraping based on query complexity
  • Efficient extraction of main content while filtering out navigation and irrelevant sections

AI-Powered Answers

  • Uses Google's Gemini AI to generate accurate, contextual responses
  • Carefully crafted prompts to ensure high-quality answers
  • Handles complex technical questions with detailed explanations
  • Maintains focus on provided content to ensure accuracy

Multi-Page Context

  • Intelligently gathers information from related documentation pages
  • Automatically identifies and follows relevant documentation links
  • Combines content from multiple sources for comprehensive answers
  • Adapts search depth based on query complexity

Caching System

  • Implements KV storage to cache responses and reduce API calls
  • Separate caching for content and responses with appropriate TTLs
  • Content cached for one week to minimize scraping operations
  • Responses cached for 24 hours to balance freshness and performance

Citation Support

  • Provides answers with specific citations to source content
  • Clear attribution using square bracket notation
  • Source URLs included for reference
  • Distinguishes between main and related page content

Error Handling

  • Graceful fallbacks for scraping issues
  • User-friendly error messages
  • Automatic handling of rate limits and API failures
  • Robust error recovery strategies

Architecture

Core Components

Worker Entrypoint (src/index.ts)

  • Main Cloudflare Worker implementation using MCP framework
  • Handles request routing and environment configuration
  • Implements caching strategy with KV storage
  • Provides user-friendly error handling

Content Scraper (src/utils.ts)

  • Utilizes FireCrawl SDK for efficient web scraping
  • Implements intelligent related page detection
  • Filters and processes content for optimal AI consumption
  • Handles batch scraping for related pages

AI Integration (src/utils.ts)

  • Integrates with Google's Gemini AI
  • Formats prompts for optimal response quality
  • Ensures proper citation and content focus
  • Handles AI response processing

Caching System

  • Implements dual-layer caching strategy
  • Separate caches for content and responses
  • Optimized TTLs for different cache types
  • Efficient cache key generation

Technical Implementation

Content Scraping Logic

The content scraping system intelligently adapts to the complexity of the query and the type of website being analyzed:

export async function scrapeContent(url: string, apiKey: string, isComplex: boolean = false): Promise {
  const app = new FirecrawlApp({ apiKey });
  
  // Always scrape the main URL first
  const mainResult = await app.scrapeUrl(url, { 
    formats: ['markdown', 'links'],
    onlyMainContent: true
  }) as ScrapeResponse;
  
  if (!mainResult.success || !mainResult.markdown) {
    throw new Error(`Failed to scrape: ${mainResult.error || 'Unknown error'}`);
  }
  
  // For simple queries or non-doc sites, return just the main content
  if (!isComplex || !url.match(/docs|documentation|github\.com|api|guide/)) {
    return mainResult.markdown;
  }
  
  // For complex queries on doc sites, try to add related content
  try {
    // Get up to 2 related pages from the links in the main page
    const relatedUrls = (mainResult.links || [])
      .filter(linkedUrl => isRelevantDocUrl(linkedUrl, url))
      .slice(0, 2);
    
    if (relatedUrls.length === 0) {
      return mainResult.markdown;
    }
    
    // Use batch scraping for efficiency
    const batchResult = await app.batchScrapeUrls(relatedUrls, {
      formats: ['markdown'],
      onlyMainContent: true
    });
    
    // Combine all content with source labels
    const allContent = [`## Main Page: ${url}\n\n${mainResult.markdown}`];
    
    if (batchResult.success && batchResult.data) {
      batchResult.data.forEach((result: any) => {
        if (result.success && result.markdown) {
          allContent.push(`## Related Page: ${result.metadata.url}\n\n${result.markdown}`);
        }
      });
    }
    
    return allContent.join('\n\n');
  } catch (error) {
    // If related page scraping fails, just return the main content
    console.error('Error getting related pages:', error);
    return mainResult.markdown;
  }
}

AI Prompt Formatting

The system uses carefully crafted prompts to ensure high-quality, focused responses:

export function formatContentQuery(content: string, question: string): string {
  return `You are a helpful AI assistant that provides accurate, concise answers based on the given content.
Your task is to answer questions using ONLY the information provided.
If the answer cannot be found in the content, say so clearly.
Always include specific citations in [square brackets] and present the most relevant information first.

Content:
${content}

Question: ${question}

Answer: `;
}

Caching Implementation

The caching system uses Cloudflare KV storage with separate caches for content and responses:

async askAboutUrl(url: string, question: string): Promise {
  // Use two distinct cache keys
  const responseCacheKey = `r:${url}:${question}`;
  const contentCacheKey = `c:${url}`;
  
  // Try to get the AI response from cache first
  const cachedResponse = await this.env.CONTENT_CACHE.get(responseCacheKey);
  if (cachedResponse) {
    return cachedResponse;
  }

  try {
    // Determine complexity of the query
    const isComplexQuery = question.length > 50 || 
                         question.includes('how') ||
                         question.includes('explain') ||
                         question.includes('compare');
    
    // Try to get scraped content from cache
    let content = await this.env.CONTENT_CACHE.get(contentCacheKey);
    
    // If no cached content, scrape it
    if (!content) {
      content = await scrapeContent(url, this.env.FIRE_CRAWL_API_KEY, isComplexQuery);
      
      // Cache scraped content for 1 week
      await this.env.CONTENT_CACHE.put(contentCacheKey, content, { expirationTtl: 604800 });
    }
    
    // Format prompt and get AI response
    const prompt = formatContentQuery(content, question);
    const response = await ask(prompt, this.env.GEMINI_API_KEY);
    
    // Cache the response for 24 hours
    await this.env.CONTENT_CACHE.put(responseCacheKey, response, { expirationTtl: 86400 });
    
    return response;
  } catch (error) {
    // Error handling...
  }
}

Usage Example

Basic Usage

The MCP Documentation Assistant exposes a single endpoint through the MCP framework:

async askAboutUrl(url: string, question: string): Promise

Example usage:

const worker = new MyWorker();
const answer = await worker.askAboutUrl(
  'https://docs.example.com/api',
  'What are the authentication methods?'
);

Response Format

🟢 High confidence

Authentication Methods in Example API

The Example API supports three authentication methods:

1. API Key Authentication

The most common method is API key authentication, where you include your API key in the request header [Main Page]. This is recommended for most use cases due to its simplicity and security.

Example:

Authorization: Bearer YOUR_API_KEY
2. OAuth 2.0

For applications requiring delegated user access, OAuth 2.0 is supported [Related Page: https://docs.example.com/api/oauth]. This method requires implementing the authorization code flow and refreshing tokens as needed.

3. JWT Authentication

For server-to-server communication, JWT authentication is available [Main Page]. This requires generating a signed JWT with your service account credentials.

All authentication methods require HTTPS, and requests without proper authentication will receive a 401 Unauthorized response [Main Page].

Setup and Configuration

Prerequisites

  • Node.js and npm installed
  • Cloudflare Workers account
  • FireCrawl API key
  • Google Gemini API key

Environment Configuration

The worker requires the following environment variables:

  • SHARED_SECRET: Secret key for MCP authentication
  • FIRE_CRAWL_API_KEY: API key for FireCrawl service
  • GEMINI_API_KEY: API key for Google's Gemini AI
  • CONTENT_CACHE: KV namespace binding for caching

Deployment

Deploy to Cloudflare Workers with:

npm run deploy