Skip to main content
Glama
search-content.ts4.73 kB
/** * MCP Tool: tableau_search_content * * Purpose: Search across all Tableau content (workbooks, views, data sources, projects) * Parameters: * - searchTerm (required): Search query text * - contentType (optional): Filter by content type * Returns: Array of search results with id, name, type, contentUrl */ import { z } from 'zod'; import { TableauClient } from '../tableau-client.js'; // Zod schema for input validation export const SearchContentArgsSchema = z.object({ searchTerm: z.string().min(1).describe('Search query text (required)'), contentType: z.enum(['workbook', 'view', 'datasource', 'project']).optional().describe('Optional: Filter by content type'), }); export type SearchContentArgs = z.infer<typeof SearchContentArgsSchema>; /** * Handler for tableau_search_content tool * * Searches across all Tableau content types (workbooks, views, data sources, projects). * Supports filtering by specific content type. * * @param args - Tool arguments (searchTerm, contentType) * @param tableauClient - Initialized Tableau client instance * @returns Formatted response with search results or error */ export async function searchContentHandler( args: SearchContentArgs, tableauClient: TableauClient ): Promise<{ content: Array<{ type: string; text: string }> }> { try { // Validate searchTerm is provided if (!args.searchTerm || args.searchTerm.trim() === '') { return { content: [{ type: 'text', text: 'Error: searchTerm is required and cannot be empty.' }] }; } // Call TableauClient to search content const results = await tableauClient.searchContent( args.searchTerm, args.contentType ); // Format response for LLM consumption if (results.length === 0) { const typeFilter = args.contentType ? ` of type '${args.contentType}'` : ''; return { content: [{ type: 'text', text: `No results found for search term '${args.searchTerm}'${typeFilter}.` }] }; } // Group results by content type for better readability const resultsByType: Record<string, typeof results> = {}; results.forEach(result => { if (!resultsByType[result.type]) { resultsByType[result.type] = []; } resultsByType[result.type].push(result); }); // Create a summary with count and details grouped by type const typeFilter = args.contentType ? ` (filtered by: ${args.contentType})` : ''; let summary = `Found ${results.length} result(s) for '${args.searchTerm}'${typeFilter}:\n\n`; // Add results grouped by type Object.entries(resultsByType).forEach(([type, items]) => { summary += `\n${type.toUpperCase()}S (${items.length}):\n`; items.forEach((item, index) => { summary += `\n${index + 1}. ${item.name}\n` + ` ID: ${item.id}\n` + ` Content URL: ${item.contentUrl}\n` + ` Type: ${item.type}`; }); summary += '\n'; }); // Also include raw JSON data for structured access const jsonData = JSON.stringify(results, null, 2); return { content: [ { type: 'text', text: summary }, { type: 'text', text: `\n\nRaw JSON data:\n${jsonData}` } ] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; // Provide helpful error messages if (errorMessage.includes('invalid') && args.contentType) { return { content: [{ type: 'text', text: `Error: Invalid content type '${args.contentType}'. Valid types are: workbook, view, datasource, project.` }] }; } return { content: [{ type: 'text', text: `Error searching content: ${errorMessage}` }] }; } } // Tool metadata for MCP server registration export const searchContentTool = { name: 'tableau_search_content', description: 'Search across all Tableau content including workbooks, views, data sources, and projects. Supports filtering by content type. Returns matching items with ID, name, type, and content URL. Use this to discover content when you don\'t know the exact ID.', inputSchema: { type: 'object', properties: { searchTerm: { type: 'string', description: 'Required: Search query text to find matching content' }, contentType: { type: 'string', enum: ['workbook', 'view', 'datasource', 'project'], description: 'Optional: Filter results by content type (workbook, view, datasource, or project)' } }, required: ['searchTerm'] } };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/russelenriquez-agile/tableau-mcp-project'

If you have feedback or need assistance with the MCP directory API, please join our Discord server