Skip to content

Conversation

@jarhun88
Copy link
Contributor

@jarhun88 jarhun88 commented Nov 21, 2025

IMPORTANT: Please do not create a Pull Request without creating an issue first.

Any change needs to be discussed before proceeding. Failure to do so may result in the rejection of
the pull request.

Pull Request Template

Description

Motivation and Context

Today, the tableau mcp server mostly provides direct access to existing APIs on the tableau platform (e.g /search, /query-datasource, /get-workbooks, etc.). However, in the case of the Pulse discover experience, we have invested a lot of time and resources into building an intelligent experience. The goal of integrating the Pulse /discover experience into the Tableau MCP server is to:

Externalize the intelligence that we have implemented natively on the tableau platform
Provide a clearer value proposition for how the MCP server improves as customers leverage the capabilities on our premium SKUs

The intelligence in the discover service is that it has been instructed how to compare and analyze a group of metric insights that belong to a metric group. In addition, it provides relevant follow-up questions based on additional deterministic insights that can be gleaned from the metric group in scope.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Other (please describe):

How Has This Been Tested?

  • vibe tested
  • sanity tool unit tests

Related Issues

Checklist

  • I have updated the version in the package.json file by using npm run version.
    For example, use npm run version:patch for a patch version bump.
  • I have made any necessary changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Contributor Agreement

By submitting this pull request, I confirm that:

Comment on lines 128 to 135
mocks.mockGetConfig.mockReturnValue({
disableMetadataApiRequests: false,
boundedContext: {
projectIds: null,
datasourceIds: null,
workbookIds: null,
},
});
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same, I feel like having the mock config may be unnecessary

Copy link
Contributor Author

Choose a reason for hiding this comment

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

keeping this cuz it seems i need it for the scoping

Copy link
Collaborator

@anyoung-tableau anyoung-tableau Nov 26, 2025

Choose a reason for hiding this comment

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

With tool scoping you will likely need to add back resetResourceAccessCheckerSingleton() in case you ever added a 2nd test that tested scoping.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm tests still pass without it, tho its not clear for me what this does

Copy link
Collaborator

Choose a reason for hiding this comment

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

The resource access checker singleton caches the results of whether a datasource is allowed or not. Resetting it clears the cache

});
};

generatePulseInsightBrief = async (
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: please document this method similar to the other ones in this file

if (message.metric_group_context) {
message.metric_group_context = message.metric_group_context.filter(
(metricContext) =>
datasourceIds.has(metricContext.metric.definition.datasource.id),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Non-blocking, but I noticed that Pulse tool scoping checks the datasourceIds from the boundedContext directly, instead of using resourceAccessChecker.isDatasourceAllowed() which also checks if the datasource exists in an allowed project if a project filter is defined. I don't think this was intentional.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants