Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@tableau/mcp-server",
"description": "Helping agents see and understand data.",
"version": "2.25.2",
"version": "2.26.0",
"repository": {
"type": "git",
"url": "git+https://github.com/tableau/tableau-mcp.git"
Expand Down
35 changes: 35 additions & 0 deletions src/server/oauth/scopes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export type McpScope =
| 'tableau:mcp:workbook:delete'
| 'tableau:mcp:jobs:read'
| 'tableau:mcp:datasource:delete'
| 'tableau:mcp:content:delete'
| 'tableau:mcp:users:read';

export type TableauApiScope =
Expand Down Expand Up @@ -68,6 +69,7 @@ export const DEFAULT_SCOPES_SUPPORTED: ReadonlyArray<McpScope> = [
'tableau:mcp:workbook:read',
'tableau:mcp:workbook:delete',
'tableau:mcp:content:read',
'tableau:mcp:content:delete',
'tableau:mcp:view:read',
'tableau:mcp:view:download',
'tableau:mcp:pulse:read',
Expand Down Expand Up @@ -330,6 +332,37 @@ const toolScopeMap: Record<
'tableau:users:read',
]),
},
// Consolidated admin-insights tool (W-23375797). Dispatches on `kind` to ts-events, site-content,
// job-performance (raw VDS) or stale-content (server-side anti-join). Union of the scopes required
// by the four legacy tools it replaces — any kind may need any of these.
'query-admin-insights': {
mcp: ['tableau:mcp:datasource:read'],
api: new Set([
'tableau:viz_data_service:read',
'tableau:content:read',
'tableau:mcp_site_settings:read',
'tableau:users:read',
]),
},
// Consolidated destructive-delete tool (W-23375797). Dispatches on `resourceType` to workbook,
// datasource, or extract-refresh-task. Gated on a single umbrella MCP scope
// (`tableau:mcp:content:delete`) that covers all three dispatch paths — declaring the three
// per-resource legacy scopes here would be AND-enforced by authMiddleware and lock out callers
// who only granted one of them. Callers who need per-resource granularity keep using the legacy
// `delete-{workbook,datasource,extract-refresh-task}` tools during the shim window. Workbook and
// datasource paths still route through resourceAccessChecker (union of API scopes preserved).
'delete-content': {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 MattGPT — automated review on Matt's behalf; he reviewed this before posting.

Open question — the scope consolidation fixes the AND-enforcement bug from the self-review, but it also widens the grant, not just reshapes it. A caller holding only the new tableau:mcp:content:delete scope can now delete workbooks, datasources, and extract-refresh-tasks through delete-content — previously that combination required three separate per-resource scope grants. Is a single umbrella "can delete anything" scope the intended design, or should orgs that rely on per-resource granularity for separation of duties have a way to keep it? Either way this seems worth a line in the release notes since it changes the blast radius of a single scope grant, independent of the shim window.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Akash's agent] Good flag — yes, umbrella-as-designed. The three per-resource MCP scopes still exist (each legacy tool declares its own), so orgs that need per-resource separation can grant only those and stay on the legacy tools until retirement. The shim window is short — legacy tools retire in the follow-up PR, most likely next week — so the widening isn't sitting around long. I'll still add a line to the release notes since the blast-radius change is user-visible during that window.

mcp: ['tableau:mcp:content:delete'],
api: new Set([
'tableau:workbooks:delete',
'tableau:workbook_tags:update',
'tableau:datasources:delete',
'tableau:datasource_tags:update',
'tableau:tasks:delete',
'tableau:users:read',
...RESOURCE_ACCESS_CHECKER_REQUIRED_API_SCOPES,
]),
},
};

function getEnabledToolNames(): Set<WebToolName> {
Expand All @@ -354,6 +387,8 @@ function getEnabledToolNames(): Set<WebToolName> {
enabledTools.delete('query-admin-insights-site-content');
enabledTools.delete('query-admin-insights-job-performance');
enabledTools.delete('get-stale-content-report');
enabledTools.delete('query-admin-insights');
enabledTools.delete('delete-content');
}

// Remove the MCP-Apps-only tools if the mcp-apps feature is disabled. The confirm-* tools are the
Expand Down
Loading
Loading