Skip to main content
Glama
russelenriquez-agile

Tableau MCP Server

README.md
# Tableau MCP Server

A Model Context Protocol (MCP) server for Tableau Cloud that provides dashboard access, data querying, and export capabilities through Cursor IDE.

## Features

- **šŸ” Discovery & Search** - Find workbooks, views, and data sources
- **šŸ“Š Data Access** - Query view data with filters as CSV or JSON
- **šŸ“¤ Export** - Export dashboards as PDF, PNG, or PowerPoint
- **šŸ”„ Data Refresh** - Trigger extract refreshes for data sources

## Prerequisites

- Node.js 18.x or later
- Google Cloud Platform account with:
  - Cloud Run enabled
  - Secret Manager enabled
  - Cloud Storage bucket for exports
- Tableau Cloud/Server with:
  - Personal Access Token (PAT) credentials
  - API access enabled

## Quick Start

### 1. Clone and Install

```bash
cd tableau-mcp
npm install
```

### 2. Configure Environment Variables

Create a `.env` file (or set environment variables):

```env
# Tableau Configuration
TABLEAU_SERVER_URL=https://prod-apnortheast-a.online.tableau.com
TABLEAU_SITE_ID=your-site-content-url
TABLEAU_PAT_NAME=your-pat-name
TABLEAU_PAT_SECRET=your-pat-secret

# MCP Server
MCP_API_KEY=your-secure-api-key

# Google Cloud
GCS_EXPORT_BUCKET=tableau-mcp-exports
GCP_PROJECT_ID=your-project-id
```

### 3. Run Locally

```bash
npm start
```

The server starts on `http://localhost:8080`:
- Health check: `GET /health`
- SSE endpoint: `GET /sse` and `POST /sse`

### 4. Configure Cursor

Add to your `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "tableau": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://tableau-mcp-400124661305.australia-southeast1.run.app/sse",
        "--header",
        "X-API-Key: <your-api-key>"
      ]
    }
  }
}
```

> **Note**: Replace `<your-api-key>` with your actual API key from Secret Manager (`tableau-mcp-api-key`).

## Available Tools

### Utility Tools
| Tool | Description |
|------|-------------|
| `tableau_get_instructions` | Get guidance on using Tableau MCP tools |
| `tableau_search` | Search content across Tableau |

### Dashboard Tools
| Tool | Description |
|------|-------------|
| `tableau_list_workbooks` | List all accessible workbooks |
| `tableau_get_workbook` | Get workbook details |
| `tableau_list_views` | List views in a workbook |
| `tableau_get_filters` | Get available filters for a view |
| `tableau_apply_filter` | Store filters for query/export |

### Data Tools
| Tool | Description |
|------|-------------|
| `tableau_query_view` | Export view data as CSV/JSON |
| `tableau_list_datasources` | List published data sources |
| `tableau_refresh_datasource` | Trigger extract refresh |

### Export Tools
| Tool | Description |
|------|-------------|
| `tableau_export_pdf` | Export view as PDF |
| `tableau_export_image` | Export view as PNG |
| `tableau_export_pptx` | Export view as PowerPoint |

## Usage Examples

### Find and Export a Dashboard

```
1. Search for dashboards:
   tableau_search({ query: "sales" })

2. List views in a workbook:
   tableau_list_views({ workbookId: "abc123" })

3. Export as PDF:
   tableau_export_pdf({ viewId: "xyz789" })
```

### Query Filtered Data

```
1. Get available filters:
   tableau_get_filters({ viewId: "xyz789" })

2. Query with filters:
   tableau_query_view({
     viewId: "xyz789",
     format: "json",
     filters: { "Region": "West" }
   })
```

## Deployment

### Cloud Run Deployment

1. **Create GCS Bucket**
   ```bash
   gsutil mb -l australia-southeast1 gs://tableau-mcp-exports
   ```

2. **Create Secrets in Secret Manager**
   ```bash
   echo -n "your-pat-name" | gcloud secrets create tableau-pat-name --data-file=-
   echo -n "your-pat-secret" | gcloud secrets create tableau-pat-secret --data-file=-
   echo -n "your-api-key" | gcloud secrets create tableau-mcp-api-key --data-file=-
   ```

3. **Grant Service Account Permissions**
   ```bash
   # Secret Manager access
   gcloud secrets add-iam-policy-binding tableau-pat-secret \
     --member="serviceAccount:YOUR_SA@PROJECT.iam.gserviceaccount.com" \
     --role="roles/secretmanager.secretAccessor"

   # GCS access
   gsutil iam ch serviceAccount:YOUR_SA@PROJECT.iam.gserviceaccount.com:objectCreator,objectViewer \
     gs://tableau-mcp-exports
   ```

4. **Configure Cloud Build Trigger**
   - Source: Your GitHub repository
   - Event: Push to `main` branch
   - Configuration: `cloudbuild.yaml`
   - Substitution variables:
     - `_TABLEAU_SERVER_URL`: Your Tableau Cloud URL
     - `_TABLEAU_SITE_ID`: Your site content URL
     - `_GCS_EXPORT_BUCKET`: Your export bucket name

5. **Deploy**
   Push to `main` branch to trigger automatic deployment.

### Manual Deployment

```bash
gcloud run deploy tableau-mcp \
  --source . \
  --region australia-southeast1 \
  --memory 1Gi \
  --timeout 300s \
  --min-instances 1 \
  --allow-unauthenticated
```

## Configuration Reference

### Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `TABLEAU_SERVER_URL` | āœ… | Tableau Cloud/Server URL |
| `TABLEAU_SITE_ID` | āœ… | Site content URL |
| `TABLEAU_PAT_NAME` | āœ… | Personal Access Token name |
| `TABLEAU_PAT_SECRET` | āœ… | Personal Access Token secret |
| `MCP_API_KEY` | āœ… | API key for MCP authentication |
| `GCS_EXPORT_BUCKET` | āœ… | GCS bucket for exports |
| `GCP_PROJECT_ID` | āœ… | Google Cloud project ID |
| `PORT` | āŒ | Server port (default: 8080) |
| `TABLEAU_API_VERSION` | āŒ | API version (default: 3.21) |

### Cloud Run Settings

| Setting | Value |
|---------|-------|
| Region | australia-southeast1 |
| Memory | 1Gi |
| CPU | 1 |
| Timeout | 300s |
| Min instances | 1 |
| Max instances | 10 |
| Concurrency | 80 |

## Limitations

- **Filters**: Cannot apply filters to live dashboard views - only at query/export time
- **PPTX Export**: Generated from PNG images, not native Tableau export
- **Data Query**: Maximum 100,000 rows per request
- **Export URLs**: Valid for 1 hour only
- **Rate Limits**: Throttled to 10 requests/second to Tableau API

## Project Structure

```
tableau-mcp/
ā”œā”€ā”€ mcp-http-server.js      # Main Express HTTP server
ā”œā”€ā”€ mcp-handler.js          # MCP protocol handler
ā”œā”€ā”€ mcp_tools.json          # Tool definitions
ā”œā”€ā”€ config.js               # Configuration management
ā”œā”€ā”€ package.json            # Dependencies
ā”œā”€ā”€ Dockerfile              # Container configuration
ā”œā”€ā”€ cloudbuild.yaml         # CI/CD configuration
ā”œā”€ā”€ lib/
│   ā”œā”€ā”€ tableau-client.js   # Tableau REST API client
│   ā”œā”€ā”€ gcs-client.js       # GCS upload/signing
│   └── logger.js           # Structured logging
ā”œā”€ā”€ 00-utility-tools/tools/
│   ā”œā”€ā”€ get-instructions.js
│   └── search.js
ā”œā”€ā”€ 01-dashboard-tools/tools/
│   ā”œā”€ā”€ list-workbooks.js
│   ā”œā”€ā”€ get-workbook.js
│   ā”œā”€ā”€ list-views.js
│   ā”œā”€ā”€ get-filters.js
│   └── apply-filter.js
ā”œā”€ā”€ 02-data-tools/tools/
│   ā”œā”€ā”€ query-view-data.js
│   ā”œā”€ā”€ list-datasources.js
│   └── refresh-datasource.js
└── 03-export-tools/tools/
    ā”œā”€ā”€ export-pdf.js
    ā”œā”€ā”€ export-image.js
    └── export-pptx.js
```

## Troubleshooting

### Authentication Errors

- Verify PAT credentials are correct
- Check that PAT has not expired
- Ensure site ID matches the site content URL (not the site name)

### Export Failures

- Check GCS bucket exists and is accessible
- Verify service account has `objectCreator` and `objectViewer` roles
- Large exports may timeout - try smaller views or increase Cloud Run timeout

### Rate Limiting

- The server throttles to 10 requests/second
- Batch operations may be slower due to throttling
- Consider increasing throttle limit for Tableau Server (not Cloud)

## License

MIT

## Author

Agile Market Intelligence