Tableau Data Assistant MCP Server
Provides MCP tools to query Tableau Server/Cloud datasources via REST API and VizQL Data Service, with support for Gemini or OpenAI as the LLM backend. Enables a natural language chat interface that can be embedded in Tableau dashboards, automatically including dashboard filter context.
README
Tableau Data Assistant — Gemini + MCP + Web Chat
Paket lengkap end-to-end:
tableau_client.py— wrapper REST API + VizQL Data Service Tableau (auth PAT, list workbook/datasource/view, query datasource).tableau_mcp_server.py— membungkus wrapper di atas jadi MCP tools (@mcp.tool()), dijalankan lewat stdio.agent_service.py— factory: memilih backend LLM (Gemini atau OpenAI) berdasarkanLLM_PROVIDERdi.env. Interface publiknya (connect(),ask_stream()) sama persis untuk kedua provider, jadiweb_app.pydangemini_client.pytidak perlu tahu/berubah soal LLM apa yang dipakai.backends/gemini_backend.py— implementasi pakai Gemini (google-genai).backends/openai_backend.py— implementasi pakai OpenAI (Chat Completions API).
gemini_client.py— CLI chat (terminal) untuk testing cepat.web_app.py— server FastAPI + WebSocket yang menyajikan UI chat dan menjembatani browser ⇄agent_service.static/— UI chat (HTML/CSS/JS statis, tanpa framework) yang bisa di-embed ke dashboard Tableau.
Browser (embed di Tableau dashboard)
│ WebSocket (/ws)
▼
web_app.py (FastAPI)
│ ask_stream()
▼
agent_service.py ── Gemini function calling
│ MCP (stdio, subprocess)
▼
tableau_mcp_server.py
│ REST API + VizQL Data Service
▼
Tableau Server / Cloud
1. Instalasi
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
2. Konfigurasi
cp env.example.txt .env
Isi .env:
TABLEAU_SERVER=https://my-tableau-server.com
TABLEAU_SITE=my_site_content_url # kosongkan "" jika Default site
TABLEAU_PAT_NAME=...
TABLEAU_PAT_SECRET=...
TABLEAU_API_VERSION=3.22
GEMINI_API_KEY=...
GEMINI_MODEL=gemini-2.5-pro # opsional, default gemini-2.5-pro
PAT dibuat di: Tableau → Account Settings → Personal Access Tokens.
2b. Ganti LLM provider (Gemini ⇄ OpenAI)
Cukup ubah satu baris di .env:
LLM_PROVIDER=gemini # atau: openai
Lalu isi kunci API yang sesuai (GEMINI_API_KEY/GEMINI_MODEL atau OPENAI_API_KEY/OPENAI_MODEL — lihat env.example.txt). Tidak ada file lain yang perlu diedit; agent_service.py otomatis meng-import backend yang tepat, dan status bar di UI chat juga otomatis menampilkan provider yang sedang aktif (mis. "siap · gemini · 6 tools").
Kalau nanti ingin menambah provider lain (mis. Claude via Anthropic API, atau model lokal), cukup buat backends/<nama>_backend.py baru dengan class TableauAgentSession yang method-nya identik (connect(), ask_stream(), close()), lalu tambahkan satu cabang elif di agent_service.py.
3. Menjalankan
a) CLI (cepat untuk testing):
python gemini_client.py
b) Web app (untuk di-embed ke dashboard):
uvicorn web_app:app --host 0.0.0.0 --port 8000 --reload
Buka http://localhost:8000 — chat box siap dipakai. Setiap tab browser = satu sesi percakapan independen (satu TableauAgentSession per koneksi WebSocket).
4. Meng-embed ke dashboard Tableau
Opsi A — Objek "Web Page" (paling sederhana)
- Deploy
web_app.pyke server yang bisa diakses via HTTPS (browser modern mewajibkan HTTPS untuk konten campuran di dalam iframe dashboard Tableau Cloud/Server). - Di Tableau Desktop/Web Edit, buka dashboard Anda → seret objek Web Page ke canvas.
- Isi URL dengan alamat app Anda, mis.
https://assistant.perusahaan-anda.com/. - Atur ukuran objek sesuai kebutuhan (chat box didesain responsif, nyaman mulai lebar ~360px).
- Publish dashboard. Chat box akan tampil sebagai panel di sisi dashboard.
Opsi B — Tableau Extensions API (sudah tersedia lengkap di paket ini)
File yang terlibat:
static/tableau-extension.js— inisialisasitableau.extensions, membaca semua worksheet + filter aktif di dashboard, menyimpannya diwindow.__dashboardContext, dan mendengarkan eventFilterChangedsupaya konteks selalu ter-update.static/index.html— memuat SDKtableau.extensions.1.latest.jsyang di-self-host distatic/vendor/(bukan dari CDN eksternal — banyak jaringan Tableau Server korporat memblokir domain sepertiextensions.tableau.com, menyebabkannet::ERR_NAME_NOT_RESOLVEDdan extension gagal total), lalutableau-extension.js, laluapp.js. Ada juga badge kecil (#context-badge) yang menampilkan filter aktif secara visual di atas chat.static/vendor/tableau.extensions.1.latest.js— salinan resmi SDK dari repotableau/extensions-apidi GitHub. Untuk update ke versi lebih baru:curl -sL -o static/vendor/tableau.extensions.1.latest.js \ https://raw.githubusercontent.com/tableau/extensions-api/master/lib/tableau.extensions.1.latest.jsstatic/app.js— setiap kali user mengirim pesan,window.__dashboardContextikut dikirim ke backend sebagai fieldcontext(selainmessage).web_app.py&agent_service.py— menerimacontextdari WebSocket dan menyisipkannya ke prompt Gemini, jadi assistant otomatis tahu filter yang sedang aktif tanpa Anda ketik manual.tableau-data-assistant.trex— manifest extension.
Catatan penting: kalau halaman ini dibuka sebagai objek Web Page biasa (Opsi A), tableau.extensions tidak akan pernah tersedia — semua kode di atas otomatis no-op dan chat tetap berfungsi normal tanpa konteks dashboard. Jadi satu paket ini mendukung kedua opsi sekaligus, tidak perlu versi terpisah.
Langkah setup:
-
Sunting
tableau-data-assistant.trex:- Ganti
<url>https://assistant.perusahaan-anda.com/</url>dengan alamat HTTPS tempatweb_app.pyAnda benar-benar di-deploy. - Untuk testing lokal, Tableau Desktop mengizinkan
http://localhost:8000selama opsi "Allow the extension to run local content" (kadang disebut "Extensions - localhost only") diaktifkan di Tableau Desktop → Help → Settings and Performance, atau saat menambahkan extension pertama kali Desktop akan menampilkan dialog konfirmasi ini. - Sesuaikan
id,name,author,email,organization,websitesesuai perusahaan Anda.
- Ganti
-
Di Tableau Desktop, buka dashboard Anda → seret objek Extension (bukan Web Page) ke canvas.
-
Pada dialog yang muncul, pilih "My Extensions" → "Access Local Extensions" → arahkan ke file
tableau-data-assistant.trexdi komputer Anda (atau file share/URL tempat manifest itu di-host, tergantung workflow tim Anda). -
Tableau akan menampilkan dialog izin ("This extension can access all data in the workbook") — ini karena manifest meminta
<full-data/>supaya assistant bisa membaca filter secara lengkap. Klik Allow. -
Extension akan memuat
index.htmlAnda di dalam iframe khusus extension. Coba ubah filter di worksheet lain pada dashboard — badge konteks di atas chat akan otomatis update, dan pertanyaan berikutnya ke assistant akan otomatis menyertakan info filter tersebut. -
Untuk publish ke Tableau Server/Cloud: upload
.trexsebagai bagian dari dashboard saat di-publish (Tableau akan menyimpannya bersama workbook), dan pastikan admin site Anda mengizinkan "Run on Tableau Server/Cloud" untuk extension dengan source URL Anda (di Server: Settings → Extensions → Allowed list; kadang perlu ditambahkan admin jika site Anda mode "safe list only").
5. Catatan produksi (penting)
- Jangan expose
GEMINI_API_KEYatau PAT Tableau ke browser — pada arsitektur ini keduanya sudah aman karena hanya dipakai di backend (agent_service.py,tableau_mcp_server.py); browser hanya bicara keweb_app.pylewat WebSocket teks biasa. - Set
allow_originsdiweb_app.py(CORS) ke domain Tableau Server/Cloud Anda, jangan biarkan"*"di production. - Satu
TableauAgentSession= satu subprocess MCP + histori chat in-memory. Untuk trafik tinggi, pertimbangkan: batas jumlah sesi aktif, timeout idle-session, atau kembangkanagent_service.pyagar satu subprocess MCP dipakai bersama (pool) alih-alih satu per user. - Jalankan di belakang reverse proxy (nginx/Caddy) dengan TLS untuk HTTPS + WSS.
- Tambahkan autentikasi (mis. cek session/cookie SSO perusahaan) di
web_app.pysebelum membuka WebSocket, supaya tidak semua orang bisa memanggil Tableau & Gemini API Anda.
6. Struktur file lengkap
tableau-mcp-gemini/
├── tableau_client.py # REST API + VizQL Data Service wrapper
├── tableau_mcp_server.py # MCP tools (list_workbooks, query_datasource, dst.)
├── agent_service.py # Factory: pilih backend LLM sesuai LLM_PROVIDER
├── backends/
│ ├── gemini_backend.py # Implementasi LLM: Gemini
│ └── openai_backend.py # Implementasi LLM: OpenAI
├── gemini_client.py # CLI chat (khusus Gemini, testing cepat)
├── web_app.py # FastAPI + WebSocket server
├── static/
│ ├── index.html # shell UI chat
│ ├── style.css # styling (console-style trace, bukan bubble generik)
│ └── app.js # koneksi WebSocket + render pesan/trace
├── requirements.txt
├── env.example.txt # salin jadi .env
└── README.md
8. Troubleshooting: assistant tidak "menyadari" perubahan filter
Kalau assistant tetap menjawab seolah tidak ada filter aktif setelah Anda ubah filter di dashboard:
- Cek dulu console browser untuk error
net::ERR_NAME_NOT_RESOLVEDpadatableau.extensions.1.latest.js. Ini penyebab paling umum: jaringan tempat Tableau Server Anda berjalan biasanya jaringan internal/korporat yang tidak boleh akses domain luar, sehingga CDN SDK gagal dimuat sama sekali danwindow.tableautidak pernah ada — akibatnyatableau-extension.jslangsung berhenti di baris pengecekan paling awal. Paket ini sudah memakai SDK yang di-self-host distatic/vendor/tableau.extensions.1.latest.js(bukan CDN) justru untuk menghindari masalah ini — pastikan Anda pakai versiindex.htmlterbaru yang me-reference/static/vendor/..., bukan versi lama yang masih menunjuk kehttps://extensions.tableau.com/.... - Buka console browser (klik-kanan panel extension → Inspect di Tableau Desktop, atau F12 di web edit) dan cari log
[tableau-extension] konteks diperbarui: .... Kalau log ini tidak muncul sama sekali saat Anda ganti filter → berartiFilterChangedevent tidak sampai ke script (biasanya karena extension belum ter-load penuh, atau Anda sedang menguji lewat mode Web Page biasa, bukan mode Extension). - Kalau log muncul tapi isinya
"tidak ada filter aktif saat ini"walau Anda yakin sudah mengubah filter → cek tipe filter yang dipakai. Versi terbarutableau-extension.jssudah menangani filter categorical, range, relative-date, dan hierarchical; kalau dashboard Anda memakai tipe filter lain yang tidak dikenali, filter tetap dicatat tapi tanpa detail nilainya — cek juga apakah filter itu diterapkan di worksheet yang datanya sedang dibaca (extension hanya membaca filter per-worksheet lewatgetFiltersAsync(), bukan filter yang cuma ada di level dashboard tanpa terhubung ke worksheet mana pun). - Kalau badge di atas chat sudah menampilkan filter yang benar, tapi jawaban assistant tetap mengabaikannya → itu bukan soal pembacaan filter lagi, melainkan soal bagaimana Gemini memakainya. Pastikan Anda pakai
agent_service.pyversi terbaru (adaSYSTEM_INSTRUCTIONyang secara eksplisit mewajibkan model menerapkan filter dari konteks ke queryquery_datasource, dan menandai konteks sebagai "TERKINI" supaya tidak bingung dengan konteks lama di riwayat chat). - Untuk mengetes cepat tanpa bolak-balik ke dashboard: buka
/langsung di browser (mode Web Page biasa), lalu di console jalankanwindow.__dashboardContext = 'Dashboard "Test" — filter aktif:\nWorksheet "Sales": Region = [West]'sebelum mengirim pesan — ini mensimulasikan konteks tanpa perlu Extensions API sungguhan.
9. Menambah tool baru
- Tambah method di
tableau_client.py. - Bungkus jadi
@mcp.tool()ditableau_mcp_server.py. - Restart
web_app.py/gemini_client.py— tool baru otomatis terdeteksi lewatsession.list_tools(), tidak perlu ubahagent_service.py,web_app.py, atau UI.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。