tableau-audit-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@tableau-audit-mcpAudit my Tableau workbook and generate a cleanup report"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Tableau Workbook Audit MCP Server
An MCP server that audits local Tableau workbooks (.twb / .twbx) for:
Unused assets — worksheets never embedded on a dashboard, calculated fields nothing depends on (directly or transitively), parameters never referenced, and groups/sets never used.
Duplicate worksheets — near-identical sheets flagged via a weighted similarity score (shared fields, mark type, filter overlap), so you know what to consolidate.
Dashboard weight — a load-time risk score per dashboard (worksheet count, filter/action/web-object counts, embedded extract size) with concrete recommendations.
No Tableau Server/Cloud connection required — it works entirely from the workbook file on disk.
Install
git clone https://github.com/Sujan2396/tableau_aduit_mcp.git
cd tableau_aduit_mcp
pip install -e .Not yet published to PyPI. pip install tableau-audit-mcp will fail
until/unless this package is actually published there — the command above
(pip install -e . from a local clone) is the only working install method
right now. If that changes, this section will be updated accordingly.
Related MCP server: mcp-shipcheck
Run standalone (for testing)
python3 -c "
from tableau_audit import load_workbook, WorkbookGraph, find_unused_assets, analyze_dashboards, find_duplicate_worksheets, render_markdown_report
loaded = load_workbook('/path/to/your/workbook.twbx')
graph = WorkbookGraph(loaded.root)
unused = find_unused_assets(graph)
dups = find_duplicate_worksheets(graph)
dws = analyze_dashboards(graph)
print(render_markdown_report('your_workbook.twbx', unused, dups, dws, loaded.total_extract_bytes / (1024*1024)))
"Run as an MCP server
python3 server.py
# or, after `pip install -e .` (registers the console script):
tableau-audit-mcpRegister with Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"tableau-audit": {
"command": "python3",
"args": ["/absolute/path/to/tableau-audit-mcp/server.py"]
}
}
}Tools exposed
Tool | Purpose |
| Parse + cache a workbook, return a summary |
| Unused worksheets/calcs/parameters/groups+sets |
| Near-duplicate worksheet pairs |
| Per-dashboard weight/risk score + recommendations |
| Compact scorecard: counts + structural-complexity % + load-time risk rating |
| Full combined Markdown report (recommended default) |
How the analysis works
Field usage: each
<worksheet>in the.twbXML lists exactly which columns it uses via<datasource-dependencies>. A field/calc/group/set with zero worksheet references (and, for calcs, no other used calc depending on it) is flagged unused.Parameters: unlike other fields, parameters aren't referenced via dependencies — they're used by name inside formulas, filters, actions, and titles. We scan those specifically for the parameter's name (and exclude the parameter's own definition, to avoid a trivial self-match).
Groups vs. Sets: both are stored in Tableau's XML as a
<column>with a<groupfilter>child, so we track them together asgroup_or_set. Reliably telling groups apart from sets from the XML alone is a known limitation (see below).Duplicate sheets: `0.7 × Jaccard(field usage) + 0.15 × (mark type match)
0.15 × Jaccard(filters)`. Tune the threshold per tool call — lower it to catch looser near-duplicates.
Dashboard weight: a heuristic score from worksheet count, filter/action/ web-object counts on the dashboard, plus overall embedded extract size (for
.twbxfiles). Thresholds are tunable intableau_audit/analysis.py.
Known limitations / next steps
Tableau version drift: the
.twbschema has shifted across Desktop versions (2018.x vs. 2023.x vs. Cloud). The XPath heuristics here cover the common structure; workbooks with heavy custom XML (Tableau Prep flows, very old Desktop versions) may need small adjustments ingraph.py.Group vs. Set disambiguation is currently a placeholder — both show up as
group_or_set. Both static groups/sets (a<column>with a<groupfilter>child) and dynamic sets like "Top N by..." (a separate top-level<group>element with a different attribute shape — validated against a real workbook) are parsed and tracked for usage, including parameters referenced viacount/size-parameterattributes rather than formula text. They just aren't labeled apart from each other. If you need Groups split from Sets specifically, the most reliable path is cross-referencing against the Tableau Metadata API rather than the raw XML.Dashboard action counts are attributed per-dashboard via a best-effort heuristic (matching worksheet names mentioned in each action's XML against the worksheets on that dashboard) rather than assigning the full workbook-wide total to every dashboard equally (a real scoring bug fixed after external code review - see CONTRIBUTING.md history). This can still under- or over-attribute for exotic action configurations across schema versions; the raw workbook-wide total is always available alongside the attributed figure for transparency.
Extract size is only available for
.twbx(packaged) workbooks, since.twbfiles reference external.hyper/.tdefiles rather than embedding them. Note this figure comes from the zip header's declared size, which isn't independently verified (see the security note inparser.py).The automated suite in
tests/test_audit.pycovers the synthetic sample workbook, regression cases found while validating against real Tableau Public workbooks, and a set of crafted fixtures undertests/fixtures/that each reproduce a specific bug found during an external code review (substring-matching false positives, Story-only worksheets, filterless duplicate scoring, per-dashboard action attribution, XML/zip hardening, cache staleness). It's not exhaustive — if you hit a workbook shape that breaks parsing, please open an issue (see CONTRIBUTING.md) with a minimal reproducing snippet.The two "Workbook Health" headline numbers are intentionally scoped honestly: structural complexity reduction % is a heuristic (documented in
compute_health_summary's docstring) based on unused-asset ratios, not a calibrated file-size prediction. Dashboard load-time risk is a qualitative Low/Medium/High rating rather than a percentage, because Tableau publishes no formula for converting static asset counts into a load-time number — for a measured value, use Tableau's own Performance Recorder.
Contributing
Contributions are welcome — see CONTRIBUTING.md for setup instructions, what kinds of contributions are most valuable, and development guidelines.
License
MIT — free to use, modify, and redistribute.
This server cannot be deployed
Maintenance
Related MCP Connectors
Generate Tableau .twb/.twbx workbooks: 47 tools for charts, dashboards, rules, CSV pipelines.
Lowers your AWS bill by helping you clean up and optimize your setup
Excel analytics: inspect, query (JSON rows), charts, and JSON-to-xlsx workbook writing.
Deterministic cleanup tools for decimals, whitespace, filenames, delimiters, and booleans.
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceEnables discovery, querying, and exporting of Tableau Cloud dashboards and data sources. Supports searching workbooks, filtering data, and exporting views as PDF, PNG, PowerPoint, CSV, or JSON.-
- AlicenseAqualityAmaintenanceAudits local package folders to generate publish-readiness reports and previews of NPM tarball contents. It helps developers identify and resolve configuration issues like missing types or broken exports before releasing code.371 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to programmatically read, modify, and query Tableau workbook files (.twb and .twbx) on the local filesystem via 80 tools.8MIT
- AlicenseAqualityBmaintenanceCreates Tableau workbooks from a declarative JSON spec, validates them by opening in the installed Tableau Public application, and publishes to Tableau Public through the desktop UI.101MIT