Skip to main content
Glama
TMTrevisan

Unified Salesforce Documentation MCP Server

by TMTrevisan

export_local_documents

Export matching offline Salesforce documentation pages as a single Markdown file by specifying output path, URL prefix, or category.

Instructions

Export all matching offline documentation pages concatenated into a single Markdown file on your local machine.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
outputPathYesAbsolute file path to save the .md file.
urlPrefixNoFilter to URLs starting with this.
categoryNoFilter by category.

Implementation Reference

  • Core handler function that queries the SQLite database for documents matching optional urlPrefix/category filters, concatenates their markdown chunks, and writes the result to a local .md file via writeFileSync.
    export async function exportLocalDocuments(outputPath: string, urlPrefix?: string, category?: string) {
        const database = await getDatabase();
    
        let query = 'SELECT d.id, d.title, d.url FROM documents d';
        const conditions = [];
        const params = [];
    
        if (urlPrefix) {
            conditions.push('d.url LIKE ?');
            params.push(`${urlPrefix}%`);
        }
    
        if (category) {
            conditions.push('d.category = ?');
            params.push(category);
        }
    
        if (conditions.length > 0) {
            query += ' WHERE ' + conditions.join(' AND ');
        }
    
        query += ' ORDER BY d.url ASC';
    
        const docStmt = database.prepare(query);
        docStmt.bind(params);
    
        const documents = [];
        while (docStmt.step()) {
            const row = docStmt.get();
            documents.push({ id: row[0], title: row[1], url: row[2] });
        }
        docStmt.free();
    
        if (documents.length === 0) {
            return { success: false, count: 0, message: "No documents matched the provided filters." };
        }
    
        let combinedMarkdown = `# Filtered Export (${documents.length} pages)\n\n`;
        if (urlPrefix) combinedMarkdown += `**URL Prefix:** \`${urlPrefix}\`\n`;
        if (category) combinedMarkdown += `**Category:** \`${category}\`\n`;
        combinedMarkdown += `---\n\n`;
    
        // Extract chunks for each matched document
        for (const doc of documents) {
            const chunkStmt = database.prepare('SELECT content FROM chunks WHERE document_id = ? ORDER BY chunk_index ASC');
            chunkStmt.bind([doc.id]);
    
            let markdown = '';
            while (chunkStmt.step()) {
                const row = chunkStmt.get();
                markdown += row[0] + '\n\n';
            }
            chunkStmt.free();
    
            // Append to the giant file
            combinedMarkdown += `# ${doc.title}\n`;
            combinedMarkdown += `**Source:** [${doc.url}](${doc.url})\n\n`;
            combinedMarkdown += `${markdown.trim()}\n\n---\n\n`;
        }
    
        // Write directly to user's disk
        writeFileSync(outputPath, combinedMarkdown, { encoding: 'utf-8' });
    
        return {
            success: true,
            count: documents.length,
            message: `Successfully exported ${documents.length} documents to ${outputPath}`
        };
    }
  • Zod schema (ExportDocsSchema) defining the input parameters: outputPath (required), urlPrefix (optional), category (optional).
    const ExportDocsSchema = z.object({
        outputPath: z.string().describe("The absolute path on your local machine to save the compiled Markdown file (e.g. /Users/name/Desktop/guide.md)"),
        urlPrefix: z.string().optional().describe("Optional. Only export documents whose URL starts with this string. Useful for clustering sections of a guide."),
        category: z.string().optional().describe("Optional. Only export documents tagged with this category.")
    });
  • src/index.ts:97-109 (registration)
    Tool registration in the ListToolsRequestSchema handler, declaring the tool name 'export_local_documents', description, and input JSON schema.
    {
        name: "export_local_documents",
        description: "Export all matching offline documentation pages concatenated into a single Markdown file on your local machine.",
        inputSchema: {
            type: "object",
            properties: {
                outputPath: { type: "string", description: "Absolute file path to save the .md file." },
                urlPrefix: { type: "string", description: "Filter to URLs starting with this." },
                category: { type: "string", description: "Filter by category." }
            },
            required: ["outputPath"]
        }
    }
  • CallToolRequestSchema handler that parses args with ExportDocsSchema, calls exportLocalDocuments(), and returns success/error response.
    if (name === "export_local_documents") {
        const { outputPath, urlPrefix, category } = ExportDocsSchema.parse(args);
        console.error(`Exporting documents to ${outputPath}...`);
        const exportResult = await exportLocalDocuments(outputPath, urlPrefix, category);
    
        if (!exportResult.success) {
            return { content: [{ type: "text", text: `Export Failed: ${exportResult.message}` }], isError: true };
        }
    
        return {
            content: [{ type: "text", text: exportResult.message }]
        };
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden. It discloses the core action (concatenating and exporting to a local file) but omits important behaviors like overwrite policy, directory creation, handling of no matches, and file format specifics. Adequate but not thorough.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, no redundant words, front-loaded with key action. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple file export tool with 3 well-documented parameters, the description covers the main idea. Minor gaps (e.g., behavior on existing file) do not significantly impair understanding for most agents.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, with clear parameter descriptions. The tool description's phrase 'all matching' reinforces filtering but adds no new meaning beyond the schema. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('export'), the resource ('offline documentation pages'), and the result ('concatenated into a single Markdown file on your local machine'). It distinguishes from siblings like read_local_document (single page) and mass_extract_guide (likely batch extraction without concatenation).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool instead of alternatives (e.g., mass_extract_guide, search_local_docs). The description does not mention context, prerequisites, or when to avoid using it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TMTrevisan/unified-sf-docs-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server