tableau-mcp-eas-auth
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-mcp-eas-authSet up EAS authentication for embedding Tableau views"
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 MCP — MCP Apps 強化フォーク
これは tableau/tableau-mcp の実験的フォークです。 本家プロダクトの README・ドキュメント・Issue・サポートは upstream と 公式ドキュメント を参照してください。 This is an experimental fork of tableau/tableau-mcp focused on strengthening its MCP Apps features (embedded viz / Pulse). For the official product, please refer to the upstream repository.
このフォークは tableau-mcp の MCP Apps 機能(チャット UI 内への Tableau 埋め込み)を強化する。 upstream に足すものは 3 つ:
EAS 認証モード —
AUTH=easを追加し、per-user の 埋め込み viz を一般の Tableau Cloud サイトで成立させるViz 状態スナップショット — 埋め込み viz の画面状態を モデルコンテキストへ push し、裏のデータソースへの深掘りクエリまでつなぐ
Pulse メトリックの埋め込み —
<tableau-pulse>の iframe 描画と状態 push
EAS 認証モード
認証モード AUTH=eas(Connected App / OAuth 2.0 Trust = 外部認可サーバー) を追加する。
MCP サーバー自身を Tableau サイトに EAS として登録する。サーバーが保持する RS256 鍵が、
REST サインイン用 JWT と埋め込み用 JWT の両方を署名する。
ゴールは MCP Apps の per-user 埋め込み viz を成立させること。それも、ユーザー体験を 「OAuth リダイレクトで Tableau にログインし、サイトを選ぶだけ」に保ったまま。 設定方法と環境変数は docs/.../authentication/eas.md を参照。
背景 — なぜ EAS モードが必要か
tableau-mcp の MCP Apps 機能は、チャット UI 内の iframe に Tableau viz を埋め込み表示できる
(render-interactive-viz / get-embed-token)。この埋め込みには Embedding API v3 用の JWT が
必要になる。upstream 4.0.6 時点で、サーバーがその署名に使える材料は次の2つしかない:
direct-trust(Connected App / Direct Trust): サイト単位の共有 secret(HS256)。動作するが、 site-wide の secret をサーバーに置く運用になる
uat(Unified Access Token): Tableau Cloud Manager 経由で組織管理者が構成する仕組み(2025年12月導入)。Cloud Manager への アクセス権が前提で、サイト管理者の権限だけでは完結しない
per-user かつ一般の Tableau Cloud サイトで使える署名方式が存在しない。これが EAS を第3の方式として
実装した理由である。EAS はサーバー内部への「署名器」の追加にすぎない。既存の OAuth ログイン層
(src/server/oauth/)には一切手を入れていない。
Tableau Cloud で実測して確定した仕様
公式ドキュメントに無い・矛盾している挙動。2026年8月時点、Tableau Cloud サンドボックスでの実測:
audクレームはtableau:<site_luid>が正。ヘルプの一部に残る素の"tableau"は エラー 10084 で拒否される(旧仕様)。site LUID は Connected App 登録後の「Copy Site ID」で 取得できるTableau は EAS の JWKS 発見時、issuer の
/.well-known/openid-configurationと/.well-known/oauth-authorization-serverをノードによって使い分ける。片方だけ serve すると サインインが確率的に失敗する(実測で成功率 ~1/6 まで低下)。両パスに同一メタデータを serve することで安定するjtiは単回使用として強制される(エラー 10091)。トークンごとに UUID を生成する必要があるUI 登録(Name / Issuer URL / Enable のみ)だけで JWKS 発見は機能する。
jwksUriの明示指定は REST API(Register EAS)でのみ可能だが、必須ではなかったREST サインインも Embedding API v3 も EAS 署名 JWT を受理する(embed は scp
["tableau:views:embed"])
デプロイ構成の注意(Tableau Cloud)
issuer は Tableau Cloud から到達可能な公開 HTTPS URL であること。Tableau 側がメタデータと JWKS を能動的に fetch しに来るため localhost 不可。ローカル検証には HTTPS トンネルか リモートデプロイが必要
埋め込み認可サーバーモード(
OAUTH_EMBEDDED_AUTHZ_SERVER=true)は Cloud のリモートデプロイでは 使えない。Tableau Cloud の OAuth エンドポイント(client_type=tableau-mcp)は、認可コードの 返し先 redirect_uri を loopback のhttp://127.0.0.1:<port>に限定している。公開 HTTPS は 400 で拒否される。この許可リストを広げる設定は Tableau Server の TSM にしか存在しない。 Cloud ではOAUTH_ISSUER=https://sso.online.tableau.com+OAUTH_EMBEDDED_AUTHZ_SERVER=falseを使うsso.online.tableau.com は動的クライアント登録(DCR)非対応・CIMD のみ対応。DCR 前提の mcp-remote(0.1.38 時点)では接続できない。CIMD 対応の MCP クライアント (claude.ai のカスタムコネクタ等)を使う
サーバーの配置リージョンは Tableau ポッドの近傍を推奨(JWKS fetch のレイテンシ対策)
既知の制約 — ホスト側 CSP(サーバー外、2026年8月時点)
Claude Desktop / claude.ai では、MCP Apps 内の viz 表示だけが 「Authentication was unsuccessful」で失敗する。これはサーバー側の問題ではない。 スタンドアロンの Embedding API v3 ページでは同じ JWT で viz が描画されることを確認済み。
原因は Claude 側の MCP Apps サンドボックスが UI リソースの csp.frameDomains 宣言を無視して
frame-src 'self' を強制し、Tableau viz のネスト iframe をブロックすること
(anthropics/claude-ai-mcp#40)。
frameDomains を尊重するホストでは動作する見込み。
Related MCP server: tableau-mcp-navi
Viz 状態スナップショット
埋め込み viz をユーザーが操作すると、iframe 側が**現在のフィルター・パラメーター・選択マーク・
アクティブシートの要約データ(件数上限つき)**をスナップショットにまとめる。まとめたものは
ext-apps の updateModelContext でウィジェットのモデルコンテキストへ push される。
これによりモデルは「いま画面に出ている数字」を推測や再クエリなしで答えられる。
スナップショットに無いカット・別シート・打ち切られた行の先は、深掘りクエリで引き直す。
スナップショットが運ぶデータソース参照と VizQL セッション値を、そのまま
query-workbook-datasource に渡す(下記)。published データソースの LUID が別途
分かっている場合は、従来どおり query-datasource も使える。
render-interactive-viz のツール結果は content[0] に従来どおりの生 JSON、content[1] に
この使い分けを説明するガイダンステキストを返す。content[0] は iframe が JSON.parse するため
バイト単位で変更してはいけない。
動作の全体像
「状態の把握」と「データの取得」を分離しているのが要点。前者は push 済みのスナップショットで 即答でき(ツールコール不要)、後者だけがツールコールになる。どちらの経路にも Tableau への 書き込み・MCP サーバー側の状態保持は無い。
sequenceDiagram
actor U as ユーザー
participant V as Tableau viz<br/>(入れ子 iframe)
participant A as スナップショットブリッジ<br/>(MCP App iframe)
participant H as Claude ホスト
participant M as モデル
participant S as MCP サーバー
participant T as Tableau Cloud
U->>V: フィルター・パラメーター・選択を操作
V-->>A: 変更イベント(debounce 2 秒で settle 待ち)
A->>V: 状態と要約データを読み取り<br/>(直列キュー + タイムアウト)
A->>H: updateModelContext(スナップショット JSON)
Note over H,M: ホストが保持し、モデルは毎ターン参照できる(毎回上書き・累積しない)
U->>M: 「いま画面に出ている数字はどう?」
M-->>U: スナップショットを参照して即答(ツールコール不要)
U->>M: 「別のカットで深掘りして」
M->>S: query-workbook-datasource(スナップショットの<br/>データソース id + セッション値。画面状態はクエリ条件に翻訳)
S->>T: VizQL Data Service<br/>(X-Tableau-Auth + セッションヘッダ 2 つ)
T-->>M: 集計結果
M-->>U: 画面状態を踏まえた分析ウィジェット恒久破損(brick)という失敗モード
これは運用上もっとも重要な注意点である。 Claude ホストはウィジェットのモデルコンテキストに 約 16,000 トークンの上限を課す。この値は公開仕様ではなく実装依存。しかも上限判定は push 時ではなく表示(display)時に行われる。
結果として次の順序で不可逆な破損が起きる:
上限超過のペイロードでも push 自体は成功し、ホスト側に保存される
次の表示時に上限判定が走り、ウィジェットがレンダリングを恒久的に拒否する
レンダリングされない = iframe が動かない = 保存値を上書きできる唯一の手段が失われる
そのツールキーは以後永久に死ぬ
復旧手段はツール名(= ウィジェットキー)のリネームのみ。 リネームが必要な箇所:
src/tools/web/renderInteractiveViz/renderInteractiveViz.ts—name:フィールドとgetAppConfig(...)の引数(resourceUriはui://<tool-name>/mcp-app.htmlとして ツール名から生成されるため、ここを直せば追従する)src/tools/web/toolName.ts—webToolNames配列(42行目付近)とwebToolGroupsのmcp-appsグループ(103行目付近)の両方src/server/oauth/scopes.ts—toolScopeMapのキー(329行目付近)と、mcp-apps 無効時にenabledTools.delete('render-interactive-viz')する箇所(399行目付近)
防御 — クライアント側ハードキャップ
上限判定が push 時に行われない以上、送る前に自分で止めるしかない。iframe 側は
src/web/apps/src/embed/vizState/payload.ts の PUSH_BUDGET_BYTES = 30,000 バイトを
ハードキャップとして持つ。
保守的に 2.5 文字/トークンで見積もって約 12k トークン。16k に対して約 25% のマージン
予算を超えるペイロードは送信しない。データ行を削って収まる形にしてから push する
16,000 という値が実装依存である以上、キャップは変更可能な定数として置いてある
データソースへの深掘り(query-workbook-datasource)
スナップショットには次の 2 つが載る。
datasources[]— 表示中のシート/ダッシュボード配下、全ワークシートのデータソース参照。 各エントリは内部 id・名前・isPublished・使用シート名のworksheetsラベルを持つ。 id で重複排除し、全体 8 件が上限vds— viz の VizQL セッション値
query-workbook-datasource はこの 2 つを引数に取る。サーバー側が自前の認証トークン +
セッションヘッダで VizQL Data Service を呼ぶ。クエリの書式は query-datasource と同一で、
query を省略するとフィールド一覧を返す。
要点:
LUID 不要。Embedding API の
DataSource.id(sqlproxy.*/federated.*)をそのまま使う。 名前解決・Metadata API 往復が要らない埋め込みデータソース(published でない = LUID が存在しない)にも到達できる。 これはこの経路の固有価値で、
query-datasourceでは原理的に不可能セッションは viz 単位。ダッシュボード配下のどのシートのデータソースにも同じ値で効く (実測済み)。ページを閉じても即座には失効しない — 26 分後の生存まで実測済みで、上限は未測定
クエリ結果は画面のフィルター状態を反映しない。スナップショットの
filters/parametersをクエリ条件へ翻訳するのはモデルの責務(push 文言で明示している)サーバー側でセッション ID はログ・通知からマスクされる。データソース許可リスト (
INCLUDE_DATASOURCE_IDS等)は LUID 前提のため、このツールには適用されない。 該当運用ではツール自体を無効化すること
設計判断と実測の根拠は worklog と verification/vds-embedding-id/FINDINGS.md を参照。
想定しているダッシュボード像
本機能がどんなダッシュボードを想定して設計されているか(フィルター/パラメーターでの 状態表現、公開データソースの参照、計算フィールドの置き場所)と、その根拠となる Embedding API / VDS の制約は AI-DASHBOARD-NOTES.md に 制約メモとしてまとめてある。
検証記録
実 viz に対する手動受け入れ(capture→push 経路の実機検証)の結果と、そこで確定した 事実は verification/viz-state/ACCEPTANCE.md に 記録してある。
Pulse メトリックの埋め込み
render-pulse-metric は Tableau Pulse メトリックを <tableau-pulse> として iframe に描画する。
構成は viz 側(render-interactive-viz + embed-viz バンドル)と対称。専用の単一ファイル HTML
バンドル embed-pulse(mcp-pulse.html)を持つ。フィルター・期間・提示されたインサイトは
viz と同じく updateModelContext でモデルコンテキストへ push する。
スナップショットに数値は入らない。 <tableau-pulse> には要約データを読む API が無く、
メトリック値は Pulse のインサイト API の担当だからである。数値が要るときは
generate-pulse-metric-value-insight-bundle か query-datasource を使う旨を、push する
プリアンブルとツール結果のガイダンス文の両方に明記してある。
埋め込みトークンのスコープ
Pulse 埋め込みは tableau:insights:embed と tableau:views:embed の両方を要求する。
公式ドキュメントに後者が必要である旨の記載はない。insights:embed 単独だと、embed signin は
200 で通るのに後続 API が 401 になる。ユーザーにはセッション切れとして見える。
実測値と切り分け手順は verification/pulse-embed/FINDINGS.md。
このため get-embed-token は任意パラメータ target(viz / pulse)を取る。省略時は従来どおり
views:embed 単独で署名するため、viz 経路の挙動は変わらない。
Tableau Server への読み替え
Server では EAS 登録が TSM(サーバー単位)になる、JWKS の公開露出が不要になる、 埋め込み認可サーバーモードが TSM 設定でリモートでも成立する、など複数の点が変わる。 TABLEAU-SERVER-EAS.md に整理してある(未実測)。
License
Upstream に従い Apache-2.0。
This server cannot be deployed
Maintenance
Related MCP Connectors
Bar-first MCP server for Tabula chart authoring, PNG rendering, and editor handoff.
Hosted MCP server with managed OAuth for 15+ toolkits: Google Workspace, Fitbit, Oura, Kalshi, etc.
Self-hosted federated MCP gateway: one OAuth 2.1 MCP server in front of N apps, user-level scopes.
Hosted remote MCP server for YNAB on Cloudflare Workers with OAuth
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceThis project builds a read-only MCP server. For full read, write, update, delete, and action capabilities and a simplified setup, check out our free CData MCP Server for Tableau CRM Analytics (beta): https://www.cdata.com/download/download.aspx?sku=FSZK-V&type=betaMIT
- AlicenseAqualityCmaintenanceA Model Context Protocol (MCP) server for Tableau Server. Enables AI assistants to interact with Tableau workbooks, views, datasources, and metadata.24MIT
- FlicenseNot gradedqualityNot gradedmaintenancePersonal MCP server for Snowflake and Tableau integration, enabling SQL queries and database/table listing as well as Tableau workbook, view, datasource management.-
- FlicenseBqualityBmaintenanceA production-grade MCP server that exposes Tableau Server/Cloud as a BI platform, enabling project, workbook, data source, user, group, job, lineage, and export operations via natural language, with role-based permissions and token optimization.69-