diff --git a/gatsby-node.js b/gatsby-node.js index 3cb3567e4..a4566688b 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -6,6 +6,62 @@ const { } = require('./src/configs/doc-configs'); const { getDocLinkFromEdge } = require('./src/utils/gatsby-utils.js'); +/* ── Build-time Markdown generation ─────────────────────────────────────── + * For every asciidoc node, convert the already-generated HTML to clean + * Markdown using cheerio (DOM pre-processing) + turndown (HTML→MD). + * The result is stored as `fields.markdownBody` on each node and exposed + * in GraphQL so CopyPageDropdown can use it instead of scraping the DOM. + */ +exports.onCreateNode = ({ node, actions }) => { + if (node.internal.type !== 'Asciidoc') return; + + const { createNodeField } = actions; + const TurndownService = require('turndown'); + const cheerio = require('cheerio'); + + const html = node.html || ''; + const title = node.document?.title || node.pageAttributes?.title || ''; + + /* Load HTML into cheerio for pre-processing */ + const $ = cheerio.load(html, { decodeEntities: false }); + + /* Remove anchor icon links that Asciidoctor injects next to headings */ + $('a.anchor').remove(); + + /* Remove the embedded TOC — it adds noise to Markdown */ + $('#toc').remove(); + + /* Convert admonition tables to readable text blocks */ + $('.admonitionblock').each((_, el) => { + const type = $(el).attr('class').match(/\b(note|tip|warning|caution|important)\b/i)?.[1]?.toUpperCase() || 'NOTE'; + const content = $(el).find('td.content').text().trim(); + $(el).replaceWith(`

${type}: ${content}

`); + }); + + /* Get the cleaned HTML */ + const cleanedHtml = $('body').html() || ''; + + /* Configure turndown */ + const td = new TurndownService({ + headingStyle: 'atx', + bulletListMarker: '-', + codeBlockStyle: 'fenced', + fence: '```', + }); + + /* GFM table plugin — renders tables as proper Markdown pipe tables */ + const { tables } = require('turndown-plugin-gfm'); + td.use(tables); + + const markdownBody = td.turndown(cleanedHtml); + + createNodeField({ + node, + name: 'markdownBody', + value: markdownBody, + }); +}; + exports.onPostBuild = () => { fsExtra.copyFileSync( `${__dirname}/robots.txt`, @@ -39,12 +95,23 @@ exports.createPages = async function ({ actions, graphql }) { `); const namePageIdMap = {}; + // Collect per-category nav HTMLs keyed by category name (pageid minus 'nav-' prefix) + const navMap = {}; + const NAV_PARTIAL_PREFIX = 'nav-'; + data.allAsciidoc.edges.forEach((e) => { const { sourceInstanceName: sourceName, relativePath: relPath, } = e.node.parent; const pageId = e.node.pageAttributes.pageid; + + // Collect nav-* files into the navMap (not content pages) + if (pageId && pageId.startsWith(NAV_PARTIAL_PREFIX)) { + navMap[pageId.slice(NAV_PARTIAL_PREFIX.length)] = e.node.html; + return; + } + if (sourceName === 'tutorials') { const relPathSplit = relPath.split('/'); const pageIdSplit = pageId.split('__'); @@ -66,13 +133,16 @@ exports.createPages = async function ({ actions, graphql }) { data.allAsciidoc.edges.forEach((edge) => { const { pageid: pageId } = edge.node.pageAttributes; + // Skip nav partial files — they are sidebar data, not content pages + if (pageId && pageId.startsWith(NAV_PARTIAL_PREFIX)) return; + const docPath = getDocLinkFromEdge(edge); actions.createPage({ path: docPath, component: require.resolve( './src/components/DevDocTemplate/index.tsx', ), - context: { pageId, navId: DOC_NAV_PAGE_ID, namePageIdMap }, + context: { pageId, navId: DOC_NAV_PAGE_ID, navMap, namePageIdMap }, }); if (pageId === 'introduction') { @@ -81,7 +151,7 @@ exports.createPages = async function ({ actions, graphql }) { component: require.resolve( './src/components/DevDocTemplate/index.tsx', ), - context: { pageId, navId: DOC_NAV_PAGE_ID, namePageIdMap }, + context: { pageId, navId: DOC_NAV_PAGE_ID, navMap, namePageIdMap }, }); } }); diff --git a/modules/ROOT/pages/ai-integration-options.adoc b/modules/ROOT/pages/ai-integration-options.adoc index 5e67530b7..ec760fd73 100644 --- a/modules/ROOT/pages/ai-integration-options.adoc +++ b/modules/ROOT/pages/ai-integration-options.adoc @@ -1,4 +1,4 @@ -= ThoughtSpot AI analytics integration += AI analytics integration :toc: true :toclevels: 3 diff --git a/modules/ROOT/pages/common/nav-embedding.adoc b/modules/ROOT/pages/common/nav-embedding.adoc new file mode 100644 index 000000000..e3f9a617d --- /dev/null +++ b/modules/ROOT/pages/common/nav-embedding.adoc @@ -0,0 +1,177 @@ + +:page-pageid: nav-embedding +:page-description: Embedding navigation + +[navSection] + +[.sidebar-title] +Embed ThoughtSpot in a web app + +* link:{{navprefix}}/getting-started[Embed with Visual Embed SDK] +* link:{{navprefix}}/tsembed[Quickstart guide] +* link:{{navprefix}}/embed-ai-search-analytics[Embed AI Search and Analytics] +** link:{{navprefix}}/embed-spotter[Embed Spotter experience] +** link:{{navprefix}}/embed-spotter-agent[Embed Spotter Agent] +* link:{{navprefix}}/embed-liveboard[Embed Analytics] +** link:{{navprefix}}/embed-liveboard[Embed a Liveboard] +** link:{{navprefix}}/embed-a-viz[Embed a visualization] +* link:{{navprefix}}/full-embed[Embed full application] +** link:{{navprefix}}/full-app-customize[Customize your embed] +** link:{{navprefix}}/customize-nav-controls[Customize navigation panels] +** link:{{navprefix}}/set-default-page[Customize default page and navigation path] +** link:{{navprefix}}/customize-homepage-experience[Customize home page experience] +* Embed token-based Search +** link:{{navprefix}}/search-embed[Embed Search] +** link:{{navprefix}}/embed-searchbar[Embed search bar] +* link:{{navprefix}}/react-app-embed[Embed with React components] + +[.sidebar-title] +Embed ThoughtSpot in a mobile app + +* link:{{navprefix}}/mobile-embed[Overview] +* link:{{navprefix}}/embed-ts-mobile-react-native[React Native SDK] +* link:{{navprefix}}/embed-ts-flutter[Flutter embed SDK] +* link:{{navprefix}}/embed-ts-swift[Swift Embed SDK] +* link:{{navprefix}}/embed-ts-android[Android Embed SDK] + +[.sidebar-title] +Embed without SDK + +** link:{{navprefix}}/embed-without-sdk[Embed without SDK] +** link:{{navprefix}}/custom-viz-rest-api[Create a custom visualization] + +[.sidebar-title] +Customize and integrate + +* link:{{navprefix}}/style-customization[Customize UI layout and styles] +** link:{{navprefix}}/customize-style[Customize basic styles] +** link:{{navprefix}}/custom-css[CSS customization framework] +** link:{{navprefix}}/theme-builder-doc[Theme builder] +** link:{{navprefix}}/customize-icons[Customize icons] +** link:{{navprefix}}/customize-text[Customize text strings] +** link:{{navprefix}}/css-variables-reference[CSS variables reference] + +* link:{{navprefix}}/filters-overview[Filters overview] +** link:{{navprefix}}/runtime-overrides[Runtime overrides] +** link:{{navprefix}}/runtime-filters[Runtime filters] +** link:{{navprefix}}/runtime-params[Runtime Parameters] +* link:{{navprefix}}/action-config[Customize menus] +** link:{{navprefix}}/actions[Action IDs in the SDK] +* link:{{navprefix}}/events-app-integration[Events and app interactions] +** link:{{navprefix}}/embed-events[Using embed events] +** link:{{navprefix}}/host-events[Using host events] +** link:{{navprefix}}/context-aware-event-routing[Context-based execution of host events] +** link:{{navprefix}}/hostEventsV2-migration[Migrating from Host Event v1 to Host Events v2 framework] +** link:{{navprefix}}/api-search-intercept[API intercept and data fetch requests] + +* link:{{navprefix}}/custom-action-intro[Custom actions] +** link:{{navprefix}}/customize-actions[Custom actions through the UI] +*** link:{{navprefix}}/custom-action-url[URL actions] +*** link:{{navprefix}}/custom-action-callback[Callback actions] +*** link:{{navprefix}}/edit-custom-action[Set the position of a custom action] +*** link:{{navprefix}}/add-action-viz[Add a local action to a visualization] +*** link:{{navprefix}}/add-action-worksheet[Add a local action to a model] +** link:{{navprefix}}/code-based-custom-action[Code based custom actions] +** link:{{navprefix}}/custom-action-payload[Callback response payload] + +* link:{{navprefix}}/customize-links[Customize links] +* link:{{navprefix}}/set-locale[Customize locale] +* link:{{navprefix}}/custom-domain-config[Custom domain configuration] +* link:{{navprefix}}/customize-emails[Customize onboarding settings] +* link:{{navprefix}}/customize-email-apis[Customize email template] +* link:{{navprefix}}/in-app-navigation[Create dynamic menus and navigation] +* link:{{navprefix}}/best-practices[Performance optimization] +** link:{{navprefix}}/best-practices[Best practices] +** link:{{navprefix}}/prerender[Prerender components] +** link:{{navprefix}}/lazy-load-fullHeight[Full height and lazy loading options] +** link:{{navprefix}}/prefetch[Prefetch static resources] +* link:{{navprefix}}/troubleshoot-errors[Troubleshoot errors] + +[.sidebar-title] +Authentication and data security + +* link:{{navprefix}}/embed-auth[Authentication] +** link:{{navprefix}}/trusted-auth[Trusted authentication] +*** link:{{navprefix}}/trusted-auth-secret-key[Secret key management] +*** link:{{navprefix}}/trusted-auth-sdk[Front-end trusted authentication integration] +*** link:{{navprefix}}/trusted-auth-token-request-service[Token request service] +*** link:{{navprefix}}/trusted-auth-troubleshoot[Troubleshoot trusted authentication] +** link:{{navprefix}}/saml-sso[SAML SSO authentication] +** link:{{navprefix}}/oidc-auth[OpenID Connect authentication] +** link:{{navprefix}}/just-in-time-provisioning[Just-in-time provisioning] +* link:{{navprefix}}/security-settings[Security settings] + +* link:{{navprefix}}/embed-object-access[Authorization] +** link:{{navprefix}}/access-control-sharing[Access control and sharing] +** link:{{navprefix}}/privileges-and-roles[Privileges and Roles] +** link:{{navprefix}}/data-security[Data security] +*** link:{{navprefix}}/rls-rules[RLS Rules] +*** link:{{navprefix}}/abac-via-rls-variables[ABAC via RLS with variables] +*** link:{{navprefix}}/jwt-abac-migration-guide[ABAC JWT migration guide] +**** link:{{navprefix}}/jwt-filter-parameters-rules-migration-guide[JWT ABAC with filter rules -> ABAC via RLS] +**** link:{{navprefix}}/jwt-abac-beta-migration-guide[JWT ABAC beta implementation -> ABAC via RLS] +*** link:{{navprefix}}/abac-user-parameters[ABAC via JWT with filter rules and parameters] +* link:{{navprefix}}/selective-user-access[User access] +* link:{{navprefix}}/troubleshoot-errors[Troubleshoot errors] + +[.sidebar-title] +Authentication and data security + +* link:{{navprefix}}/tutorials/tutorials-overview[Embedding tutorials] +* link:{{navprefix}}/tutorials/tse-fundamentals/intro[Embedding Fundamentals] +** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-01[01 - Overview] +** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-02[02 - Set up for course] +** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-03[03 - Security setup] +** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-04[04 - Start coding] +** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-05[05 - Embed Search] +** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-06[06 - Embed Natural Language Search] +** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-07[07 - Embed Liveboard] +** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-08[08 - Embed Visualization] +** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-09[09 - Embed full application] +** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-10[10 - Style embedded app] +** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-11[11 - Course summary] +** link:{{navprefix}}/tutorials/style-customization/tutorial[Style customization] +* link:{{navprefix}}/tutorials/react-components/intro[React components] +** link:{{navprefix}}/tutorials/react-components/lesson-01[01 - Initialize Visual Embed SDK] +** link:{{navprefix}}/tutorials/react-components/lesson-02[02 - ThoughtSpot component pages] +** link:{{navprefix}}/tutorials/react-components/lesson-03[03 - Menus and navigation elements] +** link:{{navprefix}}/tutorials/react-components/lesson-04[04 - Event handling] + + +[.sidebar-title] +Reference guides and changelog + +* +++Visual Embed Playground+++ +* link:{{navprefix}}/VisualEmbedSdk[Visual Embed SDK Reference] +include::generated/typedoc/CustomSideNav.adoc[] +** Custom styles +*** [.typedoc-Interface]#link:{{navprefix}}/Interface_CustomStyles[CustomStyles]# +*** [.typedoc-Interface]#link:{{navprefix}}/Interface_CustomisationsInterface[CustomisationsInterface]# +*** [.typedoc-Interface]#link:{{navprefix}}/Interface_customCssInterface[customCssInterface]# +*** [.typedoc-Interface]#link:{{navprefix}}/Interface_CustomCssVariables[customCssVariables]# +** Runtime filters +*** [.typedoc-Interface]#link:{{navprefix}}/Interface_RuntimeFilter[RuntimeFilter]# +*** [.typedoc-Enumeration]#link:{{navprefix}}/Enumeration_RuntimeFilterOp[RuntimeFilterOp]# +** Others +*** [.typedoc-Enumeration]#link:{{navprefix}}/Enumeration_Action[Action]# +*** [.typedoc-Enumeration]#link:{{navprefix}}/Enumeration_ContextMenuTriggerOptions[ContextMenuTriggerOptions]# +*** [.typedoc-Enumeration]#link:{{navprefix}}/Enumeration_DataSourceVisualMode[DataSourceVisualMode]# +*** [.typedoc-Enumeration]#link:{{navprefix}}/Enumeration_Page[Page]# +*** [.typedoc-Enumeration]#link:{{navprefix}}/Enumeration_PrefetchFeatures[PrefetchFeatures]# +*** [.typedoc-Function]#link:{{navprefix}}/Function_executeTML[executeTML]# +*** [.typedoc-Function]#link:{{navprefix}}/Function_exportTML[exportTML]# +* link:{{navprefix}}/embed-sdk-changelog[Changelog] +** link:{{navprefix}}/embed-sdk-changelog[Visual Embed SDK] +** link:{{navprefix}}/mobile-sdk-changelog[Mobile Embed SDK] + +[.sidebar-title] +Additional resources + +* link:{{navprefix}}/embed-ts[About ThoughtSpot embedding] +* link:{{navprefix}}/get-started-tse[Embed licenses] +* link:{{navprefix}}/license-feature-matrix[Feature matrix] +* link:{{navprefix}}/faqs[FAQs] +* link:{{navprefix}}/code-samples[Code samples] +* link:https://codesandbox.io/s/big-tse-react-demo-i4g9xi[React CodeSandbox, window=_blank] +* link:https://codesandbox.io/s/graphqlcookieembed-wf4fk9?file=/src/App.js:418-426[GraphQL CodeSandbox, window=_blank] + diff --git a/modules/ROOT/pages/common/nav-mcp-server.adoc b/modules/ROOT/pages/common/nav-mcp-server.adoc new file mode 100644 index 000000000..d40f131d7 --- /dev/null +++ b/modules/ROOT/pages/common/nav-mcp-server.adoc @@ -0,0 +1,32 @@ + +:page-pageid: nav-mcp-server +:page-description: MCP Server navigation + +[navSection] + +[.sidebar-title] +ThoughtSpot MCP server + +* link:{{navprefix}}/mcp-integration[Overview] +** link:{{navprefix}}/mcp-server-spotter3[MCP Server with Spotter 3] +** link:{{navprefix}}/mcp-server-legacy[Legacy MCP Server architecture and tools] +* link:{{navprefix}}/connect-mcp-server-to-clients[Connecting MCP Server to MCP clients] +* link:{{navprefix}}/custom-chatbot-integration-mcp[Integrating MCP Server in a custom app] + +[.sidebar-title] +MCP tools reference + +* link:{{navprefix}}/mcp-tool-reference[Overview] +* link:{{navprefix}}/mcp-tool-reference-spotter3[MCP tool reference (Spotter 3)] +* link:{{navprefix}}/mcp-tool-reference-spotter3[MCP tool reference (legacy version)] + +[.sidebar-title] +Related SDK components + +* [.typedoc-Function]#link:{{navprefix}}/Function_startAutoMCPFrameRenderer[startAutoMCPFrameRenderer]# +* [.typedoc-Interface]#link:{{navprefix}}/Interface_AutoMCPFrameRendererViewConfig[AutoMCPFrameRendererViewConfig]# + +[.sidebar-title] +MCP Server release notes + +* link:{{navprefix}}/mcp-server-changelog[MCP Server changelog] diff --git a/modules/ROOT/pages/common/nav-rest-api.adoc b/modules/ROOT/pages/common/nav-rest-api.adoc new file mode 100644 index 000000000..a9fec3165 --- /dev/null +++ b/modules/ROOT/pages/common/nav-rest-api.adoc @@ -0,0 +1,96 @@ + +:page-pageid: nav-rest-api +:page-description: REST API navigation + +[navSection] + +[.sidebar-title] +REST APIs + +* link:{{navprefix}}/rest-apis[Overview] +* link:{{navprefix}}/rest-apiv2-getstarted[Get started] +* link:{{navprefix}}/api-authv2[REST API v2.0 authentication] +* link:{{navprefix}}/rest-v2-changelog[REST API v2 changelog] +* link:{{navprefix}}/restV2-playground?apiResourceId=http%2Fgetting-started%2Fintroduction[REST API v2 Playground] +* link:{{navprefix}}/rest-apiv2-reference[REST API v2.0 Reference] +** link:{{navprefix}}/api-user-management[Users and group privileges] +** link:{{navprefix}}/rbac[Role-based access control] +** link:{{navprefix}}/rest-apiv2-search[Search API endpoints] +*** link:{{navprefix}}/rest-apiv2-users-search[Search users] +*** link:{{navprefix}}/rest-apiv2-groups-search[Search groups] +*** link:{{navprefix}}/rest-apiv2-metadata-search[Search metadata] +** link:{{navprefix}}/fetch-data-and-report-apis[Data and Report APIs] +** link:{{navprefix}}/spotter-api[Spotter APIs] +*** link:{{navprefix}}/spotter-agent-apis[AI APIs (Spotter Agent and Spotter 3)] +*** link:{{navprefix}}/spotter-apis-classic[AI APIs (Spotter Classic) ^BETA^] +*** link:{{navprefix}}/spotter-coaching-apis[Spotter coaching APIs ^BETA^] +** link:{{navprefix}}/audit-logs[Audit logs] +** link:{{navprefix}}/tml[TML] +** link:{{navprefix}}/collections[Collections ^BETA^] +** link:{{navprefix}}/connections[Connections] +** link:{{navprefix}}/connection-config[Connection configuration] +** link:{{navprefix}}/runtime-sort[Runtime sorting] + + +[.sidebar-title] +REST API SDK + +* link:{{navprefix}}/rest-api-sdk[Overview] +* link:{{navprefix}}/rest-api-sdk-typescript[TypeScript SDK] +* link:{{navprefix}}/rest-api-sdk-java[Java SDK] +* link:{{navprefix}}/rest-apiv2-js[REST API v2.0 in JavaScript] + +[.sidebar-title] +Webhooks + +* link:{{navprefix}}/webhooks[Overview] +* link:{{navprefix}}/webhooks-comm-channel[Configure and monitor webhook communication channels] +* link:{{navprefix}}/webhooks-s3-integration[Deliver Liveboard reports to AWS S3 Storage] +* link:{{navprefix}}/webhooks-lb-schedule[Deliver Liveboard reports to external application] +* link:{{navprefix}}/webhooks-lb-payload[Webhook response payload] +* link:{{navprefix}}/webhooks-kpi[Webhook for KPI alerts] + +[.sidebar-title] +REST API Tutorials + +* link:{{navprefix}}/tutorials/rest-api/intro[REST API Tutorials] +* link:{{navprefix}}/tutorials/rest-api/lesson-01[01 - REST API overview] +* link:{{navprefix}}/tutorials/rest-api/lesson-02[02 - Simple Python implementation] +* link:{{navprefix}}/tutorials/rest-api/lesson-03[03 - Complex REST API workflows] + +[.sidebar-title] +REST API v1 (DEPRECATED) + +* link:{{navprefix}}/rest-api-getstarted[Get started] +* link:{{navprefix}}/api-auth-session[REST API v1 authentication] +* link:{{navprefix}}/catalog-and-audit[Catalog and audit content] +* link:{{navprefix}}/rest-api-pagination[Paginate API response] +* link:{{navprefix}}/rest-api-reference[REST API v1 Reference] +** link:{{navprefix}}/orgs-api[Orgs API] +** link:{{navprefix}}/user-api[User API] +** link:{{navprefix}}/group-api[Group API] +** link:{{navprefix}}/role-api[Role API] +** link:{{navprefix}}/session-api[Session API] +** link:{{navprefix}}/connections-api[Data connection API] +** link:{{navprefix}}/metadata-api[Metadata API] +** link:{{navprefix}}/admin-api[Admin API] +** link:{{navprefix}}/tml-api[TML API] +** link:{{navprefix}}/dependent-objects-api[Dependent objects API] +** link:{{navprefix}}/search-data-api[Search data API] +** link:{{navprefix}}/liveboard-data-api[Liveboard data API] +** link:{{navprefix}}/liveboard-export-api[Liveboard export API] +** link:{{navprefix}}/security-api[Security API] +** link:{{navprefix}}/logs-api[Audit logs API] +** link:{{navprefix}}/materialization-api[Materialization API] +** link:{{navprefix}}/database-api[Database API] +** link:{{navprefix}}/rest-v1-changelog[REST API v1 changelog] +** link:{{navprefix}}/v1v2-comparison[REST v1 and v2.0 comparison] + + +//** link:{{navprefix}}/graphql-guide[GraphQL API ^Beta^] + + + + + + diff --git a/modules/ROOT/pages/common/nav-spottercode.adoc b/modules/ROOT/pages/common/nav-spottercode.adoc new file mode 100644 index 000000000..b60c85c31 --- /dev/null +++ b/modules/ROOT/pages/common/nav-spottercode.adoc @@ -0,0 +1,12 @@ + +:page-pageid: nav-spottercode +:page-description: SpotterCode navigation + +[navSection] + +[.sidebar-title] +SpotterCode agent + +* link:{{navprefix}}/SpotterCode[SpotterCode for IDEs] +* link:{{navprefix}}/integrate-SpotterCode[Integrating SpotterCode] +* link:{{navprefix}}/spottercode-prompting-guide[SpotterCode prompting guide] diff --git a/modules/ROOT/pages/common/nav-tutorials.adoc b/modules/ROOT/pages/common/nav-tutorials.adoc new file mode 100644 index 000000000..b7933f53d --- /dev/null +++ b/modules/ROOT/pages/common/nav-tutorials.adoc @@ -0,0 +1,29 @@ + +:page-pageid: nav-tutorials +:page-description: Tutorials navigation + +[navSection] + +* link:{{navprefix}}/tutorials/tutorials-overview[Tutorials] +** link:{{navprefix}}/tutorials/tse-fundamentals/intro[Embedding Fundamentals] +*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-01[01 - Overview] +*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-02[02 - Set up for course] +*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-03[03 - Security setup] +*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-04[04 - Start coding] +*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-05[05 - Embed Search] +*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-06[06 - Embed Natural Language Search] +*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-07[07 - Embed Liveboard] +*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-08[08 - Embed Visualization] +*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-09[09 - Embed full application] +*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-10[10 - Style embedded app] +*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-11[11 - Course summary] +** link:{{navprefix}}/tutorials/style-customization/tutorial[Style customization] +** link:{{navprefix}}/tutorials/react-components/intro[React components] +*** link:{{navprefix}}/tutorials/react-components/lesson-01[01 - Initialize Visual Embed SDK] +*** link:{{navprefix}}/tutorials/react-components/lesson-02[02 - ThoughtSpot component pages] +*** link:{{navprefix}}/tutorials/react-components/lesson-03[03 - Menus and navigation elements] +*** link:{{navprefix}}/tutorials/react-components/lesson-04[04 - Event handling] + +*** link:{{navprefix}}/tutorials/rest-api/lesson-04[04 - Event handling] +** Spotter +*** link:{{navprefix}}/tutorials/spotter/integrate-into-chatbot[Integrate Spotter into your Chatbot] diff --git a/modules/ROOT/pages/common/nav.adoc b/modules/ROOT/pages/common/nav.adoc index 0a8fbeb9d..a3af2a9a6 100644 --- a/modules/ROOT/pages/common/nav.adoc +++ b/modules/ROOT/pages/common/nav.adoc @@ -4,254 +4,97 @@ [navSection] -* link:{{navprefix}}/ask-docs[AskDocs ^Beta^] +[.sidebar-title] +Release notes and changelogs -* link:{{navprefix}}/whats-new[What's New] -** link:{{navprefix}}/whats-new[New features] -*** link:{{navprefix}}/fixed-issues[Fixed issues] -*** link:{{navprefix}}/known-issues[Known Issues] +* link:{{navprefix}}/whats-new[What's new] +* Changelog +** link:{{navprefix}}/embed-sdk-changelog[Visual Embed SDK changelog] +** link:{{navprefix}}/mobile-sdk-changelog[Mobile Embed SDK changelog] +** link:{{navprefix}}/rest-v2-changelog[REST API v2 changelog] +** link:{{navprefix}}/mcp-server-changelog[MCP Server changelog] +* link:{{navprefix}}/deprecated-features[Deprecation announcements] +[.sidebar-title] +Live Playgrounds -** link:{{navprefix}}/embed-sdk-changelog[SDK and API changelog] -*** link:{{navprefix}}/embed-sdk-changelog[Visual Embed changelog] -*** link:{{navprefix}}/mobile-sdk-changelog[Mobile Embed SDK changelog] -*** link:{{navprefix}}/rest-v2-changelog[REST API v2 changelog] -*** link:{{navprefix}}/rest-v1-changelog[REST API v1 changelog] -** link:{{navprefix}}/deprecated-features[Deprecation announcements] +* +++Visual Embed Playground+++ +** link:{{navprefix}}/dev-playground[How to use] -* Live Playgrounds -** +++Visual Embed Playground+++ -** link:{{navprefix}}/restV2-playground?apiResourceId=http%2Fgetting-started%2Fintroduction[REST API v2 Playground] -** link:{{navprefix}}/graphql-play-ground[GraphQL Playground] -** +++REST API v1 Playground+++ -** link:{{navprefix}}/theme-builder[Theme Builder] -** link:{{navprefix}}/spotdev-portal[How to use] -*** link:{{navprefix}}/dev-playground[Visual Embed Playground] -*** link:{{navprefix}}/graphql-playground[GraphQL Playground] -*** link:{{navprefix}}/rest-playground[REST API Playground] +* link:{{navprefix}}/restV2-playground?apiResourceId=http%2Fgetting-started%2Fintroduction[REST API v2 Playground] +** link:{{navprefix}}/rest-playground[How to use] +//** link:{{navprefix}}/graphql-play-ground[GraphQL Playground] +//** +++REST API v1 Playground+++ +* link:{{navprefix}}/theme-builder[Theme Builder] +** link:{{navprefix}}/theme-builder-doc[How to use] -* link:{{navprefix}}/tutorials/tutorials-overview[Tutorials] -** link:{{navprefix}}/tutorials/tse-fundamentals/intro[Embedding Fundamentals] -*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-01[01 - Overview] -*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-02[02 - Set up for course] -*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-03[03 - Security setup] -*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-04[04 - Start coding] -*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-05[05 - Embed Search] -*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-06[06 - Embed Natural Language Search] -*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-07[07 - Embed Liveboard] -*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-08[08 - Embed Visualization] -*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-09[09 - Embed full application] -*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-10[10 - Style embedded app] -*** link:{{navprefix}}/tutorials/tse-fundamentals/lesson-11[11 - Course summary] -** link:{{navprefix}}/tutorials/style-customization/tutorial[Style customization] -** link:{{navprefix}}/tutorials/react-components/intro[React components] -*** link:{{navprefix}}/tutorials/react-components/lesson-01[01 - Initialize Visual Embed SDK] -*** link:{{navprefix}}/tutorials/react-components/lesson-02[02 - ThoughtSpot component pages] -*** link:{{navprefix}}/tutorials/react-components/lesson-03[03 - Menus and navigation elements] -*** link:{{navprefix}}/tutorials/react-components/lesson-04[04 - Event handling] -** link:{{navprefix}}/tutorials/rest-api/intro[REST API] -*** link:{{navprefix}}/tutorials/rest-api/lesson-01[01 - REST API overview] -*** link:{{navprefix}}/tutorials/rest-api/lesson-02[02 - Simple Python implementation] -*** link:{{navprefix}}/tutorials/rest-api/lesson-03[03 - Complex REST API workflows] -*** link:{{navprefix}}/tutorials/rest-api/lesson-04[04 - Event handling] -** Spotter -*** link:{{navprefix}}/tutorials/spotter/integrate-into-chatbot[Integrate Spotter into your Chatbot] -* link:{{navprefix}}/getting-started[Embed ThoughtSpot] -** link:{{navprefix}}/getting-started[Quickstart Guide] -** link:{{navprefix}}/tsembed[Embed ThoughtSpot in Web app] -*** Embed analytics -**** link:{{navprefix}}/embed-liveboard[Embed a Liveboard] -**** link:{{navprefix}}/embed-a-viz[Embed a visualization] -*** link:{{navprefix}}/embed-ai-search-analytics[Embed AI Search and Analytics] -**** link:{{navprefix}}/embed-spotter[Embed Spotter experience] -**** link:{{navprefix}}/embed-spotter-agent[Embed Spotter Agent] -*** link:{{navprefix}}/full-embed[Embed full application] -**** link:{{navprefix}}/full-app-customize[Customize your embed] -**** link:{{navprefix}}/customize-nav-controls[Customize navigation panels] -**** link:{{navprefix}}/set-default-page[Customize default page and navigation path] -**** link:{{navprefix}}/customize-homepage-experience[Customize home page experience] - -*** Embed token-based Search -**** link:{{navprefix}}/search-embed[Embed Search] -**** link:{{navprefix}}/embed-searchbar[Embed search bar] -*** link:{{navprefix}}/react-app-embed[Embed with React components] -** link:{{navprefix}}/mobile-embed[Embed ThoughtSpot in a mobile app] -*** link:{{navprefix}}/embed-ts-mobile-react-native[React Native SDK] -*** link:{{navprefix}}/embed-ts-flutter[Flutter embed SDK] -*** link:{{navprefix}}/embed-ts-swift[Swift Embed SDK] -*** link:{{navprefix}}/embed-ts-android[Android Embed SDK] - -** Customize and integrate -*** link:{{navprefix}}/style-customization[Customize UI layout and styles] -**** link:{{navprefix}}/customize-style[Customize basic styles] -**** link:{{navprefix}}/custom-css[CSS customization framework] -***** link:{{navprefix}}/css-variables-reference[CSS variables reference] -***** link:{{navprefix}}/customize-icons[Customize icons] -***** link:{{navprefix}}/customize-text[Customize text strings] -***** link:{{navprefix}}/theme-builder-doc[Theme builder] - -*** link:{{navprefix}}/filters-overview[Filters overview] -**** link:{{navprefix}}/runtime-overrides[Runtime overrides] -**** link:{{navprefix}}/runtime-filters[Runtime filters] -**** link:{{navprefix}}/runtime-params[Runtime Parameters] - -*** link:{{navprefix}}/action-config[Customize menus] -**** link:{{navprefix}}/actions[Action IDs in the SDK] -*** link:{{navprefix}}/events-app-integration[Events and app interactions] -**** link:{{navprefix}}/embed-events[Using embed events] -**** link:{{navprefix}}/host-events[Using host events] -**** link:{{navprefix}}/context-aware-event-routing[Context-based execution of host events] -**** link:{{navprefix}}/hostEventsV2-migration[Migrating from Host Event v1 to Host Events v2 framework] -**** link:{{navprefix}}/api-search-intercept[API intercept and data fetch requests] -*** link:{{navprefix}}/custom-action-intro[Custom actions] -**** link:{{navprefix}}/customize-actions[Custom actions through the UI] -***** link:{{navprefix}}/custom-action-url[URL actions] -***** link:{{navprefix}}/custom-action-callback[Callback actions] -***** link:{{navprefix}}/edit-custom-action[Set the position of a custom action] -***** link:{{navprefix}}/add-action-viz[Add a local action to a visualization] -***** link:{{navprefix}}/add-action-worksheet[Add a local action to a model] -**** link:{{navprefix}}/code-based-custom-action[Code based custom actions] -**** link:{{navprefix}}/custom-action-payload[Callback response payload] -*** link:{{navprefix}}/customize-links[Customize links] -*** link:{{navprefix}}/set-locale[Customize locale] -*** link:{{navprefix}}/custom-domain-config[Custom domain configuration] -*** link:{{navprefix}}/customize-emails[Customize onboarding settings] -*** link:{{navprefix}}/customize-email-apis[Customize email template] -*** link:{{navprefix}}/in-app-navigation[Create dynamic menus and navigation] -** link:{{navprefix}}/security-settings[Security settings] -** link:{{navprefix}}/embed-auth[Authentication] -*** link:{{navprefix}}/trusted-auth[Trusted authentication] -**** link:{{navprefix}}/trusted-auth-secret-key[Secret key management] -**** link:{{navprefix}}/trusted-auth-sdk[Front-end trusted authentication integration] -**** link:{{navprefix}}/trusted-auth-token-request-service[Token request service] -**** link:{{navprefix}}/trusted-auth-troubleshoot[Troubleshoot trusted authentication] -*** link:{{navprefix}}/saml-sso[SAML SSO authentication] -*** link:{{navprefix}}/oidc-auth[OpenID Connect authentication] -*** link:{{navprefix}}/just-in-time-provisioning[Just-in-time provisioning] -** link:{{navprefix}}/embed-object-access[Authorization] -*** link:{{navprefix}}/access-control-sharing[Access control and sharing] -*** link:{{navprefix}}/privileges-and-roles[Privileges and Roles] -*** link:{{navprefix}}/data-security[Data security] -**** link:{{navprefix}}/rls-rules[RLS Rules] -**** link:{{navprefix}}/abac-via-rls-variables[ABAC via RLS with variables] -**** link:{{navprefix}}/jwt-abac-migration-guide[ABAC JWT migration guide] -***** link:{{navprefix}}/jwt-filter-parameters-rules-migration-guide[JWT ABAC with filter rules -> ABAC via RLS] -***** link:{{navprefix}}/jwt-abac-beta-migration-guide[JWT ABAC beta implementation -> ABAC via RLS] -**** link:{{navprefix}}/abac-user-parameters[ABAC via JWT with filter rules and parameters] -*** link:{{navprefix}}/selective-user-access[User access] -** link:{{navprefix}}/best-practices[Performance optimization] -*** link:{{navprefix}}/best-practices[Best practices] -*** link:{{navprefix}}/prerender[Prerender components] -*** link:{{navprefix}}/lazy-load-fullHeight[Full height and lazy loading options] -*** link:{{navprefix}}/prefetch[Prefetch static resources] -** link:{{navprefix}}/VisualEmbedSdk[Visual Embed SDK Reference] -include::generated/typedoc/CustomSideNav.adoc[] -*** Custom styles -**** [.typedoc-Interface]#link:{{navprefix}}/Interface_CustomStyles[CustomStyles]# -**** [.typedoc-Interface]#link:{{navprefix}}/Interface_CustomisationsInterface[CustomisationsInterface]# -**** [.typedoc-Interface]#link:{{navprefix}}/Interface_customCssInterface[customCssInterface]# -**** [.typedoc-Interface]#link:{{navprefix}}/Interface_CustomCssVariables[customCssVariables]# -*** Runtime filters -**** [.typedoc-Interface]#link:{{navprefix}}/Interface_RuntimeFilter[RuntimeFilter]# -**** [.typedoc-Enumeration]#link:{{navprefix}}/Enumeration_RuntimeFilterOp[RuntimeFilterOp]# -*** Others -**** [.typedoc-Enumeration]#link:{{navprefix}}/Enumeration_Action[Action]# -**** [.typedoc-Enumeration]#link:{{navprefix}}/Enumeration_ContextMenuTriggerOptions[ContextMenuTriggerOptions]# -**** [.typedoc-Enumeration]#link:{{navprefix}}/Enumeration_DataSourceVisualMode[DataSourceVisualMode]# -**** [.typedoc-Enumeration]#link:{{navprefix}}/Enumeration_Page[Page]# -**** [.typedoc-Enumeration]#link:{{navprefix}}/Enumeration_PrefetchFeatures[PrefetchFeatures]# -**** [.typedoc-Function]#link:{{navprefix}}/Function_executeTML[executeTML]# -**** [.typedoc-Function]#link:{{navprefix}}/Function_exportTML[exportTML]# - -** Other embedding methods -*** link:{{navprefix}}/embed-without-sdk[Embed without SDK] -*** link:{{navprefix}}/custom-viz-rest-api[Create a custom visualization] -** link:{{navprefix}}/troubleshoot-errors[Troubleshoot errors] - -* link:{{navprefix}}/rest-apis[REST API] -** link:{{navprefix}}/rest-apis[Overview] -** link:{{navprefix}}/api-user-management[Users and group privileges] -** link:{{navprefix}}/rbac[Role-based access control] -** link:{{navprefix}}/spotter-api[Spotter APIs] -*** link:{{navprefix}}/spotter-agent-apis[AI APIs (Spotter Agent and Spotter 3)] -*** link:{{navprefix}}/spotter-apis-classic[AI APIs (Spotter Classic) ^BETA^] -*** link:{{navprefix}}/spotter-coaching-apis[Spotter coaching APIs ^BETA^] +//*** link:{{navprefix}}/graphql-playground[GraphQL Playground] -** link:{{navprefix}}/audit-logs[Audit logs] -** link:{{navprefix}}/tml[TML] -** link:{{navprefix}}/collections[Collections] -** link:{{navprefix}}/connections[Connections] -*** link:{{navprefix}}/connection-config[Connection configuration] -** link:{{navprefix}}/rest-apiv2-getstarted[REST API v2.0] -*** link:{{navprefix}}/rest-apiv2-getstarted[Get started] -*** link:{{navprefix}}/api-authv2[REST API v2.0 authentication] -*** link:{{navprefix}}/rest-apiv2-js[REST API v2.0 in JavaScript] -*** link:{{navprefix}}/rest-apiv2-search[REST API v2.0 Search endpoints] -**** link:{{navprefix}}/rest-apiv2-users-search[Search users] -**** link:{{navprefix}}/rest-apiv2-groups-search[Search groups] -**** link:{{navprefix}}/rest-apiv2-metadata-search[Search metadata] -*** link:{{navprefix}}/fetch-data-and-report-apis[Data and Report APIs] -*** link:{{navprefix}}/rest-api-sdk[REST API v2.0 SDKs] -**** link:{{navprefix}}/rest-api-sdk-typescript[TypeScript SDK] -**** link:{{navprefix}}/rest-api-sdk-java[Java SDK] -** link:{{navprefix}}/rest-apiv2-reference[REST API v2.0 Reference] -** link:{{navprefix}}/rest-api-getstarted[REST API v1] -*** link:{{navprefix}}/rest-api-getstarted[Get started] -*** link:{{navprefix}}/api-auth-session[REST API v1 authentication] -*** link:{{navprefix}}/catalog-and-audit[Catalog and audit content] -*** link:{{navprefix}}/rest-api-pagination[Paginate API response] -** link:{{navprefix}}/rest-api-reference[REST API v1 Reference] -*** link:{{navprefix}}/orgs-api[Orgs API] -*** link:{{navprefix}}/user-api[User API] -*** link:{{navprefix}}/group-api[Group API] -*** link:{{navprefix}}/role-api[Role API] -*** link:{{navprefix}}/session-api[Session API] -*** link:{{navprefix}}/connections-api[Data connection API] -*** link:{{navprefix}}/metadata-api[Metadata API] -*** link:{{navprefix}}/admin-api[Admin API] -*** link:{{navprefix}}/tml-api[TML API] -*** link:{{navprefix}}/dependent-objects-api[Dependent objects API] -*** link:{{navprefix}}/search-data-api[Search data API] -*** link:{{navprefix}}/liveboard-data-api[Liveboard data API] -*** link:{{navprefix}}/liveboard-export-api[Liveboard export API] -*** link:{{navprefix}}/security-api[Security API] -*** link:{{navprefix}}/logs-api[Audit logs API] -*** link:{{navprefix}}/materialization-api[Materialization API] -*** link:{{navprefix}}/database-api[Database API] -** link:{{navprefix}}/runtime-sort[Runtime sorting] -** link:{{navprefix}}/v1v2-comparison[REST v1 and v2.0 comparison] -** link:{{navprefix}}/graphql-guide[GraphQL API ^Beta^] -** link:{{navprefix}}/webhooks[Webhooks] -*** link:{{navprefix}}/webhooks-comm-channel[Configure and monitor webhook communication channels] -*** link:{{navprefix}}/webhooks-s3-integration[Deliver Liveboard reports to AWS S3 Storage] -*** link:{{navprefix}}/webhooks-lb-schedule[Deliver Liveboard reports to external application] -*** link:{{navprefix}}/webhooks-lb-payload[Webhook response payload] -*** link:{{navprefix}}/webhooks-kpi[Webhook for KPI alerts] +[.sidebar-title] +Get started -* MCP Servers and Tools -** link:{{navprefix}}/SpotterCode[SpotterCode for IDEs] -*** link:{{navprefix}}/integrate-SpotterCode[Integrating SpotterCode] -*** link:{{navprefix}}/spottercode-prompting-guide[SpotterCode prompting guide] -** link:{{navprefix}}/ai-analytics-integration[ThoughtSpot AI analytics integration] -*** link:{{navprefix}}/mcp-integration[ThoughtSpot MCP server] -*** link:{{navprefix}}/connect-mcp-server-to-clients[Connecting MCP Server to MCP clients] -*** link:{{navprefix}}/custom-chatbot-integration-mcp[Integrating MCP Server in a custom application or chatbot] +* link:{{navprefix}}/getting-started[Embed ThoughtSpot] +* link:{{navprefix}}/SpotterCode[SpotterCode for IDEs] +* link:{{navprefix}}/rest-apis[REST APIs] +* link:{{navprefix}}/ai-analytics-integration[AI analytics integration] +* link:{{navprefix}}/mcp-integration[MCP Server integration] +//** link:{{navprefix}}/tutorials/tutorials-overview[Tutorials] +* link:{{navprefix}}/VisualEmbedSdk[SDK and API reference] +** link:{{navprefix}}/VisualEmbedSdk[Visual Embed SDK] +** link:{{navprefix}}/rest-apiv2-reference[REST API] +** link:{{navprefix}}/mcp-tool-reference[MCP tools] + + +[.sidebar-title] +Build and deploy + +* link:{{navprefix}}/development-and-deployment[Development and deployment] +** link:{{navprefix}}/thoughtspot-objects[ThoughtSpot objects] +** link:{{navprefix}}/variables[Variables] +** link:{{navprefix}}/parameterize-metadata[Parameterize metadata] + +* link:{{navprefix}}/deploy-with-tml-apis[Deploy with TML APIs] +** link:{{navprefix}}/git-provider-integration[Git provider integration] +** link:{{navprefix}}/modify-tml[TML modification] +* link:{{navprefix}}/publish-data-overview[Publish content to Orgs] +** link:{{navprefix}}/publish-to-orgs[Publish objects to Orgs] +* link:{{navprefix}}/git-integration[Deploy with GitHub APIs (legacy)] +** link:{{navprefix}}/git-configuration[Configure GitHub integration] +** link:{{navprefix}}/git-api[GitHub REST APIs] +** link:{{navprefix}}/guid-mapping[GUID mapping] + +[.sidebar-title] +Multi-tenancy + +* link:{{navprefix}}/multi-tenancy[Overview] +* link:{{navprefix}}/orgs[Multi-tenancy with Orgs] +** link:{{navprefix}}/orgs-api-op[Org administration] +** link:{{navprefix}}/multitenancy-within-an-org[Multi-tenancy within an Org] +** link:{{navprefix}}/single-tenant-data-models[Single-tenant data models with Orgs] +* link:{{navprefix}}/tse-cluster[Cluster maintenance and upgrade] + +[.sidebar-title] +Integration guides + +** link:{{navprefix}}/external-tool-script-integration[Third-party tools and custom scripts] * link:{{navprefix}}/development-and-deployment[Deployment and integration] ** link:{{navprefix}}/development-and-deployment[Development and deployment] *** link:{{navprefix}}/thoughtspot-objects[ThoughtSpot objects overview] -*** link:{{navprefix}}/variables[Custom variables] -*** link:{{navprefix}}/parameterize-metadata[Parameterize metadata] -*** link:{{navprefix}}/git-integration[Deploy with Git] -**** link:{{navprefix}}/git-configuration[Configure Git integration] -**** link:{{navprefix}}/git-api[Version Control REST APIs] -**** link:{{navprefix}}/guid-mapping[GUID mapping] +*** link:{{navprefix}}/variables[Variables] +*** link:{{navprefix}}/parameterze-metdata[Parameterize metadata] *** link:{{navprefix}}/deploy-with-tml-apis[Deploy with TML APIs] +**** link:{{navprefix}}/git-provider-integration[Git provider integration] **** link:{{navprefix}}/modify-tml[TML modification] *** link:{{navprefix}}/publish-data-overview[Publish content to Orgs] **** link:{{navprefix}}/publish-to-orgs[Publish objects to Orgs] +*** link:{{navprefix}}/git-integration[Deploy with GitHub APIs (legacy)] +**** link:{{navprefix}}/git-configuration[Configure GitHub integration] +**** link:{{navprefix}}/git-api[GitHub REST APIs] +**** link:{{navprefix}}/guid-mapping[GUID mapping] + ** link:{{navprefix}}/multi-tenancy[Multi-tenancy] *** link:{{navprefix}}/orgs[Multi-tenancy with Orgs] @@ -265,20 +108,17 @@ include::generated/typedoc/CustomSideNav.adoc[] ** link:{{navprefix}}/pendo-integration[Pendo integration with embed] ** link:{{navprefix}}/sf-integration[Integration with Salesforce] ** link:{{navprefix}}/vercel-integration[Vercel integration] -* Additional references -** link:{{navprefix}}/embed-ts[About ThoughtSpot embedding] -** link:{{navprefix}}/get-started-tse[Embed licenses] -** link:{{navprefix}}/license-feature-matrix[Feature matrix] -** link:{{navprefix}}/faqs[FAQs] -** link:{{navprefix}}/code-samples[Code samples] -** link:https://codesandbox.io/s/big-tse-react-demo-i4g9xi[React CodeSandbox, window=_blank] -** link:https://codesandbox.io/s/graphqlcookieembed-wf4fk9?file=/src/App.js:418-426[GraphQL CodeSandbox, window=_blank] -* Resources -** link:https://developers.thoughtspot.com[ThoughtSpot Developers, window=_blank] -** link:https://community.thoughtspot.com/customers/s/[Community, window=_blank] -** link:https://developers.thoughtspot.com/guides[Tutorials, window=_blank] -** link:https://developers.thoughtspot.com/codespot[CodeSpot, window=_blank] -** link:https://training.thoughtspot.com/page/developer[Training resources, window=_blank] -** link:https://docs.thoughtspot.com[Product Documentation, window=_blank] +[.sidebar-title] +Additional resources + +* link:{{navprefix}}/faqs[FAQs] +* link:https://codesandbox.io/s/big-tse-react-demo-i4g9xi[React CodeSandbox, window=_blank] +//** link:https://codesandbox.io/s/graphqlcookieembed-wf4fk9?file=/src/App.js:418-426[GraphQL CodeSandbox, window=_blank] + +* link:https://community.thoughtspot.com/customers/s/[Community, window=_blank] +* link:https://training.thoughtspot.com/page/developer[Training resources, window=_blank] +* link:https://docs.thoughtspot.com[Product Documentation, window=_blank] +* link:https://developers.thoughtspot.com[ThoughtSpot Developers, window=_blank] +* Deprecated feature docs ** link:{{navprefix}}/abac-user-parameters-beta[ABAC via tokens (pre-10.4.0.cl) (Deprecated)] diff --git a/modules/ROOT/pages/deploy-with-tml-apis.adoc b/modules/ROOT/pages/deploy-with-tml-apis.adoc index 14b0abb3a..e09eaf7d8 100644 --- a/modules/ROOT/pages/deploy-with-tml-apis.adoc +++ b/modules/ROOT/pages/deploy-with-tml-apis.adoc @@ -8,156 +8,258 @@ When deploying embedded analytics, each organization will have defined practices for development, testing, and deployment of content to ThoughtSpot. ThoughtSpot instances act as a constantly running service, so deployment only involves publishing *ThoughtSpot content*, in the form of link:https://docs.thoughtspot.com/cloud/latest/tml[ThoughtSpot Modeling Language (TML), window=_blank] files to a given ThoughtSpot instance. -ThoughtSpot has xref:version_control.adoc[Git integration] designed to automate most of the steps involved in the following process. Please see if the xref:version_control.adoc[Git integration capabilities] will work for your needs before building a process with the TML APIs directly. +The most typical pattern with ThoughtSpot involves a dev Org where content is modified by the team and then those objects are marked to form a "release" package, which then have their TML exported into a "release" branch in Git: -NOTE: Any example workflow you see within this document has been implemented and tested within the libraries available in the xref:development-and-deployment.adoc#relatedResources[Additional Resources]. We recommend that you start with these libraries and tools. +image::./images/multi_tenant_deployment.png[Multi-tenant Database Deployment SDLC Pattern] + +The TML files in the "release" branch are then moved into other "deployment branches" via pull/merge request. + +Other ThoughtSpot Orgs are "deployed to" by importing TML from their designated "deployment branch". + +The formalized release process is separate from xref:development-and-deployment.adoc#_version_control[version control], which is concerned with capturing all changes of all content in a given Org. == Overview The three steps to building an SDLC process with ThoughtSpot are: - . *xref:linkExportSource[Export source]*: Downloading ThoughtSpot objects as TML files into a source control system (for example, Git) - . *xref:linkBuildRelease[Build release]*: Altering copies of the TML files for the next stage / environment + . *xref:linkBuildRelease[Identify objects for release]*: Determine which objects in "dev Org" should become part of the "release" package + . *xref:linkExportSource[Export release TML into Git]*: Downloading ThoughtSpot objects as TML files into a source control system (for example, Git) . *xref:linkImportRelease[Import release]*: Importing the TML files into the new environment -Every object on a ThoughtSpot instance has a *GUID* as a unique reference. +== Pre-requisites +For TML files to be portable between any Org on any instance, the objects must have *obj_ids* and all Table and Connection objects must have been xref:metadata-parameterization.adoc[parameterized] with the appropriate xref:variables.adoc[variables] where necessary. -The *most essential* aspect of steps 2 and 3 is recording any newly created object GUIDs from the destination environment into a *xref:guidMapping[mapping file]* along with the GUID of the source object. +Once these pre-requisites are complete, your TML will be ready for TML Import across Orgs or publishing: -When publishing to a new environment on the same ThoughtSpot instance, you *must* swap out the GUIDs from the source environment with those of the equivalent objects in the destination environment within the TML files, so that only destination environment content is referenced. +[,YAML] +---- +obj_id: My_Connection__DATA_CHALLENGE__SALES +table: + name: SALES + db: ${dc_db} + schema: ${dc_schema} + db_table: SALES + connection: + name: My Connection + obj_id: My_Connection +---- -== Deployment scenarios +=== Parameterization with variables +In a single-tenanted database pattern, customer data is split into many separate logical databases or schemas, typically with identical table structures. -* xref:#_instance_to_instance_deployment[Instance-to-instance deployment] -* xref:#_multiple_environments_on_the_same_instance[Multiple environments on the same instance] +Queries for each customer can be identical by *xref:metadata-parameterization.adoc[parameterizing]* the attributes that vary. ThoughtSpot provides xref:variables.adoc[variables] that can be referenced in TML for this purpose. -=== Instance-to-instance deployment -The simplest deployment scenario is moving content from one ThoughtSpot instance to another separate instance. +Details about the fully-qualified table name are stored in each Table object in ThoughtSpot, rather than in the Connection object. The following can be parameterized in a Table TML file: -The TML Import process will use the `guid:` property of the imported TML files as the GUID for the new objects on the destination instance on all instances later than 9.0.0, which includes all ThoughtSpot Cloud deployments. +* database +* schema +* db_table_name -This means that a mapping file or swapping in and out GUIDs is not required. Make sure that all Connections have the same unique names on both instances and TML files should import without any modifications. +Properties of a Connection can also be parameterized. -If your instance is running a ThoughtSpot release version lower than 9.0.0.cl, refer to the xref:development-and-deployment.adoc#_notes_for_older_releases[Notes for older releases]. +Parameterization works with both TML import and xref:publishing-overview.adoc[publishing]. -=== Multiple environments on the same instance +=== obj_id +Before implementing any deployment process, you should ensure that `obj_id` is enabled on your ThoughtSpot instance. -Many ThoughtSpot customers have multiple "environments" on the same instance, either using xref:orgs.adoc[Orgs] or well-defined xref:multi-tenancy-best-practices.adoc[Access Control]. +[NOTE] +==== +Objects are only assigned automatic `obj_id` after the first change to the object once `obj_id` is enabled on an instance. +==== -In this scenario, you must track the equivalent GUIDS between source and destination environments, and swap them out within the TML files for your deployment process to work correctly. +`obj_id` for an object is available in the response from `/metadata/search` REST API as `metadata_obj_id` property: -The workflow for a very simple "dev" to "prod" flow on the same environment shown here, is the same pattern for any source-to-destination environment flow: +[,json] +---- +{ + "metadata_id":"c1e4043a-4524-4fcb-a20f-9e7aff4dc972", + "metadata_name":"Retail Sales RAD - KPIs", + "metadata_type":"LIVEBOARD", + "metadata_obj_id":"RetailSalesRAD-KPIs-c1e4043a" +} +---- +The format of `obj_id` above, with the `-{startOfGUID}` portion at the end, indicates it was an auto-generated obj_id. If the property value was `null`, then it is an object that has not been updated since the feature was enabled. -image::./images/development-deployment-process.png[Development and deployment workflow] +The `metadata/update-obj-id` REST API endpoint can change an object's `obj_id` property based on either the `metadata_id` (GUID) or the current `metadata_obj_id`: -[#guidMapping] -== GUID mapping file -As noted above, keeping a *mapping file* of GUIDs of source objects and their descendant objects in the destination environment is essential. The exact structure of the file will depend on the complexity of your deployment needs. +[,json] +---- +{ + "metadata": [ + { + "metadata_identifier": "c1e4043a-4524-4fcb-a20f-9e7aff4dc972", + "new_obj_id": "RetailSalesRAD-KPIs" + + } + ] +} +---- -The simplest pattern is to assume that releases are built exclusively from the "dev" environment, regardless of the destination environment. This pattern can be represented in the simple JSON structure: +or -[source,json] +[,json] ---- { - "test": { - "" : "" - }, - "uat": { - "" : "" - }, - "prod": { - "" : "" - } - ... + "metadata": [ + { + + "current_obj_id": "RetailSalesRAD-KPIs-c1e4043a", + "new_obj_id": "RetailSalesRAD-KPIs" + } + ] } ---- -You can use the same format for your mapping file as the xref:guid-mapping.adoc[Git deploy commits API] provided by ThoughtSpot. The most important aspect is recording the source GUID along with the GUID of the equivalent object in the destination after receiving the response from the `/metadata/tml/import` REST API call. +The request format for `metadata/update-obj-id` is an array, allowing for updating a large number of objects at once. -[#linkExportSource] -== Export source process -The process for exporting TML files into source control is: +==== Implementing obj_id in existing environments +Once you have decided on the appropriate `obj_id` for all the objects in your dev Org, you can use any existing GUID Mapping files to update the `obj_id` values for the equivalent objects in all your other Orgs. - . Use Metadata APIs (xref:metadata-api.adoc#metadata-list[/metadata/list] in v1 or link:{{navprefix}}/restV2-playground?apiResourceId=http/api-endpoints/metadata/search-metadata[/metadata/search] in v2.0) to get a filtered list of objects - . Use `/metadata/tml/export` endpoint in REST API v1 or v2.0 with `export_fqns=true` argument and `formmattype=YAML` to retrieve the TML of the object - . Save the TML response strings to disk in a Git-enabled directory using a consistent name format +You only have to do this process for existing objects *one time*, and from that point forward, you can update objects in any Org using TML with obj_ids rather than GUIDs. -You can use the link:https://thoughtspot.github.io/cs_tools/[CS Tools, window=_blank] package for a pre-built tool for programmatic exporting or build your own equivalent using the link:https://github.com/thoughtspot/thoughtspot_rest_api_v1_python[thoughtspot_rest_api_v1 Python library, window=_blank]. +[#linkBuildRelease] +== Identifying release package in dev Org +The set of objects on the *dev Org* that makes up the "deployed releases" should be identified in a way that allows easy identification of the objects to be exported into Git. -=== Best practices with TML export API -The `formattype` argument can be set to `YAML` or `JSON`. +The following mechanisms can be used to easily identify subsets of objects in an Org: -Parameterization works with both TML import and xref:publishing-overview.adoc[publishing]. +* Tags +* Content Author +* Collections (if enabled) -You can pass any number of GUIDs in the `export_ids` argument, although it is simpler to retrieve one at a time, particularly when processing the results obtained from the `export_associated=true` option. +The most typical practice is to add a *Tag*, something like *release* or *rc*, to any object that should be exported into the "release" branch. -The `export_associated` argument retrieves the TML objects for all related objects when used, including the GUID of each object within the headers. This is useful for dependency checking, and was valuable in versions lower than 8.9.0.cl to fill in `fqn` values. For more information, see xref:olderReleaseNotes[Notes for older releases]. +You can add multiple tags, if you'd like to add tags indicating versioning along with the release indicator. -[#linkBuildRelease] -== Build release process -To change the source environment TML files so that they can be imported into the destination environment, you need a process that correctly manipulates the TML files. +The `/metadata/search` REST API endpoint has parameters to filter on `tag_identifiers` and `created_by_user_identifiers`. The response from `/metadata/search` can be processed further to reduce down to the desired list of object IDs to pass to the `/metadata/tml/export` endpoint. -Common adjustments include: +[,json] +---- +{ + "metadata": [ + { + "type": "LIVEBOARD" + } + ], + "tag_identifiers": ["release"], + "sort_options": { + "field_name": order_field, + "order": "DESC" + }, + "record_size" : -1, + "record_offset": 0 +} +---- -* Switching connections at the Table level -* Changing database details within Table objects -* Adding or removing columns -* Renaming columns for translations +The `author` property of an object in the REST API is the value that the `created_by_user_identifiers` parameter in the `/metadata/search` endpoint filters on. `author` can be reassigned from the original creator via the link:https://developers.thoughtspot.com/docs/restV2-playground?apiResourceId=http%2Fapi-endpoints%2Fsecurity%2Fassign-change-author[/security/metadata/assign, window=_blank] endpoint. -For information about the specific TML changes to achieve these goals, see xref:modify-tml.adoc[Modify TML files]. There are also functioning code examples of many of these changes in the link:https://github.com/thoughtspot/thoughtspot_tml[thoughtspot_tml, window=_blank] repository. +[#linkExportSource] +== TML Export with obj_id and variables +The process for exporting TML files into source control is: -=== GUIDs in TML files determine create vs update operations + . Use Metadata Search REST API link:{{navprefix}}/restV2-playground?apiResourceId=http/api-endpoints/metadata/search-metadata[/metadata/search] to get a filtered list of objects for the release + . Use `/metadata/tml/export` endpoint with `formattype=YAML` to retrieve the TML of the object + . Save the TML response strings to disk in a Git-enabled directory using a consistent name format based on the `obj_id` -Objects of the same or different types can have the same display name in ThoughtSpot, so the GUID is necessary to identify the particular object. -In the REST APIs, `id` properties are the GUIDs. +=== Best practices with TML export API +The `/metadata/tml/export` endpoint has many options for controlling the format of the response. -In TML: +==== YAML or JSON +The `formattype` argument can be set to `YAML` or `JSON`. -* the `guid:` property will be at the top of the file -* `fqn:` properties are used to reference other connected objects (typically data sources) with a GUID +Export in YAML for saving to disk for use in Git or when using the `thoughtspot_tml` library, which is designed to handle the TML YAML format. -==== Rules for create vs. update operations -Object names are *never used* for determining an object to update, because object names are not unique within ThoughtSpot. +Export in JSON when you need details from TML within a web browser or just need to read values programmatically. -Whether an imported TML will create a new object or update an existing object depends on: +==== obj_id or guid +Once all your objects have defined `obj_id` properties, the ideal TML Export setting has the following options (you may have more or others as well): -* the presence/absence of the *guid:* property in the TML file -* whether that GUID matches an existing object on that ThoughtSpot instance -* the `force_create=true` parameter +[,json] +---- +{ + "edoc_format": "YAML", + "export_associated": false, + "export_fqn": false, + "export_options": { + "include_obj_id": true, + "include_obj_id_ref": true, + "include_guid": false + } +} +---- -Creation vs. update is determined by the following rules: +`"include_obj_id": true` specifies the `obj_id` at the top of the YAML file as the identifier for the object. - - *No GUID* in the TML file: always creates a new object with a new GUID - - *GUID in TML file*, where an object with the *same GUID already exists* in instance: update object - - *GUID in TML file*, where *no object with same GUID exists* in ThoughtSpot instance: creates a new object with the GUID from the TML file - - *Table objects* match on fully-qualified tables in the database (each Connection can only have one Table object per table in the database), not GUID: If a Table object representing the same database table is found, the GUID of the original object is maintained, but the updates are applied from the new TML file - - *force_create=true* parameter of the TML Import API is used: every uploaded TML file results in new objects being created +`"include_obj_id_ref": true` specifies that any related objects referenced in the TML file have an `obj_id` property as well. -[NOTE] -==== -In versions prior to 9.0.0.cl, ThoughtSpot did not consistently use the GUID provided in the TML file for a new object when that GUID was not already in use on that ThoughtSpot instance. -==== +The TML will end up looking like: -=== GUID mapping and swapping -Regardless of the other changes you make, building a release for an environment on the same instance will require swapping in the correct GUIDs. Because the presence of the *guid* property determines whether an individual TML file will cause a create or update action, you need to keep a *GUID mapping file* to determine how to adjust the TML files for upload to the new environment. +[,YAML] +---- +obj_id: My_Connection__DATA_CHALLENGE__SALES +table: + name: SALES + db: ${dc_db} + schema: ${dc_schema} + db_table: SALES + connection: + name: My Connection + obj_id: My_Connection +---- + +If any of the objects do not have `obj_id` set, the TML will be exported with the `guid` property at the top, or the `fqn:` property for a reference, which will be the referenced object's GUID: + +[,YAML] +---- +guid: c1e4043a-4524-4fcb-a20f-9e7aff4dc972 +table: + name: SALES + db: ${dc_db} + schema: ${dc_schema} + db_table: SALES + connection: + name: My Connection + fqn: 75b717da-94b6-42ae-ab93-110c677703fb +---- + + +==== export_associated +The `export_associated` argument retrieves the TML objects for all related objects when used, including the GUID of each object within the headers. This is useful for dependency checking, but results in longer request times and bigger responses, and possibly exporting the same object over and over. -The *guid mapping file* is referenced when creating the final TML files for publishing and then should be updated with any new object GUIDs after publishing: +=== File and directory naming pattern +`obj_id` must be unique within an Org, which makes it the obvious value to use as part of the filename of the YAML file on disk. ThoughtSpot's default file name pattern also includes the object type in the filename, resulting in a suggested pattern: - . Check the *guid mapping file* - .. If no key-value pair exists for the *dev GUID* for the new environment: *remove the guid property from the TML file*. This will cause a *create* action - .. If a key-value pair exists: *swap* the TML file *guid* value from the *dev GUID* to the *destination environment GUID*. This will cause an *update* action - . When a new object is published for the first time, record the *dev GUID* as the key, and the *new object GUID* as the value - . Perform the same process for any *fqn* properties, which specify data object references. Remove the *fqn* property if the data object is being newly created, or swap it to the mapped GUID for that environment +`{obj_id}.{object_type}.tml` -The link:https://github.com/thoughtspot/thoughtspot_tml[thoughtspot_tml library, window=_blank] provides a helper function called `disambiguate()` which implements the logic described above when provided with a Dict representing the GUID map. For information about how to use the library, see the README and examples or look at the source code if building an equivalent process yourself in another language. +You may also want to store various object types in their own directories on disk for ease of organization. + +The `obj_id` should be the first line of any TML file, and the object type should be the second, so you can easily build the filename from the `edoc` response from the TML Export REST API like: + +[,python] +---- +if 'edoc' in yaml_tml[0]: + lines = yaml_tml[0]['edoc'].splitlines() + + if lines[0].find('obj_id: ') != -1: + obj_id = lines[0].replace('obj_id: ', "") + else: + # Exception path of your choice + + obj_type = lines[1].replace(":", "") + + # Save the file with {obj_type}s/{obj_id}.{type}.{tml} + # Feel free to change directory naming structure to not have 's' at end + directory = "{}s".format(obj_type) + filename = "{}/{}.{}.tml".format(directory, obj_id, obj_type) +---- [#linkImportRelease] -== Import release process -The xref:tml-api#import[/metadata/tml/import] REST API endpoint is used to upload any number of TML files at one time. +== TML Import with obj_id and variables +The xref:tml-api.adoc#import[/metadata/tml/import] REST API endpoint is used to upload any number of TML files at one time. -All details of the objects to be created or modified are specified *within the uploaded TML file*, including the GUID which determines which existing object a given TML file will update. +All details of the objects to be created or modified are specified *within the uploaded TML file*, matching first on `obj_id` and then on `guid` if `obj_id` is not present. -The xref:development-and-deployment#linkBuildRelease[Build release process] section above describes the process for getting the TML files prepared for the import release process. The following describes the Import TML REST API call and what to do with the responses, which do feed back into the build release process in the form of the *GUID mapping file*. +If no match is found for `obj_id` or `guid`, a new object is created, with the `obj_id` specified in the TML file (`guid` will be auto-assigned). === TML import options and responses @@ -167,146 +269,52 @@ ThoughtSpot does not consider object display name for a TML file, but does use n All data objects are referenced as "tables" within TML, whether they are a ThoughtSpot Table, Model, View, SQL view, or any other data object type. The following heuristic is used to find matching objects by name within `tables` or `joins` sections: - + + . `obj_id` within other files in the same TML Import operation or existing objects in the Org . Data object names within the same TML Import operation: Must only be one single object with that name - . Searches the entire ThoughtSpot instance: Must be only one single object with that name + . Searches the entire ThoughtSpot Org: Must be only one single object with that name -The best practice is to create and upload "packages" of related objects together at once: +For this reason, we recommend importing Tables and Models from the same Connection in the same Import TML request, at least on the initial import. -* Give data objects within a package unique names, even though not enforced by ThoughtSpot -* All Table objects that use the same Connection object and all Models connected to those Tables should be uploaded together in a single TML Import -* If a data object already exists, swap out the *fqn* references to avoid the name matching heuristic +==== Rules for create vs. update operations +Object names are *never used* for determining an object to update, because object names are not unique within ThoughtSpot. -==== Storing new GUIDs in a mapping -To track relationships between objects in different environments, particularly on the same instance, you must store a *mapping* of the child object GUID to its source object GUID when you first publish the child object. +Whether an imported TML will create a new object or update an existing object depends on: -The xref:tml-api#import[import REST API endpoint] returns the GUID in the response after a successful import. The `object` key of the response to the import call contains an array, where each element has a `["response"]["header"]["id_guid"]` key providing the GUID. If you import multiple TML files at once, the response array will be in the same order as the request. This allows you to record a mapping of the originating GUID to the newly created GUIDs. +* the presence/absence of the *obj_id:* property in the TML file +* the presence/absence of the *guid:* property in the TML file +* whether that GUID matches an existing object on that ThoughtSpot instance +* the `force_create=true` parameter -[source,json] ----- -{ - "object": [ - { - "response": { - "status": { - "status_code": "OK" - }, - "header": { - "id_guid": "a09a3787-e546-42cb-888f-c17260dd1229", - "name": "Basic Answer 1", - "description": "This is basic answer with table and headline visualizations.", - "author_guid": "59481331-ee53-42be-a548-bd87be6ddd4a", - "owner_guid": "a09a3787-e546-42cb-888f-c17260dd1229", - "metadata_type": "QUESTION_ANSWER_BOOK" - } - } - } - ] -} ----- +Creation vs. update is determined by the following rules: -Update the *mapping file* with the new pair of source object GUID and destination environment object GUID, so that the release build process can do the appropriate swaps the next time the object needs to be updated. +*obj_id* is always considered first if present. ThoughtSpot looks at org_id + obj_id to find any existing object in that Org with a match, then creates a new object if one is not found +If only GUIDs are in the TML file, without obj_id, the rules are: -[#relatedResources] -== Additional Resources + - *No GUID* in the TML file: always creates a new object with a new GUID + - *GUID in TML file*, where an object with the *same GUID already exists* in instance: update object + - *GUID in TML file*, where *no object with same GUID exists* in ThoughtSpot instance: creates a new object with the GUID from the TML file + - *force_create=true* parameter of the TML Import API is used: every uploaded TML file results in new objects being created -* The link:https://github.com/thoughtspot/thoughtspot_tml[thoughtspot-tml module, window=_blank] is written in Python providing classes to work with the TML files as Python objects. You can install it via pip: +Table objects match on the real existence of the table in the particular database: -+ ----- -pip install thoughtspot_tml ----- + - *Table objects* match on fully-qualified tables in the database (each Connection can only have one Table object per table in the database), not GUID or obj_id: If a Table object representing the same database table is found, the obj_id/GUID of the original object is maintained, but the updates are applied from the new TML file -* The link:https://github.com/thoughtspot/thoughtspot_rest_api_v1_python[thoughtspot-rest-api-v1 module, window=_blank] is a Python module implementing the full ThoughtSpot V1 REST API. You can install it via pip: -+ ----- -pip install thoughtspot_rest_api_v1 ----- +[#relatedResources] +== Additional Resources -* The link:https://github.com/thoughtspot/ts_rest_api_and_tml_tools[ts_rest_api_and_tml_tools project, window=_blank] provides examples of workflows using the REST API and TML modification possible with the `thoughtspot_tml` and `thoughtspot_rest_api_v1` modules. This library is intended to provide working examples and is not maintained or supported by ThoughtSpot. +* The link:https://github.com/thoughtspot/thoughtspot_tml[thoughtspot_tml library, window=_blank] is written in Python providing classes to work with the TML files as Python objects. You can install it via pip: -* The link:https://github.com/thoughtspot/ts_rest_api_and_tml_tools/blob/main/examples/tml_and_sdlc/[examples/tml_and_sdlc/, window=_blank] directory includes many different example scripts for these TML-based workflows. + -//// -Within the examples directory, the link:https://github.com/thoughtspot/ts_rest_api_and_tml_tools/blob/main/examples/tml_and_sdlc/tml_download.py[tml_download.py, window=_blank] script is a simple example of exporting all TML objects to disk for use with Git or another source control system. -//// -* For command-line administration tools including many pre-built TML-based workflows, the link:https://github.com/thoughtspot/cs_tools[cs_tools project, window=_blank] is available. - -//// -== Notes for older releases (8.9.0.cl or earlier versions) - -[#olderReleaseNotes] -=== Add FQNs of associated objects in TML -Prior to ThoughtSpot 8.9.0.cl, TML files did not include the GUIDs of associated objects on export. However, you can use the `export_associated=true` argument to retrieve the GUIDs of the associated objects, then programmatically add the `fqn` property to the downloaded TML with the correct GUIDs. Including the GUIDs in the saved files on disk allows you to substitute the GUIDs for the equivalent objects in another environment. - -For example, in these earlier versions, the items in the `tables:` list of this example worksheet TML only include a `name:` property, representing the name of the ThoughtSpot *table* object (as opposed to the table's name in the data warehouse). - -If there are *table* objects with duplicate names, specify the GUID of the object using the `fqn:` property. This will distinguish the correct object when importing the TML back. - -When you set `export_associated=true` in the TML export command, the first item in the response will be the object you requested in the export: - -[source,yaml] ---- -guid: 0a0bb654-b0e8-482c-a6c8-9ed396d1cb92 -worksheet: - name: Markspot 2 Worksheet - tables: - - name: DIM_CUSTOMERS_2 - table_paths: - - id: DIM_CUSTOMERS_2_1 - table: DIM_CUSTOMERS_2 - join_path: - - {} -... ----- - -The overall response will be structured as a JSON array, with an `edoc` property representing the TML document itself and an `info` section providing basic metadata information, but more importantly the `name` and `id` properties. - -[source,json] ----- -{ - "object": [ - { - "edoc": "" - , - "info": { - "id": "", - "name": "", - ... - } - }, - ... - ] -} ----- - -Parse through this array and record a simple mapping of name to `guid`: - -.Python example of this process -[source,python] ----- -name_guid_map = {} - -for obj in objs: - name_guid_map[obj['info']['name']] = obj['info']['id'] +pip install thoughtspot_tml ---- -Because we know that these are the GUIDs that match the name values in this particular TML file, we can now use the map we created to add in the `fqn` properties, to result in the *worksheet* TML looking like this: +* The link:https://github.com/thoughtspot/thoughtspot_rest_api_python[thoughtspot_rest_api library, window=_blank] is a Python library implementing the full ThoughtSpot REST API. You can install it via pip: -[source,yaml] ++ ---- -guid: 0a0bb654-b0e8-482c-a6c8-9ed396d1cb92 -worksheet: - name: Markspot 2 Worksheet - tables: - - name: DIM_CUSTOMERS_2 - fqn: 3b87cea1-7767-4fd8-904f-23255d4ba7b3 - table_paths: - - id: DIM_CUSTOMERS_2_1 - table: DIM_CUSTOMERS_2 - join_path: - - {} +pip install thoughtspot_rest_api ---- -//// diff --git a/modules/ROOT/pages/deprecated-features.adoc b/modules/ROOT/pages/deprecated-features.adoc index 7ba618704..06089a22d 100644 --- a/modules/ROOT/pages/deprecated-features.adoc +++ b/modules/ROOT/pages/deprecated-features.adoc @@ -394,4 +394,4 @@ Recommended action:: For information about REST API v2.0 endpoints, refer to the following articles and visit the link:{{navprefix}}/restV2-playground?apiResourceId=http%2Fgetting-started%2Fintroduction[REST API v2 Playground]. * xref:rest-api-v2-getstarted.adoc[REST API v2.0] -* xref:rest-api-v1v2-comparison.adoc[REST API v1 and v2.0 comparison] +* xref:rest-api-v1v2-comparison.adoc[REST API v1 and v2.0 comparison] \ No newline at end of file diff --git a/modules/ROOT/pages/development-and-deployment.adoc b/modules/ROOT/pages/development-and-deployment.adoc index 98932ab93..396ed312f 100644 --- a/modules/ROOT/pages/development-and-deployment.adoc +++ b/modules/ROOT/pages/development-and-deployment.adoc @@ -12,31 +12,99 @@ ThoughtSpot instances act as a constantly running service, so xref:development-a ThoughtSpot provides numerous tools for building a structured deployment process, built around the link:https://docs.thoughtspot.com/cloud/latest/tml[ThoughtSpot Modeling Language (TML), window=_blank] format for representing the xref:intro-thoughtspot-objects.adoc[objects within ThoughtSpot]. -== Best practices -The primary tool for structured development and deployment in ThoughtSpot is called xref:orgs.adoc[Orgs]. +== Overview +ThoughtSpot may provision your organization one or more separate *instances*, each with an individual URL. -Each Org in ThoughtSpot can be xref:version_control.adoc[paired] to a link:https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-branches[branch, target=_blank] in a link:https://docs.github.com/en/repositories/creating-and-managing-repositories/about-repositories[Git repository, target=_blank] as a single *environment*. +Within a ThoughtSpot instance, the administrator of the Primary Org can create any number of logical tenants called xref:orgs.adoc[Orgs]. xref:orgs.adoc[Orgs] are fully separated tenants on a single ThoughtSpot instance. For TSE customers and others who need a structured development and deployment process, Orgs should always be enabled. -Once your environments are configured, you can xref:version_control.adoc#moving-tml-changes-between-environments[move data models and content] from the initial "dev environment" to any other environment using the xref:git-rest-api-guide.adoc[Git integration REST APIs]. +image::./images/instances_and_orgs.png[Instances and Orgs] + +By setting the `xref:intro-thoughtspot-objects.adoc#object-identifiers[obj_id]` property of objects, objects in various Orgs that are related copies of one another will have the same `obj_id`, allowing for tracking related objects and updating them without concern for each object's unique GUID. [NOTE] ==== -ThoughtSpot does not recommend TML export and import across different versions of ThoughtSpot application because the TML syntax, supported features, and object schemas can vary between releases and can sometimes lead to compatibility issues and validation errors. +ThoughtSpot does not recommend TML export and import from a *newer version* of ThoughtSpot to an instance on a *previous version*, because the TML syntax, supported features, and object schemas can vary between releases and can sometimes lead to compatibility issues and validation errors. ==== +== Version Control +*Version control* is the process of tracking changes that occur to objects in ThoughtSpot. + +A single branch in Git can be used for version control of a single Org in ThoughtSpot. + +ThoughtSpot provides a GitHub-based link:https://docs.thoughtspot.com/cloud/10.15.0.cl/git-version-control[automated version control in the UI] for Liveboards and answers or a customized process can be built using the TML Export API to any Git provider. + +It is best to use separate branches or even repositories for the UI automated version control and direct REST API processes. + +When using the TML REST APIs and a Git provider, you can also implement version control branches, but they should be separate from the "deploy branches": + +image::./images/version-control-branches.png[version control branches diagram] + +It is important to have a version control branch for any "prod" Orgs with end user created content, which otherwise will not be archived in any way. + +== Deployment +*Deployment* is the process of *making copies of objects* from one Org to another Org. + +Deployment is used in the process of building a *release* from a *dev Org* and then deploying copies of the release objects via TML to *test*, *uat*, and eventual *prod* Orgs. + +The TML Export and Import APIs allow customizable release and deployment processes to integrate with any Git provider. + +The standard deployment pattern for a xref:multi-tenancy-intro.adoc[multi-tenanted prod database] is shown below. RLS rules will filter the shared data models on the "prod" Org so that standard LBs and Answers only show the right data for each end customer, who are all only added as users to the "prod" Org. + +image::./images/multi_tenant_deployment.png[Multi-tenant Database Deployment SDLC Pattern] + +In a scenario where xref:single-tenant-data-models.adoc[end customer databases are single-tenanted], an Org can be created programmatically matching with the level of tenant separation, so that there is an Org representing each separate logical database. + +There are two techniques for managing Orgs for single-tenanted databases: + + * Publishing [beta betaBackground]^Beta^ + * Deploy to each Org using TML Import + +== Publishing + +*xref:publishing-overview.adoc[Publishing]* makes objects available in other Orgs without making copies. + +Variables can be set at the Org level to override the Connection and Table object details for Publishing objects when they are accessed in a specific Org. Variables for connections and tables work with both Publishing and TML Import. + +image::./images/publishing_diagram.png[Publishing and Variables] + +With single-tenanted prod Orgs, the *Publishing* feature allows the final deployment step to import TML into the *publisher* Org, updating the *Published* objects, which instantly updates the objects in every Org the objects are published to. + +image::./images/single_tenant_publishing.png[Publishing to Single-Tenants] + +If there are structural differences within the various databases that make Publishing unviable, the TML Import process can be used to deploy unique copies of the release TML into each Org. This process may also include modifying the release TML to introduce variation into the objects that are deployed. + +image::./images/single_tenant_deployment.png[Individual Deployment to Single-Tenants] + + + + +//// +Each Org in ThoughtSpot can be xref:version_control.adoc[paired] to a link:https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-branches[branch, target=_blank] in a link:https://docs.github.com/en/repositories/creating-and-managing-repositories/about-repositories[Git repository, target=_blank] as a single *environment*. +//// + +//// +Once your environments are configured, you can xref:version_control.adoc#moving-tml-changes-between-environments[move data models and content] from the initial "dev environment" to any other environment using the xref:git-rest-api-guide.adoc[Git integration REST APIs]. +//// + + + //// If you have used ThoughtSpot for a long time and are enabling Orgs for the first time, please see xref:moving-to-orgs.adoc[moving to Orgs from single-tenant ThoughtSpot instance]. //// -== Standard structure of Orgs +//// +== Typical Orgs pattern for SDLC When Orgs are enabled, the *Primary Org* (`org_id: 0`) should be treated as the "root" or "super-admin" Org, and all "real content" should exist on Orgs other than the Primary. +Additionally, the *Primary Org* is the only Org where *Published* objects can originate, so *Primary* serves as the *Publisher* Org within SDLC flows that involve Publishing. + The most basic standard configuration for separated development and deployment, with a xref:multi-tenancy-best-practices.adoc[multi-tenanted "prod" environment], has the following environments: - *Primary*: only used for administration of instance and Orgs themselves -- *Dev*: ThoughtSpot customer internal development team builds data models and standard Liveboards and Answers -- *Prod*: Data models and standard content are published to this environment by service account. All end customers get READ-ONLY access to data models, standard Liveboards, and Answers. +- *dev*: ThoughtSpot customer internal development team builds data models and standard Liveboards and Answers +- *test*: +- *prod*: Data models and standard content are published to this environment by service account. All end customers get READ-ONLY access to data models, standard Liveboards, and Answers. image::./images/multi-tenanted_prod_deployment.png[Multi-tenanted prod deployment model] @@ -47,20 +115,25 @@ RLS filters the shared data models on the "prod" Org so that standard LBs and An If the production end customer data models are xref:single-tenant-data-models.adoc[single-tenanted (logical separation for each end customer)], such that a different connection is necessary), then the standard deployment involves a "release"/"pre-prod" Org and then one prod Org per end customer. image::./images/single-tenant_prod_per_customer.png[Single-tenant final deployment model] - +//// +//// === Additional "typical" Orgs - *Test*, *UAT*: Additional steps in the publishing process between Dev and Prod, for verification before changes are deployed into Prod - *Internal Org(s)*: Org(s) for ThoughtSpot customer's own business work, never to be shared with end customers - Separate *'dev' instance*: Some people want a fully separated environment for dev, especially if doing MAJOR changes, even to cluster config. Recommend there be a 'Test Org' on the 'Prod Instance' to push to first, before pushing to 'Prod' - Separate *regional instances*: prod per customer Orgs may extend to multiple ThoughtSpot instances in different regional cloud data centers +//// +//// [#deploy-between-environments] == Deploying content between environments -//// + The workflow for a very simple "dev" to "prod" flow on the same environment shown here, is the same pattern for any source-to-destination environment flow: image::./images/development-deployment-process.png[Development and deployment workflow] +//// + //// === Git deployment The xref:version_control.adoc[Git REST APIs] are designed for the best practice pattern of building on a Dev Org and then deploying to any number of Orgs through Prod(s). @@ -74,9 +147,12 @@ You will need a xref:guid-mapping.adoc[GUID Mapping file] that records the `orig == Multi-tenancy and data security The exact deployment pattern chosen will depend on the design of your data warehouse. Please see the xref:multi-tenancy-intro.adoc[full documentation on multi-tenancy within ThoughtSpot] to determine which deployment pattern best fits your needs. +//// +//// == Publishing content to Orgs within a ThoughtSpot instance Starting with the 10.10.0.cl release, ThoughtSpot provides the ability to parameterize object properties using variables for each Org and publish objects directly from the Primary Org to other Orgs on a multi-tenant instance. The publishing feature [beta betaBackground]^Beta^ enables administrators to create a single main object in the Primary Org and distribute it to other Orgs within the instance. -For more information, see xref:publishing-overview.adoc[Publishing content to Orgs]. \ No newline at end of file +For more information, see xref:publishing-overview.adoc[Publishing content to Orgs]. +//// diff --git a/modules/ROOT/pages/embed-authentication.adoc b/modules/ROOT/pages/embed-authentication.adoc index ec2fdd8dc..990b76ab3 100644 --- a/modules/ROOT/pages/embed-authentication.adoc +++ b/modules/ROOT/pages/embed-authentication.adoc @@ -71,6 +71,11 @@ a| Do not use this method if you don’t want the SDK to redirect your entire ap * This authentication will fail if multifactor authentication (MFA) is enabled on your ThoughtSpot instance. Contact https://community.thoughtspot.com/customers/s/login/?ec=302&startURL=%2Fcustomers%2Fs%2Fcontactsupport[ThoughtSpot Support] for assistance. |===== +[NOTE] +==== +xref:orgs.adoc#per-org-subdomain[Per Org Subdomain] can be enabled to allow Orgs with different IdPs to be identified properly within the authentication flows triggered by the Visual Embed SDK. +==== + == User accounts Many ThoughtSpot features are tied to individual user accounts with a valid email address. xref:just-in-time-provisioning.adoc[Just-In-Time Provisioning] and user management REST APIs make it easy to create and update user accounts as part of the SSO process. @@ -218,7 +223,7 @@ The `init` method returns an event emitter, which you can use to listen to `Auth [source,TypeScript] ---- -authStatus = init(embedConfig); authStatus.on(AuthStatus.FAILURE, (reason) => { +const authStatus = init(embedConfig); authStatus.on(AuthStatus.FAILURE, (reason) => { console.log('Authentication failed'); }); ---- @@ -267,7 +272,7 @@ import { logout } from "@thoughtspot/visual-embed-sdk"; logout(); ---- -The `logout` function returns a promise that resolves when the user is logged out of ThoughtSpot. When you call `logout`, the `autoLogin` attribute is set to `false` to prevent the SDK from automatically logging in the user again. If you do not want to disable `autoLogin`, set the `doNotDisableAutoLogin` parameter to `false`. +The `logout` function returns a promise that resolves when the user is logged out of ThoughtSpot. When you call `logout`, the `autoLogin` attribute is set to `false` to prevent the SDK from automatically logging in the user again. If you do not want to disable `autoLogin`, set the `doNotDisableAutoLogin` parameter to `true`. You can also call `init` again with the `autoLogin` property set to `true` to re-login a user. diff --git a/modules/ROOT/pages/filters_overview.adoc b/modules/ROOT/pages/filters_overview.adoc index 058ebda9e..4eefefdfe 100644 --- a/modules/ROOT/pages/filters_overview.adoc +++ b/modules/ROOT/pages/filters_overview.adoc @@ -145,7 +145,7 @@ There are different types of filters, which can be applied in the following orde 1. xref:rls-rules.adoc[Row-level security (RLS) Rules]+ Tied to the logged-in user and their group memberships. Completely secure and cannot be altered by the logged-in user. 2. xref:abac-user-parameters.adoc[Attribute-Based Access Control (ABAC) filter rules] + -Filters and Parameter rules applied on a Modeland assigned to a token. +Filters and Parameter rules applied on a Model and assigned to a token. 3. xref:runtime-filters.adoc[Runtime filters] and xref:runtime-parameters.adoc[Runtime Parameters] + Set via the Visual Embed SDK or URL query parameters. Runtime filters do not display as UI filter components. 4. link:https://docs.thoughtspot.com/cloud/latest/liveboard-filters[Liveboard filters, window=_blank] + @@ -431,621 +431,6 @@ liveboardEmbed.trigger(HostEvent.UpdateFilters, { ---- |===== -[#_override_filters] -=== Overriding filters in REST API workflows - -The `override_filters` parameter on the Liveboard report API -(`POST /api/rest/2.0/report/liveboard`) lets you programmatically apply or replace -filters when exporting a Liveboard report. Filters specified here override any existing -filters on the same columns in the Liveboard. - -[IMPORTANT] -==== -This section describes the `override_filters` field used in the *REST API* request body. -If you are building an embedded application and want to update filters using the -Visual Embed SDK, see -xref:filters-overview.adoc#_updating_date_filters[Embed SDK: Updating date filters] -instead. - -The two interfaces share the same filter concepts but are *structurally different*: -the Embed SDK uses a `values[]` array to carry date values and camelCase field names, -while the REST API uses explicit named fields (`epoch`, `number`, `date_range`) in -UPPER_SNAKE_CASE type names. Do not mix examples from the two pages. -==== - -=== Request format - -The `override_filters` value is a JSON array of filter objects. Each object targets -one column. - -[source,json] ----- -"override_filters": [ - { ... }, // filter for column A - { ... } // filter for column B -] ----- - -[NOTE] -==== -`override_filters` accepts a JSON *array* directly, not an object that wraps the array. -==== - -=== Filter object structure - -Each element in the array has the following top-level fields: - -[cols="2,1,1,4", options="header"] -|=== -|Field -|Type -|Required -|Description - -|`column_name` -|string -|Yes -|Display name of the column to filter. Case-insensitive. -See <>. - -|`date_filter` -|object -|Conditional -|Date filter definition. Use for columns with a date or date-time data type. -Mutually exclusive with `generic_filter` on the same object. -See <>. - -|`generic_filter` -|object -|Conditional -|Attribute or measure filter definition. Use for non-date columns. - -|`negate` -|boolean -|No -|When `true`, inverts the filter. For `date_filter`, see the negation notes in -<>. -|=== - -[IMPORTANT] -==== -You may specify *at most one* filter object per date-type column. Providing two or more -filter objects that target the same date column returns an error: - - more than one filter objects are not allowed for date type column - -Non-date columns do not have this restriction. -==== - -[#rest-date-filter-object] -=== date_filter object - -The `date_filter` object specifies a structured date filter. Its fields map directly -to the internal `DateFilterProto` representation. - -[cols="2,1,1,4", options="header"] -|=== -|Field -|Type -|Required -|Description - -|`type` -|string -|Yes -|The date filter category. Must be one of the values in <>. - -|`datePeriod` -|string -|Conditional -|The time granularity for rolling filters. Required when `type` is `LAST_N_PERIOD`, -`NEXT_N_PERIOD`, `THIS_PERIOD`, `LAST_PERIOD`, `NEXT_PERIOD`, or `PERIOD_TO_DATE`. -See <>. - -|`op` -|string -|Yes -|The comparison operator. Valid values depend on `type`. -See <>. - -|`number` -|integer -|Conditional -|The period count. Required when `type` is `LAST_N_PERIOD` or `NEXT_N_PERIOD`. -Must be ≥ 0. - -|`epoch` -|integer (int64) -|Conditional -|A specific point in time as a Unix epoch in *seconds*, in *server timezone*. -Required when `type` is `EXACT_DATE` and `op` is an inequality (`LT`, `LE`, `GT`, -`GE`, `NE`). For `op: EQ` with `EXACT_DATE`, `epoch` is also required. - -|`date_range` -|object -|Conditional -|Required when `type` is `EXACT_DATE_RANGE`. Contains `low_epoch` and `high_epoch`, -both int64 Unix epochs in *seconds*, in *server timezone*. -`low_epoch` must be strictly less than `high_epoch`. - -|`year_name` -|string -|Conditional -|The four-digit year as a string (e.g., `"2024"`). Required for `YEAR_ONLY`, -`QUARTER_YEAR`, and `MONTH_YEAR`. Year value must be ≥ 1000. - -|`quarter_name` -|string -|Conditional -|The quarter identifier. Required for `QUARTER_YEAR`. -Valid values: `Q1`, `Q2`, `Q3`, `Q4`. - -|`month_name` -|string -|Conditional -|The month name in uppercase. Required for `MONTH_YEAR`. -Valid values: `JANUARY`, `FEBRUARY`, `MARCH`, `APRIL`, `MAY`, `JUNE`, -`JULY`, `AUGUST`, `SEPTEMBER`, `OCTOBER`, `NOVEMBER`, `DECEMBER`. - -|`include_current_period` -|boolean -|No -|For `LAST_N_PERIOD` and `NEXT_N_PERIOD` only. When `true`, includes the current -in-progress period in the filter range. Requires the *Include Current Period* -feature to be enabled on the cluster. Silently ignored if the feature is off. -|=== - -[WARNING] -==== -Epoch values must be in *server timezone* and expressed in *seconds*, not -milliseconds. Passing millisecond values (for example, `1710460800000` instead of -`1710460800`) produces an incorrect date range with no error. -==== - -[#rest-date-filter-types] -=== Supported type values - -[cols="2,4,3", options="header"] -|=== -|`type` value -|Description -|Required companion fields - -|`YESTERDAY` -|The full previous calendar day. -|`op: EQ` only - -|`TODAY` -|The current calendar day. -|`op: EQ` - -|`TOMORROW` -|The next calendar day. + -⚠️ May be suppressed on clusters with future date filters disabled. -|`op: EQ` - -|`LAST_PERIOD` -|The last single period (for example, last week). -|`datePeriod`, `op ∈ {EQ, LE, LT, GE, GT}` - -|`NEXT_PERIOD` -|The next single period (for example, next month). -|`datePeriod`, `op ∈ {EQ, LE, LT, GE, GT}` - -|`THIS_PERIOD` -|The current period (for example, this quarter). -|`datePeriod`, `op ∈ {EQ, LE, LT, GE, GT}` - -|`LAST_N_PERIOD` -|The last _N_ complete periods. -|`datePeriod`, `number ≥ 0`, `op ∈ {EQ, LE, LT, GE, GT}` + -Optional: `include_current_period` - -|`NEXT_N_PERIOD` -|The next _N_ complete periods. -|`datePeriod`, `number ≥ 0`, `op ∈ {EQ, LE, LT, GE, GT}` + -Optional: `include_current_period` - -|`PERIOD_TO_DATE` -|From the start of the current period to now. -|`datePeriod`, `op: EQ` only - -|`EXACT_DATE` -|A specific calendar date, or an inequality relative to a date. -|`epoch` (required for inequality ops), `op ∈ {EQ, NE, LT, LE, GT, GE}` - -|`EXACT_DATE_RANGE` -|A date range between two bounds (inclusive). -|`date_range.low_epoch`, `date_range.high_epoch`, `op: BW_INC` only - -|`QUARTER_YEAR` -|A specific quarter in a specific year. -|`quarter_name`, `year_name`, `op: EQ` only - -|`MONTH_YEAR` -|A specific month in a specific year. -|`month_name`, `year_name`, `op: EQ` only - -|`YEAR_ONLY` -|An entire calendar year. -|`year_name`, `op: EQ` only -|=== - -==== Unsupported type values - -The following `type` values exist in the underlying `DateFilterType` proto enum but are -*not supported* by the `override_filters` API. Passing any of these values returns an -`Unsupported date filter type` error: - -* `EXACT_TIME` -* `EXACT_DATE_TIME` -* `NOW` -* `MONTH_ONLY` -* `WEEKDAY_ONLY` -* `QUARTER_ONLY` -* `N_PERIOD_AGO` -* `PERIOD_ONLY` - -[#rest-date-period-values] -=== datePeriod values - -[cols="1,3", options="header"] -|=== -|`datePeriod` value |Description -|`DAY` |Calendar day -|`WEEK` |Calendar week -|`MONTH` |Calendar month -|`QUARTER` |Calendar quarter -|`YEAR` |Calendar year -|`HOUR` |Hour (for datetime columns only) -|`MINUTE` |Minute (for datetime columns only) -|`SECOND` |Second (for datetime columns only) -|=== - -[NOTE] -==== -`HOUR`, `MINUTE`, and `SECOND` are valid only for columns that contain a time -component. On clusters where `hideTimeBasedFilters` is active, sub-day periods -are silently suppressed in the UI, but the REST API does not enforce this at the -request level. -==== - -[#rest-valid-operators-per-type] -=== Valid operators per filter type - -The `op` field accepts string values from the `CompareTypeProto` enum. Valid -values depend on the `type`. Providing an invalid combination returns an -`Invalid date filter proto` error. - -[cols="3,4", options="header"] -|=== -|`type` value(s) -|Valid `op` values - -|`YESTERDAY`, `TODAY`, `TOMORROW` -|`EQ` only - -|`LAST_PERIOD`, `NEXT_PERIOD`, `THIS_PERIOD`, + -`LAST_N_PERIOD`, `NEXT_N_PERIOD` -|`EQ`, `LE`, `LT`, `GE`, `GT` - -|`PERIOD_TO_DATE`, `QUARTER_YEAR`, + -`MONTH_YEAR`, `YEAR_ONLY` -|`EQ` only - -|`EXACT_DATE` -|`EQ`, `NE`, `LT`, `LE`, `GT`, `GE` - -|`EXACT_DATE_RANGE` -|`BW_INC` only -|=== - -[#rest-date-filter-negate] -=== Negating a date filter - -The top-level `negate` field in the filter object inverts the match when set to `true`. - -[IMPORTANT] -==== -`negate` in the REST API is set at the *filter object* level (a sibling of -`date_filter`), not inside the `date_filter` object. -==== - -[NOTE] -==== -Old-style epoch-based date filters do not support `negate: true`. Attempting to negate -a legacy date filter returns: - - Negate not supported with old date filters -==== - -=== Examples - -==== Yesterday - -[source,json] ----- -{ - "column_name": "Order Date", - "date_filter": { - "type": "YESTERDAY", - "op": "EQ" - } -} ----- - -==== Last 3 months (rolling) - -[source,json] ----- -{ - "column_name": "Order Date", - "date_filter": { - "type": "LAST_N_PERIOD", - "datePeriod": "MONTH", - "number": 3, - "op": "EQ" - } -} ----- - -==== Last 3 months including the current partial month - -[source,json] ----- -{ - "column_name": "Order Date", - "date_filter": { - "type": "LAST_N_PERIOD", - "datePeriod": "MONTH", - "number": 3, - "op": "EQ", - "include_current_period": true - } -} ----- - -NOTE: `include_current_period` requires the *Include Current Period* feature to be -enabled on the cluster. It is silently ignored if the feature flag is off. - -==== This quarter - -[source,json] ----- -{ - "column_name": "Order Date", - "date_filter": { - "type": "THIS_PERIOD", - "datePeriod": "QUARTER", - "op": "EQ" - } -} ----- - -==== Month to date - -[source,json] ----- -{ - "column_name": "Order Date", - "date_filter": { - "type": "PERIOD_TO_DATE", - "datePeriod": "MONTH", - "op": "EQ" - } -} ----- - -==== Exact date — on March 15, 2024 - -[source,json] ----- -{ - "column_name": "Order Date", - "date_filter": { - "type": "EXACT_DATE", - "op": "EQ", - "epoch": 1710460800 - } -} ----- - -==== Exact date — after March 15, 2024 - -[source,json] ----- -{ - "column_name": "Order Date", - "date_filter": { - "type": "EXACT_DATE", - "op": "GT", - "epoch": 1710460800 - } -} ----- - -==== Exact date range — January 1 to December 31, 2024 (inclusive) - -[source,json] ----- -{ - "column_name": "Order Date", - "date_filter": { - "type": "EXACT_DATE_RANGE", - "op": "BW_INC", - "date_range": { - "low_epoch": 1704067200, - "high_epoch": 1735689599 - } - } -} ----- - -==== Specific month and year — March 2024 - -[source,json] ----- -{ - "column_name": "Order Date", - "date_filter": { - "type": "MONTH_YEAR", - "op": "EQ", - "month_name": "MARCH", - "year_name": "2024" - } -} ----- - -==== Specific quarter and year — Q1 2024 - -[source,json] ----- -{ - "column_name": "Order Date", - "date_filter": { - "type": "QUARTER_YEAR", - "op": "EQ", - "quarter_name": "Q1", - "year_name": "2024" - } -} ----- - -==== Specific year — 2024 - -[source,json] ----- -{ - "column_name": "Order Date", - "date_filter": { - "type": "YEAR_ONLY", - "op": "EQ", - "year_name": "2024" - } -} ----- - - - -==== Combining date and attribute filters in one request - -[source,json] ----- -"override_filters": [ - { - "column_name": "Order Date", - "date_filter": { - "type": "LAST_N_PERIOD", - "datePeriod": "MONTH", - "number": 3, - "op": "EQ" - } - }, - { - "column_name": "Region", - "generic_filter": { - "op": "IN", - "values": [{ "value": "West" }, { "value": "East" }] - } - } -] ----- - -[#rest-column-name-resolution] -=== Resolving column names - -The `column_name` field accepts the display name of the column as it appears in the -Liveboard's underlying data source. Matching is case-insensitive. - -When the same column name appears in more than one worksheet referenced by the -Liveboard, qualify the name using the `::` separator: - ----- -"worksheet_name::column_name" ----- - -For example: - -[source,json] ----- -{ - "column_name": "Sales Metrics::Order Date", - "date_filter": { ... } -} ----- - -If a column name matches more than one column and is not qualified, the API returns: - - Unable to determine logical column from name due to more than one matches - -[IMPORTANT] -==== -The REST API qualifier order is *`worksheet_name::column_name`* — worksheet first, -column second. This is the *opposite order* from the Visual Embed SDK's -`UpdateFilters` qualifier format, which is `column_name::datasource_name`. -See xref:filters-overview.adoc#column-name-resolution[Embed SDK: Resolving column names]. -==== - -=== Comparison with Embed SDK date filter fields - -If you are familiar with the Visual Embed SDK `UpdateFilters` date filter syntax, -the following table maps each SDK field to its REST API equivalent. - -[cols="2,2,3", options="header"] -|=== -|Embed SDK field -|REST API `date_filter` field -|Notes - -|`type` (camelCase, e.g. `LastNPeriod`) -|`type` (UPPER_SNAKE_CASE, e.g. `LAST_N_PERIOD`) -|Different naming convention. - -|`datePeriod` (e.g. `Month`) -|`datePeriod` (e.g. `MONTH`) -|Same concept, UPPER_SNAKE_CASE in REST API. - -|`operator` (e.g. `EQ`) -|`op` (e.g. `EQ`) -|Different field name. Same value strings. - -|`values[0]` (for `LastNPeriod`) -|`number` -|SDK carries N in the `values` array; REST API uses an explicit `number` field. - -|`values[0]` (for `ExactDate`) -|`epoch` -|SDK carries epoch in `values`; REST API uses an explicit `epoch` field. - -|`values[0]`, `values[1]` (for `ExactDateRange`) -|`date_range.low_epoch`, `date_range.high_epoch` -|SDK packs both bounds into `values`; REST API uses an explicit nested object. - -|`values[0]` (for `MonthYear`) -|`month_name` -|SDK: `values: ['MARCH', '2024']`. REST API: `month_name: "MARCH"`, `year_name: "2024"`. - -|`values[0]` (for `QuarterYear`) -|`quarter_name` -|SDK: `values: ['Q1', '2024']`. REST API: `quarter_name: "Q1"`, `year_name: "2024"`. - -|`values[0]` (for `YearOnly`) -|`year_name` -|SDK: `values: ['2024']`. REST API: `year_name: "2024"`. - -|`negate` -|`negate` (top-level sibling, not inside `date_filter`) -|Same semantics, different placement. - -|`includeCurrentPeriod` -|`include_current_period` -|camelCase vs snake_case. Same semantics. - -|`columnName` -|`column_name` -|Qualifier order is reversed: SDK uses `column::datasource`; REST API uses `worksheet::column`. -|=== - == Updating runtime filters For information about runtime filters update, see xref:runtime-filters.adoc#_adjust_runtime_filters_using_sdk_events[Runtime filters documentation]. diff --git a/modules/ROOT/pages/git-configuration.adoc b/modules/ROOT/pages/git-configuration.adoc index 0840dd56e..dbbf1bf12 100644 --- a/modules/ROOT/pages/git-configuration.adoc +++ b/modules/ROOT/pages/git-configuration.adoc @@ -1,12 +1,17 @@ -= Configure Git integration += Configure GitHub integration :toc: true :toclevels: 2 -:page-title: Configure Git integration +:page-title: Configure GitHub integration :page-pageid: git-configuration -:page-description: Configuring the Git integration for a ThoughtSpot instance +:page-description: Configuring the GitHub integration for a ThoughtSpot instance -Git integration requires configuration within both ThoughtSpot, accomplished via the V2.0 REST APIs, and your Git provider (GitHub currently). +[NOTE] +==== +The legacy GitHub REST APIs referenced here are tied to GitHub exclusively. The newer xref:git-provider-integration.adoc[Git provider integration pattern] provides more flexibility and control and should be utilized if you are starting out or having issues with the GitHub APIs. +==== + +GitHub integration requires configuration within both ThoughtSpot, accomplished via the V2.0 REST APIs, and your Git provider (GitHub currently). == Configure Git repository @@ -44,7 +49,7 @@ tscli git-integration enable //// == Confirm permissions within ThoughtSpot Orgs -* To commit objects from Thoughtspot to a Git repository, your ThoughtSpot user account requires at least view permission for all objects that will be committed as part of the operation. +* To commit objects from ThoughtSpot to a Git repository, your ThoughtSpot user account requires at least view permission for all objects that will be committed as part of the operation. * To deploy or revert objects from a Git repository to ThoughtSpot, you require edit access to all objects that will be updated as part of the deployment. If the deployment contains Models, Views, or Tables, users require **Can manage data** (`DATAMANAGEMENT`) privilege for deploy, commit, and revert operations. [#guid-map-and-config-files] @@ -80,17 +85,16 @@ For more advanced Git development patterns, list multiple `branch_names` in the |=== |Parameter|Description |`repository_url`|__String__. The HTTPS URL of the Git repository; for example, `\https://github.com/user/repo.git`. -|`username` -|__String__. Username to authenticate to the Git repository. +|`username`|__String__. Username to authenticate to the Git repository. |`access_token`|__String__. Access token to authenticate to the Git repository. |`org_identifier`|__String__. ID of the Org. Define this parameter only if the Orgs feature is enabled on your ThoughtSpot cluster and separate Orgs are configured for development and production environments. |`branch_names`|__Array of strings__. List of Git branches to configure. -|`commit_branch_name` |__String__. Name of the remote branch where objects committed from this Thoughtspot instance will be versioned. Replaces `default_branch_name`, which is deprecated in 9.10.5.cl. +|`commit_branch_name` |__String__. Name of the remote branch where objects committed from this ThoughtSpot instance will be versioned. Replaces `default_branch_name`, which is deprecated in 9.10.5.cl. |`default_branch_name` + __Optional__|__String__. Deprecated in 9.10.5.cl. In earlier versions, this parameter was used to configure the name of the default Git branch to use for all operations on the cluster. |`enable_guid_mapping` |__Boolean__. Enables GUID mapping and generates a GUID mapping file. Starting from 9.7.0.cl, this attribute is set to `true` by default. To know more about GUID mapping, see xref:version_control.adoc#_guid_mapping_and_configuration_files[GUID mapping]. -|`configuration_branch_name` a|__String__. Name of the branch where the configuration files related to operations between Thoughtspot and the version control repository should be maintained. Replaces `guid_mapping_branch_name`, which is deprecated in 9.10.5.cl. +|`configuration_branch_name` a|__String__. Name of the branch where the configuration files related to operations between ThoughtSpot and the version control repository should be maintained. Replaces `guid_mapping_branch_name`, which is deprecated in 9.10.5.cl. [NOTE] ==== @@ -109,14 +113,14 @@ The following example shows the API request format for connecting ThoughtSpot to ---- curl -X POST \ --url 'https://{ThoughtSpot-Host-Dev}/api/rest/2.0/vcs/git/config/create' \ - -H 'Authorization: Bearer {Bearer_token} \ + -H 'Authorization: Bearer {Bearer_token}' \ -H 'Accept: application/json'\ -H 'Content-Type: application/json' \ --data-raw '{ "repository_url": "https://github.com/user/repo.git", "username": "ts-git-user", "access_token": "{ACCESS_TOKEN}", - "org_identifier": "dev" + "org_identifier": "dev", "branch_names": [ "dev", "main" @@ -128,7 +132,7 @@ curl -X POST \ If the API request is successful, the ThoughtSpot instance will be connected to the Git repository. -Go into each Org an issue the `config/create` call to link the appropriate branch to establish all environments. +Go into each Org and issue the `config/create` call to link the appropriate branch to establish all environments. The following example shows the API request parameters to connect a ThoughtSpot `Prod` Org to the Git repo. Note that GUID mapping is enabled in the API request. @@ -138,7 +142,7 @@ The `Bearer_token` value must be requested for the desired Org, specified throug ---- curl -X POST \ --url 'https://{ThoughtSpot-Host-Prod}/api/rest/2.0/vcs/git/config/create' \ - -H 'Authorization: Bearer {Bearer_token} \ + -H 'Authorization: Bearer {Bearer_token}' \ -H 'Accept: application/json'\ -H 'Content-Type: application/json' \ --data-raw '{ @@ -146,7 +150,7 @@ curl -X POST \ "username": "ts-git-user", "access_token": "{ACCESS_TOKEN}", "enable_guid_mapping": true, - "org_identifier": "prod" + "org_identifier": "prod", "branch_names": [ "prod" ], @@ -162,9 +166,9 @@ Version control and xref:guid-mapping.adoc[GUID mapping] utilize files stored in You can initialize these files by immediately using the xref:git-rest-api-guide.adoc#deploy-commits[deploy commits REST API] after configuring the Org for Git. -See the link:https://github.com/thoughtspot/thoughtspot_rest_api_v1_python/blob/main/examples_v2/create_orgs_with_linked_git_branch.py[create_orgs_with_linked_git_branch.py script] for an example of deploying a full Orgs or branches setup for structured development and deployment. +See the link:https://github.com/thoughtspot/thoughtspot_rest_api_v1_python/blob/main/examples_v2/create_orgs_with_linked_git_branch.py[create_orgs_with_linked_git_branch.py script, window=_blank] for an example of deploying a full Orgs or branches setup for structured development and deployment. -After the Orgs are set up, you can link:https://github.com/thoughtspot/thoughtspot_rest_api_v1_python/blob/main/examples_v2/create_connection_on_orgs.py[create connections across the orgs] and xref:guid-mapping.adoc#using-mapping-for-table-tml-properties[add any necessary entries to the GUID mapping files]. +After the Orgs are set up, you can link:https://github.com/thoughtspot/thoughtspot_rest_api_v1_python/blob/main/examples_v2/create_connection_on_orgs.py[create connections across Orgs, window=_blank] and xref:guid-mapping.adoc#using-mapping-for-table-tml-properties[add any necessary entries to the GUID mapping files]. [#update-git-config] diff --git a/modules/ROOT/pages/git-provider-integration.adoc b/modules/ROOT/pages/git-provider-integration.adoc new file mode 100644 index 000000000..9892e37d1 --- /dev/null +++ b/modules/ROOT/pages/git-provider-integration.adoc @@ -0,0 +1,197 @@ += Git provider integration +:toc: true +:toclevels: 2 + +:page-title: Git provider integration using TML APIs +:page-pageid: git-provider-integration +:page-description: Overview of using a Git provider to manage SDLC in ThoughtSpot + +Git providers such as GitHub, GitLab, Azure DevOps and BitBucket can run scripts that use the ThoughtSpot REST API and TML modification capabilities. + +This allows the Git provider to become the centralized control service for deployment processes to ThoughtSpot. + +The combination of Git commands and ThoughtSpot REST API calls allows for controlled synchronization of the Git repo and the various ThoughtSpot Orgs that represent environments within the software deployment lifecycle. + +[NOTE] +==== +The legacy GitHub REST APIs are used through ThoughtSpot and are tied to GitHub exclusively. The Git provider integration pattern provides more flexibility and control. +==== + +== Overview +The Git provider integration pattern is based on storing the necessary secrets in the Git provider to allow ThoughtSpot REST API commands to be run by the Git provider when accomplishing tasks on demand or on a schedule. + +All imports and exports of ThoughtSpot TML files to and from branches, along with the commits and merges are controlled entirely in git using the Git provider's capabilities. + +The two fundamental workflows are *xref:deploy-with-tml-apis.adoc#tml-export-with-obj_id-and-variables[TML Export] to branch from Org* and *xref:deploy-with-tml-apis.adoc#tml-import-with-obj_id-and-variables[TML Import] from branch to Org*: + +=== TML Export to branch from Org + + . `git checkout {branch-name}`: switch to existing remote branch or create local branch + . `git pull`: bring down latest from remote of branch + . Script to find desired objects then Export TML, saving TML files to disk with regular save command using name pattern `{obj_id}.{type}.tml` + . `git diff-index --quiet HEAD || git commit -a -m "{commit msg}"` + . `git push`: Send changes to remote + +[NOTE] +==== +If there are no changes to any files, `git commit` will throw an error. `git diff-index --quiet HEAD || git commit -a -m "{commit msg}"` avoids this issue. +==== + +The script that actually downloads the TML should also have capabilities for xref:deploy-with-tml-apis.adoc#linkBuildRelease[filtering items to just the release package]. The same download script can handle pure version control (downloading all items) as well as downloading only the items of the release package. + +==== Efficient exporting using modified timestamp +TML Export causes activity on a ThoughtSpot instance, as TML is generated dynamically at the time of request from the current state of the objects in ThoughtSpot. + +To make the process more quick and efficient, you can implement a method for only exporting objects that have changed since the last TML Export was run, using the `/metadata/search` REST API response, which contains a `modified` timestamp in the `metadata_header` section. + + +=== TML Import from branch to Org + + . `git checkout {branch-name/tag}`: switch to existing remote branch or tag + . `git pull`: bring down latest from remote of branch + . Script to find all desired TML files in the directory, then use TML Import REST API to import into the target Org + . Script to share newly created objects to Groups in the destination Org + + +== Setup +Each Git provider has its own mechanisms for doing the following, but the overall pattern described should be possible in any of them. + +Essentially, the Git provider will store the necessary details and secrets to make REST API calls to the ThoughtSpot instance(s). + +=== Secrets and variables +The following should be stored within the Git provider for use within any automated workflows: + +* TS_SERVER +* TS_SECRET_KEY +* TS_INSTANCE_ADMIN_USERNAME +* TS_DOWNLOAD_USERNAME +* TS_IMPORT_USERNAME + +Some of these, such a `TS_DOWNLOAD_USERNAME` and `TS_IMPORT_USERNAME` may vary at a branch / environment level. Even `TS_SERVER` and `TS_SECRET_KEY` may have variations per branch if you are using multiple ThoughtSpot instances. + +=== Branches +Due to the nature of ThoughtSpot TML, you'll want to separate deployment branches for the release package from any "pure version control" branches. + +image::./images/version-control-branches.png[version control branches diagram] + +Pull requests / merges should be possible smoothly from "release" -> "test_deploy" -> "uat_deploy" -> "prod_deploy", without needing to resolve any merge conflicts. + +The following is an example branch scheme, you are welcome to adjust the names to match your preferences: + +* main / master: Actions / workflows / other shared assets, but no TML files from any Org +* dev_vc: Version Control for all content on Dev Org +* release: Branch for Specific Content to go through deployment to other Orgs +* test_deploy: Import TML from 'release' and do other Actions to Test Org +* test_vc: Version control for all content on Test Org +* Optional UAT / etc.: +** uat_deploy: Import TML from 'release' and do other Actions to UAT Org +** uat_vc: Version control for all content on UAT Org +* prod_deploy Import TML from 'release' and do other Actions to Prod Org(s) + +Version control for prod Orgs: + +* prod_vc: if single Prod, version control of all Content +* customer_orgs(s): version control branch for each Single Tenant Org + +== Local branches, copies and edits +ThoughtSpot itself is the "living source of truth", with TML only a representation of the current state of the object in the system at the time of TML Export or the desired state to bring the system to via TML Import. + +A TML Import will cause the existing object in ThoughtSpot with the same identifier (`obj_id` or `guid` if no `obj_id` is present) to update to match the state described in the imported TML file. + +You can edit a TML file in a *local branch*, but using TML Import to see the result in the originating Org will cause the object to be updated. + +There are two options: + +* Create a new Org to represent the local branch, to test the new TML +* Create a copy object in the original org, with a different identifier + +The final step would be to change the identifier in the copy object's TML to match the original identifier, then TML Import the file back into the original Org. + +image::./images/copy_edit_change_obj_id.png[Copy/edit change obj_id pattern] + +Actions like this can be performed in git however your team feels most comfortable with. The resulting changes in the "dev Org" then become part of the release package files that are exported and moved through the deployment stages like normal. + +== Other sync actions + +=== Deleting objects +When an object is deleted in the dev Org, you also need to `git rm` the file within the git release branch, so that the file will be deleted in downstream branches as you do pull/merge requsts. + +The following is the git and REST API portion of an example GitHub workflow that cleans up files that do not have a matching object in the Org any longer. + +It looks at whether the filenames (matching obj_id) in the dev branch of the git directory continue to exist via `/metadata/search` REST API command. If not found, issue `git rm` to remove the TML file, then `git commit` and `git push` to update the origin/branch. + +The `files_with_no_obj_on_org.py` script is what performs the `/metadata/search` REST API to get the list of existing objects, then looks at all the files in the git branch to see which filenames do not have corresponding obj_ids: + +[,yaml] +---- +run: | + git config --local user.email "${{ github.actor_id }}+${{ github.triggering_actor }}@users.noreply.github.com" + git config --local user.name "${{ github.triggering_actor }}" + python .github/workflows/files_with_no_obj_on_org.py > files_to_remove.txt + if [ -s "files_to_remove.txt" ]; then + echo "Files found in Org: ${{ vars.TS_ORG_NAME }} for removal:" + cat files_to_remove.txt + if [ "${{ github.event.inputs.DELETE_FLAG }}" = "DELETE" ]; then + echo "Deleting the files" + cat files_to_remove.txt | xargs git rm + rm files_to_remove.txt + git add * + git diff-index --quiet HEAD || git commit -a -m "Run ID ${{ github.run_id }}/${{github.run_attempt}} cleanup files from Org ${{ vars.TS_ORG_NAME }}" + git push + fi + else + echo "No files found to remove" + rm files_to_remove.txt + fi +---- + +[NOTE] +==== +You cannot do the reverse and simply delete objects from an Org that do not have equivalent TML files in the git directory, because end users can create new objects in an Org. +==== + +You also must consider that attempts while `git rm` command on files in release branch will flow upstream through via merge commands, removing data objects in the linked Orgs may fail if any user-created content in those Orgs are connected to the data objects. + +Thus the full deletion / cleanup process may involve manual "clean-up" in Orgs where ThoughtSpot does not allow object deletion without first deleting or changing the data source of dependent objects. + +=== obj_id updates +The `obj_id` property is simple enough to change within an Org, however the files in the repo are typically named after the `obj_id` of the object at the time of export. There will also be objects in the other Orgs with the same `obj_id`. + +An `obj_id` update should thus be *initiated from the Git provider* to rename the existing file and perform the ThoughtSpot REST API commands to update the `obj_id` across all Orgs with a copy of the object. + +The following is the git and REST API portion of example of a workflow in GitHub Action syntax to handle the rename of an object in the dev Org and release branch: + +[,yaml] +---- + - name: Change obj_id and rename file + env: + TS_SERVER: ${{ secrets.TS_SERVER }} + TS_SECRET_KEY: ${{ secrets.TS_SECRET_KEY }} + TS_USERNAME: ${{ secrets.TS_INSTANCE_ADMIN_USERNAME }} + OLD_OBJ_ID: ${{ github.event.inputs.OLD_OBJ_ID }} + NEW_OBJ_ID : ${{ github.event.inputs.NEW_OBJ_ID }} + run: | + git config --local user.email "${{ github.actor_id }}+${{ github.triggering_actor }}@users.noreply.github.com" + git config --local user.name "${{ github.triggering_actor }}" + echo "Import to Org_ID $ORG_ID rename $OLD_OBJ_ID to: $NEW_OBJ_ID" + if find . -name "${{ github.event.inputs.OLD_OBJ_ID }}*" -print -quit | grep -q .; then + echo "file for ${{ github.event.inputs.OLD_OBJ_ID }} found" + echo "Updating obj_id in org from ${{ github.event.inputs.OLD_OBJ_ID }} to ${{ github.event.inputs.NEW_OBJ_ID }}" + python .github/workflows/update_obj_id.py + echo "obj_id updated, now renaming file in repo" + O_FILE=$(find . -name "${{ github.event.inputs.OLD_OBJ_ID }}*" -print) + N_FILE="${O_FILE//${{ github.event.inputs.OLD_OBJ_ID }}/${{ github.event.inputs.NEW_OBJ_ID }}}" + echo "$O_FILE rename to $N_FILE" + git mv $O_FILE $N_FILE + git diff-index --quiet HEAD || git commit -a -m "Run ID ${{ github.run_id }}/${{github.run_attempt}} changed obj_id" + git push + echo "File rename successful" + else + echo "no file found matching ${{ github.event.inputs.OLD_OBJ_ID }}, no action taken" + fi +---- + +== GitHub Actions example +A repo with link:https://github.com/bryanthowell-ts/git-test-2/tree/main/.github/workflows[example GitHub workflow files to power Actions is available, window=_blank]. + +The workflows are composed of a YAML workflow file and a Python script using the link:https://github.com/thoughtspot/thoughtspot_rest_api_python[thoughtspot_rest_api Python library, window=_blank]. Both components are useful starting points for implementing in a different Git provider. diff --git a/modules/ROOT/pages/git-rest-api-guide.adoc b/modules/ROOT/pages/git-rest-api-guide.adoc index dbf1d6e7f..499b6656b 100644 --- a/modules/ROOT/pages/git-rest-api-guide.adoc +++ b/modules/ROOT/pages/git-rest-api-guide.adoc @@ -1,10 +1,15 @@ -= Version Control REST APIs += GitHub REST APIs :toc: true :toclevels: 2 -:page-title: Git REST API guide +:page-title: GitHub REST API guide :page-pageid: git-api -:page-description: Guide to Git Integration REST APIs +:page-description: Guide to GitHub Integration REST APIs + +[NOTE] +==== +The legacy GitHub REST APIs referenced here are tied to GitHub exclusively. The newer xref:git-provider-integration.adoc[Git provider integration pattern] provides more flexibility and control and should be utilized if you are starting out or having issues with the GitHub APIs. +==== The `/vcs/git/` endpoints of the v2.0 REST API provide all the functionality necessary to xref:git-configuration.adoc[configure], perform version control, and deploy changes to different ThoughtSpot environments, other than xref:guid-mapping.adoc#connection_variations[configuring connections]. @@ -16,7 +21,7 @@ The xref:version_control.adoc#moving-tml-changes-between-environments[basic proc The following sections describe how to use the version control REST APIs after completing xref:git-configuration.adoc[Git configuration] for a ThoughtSpot instance. -There is a complete implementation of all Git REST APIs available in the link:https://thoughtspot.github.io/cs_tools/[CS Tools package, target=_blank] as well as link:https://github.com/thoughtspot/thoughtspot_rest_api_v1_python/blob/main/examples_v2/[example workflow scripts available in Python, target=_blank]. +There is a complete implementation of all Git REST APIs available in the link:https://thoughtspot.github.io/cs_tools/[CS Tools package, target=_blank] as well as link:https://github.com/thoughtspot/thoughtspot_rest_api_v1_python/blob/main/examples_v2/[example workflow scripts available in Python, window=_blank]. == Commit files The `/api/rest/2.0/vcs/git/branches/commit` API call exports the TML files for the requested ThoughtSpot objects directly to a Git branch and commits the changes. @@ -55,7 +60,7 @@ The following example shows the API request with Liveboard and Model objects to ---- curl -X POST \ --url 'https://{ThoughtSpot-Host}/api/rest/2.0/vcs/git/branches/commit' \ - -H 'Authorization: Bearer {Bearer_token}\ + -H 'Authorization: Bearer {Bearer_token}' \ -H 'Accept: application/json'\ -H 'Content-Type: application/json' \ --data-raw '{ @@ -189,13 +194,13 @@ Due to GUID mapping requirements in most destination environments, it is current === Request example -The following example shows the API request with Liveboard and Model objects to commit to Git. +The following example shows the API request to validate a merge from the dev branch to main. [source,cURL] ---- curl -X POST \ --url 'https://{ThoughtSpot-Host}/api/rest/2.0/vcs/git/branches/validate' \ - -H 'Authorization: Bearer {Bearer_token}\ + -H 'Authorization: Bearer {Bearer_token}' \ -H 'Accept: application/json'\ -H 'Content-Type: application/json' \ --data-raw '{ @@ -246,7 +251,7 @@ The following example shows the API request for reverting a commit. ---- curl -X POST \ --url 'https://{ThoughtSpot-Host}/api/rest/2.0/vcs/git/commits/afc0fea831558e30d7064ab019f49243b1f09552/revert' \ - -H 'Authorization: Bearer {Bearer_token}\\ + -H 'Authorization: Bearer {Bearer_token}' \ -H 'Accept: application/json'\ -H 'Content-Type: application/json' \ --data-raw '{ diff --git a/modules/ROOT/pages/just-in-time-provisioning.adoc b/modules/ROOT/pages/just-in-time-provisioning.adoc index 7a4d86e07..a5e80275f 100644 --- a/modules/ROOT/pages/just-in-time-provisioning.adoc +++ b/modules/ROOT/pages/just-in-time-provisioning.adoc @@ -1,53 +1,180 @@ = Just-in-time provisioning :toc: true -:toclevels: 1 +:toclevels: 2 :page-title: Just-in-time provisioning of users and groups :page-pageid: just-in-time-provisioning :page-description: Just-in-time provisioning using SSO -ThoughtSpot can use the SSO process to create users and assign them to ThoughtSpot groups. +Just-in-time (JIT) provisioning in ThoughtSpot refers to creating or updating authentication and authorization at the time a user signs in to ThoughtSpot. -The capabilities are the same between SAML, OIDC, and trusted authentication methods, but the implementations of each are slightly different. +Due to the variety of options in ThoughtSpot, there are often several ways to accomplish JIT provisioning. -== User creation -Just-in-time provisioning (JIT) allows creating a user if they do not already exist at the time of SSO sign-in. +The steps to JIT provisioning are conceptually: -Creating a new user requires the assertion containing the username, email address, display name, groups, and org details if your instance has Orgs. + . Does the user exist in ThoughtSpot? + .. If the user does not exist, create the user. + . Is the user in this Org? + .. If not in the Org, add the user to the Org. + . Update the user's current provisioning within the Org (ThoughtSpot Group membership). + . Update any variable values for the user via token request (token authentication only). -Users created via JIT provisioning are identical to users created manually or via the REST APIs, except they do not have passwords in Thoughtspot; they cannot access ThoughtSpot other than through the SSO method. You can assign a password to any user later through the UI or a REST API call. +Due to the nature of API capabilities and error responses, along with restrictions around Org separation, the actual order of efficient steps may not follow the order listed above. -== Group assignment -Users can be assigned to ThoughtSpot groups via JIT as well. The list of groups should be composed of `group_name` properties, rather than `display_name`. -* JIT group assignment is a full replacement of the user's set of groups. -* Groups that do not exist will be created during the provisioning process, but a ThoughtSpot group by default provides no access control or privileges. However, you can assign privileges to the new groups via REST API update requests. -* Groups created via JIT provisioning will have the same group name as the one used by the `ts_groups` property in any RLS rules. +== JIT REST API provisioning (trusted authentication) +All of the following may be considered for JIT provisioning, using the same REST API capabilities as provisioning ahead of time: -== JIT provisioning and authentication token generation via REST APIs -Both REST API V1 and V2 tokens support just-in-time provisioning of users. + * User creation or adding to Org + * Group assignment for users + ** Group creation and updates + * RLS variable values for user -=== REST API v2 (Recommended) -Both `/api/rest/2.0/auth/token/full' and `/api/rest/2.0/auth/token/object` API endpoints allow getting an authentication token for the user being provisioned just-in-time. +These can all be implemented as part of the *xref:trusted-auth-token-request-service.adoc[token request service]* in the trusted authentication pattern. + +The *token request service* will need access to both the `secret_key` for the token requests and a *service account* with the appropriate administrator privileges to run the other REST API commands. + +== User creation or adding to Org +For a login token to be requested, the user must exist in ThoughtSpot in the Org the token is being requested for. + +Creating a new user requires at minimum the username, email address, display name, and org IDs to create them in. + +=== Create user and update user REST APIs +If you need to update a user's details, including their group membership, the simplest method is to use: + +. `link:https://developers.thoughtspot.com/docs/restV2-playground?apiResourceId=http%2Fapi-endpoints%2Fusers%2Fupdate-user[/users/{user-identifier}/update]` in the target Org with the `operation: REPLACE` option. + +.. If you receive an error, retry the `/users/{user-identifier}/update` request with an Administrator service account in the Primary Org to add the user to the desired Org, with `operation: ADD`. +.. If you still receive an error, the user does not exist in ThoughtSpot. Use `/users/create` from the Primary Org to create the user and place in the desired Org(s). +.. Retry the original `/users/{user-identifier}/update` command in the desired Org. +. Request the preferred auth token for the user, without using any `autocreate=` options. + +You could instead check for the user's state with an Org via `/users/search`. and avoiding unnecessary updates and error handling steps. + +Any additional changes to the Groups themselves can be managed with other REST APIs described in the following section. + +=== autocreate using token request +There are several token request endpoints, each with an `autocreate=true` option for just-in-time provisioning: + +* `/api/rest/2.0/auth/token/full` +* `/api/rest/2.0/auth/token/custom` +* `/api/rest/2.0/auth/token/object` + +[NOTE] +==== +`autocreate=true` creates the user (and any new groups) with default options, which may not be preferred. Using the direct `users` and `groups` endpoints allows full control of their options. +==== + +The following details must be included in a request with `autocreate=true` to allow provisioning the user: * The `auto_create: true` parameter enables the token for the JIT provisioning of the user. * The `display_name` and `email` parameters are also required for JIT user creation. * If Orgs are enabled, specify the `org_id` parameter to direct ThoughtSpot to assign the user to the specified Org. * Specify the `group_identifiers` parameter only if you want to enable JIT group assignment. Passing `group_identifiers: []` will set the user to be assigned to *no groups*, while excluding the `group_identifiers` parameter altogether will leave the user assigned to their existing set of groups. -For more information, see xref:authentication.adoc#_just_in_time_provisioning[Just-in-time provisioning via REST v2 API]. +Users created via `autocreate=true` are identical to users created manually or via the REST APIs, except they do not have passwords in ThoughtSpot; they cannot access ThoughtSpot other than through the SSO method. You can assign a password to any user later through the UI or a REST API call. + +== Group assignment +Groups in ThoughtSpot are used to assign a variety of attributes such as content sharing, group-based RLS, roles, and column-level security. JIT provisioning often requires a combination of updates to both the user and the groups they belong to. + +=== Group assignment via Update User REST API +The `/users/{user-identifier}/update` API can update a user's Group membership within the Org, determined by the org_id of the auth token used for the REST API request: + +[,json] +---- +{ + "operation": "ADD", + "group_identifiers": [ + "New Group A" + ] +} +---- + +You can also choose `"operation" : "REPLACE"` to reset the entire set of Groups for a user. + +[NOTE] +==== +You cannot set a user's groups in an Org other than the REST API request's auth token. If you create a user from the Primary Org, any `group_identifiers` provided at that time will apply only within the Primary Org, even if you add the user to multiple Orgs in the `/users/create` request. +==== + +=== Group assignment via Update Group REST API +Because group membership is a relationship between a user and a group, you can also update the set of users within a group using the `link:https://developers.thoughtspot.com/docs/restV2-playground?apiResourceId=http%2Fapi-endpoints%2Fgroups%2Fupdate-user-group[/groups/{group_identifier}/update]` REST API endpoint. + +Similarly to the user update endpoint, you can choose between three operations: `ADD`, `REPLACE`, and `REMOVE` to update only the `user_identifiers` of a group without affecting other properties: + +[,json] +---- +{ + "operation": "ADD", + "user_identifiers": [ + "new.user@website.com" + ] +} +---- + +=== Group assignment via token request +The various token requests can set or update a user's group membership when `autocreate=true` is set. However, they have slightly different behaviors: + +* `/auth/token/full` and `/auth/token/object` do a *full replace* of the list of groups on every token request +* `/auth/token/custom` only assigns groups *if the user is created* + +The list of groups should be composed of `group_name` properties, rather than `display_name`. +If a group name is provided that does not match any existing group name, a new group will be created during the provisioning process. + +Groups created via `autocreate=true` will have identical `group_name` and `display_name` properties but will otherwise be a default ThoughtSpot group, granting no access control, privileges or roles. + +However, you can assign privileges or make any other adjustment to the new groups via REST API `link:https://developers.thoughtspot.com/docs/restV2-playground?apiResourceId=http%2Fapi-endpoints%2Fgroups%2Fupdate-user-group[/groups/{group_identifier}/update]` endpoint. + + +== Group privileges and access control via REST APIs +xref:api-user-management.adoc[Privileges] are either assigned directly to a group or part of roles if xref:roles.adoc[Role-based access control (RBAC)] is enabled on your instance. + +Roles must be created first prior to being assigned as part of the `/groups/create` or `/groups/{group_identifier}/update` REST API request. + +Access control in ThoughtSpot is based on *link:https://developers.thoughtspot.com/docs/restV2-playground?apiResourceId=http%2Fapi-endpoints%2Fsecurity%2Fshare-metadata[sharing content]* to groups or directly to users. + +Sharing requires that the group or user exist prior to calling the sharing REST API. + +== RLS variable values +RLS rules can use a user's *username*, *group membership* or *variable values* to define a filtering clause added to all queries on a table. + +If using `ts_groups` in a RLS Rule, the group names must match exactly with the values in a column in the data warehouse, so the name of the group itself serves as a __data entitlement__. + +Variable values are used as part of the xref:abac_rls-variables.adoc[ABAC via RLS variables] pattern, which allows assigning many values to multiple variables via the xref:abac_rls-variables.adoc#_create_an_abac_token_request_with_variable_attributes[Custom Token request]. + +There is also a direct xref:variables.adoc#_update_variable_values[variable values update REST API] for more complex or bulk updates. + + + + + +//// +=== JIT provisioning and authentication token generation via REST APIs +Both REST API V1 and V2 tokens support just-in-time provisioning of users. + +=== REST API v2 (Recommended) +//// + +//// === REST API v1 The `/tspublic/v1/session/auth/token` API endpoint can provision a new user by setting the `autocreate` property to `true`. For more information, see xref:session-api.adoc#session-authToken[Session API]. - +//// +//// == Org IDs If the Orgs feature is enabled on your instance, you do need to specify the Org ID when creating a user. Org IDs are integers that are created automatically when a cluster administrator creates an Org. Administrators can get the Org IDs configured on a ThoughtSpot instance via `/tspublic/v1/org/search` or `/api/rest/2.0/orgs/search` API endpoint. To know the Org ID of your current Org, send a `GET` request to the `/tspublic/v1/session/orgs` API endpoint within the browser. For more information about Org APIs, see xref:org-manage-api.adoc[Org administration]. +//// + +== IdP assertion provisioning +Due to the nature of assertions returned from an IdP, the JIT provisioning capabilities are more limited. The REST APIs available within the trusted authentication workflow described above can still be used for provisioning and updates, but must be made prior to IdP assertion. + +In general, the IdP assertion can create a user and add them to existing ThoughtSpot groups within existing ThoughtSpot Orgs. == SAML SSO authentication For SAML SSO users, you can link:https://docs.thoughtspot.com/cloud/latest/authentication-integration#_enable_saml_authentication[enable SAML authentication, window=_blank] and *Automatically add SAML users to ThoughtSpot upon first authentication*. @@ -61,11 +188,4 @@ OIDC SSO can be configured for JIT user creation, as the necessary properties sh JIT group assignment xref:configure-oidc.adoc#group-synchronization[can be enabled for OIDC via a support ticket]. -== Group privileges and access control via REST APIs - -JIT provisioning of groups does not provide the full configuration of groups or assign access control. You can use the REST APIs to create, edit, and synchronize groups with the embedding application. For more information about group privileges, see xref:api-user-management.adoc[user and group privileges]. - -REST API calls other than *token requests* must be performed using a ThoughtSpot user account with the appropriate level of administrative privileges. For example, you could use xref:rest-api-v2-reference.adoc#_groups[REST API v2.0] or the xref:rest-api-reference.adoc#_groups_and_privileges[REST API v1] group endpoints to implement ThoughtSpot groups that are intended for use in Row Level Security (RLS) rules. -For these groups, the group name must match exactly with a value in a column in the data warehouse, so the name of the group itself serves as a __data entitlement__. For more information, see xref:abac-user-parameters.adoc[Attribute-based access control]. -Similarly, if xref:roles.adoc[Role-based access control (RBAC)] is enabled on your instance, you must map role privileges to groups and then assign them to users. diff --git a/modules/ROOT/pages/mcp-connect-custom-chatbot.adoc b/modules/ROOT/pages/mcp-connect-custom-chatbot.adoc index fdf83129c..9f24f78e6 100644 --- a/modules/ROOT/pages/mcp-connect-custom-chatbot.adoc +++ b/modules/ROOT/pages/mcp-connect-custom-chatbot.adoc @@ -14,16 +14,11 @@ When integrated, the agent in your custom application can: * Support natural language conversation sessions for data questions. * Generate embeddable visualizations and programmatically create a Liveboard. -[IMPORTANT] -==== -Currently, the MCP Server integration does not support link:https://docs.thoughtspot.com/cloud/latest/spotter-versions[Spotter 3 capabilities]. -==== - == Before you begin Before you begin, review the following prerequisites: * Node.js version 22 or later is installed and available in your environment. -* Ensure that your setup has access to a ThoughtSpot application instance with 10.11.0.cl or a later release version. +* Ensure that your setup has access to a ThoughtSpot application instance with 10.11.0.cl or a later release. For MCP Server with Spotter 3 capabilities, ensure that your ThoughtSpot instance is 26.2.0.cl or later. * Ensure that the users have the necessary permissions to view data from relevant models and tables in ThoughtSpot. Existing RLS/CLS rules on tables are enforced automatically in data source responses. To create charts or Liveboards from a conversation session, data download and content creation privileges are required. == Authenticating users @@ -37,8 +32,16 @@ The token generated for the user session is used as a bearer token when your bac == Connecting clients If your custom chatbot implementation uses Claude, OpenAI, or Gemini LLM APIs to call MCP tools, ensure that your MCP Server endpoint, authentication token, and ThoughtSpot host are included in the API request. +When integrating with apps using custom workflows, ThoughtSpot recommends using the MCP server URL with the date-based `api-version` parameter. This allows you to pin a specific version and avoid introducing unintended changes to custom workflows that rely on tool responses. + +* For OAuth clients: +`https://agent.thoughtspot.app/mcp?api-version={YYYY-MM-DD}` + +* For bearer token clients: +`https://agent.thoughtspot.app/token/mcp?api-version={YYYY-MM-DD}` + === Claude MCP connector -If your application uses Claude MCP connector, use the following API request format to connect Claude to the MCP Server: +If your application uses the Claude MCP connector, use the following API request format to connect Claude to the MCP Server: [source,bash] ---- @@ -57,7 +60,7 @@ curl https://api.anthropic.com/v1/messages \ "mcp_servers": [ { "type": "url", - "url": "https://agent.thoughtspot.app/bearer/mcp", + "url": "https://agent.thoughtspot.app/token/mcp?api-version={YYYY-MM-DD}", "name": "thoughtspot", "authorization_token": "TS_AUTH_TOKEN@my-instance.thoughtspot.cloud" } @@ -68,10 +71,10 @@ curl https://api.anthropic.com/v1/messages \ In the above example, the API call includes: * The user’s message. -* ThoughtSpot’s MCP Server endpoint `https://agent.thoughtspot.app/bearer/mcp`. +* ThoughtSpot’s MCP Server endpoint `\https://agent.thoughtspot.app/token/mcp?api-version={YYYY-MM-DD}`. Replace `YYYY-MM-DD` with an actual date string. * An `authorization_token` that encodes which ThoughtSpot instance and user/token to use. -Claude uses the configured MCP Server to call ThoughtSpot MCP tools as needed, using the bearer-style token you provided. +Claude uses the configured MCP Server to call ThoughtSpot MCP tools as needed, using the bearer token you provided. === OpenAI Responses API If your application uses an OpenAI LLM, use the following API request format to connect OpenAI to the MCP Server: @@ -87,7 +90,7 @@ curl https://api.openai.com/v1/responses \ { "type": "mcp", "server_label": "thoughtspot", - "server_url": "https://agent.thoughtspot.app/bearer/mcp", + "server_url": "https://agent.thoughtspot.app/token/mcp?api-version={YYYY-MM-DD}", "headers": { "Authorization": "Bearer TS_AUTH_TOKEN", "x-ts-host": "my-instance.thoughtspot.cloud" @@ -101,10 +104,10 @@ curl https://api.openai.com/v1/responses \ In the above example, the API call includes the following parameters: * MCP as the tool type. -* ThoughtSpot MCP Server URL. +* ThoughtSpot MCP Server URL. Replace `YYYY-MM-DD` in the URL with an actual date string. * Authentication token and ThoughtSpot host URL. -The OpenAI LLM model uses the configured MCP Server, sends the provided headers on each MCP tool call, and gets the requested data from your ThoughtSpot instance under that token's identity. +The OpenAI LLM uses the configured MCP Server, sends the provided headers on each MCP tool call, and gets the requested data from your ThoughtSpot instance under that token's identity. === Gemini API @@ -120,7 +123,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; const transport = new StreamableHTTPClientTransport( - new URL("https://agent.thoughtspot.app/bearer/mcp"), + new URL("https://agent.thoughtspot.app/token/mcp?api-version={YYYY-MM-DD}"), { requestInit: { headers: { @@ -154,7 +157,7 @@ await mcpClient.close(); The above example: -* Creates an MCP client and connects it to the ThoughtSpot MCP Server using `StreamableHTTPClientTransport`. +* Creates an MCP client and connects it to the ThoughtSpot MCP Server using `StreamableHTTPClientTransport`. Ensure that you replace `YYYY-MM-DD` in the URL with an actual date string. * Sends the required headers with the authentication token and ThoughtSpot host URL in MCP requests. * Wraps the MCP client as a tool and passes it into `GoogleGenAI` so Gemini can call ThoughtSpot tools as part of answering a user's query. @@ -163,17 +166,20 @@ The above example: To verify the integration: . Start a chat session by asking a question and verify whether your chatbot's LLM is calling the ThoughtSpot MCP tools to generate a response. + -A typical agentic workflow follows this pattern: -* Calls `getRelevantQuestions` to break the request into sub-queries -* Calls `getAnswer` to run those questions in ThoughtSpot and receive structured data and visualization metadata -* Based on a user prompt, calls `createLiveboard` to save the results in a ThoughtSpot Liveboard. -. Verify whether the metadata in the output includes `frame_url` to embed a visualization in an iframe or HTML snippet. +. Verify the tool calls. For information about tool calls and responses, see xref:mcp-tool-reference-guide.adoc[MCP tool reference guide]. +. Verify the Liveboard creation workflow and check whether a Liveboard is created in ThoughtSpot. +. Verify whether the metadata in the output includes the URL to embed a visualization in an iframe or HTML snippet. + +== Displaying visualization in iframe +Visualizations are returned as ThoughtSpot Answers via iframes. Use the xref:startAutoMCPFrameRenderer.adoc[startAutoMCPFrameRenderer] function to display the iframe. + +An example project showing how this is used in the `app.jsx` file with a code sample is available in the link:https://github.com/thoughtspot/developer-examples/blob/main/mcp/python-react-agent-simple-ui/client/src/App.jsx[developer-examples GitHub repository, window=_blank]. == Troubleshooting errors Cannot connect to MCP Server:: -* Verify if the MCP Server is reachable. +* Verify that the MCP Server is reachable. * Ensure that the correct MCP Server URL is used in API requests. * If the issue persists, verify the logs and contact ThoughtSpot Support for assistance. @@ -183,173 +189,13 @@ Authentication failure:: * Verify whether the MCP Server and ThoughtSpot host are reachable. * Verify whether the user has the necessary privileges to view data or create content. -== MCP tool calls and response output -The following sections outline the MCP request input schema and data structure of the response. - -=== ping -Runs a basic health check to validate that the MCP Server is reachable. - -[source,ts] ----- -const tsPing = await callMCPTool("ping", {}); ----- - -=== getDataSourceSuggestions -Suggests appropriate ThoughtSpot data models for a given natural language question. - - -==== Example request - -[source,ts] ----- -const dsSuggestions = await callMCPTool("getDataSourceSuggestions", { - query: "show me sales by region" // user's query -}); ----- - -==== Response format - -Returns an object containing an array of suggestions: - -[source,json] ----- -{ - "suggestions": [ - { - "header": { - "guid": "worksheet-guid-123", - "displayName": "Sales Analytics", - "description": "Sales performance by region, product, and channel" - }, - "confidence": 0.92, - "llmReasoning": "This worksheet contains sales metrics and regional dimensions relevant to the query." - } - ] -} ----- - -Key fields are: - -* `header.guid`: Unique ID for the datasource. The `datasourceId` is used in `getRelevantQuestions` and `getAnswer` calls. -* `header.displayName`: Name of the data source. -* `header.description`: Optional description of the data source. -* `confidence`: Numeric score indicating the confidence of the system about a data model being the right match for the user’s query. -* `llmReasoning`: LLM's reasoning for the suggestion. - -=== getRelevantQuestions -Uses ThoughtSpot’s reasoning engine to generate AI-suggested sub-queries that help generate specific answers for a given data context. - -==== Example call - -[source,ts] ----- -const result = await callMCPTool("getRelevantQuestions", { - query: "show me sales data", // User's natural language query - datasourceIds: ["model-guid-123"], // Array of worksheet/datasource GUIDs - additionalContext: "User is interested in the data for underperforming regions and products" -}); ----- - -==== Response example - -[source,json] ----- -{ - "questions": [ - "What is the total sales revenue by region?", - "Which products have the highest revenue?", - "What are the top selling categories?" - ] -} ----- - -Each returned question can then be passed individually into `getAnswer`. - -=== getAnswer -Executes a natural language question for a given data context and returns the resulting data and visualization metadata. Clients can use this data and frame URL to render visualizations. - -==== Example call - -[source,ts] ----- -const result = await callMCPTool("getAnswer", { - question: "Total sales by region", // Natural language question - datasourceId: "model-guid-123" // Worksheet/datasource GUID -}); ----- - -==== Response example - -[source,json] ----- -{ - "question": "Total sales by region", - "session_identifier": "abc-123-def-456", - "generation_number": 2, - "data": "\"Region\",\"Total Sales\"\n\"East\",100000\n...", - "frame_url": "https://...", - "fields_info": "..." -} ----- - -Key fields are: - -* `session_identifier`: Unique session ID used to group answers. Required when creating a Liveboard from this answer using the `createLiveboard` MCP tool. -* `generation_number`: Version number for this answer. Required for Liveboard creation. -* `question`: The executed question; useful for display and to pass it into the `createLiveboard` request. -* `data`: Data returned in encoded format. Contains column headers and all returned rows in comma-separated format, which can be parsed to render tables or charts in your application. -* `frame_url`: Optional iframe URL for embedding the visualization in your UI. -* `fields_info`: Descriptive metadata about the fields and chart, useful for explanations. - -=== createLiveboard - -Creates a ThoughtSpot Liveboard with one or more answers from the results. This is a two-step process and includes the following calls: - -. Call `getAnswer` to generate visualizations and obtain `session_identifier` and `generation_number`. -. Call `createLiveboard` with those values to create the Liveboard. - -==== Example call - -[source,ts] ----- -const answerData = JSON.parse(answerResult.result.content); - -const liveboardResult = await callMCPTool("createLiveboard", { - name: "My Sales Dashboard", - noteTile: "My Sales Dashboard was created by TS MCP Chat", // Description text for the Liveboard - answers: [{ - question: answerData.question, // Display name for the Liveboard - session_identifier: answerData.session_identifier, - generation_number: answerData.generation_number - }] -}); ----- - -Required attributes are: - -* `noteTile`: Use this field for any Liveboard description or notes; a separate description field is not supported. -* `answers`: Required array. Each item must include `question`, `session_identifier`, and `generation_number` from a prior `getAnswer` call. - -==== Response example - -[source,json] ----- -{ - "liveboardId": "liveboard-guid-here", - "name": "My Sales Dashboard", - "frame_url": "https://..." -} ----- - -Key fields are: +== MCP tools and response +For information about tool calls and responses, refer to the xref:mcp-tool-reference-guide.adoc[MCP tool reference guide]. -* `liveboardId`: GUID of the created Liveboard. -* `name`: Name of the Liveboard. -* `frame_url`: URL that can be embedded to display the Liveboard. == Additional resources * To view the MCP Server code, go to the link:https://github.com/thoughtspot/mcp-server[MCP Server GitHub repository, window=_blank]. -* For a chat client example, see link:https://github.com/thoughtspot/developer-examples/tree/main/mcp/python-react-agent-simple-ui[Python Agent with Simple React UI]. +* For a chat client example, see link:https://github.com/thoughtspot/developer-examples/tree/main/mcp/python-react-agent-simple-ui[Python Agent with Simple React UI, window=_blank]. diff --git a/modules/ROOT/pages/mcp-integration.adoc b/modules/ROOT/pages/mcp-integration.adoc index 19a630b1f..82424a00e 100644 --- a/modules/ROOT/pages/mcp-integration.adoc +++ b/modules/ROOT/pages/mcp-integration.adoc @@ -6,135 +6,182 @@ :page-pageid: mcp-integration :page-description: Learn what ThoughtSpot MCP Server is, when to use it, and how it fits into your AI and analytics architecture. -ThoughtSpot’s Agentic Model Context Protocol (MCP) Server allows you to integrate ThoughtSpot analytics into any AI-native application, custom chatbot, or LLM platform that supports MCP. Instead of rebuilding analytics logic yourself, you connect an LLM/AI agent to the ThoughtSpot MCP Server. +ThoughtSpot’s Model Context Protocol (MCP) Server enables integration of ThoughtSpot analytics into any AI-native application, custom chatbot, or LLM platform that supports MCP. Instead of rebuilding analytics logic yourself, you connect an LLM/AI agent to the ThoughtSpot MCP Server. == Overview -ThoughtSpot MCP Server exposes ThoughtSpot analytics as tools and resources that MCP-compatible agents can discover and call. - -When integrated, the MCP Server equips your AI agent/LLM with the following capabilities: +ThoughtSpot MCP Server exposes ThoughtSpot analytics as tools and resources that MCP-compatible agents can discover and use. When integrated, the MCP Server provides your AI agent or LLM with the following capabilities: * Automatic discovery of ThoughtSpot MCP tools * Natural language queries and responses * Programmatic creation of Liveboards and visualizations -* Generating embeddable visualizations for custom chatbot workflows +* Generating embeddable visualizations + +=== Supported integrations +ThoughtSpot MCP Server supports two primary integration options: + +[cols="2,6", options="header"] +|=== +| Integration option +| Description +| xref:mcp-server-client-connection.adoc[Plug-and-play clients] +|This integration works with agents or LLMs that natively support MCP, such as Claude, OpenAI, Gemini, or custom MCP clients. It allows your AI agent to call tools directly and leverage ThoughtSpot’s governed analytics, business semantic layer, data context, and row-level/object-level security, without the need to build your analytics logic. -=== Supported use cases +**When to use**: +If your application already has an AI chat interface or agentic experience, you can quickly add analytics to your existing setup without custom development. -ThoughtSpot supports MCP Server integration for the following use cases: +|xref:mcp-connect-custom-chatbot.adoc[Custom chatbot integration] +|If you are building your own MCP-based chatbot or application with custom orchestration logic or LLM, you can integrate the ThoughtSpot MCP Server to call ThoughtSpot tools behind your own web experience. -* *Plug-and-play clients* + -If your application already has an AI chat interface, you can use the MCP Server to plug ThoughtSpot analytics into your application's agentic experience. This integration works with agents or LLMs that natively support MCP, such as Claude, OpenAI, Gemini, or custom MCP clients. It allows your AI agent to call tools and leverage ThoughtSpot’s governed analytics, business semantic layer, data context, and row-level/object-level security, so you don’t need to build your own analytics logic. +**When to use**: +Use this option if your organization requires a custom conversation flow, backend orchestration, and a tailored analytics experience for your users. +|=== -* *Custom chatbot integration* + -If you are building an MCP-based chatbot or application with your own orchestration logic or LLM, and you want to call ThoughtSpot MCP tools behind a custom web experience, integrate the MCP Server into your application. This approach is recommended when you need fine-grained control over conversation flow, backend orchestration, and the analytics experience. +Regardless of integration mode, ThoughtSpot’s semantic layer, data context, and security features ensure trusted and governed analytics for all users. -==== Choosing the right integration option +=== MCP Server license +ThoughtSpot MCP Server is available as an add-on with the following link:https://www.thoughtspot.com/pricing[license plans]: -Your integration choice depends on where the conversational UI is presented to the user and whether your application relies on ThoughtSpot, a third-party AI agent, or your own agentic AI to orchestrate the analytics workflow. +* ThoughtSpot Enterprise Edition +* ThoughtSpot Embedded -Regardless of the integration mode, you can leverage ThoughtSpot’s semantic layer, data context, object-level, row-level, and column-level security to ensure trusted, governed analytics for your users. +To learn more about subscription options, contact your ThoughtSpot sales representative. -=== Architecture and roles -The MCP Server integration and orchestration layer includes the following core components: +== Core components and roles +The MCP Server integration and orchestration layers include the following core components: -[width="100%" cols="2,4"] +[width="100%" cols="2,6"] [options='header'] -|====== +|=== |Component|Role -|*Client Interface* a| -User interface that renders chat, responses, and charts. For example, Claude AI web app, Claude Desktop, ChatGPT, OpenAI-based integrations, Gemini-based agents, custom web applications, or internal tools. +|**Host application** | The AI platform or AI-native app that renders chat, responses, and charts, and manages user-facing conversation. For example, Claude AI web app, Claude Desktop, ChatGPT, OpenAI-based integrations, Gemini-based agents, custom web applications, or internal tools. -|*Agent or LLM* -a| Acts as orchestrator. + +|**MCP client** +a|The MCP client discovers available tools, manages the MCP connection to the server, and passes tool calls between the LLM and the MCP Server. -- Receives the user’s prompt -- Discovers ThoughtSpot MCP tools -- Decides which tools to call and in what order. -- Combines ThoughtSpot results with other sources and generates the final answer. +|**ThoughtSpot MCP Server** a| +The remote MCP server hosted by ThoughtSpot. -|*ThoughtSpot MCP Server* a| -- Acts as a gateway between the agent and ThoughtSpot. -- Exposes analytics as MCP tools. -- Validates requests and forwards calls to ThoughtSpot. +- Acts as a gateway between the MCP client and ThoughtSpot. +- Exposes ThoughtSpot analytics as MCP tools. +- Receives tool calls, authenticates via OAuth/Bearer Token, and routes requests to ThoughtSpot. -|*ThoughtSpot instance* +|**ThoughtSpot instance** | Your ThoughtSpot instance where data models, Liveboards, and security policies exist. + - Executes queries and generates visualizations -- Provides access to data - Enforces data security with RLS and CLS rules. -|*End user* -|Interacts with an AI client or custom application, asks questions, and acts on results. -|====== +- In integrations using the MCP Server with Spotter 3 support, it provides additional capabilities such as advanced analytics, reasoning, forecasting, automatic data source selection, and deep research. +|=== The following figure illustrates the interaction between the user, agent, and MCP Server: [.widthAuto] image::./images/agents-mcp-server-arch.png[MCP integration] -=== MCP tools and resources - -ThoughtSpot MCP Server exposes the following tools and resources: - -* `ping` + -Connectivity/health check. Used by the MCP host, such as Claude, Gemini, or ChatGPT, to verify whether it can reach the ThoughtSpot MCP Server and whether the server is available. - -* `getDataSourceSuggestions` + -Suggests the most relevant ThoughtSpot data sources for a given query. - -* `getRelevantQuestions` + -Uses ThoughtSpot’s reasoning engine to turn a broad or high‑level user query into a set of concrete analytical questions that should be asked of the data. - -* `getAnswer` + -Executes those analytical questions and returns structured data and answers. +== MCP Server architecture and tools +For more information about MCP tools, resources, and workflow processing, see the following documentation: -* `createLiveboard` + -Creates a ThoughtSpot Liveboard from a list of answers/questions, typically at the end of a conversation. It turns the conversational analysis into a Liveboard with visualizations. +* xref:mcp-server-spotter3.adoc[MCP Server with Spotter 3] +* xref:mcp-server-legacy.adoc[Legacy MCP Server architecture and tools] -=== How it works +//// -The agentic interactions in an orchestrated environment typically include these steps: +|**Embedded visualizations** +|Not supported in turnkey platforms; requires additional development work in custom apps. +|Supports direct embedding of charts in MCP clients and via `iframe_url` in custom apps. Every answer includes an `iframe_url` that renders as an interactive ThoughtSpot visualization. -. *User asks a question* + -A user sends a query in the chat interface to get data. For example, `What were the total sales of Jackets and Bags in the Northeast last year?`. + -Optionally, the user can specify the data context to generate a response. - -. *Agent calls `getDataSourceSuggestions` (optional)* + -If the user’s question doesn’t specify a data source, the agent can call `getDataSourceSuggestions`. -ThoughtSpot returns candidate data sources (models) with confidence scores and reasoning. - -. *User's query is decomposed into sub-questions* + -To break the user’s query into smaller analytical questions, the agent calls `getRelevantQuestions`. + -In response to the agent's request, ThoughtSpot returns the AI-suggested, schema-aware questions that are easier to execute analytically. - -. *The query is processed for generating answers* + -For each suggested or chosen question, the agent calls `getAnswer`. ThoughtSpot returns the following: + -* Preview data for LLM reasoning. -* Visualization metadata, including an embeddable `frame_url`. -* `session_identifier` and `generation_number` for charts that are used as input for creating a Liveboard. - -. *A Liveboard is generated from the results* (optional) + -The user can choose to save answers from the conversation in a ThoughtSpot Liveboard. For this workflow, the agent extracts `question`, `session_identifier`, and `generation_number` from each `getAnswer` response and calls `createLiveboard`. + -ThoughtSpot creates a Liveboard and returns identifiers and a `frame_url` for the Liveboard. -+ -During this interaction, users typically see a natural-language summary. When a Liveboard is created, a link to open the corresponding Liveboard in ThoughtSpot is generated. -+ -In custom applications, you can embed the visualizations generated from the interaction, load them inside iframe elements, and render interactive charts directly in your webpage. You can also add your own buttons or links, such as 'Save as Liveboard' or 'Pin this analysis', which call `createLiveboard` to create or persist a Liveboard that contains your current charts and analysis. - -== Getting access to the MCP Server - -ThoughtSpot MCP Server is available as an add-on with the following link:https://www.thoughtspot.com/pricing[license plans]: - -* ThoughtSpot Enterprise Edition -* ThoughtSpot Embedded - -To learn more about subscription options, contact your ThoughtSpot Sales representative. +=== MCP tools and resources +The following table +[cols="2,2,4", options="header"] +|=== +|| Legacy MCP Server setup | MCP Server with Spotter 3 support +|**MCP Server connectivity test**. | `ping` +| `check_system_readiness` + +|**Conversation session initiation** +|Does not support session-based architecture. Tools are stateless. +|`create_analysis_session` + +Creates a stateful session and returns `analytical_session_id`, which is required for subsequent calls. + +|**Data source selection** +|`getDataSourceSuggestions` + +Standalone tool. Called separately to retrieve source suggestions and pass +the result to other tools. +|Built into `create_analysis_session` via optional `data_source_id` parameter + +If the parameter is omitted, ThoughtSpot automatically selects the most relevant source from the question. + +|**Query submission** +|`getRelevantQuestions` + +Breaks a query into questions ThoughtSpot analytics can answer. Returns answers directly in the same call. +|`send_session_message` + +Sends a question or follow-up message in natural language. Does not return the full answer immediately, but triggers asynchronous processing. Returns only the `success` message. + +|**Intermediate thinking / reasoning** +|Not exposed to users. +|`get_session_updates` update types expose `text` and `text-chunk` to users during polling. + +|**Answer retrieval** +|`getAnswer` + +Returns structured data and answers and the full response. +|`get_session_updates` + +Polls for streamed updates across multiple calls and accumulates updates from every poll. The tool is called in a loop until the `is_done: true` state. + +|**Visualization output** +|Not included in tool responses +|The `iframe_url` field in the `session_update` -> `answer` -> `type` returned by the `get_session_updates` tool. + +|**Liveboard creation** +|`createLiveboard` + +Creates a Liveboard from a list of answers. +|`create_dashboard` + +Creates a dashboard from `answer_id` values collected from the session update type `answer`. Requires a `note_tile` HTML summary tile. + +|**Follow-up questions** +|`getRelevantQuestions` with `additionalContext` parameter. Requires prior context for each follow-up call. +|`send_session_message` with the same `analytical_session_id`. The session retains context automatically. The `additional_context` parameter can be included to inject new context for each follow-up question or message. +|| +|=== +//// + +== MCP Server URL + +ThoughtSpot MCP Server now uses date-based API versioning in the URL. New versions are identified using the `?api-version=YYYY-MM-DD` parameter, which you can append to the MCP Server URL to pin your integration to a specific version. Each new version may introduce tool changes, enhancements, or bug fixes. + +When you set the `api-version` to a specific date string, the server returns the version released on the specified date. If no new version of MCP Server is released on the date specified in the URL, the server returns the closest earlier version. For example, if you request `?api-version=2026-06-01` and no new version has been released since `2026-05-01`, the server returns the 2026-05-01 version. This means your integration continues to work without breaking, and you only need to update your pinned date if you want to opt in for a newer version. + +To automatically receive every new version of the MCP tools as ThoughtSpot releases them, use the URL without a pinned `api-version`. Note that the new versions may introduce changes to tool behavior, input parameters, or output schemas that affect your integration. Therefore, we recommend pinning your integration to a specific version. + +[cols="2,6", options="header"] +|==== +|Apps/Integration type| MCP Server URL +|**OAuth apps** + +(Plug-and-play integration) a| + +* `\https://agent.thoughtspot.app/mcp?api-version=latest` + +Always points to the latest version. + +* `\https://agent.thoughtspot.app/mcp` + +Currently, this URL points to the baseline version with legacy MCP tools. It will resolve to the latest version in the near future. + +* If you want to pin a specific version, use the URL with the `api-version` parameter and specify the date string: + +`\https://agent.thoughtspot.app/mcp?api-version={YYYY-MM-DD}`. For example, `?api-version=2026-05-01` + +|**Bearer token apps** a| * `\https://agent.thoughtspot.app/token/mcp` + +Always points to the latest version. +* `\https://agent.thoughtspot.app/token/mcp?api-version={YYYY-MM-DD}` + +Replace `{YYYY-MM-DD}` with the actual date string to point to the specified version or the closest earlier version. For example, `?api-version=2026-05-01` +|==== + +[IMPORTANT] +==== +The `\https://agent.thoughtspot.app/openai/mcp` and `\https://agent.thoughtspot.app/bearer/mcp` are deprecated and point to the version with legacy MCP tools only. +ThoughtSpot recommends migrating your existing MCP Server integration setup to the new version. For more information, see xref:mcp-server-changelog.adoc#_migration_guidelines[MCP Server changelog]. +==== == Next steps -* To learn how to connect existing MCP-aware tools such as Claude, ChatGPT, and Gemini, see xref:mcp-server-client-connection.adoc[Connecting MCP clients to ThoughtSpot MCP Server]. -* To learn how to integrate MCP Server with a custom chatbot or application, see xref:mcp-connect-custom-chatbot.adoc[Integrating MCP Server in a custom chatbot]. +* To learn how to connect existing MCP-aware tools such as Claude, ChatGPT, and Gemini, see the xref:mcp-server-client-connection.adoc[Connecting MCP clients to ThoughtSpot MCP Server] documentation. +* To learn how to integrate MCP Server with a custom chatbot or application, see the xref:mcp-connect-custom-chatbot.adoc[Integrating MCP Server in a custom chatbot] documentation. == Additional resources -* For information about MCP, see link:https://modelcontextprotocol.io[Model Context Protocol specification, window=_blank]. -* For implementation details, see link:https://github.com/thoughtspot/mcp-server[MCP Server GitHub repository, window=_blank]. +* For information about MCP, see the link:https://modelcontextprotocol.io[Model Context Protocol specification, window=_blank]. +* For implementation details, see the link:https://github.com/thoughtspot/mcp-server[MCP Server GitHub repository, window=_blank]. diff --git a/modules/ROOT/pages/mcp-server-changelog.adoc b/modules/ROOT/pages/mcp-server-changelog.adoc new file mode 100644 index 000000000..ce53f8fe9 --- /dev/null +++ b/modules/ROOT/pages/mcp-server-changelog.adoc @@ -0,0 +1,110 @@ += ThoughtSpot MCP Server changelog +:toc: true +:toclevels: 2 + +:page-title: MCP Server Changelog +:page-pageid: mcp-server-changelog +:page-description: Release history for the ThoughtSpot MCP Server, including new tools, breaking changes, deprecations, and bug fixes. +:keywords: MCP Server, changelog, release notes, api-version, breaking changes, deprecation + +This changelog lists the new features, enhancements, and other changes introduced in the released versions of the ThoughtSpot MCP Server. For information about MCP Server integration, see the xref:mcp-integration.adoc[MCP Server integration guide]. + +// ============================================================ +// VERSION TEMPLATE — copy this block for each new release +// ============================================================ +// +// == YYYY-MM-DD +// [.version-badge.breaking]#Breaking# / +// [.version-badge.new]#New# / +// [.version-badge.deprecated]#Deprecated# / +// [.version-badge.fixed]#Fixed# +// +// *API version string:* `?api-version=YYYY-MM-DD` +// *Status:* Current / Supported / Deprecated +// *Affects:* Developers, Administrators, End Users +// ============================================================ + + +== May 2026 + +*API version string:* `?api-version=2026-05-01`. + +*Upgrade notes*: Recommended for new integrations. Introduces breaking changes to existing MCP Server integrations. See the xref:mcp-server-changelog.adoc#_migration_guidelines[migration guidelines]. + +[.cl-table, cols="1,4", frame=none, grid=none] +|==== +a| +[.cl-label] +*2026-05-01* + +a| + +[discrete] +==== Support for Spotter 3 +ThoughtSpot MCP Server now supports Spotter 3, enabling advanced analytics, forecasting, multi-step reasoning, and deep research. The new MCP tools support real-time streaming, session-based conversations, richer interactions, and direct embedding of visualizations in MCP-aware apps. + +For more information, see xref:mcp-server-spotter3.adoc[MCP Server with Spotter 3]. + +--- + +[discrete] +==== MCP Server URL changes and API versioning [.version-badge.breaking]#Breaking# +MCP Server URLs now support date-based versioning, defined using the `?api-version=YYYY-MM-DD` parameter. Ensure that you update the xref:mcp-integration.adoc#_mcp_server_url[MCP Server URL] in your integrations as needed. + +[NOTE] +==== +* The MCP Server URLs without the API version always point to the latest version and may introduce new tools. Pin your integration to a tested version using the `?api-version={YYYY-MM-DD}` parameter. For example, `?api-version=2026-05-01`. +* If the API version is set to a future date, the server returns the latest API version released before the date specified in the URL. +==== + +--- + +[discrete] +==== MCP tools and processing model [.version-badge.breaking]#Breaking# +The MCP Server URL now points to the Spotter 3-powered MCP tools. With this enhancement, the legacy tools in your existing integrations will be replaced with new tools. If your app uses custom workflows, you must update your integrations to use the new MCP tools or pin a previous version using the `?api-version={YYYY-MM-DD}` parameter in the URL to preserve your existing changes. + +===== Migration guidelines +Migrating from your existing setup to the new version requires updating the MCP client configuration to point to the new URL and rewriting tool-calling logic to use the new asynchronous, polling model. + +To update your integration to use Spotter 3 features and the new MCP tools: + +. Rewrite your integration to use the new tools. Replace the old synchronous tool-calling pattern with the new asynchronous polling pattern. For code samples and tool reference, see the xref:mcp-tool-reference-guide.adoc[MCP tool reference guide]. +. Configure the URL that points to the new MCP tools. +. Test your integration end-to-end. +. Roll out to production environments after validation. +|==== + +== April 2026 +*API version string:* `?api-version=2026-04-30` or an earlier date string + +*Upgrade recommendation*: Supports the legacy MCP tools and URLs only. Upgrade your integrations to version 2026-04-30 or later. + +[.cl-table, cols="1,4", frame=none, grid=none] +|==== +a| +[.cl-label] +*2026-04-30* + +a| + +[discrete] +==== MCP tools, processing model, and answer retrieval +Supports the following MCP tools released in the initial version of ThoughtSpot MCP Server. + +* `ping`: Tests connectivity and authentication. +* `getDataSourceSuggestions`: Returns available data source suggestions +for a given query. +* `getRelevantQuestions`: Breaks a query into sub-questions. Returns answers synchronously. +* `getAnswer`: Returns the answer to a specific sub-question. +* `createLiveboard`: Creates a ThoughtSpot Liveboard from a list of answers. + +--- + +[discrete] +==== MCP Server URLs +Supports the following URLs: + +* `\https://agent.thoughtspot.app/mcp` (OAuth Apps) +* `\https://agent.thoughtspot.app/bearer/mcp` (Bearer Token Apps) +* `\https://agent.thoughtspot.app/openai/mcp` (OpenAI-compatible clients) + +These URLs are deprecated as of the MCP Server 2026-05-01 release. See the xref:mcp-server-changelog.adoc#_mcp_server_url_changes_and_api_versioning[changelog] for more information. + +|==== diff --git a/modules/ROOT/pages/mcp-server-client-connection.adoc b/modules/ROOT/pages/mcp-server-client-connection.adoc index 94dcb6281..748c30855 100644 --- a/modules/ROOT/pages/mcp-server-client-connection.adoc +++ b/modules/ROOT/pages/mcp-server-client-connection.adoc @@ -17,32 +17,63 @@ When your MCP client is connected to the ThoughtSpot MCP Server, the AI agent/LL * Create a Liveboard with the visualizations generated during the interaction. +//// [IMPORTANT] ==== * Currently, the MCP Server integration does not support link:https://docs.thoughtspot.com/cloud/latest/spotter-versions[Spotter 3 capabilities]. * In the plug-and-play integration mode, embedding visualizations is not supported. ==== +//// == Before you begin Before you begin, review the following prerequisites: -* Ensure that your setup has access to a ThoughtSpot application instance with 10.11.0.cl or a later release version. +* Ensure that your setup has access to a ThoughtSpot application instance with 10.11.0.cl or a later release. For MCP Server with Spotter 3 capabilities, ensure that your ThoughtSpot instance is 26.2.0.cl or later. * Ensure that the users have the necessary permissions to view data from relevant models and tables in ThoughtSpot. Existing RLS/CLS rules on tables are enforced automatically in data source responses. To create charts or Liveboards from a conversation session, data download and content creation privileges are required. === Connecting clients that support remote MCP servers -To connect to a client that supports remote MCP servers natively, add the MCP Server endpoint to your client's configuration settings. +To connect a client that supports remote MCP servers natively, add the MCP Server endpoint to your client's configuration settings. -`\https://agent.thoughtspot.app/mcp` +For OAuth clients, the following options are available: -For clients that require a bearer token for authentication, use the following URL format: +* `\https://agent.thoughtspot.app/mcp?api-version=latest` + +This URL always points to the latest version. -`\https://agent.thoughtspot.app/bearer/mcp` +* `\https://agent.thoughtspot.app/mcp` ++ +[NOTE] +==== +Currently, this URL points to the baseline version with legacy MCP tools. It will resolve to the latest version in the near future. During this period, you can switch to `\https://agent.thoughtspot.app/mcp?api-version=latest` to access the latest MCP tools. +==== + +* `\https://agent.thoughtspot.app/mcp?api-version={YYYY-MM-DD}` + +If you want to pin a specific version, use this URL format. + + +[IMPORTANT] +==== +The `\https://agent.thoughtspot.app/openai/mcp` is deprecated and not recommended for use in OpenAI integrations. +==== +//// +For bearer token clients:: +For clients that require a bearer token for authentication, use the following URL: ++ +`\https://agent.thoughtspot.app/token/mcp` (Recommended) + +This URL always points to the version with the latest tools. -For OpenAI MCP and Responses API integration, use the following URL: ++ +If you want to use a version released on or before a specific date, use the URL with the date parameter: + +`\https://agent.thoughtspot.app/token/mcp?api-version={YYYY-MM-DD}` -`\https://agent.thoughtspot.app/openai/mcp` -For additional information about how to register a remote MCP Server, refer to your client's documentation. +For OpenAI MCP and Responses API:: +Use the following URL: ++ +`\https://agent.thoughtspot.app/token/mcp?api-version={YYYY-MM-DD}` ++ +//// + +For more information about how to register a remote MCP Server, see your client's documentation. === Connecting MCP Server to local MCP clients For MCP clients that do not natively support configuring a remote MCP Server URL, you must use the `mcp-remote` component. For desktop clients that rely on local MCP components, ensure that Node.js version 22 or later is installed on your system. @@ -55,7 +86,7 @@ For MCP clients that do not natively support configuring a remote MCP Server URL "command": "npx", "args": [ "mcp-remote", - "https://agent.thoughtspot.app/mcp" + "https://agent.thoughtspot.app/mcp?api-version={YYYY-MM-DD}" // replace YYYY-MM-DD with an actual date string ] } } @@ -87,14 +118,14 @@ After the MCP Server is connected, some clients show *ThoughtSpot Data Sources* To verify the integration: . Start a chat session with the agent and verify the response. -. Verify that xref:mcp-integration.adoc#_mcp_tools_and_resources[MCP tools are being called] to generate responses. -. Prompt the agent to create a Liveboard from a query response and verify whether a Liveboard is added to your ThoughtSpot application. +. Verify that MCP tools are being called to generate responses. See the xref:mcp-tool-reference-guide.adoc[MCP tool reference guide] for information about tool calls. +. Try the Liveboard creation request and verify whether a Liveboard is added to your ThoughtSpot application. == Troubleshooting errors MCP Server is not connected:: -* Verify if the MCP Server is reachable. +* Verify that the MCP Server is reachable. * Ensure that you have access to a ThoughtSpot instance. * Ensure that there are no configuration errors. * If the issue persists, verify the logs and contact ThoughtSpot Support for assistance. @@ -102,7 +133,7 @@ MCP Server is not connected:: Authentication failure:: If user authentication fails, or if the server returns HTTP 500, 401, or 403 status codes: * Verify whether the MCP Server endpoint and ThoughtSpot host are correctly configured in your client and are reachable. -* Verify if the user session has expired. Log in to your ThoughtSpot application to start a new session. +* Check whether the user session has expired. Log in to your ThoughtSpot application to start a new session. * Verify whether the user has the necessary privileges to view data or create content. == Additional resources diff --git a/modules/ROOT/pages/mcp-server-legacy.adoc b/modules/ROOT/pages/mcp-server-legacy.adoc new file mode 100644 index 000000000..d10e0fbfd --- /dev/null +++ b/modules/ROOT/pages/mcp-server-legacy.adoc @@ -0,0 +1,61 @@ += Legacy MCP Server architecture and tools +:toc: true +:toclevels: 3 + +:page-title: Legacy MCP Server architecture and tools +:page-pageid: mcp-server-legacy +:page-description: Learn about the legacy MCP Server architecture and how it fits into your AI and analytics architecture. + +The legacy MCP server setup uses synchronous architecture. It does not support advanced analytics, session context retention, automatic data source selection, streaming responses, and the full answer is always returned inline. All context and data source management must be handled by the client on every request. + +Functional capabilities:: +Limited capabilities for complex analysis and context integration. +When to use:: +It is recommended only for maintaining existing integrations, not for new development or advanced use cases. +Integration pattern and session model:: +The integration pattern is synchronous and stateless. Each tool call is independent and there is no persistent session. Any required context must be manually injected with every follow-up call, as the server does not retain context between requests. + +Data source selection:: +Data source suggestions are not built-in. A separate tool call (`getDataSourceSuggestions`) is required to retrieve possible data sources for each query. + +Response delivery:: +The server returns the full response in a single, synchronous call. There is no support for streaming or incremental updates. + +Follow-up questions:: +Every follow-up call requires the prior context to be manually included, as the server does not maintain conversational state. + +[.widthAuto] +image::./images/mcp-architecture-legacy.png[MCP architecture legacy] + +== Tool calls and workflow processing +The workflow in the legacy MCP Server setup typically includes the following stages: + +. *User asks a question* + +A user sends a query in the chat interface to get data. For example, `What were the total sales of Jackets and Bags in the Northeast last year?` + +Optionally, the user can specify the data context to generate a response. + +. *Agent calls `getDataSourceSuggestions` (optional)* + +If the user’s question doesn’t specify a data source, the agent can call `getDataSourceSuggestions` to retrieve a list of relevant ThoughtSpot data sources. +ThoughtSpot returns candidate data sources (models) with confidence scores and reasoning. + +. *User's query is decomposed into sub-questions* + +To break the user’s query into sub-questions, the agent calls `getRelevantQuestions`. ThoughtSpot returns the AI-suggested, schema-aware questions that are easier to execute analytically. + +. *The query is processed for generating answers* + +For each suggested or chosen question, the agent calls `getAnswer`. ThoughtSpot returns the following: + +* Preview data for LLM reasoning. +* Visualization metadata, including an embeddable `frame_url`. +* `session_identifier` and `generation_number` for charts that are used as input for creating a Liveboard. + +. *A Liveboard is generated from the results* (optional) + +To save answers from the conversation sessions in a ThoughtSpot Liveboard, the agent extracts the `question`, `session_identifier`, and `generation_number` from each `getAnswer` response and calls `createLiveboard`. + +ThoughtSpot creates a persistent Liveboard from the session's answers and returns identifiers and a `frame_url` for the Liveboard. + +In the legacy MCP Server setup, to ask a follow-up question, the agent calls the `getRelevantQuestions` again, because the server doesn't retain context. For follow-up questions, the agent must pass the context explicitly via `additionalContext`. + +For more information about the tool calls, input parameters, and response output, see xref:mcp-tool-reference-guide.adoc#_legacy_mcp_server_setup[MCP tool reference guide]. + + +== Additional resources +* For information about MCP, see the link:https://modelcontextprotocol.io[Model Context Protocol specification, window=_blank]. +* For implementation details, see the link:https://github.com/thoughtspot/mcp-server[MCP Server GitHub repository, window=_blank]. diff --git a/modules/ROOT/pages/mcp-server-spotter3.adoc b/modules/ROOT/pages/mcp-server-spotter3.adoc new file mode 100644 index 000000000..aaa0ae0d7 --- /dev/null +++ b/modules/ROOT/pages/mcp-server-spotter3.adoc @@ -0,0 +1,94 @@ += MCP Server with Spotter 3 capabilities +:toc: true +:toclevels: 3 + +:page-title: MCP Server with Spotter 3 capabilities +:page-pageid: mcp-server-spotter3 +:page-description: Learn about the MCP Server with Spotter 3 capabilities, including advanced analytics, streaming responses, and session-based conversations. + +ThoughtSpot MCP Server supports link:https://docs.thoughtspot.com/cloud/latest/spotter-versions[Spotter 3, window=_blank], which enables advanced analytics, forecasting, multi-step reasoning and analysis, and deep research capabilities. +The MCP Server with Spotter 3 introduces new MCP tools, real-time streaming responses, session-based conversations, and richer interactions. + +[cols="2,4,4", options="header"] +|==== +||Legacy MCP Server setup|MCP Server with Spotter 3 +|**Functional differences** +|Limited capabilities for complex analysis and context integration. +a|* Supports advanced analytics, forecasting, and deep research capabilities. +* Supports asynchronous streaming, session-based conversations, and context integration. + +|**Recommended for** +|Maintaining existing integrations only. +|All new integrations + +|**Integration pattern + +Session model + +Response processing** +|Synchronous and stateless integration pattern. Each tool call is independent. Does not support persistent sessions and requires prior context to be injected manually on every follow-up call. + +|Asynchronous and stateful sessions. Allows multiple follow-up questions within a session. Responses are streamed with intermediate updates, including thinking narration and clarifications. Context is retained automatically across all follow-up questions within the session. + +|**Data source selection** +|Requires a separate tool call (`getDataSourceSuggestions`) to retrieve source suggestions. +|Built into session creation. If the `data_source_id` is not explicitly specified in the query, the most relevant source is automatically selected based on the user's query. + +|**Response delivery** +|Returns full response in a single synchronous call. +|Responses are streamed incrementally; updates are accumulated via polling. + +|**Follow-up questions** +|Requires prior context on every follow-up call. +|The session retains context automatically. + +Optionally, the `additional_context` parameter can be included to inject new external context for each follow-up question or message. + +|**API versioning support** +|Not available. +|Supports date-based API versioning, which is identified in the MCP Server URL as `?api-version=YYYY-MM-DD`. +|| +|==== + +The following figure illustrates the MCP architecture, tool calls, and workflow in the new MCP Server version: + +[.widthAuto] +image::./images/mcp-architecture-new.png[MCP architecture new] + +== Tool calls and workflow processing +The workflow in the MCP Server with Spotter 3 typically includes the following stages: + +1. *User asks a question* + +A user sends a query in the chat interface to get data insights. For +example, _What were the total sales of Jackets and Bags in the Northeast +last year?_ + +2. *Agent calls `create_analysis_session`* + +The agent calls `create_analysis_session` to establish a stateful analytical session with ThoughtSpot's Spotter 3 engine. ThoughtSpot returns an `analytical_session_id` that identifies the session for all subsequent calls. + +If the user specified a data source, the agent passes it as the optional `data_source_id` parameter. If not specified, ThoughtSpot automatically selects the most relevant data source based on the question. + +3. *Agent calls `send_session_message`* + +The agent calls `send_session_message` with the `analytical_session_id` and the user's question. Optionally, the agent can pass `additional_context` to provide external information that should influence the analysis. For example, `The user's fiscal year starts in April` or `The user is a manager of the West region`. + +ThoughtSpot confirms receipt with a `success` response and begins processing the question asynchronously. The answer is not returned in this call. + +4. *Agent polls `get_session_updates` for results* + +The agent calls `get_session_updates` repeatedly in a loop until `is_done` is `true`. ThoughtSpot streams updates incrementally across multiple polls. The agent must accumulate updates from every poll. ThoughtSpot returns the following update types: + +* `text-chunk` - real-time thinking narration from Spotter describing what it is doing, streamed in fragments. Concatenate chunks in order to form the complete narration. +* `text` - complete standalone messages representing clarifications, caveats, or assumptions Spotter made during analysis. +* `answer` - a final analytical result containing: +** `answer_title` - a human-readable description of what the answer shows. +** `answer_query` - the ThoughtSpot search query used to generate the answer. +** `iframe_url` - an embeddable URL for rendering an interactive ThoughtSpot visualization. +** `answer_id` - a unique identifier for the answer, used as input for creating a dashboard. + +5. *A dashboard is generated from the results (optional)* + +The user can choose to save answers from the conversation as a ThoughtSpot dashboard. For this workflow, the agent extracts the `answer_id` and `answer_title` from each `answer` type update collected during polling and calls `create_dashboard`. + +ThoughtSpot creates a dashboard and returns a `dashboard_id` and a +`dashboard_url`, a direct link to the dashboard in the ThoughtSpot UI. + +6. *User asks a follow-up question (optional)* + +The user can ask a follow-up question in the same session. The agent calls `send_session_message` again using the same `analytical_session_id`. ThoughtSpot retains the full conversation context automatically. The agent returns to step 4 to poll for the follow-up response. + +For more information about the tool calls, input parameters, and response output, see xref:mcp-tool-reference-spotter3.adoc[MCP tool reference (Spotter 3)]. + +== Additional resources +* For information about MCP, see the link:https://modelcontextprotocol.io[Model Context Protocol specification, window=_blank]. +* For implementation details, see the link:https://github.com/thoughtspot/mcp-server[MCP Server GitHub repository, window=_blank]. diff --git a/modules/ROOT/pages/mcp-tool-reference-guide.adoc b/modules/ROOT/pages/mcp-tool-reference-guide.adoc new file mode 100644 index 000000000..c9fb5b1dc --- /dev/null +++ b/modules/ROOT/pages/mcp-tool-reference-guide.adoc @@ -0,0 +1,18 @@ += MCP tool reference +:toc: true +:toclevels: 3 + +:page-title: ThoughtSpot MCP tool reference guide +:page-pageid: mcp-tool-reference +:page-description: Refer to this guide to learn which MCP tools are supported, input parameters used for tool calls, and the response format. + +ThoughtSpot MCP Server provides specialized tools that enable the AI agent in your application to access ThoughtSpot analytics. This page lists all supported MCP tools and describes how to call these tools and analyze responses. Refer to the following sections for more information: + +* xref:mcp-tool-reference-spotter3.adoc[MCP Server version with Spotter 3] [.version-badge.new]#New# +* xref:mcp-tool-reference-legacy.adoc[MCP Server with legacy tools] + +== Additional resources + +* To view the MCP Server code, see the link:https://github.com/thoughtspot/mcp-server[MCP Server GitHub repository, window=_blank]. +* For a chat client example, see link:https://github.com/thoughtspot/developer-examples/tree/main/mcp/python-react-agent-simple-ui[Python Agent with Simple React UI]. +* See xref:mcp-connect-custom-chatbot.adoc[Integrating MCP Server in a custom application or chatbot] diff --git a/modules/ROOT/pages/mcp-tool-reference-legacy.adoc b/modules/ROOT/pages/mcp-tool-reference-legacy.adoc new file mode 100644 index 000000000..f2a98be63 --- /dev/null +++ b/modules/ROOT/pages/mcp-tool-reference-legacy.adoc @@ -0,0 +1,173 @@ += MCP tool reference (legacy version) +:toc: true +:toclevels: 3 + +:page-title: ThoughtSpot MCP tool reference guide +:page-pageid: mcp-tool-reference-legacy +:page-description: Refer to this guide to learn which MCP tools are supported, input parameters used for tool calls, and the response format. + +This reference guide lists the legacy MCP tools supported by the MCP Server in versions prior to 2026-05-01 and describes the MCP request input schema and data structure of the response. + +== ping +Runs a basic health check to validate that the MCP Server is reachable. + +[source,typescript] +---- +const tsPing = await callMCPTool("ping", {}); +---- + +== getDataSourceSuggestions +Suggests appropriate ThoughtSpot data models for a given natural language question. + +=== Example call + +[source,typescript] +---- +const dsSuggestions = await callMCPTool("getDataSourceSuggestions", { + query: "show me sales by region" // user's query +}); +---- + +=== Response + +Returns an object containing an array of suggestions: + +[source,json] +---- +{ + "suggestions": [ + { + "header": { + "guid": "worksheet-guid-123", + "displayName": "Sales Analytics", + "description": "Sales performance by region, product, and channel" + }, + "confidence": 0.92, + "llmReasoning": "This worksheet contains sales metrics and regional dimensions relevant to the query." + } + ] +} +---- + +Key fields are: + +* `header.guid`: Unique ID for the datasource. The `datasourceId` is used in `getRelevantQuestions` and `getAnswer` calls. +* `header.displayName`: Name of the data source. +* `header.description`: Optional description of the data source. +* `confidence`: Numeric score indicating the confidence of the system about a data model being the right match for the user’s query. +* `llmReasoning`: LLM's reasoning for the suggestion. + +== getRelevantQuestions +Uses ThoughtSpot’s reasoning engine to generate AI-suggested sub-queries that help generate specific answers for a given data context. + +=== Example call + +[source,typescript] +---- +const result = await callMCPTool("getRelevantQuestions", { + query: "show me sales data", // User's natural language query + datasourceIds: ["model-guid-123"], // Array of worksheet/datasource GUIDs + additionalContext: "User is interested in the data for underperforming regions and products" +}); +---- + +=== Response + +[source,json] +---- +{ + "questions": [ + "What is the total sales revenue by region?", + "Which products have the highest revenue?", + "What are the top selling categories?" + ] +} +---- + +Each returned question can then be passed individually into `getAnswer`. + +== getAnswer +Executes a natural language query for a given data context and returns the resulting data and visualization metadata. Clients can use this data and frame URL to render visualizations. + +=== Example call + +[source,typescript] +---- +const result = await callMCPTool("getAnswer", { + question: "Total sales by region", // Natural language question + datasourceId: "model-guid-123" // Worksheet/datasource GUID +}); +---- + +=== Response + +[source,json] +---- +{ + "question": "Total sales by region", + "session_identifier": "abc-123-def-456", + "generation_number": 2, + "data": "\"Region\",\"Total Sales\"\n\"East\",100000\n...", + "frame_url": "https://...", + "fields_info": "..." +} +---- + +Key fields are: + +* `session_identifier`: Unique session ID used to group answers. Required when creating a Liveboard from this answer using the `createLiveboard` MCP tool. +* `generation_number`: Version number for this answer. Required for Liveboard creation. +* `question`: The executed question; useful for display and to pass it into the `createLiveboard` request. +* `data`: Data returned in encoded format. Contains column headers and all returned rows in comma-separated format, which can be parsed to render tables or charts in your application. +* `frame_url`: Optional iframe URL for embedding the visualization in your UI. +* `fields_info`: Descriptive metadata about the fields and chart, useful for explanations. + +== createLiveboard + +Creates a ThoughtSpot Liveboard with one or more answers from the results. This is a two-step process and includes the following calls: + +. Call `getAnswer` to generate visualizations and obtain `session_identifier` and `generation_number`. +. Call `createLiveboard` with those values to create the Liveboard. + +=== Example call + +[source,typescript] +---- +const answerData = JSON.parse(answerResult.result.content); + +const liveboardResult = await callMCPTool("createLiveboard", { + name: "My Sales Dashboard", + noteTile: "My Sales Dashboard was created by TS MCP Chat", // Description text for the Liveboard + answers: [{ + question: answerData.question, // Display name for the Liveboard + session_identifier: answerData.session_identifier, + generation_number: answerData.generation_number + }] +}); +---- + +Required attributes are: + +* `noteTile`: Use this field for any Liveboard description or notes; a separate description field is not supported. +* `answers`: Required array. Each item must include `question`, `session_identifier`, and `generation_number` from a prior `getAnswer` call. + +=== Response + +[source,json] +---- +{ + "liveboardId": "liveboard-guid-here", + "name": "My Sales Dashboard", + "frame_url": "https://..." +} +---- + +Key fields are: + +* `liveboardId`: GUID of the created Liveboard. +* `name`: Name of the Liveboard. +* `frame_url`: URL that can be embedded to display the Liveboard. + + + + diff --git a/modules/ROOT/pages/mcp-tool-reference-spotter3.adoc b/modules/ROOT/pages/mcp-tool-reference-spotter3.adoc new file mode 100644 index 000000000..997c9905b --- /dev/null +++ b/modules/ROOT/pages/mcp-tool-reference-spotter3.adoc @@ -0,0 +1,368 @@ += MCP tool reference (Spotter 3) +:toc: true +:toclevels: 3 + +:page-title: ThoughtSpot MCP tool reference guide +:page-pageid: mcp-tool-reference-spotter3 +:page-description: Refer to this guide to learn which MCP tools are supported, input parameters used for tool calls, and the response format. + +The new ThoughtSpot MCP integration exposes a session-based workflow for running natural language analytics queries against your ThoughtSpot data sources. The pattern is always: **create a session** → **send a message** → **poll for updates**. + +== create_analysis_session +Start an analytical session with ThoughtSpot's analytics agent. This is the required first step before sending any questions. + +Sessions are conversational. Once created, you can send multiple follow-up questions to the same session without calling `create_analysis_session` again. + +=== Input parameter +The `data_source_id` is optional. Provide this when the user has specified or confirmed a data source, or when context makes a particular source obvious. Omit to let ThoughtSpot automatically select the most relevant source based on the question. + +=== Example call + +[div tabbed-code] +-- +[source,javascript] +---- +const session = await callMCPTool("create_analysis_session", { + data_source_id: "model-guid-123" // Optional — GUID of the ThoughtSpot worksheet or model to query. Omit to let ThoughtSpot automatically select the most relevant data source. +}); +---- + +[source,python] +---- +call_mcp_tool( + "create_analysis_session", + { + "data_source_id": "model-guid-123" # Optional — GUID of the ThoughtSpot worksheet or model to query. + }, +) +---- +-- + +=== Response + +[source,json] +---- +{ +"analytical_session_id": "session-guid-abc123" +} +---- + +* `analytical_session_id`: Session ID. Pass this to `send_session_message` and `get_session_updates`. + +* Always capture the returned `analytical_session_id`. It is required for all subsequent calls. + +== send_session_message +Send a natural language analytical question or follow-up to an existing session. The agent processes requests asynchronously, so this tool does not return the answer directly; use `get_session_updates` to retrieve the response. + +=== Input parameters + +[cols="2,4", options="header"] +|==== +|Field|Description + +|`analytical_session_id` | The session to send the message to. Obtained from the `create_analysis_session` call. +|`message`|A natural language analytical question or follow-up to send to the ThoughtSpot agent. +|`additional_context` + +__Optional__|Can be used to provide external information relating to the question. For example, “The user’s fiscal year starts in April”, or “The user is a manager of the West region”. +|==== + +=== Example call + +[div tabbed-code] +-- +[source,javascript] +---- +const sendMessage = await callMCPTool("send_session_message", { + analytical_session_id: "sess_abc123", // Session ID from create_analysis_session. + message: "What were total sales by region last quarter?", // User's natural language question. + additional_context: "The user's fiscal year starts in April. " + + "Focus on underperforming regions only." // Optional — external information to influence the analysis. +}); +---- + +[source,python] +---- +call_mcp_tool( + "send_session_message", + { + "analytical_session_id": "sess_abc123", # Session ID from create_analysis_session. + "message": "What were total sales by region last quarter?", # User's natural language question. + "additional_context": ( # Optional — external information + "The user's fiscal year starts in April." + "Focus on underperforming regions only." # to influence the analysis. + ), + }, +) +---- +-- + +=== Response + +[source,json] +---- +{ + "success": true +} +---- + +* `success`: Confirms whether the message was successfully received by the agent. + +[NOTE] +==== +* After a successful send, immediately begin polling with `get_session_updates`. +* Do not send a second message until `get_session_updates` returns `is_done: true`. The agent processes one message at a time per session. +* To ask a follow-up question, reuse the same `analytical_session_id`. There is no need to create a new session. +==== + +== get_session_updates + +Poll for the latest response from a ThoughtSpot analytics session. Call this repeatedly after `send_session_message` until `is_done` is `true`. + +**Important**: A single call to `get_session_updates` will rarely contain the full response. Spotter streams its work incrementally, including intermediate thinking steps, across multiple polling calls. You must accumulate updates from every poll and combine them to get the complete picture. + +=== Input parameters +Send the `analytical_session_id` to specify the session to retrieve updates for. + +=== Example call + +[div tabbed-code] +-- +[source,typescript] +---- +const updates = await callMCPTool("get_session_updates", { + analytical_session_id: "session-guid-abc123" // Session ID from the `create_analysis_session` call. +}); +---- + +[source,python] +---- +call_mcp_tool( + "get_session_updates", + {"analytical_session_id": "sess_abc123"}, # Session ID from create_analysis_session. +) +---- +-- + +=== Response + +Poll returning intermediate updates with the "is_thinking" response: + +[source,json] +---- +{ + "is_done": false, + "session_updates": [ + { + "is_thinking":true, + "type":"text_chunk", + "text":"Let me look at your sales data by region...", + }, + ] +} +---- + +Poll returning final updates: + +[source,json] +---- +{ + "is_done": true, + "session_updates":[ + { + "is_thinking":false, + "type":"text-chunk", + "text":"Data broken down by region..." + }, + { + "is_thinking":false, + "type":"text", + "text":"I'm interpreting 'last quarter' as Q4 2025 (October–December), based on a fiscal year starting in April." + }, + { + "is_thinking":false, + "type":"answer", + "answer_title":"Total Sales by Region — Q4 2025", + "answer_query":"total sales by region last quarter", + "iframe_url":"https://your-instance.thoughtspot.cloud/embed/...", + "answer_id":"answer-guid-xyz789" + } + ] +} +---- + +=== Handling streamed responses +Spotter queries are processed asynchronously and streamed in real time. This means the full response is never contained in a single `get_session_updates` call. + +Each call to `get_session_updates` returns only the updates generated since the previous call. The `session_updates` array may indicate that Spotter is still processing with an `is_thinking` state, may include intermediate updates, or may contain several updates at once. Updates typically arrive as text or text-chunk types, reflecting Spotter’s ongoing reasoning, before the final answer update is provided. This intermediate content shows Spotter’s step-by-step thought process and should be preserved and presented to the user for transparency into how the answer is derived. + +A typical response sequence might look like: + +. Thinking narration: `text-chunk` updates with `is_thinking` state describing what Spotter is doing. +. Clarifications or caveats: `text` updates explaining assumptions, filters applied, or potential ambiguities in the question. +. Intermediate conclusions: partial results or contextual notes before the final answer. +. The final answer: one or more `answer` updates containing the visualization title, the underlying query, and the embeddable iframe URL. + +This means a complete response might span between 5–20+ `get_session_updates` calls and contain many `session_update` objects before `is_done` becomes `true`. All of this content — the thinking, the narration, and the final answer — should be accumulated and presented together to give the user the full picture. + +=== Type definition: session_update + +Each item in the `session_updates` list is a `session_update` object. The `type` field determines which other fields are present. + +[cols="2,2,4", options="header"] +|==== +|Field|Type|Description +.3+|`type` +|`"text"`|A complete natural language message from the agent. +|`"text-chunk"` | A streaming chunk of a longer message. Concatenate all chunks to reconstruct the full text. +|`"answer"`|Populates `answer_title`, `answer_query`, `iframe_url` fields. A data visualization result with a title, the underlying query, and an embeddable URL. +|`text`|__String__|The text content of the message. Present only when `type` is `"text"` or `"text-chunk"`. For `"text-chunk"` updates, concatenate all chunks in order to form the complete message. +|`answer_title`|__String__|A human-readable title describing what the answer shows. Present only when `type` is `"answer"`. +|`answer_query`|__String__|The search query ThoughtSpot used to generate the answer. Present only when `type` is `"answer"`. Useful for explaining to users what data was queried or for diagnosing unexpected results. +|`iframe_url`|__String__|An embeddable URL for rendering the answer as an interactive visualization. Present only when `type` is `"answer"`. Use this to display a live chart or table if your environment supports iframes. +|==== + + +== create_dashboard + +Create a ThoughtSpot dashboard from answers generated in an analysis session. + +* Call this only after `get_session_updates` returns `is_done: true`, because you need the `answer_id` values from completed answer updates. +* Collect all updates where type is answer across every poll of `get_session_updates`. Each one produces an `answer_id` you can include in the dashboard. +* The `note_tile` should summarize the full analysis. It is the first thing a viewer sees on the dashboard. +* Multiple answers from the same session or across multiple sessions can be combined into a single dashboard. + +=== Input parameters + +[cols="2,4", options="header"] +|==== +|Field|Description + +|`title` |Required. Title of the dashboard to be created. +|`answers`|Required. List of answer objects to add to the dashboard. Each answer requires an `answer_id` (from `get_session_updates` where `type` is `answer`) and a `title`. +|`note_tile`| Required. An HTML summary of the analysis and answers, rendered as a styled tile on the dashboard. Must be a single line with no line breaks. Use `
` for spacing within the HTML. Include emojis, colors, and a `"Generated on