search_collection
Search across all content types including personas, skills, agents, and prompts using keywords. Use this tool to locate specific AI behavioral profiles or other resources within DollhouseMCP's collection.
Instructions
Search for content in the collection by keywords. This searches all content types including personas (AI behavioral profiles that users activate to change AI behavior), skills, agents, prompts, etc. When a user asks to 'find a persona', search in the collection.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query for finding content. Examples: 'creative writer', 'explain like I'm five', 'coding assistant'. Users typically search for personas by their behavioral traits or names. |
Implementation Reference
- src/server/tools/CollectionTools.ts:31-46 (registration)Tool registration, schema, and thin handler for 'search_collection' tool. Schema requires 'query' string. Handler delegates to server.searchCollection(query).tool: { name: "search_collection", description: "Search for content in the collection by keywords. This searches all content types including personas (AI behavioral profiles that users activate to change AI behavior), skills, agents, prompts, etc. When a user asks to 'find a persona', search in the collection.", inputSchema: { type: "object", properties: { query: { type: "string", description: "Search query for finding content. Examples: 'creative writer', 'explain like I'm five', 'coding assistant'. Users typically search for personas by their behavioral traits or names.", }, }, required: ["query"], }, }, handler: (args: any) => server.searchCollection(args.query) },
- src/server/ServerSetup.ts:58-60 (registration)Registers the collection tools module, which includes the search_collection tool, into the MCP tool registry.// Register collection tools this.toolRegistry.registerMany(getCollectionTools(instance));
- Core handler logic for collection search: validates query, attempts GitHub API search, falls back to cache/searchSeedData, with security and logging.async searchCollection(query: string): Promise<any[]> { logger.debug(`CollectionSearch.searchCollection called with query: "${query}"`); // Validate search query for security try { validateSearchQuery(query, 1000); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.error('Search query validation failed:', { query, error: errorMessage }); ErrorHandler.logError('CollectionSearch.search.validateQuery', error, { query }); return []; } try { // First, try GitHub API search if authenticated const searchUrl = `${this.searchBaseUrl}?q=${encodeURIComponent(query)}+repo:DollhouseMCP/collection+path:library+extension:md`; logger.debug(`Attempting GitHub API search with URL: ${searchUrl}`); const data = await this.githubClient.fetchFromGitHub(searchUrl, false); // Don't require auth for search if (data.items && Array.isArray(data.items)) { logger.debug(`Found ${data.items.length} items via GitHub API search`); // Update cache with fresh data from API await this.updateCacheFromGitHubItems(data.items); return data.items; } logger.debug('GitHub API search returned no items, falling back to cache'); return []; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.debug(`GitHub API search failed: ${errorMessage}. Falling back to cached search.`); ErrorHandler.logError('CollectionSearch.search.githubApi', error, { query }); // Fallback to cached search return this.searchFromCache(query); } }
- Helper function to format search results as formatted text with icons, paths, and install/get commands.formatSearchResults(items: any[], query: string, personaIndicator: string = ''): string { if (items.length === 0) { return `${personaIndicator}๐ No content found for query: "${query}"`; } const textParts = [`${personaIndicator}๐ **Search Results for "${query}"** (${items.length} found)\n\n`]; items.forEach((item: any) => { // Extract content type from path (library/personas/creative/writer.md -> personas) const pathParts = item.path.split('/'); const contentType = pathParts[1] || 'content'; const contentIcons: { [key: string]: string } = { 'personas': '๐ญ', 'skills': '๐ ๏ธ', 'agents': '๐ค', 'prompts': '๐ฌ', 'templates': '๐', 'tools': '๐ง', 'ensembles': '๐ผ' }; const icon = contentIcons[contentType] || '๐'; textParts.push( ` ${icon} **${item.name.replace('.md', '')}**\n`, ` ๐ Path: ${item.path}\n`, ` ๐ฅ Install: \`install_collection_content "${item.path}"\`\n`, ` ๐๏ธ Details: \`get_collection_content "${item.path}"\`\n\n` ); }); return textParts.join(''); }