get-metadata.ts•6.21 kB
/**
* MCP Tool: tableau_get_metadata
*
* Purpose: Get comprehensive metadata for a workbook or view
* Parameters:
* - contentId (required): Workbook or view identifier
* - contentType (required): 'workbook' or 'view'
* Returns: Detailed metadata including fields, data sources, permissions, etc.
*/
import { z } from 'zod';
import { TableauClient } from '../tableau-client.js';
// Zod schema for input validation
export const GetMetadataArgsSchema = z.object({
contentId: z.string().min(1).describe('Content identifier (required)'),
contentType: z.enum(['workbook', 'view']).describe('Content type: workbook or view (required)'),
});
export type GetMetadataArgs = z.infer<typeof GetMetadataArgsSchema>;
/**
* Handler for tableau_get_metadata tool
*
* Retrieves comprehensive metadata for a workbook or view including
* basic info, timestamps, project, owner, tags, and related resources.
*
* @param args - Tool arguments (contentId, contentType)
* @param tableauClient - Initialized Tableau client instance
* @returns Formatted response with metadata or error
*/
export async function getMetadataHandler(
args: GetMetadataArgs,
tableauClient: TableauClient
): Promise<{ content: Array<{ type: string; text: string }> }> {
try {
// Validate required parameters
if (!args.contentId || args.contentId.trim() === '') {
return {
content: [{
type: 'text',
text: 'Error: contentId is required and cannot be empty.'
}]
};
}
if (!args.contentType) {
return {
content: [{
type: 'text',
text: 'Error: contentType is required. Must be either "workbook" or "view".'
}]
};
}
// Route to appropriate method based on content type
let metadata: any;
if (args.contentType === 'workbook') {
metadata = await tableauClient.getWorkbookMetadata(args.contentId);
} else if (args.contentType === 'view') {
metadata = await tableauClient.getViewMetadata(args.contentId);
} else {
return {
content: [{
type: 'text',
text: `Error: Invalid contentType '${args.contentType}'. Must be either 'workbook' or 'view'.`
}]
};
}
// Format response for LLM consumption
let summary = `Metadata for ${args.contentType}: ${metadata.name}\n\n`;
// Basic information
summary += `BASIC INFORMATION:\n`;
summary += `ID: ${metadata.id}\n`;
summary += `Name: ${metadata.name}\n`;
summary += `Content URL: ${metadata.contentUrl || 'N/A'}\n`;
if (metadata.description) {
summary += `Description: ${metadata.description}\n`;
}
// Timestamps
summary += `\nTIMESTAMPS:\n`;
if (metadata.createdAt) {
summary += `Created: ${new Date(metadata.createdAt).toLocaleString()}\n`;
}
if (metadata.updatedAt) {
summary += `Updated: ${new Date(metadata.updatedAt).toLocaleString()}\n`;
}
// Project information
if (metadata.project) {
summary += `\nPROJECT:\n`;
summary += `Name: ${metadata.project.name}\n`;
summary += `ID: ${metadata.project.id}\n`;
}
// Owner information
if (metadata.owner) {
summary += `\nOWNER:\n`;
summary += `Name: ${metadata.owner.name || metadata.owner.id}\n`;
summary += `ID: ${metadata.owner.id}\n`;
}
// Tags
if (metadata.tags && metadata.tags.length > 0) {
summary += `\nTAGS:\n`;
summary += metadata.tags.map((tag: any) => `- ${tag.label || tag}`).join('\n') + '\n';
}
// Workbook-specific: Views and Data Sources
if (args.contentType === 'workbook') {
if (metadata.views && metadata.views.length > 0) {
summary += `\nVIEWS (${metadata.views.length}):\n`;
metadata.views.forEach((view: any, index: number) => {
summary += `${index + 1}. ${view.name} (ID: ${view.id})\n`;
});
}
if (metadata.dataSources && metadata.dataSources.length > 0) {
summary += `\nDATA SOURCES (${metadata.dataSources.length}):\n`;
metadata.dataSources.forEach((ds: any, index: number) => {
summary += `${index + 1}. ${ds.name} (ID: ${ds.id})\n`;
});
}
}
// View-specific: Workbook reference
if (args.contentType === 'view' && metadata.workbook) {
summary += `\nPARENT WORKBOOK:\n`;
summary += `Name: ${metadata.workbook.name}\n`;
summary += `ID: ${metadata.workbook.id}\n`;
}
// Also include raw JSON data for structured access
const jsonData = JSON.stringify(metadata, 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('404') || errorMessage.includes('not found')) {
return {
content: [{
type: 'text',
text: `Error: ${args.contentType} with ID '${args.contentId}' not found. Please verify the ID is correct and you have access to it.`
}]
};
}
return {
content: [{
type: 'text',
text: `Error retrieving metadata: ${errorMessage}`
}]
};
}
}
// Tool metadata for MCP server registration
export const getMetadataTool = {
name: 'tableau_get_metadata',
description: 'Get comprehensive metadata for a workbook or view. Returns detailed information including basic info, timestamps, project, owner, tags, and related resources. For workbooks: includes list of views and data sources. For views: includes parent workbook reference.',
inputSchema: {
type: 'object',
properties: {
contentId: {
type: 'string',
description: 'Required: Content identifier (workbook ID or view ID)'
},
contentType: {
type: 'string',
enum: ['workbook', 'view'],
description: 'Required: Type of content (workbook or view)'
}
},
required: ['contentId', 'contentType']
}
};