TOOL API
search_ documents
Escalation tool — never the first discovery step. Always start with `browse_documents()` (after `get_folder_structure()` when visible). Pick a mode: • mode="query" — keyword precision when browse missed a known doc by precise term, acronym, or file-name fragment. AND match with graded OR fallback; sorted by upload date — judge relevance yourself, no semantic ranking. • mode="metadata" — structured filter / sort / aggregates over the declared schema. Use after browse missed a typed-attribute query, OR for counts / averages / extremes browse cannot answer. Call `get_metadata_schema()` FIRST to confirm field names and types — guessing risks silent zero-match.
Call information
- Tool slug
- pageindex-mcp.search_documents
- Provider
- PageIndex
- Average response
- 0 ms
- Calls in 7 days
- 0
Input parameters
modeSearch mode (default "query"). Pick exactly one based on the user's intent. "query": keyword precision search. Provide `query` (keyword[s], not a sentence). Use as an ESCALATION when `browse_documents(sort="relevance")` + the persistence retries missed a document by precise term, acronym, or file-name fragment. "metadata": structured query against the declared metadata schema. Provide `metadata: { metadata_filter?, sort?, aggregates?, group_by? }`. Use as a FALLBACK after browse paths missed a typed-attribute query, OR DIRECTLY for structural questions `browse_documents()` cannot answer (counts / averages / extremes).
queryKeyword query (required when mode="query", forbidden otherwise). Pass keyword(s) only — NOT a natural-language sentence. Multiple keywords are AND-matched: every token must appear in the file name or description. Examples: "machine learning safety" ✓; "documents about machine learning safety" ✗ (stop words "documents"/"about" will block matches).
metadataStructured metadata query (mode='metadata' only). Inner shape: { metadata_filter?, sort?, aggregates?, group_by? } — at least one of `metadata_filter`, `aggregates`, or `group_by` is required. The four MUST be nested under this top-level `metadata` object — passing them as siblings of `mode` fails schema validation. Literal call shape (full library count): {"mode":"metadata","recursive":true,"metadata":{"aggregates":{"n":{"$count":{}}}}} Literal call shape (per-category count): {"mode":"metadata","recursive":true,"metadata":{"group_by":["category"],"aggregates":{"n":{"$count":{}}}}} Use as a FALLBACK after browse paths missed a typed-attribute query, OR DIRECTLY for structural questions `browse_documents()` cannot answer (counts / averages / extremes / per-value distributions). Call `get_metadata_schema()` FIRST to discover available field names and types. When `group_by` is present the response is `{groups, total, truncated}` instead of `{documents, ...}` — group rows flatten the group keys + aggregate aliases. metadata_filter: Optional MongoDB-style filter over document metadata fields. Call get_metadata_schema() FIRST to discover available fields + types — a wrong field name or value type silently returns zero matches. Shape: flat dict. Same-level keys are ANDed implicitly. Operators: short form {"k":v} (= $eq), $eq $ne $in $gt $gte $lt $lte $and $or. Examples: {"year":2024} · {"year":{"$gte":2020}} · {"$or":[{"source":"web"},{"source":"docs"}]} · {"$and":[{"year":{"$gte":2020}},{"type":{"$in":["pdf","md"]}}]}. One operator per leaf — to range-AND the same field, wrap two leaves in $and. Types must match storage exactly ({"year":2024} ≠ {"year":"2024"}). $ne matches when the field is missing. Field names must match ^[a-zA-Z][a-zA-Z0-9_]*$; max 5 levels of $and/$or nesting. Covers your own documents only — shared folders are excluded. NOT supported: $regex $exists $nin $not $nor $all $elemMatch $size. sort: Optional MongoDB-style sort spec. Shape: dict mapping field names to 1 (asc) or -1 (desc); insertion order is significant. Example: {"score":-1,"year":1}. Max 5 fields. _id and $meta are not allowed. Backend default ordering is createdAt DESC; id ASC is auto-appended as tiebreaker. aggregates: Optional $group-style accumulators over the FULL filter match (limit/offset are ignored). Shape: {alias: {$op: arg}}, max 10 entries; aliases must match ^[a-zA-Z][a-zA-Z0-9_]*$. Operators: $count $sum $avg $max $min. $count value MUST be an empty object: {"n":{"$count":{}}} ✓; {"n":{"$count":1}} ✗; {"n":{"$count":"$field"}} ✗. $sum: 1 (literal) → COUNT(*); $sum: "$field" sums field. $avg/$max/$min require "$field". Field references resolve to METADATA fields with the bare name — write "$year" (NOT "$metadata.year", NOT a top-level field like "$pageNum"). Non-numeric values in numeric aggregators return null. Full example: {"n":{"$count":{}},"total_pages":{"$sum":"$page_count"},"latest":{"$max":"$revision_date"}} — 1 unconditional count, 1 numeric sum, 1 max over a string field. For per-value breakdowns (counts/distribution by category) prefer `group_by` over running one $count per value. NOT supported: $group _id, $push, $addToSet, $first, $last, $stdDev, $percentile, $lookup, $unwind, $facet, expressions like {$multiply: [...]}. group_by: Optional axes to GROUP BY — flat array of metadata field names, max 5. Only metadata fields are grouped (document columns like folderId are not); documents missing a field bucket into a single null group. When present the response switches from a documents list to {groups, total, truncated}; `aggregates` becomes REQUIRED and `offset` is ignored. Aggregate aliases must NOT collide with group_by field names (output column collision → 400). `sort` keys must be one of the group_by fields or an aggregate alias; default ordering is the group keys ASC in declared order. Example: group_by=["category"], aggregates={"n":{"$count":{}}} → [{"category":"AHU","n":24},{"category":"Centrifugal","n":72}]. Use this for per-value counts / distributions instead of running one filtered $count per value.
folder_idFolder scope (default "root"). Pass a specific folder ID to scope into that folder, or "root" to reference the library root. Combine with `recursive` to control breadth. Mirrors browse_documents — copy a folder_id from a browse response verbatim.
recursiveWhether to include documents from descendant folders. When true (default), searches the entire subtree of folder_id — for "root" that means the whole library, including the read-only "shared-with-me" and "following" folders. Set false to restrict to the direct contents of folder_id: root-level documents for "root", directly-shared documents for the read-only folders. Guidance differs by mode: • mode="query" (keyword): keep the default (true) for a broad recall; narrow to false only to target a specific folder's direct contents. • mode="metadata": keep recursive=true (default) for any library-wide filter / count / aggregate. recursive=false with folder_id="root" matches only documents that sit DIRECTLY at root with no parent folder (almost always 0). Metadata queries cover your own documents only — shared folders are never included.
limitNumber of documents to return (0-50). Default 10, except when `mode="metadata"` carries `aggregates` — then the default is 0 (skip the docs payload). With `group_by` it caps group rows instead, default 50.
offsetZero-based pagination offset (mode="metadata" only — keyword mode does not paginate). Pass `next_offset` from a previous metadata response to fetch the next page.
metadata_filtermode="query" only — narrows keyword hits to documents matching this filter. For mode="metadata", put the filter inside `metadata.metadata_filter`. Optional MongoDB-style filter over document metadata fields. Call get_metadata_schema() FIRST to discover available fields + types — a wrong field name or value type silently returns zero matches. Shape: flat dict. Same-level keys are ANDed implicitly. Operators: short form {"k":v} (= $eq), $eq $ne $in $gt $gte $lt $lte $and $or. Examples: {"year":2024} · {"year":{"$gte":2020}} · {"$or":[{"source":"web"},{"source":"docs"}]} · {"$and":[{"year":{"$gte":2020}},{"type":{"$in":["pdf","md"]}}]}. One operator per leaf — to range-AND the same field, wrap two leaves in $and. Types must match storage exactly ({"year":2024} ≠ {"year":"2024"}). $ne matches when the field is missing. Field names must match ^[a-zA-Z][a-zA-Z0-9_]*$; max 5 levels of $and/$or nesting. Covers your own documents only — shared folders are excluded. NOT supported: $regex $exists $nin $not $nor $all $elemMatch $size.