Use Case Deep Dives: Four Walk-Throughs You Can Replicate

Part 5 of the Local-First AI Agents series — four pipelines, each replicable with any OpenAI-compatible local LLM.

These four use cases are end-to-end walk-throughs. Each one uses the Standard tier (paper-search, fetch, time, sequentialthinking, wikipedia-mcp, duckduckgo, playwright, markdownify) unless noted, and can be replicated with any OpenAI-compatible local LLM.

Use case A: academic research pipeline

Goal: Search for papers on a topic, download PDFs, convert to markdown, and build a local knowledge base.

Tools used: paper-search, markdownify, fetch

Context budget: ~10 tools active, ~400 tokens of tool definitions

Step 1: Search for papers

# Using the MCP client directly
result = call_tool("search_papers", {
    "query": "knowledge distillation survey",
    "max_results_per_source": 20,
    "sources": "arxiv,semantic_scholar"
})

The search_papers tool returns structured JSON with titles, abstracts, citation counts, and PDF URLs for each result.

Step 2: Download PDFs with unique filenames

A small wrapper script handles this automatically. It:

  • Deduplicates results across sources
  • Sorts by relevance (topic-specific papers first, then by citation count)
  • Downloads with unique filenames: {number}_{arxiv_id}_{title_slug}.pdf
  • Saves a manifest.json tracking all downloads
  • Adds 5-second delays between downloads to avoid rate limits

Output from a real run:

Searching for 'knowledge distillation' (up to 20 per source)...

  Saved raw JSON: ~/data.mcp/papers/knowledge-distillation/search_20260830_140523.json (20 papers)

  [01/20] A Survey on Knowledge Distillation of Large Language Models...
              Saved: 01_2402.13116_A_Survey_on_Knowledge_Distillation_of_La.pdf (342KB)
  [02/20] Knowledge Distillation: A Survey...
              Saved: 02_2006.02371_Knowledge_Distillation_A_Survey.pdf (518KB)
  ...

  Downloaded 18/20 papers to ~/data.mcp/papers/knowledge-distillation/

Step 3: Convert PDFs to markdown

Use the markdownify server to convert downloaded PDFs:

# Convert a single PDF
result = call_tool("pdf-to-markdown", {
    "url": "file:///workspace/papers/knowledge-distillation/01_2402.13116_A_Survey_on_Knowledge_Distillation_of_La.pdf"
})

Or batch convert with a script:

import os
import json

papers_dir = os.path.expanduser("~/data.mcp/papers/knowledge-distillation")
manifest = json.load(open(f"{papers_dir}/manifest.json"))
base = os.path.expanduser("~/data.mcp/")

for paper in manifest:
    if paper.get("local_path") and paper["local_path"].endswith(".pdf"):
        pdf_path = paper["local_path"].replace(base, "/workspace/")
        result = call_tool("pdf-to-markdown", {"url": f"file://{pdf_path}"})
        # Save markdown alongside the PDF
        md_path = paper["local_path"].replace(".pdf", ".md")
        with open(md_path, "w") as f:
            f.write(result)
        print(f"Converted: {os.path.basename(md_path)}")

Step 4: Build a knowledge base

With markdown versions of all papers, you can:

  • Search locally: Use sequentialthinking to reason over the content
  • Store in memory: Create entities and relations in the knowledge graph
  • Index with sqlite: Store structured metadata for querying
# Store paper metadata in a structured way
for paper in manifest[:5]:  # Top 5 papers
    call_tool("sequentialthinking", {
        "thought": f"Paper: {paper['title']}\n"
                  f"Citations: {paper['citations']}\n"
                  f"Key finding: {paper['abstract'][:500]}",
        "thoughtNumber": 1,
        "totalThoughts": 5,
        "nextThoughtNeeded": True
    })

Results

  • 20 papers downloaded and stored persistently
  • Raw JSON responses saved with timestamps
  • PDFs converted to searchable markdown
  • Knowledge base ready for querying
  • All data stays on your machine

Use case B: web research & consolidation

Goal: Research a topic across multiple sources (Wikipedia, web search, direct page access) with screenshots and content archival.

Tools used: duckduckgo, wikipedia-mcp, playwright, fetch, sequentialthinking

Step 1: Start with a Wikipedia overview

# Get a broad overview first
summary = call_tool("get_summary", {"title": "Knowledge distillation"})

Response:

{
  "title": "Knowledge distillation",
  "summary": "In machine learning, knowledge distillation is the process of transferring knowledge from a large model (teacher) to a smaller model (student)..."
}

Step 2: Search the web for recent developments

# Find recent articles beyond Wikipedia
results = call_tool("search", {
    "query": "knowledge distillation large language models 2024 2025"
})

Step 3: Take screenshots of key pages

# Navigate to a key resource and capture it
call_tool("browser_navigate", {"url": "https://arxiv.org/abs/2402.13116"})
screenshot = call_tool("browser_take_screenshot", {})

# The screenshot is saved to /workspace/playwright/output/ on the host
# Access the page content as an accessibility tree
content = call_tool("browser_snapshot", {})

Step 4: Network traffic analysis

# Monitor network requests (useful for API research or debugging)
requests = call_tool("browser_network_requests", {})

# Get full details of a specific request
details = call_tool("browser_network_request", {"requestId": requests[0]["id"]})

Step 5: Consolidate with sequential thinking

call_tool("sequentialthinking", {
    "thought": "Wikipedia provides a foundational definition. Web search reveals 3 key trends: "
               "1) LLM distillation (compressing large models), "
               "2) Multi-teacher distillation, "
               "3) Self-distillation without a teacher model. "
               "The arXiv paper 2402.13116 is a comprehensive survey covering all three.",
    "thoughtNumber": 1,
    "totalThoughts": 3,
    "nextThoughtNeeded": True
})

Step 6: Archive everything

Screenshots are automatically saved to /workspace/playwright/output/ on the host filesystem. You can also use fetch to grab page content as markdown:

page_content = call_tool("fetch", {
    "url": "https://en.wikipedia.org/wiki/Knowledge_distillation"
})

Use case C: document processing pipeline

Goal: Convert various document formats (PDF, DOCX, XLSX, PPTX, web pages) to markdown for ingestion by a local LLM.

Tools used: markdownify, fetch, filesystem

Why this matters: Local LLMs can’t read PDFs or DOCX files directly. Converting to markdown gives them structured, searchable content.

Supported conversions

InputToolOutput
PDFpdf-to-markdownStructured text with headings
DOCXdocx-to-markdownFormatted text with tables
XLSXxlsx-to-markdownTabular data as markdown tables
PPTXpptx-to-markdownSlide content with notes
Web pagewebpage-to-markdownCleaned HTML → markdown
YouTubeyoutube-to-markdownTranscript + metadata
Imageimage-to-markdownDescription + metadata
Audioaudio-to-markdownTranscription (if available)

Batch processing script

#!/usr/bin/env python3
"""Convert documents in a directory to markdown using MCP markdownify."""

import os

base = os.path.expanduser("~/data.mcp/")
INPUT_DIR = os.path.join(base, "papers/knowledge-distillation")
OUTPUT_DIR = os.path.join(base, "markdownify/knowledge-distillation")
os.makedirs(OUTPUT_DIR, exist_ok=True)

# Mapping of file extensions to markdownify tools
EXTENSION_MAP = {
    ".pdf": "pdf-to-markdown",
    ".docx": "docx-to-markdown",
    ".xlsx": "xlsx-to-markdown",
    ".pptx": "pptx-to-markdown",
}

for filename in os.listdir(INPUT_DIR):
    ext = os.path.splitext(filename)[1].lower()
    if ext not in EXTENSION_MAP:
        continue

    tool = EXTENSION_MAP[ext]
    input_path = os.path.join(INPUT_DIR, filename)

    # markdownify uses file:// URIs relative to the gateway container
    container_path = input_path.replace(base, "/workspace/")

    result = call_tool(tool, {"url": f"file://{container_path}"})

    output_file = os.path.join(OUTPUT_DIR, filename.replace(ext, ".md"))
    with open(output_file, "w") as f:
        f.write(result)

    print(f"Converted: {filename} → {os.path.basename(output_file)}")

Processing web content

# Convert a web page to markdown for local analysis
result = call_tool("webpage-to-markdown", {
    "url": "https://arxiv.org/abs/2402.13116"
})

# Save it
with open(os.path.join(base, "markdownify/arxiv-kd-survey.md"), "w") as f:
    f.write(result)

Key insight

The markdownify server writes output to /workspace/markdownify/ on the host filesystem when you use file-based tools. Web-based conversions return the markdown directly. Either way, you end up with clean, LLM-friendly markdown that preserves document structure.

Use case D: multi-iteration research with task orchestration

Goal: Plan, track, and consolidate a multi-day research project using task management and persistent storage.

Tools used: task-orchestrator, memory, sequentialthinking, paper-search, wikipedia-mcp

This use case requires the Extended tier (add task-orchestrator to --servers).

Why task orchestration?

Single-shot LLM prompts don’t work for complex research. You need to:

  1. Plan: Break the research into tasks and subtasks
  2. Track: Remember what you’ve found, what’s still pending
  3. Consolidate: Synthesize findings across multiple sessions
  4. Persist: Store knowledge for future sessions

Task Orchestrator provides structured project management with features, tasks, sections, dependencies, and markdown export. Combined with Memory (knowledge graph) and sequential thinking, you get a research workflow that persists across sessions.

Step 1: Create the research project

# Create a project
project = call_tool("create_project", {
    "name": "Knowledge Distillation Survey",
    "description": "Comprehensive survey of KD methods for LLMs"
})

project_id = project["id"]

# Create features (major research areas)
feature1 = call_tool("create_feature", {
    "project_id": project_id,
    "name": "Classical KD Methods",
    "description": "Logit-based, feature-based, attention-based distillation"
})

feature2 = call_tool("create_feature", {
    "project_id": project_id,
    "name": "LLM-Specific KD",
    "description": "Distillation techniques specific to large language models"
})

feature3 = call_tool("create_feature", {
    "project_id": project_id,
    "name": "Self-Distillation",
    "description": "Methods where the teacher and student are the same model"
})

Step 2: Break down into tasks

# Tasks under Feature 1: Classical KD Methods
call_tool("create_task", {
    "feature_id": feature1["id"],
    "name": "Survey Hinton et al. 2015",
    "description": "Read and summarize the original KD paper"
})

call_tool("create_task", {
    "feature_id": feature1["id"],
    "name": "Categorize distillation types",
    "description": "Create taxonomy: response-based, feature-based, relation-based"
})

# Tasks under Feature 2: LLM-Specific KD
call_tool("create_task", {
    "feature_id": feature2["id"],
    "name": "Search for LLM KD papers",
    "description": "Use paper-search to find recent LLM distillation papers"
})

Step 3: Execute research iterations

# Iteration 1: Search for papers
papers = call_tool("search_papers", {
    "query": "knowledge distillation large language models",
    "max_results_per_source": 20,
    "sources": "arxiv"
})

# Store key findings in the knowledge graph
for paper in papers[:5]:
    call_tool("create_entities", {
        "entities": [{
            "name": paper["title"][:80],
            "entityType": "Paper",
            "observations": [
                f"Citations: {paper.get('citations', 'N/A')}",
                f"ArXiv: {paper.get('paper_id', 'N/A')}",
                f"Abstract: {paper.get('abstract', '')[:200]}"
            ]
        }]
    })

# Create relations between papers
call_tool("create_relations", {
    "relations": [{
        "from": papers[0]["title"][:80],
        "to": papers[1]["title"][:80],
        "relationType": "cites"
    }]
})

Step 4: Consolidate

# Export project as markdown for human review
md = call_tool("project_to_markdown", {"project_id": project_id})

with open(os.path.join(base, "kd-survey-project.md"), "w") as f:
    f.write(md)

# Read the knowledge graph
graph = call_tool("read_graph", {})
with open(os.path.join(base, "kd-knowledge-graph.json"), "w") as f:
    json.dump(graph, f, indent=2)

Step 5: Pick up later

Because task-orchestrator persists data in /workspace/task-orchestrator/ and memory persists in /workspace/memory/, you can start a new session days later and pick up exactly where you left off:

# Load existing project
overview = call_tool("get_overview", {"project_id": project_id})

# Check what tasks are still pending
tasks = call_tool("search_tasks", {
    "project_id": project_id,
    "status": "pending"
})

# Search the knowledge graph for previous findings
findings = call_tool("search_nodes", {"query": "distillation"})

Choosing your use case

Use CaseTierKey ToolsContext NeededTime
Academic ResearchStandardpaper-search, markdownify, fetch16k+30-60 min
Web ResearchStandardduckduckgo, wikipedia, playwright16k+15-30 min
Document ProcessingStandardmarkdownify, fetch8k+10-20 min
Multi-Iteration ResearchExtendedtask-orchestrator, memory, sequentialthinking32k+Multi-day

All four use cases keep data on your machine. No cloud APIs required. No data leaves your network.

Next: Lessons Learned, Gotchas, and What’s Next