browse_collection
Explore and filter AI personas, skills, agents, and templates from the DollhouseMCP collection by section and content type to manage dynamic AI behavior profiles effectively.
Instructions
Browse content from the DollhouseMCP collection by section and content type. Content types include personas (AI behavioral profiles), skills, agents, and templates. When users ask for 'personas', they're referring to content in the personas type.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| section | No | Collection section to browse (library, showcase, catalog). Leave empty to see all sections. | |
| type | No | Content type within the library section: personas, skills, agents, or templates. Only used when section is 'library'. |
Implementation Reference
- src/server/tools/CollectionTools.ts:10-29 (registration)Registration of the 'browse_collection' tool, including its name, description, input schema, and handler function that delegates to server.browseCollection(section, type).{ tool: { name: "browse_collection", description: "Browse content from the DollhouseMCP collection by section and content type. Content types include personas (AI behavioral profiles), skills, agents, and templates. When users ask for 'personas', they're referring to content in the personas type.", inputSchema: { type: "object", properties: { section: { type: "string", description: "Collection section to browse (library, showcase, catalog). Leave empty to see all sections.", }, type: { type: "string", description: "Content type within the library section: personas, skills, agents, templates, or memories. Only used when section is 'library'.", }, }, }, }, handler: (args: any) => server.browseCollection(args?.section, args?.type) },
- Input schema definition for the 'browse_collection' tool, specifying optional 'section' and 'type' parameters.inputSchema: { type: "object", properties: { section: { type: "string", description: "Collection section to browse (library, showcase, catalog). Leave empty to see all sections.", }, type: { type: "string", description: "Content type within the library section: personas, skills, agents, templates, or memories. Only used when section is 'library'.", }, }, },
- Core handler logic for browsing the collection: prioritizes index, falls back to GitHub API, then cache/seed data. Filters for MCP-supported types and formats directory listings.async browseCollection(section?: string, type?: string): Promise<{ items: any[], categories: any[], sections?: any[] }> { try { // Try using collection index first for faster browsing const indexResult = await this.browseFromIndex(section, type); if (indexResult) { logger.debug('Used collection index for browsing'); return indexResult; } // Fallback to GitHub API let url = this.baseUrl; // If no section provided, show top-level sections if (!section) { const data = await this.githubClient.fetchFromGitHub(url, false); if (!Array.isArray(data)) { throw new Error('Invalid collection response. Expected directory listing.'); } // Filter to only show content directories const sections = data.filter((item: any) => item.type === 'dir' && ['library', 'showcase', 'catalog'].includes(item.name) ); return { items: [], categories: [], sections }; } // Browse within a section url = type ? `${this.baseUrl}/${section}/${type}` : `${this.baseUrl}/${section}`; const data = await this.githubClient.fetchFromGitHub(url, false); if (!Array.isArray(data)) { throw new Error('Invalid collection response. Expected directory listing.'); } // In the library section, we have content type directories if (section === 'library' && !type) { // Filter to only show MCP-supported content types const contentTypes = data.filter((item: any) => { if (item.type !== 'dir') return false; const elementType = isElementType(item.name) ? item.name as ElementType : null; return elementType && isMCPSupportedType(elementType); }); return { items: [], categories: contentTypes }; } // For library content types, show files directly (flat structure) const items = data.filter((item: any) => item.type === 'file' && item.name.endsWith('.md')); // For non-library sections, they might still have subdirectories const categories = section === 'library' ? [] : data.filter((item: any) => item.type === 'dir'); return { items, categories }; } catch (error) { logger.debug(`GitHub API browse failed, falling back to cache: ${error}`); // Fallback to cached data return this.browseFromCache(section, type); } }
- Helper method to browse using the fast collection index, with fallback null if unavailable.private async browseFromIndex(section?: string, type?: string): Promise<{ items: any[], categories: any[], sections?: any[] } | null> { try { const index = await this.indexManager.getIndex(); // If no section provided, show top-level sections if (!section) { const sections = [ { name: 'library', type: 'dir' }, { name: 'showcase', type: 'dir' }, { name: 'catalog', type: 'dir' } ]; return { items: [], categories: [], sections }; } // In the library section, we have content type directories if (section === 'library' && !type) { // Get unique content types from index const contentTypes = this.getContentTypesFromIndex(index); return { items: [], categories: contentTypes }; } // Get items for specific type or all items in section const items = this.getItemsFromIndex(index, section, type); const formattedItems = this.convertIndexItemsToGitHubFormat(items); return { items: formattedItems, categories: [] }; } catch (error) { logger.debug('Failed to browse from collection index', { error: error instanceof Error ? error.message : String(error) }); return null; } } /** * Get unique content types from collection index */ private getContentTypesFromIndex(index: CollectionIndex): any[] { const types = new Set<string>(); // Extract types from index keys and filter for MCP-supported types