search_notes
Enable quick and precise retrieval of notes in TriliumNext by entering a search query. Optionally include archived notes or use fast search to exclude content scanning.
Instructions
Search notes in TriliumNext
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| fastSearch | No | Enable fast search (fulltext doesn't look into content) | |
| includeArchivedNotes | No | Include archived notes in search results | |
| query | Yes | Search query |
Input Schema (JSON Schema)
{
"properties": {
"fastSearch": {
"description": "Enable fast search (fulltext doesn't look into content)",
"type": "boolean"
},
"includeArchivedNotes": {
"description": "Include archived notes in search results",
"type": "boolean"
},
"query": {
"description": "Search query",
"type": "string"
}
},
"required": [
"query"
],
"type": "object"
}
Implementation Reference
- src/modules/searchHandler.ts:17-48 (handler)Main handler function for the search_notes tool. Validates permissions, constructs SearchOperation from arguments, calls the core search logic, formats results as MCP content response.export async function handleSearchNotesRequest( args: any, axiosInstance: any, permissionChecker: PermissionChecker ): Promise<{ content: Array<{ type: string; text: string }> }> { if (!permissionChecker.hasPermission("READ")) { throw new McpError(ErrorCode.InvalidRequest, "Permission denied: Not authorized to search notes."); } try { const searchOperation: SearchOperation = { text: args.text, searchCriteria: args.searchCriteria, limit: args.limit }; const result = await handleSearchNotes(searchOperation, axiosInstance); const resultsText = JSON.stringify(result.results, null, 2); return { content: [{ type: "text", text: `${result.debugInfo || ''}${resultsText}` }] }; } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError(ErrorCode.InvalidParams, error instanceof Error ? error.message : String(error)); } }
- src/modules/searchManager.ts:27-62 (helper)Core search logic implementation. Builds TriliumNext search query from parameters, decides on fastSearch usage, performs API call to /notes endpoint, processes and trims results.export async function handleSearchNotes( args: SearchOperation, axiosInstance: any ): Promise<SearchResponse> { // Build query from structured parameters const query = buildSearchQuery(args); if (!query.trim()) { throw new Error("At least one search parameter must be provided"); } const params = new URLSearchParams(); params.append("search", query); // Smart fastSearch logic: use fastSearch=true ONLY when ONLY text parameter is provided (no other parameters) const hasOnlyText = args.text && (!args.searchCriteria || !Array.isArray(args.searchCriteria) || args.searchCriteria.length === 0) && !args.limit; // fastSearch doesn't support limit clauses params.append("fastSearch", hasOnlyText ? "true" : "false"); params.append("includeArchivedNotes", "true"); // Always include archived notes const response = await axiosInstance.get(`/notes?${params.toString()}`); // Prepare verbose debug info if enabled const verboseInfo = createSearchDebugInfo(query, args); let searchResults = response.data.results || []; const trimmedResults = trimNoteResults(searchResults); return { results: trimmedResults, debugInfo: verboseInfo }; }
- src/index.ts:109-111 (registration)Tool dispatch registration in the main MCP server request handler switch statement.case "search_notes": return await handleSearchNotesRequest(request.params.arguments, this.axiosInstance, this);
- MCP tool definition including name, description, and inputSchema referencing shared search properties.name: "search_notes", description: "Unified search with comprehensive filtering capabilities including keyword search, date ranges, field-specific searches, attribute searches, note properties, template-based searches, note type filtering, MIME type filtering, and hierarchy navigation through unified searchCriteria structure. For simple keyword searches, use the 'text' parameter. For complex boolean logic like 'docker OR kubernetes', use searchCriteria with proper OR logic. For template search: use relation type with 'template.title' property and built-in template values like 'Calendar', 'Board', 'Text Snippet', 'Grid View', 'List View', 'Table', 'Geo Map'. For note type search: use noteProperty type with 'type' property and values from the 9 supported ETAPI types: 'text', 'code', 'render', 'search', 'relationMap', 'book', 'noteMap', 'mermaid', 'webView'. For MIME type search: use noteProperty type with 'mime' property and MIME values like 'text/javascript', 'text/x-python', 'text/vnd.mermaid', 'application/json'. Use hierarchy properties like 'parents.noteId', 'children.noteId', or 'ancestors.noteId' for navigation.", inputSchema: { type: "object", properties: searchProperties, }, }
- src/utils/validationUtils.ts:41-45 (schema)Zod schema for validating search_notes input parameters.export const searchNotesSchema = z.object({ text: z.string().optional(), searchCriteria: z.array(searchCriteriaSchema).optional(), limit: z.number().min(1, 'Limit must be at least 1').optional() });