Search notes
search_notesSearch the user's notes. Words are matched against the note's text, its tags, and the title, description and URL of any link saved with it; a word of three characters or fewer counts only as a whole word. The default mode ("auto") escalates only as far as it needs to: every word, then any word, then meaning — and the reply's matched field says which one answered, so a relaxed or semantic result is never mistaken for an exact one. Pin the strategy with mode="keyword" (every word must appear; never widens), "semantic" (meaning only) or "hybrid" (both, fused). Source, date, photo and thread filters compose with the text query and tags. Filter by tag with tags, which is the right tool for a request like "my #bug notes". An empty result carries hints: what the collection actually contains and which query to try next — read them instead of guessing another wording. Bodies are omitted unless you pass full=true; complete imported source metadata is omitted with them. Compact notes come back as { id, label, user_text, tags, source, root_id, parent_id, is_thread_head, thread_count, updated_at, … }. user_text is only text deliberately written by the user; imported page or social-post copy is source metadata. label names the note even when it has no title — use it when showing a note to a human. updated_at is what you pass back as if_updated_at when you write.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | Include each note’s body. Default false — leave it off for wide searches. | |
| mode | No | Default auto: exact first, widening only if that finds nothing. Pin to keyword for strictly deterministic matching, or to semantic/hybrid to force meaning-based retrieval. | |
| tags | No | Only notes carrying ALL of these tags. Case-insensitive, no leading #. A tag also covers everything under it: "notemcp" matches a note tagged "notemcp/bug/share", so filter by the broadest level that answers the question and narrow only if you get too much back. Matching is from the start of the path: "main" does not match "features/main". | |
| limit | No | Max results (default 20, max 100) | |
| query | No | Words to match. Omit to use filters alone. | |
| offset | No | Skip this many results, for paging | |
| root_id | No | Return the thread head and continuations belonging to this root note. | |
| archived | No | Default exclude. | |
| has_photos | No | Whether the note has a body attachment or a retrievable link-preview thumbnail. | |
| has_source | No | Whether imported URL/title/description/image source metadata exists. | |
| source_type | No | Exact capture/source type, such as "share" or "agent". | |
| created_after | No | Created at or after this timestamp (inclusive). | |
| source_domain | No | Exact source hostname, case-insensitive and ignoring a leading www., such as "instagram.com". | |
| updated_after | No | Updated at or after this timestamp (inclusive). | |
| created_before | No | Created before this timestamp (exclusive). | |
| updated_before | No | Updated before this timestamp (exclusive). |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| error | No | ||
| hints | No | Present only when notes is empty: concrete next queries worth trying. | |
| notes | No | ||
| notice | No | Present when the answer is not what was asked for — a fallback or degradation. | |
| matched | No | Which strategy produced these notes. "any_term" means the every-word search found nothing and this is a relaxed any-word fallback. | |
| withheld | No | How many further notes matched but were not read, because this connection reads only part of a large collection. Present only when greater than zero. Those notes still exist and are searchable inside NoteMCP — they are invisible to this connection, not deleted. Treat the answer as incomplete and say so, rather than reporting that the user has nothing on the subject. | |
| capabilities | No | Present only when a retrieval capability is unavailable. |