search-backbone
Search across Backbone.js documentation chapters for specific text. Retrieve relevant chapter links and excerpts based on query, case sensitivity, and desired number of excerpts.
Instructions
Busca texto en los capítulos Markdown y devuelve enlaces a los capítulos con coincidencias.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| caseSensitive | No | Distinguir mayúsculas/minúsculas | |
| maxExcerpts | No | Número de fragmentos por capítulo | |
| query | Yes | Texto a buscar |
Implementation Reference
- src/server.ts:76-102 (handler)MCP tool handler for 'search-backbone': parses args, calls searchResources helper, formats results as text summary and resource links.async (args) => { const query = args.query; const caseSensitive = args.caseSensitive; const maxExcerpts = args.maxExcerpts; const results = searchResources(query, { caseSensitive, maxExcerpts }); if (!results.length) { return { content: [ { type: "text", text: `Sin coincidencias para "${query}".` } ] }; } const content: Array<any> = []; content.push({ type: "text", text: `Coincidencias: ${results.length} capítulos para "${query}".` }); for (const r of results) { content.push({ type: "resource_link", uri: r.uri, name: `Capítulo ${String(r.chapter).padStart(2, '0')} — ${r.title}`, mimeType: r.mimeType, description: r.excerpts[0] ?? undefined, }); } return { content }; }
- src/server.ts:67-75 (schema)Input schema definition using Zod for the 'search-backbone' tool, including query (required), caseSensitive and maxExcerpts (optional).{ title: "Buscar en capítulos Backbone", description: "Busca texto en los capítulos Markdown y devuelve enlaces a los capítulos con coincidencias.", inputSchema: { query: z.string().min(2, 'La consulta debe tener al menos 2 caracteres').describe('Texto a buscar'), caseSensitive: z.boolean().optional().describe('Distinguir mayúsculas/minúsculas'), maxExcerpts: z.number().int().min(1).max(5).optional().describe('Número de fragmentos por capítulo'), } },
- src/server.ts:65-66 (registration)Registration of the 'search-backbone' tool on the MCP server.server.registerTool( "search-backbone",
- src/mcp-server.ts:49-103 (helper)Core helper function implementing text search across Backbone chapters using regex, extracting excerpts and sorting by occurrence count.export const searchResources = ( query: string, opts?: { caseSensitive?: boolean; maxExcerpts?: number } ): SearchMatch[] => { const q = (query ?? '').trim(); if (!q) return []; loadResources(); const escapeRegExp = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const flags = opts?.caseSensitive ? 'g' : 'gi'; const regex = new RegExp(escapeRegExp(q), flags); const maxExcerpts = Math.max(1, Math.min(10, opts?.maxExcerpts ?? 3)); const matches: SearchMatch[] = []; for (const r of cachedResources) { const text = r.content.text ?? ''; if (!text) continue; let occurrences = 0; const excerpts: string[] = []; let m: RegExpExecArray | null; while ((m = regex.exec(text)) !== null) { occurrences++; if (excerpts.length < maxExcerpts) { const start = Math.max(0, m.index - 60); const end = Math.min(text.length, m.index + m[0].length + 60); const snippet = `${start > 0 ? '…' : ''}${text .slice(start, end) .replace(/\s+/g, ' ') .trim()}${end < text.length ? '…' : ''}`; excerpts.push(snippet); } if (regex.lastIndex === m.index) regex.lastIndex++; // evitar bucles con coincidencias vacías } if (occurrences > 0) { const chapter = r.metadata?.chapter ?? 0; const title = r.metadata?.title ?? `Capítulo ${chapter}`; const uri = `backbone://chapter/${String(chapter).padStart(2, '0')}`; matches.push({ chapter, title, uri, mimeType: r.content.mimeType, occurrences, excerpts, }); } } return matches.sort((a, b) => b.occurrences - a.occurrences); }