Sifter - Turn a folder of documents into typed records you can query
About
Sifter extracts structured, typed records from your documents (PDFs, scans, contracts, invoices) using a natural-language field spec, then lets an agent query and aggregate them — exact counts, sums, filters, with citations back to the source page. Unlike RAG, it answers collecti
Details
- Author
- sifter-ai
- Downloads
- 249
- Categories
- Other, Knowledge Base, Productivity
Jump to
- Extract typed records from any document using natural language
- Query and aggregate over all records with exact answers
- Every value cited back to source page and bounding box
- Supports PDFs, scans, images, contracts, receipts, invoices
- Self-host locally for free with your own model (MIT license)
- Connect via hosted endpoint or local Docker deployment
Setting up with Highlight
This MCP is not yet compatible with Highlight’s one-click setup. However, you can still use it with Highlight by following these steps:
- Download and install Highlight from highlightai.com/download
- Navigate to the plugins tab and select "Add Custom Plugin"
-
Configure the plugin with the settings below
Plugin Name
Sifter - Turn a folder of documents into typed records you can queryCommand (node, npx, python, etc.)Please refer to the README for specific instructions on how to obtain API keys or other required environment variables.
- Enable "Start Automatically" if you want the plugin to start when Highlight launches
From the repository
Connect via an MCP client configuration: remote (hosted endpoint with Bearer API key) or local (self-hosted using uvx sifter-mcp and docker compose up -d). Once connected, use the server’s tools to create a sift (define extraction fields in plain language), upload documents (PDFs, scans, images, etc.), and then list, filter, or aggregate records with full citations.
list_sifts
List sifts with their name, instructions, and document/record counts. Args: limit: Maximum number of sifts to return (default 50, max 200) offset: Number of sifts to skip for pagination
get_sift
Get sift metadata and inferred extraction schema for a specific sift.
list_records
Get extracted records from a sift. Args: sift_id: The sift identifier limit: Maximum number of records to return (default 20, max 100) offset: Number of records to skip (ignored when cursor is provided) cursor: Opaque pagination cursor from a previous call's next_cursor field
query_sift
Run a natural language query over a sift's extracted records. Args: sift_id: The sift identifier natural_language: The question to answer (e.g. "What is the total by client?")
list_folders
List folders with their name and document count. Args: limit: Maximum number of folders to return (default 100, max 200) offset: Number of folders to skip for pagination
get_folder
Get folder metadata, linked sifts, and document list for a specific folder. Args: folder_path: Folder path (e.g. '/invoices/2025')
get_record_citations
Get per-field citation map for a record (page, bbox, source text for each field). Args: sift_id: The sift identifier record_id: The record identifier
create_sift
Create a new sift with the given extraction instructions. Args: name: Human-readable sift name instructions: Natural language extraction instructions (e.g. "client, date, total") folder_path: Optional folder path to link (e.g. '/invoices/2025'); created if it doesn't exist
update_sift
Update an existing sift's name or instructions. Args: sift_id: The sift identifier name: New name (leave empty to keep current) instructions: New instructions (leave empty to keep current)
delete_sift
Delete a sift and all its records. Args: sift_id: The sift identifier
upload_document
Upload a document to a folder. The folder is created if it doesn't exist. The document will be processed by all sifts linked to the folder. Args: folder_path: Target folder path (e.g. '/invoices/2025'). Created if it doesn't exist. filename: Original filename (used for display) content_base64: Base64-encoded file bytes
run_extraction
Enqueue extraction for a document on a specific sift. Args: document_id: The document identifier sift_id: The sift to extract with
get_extraction_status
Check extraction status for a document on a sift. Args: document_id: The document identifier sift_id: The sift identifier Returns: {"status": "queued|running|completed|failed", "error": "..." (on failure)}
find_records
Filter records with structured criteria (no LLM roundtrip). Args: sift_id: The sift identifier filter: Mongo-subset filter dict e.g. {"total": {"$gt": 1000}} sort: Optional sort spec e.g. [["date", -1]] limit: Max records to return (default 50) cursor: Opaque pagination cursor from a previous call Returns: {"records": [...], "next_cursor": "..." | null}
aggregate_sift
Run a MongoDB aggregation pipeline against a sift's records. Args: sift_id: The sift identifier pipeline: MongoDB aggregation pipeline stages e.g. [{"$group": {"_id": "$client", "total": {"$sum": "$total"}}}] Returns: Array of aggregated rows
Claude Desktop / Cursor
Paste into your MCP client config file to install this server.
{
"mcpServers": {
"sifter - turn a folder of documents into typed records you can query": {
"sifter": {
"command": "uvx",
"args": [
"sifter-mcp",
"--base-url",
"https://api.sifter.run/api"
],
"env": {
"SIFTER_API_KEY": "sk-..."
}
}
}
}
}
McpServers
{
"sifter": {
"command": "uvx",
"args": [
"sifter-mcp",
"--base-url",
"https://api.sifter.run/api"
],
"env": {
"SIFTER_API_KEY": "sk-..."
}
}
}
Sifter MCP Server
Turn a folder of documents into a database your agent can query. RAG is great at finding a passage. It can't answer the questions people actually ask about a pile of documents — "how many invoices are unpaid", "total billed to this client this year", "which contracts expire in the next 90 days". Those are aggregations over the whole collection, and top-k retrieval only ever sees a handful of docs. Sifter takes a different path: it extracts every document into a typed record (you describe the fields in plain language, the schema is inferred), then exposes them over MCP so your agent can query and aggregate them — exact counts, sums, filters, group-bys — with every field cited back to its source page. Not a paragraph. A figure.What the agent can do
- Create a sift — define an extraction in natural language (e.g. "from invoices: client, date, total — skip anything that isn't an invoice"). - Upload documents — PDFs, scans, contracts, receipts, images. - List & filter records — typed fields, real filters. - Aggregate — counts, sums, group-bys over all records, not a sample. - Get citations — trace any value back to its source document, page, and bounding box.Connect
Remote (hosted, zero install — Starter+)
``json
{
"mcpServers": {
"sifter": {
"url": "https://api.sifter.run/mcp",
"headers": { "Authorization": "Bearer sk-..." }
}
}
}
`
Get an API key at sifter.run → API Keys. The remote endpoint is a
Starter+ feature; free-plan keys receive 402 on tool calls.
Local (self-host, free, MIT — bring your own model)
`json
{
"mcpServers": {
"sifter": {
"command": "uvx",
"args": ["sifter-mcp", "--base-url", "http://localhost:8000"],
"env": { "SIFTER_API_KEY": "sk-..." }
}
}
}
`
Run the open-source engine with docker compose up -d` and point the server at your instance.
Local models work — the LLM is only the extractor, so nothing has to leave your machine.
Try it
> "How much have we invoiced per client this year, highest first?" > "What's the total unpaid across all invoices?" > "Which contracts expire in the next 90 days?" Each runs as a real query over every record and returns an exact answer, traceable to the source.Links
- Repo (open source, MIT): https://github.com/sifter-ai/sifter - Docs: https://docs.sifter.run - Hosted: https://sifter.run Tags: document-extraction · structured-data · rag · pdf · ocr · data · agents · invoices · self-hostedSign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.





