Skip to main content
Glama

PocketMCP

PocketMCP is a lightweight, local-first MCP (Model Context Protocol) server that automatically watches folders, chunks and embeds files locally using Transformers.js with MiniLM, stores vectors in SQLite + sqlite-vec, and exposes semantic search capabilities to VS Code and Cursor. Designed for small machines (I'm running on an Intel N100 with 16GB RAM) with zero external dependencies after initial model download.

Features

  • šŸ” Semantic Search: Find content by meaning, not just keywords

  • šŸ“ Auto-Ingestion: Watches folders and automatically processes new/changed files

  • šŸ“„ Multi-Format Support: PDF, DOCX, Markdown, and plain text files

  • ⚔ Local-First: Runs completely offline after initial model download

  • šŸ—„ļø SQLite Storage: Fast, reliable vector storage with sqlite-vec extension

  • šŸ”§ MCP Integration: Native support for VS Code and Cursor via MCP protocol

  • 🌐 Web Interface: Built-in web tester for validation and manual testing

  • šŸ’¾ Efficient: Designed for resource-constrained environments

  • šŸ”„ Real-time: Debounced file watching with smart concurrency limits

  • šŸ“Š Smart Segmentation: Page-aware PDF processing and section-aware DOCX handling

  • šŸ›”ļø Robust Error Handling: Graceful handling of encrypted, corrupted, or oversized files

Related MCP server: knowledgine

Architecture

flowchart TD
    subgraph "MCP Clients"
        A[VS Code] 
        B[Cursor]
    end
    
    subgraph "Web Interface"
        W1[React Frontend<br/>:5173]
        W2[Express API<br/>:5174]
    end
    
    subgraph "PocketMCP Server"
        C[MCP Server<br/>stdio transport]
        D[File Watcher<br/>chokidar]
        E[Text Chunker<br/>~1000 chars]
        F[Embeddings<br/>Transformers.js<br/>MiniLM-L6-v2]
        G[SQLite + sqlite-vec<br/>Vector Database]
    end
    
    subgraph "File System"
        H[Watch Directory<br/>./kb/]
        I[Data Directory<br/>./data/]
    end
    
    A -.->|MCP Tools| C
    B -.->|MCP Tools| C
    W1 -->|HTTP API| W2
    W2 -->|Database Access| G
    C --> D
    D -->|File Changes| E
    E -->|Text Chunks| F
    F -->|384-dim Vectors| G
    G -.->|Search Results| C
    D -.->|Monitors| H
    G -.->|Stores in| I
    
    classDef mcpClient fill:#e1f5fe
    classDef webInterface fill:#fff3e0
    classDef server fill:#f3e5f5
    classDef storage fill:#e8f5e8
    
    class A,B mcpClient
    class W1,W2 webInterface
    class C,D,E,F,G server
    class H,I storage

Performance & Limits

  • Sweet spot: 10K-100K chunks on modest hardware

  • Query latency: Sub-100ms for top_k <= 10 on typical corpora

  • Memory usage: ~100MB for model + minimal overhead per document

  • Concurrency: Limited to 3 simultaneous file operations by default

  • File size limit: 50MB per file (configurable)

Screenshots

Web Server - Stats Web Server - Search Integration - stdio Integration - http

Table of Contents

Quick Start

1. Installation

# Clone or download the project
cd PocketMCP

# Install dependencies
pnpm install

# Setup environment
pnpm setup
# Or manually: cp .env.sample .env

2. Configuration

Edit .env file:

# SQLite database path
SQLITE_PATH=./data/index.db

# Directory to watch for file changes (optional)
WATCH_DIR=./kb

# Embedding model (default is recommended)
MODEL_ID=Xenova/all-MiniLM-L6-v2

# Chunking configuration
CHUNK_SIZE=1000
CHUNK_OVERLAP=120

3. Create Content Directory

# Create directory for your documents
mkdir -p kb

# Add some markdown or text files
echo "# My First Document" > kb/test.md
echo "This is a sample document for testing PocketMCP." >> kb/test.md

4. Start the Server

# Development - MCP server + web interface
pnpm dev

# Production - MCP server only
pnpm build && pnpm start

On first run, the server will download the MiniLM model (~100MB) and then process any files in your watch directory.

Web Tester

PocketMCP includes a comprehensive web interface for testing and validation.

Access Points

Features

šŸ“Š Database Diagnostics Panel

  • Real-time database status monitoring

  • Table counts and vector dimensions

  • SQLite WAL mode verification

  • Error detection and reporting

  • One-click smoke testing

šŸ” Search Panel

  • Interactive semantic search testing

  • LIKE vs Vector search modes

  • Configurable result count (top-K)

  • Detailed result inspection

  • Performance metrics (response time)

šŸ“„ Documents Panel

  • Browse all indexed documents

  • Pagination support

  • Document metadata display

  • Creation and update timestamps

šŸ”Ž Chunk Viewer

  • Detailed chunk inspection modal

  • Full text content display

  • Metadata and offset information

  • Copy-to-clipboard functionality

API Endpoints

Endpoint

Method

Description

/health

GET

Server health check

/api/db/diag

GET

Database diagnostics

/api/search

POST

Semantic search

/api/chunk/:id

GET

Get specific chunk

/api/docs

GET

List documents

Example API Usage

Search Documents:

curl -X POST http://127.0.0.1:5174/api/search \
  -H "Content-Type: application/json" \
  -d '{"query": "machine learning", "top_k": 5, "mode": "like"}'

Get Diagnostics:

curl http://127.0.0.1:5174/api/db/diag | jq .

šŸ”§ MCP Client Integration

Cursor Integration

  1. Open Cursor Settings → MCP

  2. Add a new server:

{
  "command": "pnpm",
  "args": ["dev:mcp"],
  "cwd": "/path/to/PocketMCP",
  "env": {
    "TRANSPORT": "stdio",
    "SQLITE_PATH": "./data/index.db",
    "WATCH_DIR": "./kb"
  }
}

VS Code Integration

Add to your MCP settings:

{
  "mcpServers": {
    "pocketmcp": {
      "command": "pnpm",
      "args": ["dev:mcp"],
      "cwd": "/path/to/PocketMCP",
      "env": {
        "TRANSPORT": "stdio",
        "SQLITE_PATH": "./data/index.db",
        "WATCH_DIR": "./kb"
      }
    }
  }
}

HTTP Transport (Web Clients)

For web clients or remote access:

{
  "mcpServers": {
    "pocketmcp": {
      "transport": "http",
      "url": "http://localhost:8001/mcp"
    }
  }
}

šŸ“š API Reference

MCP Tools

Search for similar content using semantic search.

{
  "query": "machine learning algorithms",
  "top_k": 5,
  "filter": {
    "doc_ids": ["doc_123", "doc_456"]
  }
}

upsert_documents

Insert or update documents programmatically.

{
  "docs": [
    {
      "text": "Your document content here...",
      "external_id": "my_doc_1",
      "title": "Important Notes",
      "metadata": {}
    }
  ]
}

delete_documents

Delete documents by ID.

{
  "doc_ids": ["doc_123"],
  "external_ids": ["my_doc_1"]
}

list_documents

List all documents with pagination.

{
  "page": {
    "limit": 20
  }
}

MCP Resources

PocketMCP provides resource URIs for accessing specific chunks:

  • Format: mcp+doc://<doc_id>#<chunk_id>

  • Returns: Complete chunk data including text, offsets, and metadata

Configuration

Environment Variables

Variable

Default

Description

SQLITE_PATH

./data/index.db

Path to SQLite database file

WATCH_DIR

(none)

Directory to watch for file changes

MODEL_ID

Xenova/all-MiniLM-L6-v2

Hugging Face model for embeddings

CHUNK_SIZE

1000

Target chunk size in characters

CHUNK_OVERLAP

120

Overlap between chunks in characters

PDF_MAX_PAGES

300

Maximum pages to process in PDF files

PDF_MIN_TEXT_CHARS

500

Minimum text characters required in PDFs

DOC_MAX_BYTES

10000000

Maximum file size for DOCX files (10MB)

DOCX_SPLIT_ON_HEADINGS

false

Split DOCX documents on headings (h1/h2)

NODE_ENV

development

Environment mode

VERBOSE_LOGGING

false

Enable detailed logs

DEBUG_DOTENV

false

Enable dotenv debug output

API_PORT

5174

Web API server port

API_BIND

127.0.0.1

API server bind address

TRANSPORT

both

MCP transport mode (stdio/http/both)

HTTP_HOST

0.0.0.0

HTTP server bind address

HTTP_PORT

8001

MCP server port

LOG_LEVEL

info

Logging level (debug/info/warn/error)

Available Scripts

Script

Description

pnpm dev

Start web interface + API server for testing

pnpm dev:mcp

Start MCP server (both transports + file watching)

pnpm build

Build all components

pnpm start

Start production MCP server (both transports + file watching)

pnpm setup

Create .env from template

pnpm clean

Clean build artifacts and database

Watch Directory

  • WATCH_DIR is optional - if not set, only manual document upserts work

  • Supported files: .md, .txt, .pdf, .docx

  • File filtering: Automatically ignores temp files, .DS_Store, node_modules, etc.

  • Nested directories: Recursively watches all subdirectories

Document Processing

Processing Pipeline: Documents → Segments → Chunks

  1. Documents: Top-level files with metadata

  2. Segments: Logical divisions (PDF pages, DOCX sections, etc.)

  3. Chunks: Text pieces optimized for embedding (~1000 chars)

Status Types: ok, skipped, needs_ocr, too_large, error

Supported File Types

  • Markdown (.md)

  • Plain text (.txt)

  • PDF (.pdf) - Text-based only, no OCR

  • DOCX (.docx) - Microsoft Word documents

Notes:

  • Encrypted/password-protected files are skipped

  • Large files exceeding limits are marked as too_large

  • Scanned PDFs requiring OCR are marked as needs_ocr

Development

Project Structure

PocketMCP/                    # Monorepo root
ā”œā”€ā”€ package.json             # Workspace configuration
ā”œā”€ā”€ pnpm-workspace.yaml      # pnpm workspace setup
ā”œā”€ā”€ .env                     # Environment variables
ā”œā”€ā”€ .env.sample              # Environment template
ā”œā”€ā”€ apps/
│   ā”œā”€ā”€ api/                 # Express API server
│   │   ā”œā”€ā”€ src/
│   │   │   ā”œā”€ā”€ server.ts    # Main API server
│   │   │   └── db.ts        # Database manager
│   │   └── package.json
│   └── web/                 # React + Vite frontend
│       ā”œā”€ā”€ src/
│       │   ā”œā”€ā”€ App.tsx      # Main app component
│       │   ā”œā”€ā”€ store.ts     # Zustand state management
│       │   ā”œā”€ā”€ api.ts       # API client
│       │   └── components/  # UI components
│       └── package.json
ā”œā”€ā”€ src/                     # Original MCP server
│   ā”œā”€ā”€ server.ts            # MCP server and main entry point
│   ā”œā”€ā”€ db.ts                # SQLite database with sqlite-vec
│   ā”œā”€ā”€ embeddings.ts        # Transformers.js embedding pipeline
│   ā”œā”€ā”€ chunker.ts           # Text chunking with sentence awareness
│   ā”œā”€ā”€ ingest.ts            # Generic document ingestion
│   ā”œā”€ā”€ file-ingest.ts       # File-specific ingestion logic
│   └── watcher.ts           # File system watcher with debouncing
ā”œā”€ā”€ data/                    # SQLite database storage
ā”œā”€ā”€ kb/                      # Default watch directory (configurable)
└── README.md

Development Commands

# Install and setup
pnpm install
pnpm setup

# Development
pnpm dev          # Web interface + API
pnpm dev:mcp      # MCP server only

# Production
pnpm build
pnpm start

# Testing
curl http://127.0.0.1:5174/health

Deployment

Quick Start:

# Pull and run with all services (MCP + API + Web UI)
docker run -d \
  --name pocketmcp \
  --restart unless-stopped \
  -p 8001:8001 \
  -p 5174:5174 \
  -p 5173:5173 \
  -v pocketmcp_data:/app/data \
  -v pocketmcp_kb:/app/kb \
  -v pocketmcp_cache:/app/.cache \
  ghcr.io/kailash-sankar/pocketmcp:latest

Access Points:

  • MCP Server: http://localhost:8001

  • API Server: http://localhost:5174

  • Web UI: http://localhost:5173

Docker Compose:

git clone https://github.com/kailash-sankar/PocketMCP.git
cd PocketMCP
cp .env.sample .env
docker-compose up -d

Portainer Stacks

  1. Go to Stacks → Add stack

  2. Name: pocketmcp

  3. Paste this configuration:

version: '3.8'
services:
  pocketmcp:
    image: ghcr.io/kailash-sankar/pocketmcp:latest
    container_name: pocketmcp
    restart: unless-stopped
    ports:
      - "8001:8001"  # MCP Server
      - "5174:5174"  # API Server  
      - "5173:5173"  # Web UI
    volumes:
      - pocketmcp_data:/app/data
      - pocketmcp_kb:/app/kb  
      - pocketmcp_cache:/app/.cache
    environment:
      - NODE_ENV=production
      - TRANSPORT=both
      - SQLITE_PATH=/app/data/index.db
      - WATCH_DIR=/app/kb
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5173/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

volumes:
  pocketmcp_data:
  pocketmcp_kb:
  pocketmcp_cache:

Direct Installation

# Clone and setup
git clone https://github.com/kailash-sankar/PocketMCP.git
cd PocketMCP
pnpm install
pnpm setup

# Configure environment
cp .env.sample .env
# Edit .env with your settings

# Create content directory
mkdir -p kb

# Build and start
pnpm build
pnpm start

Access Points:

  • MCP Server: http://localhost:8001

  • API Server: http://localhost:5174

  • Web UI: http://localhost:5173

Troubleshooting

Model Download Issues

If the embedding model fails to download:

  • Check internet connection for initial download

  • Model cache location: ~/.cache/huggingface/transformers/

  • Clear cache and retry if needed

SQLite Extension Issues

If sqlite-vec fails to load:

  • Ensure sqlite-vec npm package is installed

  • Check that your system supports the required SQLite version

  • The system automatically falls back to regular SQLite tables if vec0 virtual tables fail

File Watching Issues

  • Files not being detected: Check file extensions and ignore patterns

  • High CPU usage: Increase debounce time with larger debounceMs values

  • Permission errors: Ensure read/write access to watch and data directories

Web Interface Issues

  • API not accessible: Ensure API server is running on port 5174

  • Database not found: Check SQLITE_PATH environment variable

  • CORS errors: API server includes CORS headers for local development

Memory Issues

  • Reduce CHUNK_SIZE for lower memory usage

  • Process fewer files simultaneously by reducing maxConcurrency

  • Consider using a smaller embedding model (though this requires code changes)

Common Error Messages

"Too many parameter values were provided"

  • This was a known issue with sqlite-vec virtual tables, now fixed with automatic fallback

"Failed to load sqlite-vec extension"

  • System automatically falls back to regular SQLite tables with JSON embeddings

"Database file does not exist"

  • Run the MCP server first to create the database, or check the SQLITE_PATH

License

MIT License - see LICENSE file for details.

Contributing

  1. Fork the repository

  2. Create a feature branch

  3. Make your changes

  4. Add tests if applicable

  5. Submit a pull request

Acknowledgments

  • sqlite-vec for fast vector similarity search

  • Transformers.js for local embedding generation

  • Model Context Protocol for standardized tool integration

  • Hugging Face for the MiniLM model

  • React + Vite for the modern web interface

  • TailwindCSS for beautiful, responsive styling

Available Tools

4 tools
delete_documentsC

Delete documents by ID or external ID

ParametersJSON Schema
NameRequiredDescriptionDefault
doc_idsNoDocument IDs to delete
external_idsNoExternal IDs to delete

TDQS

C2.9/5.0
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure but offers only the word 'Delete'. It fails to specify whether deletions are permanent or soft, what occurs if IDs don't exist, or how the tool handles the case where zero required parameters means both ID arrays are optional (which could imply bulk-deletion behavior).

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?

The description is efficiently compressed into six words with the action verb front-loaded. Every word serves a purpose with no redundant filler, making it appropriately sized for the tool's scope.

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

Completeness2/5

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

For a destructive operation with no output schema and no annotations, the description is incomplete. It omits critical behavioral context such as return values, error handling for non-existent IDs, the consequence of calling with zero parameters (since none are required), and whether deletions are atomic.

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 description coverage is 100%, documenting both 'doc_ids' and 'external_ids' as arrays for deletion. The description merely restates these parameter purposes ('by ID or external ID') without adding semantic value regarding format constraints, validation rules, or the implications of providing both versus neither parameter.

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

Purpose4/5

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

The description provides a clear verb ('Delete') and resource ('documents') with specific identifier types ('ID or external ID'). It distinguishes from siblings like 'list_documents' and 'search' (read operations) and 'upsert_documents' (create/update) through the destructive verb.

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?

The description provides no guidance on when to use this tool versus alternatives, nor does it warn about the destructive nature or prerequisites like confirmation requirements. It fails to clarify the relationship with 'upsert_documents' despite both being mutation operations.

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

list_documentsC

List all documents with pagination

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNoPagination options

TDQS

C2.6/5.0
Behavior2/5

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

Mentions pagination behavior, but without annotations, the description fails to disclose other critical traits: it doesn't confirm the read-only nature (though implied by 'list'), describe the return structure, or explain error conditions given the lack of output_schema.

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

Conciseness4/5

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

Extremely concise at only 5 words. While efficient in word count, this brevity contributes to underspecification given the lack of supporting annotations or output schema. No filler or redundancy.

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

Completeness2/5

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

Severely incomplete given zero annotations and no output_schema. The description should compensate by describing what the tool returns (document structure, total count, etc.) and confirming read-only safety, but it provides only the minimal action verb.

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 descriptioncoverage is 100%, establishing a baseline of 3. The description mentions 'pagination' which loosely maps to the 'page' parameter object, but adds no syntax guidance, format details, or constraint explanations beyond what the schemaalready provides.

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

Purpose3/5

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

States the basic action (list documents) and mentions pagination, but provides minimal scope definition. Does not explicitly distinguish from the 'search' sibling tool, which also retrieves documentsbut likely with filtering capabilities.

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?

Contains no guidance on when to use this tool versus alternatives like 'search' (for filtered queries) or 'upsert_documents'. Missing conditions or prerequisites for invocation.

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

upsert_documentsC

Insert or update documents with text content

ParametersJSON Schema
NameRequiredDescriptionDefault
docsYesArray of documents to upsert

TDQS

C2.9/5.0
Behavior2/5

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

No annotations are provided, so the description must carry full behavioral disclosure. While 'Insert or update' signals mutation, it fails to explain the upsert key logic (what field determines if it updates vs inserts), whether updates are partial or full overwrites, or potential failure modes.

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

Conciseness4/5

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

Extremely brief at eight words with no redundancy. The phrase 'with text content' front-loads the essential requirement. However, given the lack of annotations, the extreme brevity leaves critical behavioral information unstated.

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

Completeness3/5

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

Minimum viable given good schema coverage. However, with no annotations and no output schema, the description should explain the upsert matching behavior and return values. It leaves significant gaps for a mutation tool with sibling search functionality.

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?

With 100% schema coverage, the structured schema already documents all parameters adequately. The description mentions 'text content', which aligns with the required 'text' field, but adds minimal semantic value beyond what the schema provides. Baseline 3 appropriate.

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

Purpose4/5

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

The description states a specific action ('Insert or update') and resource ('documents'), and the 'upsert' terminology distinguishes it from siblings delete_documents, list_documents, and search. However, it doesn't clarify the scope or matching logic (e.g., when it inserts vs updates).

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?

Provides no guidance on when to use this tool versus alternatives. It does not mention prerequisites (like external_id for updates) or when to prefer delete_documents or search over this mutation tool.

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

TDQS

B3.4/5.0
Disambiguation5/5

Each tool has a clearly distinct purpose with no overlap: delete_documents removes documents, list_documents retrieves them, search finds similar content, and upsert_documents inserts or updates. An agent can easily tell them apart based on their specific actions.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern (e.g., delete_documents, list_documents, upsert_documents), with 'search' as a slight deviation that still fits semantically. The naming is predictable and readable throughout.

Tool Count5/5

With 4 tools, the server is well-scoped for document management, covering core operations like listing, searching, upserting, and deleting. Each tool earns its place without being too sparse or bloated.

Completeness4/5

The tool set provides strong coverage for basic document CRUD and search operations, but lacks explicit tools for actions like retrieving a single document by ID or updating metadata, which could be minor gaps agents might need to work around.

Maintenance

ActivityInactive
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

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/Kailash-Sankar/PocketMCP'

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