@tableau/mcp-server 2.21.1 → 2.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Public, dependency-free provider contract for telemetry.
3
+ *
4
+ * This module is exposed as a package subpath (`@tableau/mcp-server/telemetry/telemetryProvider`)
5
+ * so external deployments can implement a custom telemetry provider against a stable type,
6
+ * without importing the server's internal config schemas or zod. Keep it free of runtime dependencies.
7
+ *
8
+ * `TelemetryAttributes` is hand-written here to avoid runtime dependencies.
9
+ */
10
+ /**
11
+ * Attributes/dimensions attached to a telemetry metric.
12
+ * Values can be strings, numbers, booleans, or undefined.
13
+ */
14
+ export type TelemetryAttributes = Record<string, string | number | boolean | undefined>;
15
+ /**
16
+ * Telemetry provider interface for metrics collection.
17
+ */
18
+ export interface TelemetryProvider {
19
+ /**
20
+ * Initialize the telemetry provider.
21
+ */
22
+ initialize(): void;
23
+ /**
24
+ * Record a custom metric with the given name and attributes.
25
+ *
26
+ * @param name - The metric name (e.g., 'apm_mcp_tool_calls')
27
+ * @param value - The metric value (default: 1 for counters)
28
+ * @param attributes - Dimensions/tags for the metric
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * telemetry.recordMetric('apm_mcp_tool_calls', 1, {
33
+ * tool_name: 'list-pulse-metric-subscriptions',
34
+ * });
35
+ * ```
36
+ */
37
+ recordMetric(name: string, value: number, attributes: TelemetryAttributes): void;
38
+ /**
39
+ * Record a histogram observation (e.g., latency) with the given name and attributes.
40
+ *
41
+ * @param name - The metric name (e.g., 'http_server_request_duration')
42
+ * @param value - The observed value (e.g., duration in milliseconds)
43
+ * @param attributes - Dimensions/tags for the metric
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * telemetry.recordHistogram('apm_mcp_tool_duration', 142.5, {
48
+ * tool_name: 'get-datasource-metadata',
49
+ * success: true,
50
+ * });
51
+ * ```
52
+ */
53
+ recordHistogram(name: string, value: number, attributes: TelemetryAttributes): void;
54
+ }
@@ -1,3 +1,3 @@
1
- "use strict";var Ke=Object.create;var J=Object.defineProperty;var Ge=Object.getOwnPropertyDescriptor;var Ye=Object.getOwnPropertyNames;var je=Object.getPrototypeOf,Be=Object.prototype.hasOwnProperty;var Fe=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Ye(t))!Be.call(e,i)&&i!==r&&J(e,i,{get:()=>t[i],enumerable:!(o=Ge(t,i))||o.enumerable});return e};var We=(e,t,r)=>(r=e!=null?Ke(je(e)):{},Fe(t||!e||!e.__esModule?J(r,"default",{value:e,enumerable:!0}):r,e));var ie=We(require("dotenv"));var re=require("path");var h=require("fs");var Z=require("path");var Je;var $=()=>Je;var $e=["debug","info","notice","warning","error","critical","alert","emergency"],E=Object.fromEntries($e.map((e,t)=>[e,t]));function ze(e,t){return E[e]>=E[t]}function qe(e){return e in E}function z(e){let t=e?.trim();return t&&qe(t)?t:"info"}function Qe(e){return e instanceof Error?{name:e.name,message:e.message,stack:e.stack,...e.cause!==void 0&&{cause:e.cause}}:e}function L(e){let t=q();if(ze(e.level,t.logLevel)){if(e.data=Qe(e.data),t.loggers.has("appLogger")){let r=JSON.stringify(e);t.transport==="http"?console.log(r):process.stderr.write(r+`
2
- `)}t.loggers.has("fileLogger")&&$()?.log(e)}}var Xe=["fileLogger","appLogger"],Ze=new Set(Xe);function Q(e){return e?new Set(e.split(",").map(t=>t.trim()).filter(t=>Ze.has(t))):new Set(["appLogger"])}var et=["stdio","http"];function _(e){return!!et.find(t=>t===e)}function X(){if(typeof __dirname=="string")return __dirname;throw new Error("__dirname is not set")}var l={fromSeconds:e=>e*1e3,fromMinutes:e=>e*60*1e3,fromHours:e=>e*60*60*1e3,fromDays:e=>e*24*60*60*1e3,fromWeeks:e=>e*7*24*60*60*1e3,fromMonths:e=>e*30*24*60*60*1e3,fromYears:e=>e*365.25*24*60*60*1e3};function a(e,{defaultValue:t,minValue:r,maxValue:o}={defaultValue:0,minValue:Number.NEGATIVE_INFINITY,maxValue:Number.POSITIVE_INFINITY}){if(!e)return t;let i=parseFloat(e);return isNaN(i)||r!==void 0&&i<r||o!==void 0&&i>o?t:i}var tt=X(),p=class{transport;defaultNotificationLevel;logLevel;loggers;fileLoggerDirectory;disableLogMasking;maxRequestTimeoutMs;notificationPayloadMaxBytes;constructor(){let t=R(process.env),{TRANSPORT:r,DEFAULT_NOTIFICATION_LEVEL:o,LOG_LEVEL:i,ENABLED_LOGGERS:m,FILE_LOGGER_DIRECTORY:f,DISABLE_LOG_MASKING:v,MAX_REQUEST_TIMEOUT_MS:S,NOTIFICATION_PAYLOAD_MAX_BYTES:A}=t;this.transport=_(r)?r:"stdio",this.defaultNotificationLevel=o??"debug",this.logLevel=z(i),this.loggers=Q(m),this.fileLoggerDirectory=f||(0,Z.join)(tt,"logs"),this.disableLogMasking=v==="true",this.maxRequestTimeoutMs=a(S,{defaultValue:l.fromMinutes(10),minValue:5e3,maxValue:l.fromHours(1)}),this.notificationPayloadMaxBytes=a(A,{defaultValue:8192,minValue:1})}};function R(e){return Object.entries(e).reduce((t,[r,o])=>(o?.startsWith("${user_config.")?t[r]="":t[r]=o,t),{})}var q=()=>new p;var n=require("zod"),Gt=n.z.record(n.z.string(),n.z.union([n.z.string(),n.z.number(),n.z.boolean(),n.z.undefined()])),rt=n.z.enum(["noop","custom"]),ot=n.z.object({provider:n.z.literal("noop")}),O=n.z.object({module:n.z.string({required_error:'Custom provider requires "module" path'})}).passthrough(),it=n.z.object({provider:n.z.literal("custom"),providerConfig:O}),Yt=n.z.discriminatedUnion("provider",[ot,it]);function ee(e){return rt.safeParse(e).success}function s(e,t){if(!e)throw new Error(t||"Invariant Violation")}var nt=["pat","uat","direct-trust","oauth"];function st(e){return nt.some(t=>t===e)}var C=class extends p{auth;server;sslKey;sslCert;httpPort;corsOriginConfig;siteName;patName;patValue;jwtUsername;connectedAppClientId;connectedAppSecretId;connectedAppSecretValue;uatTenantId;uatIssuer;uatUsernameClaimName;uatPrivateKey;uatKeyId;jwtAdditionalPayload;datasourceCredentials;disableSessionManagement;tableauServerVersionCheckIntervalInHours;passthroughAuthUserSessionCheckIntervalInMinutes;mcpSiteSettingsCheckIntervalInMinutes;enableMcpSiteSettings;allowSitesToConfigureRequestOverrides;enablePassthroughAuth;oauth;telemetry;latencyMetricName;productTelemetryEndpoint;productTelemetryEnabled;isHyperforce;breakGlassDisableGlobally;adminToolsEnabled;cspAllowedDomains;constructor(){super();let t=R(process.env),{AUTH:r,SERVER:o,SITE_NAME:i,TRANSPORT:m,SSL_KEY:f,SSL_CERT:v,HTTP_PORT_ENV_VAR_NAME:S,CORS_ORIGIN_CONFIG:A,PAT_NAME:w,PAT_VALUE:U,JWT_SUB_CLAIM:T,CONNECTED_APP_CLIENT_ID:N,CONNECTED_APP_SECRET_ID:M,CONNECTED_APP_SECRET_VALUE:D,UAT_TENANT_ID:V,UAT_ISSUER:x,UAT_USERNAME_CLAIM_NAME:ne,UAT_USERNAME_CLAIM:H,UAT_PRIVATE_KEY:y,UAT_PRIVATE_KEY_PATH:d,UAT_KEY_ID:se,JWT_ADDITIONAL_PAYLOAD:ae,DATASOURCE_CREDENTIALS:le,DISABLE_SESSION_MANAGEMENT:ue,TABLEAU_SERVER_VERSION_CHECK_INTERVAL_IN_HOURS:me,PASSTHROUGH_AUTH_USER_SESSION_CHECK_INTERVAL_IN_MINUTES:de,MCP_SITE_SETTINGS_CHECK_INTERVAL_IN_MINUTES:ce,ENABLE_MCP_SITE_SETTINGS:pe,ALLOW_SITES_TO_CONFIGURE_REQUEST_OVERRIDES:he,ENABLE_PASSTHROUGH_AUTH:Te,DANGEROUSLY_DISABLE_OAUTH:ge,OAUTH_EMBEDDED_AUTHZ_SERVER:Ee,OAUTH_ISSUER:g,OAUTH_LOCK_SITE:_e,OAUTH_JWE_PRIVATE_KEY:fe,OAUTH_JWE_PRIVATE_KEY_PATH:ve,OAUTH_JWE_PRIVATE_KEY_PASSPHRASE:Se,OAUTH_RESOURCE_URI:Ae,OAUTH_GLOBAL_RESOURCE_URIS:k,OAUTH_REDIRECT_URI:ye,OAUTH_CLIENT_ID_SECRET_PAIRS:I,OAUTH_CIMD_DNS_SERVERS:K,ADVERTISE_API_SCOPES:Ie,OAUTH_AUTHORIZATION_CODE_TIMEOUT_MS:be,OAUTH_ACCESS_TOKEN_TIMEOUT_MS:Pe,OAUTH_REFRESH_TOKEN_TIMEOUT_MS:Le,OAUTH_DISABLE_SCOPES:Re,TELEMETRY_PROVIDER:G,TELEMETRY_PROVIDER_CONFIG:Y,LATENCY_METRIC_NAME:Oe,PRODUCT_TELEMETRY_ENDPOINT:Ce,PRODUCT_TELEMETRY_ENABLED:we,IS_HYPERFORCE:Ue,BREAK_GLASS_DISABLE_GLOBALLY:Ne,ADMIN_TOOLS_ENABLED:Me,CSP_ALLOWED_DOMAINS:j}=t,b="";this.siteName=i??"",this.sslKey=f?.trim()??"",this.sslCert=v?.trim()??"",this.httpPort=a(t[S?.trim()||"PORT"],{defaultValue:3927,minValue:1,maxValue:65535}),this.corsOriginConfig=lt(A?.trim()??""),this.datasourceCredentials=le??"",this.disableSessionManagement=ue==="true",this.tableauServerVersionCheckIntervalInHours=a(me,{defaultValue:1,minValue:1,maxValue:168}),this.passthroughAuthUserSessionCheckIntervalInMinutes=a(de,{defaultValue:10,minValue:0,maxValue:1440}),this.mcpSiteSettingsCheckIntervalInMinutes=a(ce,{defaultValue:10,minValue:1,maxValue:1440}),this.enableMcpSiteSettings=pe!=="false",this.allowSitesToConfigureRequestOverrides=he==="true",this.enablePassthroughAuth=Te==="true";let P=ge==="true",De=!(Re==="true"),Ve=Ee!=="false";if(this.allowSitesToConfigureRequestOverrides&&!this.enableMcpSiteSettings)throw new Error('ALLOW_SITES_TO_CONFIGURE_REQUEST_OVERRIDES is "true", but MCP site settings are not enabled.');if(this.oauth={enabled:P?!1:!!g,embeddedAuthzServer:Ve,issuer:g??"",resourceUri:Ae??`http://127.0.0.1:${this.httpPort}`,globalResourceUris:k?k.split(",").map(u=>u.trim()).filter(Boolean):[],redirectUri:ye||(g?`${g}/Callback`:""),lockSite:_e!=="false",jwePrivateKey:fe??"",jwePrivateKeyPath:ve??"",jwePrivateKeyPassphrase:Se||void 0,dnsServers:K?K.split(",").map(u=>u.trim()):["1.1.1.1","1.0.0.1"],authzCodeTimeoutMs:a(be,{defaultValue:l.fromMinutes(10),minValue:0,maxValue:l.fromHours(1)}),accessTokenTimeoutMs:a(Pe,{defaultValue:l.fromHours(1),minValue:0,maxValue:l.fromDays(30)}),refreshTokenTimeoutMs:a(Le,{defaultValue:l.fromDays(30),minValue:0,maxValue:l.fromYears(1)}),clientIdSecretPairs:I?I.split(",").reduce((u,ke)=>{let[F,W]=ke.split(":");return F&&W&&(u[F]=W),u},{}):null,enforceScopes:De,advertiseApiScopes:Ie==="true"},this.oauth.clientIdSecretPairs&&Object.keys(this.oauth.clientIdSecretPairs).length===0)throw new Error(`OAUTH_CLIENT_ID_SECRET_PAIRS is in an invalid format: ${I}. Should be in the format: clientId:secret`);if((ee(G)?G:"noop")==="custom"){if(!Y)throw new Error('TELEMETRY_PROVIDER_CONFIG is required when TELEMETRY_PROVIDER is "custom"');this.telemetry={provider:"custom",providerConfig:O.parse(JSON.parse(Y))}}else this.telemetry={provider:"noop"};if(this.latencyMetricName=Oe||"http_server_1agg1_request_duration",this.productTelemetryEndpoint=Ce||"https://prod.telemetry.tableausoftware.com",this.productTelemetryEnabled=we!=="false",this.isHyperforce=Ue==="true",this.breakGlassDisableGlobally=Ne==="true",this.adminToolsEnabled=Me==="true",this.auth=st(r)?r:this.oauth.enabled?"oauth":"pat",this.transport=_(m)?m:this.oauth.enabled?"http":"stdio",this.transport==="http"&&!P&&!this.oauth.issuer)throw new Error('OAUTH_ISSUER must be set when TRANSPORT is "http" unless DANGEROUSLY_DISABLE_OAUTH is "true"');if(this.auth==="oauth"){if(P)throw new Error('When AUTH is "oauth", DANGEROUSLY_DISABLE_OAUTH cannot be "true"');if(!this.oauth.issuer)throw new Error('When AUTH is "oauth", OAUTH_ISSUER must be set')}else s(o,"The environment variable SERVER is not set"),at(o);if(this.oauth.enabled){if(this.oauth.embeddedAuthzServer){if(s(this.oauth.redirectUri,"The environment variable OAUTH_REDIRECT_URI is not set"),!this.oauth.jwePrivateKey&&!this.oauth.jwePrivateKeyPath)throw new Error("One of the environment variables: OAUTH_JWE_PRIVATE_KEY_PATH or OAUTH_JWE_PRIVATE_KEY must be set");if(this.oauth.jwePrivateKey&&this.oauth.jwePrivateKeyPath)throw new Error("Only one of the environment variables: OAUTH_JWE_PRIVATE_KEY or OAUTH_JWE_PRIVATE_KEY_PATH must be set");if(this.oauth.jwePrivateKeyPath&&process.env.TABLEAU_MCP_TEST!=="true"&&!(0,h.existsSync)(this.oauth.jwePrivateKeyPath))throw new Error(`OAuth JWE private key path does not exist: ${this.oauth.jwePrivateKeyPath}`)}if(this.transport==="stdio")throw new Error('TRANSPORT must be "http" when OAUTH_ISSUER is set')}if(this.auth==="pat")s(w,"The environment variable PAT_NAME is not set"),s(U,"The environment variable PAT_VALUE is not set");else if(this.auth==="direct-trust")s(T,"The environment variable JWT_SUB_CLAIM is not set"),s(N,"The environment variable CONNECTED_APP_CLIENT_ID is not set"),s(M,"The environment variable CONNECTED_APP_SECRET_ID is not set"),s(D,"The environment variable CONNECTED_APP_SECRET_VALUE is not set"),b=T??"";else if(this.auth==="uat"){if(s(V,"The environment variable UAT_TENANT_ID is not set"),s(x,"The environment variable UAT_ISSUER is not set"),!H&&!T)throw new Error("One of the environment variables: UAT_USERNAME_CLAIM or JWT_SUB_CLAIM must be set");if(b=H??T??"",!y&&!d)throw new Error("One of the environment variables: UAT_PRIVATE_KEY_PATH or UAT_PRIVATE_KEY must be set");if(y&&d)throw new Error("Only one of the environment variables: UAT_PRIVATE_KEY or UAT_PRIVATE_KEY_PATH must be set");if(d&&process.env.TABLEAU_MCP_TEST!=="true"&&!(0,h.existsSync)(d))throw new Error(`UAT private key path does not exist: ${d}`)}this.server=o??"";let B=this.server?new URL(this.server).origin:"",xe=["https://*.online.tableau.com","https://*.tableau.com",...B?[B]:[]],He=j?j.split(",").map(u=>u.trim()):[];this.cspAllowedDomains=[...xe,...He],this.patName=w??"",this.patValue=U??"",this.jwtUsername=b??"",this.connectedAppClientId=N??"",this.connectedAppSecretId=M??"",this.connectedAppSecretValue=D??"",this.uatTenantId=V??"",this.uatIssuer=x??"",this.uatUsernameClaimName=ne||"email",this.uatPrivateKey=y||(d?(0,h.readFileSync)(d,"utf8"):""),this.uatKeyId=se??"",this.jwtAdditionalPayload=ae||"{}"}};function at(e){if(!["https://","http://"].find(t=>e.startsWith(t)))throw new Error(`The environment variable SERVER must start with "http://" or "https://": ${e}`);try{new URL(e)}catch(t){let r=t instanceof Error?t.message:String(t);throw new Error(`The environment variable SERVER is not a valid URL: ${e} -- ${r}`)}}function lt(e){if(!e)return!0;if(e.match(/^true|false$/i))return e.toLowerCase()==="true";if(e==="*")return"*";if(e.startsWith("[")&&e.endsWith("]"))try{return JSON.parse(e).map(r=>new URL(r).origin)}catch{throw new Error(`The environment variable CORS_ORIGIN_CONFIG is not a valid array of URLs: ${e}`)}try{return new URL(e).origin}catch{throw new Error(`The environment variable CORS_ORIGIN_CONFIG is not a valid URL: ${e}`)}}var te=()=>new C;var c=class{initialize(){}recordMetric(t,r,o){}recordHistogram(t,r,o){}};function ut(e){return Object.getOwnPropertyNames(e.prototype).filter(t=>t!=="constructor"&&typeof e.prototype[t]=="function")}function mt(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function dt(e){if(!mt(e))throw new Error("Provider must be an object");let r=ut(c).filter(o=>typeof e[o]!="function");if(r.length>0)throw new Error(`Custom provider missing required methods: ${r.join(", ")}`)}function oe(){let e=te(),t;try{switch(e.telemetry.provider){case"custom":t=ct(e.telemetry.providerConfig);break;case"noop":t=new c;break}return t.initialize(),global.__telemetryProvider=t,t}catch(r){L({message:"Failed to initialize telemetry provider",level:"error",logger:"telemetry",data:r}),L({message:"Falling back to NoOp telemetry provider",level:"info",logger:"telemetry"});let o=new c;return o.initialize(),global.__telemetryProvider=o,o}}function ct(e){if(!e?.module)throw new Error(`Custom telemetry provider requires "module" in providerConfig. Example: TELEMETRY_PROVIDER_CONFIG='{"module":"./my-telemetry.js"}'`);let t=e.module;if(typeof t!="string")throw new Error('Custom telemetry provider requires "module" to be a string');let r;t.startsWith(".")||t.startsWith("/")?r=(0,re.resolve)(process.cwd(),t):r=t;try{let o=require(r),i=o.default||o.TelemetryProvider;if(!i)throw new Error(`Module ${t} must export a default class or named export "TelemetryProvider" that implements the TelemetryProvider interface`);let m=new i(e);return dt(m),m}catch(o){let i=`Failed to load custom telemetry provider from "${t}". `;throw o instanceof Error&&"code"in o&&o.code==="MODULE_NOT_FOUND"?i+="Module not found. If using a file path, ensure the file exists and the path is correct. If using an npm package, ensure it is installed.":i+=`Error: ${o}`,new Error(i)}}ie.default.config();try{oe()}catch(e){console.warn("Failed to initialize telemetry:",e)}
1
+ "use strict";var Be=Object.create;var Q=Object.defineProperty;var We=Object.getOwnPropertyDescriptor;var Je=Object.getOwnPropertyNames;var qe=Object.getPrototypeOf,ze=Object.prototype.hasOwnProperty;var $e=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Je(t))!ze.call(e,i)&&i!==r&&Q(e,i,{get:()=>t[i],enumerable:!(o=We(t,i))||o.enumerable});return e};var Qe=(e,t,r)=>(r=e!=null?Be(qe(e)):{},$e(t||!e||!e.__esModule?Q(r,"default",{value:e,enumerable:!0}):r,e));var ue=Qe(require("dotenv"));var ae=require("path");var E=require("fs");var oe=require("path");var Xe;var X=()=>Xe;var Ze=["debug","info","notice","warning","error","critical","alert","emergency"],f=Object.fromEntries(Ze.map((e,t)=>[e,t]));function et(e,t){return f[e]>=f[t]}function tt(e){return e in f}function Z(e){let t=e?.trim();return t&&tt(t)?t:"info"}function rt(e){return e instanceof Error?{name:e.name,message:e.message,stack:e.stack,...e.cause!==void 0&&{cause:e.cause}}:e}var ot="audit";function L(e){let t=ee();if(!(e.logger!==ot&&!et(e.level,t.logLevel))){if(e.data=rt(e.data),t.loggers.has("appLogger")){let r=JSON.stringify(e);t.transport==="http"?console.log(r):process.stderr.write(r+`
2
+ `)}t.loggers.has("fileLogger")&&X()?.log(e)}}var it=["fileLogger","appLogger"],st=new Set(it);function te(e){return e?new Set(e.split(",").map(t=>t.trim()).filter(t=>st.has(t))):new Set(["appLogger"])}var nt=["stdio","http"];function _(e){return!!nt.find(t=>t===e)}function re(){if(typeof __dirname=="string")return __dirname;throw new Error("__dirname is not set")}var a={fromSeconds:e=>e*1e3,fromMinutes:e=>e*60*1e3,fromHours:e=>e*60*60*1e3,fromDays:e=>e*24*60*60*1e3,fromWeeks:e=>e*7*24*60*60*1e3,fromMonths:e=>e*30*24*60*60*1e3,fromYears:e=>e*365.25*24*60*60*1e3};function n(e,{defaultValue:t,minValue:r,maxValue:o}={defaultValue:0,minValue:Number.NEGATIVE_INFINITY,maxValue:Number.POSITIVE_INFINITY}){if(!e)return t;let i=parseFloat(e);return isNaN(i)||r!==void 0&&i<r||o!==void 0&&i>o?t:i}var at=re(),h=class{transport;defaultNotificationLevel;logLevel;loggers;fileLoggerDirectory;disableLogMasking;maxRequestTimeoutMs;notificationPayloadMaxBytes;constructor(){let t=C(process.env),{TRANSPORT:r,DEFAULT_NOTIFICATION_LEVEL:o,LOG_LEVEL:i,ENABLED_LOGGERS:d,FILE_LOGGER_DIRECTORY:v,DISABLE_LOG_MASKING:S,MAX_REQUEST_TIMEOUT_MS:A,NOTIFICATION_PAYLOAD_MAX_BYTES:y}=t;this.transport=_(r)?r:"stdio",this.defaultNotificationLevel=o??"debug",this.logLevel=Z(i),this.loggers=te(d),this.fileLoggerDirectory=v||(0,oe.join)(at,"logs"),this.disableLogMasking=S==="true",this.maxRequestTimeoutMs=n(A,{defaultValue:a.fromMinutes(10),minValue:5e3,maxValue:a.fromHours(1)}),this.notificationPayloadMaxBytes=n(y,{defaultValue:8192,minValue:1})}};function C(e){return Object.entries(e).reduce((t,[r,o])=>(o?.startsWith("${user_config.")?t[r]="":t[r]=o,t),{})}var ee=()=>new h;var l=require("zod"),lt=l.z.enum(["server","custom"]);function ie(e){return lt.safeParse(e).success}var ut=l.z.object({provider:l.z.literal("server")}),O=l.z.object({module:l.z.string({required_error:'Custom provider requires "module" path'})}).passthrough(),mt=l.z.object({provider:l.z.literal("custom"),providerConfig:O}),$t=l.z.discriminatedUnion("provider",[ut,mt]);var u=require("zod"),dt=u.z.enum(["noop","custom"]),pt=u.z.object({provider:u.z.literal("noop")}),w=u.z.object({module:u.z.string({required_error:'Custom provider requires "module" path'})}).passthrough(),ct=u.z.object({provider:u.z.literal("custom"),providerConfig:w}),Xt=u.z.discriminatedUnion("provider",[pt,ct]);function se(e){return dt.safeParse(e).success}function s(e,t){if(!e)throw new Error(t||"Invariant Violation")}var ht=["pat","uat","direct-trust","oauth"];function Et(e){return ht.some(t=>t===e)}var U=class extends h{auth;server;sslKey;sslCert;httpPort;corsOriginConfig;siteName;patName;patValue;jwtUsername;connectedAppClientId;connectedAppSecretId;connectedAppSecretValue;uatTenantId;uatIssuer;uatUsernameClaimName;uatPrivateKey;uatKeyId;jwtAdditionalPayload;datasourceCredentials;disableSessionManagement;tableauServerVersionCheckIntervalInHours;passthroughAuthUserSessionCheckIntervalInMinutes;mcpSiteSettingsCheckIntervalInMinutes;enableMcpSiteSettings;allowSitesToConfigureRequestOverrides;enablePassthroughAuth;oauth;telemetry;latencyMetricName;productTelemetryEndpoint;productTelemetryEnabled;isHyperforce;featureGate;breakGlassDisableGlobally;adminToolsEnabled;cspAllowedDomains;constructor(){super();let t=C(process.env),{AUTH:r,SERVER:o,SITE_NAME:i,TRANSPORT:d,SSL_KEY:v,SSL_CERT:S,HTTP_PORT_ENV_VAR_NAME:A,CORS_ORIGIN_CONFIG:y,PAT_NAME:N,PAT_VALUE:M,JWT_SUB_CLAIM:g,CONNECTED_APP_CLIENT_ID:D,CONNECTED_APP_SECRET_ID:V,CONNECTED_APP_SECRET_VALUE:x,UAT_TENANT_ID:G,UAT_ISSUER:H,UAT_USERNAME_CLAIM_NAME:me,UAT_USERNAME_CLAIM:k,UAT_PRIVATE_KEY:I,UAT_PRIVATE_KEY_PATH:p,UAT_KEY_ID:de,JWT_ADDITIONAL_PAYLOAD:pe,DATASOURCE_CREDENTIALS:ce,DISABLE_SESSION_MANAGEMENT:he,TABLEAU_SERVER_VERSION_CHECK_INTERVAL_IN_HOURS:Ee,PASSTHROUGH_AUTH_USER_SESSION_CHECK_INTERVAL_IN_MINUTES:ge,MCP_SITE_SETTINGS_CHECK_INTERVAL_IN_MINUTES:Te,ENABLE_MCP_SITE_SETTINGS:fe,ALLOW_SITES_TO_CONFIGURE_REQUEST_OVERRIDES:_e,ENABLE_PASSTHROUGH_AUTH:ve,DANGEROUSLY_DISABLE_OAUTH:Se,OAUTH_EMBEDDED_AUTHZ_SERVER:Ae,OAUTH_ISSUER:T,OAUTH_LOCK_SITE:ye,OAUTH_JWE_PRIVATE_KEY:Ie,OAUTH_JWE_PRIVATE_KEY_PATH:Pe,OAUTH_JWE_PRIVATE_KEY_PASSPHRASE:Re,OAUTH_RESOURCE_URI:be,OAUTH_GLOBAL_RESOURCE_URIS:K,OAUTH_REDIRECT_URI:Le,OAUTH_CLIENT_ID_SECRET_PAIRS:P,OAUTH_CIMD_DNS_SERVERS:F,ADVERTISE_API_SCOPES:Ce,OAUTH_AUTHORIZATION_CODE_TIMEOUT_MS:Oe,OAUTH_ACCESS_TOKEN_TIMEOUT_MS:we,OAUTH_REFRESH_TOKEN_TIMEOUT_MS:Ue,OAUTH_DISABLE_SCOPES:Ne,TELEMETRY_PROVIDER:j,TELEMETRY_PROVIDER_CONFIG:Y,FEATURE_GATE_PROVIDER:B,FEATURE_GATE_PROVIDER_CONFIG:W,LATENCY_METRIC_NAME:Me,PRODUCT_TELEMETRY_ENDPOINT:De,PRODUCT_TELEMETRY_ENABLED:Ve,IS_HYPERFORCE:xe,BREAK_GLASS_DISABLE_GLOBALLY:Ge,ADMIN_TOOLS_ENABLED:He,CSP_ALLOWED_DOMAINS:J}=t,R="";this.siteName=i??"",this.sslKey=v?.trim()??"",this.sslCert=S?.trim()??"",this.httpPort=n(t[A?.trim()||"PORT"],{defaultValue:3927,minValue:1,maxValue:65535}),this.corsOriginConfig=Tt(y?.trim()??""),this.datasourceCredentials=ce??"",this.disableSessionManagement=he==="true",this.tableauServerVersionCheckIntervalInHours=n(Ee,{defaultValue:1,minValue:1,maxValue:168}),this.passthroughAuthUserSessionCheckIntervalInMinutes=n(ge,{defaultValue:10,minValue:0,maxValue:1440}),this.mcpSiteSettingsCheckIntervalInMinutes=n(Te,{defaultValue:10,minValue:1,maxValue:1440}),this.enableMcpSiteSettings=fe!=="false",this.allowSitesToConfigureRequestOverrides=_e==="true",this.enablePassthroughAuth=ve==="true";let b=Se==="true",ke=!(Ne==="true"),Ke=Ae!=="false";if(this.allowSitesToConfigureRequestOverrides&&!this.enableMcpSiteSettings)throw new Error('ALLOW_SITES_TO_CONFIGURE_REQUEST_OVERRIDES is "true", but MCP site settings are not enabled.');if(this.oauth={enabled:b?!1:!!T,embeddedAuthzServer:Ke,issuer:T??"",resourceUri:be??`http://127.0.0.1:${this.httpPort}`,globalResourceUris:K?K.split(",").map(m=>m.trim()).filter(Boolean):[],redirectUri:Le||(T?`${T}/Callback`:""),lockSite:ye!=="false",jwePrivateKey:Ie??"",jwePrivateKeyPath:Pe??"",jwePrivateKeyPassphrase:Re||void 0,dnsServers:F?F.split(",").map(m=>m.trim()):["1.1.1.1","1.0.0.1"],authzCodeTimeoutMs:n(Oe,{defaultValue:a.fromMinutes(10),minValue:0,maxValue:a.fromHours(1)}),accessTokenTimeoutMs:n(we,{defaultValue:a.fromHours(1),minValue:0,maxValue:a.fromDays(30)}),refreshTokenTimeoutMs:n(Ue,{defaultValue:a.fromDays(30),minValue:0,maxValue:a.fromYears(1)}),clientIdSecretPairs:P?P.split(",").reduce((m,Ye)=>{let[z,$]=Ye.split(":");return z&&$&&(m[z]=$),m},{}):null,enforceScopes:ke,advertiseApiScopes:Ce==="true"},this.oauth.clientIdSecretPairs&&Object.keys(this.oauth.clientIdSecretPairs).length===0)throw new Error(`OAUTH_CLIENT_ID_SECRET_PAIRS is in an invalid format: ${P}. Should be in the format: clientId:secret`);if((se(j)?j:"noop")==="custom"){if(!Y)throw new Error('TELEMETRY_PROVIDER_CONFIG is required when TELEMETRY_PROVIDER is "custom"');this.telemetry={provider:"custom",providerConfig:w.parse(JSON.parse(Y))}}else this.telemetry={provider:"noop"};if(this.latencyMetricName=Me||"http_server_1agg1_request_duration",this.productTelemetryEndpoint=De||"https://prod.telemetry.tableausoftware.com",this.productTelemetryEnabled=Ve!=="false",this.isHyperforce=xe==="true",ie(B)&&B==="custom"){if(!W)throw new Error('FEATURE_GATE_PROVIDER_CONFIG is required when FEATURE_GATE_PROVIDER is "custom"');this.featureGate={provider:"custom",providerConfig:O.parse(JSON.parse(W))}}else this.featureGate={provider:"server"};if(this.breakGlassDisableGlobally=Ge==="true",this.adminToolsEnabled=He==="true",this.auth=Et(r)?r:this.oauth.enabled?"oauth":"pat",this.transport=_(d)?d:this.oauth.enabled?"http":"stdio",this.transport==="http"&&!b&&!this.oauth.issuer)throw new Error('OAUTH_ISSUER must be set when TRANSPORT is "http" unless DANGEROUSLY_DISABLE_OAUTH is "true"');if(this.auth==="oauth"){if(b)throw new Error('When AUTH is "oauth", DANGEROUSLY_DISABLE_OAUTH cannot be "true"');if(!this.oauth.issuer)throw new Error('When AUTH is "oauth", OAUTH_ISSUER must be set')}else s(o,"The environment variable SERVER is not set"),gt(o);if(this.oauth.enabled){if(this.oauth.embeddedAuthzServer){if(s(this.oauth.redirectUri,"The environment variable OAUTH_REDIRECT_URI is not set"),!this.oauth.jwePrivateKey&&!this.oauth.jwePrivateKeyPath)throw new Error("One of the environment variables: OAUTH_JWE_PRIVATE_KEY_PATH or OAUTH_JWE_PRIVATE_KEY must be set");if(this.oauth.jwePrivateKey&&this.oauth.jwePrivateKeyPath)throw new Error("Only one of the environment variables: OAUTH_JWE_PRIVATE_KEY or OAUTH_JWE_PRIVATE_KEY_PATH must be set");if(this.oauth.jwePrivateKeyPath&&process.env.TABLEAU_MCP_TEST!=="true"&&!(0,E.existsSync)(this.oauth.jwePrivateKeyPath))throw new Error(`OAuth JWE private key path does not exist: ${this.oauth.jwePrivateKeyPath}`)}if(this.transport==="stdio")throw new Error('TRANSPORT must be "http" when OAUTH_ISSUER is set')}if(this.auth==="pat")s(N,"The environment variable PAT_NAME is not set"),s(M,"The environment variable PAT_VALUE is not set");else if(this.auth==="direct-trust")s(g,"The environment variable JWT_SUB_CLAIM is not set"),s(D,"The environment variable CONNECTED_APP_CLIENT_ID is not set"),s(V,"The environment variable CONNECTED_APP_SECRET_ID is not set"),s(x,"The environment variable CONNECTED_APP_SECRET_VALUE is not set"),R=g??"";else if(this.auth==="uat"){if(s(G,"The environment variable UAT_TENANT_ID is not set"),s(H,"The environment variable UAT_ISSUER is not set"),!k&&!g)throw new Error("One of the environment variables: UAT_USERNAME_CLAIM or JWT_SUB_CLAIM must be set");if(R=k??g??"",!I&&!p)throw new Error("One of the environment variables: UAT_PRIVATE_KEY_PATH or UAT_PRIVATE_KEY must be set");if(I&&p)throw new Error("Only one of the environment variables: UAT_PRIVATE_KEY or UAT_PRIVATE_KEY_PATH must be set");if(p&&process.env.TABLEAU_MCP_TEST!=="true"&&!(0,E.existsSync)(p))throw new Error(`UAT private key path does not exist: ${p}`)}this.server=o??"";let q=this.server?new URL(this.server).origin:"",Fe=["https://*.online.tableau.com","https://*.tableau.com",...q?[q]:[]],je=J?J.split(",").map(m=>m.trim()):[];this.cspAllowedDomains=[...Fe,...je],this.patName=N??"",this.patValue=M??"",this.jwtUsername=R??"",this.connectedAppClientId=D??"",this.connectedAppSecretId=V??"",this.connectedAppSecretValue=x??"",this.uatTenantId=G??"",this.uatIssuer=H??"",this.uatUsernameClaimName=me||"email",this.uatPrivateKey=I||(p?(0,E.readFileSync)(p,"utf8"):""),this.uatKeyId=de??"",this.jwtAdditionalPayload=pe||"{}"}};function gt(e){if(!["https://","http://"].find(t=>e.startsWith(t)))throw new Error(`The environment variable SERVER must start with "http://" or "https://": ${e}`);try{new URL(e)}catch(t){let r=t instanceof Error?t.message:String(t);throw new Error(`The environment variable SERVER is not a valid URL: ${e} -- ${r}`)}}function Tt(e){if(!e)return!0;if(e.match(/^true|false$/i))return e.toLowerCase()==="true";if(e==="*")return"*";if(e.startsWith("[")&&e.endsWith("]"))try{return JSON.parse(e).map(r=>new URL(r).origin)}catch{throw new Error(`The environment variable CORS_ORIGIN_CONFIG is not a valid array of URLs: ${e}`)}try{return new URL(e).origin}catch{throw new Error(`The environment variable CORS_ORIGIN_CONFIG is not a valid URL: ${e}`)}}var ne=()=>new U;var c=class{initialize(){}recordMetric(t,r,o){}recordHistogram(t,r,o){}};function ft(e){return Object.getOwnPropertyNames(e.prototype).filter(t=>t!=="constructor"&&typeof e.prototype[t]=="function")}function _t(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function vt(e){if(!_t(e))throw new Error("Provider must be an object");let r=ft(c).filter(o=>typeof e[o]!="function");if(r.length>0)throw new Error(`Custom provider missing required methods: ${r.join(", ")}`)}function le(){let e=ne(),t;try{switch(e.telemetry.provider){case"custom":t=St(e.telemetry.providerConfig);break;case"noop":t=new c;break}return t.initialize(),global.__telemetryProvider=t,t}catch(r){L({message:"Failed to initialize telemetry provider",level:"error",logger:"telemetry",data:r}),L({message:"Falling back to NoOp telemetry provider",level:"info",logger:"telemetry"});let o=new c;return o.initialize(),global.__telemetryProvider=o,o}}function St(e){if(!e?.module)throw new Error(`Custom telemetry provider requires "module" in providerConfig. Example: TELEMETRY_PROVIDER_CONFIG='{"module":"./my-telemetry.js"}'`);let t=e.module;if(typeof t!="string")throw new Error('Custom telemetry provider requires "module" to be a string');let r;t.startsWith(".")||t.startsWith("/")?r=(0,ae.resolve)(process.cwd(),t):r=t;try{let o=require(r),i=o.default||o.TelemetryProvider;if(!i)throw new Error(`Module ${t} must export a default class or named export "TelemetryProvider" that implements the TelemetryProvider interface`);let d=new i(e);return vt(d),d}catch(o){let i=`Failed to load custom telemetry provider from "${t}". `;throw o instanceof Error&&"code"in o&&o.code==="MODULE_NOT_FOUND"?i+="Module not found. If using a file path, ensure the file exists and the path is correct. If using an npm package, ensure it is installed.":i+=`Error: ${o}`,new Error(i)}}ue.default.config();try{le()}catch(e){console.warn("Failed to initialize telemetry:",e)}
3
3
  //# sourceMappingURL=tracing.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/telemetry/tracing.ts", "../../src/telemetry/init.ts", "../../src/config.ts", "../../src/config.shared.ts", "../../src/logging/fileLogger.ts", "../../src/logging/types.ts", "../../src/logging/logger.ts", "../../src/logging/loggerType.ts", "../../src/transports.ts", "../../src/utils/getDirname.ts", "../../src/utils/milliseconds.ts", "../../src/utils/parseNumber.ts", "../../src/telemetry/types.ts", "../../src/utils/invariant.ts", "../../src/telemetry/noop.ts"],
4
- "sourcesContent": ["/**\n * APM agent preload script\n *\n * Use with node -r flag to start APM agent before application code:\n * node -r ./build/telemetry/tracing.js build/index.js\n *\n * Environment variables:\n * - TELEMETRY_PROVIDER=custom - Use custom telemetry provider (default: noop)\n */\n\n// Load .env before anything else\nimport dotenv from 'dotenv';\ndotenv.config();\n\nimport { initializeTelemetry } from './init.js';\n\ntry {\n initializeTelemetry();\n} catch (error) {\n console.warn('Failed to initialize telemetry:', error);\n}\n", "/**\n * Telemetry initialization and provider factory\n */\n\nimport { resolve } from 'path';\n\nimport { getConfig } from '../config.js';\nimport { log } from '../logging/logger.js';\nimport { NoOpTelemetryProvider } from './noop.js';\nimport { TelemetryProvider } from './types.js';\n\n/**\n * Get all instance methods from a class prototype\n */\nfunction getInstanceMethods(cls: new (...args: unknown[]) => unknown): string[] {\n return Object.getOwnPropertyNames(cls.prototype).filter(\n (name) => name !== 'constructor' && typeof cls.prototype[name] === 'function',\n );\n}\n\nfunction isRecord(obj: unknown): obj is Record<string, unknown> {\n return typeof obj === 'object' && obj !== null && !Array.isArray(obj);\n}\n\n/**\n * Validate that a provider implements all required TelemetryProvider methods\n */\nfunction validateTelemetryProvider(provider: unknown): asserts provider is TelemetryProvider {\n if (!isRecord(provider)) {\n throw new Error('Provider must be an object');\n }\n\n const requiredMethods = getInstanceMethods(NoOpTelemetryProvider);\n // Keep only methods that provider doesn't have (i.e., missing or miscategorized methods)\n const missingMethods = requiredMethods.filter((method) => typeof provider[method] !== 'function');\n\n if (missingMethods.length > 0) {\n throw new Error(`Custom provider missing required methods: ${missingMethods.join(', ')}`);\n }\n}\n\n// Use global to share provider across bundles (tracing.js and index.js)\ndeclare global {\n var __telemetryProvider: TelemetryProvider | undefined;\n}\n\n/**\n * Get the current telemetry provider instance.\n * If not initialized, returns a NoOp provider.\n *\n * @returns The telemetry provider\n */\nexport function getTelemetryProvider(): TelemetryProvider {\n if (!global.__telemetryProvider) {\n // return a NoOp provider for this request if telemetry hasn't been initialized\n return new NoOpTelemetryProvider();\n }\n return global.__telemetryProvider;\n}\n\n/**\n * Initialize the telemetry provider based on configuration.\n *\n * This function should be called early in application startup, before any\n * HTTP requests or other instrumented operations occur.\n *\n * @returns A configured telemetry provider\n *\n * @example\n * function main() {\n * // Initialize telemetry first\n * const telemetry = initializeTelemetry();\n *\n * // Start application...\n * }\n */\nexport function initializeTelemetry(): TelemetryProvider {\n const config = getConfig();\n let provider: TelemetryProvider;\n\n try {\n // Select provider based on configuration\n switch (config.telemetry.provider) {\n case 'custom':\n // Load custom provider from user's filesystem\n provider = loadCustomProvider(config.telemetry.providerConfig);\n break;\n\n case 'noop':\n provider = new NoOpTelemetryProvider();\n break;\n }\n\n // Initialize the provider\n provider.initialize();\n global.__telemetryProvider = provider;\n return provider;\n } catch (error) {\n log({\n message: 'Failed to initialize telemetry provider',\n level: 'error',\n logger: 'telemetry',\n data: error,\n });\n log({ message: 'Falling back to NoOp telemetry provider', level: 'info', logger: 'telemetry' });\n\n // Fallback to NoOp on error - telemetry failures shouldn't break the application\n const fallbackProvider = new NoOpTelemetryProvider();\n fallbackProvider.initialize();\n global.__telemetryProvider = fallbackProvider;\n return fallbackProvider;\n }\n}\n\n/**\n * Load a custom telemetry provider from user's filesystem or npm package.\n *\n * The custom provider module should export a default class that implements TelemetryProvider.\n *\n * @param config - Provider configuration containing the module path\n * @returns A configured custom telemetry provider\n *\n * @example Custom provider from file\n * TELEMETRY_PROVIDER=custom\n * TELEMETRY_PROVIDER_CONFIG='{\"module\":\"./my-telemetry.js\"}'\n */\nfunction loadCustomProvider(config?: Record<string, unknown>): TelemetryProvider {\n if (!config?.module) {\n throw new Error(\n 'Custom telemetry provider requires \"module\" in providerConfig. ' +\n 'Example: TELEMETRY_PROVIDER_CONFIG=\\'{\"module\":\"./my-telemetry.js\"}\\'',\n );\n }\n\n const modulePath = config.module;\n\n if (typeof modulePath !== 'string') {\n throw new Error('Custom telemetry provider requires \"module\" to be a string');\n }\n\n // Determine if it's a file path or npm package name\n let resolvedPath: string;\n\n if (modulePath.startsWith('.') || modulePath.startsWith('/')) {\n // File path - resolve relative to process working directory (user's project root)\n resolvedPath = resolve(process.cwd(), modulePath);\n } else {\n // npm package name - require as-is\n resolvedPath = modulePath;\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports -- Sync load for preload script\n const module = require(resolvedPath);\n\n // Look for default export or named export \"TelemetryProvider\"\n const ProviderClass = module.default || module.TelemetryProvider;\n\n if (!ProviderClass) {\n throw new Error(\n `Module ${modulePath} must export a default class or named export \"TelemetryProvider\" ` +\n 'that implements the TelemetryProvider interface',\n );\n }\n\n // Instantiate the provider with the full config\n const provider = new ProviderClass(config);\n\n // Validate the provider implements TelemetryProvider interface\n validateTelemetryProvider(provider);\n return provider;\n } catch (error) {\n // Provide helpful error message with common issues\n let errorMessage = `Failed to load custom telemetry provider from \"${modulePath}\". `;\n\n if (error instanceof Error && 'code' in error && error.code === 'MODULE_NOT_FOUND') {\n errorMessage +=\n 'Module not found. ' +\n 'If using a file path, ensure the file exists and the path is correct. ' +\n 'If using an npm package, ensure it is installed.';\n } else {\n errorMessage += `Error: ${error}`;\n }\n\n throw new Error(errorMessage);\n }\n}\n", "import { CorsOptions } from 'cors';\nimport { existsSync, readFileSync } from 'fs';\n\nimport { BaseConfig, removeClaudeMcpBundleUserConfigTemplates } from './config.shared.js';\nimport { isTelemetryProvider, providerConfigSchema, TelemetryConfig } from './telemetry/types.js';\nimport { isTransport } from './transports.js';\nimport invariant from './utils/invariant.js';\nimport { milliseconds } from './utils/milliseconds.js';\nimport { parseNumber } from './utils/parseNumber.js';\n\nconst authTypes = ['pat', 'uat', 'direct-trust', 'oauth'] as const;\ntype AuthType = (typeof authTypes)[number];\n\nfunction isAuthType(auth: unknown): auth is AuthType {\n return authTypes.some((type) => type === auth);\n}\n\nexport class Config extends BaseConfig {\n auth: AuthType;\n server: string;\n sslKey: string;\n sslCert: string;\n httpPort: number;\n corsOriginConfig: CorsOptions['origin'];\n siteName: string;\n patName: string;\n patValue: string;\n jwtUsername: string;\n connectedAppClientId: string;\n connectedAppSecretId: string;\n connectedAppSecretValue: string;\n uatTenantId: string;\n uatIssuer: string;\n uatUsernameClaimName: string;\n uatPrivateKey: string;\n uatKeyId: string;\n jwtAdditionalPayload: string;\n datasourceCredentials: string;\n disableSessionManagement: boolean;\n tableauServerVersionCheckIntervalInHours: number;\n passthroughAuthUserSessionCheckIntervalInMinutes: number;\n mcpSiteSettingsCheckIntervalInMinutes: number;\n enableMcpSiteSettings: boolean;\n allowSitesToConfigureRequestOverrides: boolean;\n enablePassthroughAuth: boolean;\n oauth: {\n enabled: boolean;\n embeddedAuthzServer: boolean;\n issuer: string;\n redirectUri: string;\n resourceUri: string;\n globalResourceUris: string[];\n lockSite: boolean;\n jwePrivateKey: string;\n jwePrivateKeyPath: string;\n jwePrivateKeyPassphrase: string | undefined;\n authzCodeTimeoutMs: number;\n accessTokenTimeoutMs: number;\n refreshTokenTimeoutMs: number;\n clientIdSecretPairs: Record<string, string> | null;\n dnsServers: string[];\n enforceScopes: boolean;\n advertiseApiScopes: boolean;\n };\n telemetry: TelemetryConfig;\n latencyMetricName: string;\n productTelemetryEndpoint: string;\n productTelemetryEnabled: boolean;\n isHyperforce: boolean;\n breakGlassDisableGlobally: boolean;\n adminToolsEnabled: boolean;\n cspAllowedDomains: string[];\n\n constructor() {\n super();\n\n const cleansedVars = removeClaudeMcpBundleUserConfigTemplates(process.env);\n const {\n AUTH: auth,\n SERVER: server,\n SITE_NAME: siteName,\n TRANSPORT: transport,\n SSL_KEY: sslKey,\n SSL_CERT: sslCert,\n HTTP_PORT_ENV_VAR_NAME: httpPortEnvVarName,\n CORS_ORIGIN_CONFIG: corsOriginConfig,\n PAT_NAME: patName,\n PAT_VALUE: patValue,\n JWT_SUB_CLAIM: jwtSubClaim,\n CONNECTED_APP_CLIENT_ID: clientId,\n CONNECTED_APP_SECRET_ID: secretId,\n CONNECTED_APP_SECRET_VALUE: secretValue,\n UAT_TENANT_ID: uatTenantId,\n UAT_ISSUER: uatIssuer,\n UAT_USERNAME_CLAIM_NAME: uatUsernameClaimName,\n UAT_USERNAME_CLAIM: uatUsernameClaim,\n UAT_PRIVATE_KEY: uatPrivateKey,\n UAT_PRIVATE_KEY_PATH: uatPrivateKeyPath,\n UAT_KEY_ID: uatKeyId,\n JWT_ADDITIONAL_PAYLOAD: jwtAdditionalPayload,\n DATASOURCE_CREDENTIALS: datasourceCredentials,\n DISABLE_SESSION_MANAGEMENT: disableSessionManagement,\n TABLEAU_SERVER_VERSION_CHECK_INTERVAL_IN_HOURS: tableauServerVersionCheckIntervalInHours,\n PASSTHROUGH_AUTH_USER_SESSION_CHECK_INTERVAL_IN_MINUTES:\n passthroughAuthUserSessionCheckIntervalInMinutes,\n MCP_SITE_SETTINGS_CHECK_INTERVAL_IN_MINUTES: mcpSiteSettingsCheckIntervalInMinutes,\n ENABLE_MCP_SITE_SETTINGS: enableMcpSiteSettings,\n ALLOW_SITES_TO_CONFIGURE_REQUEST_OVERRIDES: allowSitesToConfigureRequestOverrides,\n ENABLE_PASSTHROUGH_AUTH: enablePassthroughAuth,\n DANGEROUSLY_DISABLE_OAUTH: disableOauth,\n OAUTH_EMBEDDED_AUTHZ_SERVER: oauthEmbeddedAuthzServer,\n OAUTH_ISSUER: oauthIssuer,\n OAUTH_LOCK_SITE: oauthLockSite,\n OAUTH_JWE_PRIVATE_KEY: oauthJwePrivateKey,\n OAUTH_JWE_PRIVATE_KEY_PATH: oauthJwePrivateKeyPath,\n OAUTH_JWE_PRIVATE_KEY_PASSPHRASE: oauthJwePrivateKeyPassphrase,\n OAUTH_RESOURCE_URI: oauthResourceUri,\n OAUTH_GLOBAL_RESOURCE_URIS: oauthGlobalResourceUris,\n OAUTH_REDIRECT_URI: redirectUri,\n OAUTH_CLIENT_ID_SECRET_PAIRS: oauthClientIdSecretPairs,\n OAUTH_CIMD_DNS_SERVERS: dnsServers,\n ADVERTISE_API_SCOPES: advertiseApiScopes,\n OAUTH_AUTHORIZATION_CODE_TIMEOUT_MS: authzCodeTimeoutMs,\n OAUTH_ACCESS_TOKEN_TIMEOUT_MS: accessTokenTimeoutMs,\n OAUTH_REFRESH_TOKEN_TIMEOUT_MS: refreshTokenTimeoutMs,\n OAUTH_DISABLE_SCOPES: oauthDisableScopes,\n TELEMETRY_PROVIDER: telemetryProvider,\n TELEMETRY_PROVIDER_CONFIG: telemetryProviderConfig,\n LATENCY_METRIC_NAME: latencyMetricName,\n PRODUCT_TELEMETRY_ENDPOINT: productTelemetryEndpoint,\n PRODUCT_TELEMETRY_ENABLED: productTelemetryEnabled,\n IS_HYPERFORCE: isHyperforce,\n BREAK_GLASS_DISABLE_GLOBALLY: breakGlassDisableGlobally,\n ADMIN_TOOLS_ENABLED: adminToolsEnabled,\n CSP_ALLOWED_DOMAINS: cspAllowedDomains,\n } = cleansedVars;\n\n let jwtUsername = '';\n\n this.siteName = siteName ?? '';\n\n this.sslKey = sslKey?.trim() ?? '';\n this.sslCert = sslCert?.trim() ?? '';\n this.httpPort = parseNumber(cleansedVars[httpPortEnvVarName?.trim() || 'PORT'], {\n defaultValue: 3927,\n minValue: 1,\n maxValue: 65535,\n });\n this.corsOriginConfig = getCorsOriginConfig(corsOriginConfig?.trim() ?? '');\n this.datasourceCredentials = datasourceCredentials ?? '';\n this.disableSessionManagement = disableSessionManagement === 'true';\n\n this.tableauServerVersionCheckIntervalInHours = parseNumber(\n tableauServerVersionCheckIntervalInHours,\n {\n defaultValue: 1,\n minValue: 1,\n maxValue: 24 * 7, // 7 days\n },\n );\n\n this.passthroughAuthUserSessionCheckIntervalInMinutes = parseNumber(\n passthroughAuthUserSessionCheckIntervalInMinutes,\n {\n defaultValue: 10,\n minValue: 0,\n maxValue: 60 * 24, // 24 hours\n },\n );\n\n this.mcpSiteSettingsCheckIntervalInMinutes = parseNumber(\n mcpSiteSettingsCheckIntervalInMinutes,\n {\n defaultValue: 10,\n minValue: 1,\n maxValue: 60 * 24, // 24 hours\n },\n );\n\n this.enableMcpSiteSettings = enableMcpSiteSettings !== 'false';\n this.allowSitesToConfigureRequestOverrides = allowSitesToConfigureRequestOverrides === 'true';\n this.enablePassthroughAuth = enablePassthroughAuth === 'true';\n const disableOauthOverride = disableOauth === 'true';\n const disableScopes = oauthDisableScopes === 'true';\n const enforceScopes = !disableScopes;\n const embeddedAuthzServer = oauthEmbeddedAuthzServer !== 'false';\n\n if (this.allowSitesToConfigureRequestOverrides && !this.enableMcpSiteSettings) {\n throw new Error(\n 'ALLOW_SITES_TO_CONFIGURE_REQUEST_OVERRIDES is \"true\", but MCP site settings are not enabled.',\n );\n }\n\n this.oauth = {\n enabled: disableOauthOverride ? false : !!oauthIssuer,\n embeddedAuthzServer,\n issuer: oauthIssuer ?? '',\n resourceUri: oauthResourceUri ?? `http://127.0.0.1:${this.httpPort}`,\n globalResourceUris: oauthGlobalResourceUris\n ? oauthGlobalResourceUris\n .split(',')\n .map((uri) => uri.trim())\n .filter(Boolean)\n : [],\n redirectUri: redirectUri || (oauthIssuer ? `${oauthIssuer}/Callback` : ''),\n lockSite: oauthLockSite !== 'false', // Site locking is enabled by default\n jwePrivateKey: oauthJwePrivateKey ?? '',\n jwePrivateKeyPath: oauthJwePrivateKeyPath ?? '',\n jwePrivateKeyPassphrase: oauthJwePrivateKeyPassphrase || undefined,\n dnsServers: dnsServers\n ? dnsServers.split(',').map((ip) => ip.trim())\n : ['1.1.1.1', '1.0.0.1' /* Cloudflare public DNS */],\n authzCodeTimeoutMs: parseNumber(authzCodeTimeoutMs, {\n defaultValue: milliseconds.fromMinutes(10),\n minValue: 0,\n maxValue: milliseconds.fromHours(1),\n }),\n accessTokenTimeoutMs: parseNumber(accessTokenTimeoutMs, {\n defaultValue: milliseconds.fromHours(1),\n minValue: 0,\n maxValue: milliseconds.fromDays(30),\n }),\n refreshTokenTimeoutMs: parseNumber(refreshTokenTimeoutMs, {\n defaultValue: milliseconds.fromDays(30),\n minValue: 0,\n maxValue: milliseconds.fromYears(1),\n }),\n clientIdSecretPairs: oauthClientIdSecretPairs\n ? oauthClientIdSecretPairs.split(',').reduce<Record<string, string>>((acc, curr) => {\n const [clientId, secret] = curr.split(':');\n if (clientId && secret) {\n acc[clientId] = secret;\n }\n return acc;\n }, {})\n : null,\n enforceScopes,\n advertiseApiScopes: advertiseApiScopes === 'true',\n };\n\n if (\n this.oauth.clientIdSecretPairs &&\n Object.keys(this.oauth.clientIdSecretPairs).length === 0\n ) {\n throw new Error(\n `OAUTH_CLIENT_ID_SECRET_PAIRS is in an invalid format: ${oauthClientIdSecretPairs}. Should be in the format: clientId:secret`,\n );\n }\n\n const parsedProvider = isTelemetryProvider(telemetryProvider) ? telemetryProvider : 'noop';\n if (parsedProvider === 'custom') {\n if (!telemetryProviderConfig) {\n throw new Error(\n 'TELEMETRY_PROVIDER_CONFIG is required when TELEMETRY_PROVIDER is \"custom\"',\n );\n }\n this.telemetry = {\n provider: 'custom',\n providerConfig: providerConfigSchema.parse(JSON.parse(telemetryProviderConfig)),\n };\n } else {\n this.telemetry = {\n provider: 'noop',\n };\n }\n\n this.latencyMetricName = latencyMetricName || 'http_server_1agg1_request_duration';\n this.productTelemetryEndpoint =\n productTelemetryEndpoint || 'https://prod.telemetry.tableausoftware.com';\n this.productTelemetryEnabled = productTelemetryEnabled !== 'false';\n this.isHyperforce = isHyperforce === 'true';\n this.breakGlassDisableGlobally = breakGlassDisableGlobally === 'true';\n this.adminToolsEnabled = adminToolsEnabled === 'true';\n\n this.auth = isAuthType(auth) ? auth : this.oauth.enabled ? 'oauth' : 'pat';\n this.transport = isTransport(transport) ? transport : this.oauth.enabled ? 'http' : 'stdio';\n\n if (this.transport === 'http' && !disableOauthOverride && !this.oauth.issuer) {\n throw new Error(\n 'OAUTH_ISSUER must be set when TRANSPORT is \"http\" unless DANGEROUSLY_DISABLE_OAUTH is \"true\"',\n );\n }\n\n if (this.auth === 'oauth') {\n if (disableOauthOverride) {\n throw new Error('When AUTH is \"oauth\", DANGEROUSLY_DISABLE_OAUTH cannot be \"true\"');\n }\n\n if (!this.oauth.issuer) {\n throw new Error('When AUTH is \"oauth\", OAUTH_ISSUER must be set');\n }\n } else {\n invariant(server, 'The environment variable SERVER is not set');\n validateServer(server);\n }\n\n if (this.oauth.enabled) {\n if (this.oauth.embeddedAuthzServer) {\n invariant(this.oauth.redirectUri, 'The environment variable OAUTH_REDIRECT_URI is not set');\n\n if (!this.oauth.jwePrivateKey && !this.oauth.jwePrivateKeyPath) {\n throw new Error(\n 'One of the environment variables: OAUTH_JWE_PRIVATE_KEY_PATH or OAUTH_JWE_PRIVATE_KEY must be set',\n );\n }\n\n if (this.oauth.jwePrivateKey && this.oauth.jwePrivateKeyPath) {\n throw new Error(\n 'Only one of the environment variables: OAUTH_JWE_PRIVATE_KEY or OAUTH_JWE_PRIVATE_KEY_PATH must be set',\n );\n }\n\n if (\n this.oauth.jwePrivateKeyPath &&\n process.env.TABLEAU_MCP_TEST !== 'true' &&\n !existsSync(this.oauth.jwePrivateKeyPath)\n ) {\n throw new Error(\n `OAuth JWE private key path does not exist: ${this.oauth.jwePrivateKeyPath}`,\n );\n }\n }\n\n if (this.transport === 'stdio') {\n throw new Error('TRANSPORT must be \"http\" when OAUTH_ISSUER is set');\n }\n }\n\n if (this.auth === 'pat') {\n invariant(patName, 'The environment variable PAT_NAME is not set');\n invariant(patValue, 'The environment variable PAT_VALUE is not set');\n } else if (this.auth === 'direct-trust') {\n invariant(jwtSubClaim, 'The environment variable JWT_SUB_CLAIM is not set');\n invariant(clientId, 'The environment variable CONNECTED_APP_CLIENT_ID is not set');\n invariant(secretId, 'The environment variable CONNECTED_APP_SECRET_ID is not set');\n invariant(secretValue, 'The environment variable CONNECTED_APP_SECRET_VALUE is not set');\n\n jwtUsername = jwtSubClaim ?? '';\n } else if (this.auth === 'uat') {\n invariant(uatTenantId, 'The environment variable UAT_TENANT_ID is not set');\n invariant(uatIssuer, 'The environment variable UAT_ISSUER is not set');\n\n if (!uatUsernameClaim && !jwtSubClaim) {\n throw new Error(\n 'One of the environment variables: UAT_USERNAME_CLAIM or JWT_SUB_CLAIM must be set',\n );\n }\n\n jwtUsername = uatUsernameClaim ?? jwtSubClaim ?? '';\n\n if (!uatPrivateKey && !uatPrivateKeyPath) {\n throw new Error(\n 'One of the environment variables: UAT_PRIVATE_KEY_PATH or UAT_PRIVATE_KEY must be set',\n );\n }\n\n if (uatPrivateKey && uatPrivateKeyPath) {\n throw new Error(\n 'Only one of the environment variables: UAT_PRIVATE_KEY or UAT_PRIVATE_KEY_PATH must be set',\n );\n }\n\n if (\n uatPrivateKeyPath &&\n process.env.TABLEAU_MCP_TEST !== 'true' &&\n !existsSync(uatPrivateKeyPath)\n ) {\n throw new Error(`UAT private key path does not exist: ${uatPrivateKeyPath}`);\n }\n }\n\n this.server = server ?? '';\n\n // Configure CSP domains with serverOrigin in defaults\n const serverOrigin = this.server ? new URL(this.server).origin : '';\n const defaultDomains = [\n 'https://*.online.tableau.com',\n 'https://*.tableau.com',\n ...(serverOrigin ? [serverOrigin] : []),\n ];\n const customDomains = cspAllowedDomains\n ? cspAllowedDomains.split(',').map((d) => d.trim())\n : [];\n this.cspAllowedDomains = [...defaultDomains, ...customDomains];\n\n this.patName = patName ?? '';\n this.patValue = patValue ?? '';\n this.jwtUsername = jwtUsername ?? '';\n this.connectedAppClientId = clientId ?? '';\n this.connectedAppSecretId = secretId ?? '';\n this.connectedAppSecretValue = secretValue ?? '';\n this.uatTenantId = uatTenantId ?? '';\n this.uatIssuer = uatIssuer ?? '';\n this.uatUsernameClaimName = uatUsernameClaimName || 'email';\n this.uatPrivateKey =\n uatPrivateKey || (uatPrivateKeyPath ? readFileSync(uatPrivateKeyPath, 'utf8') : '');\n this.uatKeyId = uatKeyId ?? '';\n this.jwtAdditionalPayload = jwtAdditionalPayload || '{}';\n }\n}\n\nfunction validateServer(server: string): void {\n if (!['https://', 'http://'].find((prefix) => server.startsWith(prefix))) {\n throw new Error(\n `The environment variable SERVER must start with \"http://\" or \"https://\": ${server}`,\n );\n }\n\n try {\n new URL(server);\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(\n `The environment variable SERVER is not a valid URL: ${server} -- ${errorMessage}`,\n );\n }\n}\n\nfunction getCorsOriginConfig(corsOriginConfig: string): CorsOptions['origin'] {\n if (!corsOriginConfig) {\n return true;\n }\n\n if (corsOriginConfig.match(/^true|false$/i)) {\n return corsOriginConfig.toLowerCase() === 'true';\n }\n\n if (corsOriginConfig === '*') {\n return '*';\n }\n\n if (corsOriginConfig.startsWith('[') && corsOriginConfig.endsWith(']')) {\n try {\n const origins = JSON.parse(corsOriginConfig) as Array<string>;\n return origins.map((origin) => new URL(origin).origin);\n } catch {\n throw new Error(\n `The environment variable CORS_ORIGIN_CONFIG is not a valid array of URLs: ${corsOriginConfig}`,\n );\n }\n }\n\n try {\n return new URL(corsOriginConfig).origin;\n } catch {\n throw new Error(\n `The environment variable CORS_ORIGIN_CONFIG is not a valid URL: ${corsOriginConfig}`,\n );\n }\n}\n\nexport const getConfig = (): Config => new Config();\n", "import { join } from 'path';\n\nimport { parseLogLevel } from './logging/logger.js';\nimport { LoggerType, parseLoggerTypes } from './logging/loggerType.js';\nimport { LogLevel } from './logging/types.js';\nimport { isTransport, TransportName } from './transports.js';\nimport { getDirname } from './utils/getDirname.js';\nimport { milliseconds } from './utils/milliseconds.js';\nimport { parseNumber } from './utils/parseNumber.js';\n\nconst __dirname = getDirname();\n\nexport class BaseConfig {\n transport: TransportName;\n defaultNotificationLevel: string;\n logLevel: LogLevel;\n loggers: Set<LoggerType>;\n fileLoggerDirectory: string;\n disableLogMasking: boolean;\n maxRequestTimeoutMs: number;\n notificationPayloadMaxBytes: number;\n\n constructor() {\n const cleansedVars = removeClaudeMcpBundleUserConfigTemplates(process.env);\n const {\n TRANSPORT: transport,\n DEFAULT_NOTIFICATION_LEVEL: defaultNotificationLevel,\n LOG_LEVEL: logLevel,\n ENABLED_LOGGERS: logging,\n FILE_LOGGER_DIRECTORY: fileLoggerDirectory,\n DISABLE_LOG_MASKING: disableLogMasking,\n MAX_REQUEST_TIMEOUT_MS: maxRequestTimeoutMs,\n NOTIFICATION_PAYLOAD_MAX_BYTES: notificationPayloadMaxBytes,\n } = cleansedVars;\n\n this.transport = isTransport(transport) ? transport : 'stdio';\n this.defaultNotificationLevel = defaultNotificationLevel ?? 'debug';\n this.logLevel = parseLogLevel(logLevel);\n this.loggers = parseLoggerTypes(logging);\n this.fileLoggerDirectory = fileLoggerDirectory || join(__dirname, 'logs');\n this.disableLogMasking = disableLogMasking === 'true';\n this.maxRequestTimeoutMs = parseNumber(maxRequestTimeoutMs, {\n defaultValue: milliseconds.fromMinutes(10),\n minValue: 5000,\n maxValue: milliseconds.fromHours(1),\n });\n this.notificationPayloadMaxBytes = parseNumber(notificationPayloadMaxBytes, {\n defaultValue: 8192,\n minValue: 1,\n });\n }\n}\n\n// When the user does not provide a site name in the Claude MCP Bundle configuration,\n// Claude doesn't replace its value and sets the site name to \"${user_config.site_name}\".\nexport function removeClaudeMcpBundleUserConfigTemplates(\n envVars: Record<string, string | undefined>,\n): Record<string, string | undefined> {\n return Object.entries(envVars).reduce<Record<string, string | undefined>>((acc, [key, value]) => {\n if (value?.startsWith('${user_config.')) {\n acc[key] = '';\n } else {\n acc[key] = value;\n }\n return acc;\n }, {});\n}\n\nexport const getBaseConfig = (): BaseConfig => new BaseConfig();\n", "import { appendFile } from 'node:fs/promises';\n\nimport { existsSync, mkdirSync } from 'fs';\nimport { join } from 'path';\n\nimport { getExceptionMessage } from '../utils/getExceptionMessage.js';\nimport type { LogEntry } from './types.js';\n\nlet _fileLogger: FileLogger | undefined;\n\nexport const setFileLogger = (logger: FileLogger): void => {\n _fileLogger = logger;\n};\n\nexport const getFileLogger = (): FileLogger | undefined => _fileLogger;\n\nexport class FileLogger {\n private readonly _logDirectory: string;\n private readonly _fileMutexes = new Map<string, Promise<void>>();\n\n constructor({ logDirectory }: { logDirectory: string }) {\n this._logDirectory = logDirectory;\n\n if (!existsSync(this._logDirectory)) {\n mkdirSync(this._logDirectory, { recursive: true });\n }\n }\n\n async log(entry: LogEntry): Promise<void> {\n // Create a new log file each hour e.g. 2025-10-15T21-00-00-000Z.log\n const timestamp = new Date().toISOString();\n const filename = `${new Date(new Date().setMinutes(0, 0, 0)).toISOString().replace(/[:.]/g, '-')}.log`;\n const logFilePath = join(this._logDirectory, filename);\n\n // Get or create a mutex for this specific log file\n const mutexKey = logFilePath;\n const currentMutex = this._fileMutexes.get(mutexKey) ?? Promise.resolve();\n\n // Chain the file write operation after the current mutex\n const newMutex = currentMutex.then(async () => {\n try {\n // appendFile will create the file if it doesn't exist\n await appendFile(logFilePath, JSON.stringify({ timestamp, ...entry }) + '\\n');\n } catch (error) {\n process.stderr.write(\n `Failed to write to log file ${logFilePath}: ${getExceptionMessage(error)}\\n`,\n );\n }\n });\n\n this._fileMutexes.set(mutexKey, newMutex);\n\n // Clean up completed mutexes to prevent memory leaks\n newMutex.finally(() => {\n if (this._fileMutexes.get(mutexKey) === newMutex) {\n this._fileMutexes.delete(mutexKey);\n }\n });\n\n // Wait for the file write operation to complete\n await newMutex;\n }\n}\n", "import type { LoggingLevel } from '@modelcontextprotocol/sdk/types.js';\n\nexport type LogLevel = LoggingLevel;\nexport const orderedLogLevels = [\n 'debug',\n 'info',\n 'notice',\n 'warning',\n 'error',\n 'critical',\n 'alert',\n 'emergency',\n] as const;\n\nexport const logLevelSeverity = Object.fromEntries(\n orderedLogLevels.map((level, index) => [level, index]),\n) as Record<LogLevel, number>;\n\nexport type LogEntry = {\n message: string;\n data?: unknown;\n level: LogLevel;\n logger: string | undefined;\n};\n", "import { getBaseConfig } from '../config.shared.js';\nimport { getFileLogger } from './fileLogger.js';\nimport { LogEntry, LogLevel, logLevelSeverity } from './types.js';\n\nexport function shouldLog(entryLevel: LogLevel, minLevel: LogLevel): boolean {\n return logLevelSeverity[entryLevel] >= logLevelSeverity[minLevel];\n}\n\nfunction isLogLevel(value: string): value is LogLevel {\n return value in logLevelSeverity;\n}\n\nexport function parseLogLevel(value: string | undefined): LogLevel {\n const level = value?.trim();\n if (level && isLogLevel(level)) {\n return level;\n }\n return 'info';\n}\n\n/**\n * Custom JSON.stringify replacer that serializes Error objects properly.\n * Removes the config field from AxiosError to avoid logging sensitive headers.\n */\nfunction errorReplacer(data: unknown): unknown {\n if (data instanceof Error) {\n return {\n name: data.name,\n message: data.message,\n stack: data.stack,\n ...(data.cause !== undefined && { cause: data.cause }),\n };\n }\n\n return data;\n}\n\nexport function log(entry: LogEntry): void {\n const config = getBaseConfig();\n if (!shouldLog(entry.level, config.logLevel)) {\n return;\n }\n\n // we are removing any unnecessary fields that may also leak sensitive data\n entry.data = errorReplacer(entry.data);\n\n if (config.loggers.has('appLogger')) {\n const message = JSON.stringify(entry);\n if (config.transport === 'http') {\n // eslint-disable-next-line no-console -- console.log is intentional here since the transport is not stdio.\n console.log(message);\n } else {\n process.stderr.write(message + '\\n');\n }\n }\n if (config.loggers.has('fileLogger')) {\n getFileLogger()?.log(entry);\n }\n}\n", "export const loggerTypes = ['fileLogger', 'appLogger'] as const;\nexport type LoggerType = (typeof loggerTypes)[number];\nconst validLoggerTypes = new Set(loggerTypes);\n\nexport function parseLoggerTypes(value: string | undefined): Set<LoggerType> {\n if (!value) {\n return new Set<LoggerType>(['appLogger']);\n }\n return new Set(\n value\n .split(',')\n .map((s) => s.trim())\n .filter((s): s is LoggerType => validLoggerTypes.has(s as LoggerType)),\n );\n}\n", "const transports = ['stdio', 'http'] as const;\nexport type TransportName = (typeof transports)[number];\nexport function isTransport(transport: unknown): transport is TransportName {\n return !!transports.find((t) => t === transport);\n}\n", "export function getDirname(): string {\n if (typeof __dirname === 'string') {\n return __dirname;\n }\n\n throw new Error('__dirname is not set');\n}\n", "export const milliseconds = {\n fromSeconds: (seconds: number) => seconds * 1000,\n fromMinutes: (minutes: number) => minutes * 60 * 1000,\n fromHours: (hours: number) => hours * 60 * 60 * 1000,\n fromDays: (days: number) => days * 24 * 60 * 60 * 1000,\n fromWeeks: (weeks: number) => weeks * 7 * 24 * 60 * 60 * 1000,\n fromMonths: (months: number) => months * 30 * 24 * 60 * 60 * 1000,\n fromYears: (years: number) => years * 365.25 * 24 * 60 * 60 * 1000,\n};\n", "export function parseNumber(\n value: string | undefined,\n {\n defaultValue,\n minValue,\n maxValue,\n }: { defaultValue: number; minValue?: number; maxValue?: number } = {\n defaultValue: 0,\n minValue: Number.NEGATIVE_INFINITY,\n maxValue: Number.POSITIVE_INFINITY,\n },\n): number {\n if (!value) {\n return defaultValue;\n }\n\n const number = parseFloat(value);\n return isNaN(number) ||\n (minValue !== undefined && number < minValue) ||\n (maxValue !== undefined && number > maxValue)\n ? defaultValue\n : number;\n}\n", "import { z } from 'zod';\n\n/**\n * Telemetry provider interface for metrics collection.\n */\nexport interface TelemetryProvider {\n /**\n * Initialize the telemetry provider.\n */\n initialize(): void;\n\n /**\n * Record a custom metric with the given name and attributes.\n *\n * @param name - The metric name (e.g., 'apm_mcp_tool_calls')\n * @param value - The metric value (default: 1 for counters)\n * @param attributes - Dimensions/tags for the metric\n *\n * @example\n * ```typescript\n * telemetry.recordMetric('apm_mcp_tool_calls', 1, {\n * tool_name: 'list-pulse-metric-subscriptions',\n * });\n * ```\n */\n recordMetric(name: string, value: number, attributes: TelemetryAttributes): void;\n\n /**\n * Record a histogram observation (e.g., latency) with the given name and attributes.\n *\n * @param name - The metric name (e.g., 'http_server_request_duration')\n * @param value - The observed value (e.g., duration in milliseconds)\n * @param attributes - Dimensions/tags for the metric\n *\n * @example\n * ```typescript\n * telemetry.recordHistogram('apm_mcp_tool_duration', 142.5, {\n * tool_name: 'get-datasource-metadata',\n * success: true,\n * });\n * ```\n */\n recordHistogram(name: string, value: number, attributes: TelemetryAttributes): void;\n}\n\n/**\n * Schema for telemetry attributes.\n * Values can be strings, numbers, booleans, or undefined.\n */\nexport const telemetryAttributesSchema = z.record(\n z.string(),\n z.union([z.string(), z.number(), z.boolean(), z.undefined()]),\n);\nexport type TelemetryAttributes = z.infer<typeof telemetryAttributesSchema>;\n\n/**\n * Valid telemetry provider names\n */\nexport const telemetryProviderSchema = z.enum(['noop', 'custom']);\nexport type TelemetryProviderType = z.infer<typeof telemetryProviderSchema>;\n\n/**\n * Schema for noop telemetry config (no telemetry)\n */\nexport const noopTelemetryConfigSchema = z.object({\n provider: z.literal('noop'),\n});\n\n/**\n * Schema for custom telemetry provider config.\n * Requires 'module' field, allows additional provider-specific options.\n */\nexport const providerConfigSchema = z\n .object({\n module: z.string({ required_error: 'Custom provider requires \"module\" path' }),\n })\n .passthrough();\n\n/**\n * Schema for custom telemetry config\n *\n * @example\n * ```json\n * {\n * \"provider\": \"custom\",\n * \"providerConfig\": {\n * \"module\": \"./my-otel-provider.js\"\n * }\n * }\n * ```\n */\nexport const customTelemetryConfigSchema = z.object({\n provider: z.literal('custom'),\n providerConfig: providerConfigSchema,\n});\n\n/**\n * Combined telemetry config schema (discriminated union)\n */\nexport const telemetryConfigSchema = z.discriminatedUnion('provider', [\n noopTelemetryConfigSchema,\n customTelemetryConfigSchema,\n]);\n\nexport type TelemetryConfig = z.infer<typeof telemetryConfigSchema>;\n\n/**\n * Type guard for telemetry provider names\n */\nexport function isTelemetryProvider(provider: unknown): provider is TelemetryProviderType {\n return telemetryProviderSchema.safeParse(provider).success;\n}\n", "export default function invariant(condition: unknown, message?: string): asserts condition {\n if (!condition) {\n throw new Error(message ? message : 'Invariant Violation');\n }\n}\n", "/**\n * NoOp telemetry provider - does nothing.\n * This is the default provider when telemetry is disabled.\n *\n * Zero overhead implementation that can be safely used in production\n * when telemetry is not needed.\n */\n\nimport { TelemetryAttributes, TelemetryProvider } from './types.js';\n\nexport class NoOpTelemetryProvider implements TelemetryProvider {\n initialize(): void {\n // No-op\n }\n\n recordMetric(_name: string, _value: number, _attributes: TelemetryAttributes): void {\n // No-op\n }\n\n recordHistogram(_name: string, _value: number, _attributes: TelemetryAttributes): void {\n // No-op\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["import_dotenv", "import_path", "import_fs", "import_path", "_fileLogger", "getFileLogger", "_fileLogger", "orderedLogLevels", "logLevelSeverity", "level", "index", "shouldLog", "entryLevel", "minLevel", "logLevelSeverity", "isLogLevel", "value", "parseLogLevel", "level", "errorReplacer", "data", "log", "entry", "config", "getBaseConfig", "message", "getFileLogger", "loggerTypes", "validLoggerTypes", "parseLoggerTypes", "value", "s", "transports", "isTransport", "transport", "getDirname", "milliseconds", "seconds", "minutes", "hours", "days", "weeks", "months", "years", "parseNumber", "value", "defaultValue", "minValue", "maxValue", "number", "__dirname", "getDirname", "BaseConfig", "cleansedVars", "removeClaudeMcpBundleUserConfigTemplates", "transport", "defaultNotificationLevel", "logLevel", "logging", "fileLoggerDirectory", "disableLogMasking", "maxRequestTimeoutMs", "notificationPayloadMaxBytes", "isTransport", "parseLogLevel", "parseLoggerTypes", "parseNumber", "milliseconds", "envVars", "acc", "key", "value", "getBaseConfig", "import_zod", "telemetryAttributesSchema", "telemetryProviderSchema", "noopTelemetryConfigSchema", "providerConfigSchema", "customTelemetryConfigSchema", "telemetryConfigSchema", "isTelemetryProvider", "provider", "invariant", "condition", "message", "authTypes", "isAuthType", "auth", "type", "Config", "BaseConfig", "cleansedVars", "removeClaudeMcpBundleUserConfigTemplates", "server", "siteName", "transport", "sslKey", "sslCert", "httpPortEnvVarName", "corsOriginConfig", "patName", "patValue", "jwtSubClaim", "clientId", "secretId", "secretValue", "uatTenantId", "uatIssuer", "uatUsernameClaimName", "uatUsernameClaim", "uatPrivateKey", "uatPrivateKeyPath", "uatKeyId", "jwtAdditionalPayload", "datasourceCredentials", "disableSessionManagement", "tableauServerVersionCheckIntervalInHours", "passthroughAuthUserSessionCheckIntervalInMinutes", "mcpSiteSettingsCheckIntervalInMinutes", "enableMcpSiteSettings", "allowSitesToConfigureRequestOverrides", "enablePassthroughAuth", "disableOauth", "oauthEmbeddedAuthzServer", "oauthIssuer", "oauthLockSite", "oauthJwePrivateKey", "oauthJwePrivateKeyPath", "oauthJwePrivateKeyPassphrase", "oauthResourceUri", "oauthGlobalResourceUris", "redirectUri", "oauthClientIdSecretPairs", "dnsServers", "advertiseApiScopes", "authzCodeTimeoutMs", "accessTokenTimeoutMs", "refreshTokenTimeoutMs", "oauthDisableScopes", "telemetryProvider", "telemetryProviderConfig", "latencyMetricName", "productTelemetryEndpoint", "productTelemetryEnabled", "isHyperforce", "breakGlassDisableGlobally", "adminToolsEnabled", "cspAllowedDomains", "jwtUsername", "parseNumber", "getCorsOriginConfig", "disableOauthOverride", "enforceScopes", "embeddedAuthzServer", "uri", "ip", "milliseconds", "acc", "curr", "secret", "isTelemetryProvider", "providerConfigSchema", "isTransport", "invariant", "validateServer", "serverOrigin", "defaultDomains", "customDomains", "d", "prefix", "error", "errorMessage", "origin", "getConfig", "NoOpTelemetryProvider", "_name", "_value", "_attributes", "getInstanceMethods", "cls", "name", "isRecord", "obj", "validateTelemetryProvider", "provider", "missingMethods", "NoOpTelemetryProvider", "method", "initializeTelemetry", "config", "getConfig", "provider", "loadCustomProvider", "NoOpTelemetryProvider", "error", "log", "fallbackProvider", "modulePath", "resolvedPath", "module", "ProviderClass", "validateTelemetryProvider", "errorMessage", "dotenv", "initializeTelemetry", "error"]
3
+ "sources": ["../../src/telemetry/tracing.ts", "../../src/telemetry/init.ts", "../../src/config.ts", "../../src/config.shared.ts", "../../src/logging/fileLogger.ts", "../../src/logging/types.ts", "../../src/logging/logger.ts", "../../src/logging/loggerType.ts", "../../src/transports.ts", "../../src/utils/getDirname.ts", "../../src/utils/milliseconds.ts", "../../src/utils/parseNumber.ts", "../../src/features/types.ts", "../../src/telemetry/types.ts", "../../src/utils/invariant.ts", "../../src/telemetry/noop.ts"],
4
+ "sourcesContent": ["/**\n * APM agent preload script\n *\n * Use with node -r flag to start APM agent before application code:\n * node -r ./build/telemetry/tracing.js build/index.js\n *\n * Environment variables:\n * - TELEMETRY_PROVIDER=custom - Use custom telemetry provider (default: noop)\n */\n\n// Load .env before anything else\nimport dotenv from 'dotenv';\ndotenv.config();\n\nimport { initializeTelemetry } from './init.js';\n\ntry {\n initializeTelemetry();\n} catch (error) {\n console.warn('Failed to initialize telemetry:', error);\n}\n", "/**\n * Telemetry initialization and provider factory\n */\n\nimport { resolve } from 'path';\n\nimport { getConfig } from '../config.js';\nimport { log } from '../logging/logger.js';\nimport { NoOpTelemetryProvider } from './noop.js';\nimport type { TelemetryProvider } from './telemetryProvider.js';\n\n/**\n * Get all instance methods from a class prototype\n */\nfunction getInstanceMethods(cls: new (...args: unknown[]) => unknown): string[] {\n return Object.getOwnPropertyNames(cls.prototype).filter(\n (name) => name !== 'constructor' && typeof cls.prototype[name] === 'function',\n );\n}\n\nfunction isRecord(obj: unknown): obj is Record<string, unknown> {\n return typeof obj === 'object' && obj !== null && !Array.isArray(obj);\n}\n\n/**\n * Validate that a provider implements all required TelemetryProvider methods\n */\nfunction validateTelemetryProvider(provider: unknown): asserts provider is TelemetryProvider {\n if (!isRecord(provider)) {\n throw new Error('Provider must be an object');\n }\n\n const requiredMethods = getInstanceMethods(NoOpTelemetryProvider);\n // Keep only methods that provider doesn't have (i.e., missing or miscategorized methods)\n const missingMethods = requiredMethods.filter((method) => typeof provider[method] !== 'function');\n\n if (missingMethods.length > 0) {\n throw new Error(`Custom provider missing required methods: ${missingMethods.join(', ')}`);\n }\n}\n\n// Use global to share provider across bundles (tracing.js and index.js)\ndeclare global {\n var __telemetryProvider: TelemetryProvider | undefined;\n}\n\n/**\n * Get the current telemetry provider instance.\n * If not initialized, returns a NoOp provider.\n *\n * @returns The telemetry provider\n */\nexport function getTelemetryProvider(): TelemetryProvider {\n if (!global.__telemetryProvider) {\n // return a NoOp provider for this request if telemetry hasn't been initialized\n return new NoOpTelemetryProvider();\n }\n return global.__telemetryProvider;\n}\n\n/**\n * Initialize the telemetry provider based on configuration.\n *\n * This function should be called early in application startup, before any\n * HTTP requests or other instrumented operations occur.\n *\n * @returns A configured telemetry provider\n *\n * @example\n * function main() {\n * // Initialize telemetry first\n * const telemetry = initializeTelemetry();\n *\n * // Start application...\n * }\n */\nexport function initializeTelemetry(): TelemetryProvider {\n const config = getConfig();\n let provider: TelemetryProvider;\n\n try {\n // Select provider based on configuration\n switch (config.telemetry.provider) {\n case 'custom':\n // Load custom provider from user's filesystem\n provider = loadCustomProvider(config.telemetry.providerConfig);\n break;\n\n case 'noop':\n provider = new NoOpTelemetryProvider();\n break;\n }\n\n // Initialize the provider\n provider.initialize();\n global.__telemetryProvider = provider;\n return provider;\n } catch (error) {\n log({\n message: 'Failed to initialize telemetry provider',\n level: 'error',\n logger: 'telemetry',\n data: error,\n });\n log({ message: 'Falling back to NoOp telemetry provider', level: 'info', logger: 'telemetry' });\n\n // Fallback to NoOp on error - telemetry failures shouldn't break the application\n const fallbackProvider = new NoOpTelemetryProvider();\n fallbackProvider.initialize();\n global.__telemetryProvider = fallbackProvider;\n return fallbackProvider;\n }\n}\n\n/**\n * Load a custom telemetry provider from user's filesystem or npm package.\n *\n * The custom provider module should export a default class that implements TelemetryProvider.\n *\n * @param config - Provider configuration containing the module path\n * @returns A configured custom telemetry provider\n *\n * @example Custom provider from file\n * TELEMETRY_PROVIDER=custom\n * TELEMETRY_PROVIDER_CONFIG='{\"module\":\"./my-telemetry.js\"}'\n */\nfunction loadCustomProvider(config?: Record<string, unknown>): TelemetryProvider {\n if (!config?.module) {\n throw new Error(\n 'Custom telemetry provider requires \"module\" in providerConfig. ' +\n 'Example: TELEMETRY_PROVIDER_CONFIG=\\'{\"module\":\"./my-telemetry.js\"}\\'',\n );\n }\n\n const modulePath = config.module;\n\n if (typeof modulePath !== 'string') {\n throw new Error('Custom telemetry provider requires \"module\" to be a string');\n }\n\n // Determine if it's a file path or npm package name\n let resolvedPath: string;\n\n if (modulePath.startsWith('.') || modulePath.startsWith('/')) {\n // File path - resolve relative to process working directory (user's project root)\n resolvedPath = resolve(process.cwd(), modulePath);\n } else {\n // npm package name - require as-is\n resolvedPath = modulePath;\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports -- Sync load for preload script\n const module = require(resolvedPath);\n\n // Look for default export or named export \"TelemetryProvider\"\n const ProviderClass = module.default || module.TelemetryProvider;\n\n if (!ProviderClass) {\n throw new Error(\n `Module ${modulePath} must export a default class or named export \"TelemetryProvider\" ` +\n 'that implements the TelemetryProvider interface',\n );\n }\n\n // Instantiate the provider with the full config\n const provider = new ProviderClass(config);\n\n // Validate the provider implements TelemetryProvider interface\n validateTelemetryProvider(provider);\n return provider;\n } catch (error) {\n // Provide helpful error message with common issues\n let errorMessage = `Failed to load custom telemetry provider from \"${modulePath}\". `;\n\n if (error instanceof Error && 'code' in error && error.code === 'MODULE_NOT_FOUND') {\n errorMessage +=\n 'Module not found. ' +\n 'If using a file path, ensure the file exists and the path is correct. ' +\n 'If using an npm package, ensure it is installed.';\n } else {\n errorMessage += `Error: ${error}`;\n }\n\n throw new Error(errorMessage);\n }\n}\n", "import { CorsOptions } from 'cors';\nimport { existsSync, readFileSync } from 'fs';\n\nimport { BaseConfig, removeClaudeMcpBundleUserConfigTemplates } from './config.shared.js';\nimport {\n FeatureGateConfig,\n isFeatureGateProvider,\n providerConfigSchema as featureGateProviderConfigSchema,\n} from './features/types.js';\nimport { isTelemetryProvider, providerConfigSchema, TelemetryConfig } from './telemetry/types.js';\nimport { isTransport } from './transports.js';\nimport invariant from './utils/invariant.js';\nimport { milliseconds } from './utils/milliseconds.js';\nimport { parseNumber } from './utils/parseNumber.js';\n\nconst authTypes = ['pat', 'uat', 'direct-trust', 'oauth'] as const;\ntype AuthType = (typeof authTypes)[number];\n\nfunction isAuthType(auth: unknown): auth is AuthType {\n return authTypes.some((type) => type === auth);\n}\n\nexport class Config extends BaseConfig {\n auth: AuthType;\n server: string;\n sslKey: string;\n sslCert: string;\n httpPort: number;\n corsOriginConfig: CorsOptions['origin'];\n siteName: string;\n patName: string;\n patValue: string;\n jwtUsername: string;\n connectedAppClientId: string;\n connectedAppSecretId: string;\n connectedAppSecretValue: string;\n uatTenantId: string;\n uatIssuer: string;\n uatUsernameClaimName: string;\n uatPrivateKey: string;\n uatKeyId: string;\n jwtAdditionalPayload: string;\n datasourceCredentials: string;\n disableSessionManagement: boolean;\n tableauServerVersionCheckIntervalInHours: number;\n passthroughAuthUserSessionCheckIntervalInMinutes: number;\n mcpSiteSettingsCheckIntervalInMinutes: number;\n enableMcpSiteSettings: boolean;\n allowSitesToConfigureRequestOverrides: boolean;\n enablePassthroughAuth: boolean;\n oauth: {\n enabled: boolean;\n embeddedAuthzServer: boolean;\n issuer: string;\n redirectUri: string;\n resourceUri: string;\n globalResourceUris: string[];\n lockSite: boolean;\n jwePrivateKey: string;\n jwePrivateKeyPath: string;\n jwePrivateKeyPassphrase: string | undefined;\n authzCodeTimeoutMs: number;\n accessTokenTimeoutMs: number;\n refreshTokenTimeoutMs: number;\n clientIdSecretPairs: Record<string, string> | null;\n dnsServers: string[];\n enforceScopes: boolean;\n advertiseApiScopes: boolean;\n };\n telemetry: TelemetryConfig;\n latencyMetricName: string;\n productTelemetryEndpoint: string;\n productTelemetryEnabled: boolean;\n isHyperforce: boolean;\n featureGate: FeatureGateConfig;\n breakGlassDisableGlobally: boolean;\n adminToolsEnabled: boolean;\n cspAllowedDomains: string[];\n\n constructor() {\n super();\n\n const cleansedVars = removeClaudeMcpBundleUserConfigTemplates(process.env);\n const {\n AUTH: auth,\n SERVER: server,\n SITE_NAME: siteName,\n TRANSPORT: transport,\n SSL_KEY: sslKey,\n SSL_CERT: sslCert,\n HTTP_PORT_ENV_VAR_NAME: httpPortEnvVarName,\n CORS_ORIGIN_CONFIG: corsOriginConfig,\n PAT_NAME: patName,\n PAT_VALUE: patValue,\n JWT_SUB_CLAIM: jwtSubClaim,\n CONNECTED_APP_CLIENT_ID: clientId,\n CONNECTED_APP_SECRET_ID: secretId,\n CONNECTED_APP_SECRET_VALUE: secretValue,\n UAT_TENANT_ID: uatTenantId,\n UAT_ISSUER: uatIssuer,\n UAT_USERNAME_CLAIM_NAME: uatUsernameClaimName,\n UAT_USERNAME_CLAIM: uatUsernameClaim,\n UAT_PRIVATE_KEY: uatPrivateKey,\n UAT_PRIVATE_KEY_PATH: uatPrivateKeyPath,\n UAT_KEY_ID: uatKeyId,\n JWT_ADDITIONAL_PAYLOAD: jwtAdditionalPayload,\n DATASOURCE_CREDENTIALS: datasourceCredentials,\n DISABLE_SESSION_MANAGEMENT: disableSessionManagement,\n TABLEAU_SERVER_VERSION_CHECK_INTERVAL_IN_HOURS: tableauServerVersionCheckIntervalInHours,\n PASSTHROUGH_AUTH_USER_SESSION_CHECK_INTERVAL_IN_MINUTES:\n passthroughAuthUserSessionCheckIntervalInMinutes,\n MCP_SITE_SETTINGS_CHECK_INTERVAL_IN_MINUTES: mcpSiteSettingsCheckIntervalInMinutes,\n ENABLE_MCP_SITE_SETTINGS: enableMcpSiteSettings,\n ALLOW_SITES_TO_CONFIGURE_REQUEST_OVERRIDES: allowSitesToConfigureRequestOverrides,\n ENABLE_PASSTHROUGH_AUTH: enablePassthroughAuth,\n DANGEROUSLY_DISABLE_OAUTH: disableOauth,\n OAUTH_EMBEDDED_AUTHZ_SERVER: oauthEmbeddedAuthzServer,\n OAUTH_ISSUER: oauthIssuer,\n OAUTH_LOCK_SITE: oauthLockSite,\n OAUTH_JWE_PRIVATE_KEY: oauthJwePrivateKey,\n OAUTH_JWE_PRIVATE_KEY_PATH: oauthJwePrivateKeyPath,\n OAUTH_JWE_PRIVATE_KEY_PASSPHRASE: oauthJwePrivateKeyPassphrase,\n OAUTH_RESOURCE_URI: oauthResourceUri,\n OAUTH_GLOBAL_RESOURCE_URIS: oauthGlobalResourceUris,\n OAUTH_REDIRECT_URI: redirectUri,\n OAUTH_CLIENT_ID_SECRET_PAIRS: oauthClientIdSecretPairs,\n OAUTH_CIMD_DNS_SERVERS: dnsServers,\n ADVERTISE_API_SCOPES: advertiseApiScopes,\n OAUTH_AUTHORIZATION_CODE_TIMEOUT_MS: authzCodeTimeoutMs,\n OAUTH_ACCESS_TOKEN_TIMEOUT_MS: accessTokenTimeoutMs,\n OAUTH_REFRESH_TOKEN_TIMEOUT_MS: refreshTokenTimeoutMs,\n OAUTH_DISABLE_SCOPES: oauthDisableScopes,\n TELEMETRY_PROVIDER: telemetryProvider,\n TELEMETRY_PROVIDER_CONFIG: telemetryProviderConfig,\n FEATURE_GATE_PROVIDER: featureGateProvider,\n FEATURE_GATE_PROVIDER_CONFIG: featureGateProviderConfig,\n LATENCY_METRIC_NAME: latencyMetricName,\n PRODUCT_TELEMETRY_ENDPOINT: productTelemetryEndpoint,\n PRODUCT_TELEMETRY_ENABLED: productTelemetryEnabled,\n IS_HYPERFORCE: isHyperforce,\n BREAK_GLASS_DISABLE_GLOBALLY: breakGlassDisableGlobally,\n ADMIN_TOOLS_ENABLED: adminToolsEnabled,\n CSP_ALLOWED_DOMAINS: cspAllowedDomains,\n } = cleansedVars;\n\n let jwtUsername = '';\n\n this.siteName = siteName ?? '';\n\n this.sslKey = sslKey?.trim() ?? '';\n this.sslCert = sslCert?.trim() ?? '';\n this.httpPort = parseNumber(cleansedVars[httpPortEnvVarName?.trim() || 'PORT'], {\n defaultValue: 3927,\n minValue: 1,\n maxValue: 65535,\n });\n this.corsOriginConfig = getCorsOriginConfig(corsOriginConfig?.trim() ?? '');\n this.datasourceCredentials = datasourceCredentials ?? '';\n this.disableSessionManagement = disableSessionManagement === 'true';\n\n this.tableauServerVersionCheckIntervalInHours = parseNumber(\n tableauServerVersionCheckIntervalInHours,\n {\n defaultValue: 1,\n minValue: 1,\n maxValue: 24 * 7, // 7 days\n },\n );\n\n this.passthroughAuthUserSessionCheckIntervalInMinutes = parseNumber(\n passthroughAuthUserSessionCheckIntervalInMinutes,\n {\n defaultValue: 10,\n minValue: 0,\n maxValue: 60 * 24, // 24 hours\n },\n );\n\n this.mcpSiteSettingsCheckIntervalInMinutes = parseNumber(\n mcpSiteSettingsCheckIntervalInMinutes,\n {\n defaultValue: 10,\n minValue: 1,\n maxValue: 60 * 24, // 24 hours\n },\n );\n\n this.enableMcpSiteSettings = enableMcpSiteSettings !== 'false';\n this.allowSitesToConfigureRequestOverrides = allowSitesToConfigureRequestOverrides === 'true';\n this.enablePassthroughAuth = enablePassthroughAuth === 'true';\n const disableOauthOverride = disableOauth === 'true';\n const disableScopes = oauthDisableScopes === 'true';\n const enforceScopes = !disableScopes;\n const embeddedAuthzServer = oauthEmbeddedAuthzServer !== 'false';\n\n if (this.allowSitesToConfigureRequestOverrides && !this.enableMcpSiteSettings) {\n throw new Error(\n 'ALLOW_SITES_TO_CONFIGURE_REQUEST_OVERRIDES is \"true\", but MCP site settings are not enabled.',\n );\n }\n\n this.oauth = {\n enabled: disableOauthOverride ? false : !!oauthIssuer,\n embeddedAuthzServer,\n issuer: oauthIssuer ?? '',\n resourceUri: oauthResourceUri ?? `http://127.0.0.1:${this.httpPort}`,\n globalResourceUris: oauthGlobalResourceUris\n ? oauthGlobalResourceUris\n .split(',')\n .map((uri) => uri.trim())\n .filter(Boolean)\n : [],\n redirectUri: redirectUri || (oauthIssuer ? `${oauthIssuer}/Callback` : ''),\n lockSite: oauthLockSite !== 'false', // Site locking is enabled by default\n jwePrivateKey: oauthJwePrivateKey ?? '',\n jwePrivateKeyPath: oauthJwePrivateKeyPath ?? '',\n jwePrivateKeyPassphrase: oauthJwePrivateKeyPassphrase || undefined,\n dnsServers: dnsServers\n ? dnsServers.split(',').map((ip) => ip.trim())\n : ['1.1.1.1', '1.0.0.1' /* Cloudflare public DNS */],\n authzCodeTimeoutMs: parseNumber(authzCodeTimeoutMs, {\n defaultValue: milliseconds.fromMinutes(10),\n minValue: 0,\n maxValue: milliseconds.fromHours(1),\n }),\n accessTokenTimeoutMs: parseNumber(accessTokenTimeoutMs, {\n defaultValue: milliseconds.fromHours(1),\n minValue: 0,\n maxValue: milliseconds.fromDays(30),\n }),\n refreshTokenTimeoutMs: parseNumber(refreshTokenTimeoutMs, {\n defaultValue: milliseconds.fromDays(30),\n minValue: 0,\n maxValue: milliseconds.fromYears(1),\n }),\n clientIdSecretPairs: oauthClientIdSecretPairs\n ? oauthClientIdSecretPairs.split(',').reduce<Record<string, string>>((acc, curr) => {\n const [clientId, secret] = curr.split(':');\n if (clientId && secret) {\n acc[clientId] = secret;\n }\n return acc;\n }, {})\n : null,\n enforceScopes,\n advertiseApiScopes: advertiseApiScopes === 'true',\n };\n\n if (\n this.oauth.clientIdSecretPairs &&\n Object.keys(this.oauth.clientIdSecretPairs).length === 0\n ) {\n throw new Error(\n `OAUTH_CLIENT_ID_SECRET_PAIRS is in an invalid format: ${oauthClientIdSecretPairs}. Should be in the format: clientId:secret`,\n );\n }\n\n const parsedProvider = isTelemetryProvider(telemetryProvider) ? telemetryProvider : 'noop';\n if (parsedProvider === 'custom') {\n if (!telemetryProviderConfig) {\n throw new Error(\n 'TELEMETRY_PROVIDER_CONFIG is required when TELEMETRY_PROVIDER is \"custom\"',\n );\n }\n this.telemetry = {\n provider: 'custom',\n providerConfig: providerConfigSchema.parse(JSON.parse(telemetryProviderConfig)),\n };\n } else {\n this.telemetry = {\n provider: 'noop',\n };\n }\n\n this.latencyMetricName = latencyMetricName || 'http_server_1agg1_request_duration';\n this.productTelemetryEndpoint =\n productTelemetryEndpoint || 'https://prod.telemetry.tableausoftware.com';\n this.productTelemetryEnabled = productTelemetryEnabled !== 'false';\n this.isHyperforce = isHyperforce === 'true';\n\n // Feature gate provider configuration (similar to telemetry provider)\n if (isFeatureGateProvider(featureGateProvider) && featureGateProvider === 'custom') {\n if (!featureGateProviderConfig) {\n throw new Error(\n 'FEATURE_GATE_PROVIDER_CONFIG is required when FEATURE_GATE_PROVIDER is \"custom\"',\n );\n }\n this.featureGate = {\n provider: 'custom',\n providerConfig: featureGateProviderConfigSchema.parse(\n JSON.parse(featureGateProviderConfig),\n ),\n };\n } else {\n this.featureGate = {\n provider: 'server',\n };\n }\n\n this.breakGlassDisableGlobally = breakGlassDisableGlobally === 'true';\n this.adminToolsEnabled = adminToolsEnabled === 'true';\n\n this.auth = isAuthType(auth) ? auth : this.oauth.enabled ? 'oauth' : 'pat';\n this.transport = isTransport(transport) ? transport : this.oauth.enabled ? 'http' : 'stdio';\n\n if (this.transport === 'http' && !disableOauthOverride && !this.oauth.issuer) {\n throw new Error(\n 'OAUTH_ISSUER must be set when TRANSPORT is \"http\" unless DANGEROUSLY_DISABLE_OAUTH is \"true\"',\n );\n }\n\n if (this.auth === 'oauth') {\n if (disableOauthOverride) {\n throw new Error('When AUTH is \"oauth\", DANGEROUSLY_DISABLE_OAUTH cannot be \"true\"');\n }\n\n if (!this.oauth.issuer) {\n throw new Error('When AUTH is \"oauth\", OAUTH_ISSUER must be set');\n }\n } else {\n invariant(server, 'The environment variable SERVER is not set');\n validateServer(server);\n }\n\n if (this.oauth.enabled) {\n if (this.oauth.embeddedAuthzServer) {\n invariant(this.oauth.redirectUri, 'The environment variable OAUTH_REDIRECT_URI is not set');\n\n if (!this.oauth.jwePrivateKey && !this.oauth.jwePrivateKeyPath) {\n throw new Error(\n 'One of the environment variables: OAUTH_JWE_PRIVATE_KEY_PATH or OAUTH_JWE_PRIVATE_KEY must be set',\n );\n }\n\n if (this.oauth.jwePrivateKey && this.oauth.jwePrivateKeyPath) {\n throw new Error(\n 'Only one of the environment variables: OAUTH_JWE_PRIVATE_KEY or OAUTH_JWE_PRIVATE_KEY_PATH must be set',\n );\n }\n\n if (\n this.oauth.jwePrivateKeyPath &&\n process.env.TABLEAU_MCP_TEST !== 'true' &&\n !existsSync(this.oauth.jwePrivateKeyPath)\n ) {\n throw new Error(\n `OAuth JWE private key path does not exist: ${this.oauth.jwePrivateKeyPath}`,\n );\n }\n }\n\n if (this.transport === 'stdio') {\n throw new Error('TRANSPORT must be \"http\" when OAUTH_ISSUER is set');\n }\n }\n\n if (this.auth === 'pat') {\n invariant(patName, 'The environment variable PAT_NAME is not set');\n invariant(patValue, 'The environment variable PAT_VALUE is not set');\n } else if (this.auth === 'direct-trust') {\n invariant(jwtSubClaim, 'The environment variable JWT_SUB_CLAIM is not set');\n invariant(clientId, 'The environment variable CONNECTED_APP_CLIENT_ID is not set');\n invariant(secretId, 'The environment variable CONNECTED_APP_SECRET_ID is not set');\n invariant(secretValue, 'The environment variable CONNECTED_APP_SECRET_VALUE is not set');\n\n jwtUsername = jwtSubClaim ?? '';\n } else if (this.auth === 'uat') {\n invariant(uatTenantId, 'The environment variable UAT_TENANT_ID is not set');\n invariant(uatIssuer, 'The environment variable UAT_ISSUER is not set');\n\n if (!uatUsernameClaim && !jwtSubClaim) {\n throw new Error(\n 'One of the environment variables: UAT_USERNAME_CLAIM or JWT_SUB_CLAIM must be set',\n );\n }\n\n jwtUsername = uatUsernameClaim ?? jwtSubClaim ?? '';\n\n if (!uatPrivateKey && !uatPrivateKeyPath) {\n throw new Error(\n 'One of the environment variables: UAT_PRIVATE_KEY_PATH or UAT_PRIVATE_KEY must be set',\n );\n }\n\n if (uatPrivateKey && uatPrivateKeyPath) {\n throw new Error(\n 'Only one of the environment variables: UAT_PRIVATE_KEY or UAT_PRIVATE_KEY_PATH must be set',\n );\n }\n\n if (\n uatPrivateKeyPath &&\n process.env.TABLEAU_MCP_TEST !== 'true' &&\n !existsSync(uatPrivateKeyPath)\n ) {\n throw new Error(`UAT private key path does not exist: ${uatPrivateKeyPath}`);\n }\n }\n\n this.server = server ?? '';\n\n // Configure CSP domains with serverOrigin in defaults\n const serverOrigin = this.server ? new URL(this.server).origin : '';\n const defaultDomains = [\n 'https://*.online.tableau.com',\n 'https://*.tableau.com',\n ...(serverOrigin ? [serverOrigin] : []),\n ];\n const customDomains = cspAllowedDomains\n ? cspAllowedDomains.split(',').map((d) => d.trim())\n : [];\n this.cspAllowedDomains = [...defaultDomains, ...customDomains];\n\n this.patName = patName ?? '';\n this.patValue = patValue ?? '';\n this.jwtUsername = jwtUsername ?? '';\n this.connectedAppClientId = clientId ?? '';\n this.connectedAppSecretId = secretId ?? '';\n this.connectedAppSecretValue = secretValue ?? '';\n this.uatTenantId = uatTenantId ?? '';\n this.uatIssuer = uatIssuer ?? '';\n this.uatUsernameClaimName = uatUsernameClaimName || 'email';\n this.uatPrivateKey =\n uatPrivateKey || (uatPrivateKeyPath ? readFileSync(uatPrivateKeyPath, 'utf8') : '');\n this.uatKeyId = uatKeyId ?? '';\n this.jwtAdditionalPayload = jwtAdditionalPayload || '{}';\n }\n}\n\nfunction validateServer(server: string): void {\n if (!['https://', 'http://'].find((prefix) => server.startsWith(prefix))) {\n throw new Error(\n `The environment variable SERVER must start with \"http://\" or \"https://\": ${server}`,\n );\n }\n\n try {\n new URL(server);\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(\n `The environment variable SERVER is not a valid URL: ${server} -- ${errorMessage}`,\n );\n }\n}\n\nfunction getCorsOriginConfig(corsOriginConfig: string): CorsOptions['origin'] {\n if (!corsOriginConfig) {\n return true;\n }\n\n if (corsOriginConfig.match(/^true|false$/i)) {\n return corsOriginConfig.toLowerCase() === 'true';\n }\n\n if (corsOriginConfig === '*') {\n return '*';\n }\n\n if (corsOriginConfig.startsWith('[') && corsOriginConfig.endsWith(']')) {\n try {\n const origins = JSON.parse(corsOriginConfig) as Array<string>;\n return origins.map((origin) => new URL(origin).origin);\n } catch {\n throw new Error(\n `The environment variable CORS_ORIGIN_CONFIG is not a valid array of URLs: ${corsOriginConfig}`,\n );\n }\n }\n\n try {\n return new URL(corsOriginConfig).origin;\n } catch {\n throw new Error(\n `The environment variable CORS_ORIGIN_CONFIG is not a valid URL: ${corsOriginConfig}`,\n );\n }\n}\n\nexport const getConfig = (): Config => new Config();\n", "import { join } from 'path';\n\nimport { parseLogLevel } from './logging/logger.js';\nimport { LoggerType, parseLoggerTypes } from './logging/loggerType.js';\nimport { LogLevel } from './logging/types.js';\nimport { isTransport, TransportName } from './transports.js';\nimport { getDirname } from './utils/getDirname.js';\nimport { milliseconds } from './utils/milliseconds.js';\nimport { parseNumber } from './utils/parseNumber.js';\n\nconst __dirname = getDirname();\n\nexport class BaseConfig {\n transport: TransportName;\n defaultNotificationLevel: string;\n logLevel: LogLevel;\n loggers: Set<LoggerType>;\n fileLoggerDirectory: string;\n disableLogMasking: boolean;\n maxRequestTimeoutMs: number;\n notificationPayloadMaxBytes: number;\n\n constructor() {\n const cleansedVars = removeClaudeMcpBundleUserConfigTemplates(process.env);\n const {\n TRANSPORT: transport,\n DEFAULT_NOTIFICATION_LEVEL: defaultNotificationLevel,\n LOG_LEVEL: logLevel,\n ENABLED_LOGGERS: logging,\n FILE_LOGGER_DIRECTORY: fileLoggerDirectory,\n DISABLE_LOG_MASKING: disableLogMasking,\n MAX_REQUEST_TIMEOUT_MS: maxRequestTimeoutMs,\n NOTIFICATION_PAYLOAD_MAX_BYTES: notificationPayloadMaxBytes,\n } = cleansedVars;\n\n this.transport = isTransport(transport) ? transport : 'stdio';\n this.defaultNotificationLevel = defaultNotificationLevel ?? 'debug';\n this.logLevel = parseLogLevel(logLevel);\n this.loggers = parseLoggerTypes(logging);\n this.fileLoggerDirectory = fileLoggerDirectory || join(__dirname, 'logs');\n this.disableLogMasking = disableLogMasking === 'true';\n this.maxRequestTimeoutMs = parseNumber(maxRequestTimeoutMs, {\n defaultValue: milliseconds.fromMinutes(10),\n minValue: 5000,\n maxValue: milliseconds.fromHours(1),\n });\n this.notificationPayloadMaxBytes = parseNumber(notificationPayloadMaxBytes, {\n defaultValue: 8192,\n minValue: 1,\n });\n }\n}\n\n// When the user does not provide a site name in the Claude MCP Bundle configuration,\n// Claude doesn't replace its value and sets the site name to \"${user_config.site_name}\".\nexport function removeClaudeMcpBundleUserConfigTemplates(\n envVars: Record<string, string | undefined>,\n): Record<string, string | undefined> {\n return Object.entries(envVars).reduce<Record<string, string | undefined>>((acc, [key, value]) => {\n if (value?.startsWith('${user_config.')) {\n acc[key] = '';\n } else {\n acc[key] = value;\n }\n return acc;\n }, {});\n}\n\nexport const getBaseConfig = (): BaseConfig => new BaseConfig();\n", "import { appendFile } from 'node:fs/promises';\n\nimport { existsSync, mkdirSync } from 'fs';\nimport { join } from 'path';\n\nimport { getExceptionMessage } from '../utils/getExceptionMessage.js';\nimport type { LogEntry } from './types.js';\n\nlet _fileLogger: FileLogger | undefined;\n\nexport const setFileLogger = (logger: FileLogger): void => {\n _fileLogger = logger;\n};\n\nexport const getFileLogger = (): FileLogger | undefined => _fileLogger;\n\nexport class FileLogger {\n private readonly _logDirectory: string;\n private readonly _fileMutexes = new Map<string, Promise<void>>();\n\n constructor({ logDirectory }: { logDirectory: string }) {\n this._logDirectory = logDirectory;\n\n if (!existsSync(this._logDirectory)) {\n mkdirSync(this._logDirectory, { recursive: true });\n }\n }\n\n async log(entry: LogEntry): Promise<void> {\n // Create a new log file each hour e.g. 2025-10-15T21-00-00-000Z.log\n const timestamp = new Date().toISOString();\n const filename = `${new Date(new Date().setMinutes(0, 0, 0)).toISOString().replace(/[:.]/g, '-')}.log`;\n const logFilePath = join(this._logDirectory, filename);\n\n // Get or create a mutex for this specific log file\n const mutexKey = logFilePath;\n const currentMutex = this._fileMutexes.get(mutexKey) ?? Promise.resolve();\n\n // Chain the file write operation after the current mutex\n const newMutex = currentMutex.then(async () => {\n try {\n // appendFile will create the file if it doesn't exist\n await appendFile(logFilePath, JSON.stringify({ timestamp, ...entry }) + '\\n');\n } catch (error) {\n process.stderr.write(\n `Failed to write to log file ${logFilePath}: ${getExceptionMessage(error)}\\n`,\n );\n }\n });\n\n this._fileMutexes.set(mutexKey, newMutex);\n\n // Clean up completed mutexes to prevent memory leaks\n newMutex.finally(() => {\n if (this._fileMutexes.get(mutexKey) === newMutex) {\n this._fileMutexes.delete(mutexKey);\n }\n });\n\n // Wait for the file write operation to complete\n await newMutex;\n }\n}\n", "import type { LoggingLevel } from '@modelcontextprotocol/sdk/types.js';\n\nexport type LogLevel = LoggingLevel;\nexport const orderedLogLevels = [\n 'debug',\n 'info',\n 'notice',\n 'warning',\n 'error',\n 'critical',\n 'alert',\n 'emergency',\n] as const;\n\nexport const logLevelSeverity = Object.fromEntries(\n orderedLogLevels.map((level, index) => [level, index]),\n) as Record<LogLevel, number>;\n\nexport type LogEntry = {\n message: string;\n data?: unknown;\n level: LogLevel;\n logger: string | undefined;\n};\n", "import { getBaseConfig } from '../config.shared.js';\nimport { getFileLogger } from './fileLogger.js';\nimport { LogEntry, LogLevel, logLevelSeverity } from './types.js';\n\nexport function shouldLog(entryLevel: LogLevel, minLevel: LogLevel): boolean {\n return logLevelSeverity[entryLevel] >= logLevelSeverity[minLevel];\n}\n\nfunction isLogLevel(value: string): value is LogLevel {\n return value in logLevelSeverity;\n}\n\nexport function parseLogLevel(value: string | undefined): LogLevel {\n const level = value?.trim();\n if (level && isLogLevel(level)) {\n return level;\n }\n return 'info';\n}\n\n/**\n * Custom JSON.stringify replacer that serializes Error objects properly.\n * Removes the config field from AxiosError to avoid logging sensitive headers.\n */\nfunction errorReplacer(data: unknown): unknown {\n if (data instanceof Error) {\n return {\n name: data.name,\n message: data.message,\n stack: data.stack,\n ...(data.cause !== undefined && { cause: data.cause }),\n };\n }\n\n return data;\n}\n\n/**\n * The dedicated logger name for authoritative audit records (e.g. the mutation guard). Audit\n * records are a security control, so they bypass the LOG_LEVEL severity filter below \u2014 an operator\n * must not be able to suppress them by raising LOG_LEVEL. They still honor the appLogger/fileLogger\n * sink selection like any other entry.\n */\nexport const AUDIT_LOGGER = 'audit';\n\nexport function log(entry: LogEntry): void {\n const config = getBaseConfig();\n // Audit records always pass the severity gate; all other entries honor the configured level.\n if (entry.logger !== AUDIT_LOGGER && !shouldLog(entry.level, config.logLevel)) {\n return;\n }\n\n // we are removing any unnecessary fields that may also leak sensitive data\n entry.data = errorReplacer(entry.data);\n\n if (config.loggers.has('appLogger')) {\n const message = JSON.stringify(entry);\n if (config.transport === 'http') {\n // eslint-disable-next-line no-console -- console.log is intentional here since the transport is not stdio.\n console.log(message);\n } else {\n process.stderr.write(message + '\\n');\n }\n }\n if (config.loggers.has('fileLogger')) {\n getFileLogger()?.log(entry);\n }\n}\n", "export const loggerTypes = ['fileLogger', 'appLogger'] as const;\nexport type LoggerType = (typeof loggerTypes)[number];\nconst validLoggerTypes = new Set(loggerTypes);\n\nexport function parseLoggerTypes(value: string | undefined): Set<LoggerType> {\n if (!value) {\n return new Set<LoggerType>(['appLogger']);\n }\n return new Set(\n value\n .split(',')\n .map((s) => s.trim())\n .filter((s): s is LoggerType => validLoggerTypes.has(s as LoggerType)),\n );\n}\n", "const transports = ['stdio', 'http'] as const;\nexport type TransportName = (typeof transports)[number];\nexport function isTransport(transport: unknown): transport is TransportName {\n return !!transports.find((t) => t === transport);\n}\n", "export function getDirname(): string {\n if (typeof __dirname === 'string') {\n return __dirname;\n }\n\n throw new Error('__dirname is not set');\n}\n", "export const milliseconds = {\n fromSeconds: (seconds: number) => seconds * 1000,\n fromMinutes: (minutes: number) => minutes * 60 * 1000,\n fromHours: (hours: number) => hours * 60 * 60 * 1000,\n fromDays: (days: number) => days * 24 * 60 * 60 * 1000,\n fromWeeks: (weeks: number) => weeks * 7 * 24 * 60 * 60 * 1000,\n fromMonths: (months: number) => months * 30 * 24 * 60 * 60 * 1000,\n fromYears: (years: number) => years * 365.25 * 24 * 60 * 60 * 1000,\n};\n", "export function parseNumber(\n value: string | undefined,\n {\n defaultValue,\n minValue,\n maxValue,\n }: { defaultValue: number; minValue?: number; maxValue?: number } = {\n defaultValue: 0,\n minValue: Number.NEGATIVE_INFINITY,\n maxValue: Number.POSITIVE_INFINITY,\n },\n): number {\n if (!value) {\n return defaultValue;\n }\n\n const number = parseFloat(value);\n return isNaN(number) ||\n (minValue !== undefined && number < minValue) ||\n (maxValue !== undefined && number > maxValue)\n ? defaultValue\n : number;\n}\n", "import { z } from 'zod';\n\n/**\n * Valid feature gate provider names\n */\nexport const featureGateProviderSchema = z.enum(['server', 'custom']);\nexport type FeatureGateProviderType = z.infer<typeof featureGateProviderSchema>;\n\n/**\n * Type guard for feature gate provider names\n */\nexport function isFeatureGateProvider(provider: unknown): provider is FeatureGateProviderType {\n return featureGateProviderSchema.safeParse(provider).success;\n}\n\n/**\n * Schema for server feature gate config (uses features.json file)\n */\nexport const serverFeatureGateConfigSchema = z.object({\n provider: z.literal('server'),\n});\n\n/**\n * Schema for provider config (module path + optional provider-specific options)\n */\nexport const providerConfigSchema = z\n .object({\n module: z.string({ required_error: 'Custom provider requires \"module\" path' }),\n })\n .passthrough();\n\n/**\n * Schema for custom feature gate config\n *\n * @example\n * ```json\n * {\n * \"provider\": \"custom\",\n * \"providerConfig\": {\n * \"module\": \"./my-feature-gate-provider.js\"\n * }\n * }\n * ```\n */\nexport const customFeatureGateConfigSchema = z.object({\n provider: z.literal('custom'),\n providerConfig: providerConfigSchema,\n});\n\n/**\n * Combined feature gate config schema (discriminated union)\n */\nexport const featureGateConfigSchema = z.discriminatedUnion('provider', [\n serverFeatureGateConfigSchema,\n customFeatureGateConfigSchema,\n]);\n\nexport type FeatureGateConfig = z.infer<typeof featureGateConfigSchema>;\n", "import { z } from 'zod';\n\n/**\n * Valid telemetry provider names\n */\nexport const telemetryProviderSchema = z.enum(['noop', 'custom']);\nexport type TelemetryProviderType = z.infer<typeof telemetryProviderSchema>;\n\n/**\n * Schema for noop telemetry config (no telemetry)\n */\nexport const noopTelemetryConfigSchema = z.object({\n provider: z.literal('noop'),\n});\n\n/**\n * Schema for custom telemetry provider config.\n * Requires 'module' field, allows additional provider-specific options.\n */\nexport const providerConfigSchema = z\n .object({\n module: z.string({ required_error: 'Custom provider requires \"module\" path' }),\n })\n .passthrough();\n\n/**\n * Schema for custom telemetry config\n *\n * @example\n * ```json\n * {\n * \"provider\": \"custom\",\n * \"providerConfig\": {\n * \"module\": \"./my-otel-provider.js\"\n * }\n * }\n * ```\n */\nexport const customTelemetryConfigSchema = z.object({\n provider: z.literal('custom'),\n providerConfig: providerConfigSchema,\n});\n\n/**\n * Combined telemetry config schema (discriminated union)\n */\nexport const telemetryConfigSchema = z.discriminatedUnion('provider', [\n noopTelemetryConfigSchema,\n customTelemetryConfigSchema,\n]);\n\nexport type TelemetryConfig = z.infer<typeof telemetryConfigSchema>;\n\n/**\n * Type guard for telemetry provider names\n */\nexport function isTelemetryProvider(provider: unknown): provider is TelemetryProviderType {\n return telemetryProviderSchema.safeParse(provider).success;\n}\n", "export default function invariant(condition: unknown, message?: string): asserts condition {\n if (!condition) {\n throw new Error(message ? message : 'Invariant Violation');\n }\n}\n", "/**\n * NoOp telemetry provider - does nothing.\n * This is the default provider when telemetry is disabled.\n *\n * Zero overhead implementation that can be safely used in production\n * when telemetry is not needed.\n */\n\nimport type { TelemetryAttributes, TelemetryProvider } from './telemetryProvider.js';\n\nexport class NoOpTelemetryProvider implements TelemetryProvider {\n initialize(): void {\n // No-op\n }\n\n recordMetric(_name: string, _value: number, _attributes: TelemetryAttributes): void {\n // No-op\n }\n\n recordHistogram(_name: string, _value: number, _attributes: TelemetryAttributes): void {\n // No-op\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["import_dotenv", "import_path", "import_fs", "import_path", "_fileLogger", "getFileLogger", "_fileLogger", "orderedLogLevels", "logLevelSeverity", "level", "index", "shouldLog", "entryLevel", "minLevel", "logLevelSeverity", "isLogLevel", "value", "parseLogLevel", "level", "errorReplacer", "data", "AUDIT_LOGGER", "log", "entry", "config", "getBaseConfig", "message", "getFileLogger", "loggerTypes", "validLoggerTypes", "parseLoggerTypes", "value", "s", "transports", "isTransport", "transport", "getDirname", "milliseconds", "seconds", "minutes", "hours", "days", "weeks", "months", "years", "parseNumber", "value", "defaultValue", "minValue", "maxValue", "number", "__dirname", "getDirname", "BaseConfig", "cleansedVars", "removeClaudeMcpBundleUserConfigTemplates", "transport", "defaultNotificationLevel", "logLevel", "logging", "fileLoggerDirectory", "disableLogMasking", "maxRequestTimeoutMs", "notificationPayloadMaxBytes", "isTransport", "parseLogLevel", "parseLoggerTypes", "parseNumber", "milliseconds", "envVars", "acc", "key", "value", "getBaseConfig", "import_zod", "featureGateProviderSchema", "isFeatureGateProvider", "provider", "serverFeatureGateConfigSchema", "providerConfigSchema", "customFeatureGateConfigSchema", "featureGateConfigSchema", "import_zod", "telemetryProviderSchema", "noopTelemetryConfigSchema", "providerConfigSchema", "customTelemetryConfigSchema", "telemetryConfigSchema", "isTelemetryProvider", "provider", "invariant", "condition", "message", "authTypes", "isAuthType", "auth", "type", "Config", "BaseConfig", "cleansedVars", "removeClaudeMcpBundleUserConfigTemplates", "server", "siteName", "transport", "sslKey", "sslCert", "httpPortEnvVarName", "corsOriginConfig", "patName", "patValue", "jwtSubClaim", "clientId", "secretId", "secretValue", "uatTenantId", "uatIssuer", "uatUsernameClaimName", "uatUsernameClaim", "uatPrivateKey", "uatPrivateKeyPath", "uatKeyId", "jwtAdditionalPayload", "datasourceCredentials", "disableSessionManagement", "tableauServerVersionCheckIntervalInHours", "passthroughAuthUserSessionCheckIntervalInMinutes", "mcpSiteSettingsCheckIntervalInMinutes", "enableMcpSiteSettings", "allowSitesToConfigureRequestOverrides", "enablePassthroughAuth", "disableOauth", "oauthEmbeddedAuthzServer", "oauthIssuer", "oauthLockSite", "oauthJwePrivateKey", "oauthJwePrivateKeyPath", "oauthJwePrivateKeyPassphrase", "oauthResourceUri", "oauthGlobalResourceUris", "redirectUri", "oauthClientIdSecretPairs", "dnsServers", "advertiseApiScopes", "authzCodeTimeoutMs", "accessTokenTimeoutMs", "refreshTokenTimeoutMs", "oauthDisableScopes", "telemetryProvider", "telemetryProviderConfig", "featureGateProvider", "featureGateProviderConfig", "latencyMetricName", "productTelemetryEndpoint", "productTelemetryEnabled", "isHyperforce", "breakGlassDisableGlobally", "adminToolsEnabled", "cspAllowedDomains", "jwtUsername", "parseNumber", "getCorsOriginConfig", "disableOauthOverride", "enforceScopes", "embeddedAuthzServer", "uri", "ip", "milliseconds", "acc", "curr", "secret", "isTelemetryProvider", "providerConfigSchema", "isFeatureGateProvider", "isTransport", "invariant", "validateServer", "serverOrigin", "defaultDomains", "customDomains", "d", "prefix", "error", "errorMessage", "origin", "getConfig", "NoOpTelemetryProvider", "_name", "_value", "_attributes", "getInstanceMethods", "cls", "name", "isRecord", "obj", "validateTelemetryProvider", "provider", "missingMethods", "NoOpTelemetryProvider", "method", "initializeTelemetry", "config", "getConfig", "provider", "loadCustomProvider", "NoOpTelemetryProvider", "error", "log", "fallbackProvider", "modulePath", "resolvedPath", "module", "ProviderClass", "validateTelemetryProvider", "errorMessage", "dotenv", "initializeTelemetry", "error"]
7
7
  }
@@ -70,7 +70,7 @@ Boolean requesting whether a visible border and background is provided by the ho
70
70
  - omitted: host decides border`)});h({method:u("ui/request-display-mode"),params:h({mode:lt.describe("The display mode being requested.")})});var gg=h({mode:lt.describe("The display mode that was actually set. May differ from requested if not supported.")}).passthrough(),vg=C([u("model"),u("app")]).describe("Tool visibility scope - who can access the tool.");h({resourceUri:m().optional(),visibility:O(vg).optional().describe(`Who can access this tool. Default: ["model", "app"]
71
71
  - "model": Tool visible to and callable by the agent
72
72
  - "app": Tool callable by the app from this server only`),csp:je().optional(),permissions:je().optional()});h({mimeTypes:O(m()).optional().describe('Array of supported MIME types for UI resources.\nMust include `"text/html;profile=mcp-app"` for MCP Apps support.')});h({method:u("ui/download-file"),params:h({contents:O(C([ed,td])).describe("Resource contents to download — embedded (inline data) or linked (host fetches). Uses standard MCP resource types.")})});h({method:u("ui/message"),params:h({role:u("user").describe('Message role, currently only "user" is supported.'),content:O(jt).describe("Message content blocks (text, image, etc.).")})});h({method:u("ui/notifications/sandbox-resource-ready"),params:h({html:m().describe("HTML content to load into the inner iframe."),sandbox:m().optional().describe("Optional override for the inner iframe's sandbox attribute."),csp:Uo.optional().describe("CSP configuration from resource metadata."),permissions:Zo.optional().describe("Sandbox permissions from resource metadata.")})});var _g=h({method:u("ui/notifications/tool-result"),params:er.describe("Standard MCP tool execution result.")}),sd=h({toolInfo:h({id:xt.optional().describe("JSON-RPC id of the tools/call request."),tool:Po.describe("Tool definition including name, inputSchema, etc.")}).optional().describe("Metadata of the tool call that instantiated this App."),theme:ng.optional().describe("Current color theme preference."),styles:mg.optional().describe("Style configuration for theming the app."),displayMode:lt.optional().describe("How the UI is currently displayed."),availableDisplayModes:O(lt).optional().describe("Display modes the host supports."),containerDimensions:C([h({height:P().describe("Fixed container height in pixels.")}),h({maxHeight:C([P(),st()]).optional().describe("Maximum container height in pixels.")})]).and(C([h({width:P().describe("Fixed container width in pixels.")}),h({maxWidth:C([P(),st()]).optional().describe("Maximum container width in pixels.")})])).optional().describe(`Container dimensions. Represents the dimensions of the iframe or other
73
- container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:m().optional().describe("User's language and region preference in BCP 47 format."),timeZone:m().optional().describe("User's timezone in IANA format."),userAgent:m().optional().describe("Host application identifier."),platform:C([u("web"),u("desktop"),u("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:h({touch:J().optional().describe("Whether the device supports touch input."),hover:J().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:h({top:P().describe("Top safe area inset in pixels."),right:P().describe("Right safe area inset in pixels."),bottom:P().describe("Bottom safe area inset in pixels."),left:P().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),yg=h({method:u("ui/notifications/host-context-changed"),params:sd.describe("Partial context update containing only changed fields.")});h({method:u("ui/update-model-context"),params:h({content:O(jt).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:L(m(),B().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});h({method:u("ui/initialize"),params:h({appInfo:Yn.describe("App identification (name and version)."),appCapabilities:hg.describe("Features and capabilities this app provides."),protocolVersion:m().describe("Protocol version this app supports.")})});var bg=h({protocolVersion:m().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:Yn.describe("Host application identification and version."),hostCapabilities:fg.describe("Features and capabilities provided by the host."),hostContext:sd.describe("Rich context about the host environment.")}).passthrough(),$g={target:"draft-2020-12"};async function Sa(n,e){let r=n["~standard"];if(r.jsonSchema)return r.jsonSchema[e]($g);if(r.vendor==="zod"){let{z:o}=await ld(()=>Promise.resolve().then(()=>uf),void 0,import.meta.url);return o.toJSONSchema(n,{io:e})}throw Error(`Schema (vendor: ${r.vendor}) does not implement Standard JSON Schema (~standard.jsonSchema). Use a library that does (zod v4, ArkType, Valibot) or wrap your schema accordingly.`)}async function xa(n,e,r=""){let o=await n["~standard"].validate(e);if(o.issues){let t=o.issues.map(i=>{let a=i.path?.map(s=>typeof s=="object"?s.key:s).join(".");return a?`${a}: ${i.message}`:i.message}).join("; ");throw Error(r+t)}return o.value}class Co extends Yh{_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;_registeredTools={};_initializedSent=!1;_assertInitialized(e){if(this._initializedSent)return;let r=`[ext-apps] App.${e}() called before connect() completed the ui/initialize handshake. Await app.connect() before calling this method, or move data loading to an ontoolresult handler.`;if(this.options?.strict)throw Error(r);console.warn(`${r}. This will throw in a future release.`)}eventSchemas={toolinput:cg,toolinputpartial:ug,toolresult:_g,toolcancelled:lg,hostcontextchanged:yg};static ONE_SHOT_EVENTS=new Set(["toolinput","toolinputpartial","toolresult","toolcancelled"]);_everHadListener=new Set;_assertHandlerTiming(e){if(!Co.ONE_SHOT_EVENTS.has(e)||this._everHadListener.has(e)||(this._everHadListener.add(e),!this._initializedSent))return;let r=`[ext-apps] "${String(e)}" handler registered after connect() completed the ui/initialize handshake. The host may have already sent this notification. Register handlers before calling app.connect().`;if(this.options?.strict)throw Error(r);console.warn(r)}setEventHandler(e,r){r&&this._assertHandlerTiming(e),super.setEventHandler(e,r)}addEventListener(e,r){this._assertHandlerTiming(e),super.addEventListener(e,r)}onEventDispatch(e,r){e==="hostcontextchanged"&&(this._hostContext={...this._hostContext,...r})}constructor(e,r={},o={autoResize:!0}){super(o),this._appInfo=e,this._capabilities=r,this.options=o,o.allowUnsafeEval||ee({jitless:!0}),this.setRequestHandler(Xn,t=>(console.log("Received ping:",t.params),{})),this.setEventHandler("hostcontextchanged",void 0)}registerCapabilities(e){if(this.transport)throw Error("Cannot register capabilities after transport is established");this._capabilities=Qh(this._capabilities,e)}registerTool(e,r,o){if(this._registeredTools[e])throw Error(`Tool ${e} is already registered`);let t=this,i=()=>{t._initializedSent&&t._capabilities.tools?.listChanged&&t.sendToolListChanged()},a=r.inputSchema!==void 0,s={title:r.title,description:r.description,inputSchema:r.inputSchema,outputSchema:r.outputSchema,annotations:r.annotations,_meta:r._meta,enabled:!0,enable(){this.enabled=!0,i()},disable(){this.enabled=!1,i()},update(c){Object.assign(this,c),i()},remove(){t._registeredTools[e]===s&&(delete t._registeredTools[e],i())},handler:async(c,l)=>{if(!s.enabled)throw Error(`Tool ${e} is disabled`);let p;if(a){let f=s.inputSchema,b=f?await xa(f,c??{},`Invalid input for tool ${e}: `):c??{};p=await o(b,l)}else p=await o(l);return s.outputSchema&&!p.isError&&(p.structuredContent=await xa(s.outputSchema,p.structuredContent,`Invalid output for tool ${e}: `)),p}};return this._registeredTools[e]=s,!this._capabilities.tools&&!this.transport&&this.registerCapabilities({tools:{listChanged:!0}}),this.ensureToolHandlersInitialized(),i(),s}_toolHandlersInitialized=!1;ensureToolHandlersInitialized(){this._toolHandlersInitialized||(this._toolHandlersInitialized=!0,this.oncalltool=async(e,r)=>{let o=this._registeredTools[e.name];if(!o)throw Error(`Tool ${e.name} not found`);return o.handler(e.arguments,r)},this.onlisttools=async(e,r)=>({tools:await Promise.all(Object.entries(this._registeredTools).filter(([o,t])=>t.enabled).map(async([o,t])=>{let i={name:o,title:t.title,description:t.description,inputSchema:t.inputSchema?await Sa(t.inputSchema,"input"):{type:"object",properties:{}}};return t.outputSchema&&(i.outputSchema=await Sa(t.outputSchema,"output")),t.annotations&&(i.annotations=t.annotations),t._meta&&(i._meta=t._meta),i}))}))}async sendToolListChanged(e={}){this._assertInitialized("sendToolListChanged"),await this.notification({method:"notifications/tools/list_changed",params:e})}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}get ontoolinput(){return this.getEventHandler("toolinput")}set ontoolinput(e){this.setEventHandler("toolinput",e)}get ontoolinputpartial(){return this.getEventHandler("toolinputpartial")}set ontoolinputpartial(e){this.setEventHandler("toolinputpartial",e)}get ontoolresult(){return this.getEventHandler("toolresult")}set ontoolresult(e){this.setEventHandler("toolresult",e)}get ontoolcancelled(){return this.getEventHandler("toolcancelled")}set ontoolcancelled(e){this.setEventHandler("toolcancelled",e)}get onhostcontextchanged(){return this.getEventHandler("hostcontextchanged")}set onhostcontextchanged(e){this.setEventHandler("hostcontextchanged",e)}_onteardown;get onteardown(){return this._onteardown}set onteardown(e){this.warnIfRequestHandlerReplaced("onteardown",this._onteardown,e),this._onteardown=e,this.replaceRequestHandler(pg,(r,o)=>{if(!this._onteardown)throw Error("No onteardown handler set");return this._onteardown(r.params,o)})}_oncalltool;get oncalltool(){return this._oncalltool}set oncalltool(e){this.warnIfRequestHandlerReplaced("oncalltool",this._oncalltool,e),this._oncalltool=e,this.replaceRequestHandler(rd,(r,o)=>{if(!this._oncalltool)throw Error("No oncalltool handler set");return this._oncalltool(r.params,o)})}_onlisttools;get onlisttools(){return this._onlisttools}set onlisttools(e){this.warnIfRequestHandlerReplaced("onlisttools",this._onlisttools,e),this._onlisttools=e,this.replaceRequestHandler(nd,(r,o)=>{if(!this._onlisttools)throw Error("No onlisttools handler set");return this._onlisttools(r.params,o)})}assertCapabilityForMethod(e){switch(e){case"sampling/createMessage":if(!this._hostCapabilities?.sampling)throw Error(`Host does not support sampling (required for ${e})`);break}}assertRequestHandlerCapability(e){switch(e){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${e})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${e} registered`)}}assertNotificationCapability(e){}assertTaskCapability(e){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(e){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(e,r){if(this._assertInitialized("callServerTool"),typeof e=="string")throw Error(`callServerTool() expects an object as its first argument, but received a string ("${e}"). Did you mean: callServerTool({ name: "${e}", arguments: { ... } })?`);return await this.request({method:"tools/call",params:e},er,{onprogress:()=>{},resetTimeoutOnProgress:!0,...r})}async readServerResource(e,r){return this._assertInitialized("readServerResource"),await this.request({method:"resources/read",params:e},Xl,r)}async listServerResources(e,r){return this._assertInitialized("listServerResources"),await this.request({method:"resources/list",params:e},Yl,r)}async createSamplingMessage(e,r){this._assertInitialized("createSamplingMessage");let o=e.tools?ad:od;return await this.request({method:"sampling/createMessage",params:e},o,r)}sendMessage(e,r){return this._assertInitialized("sendMessage"),this.request({method:"ui/message",params:e},sg,r)}sendLog(e){return this.notification({method:"notifications/message",params:e})}updateModelContext(e,r){return this._assertInitialized("updateModelContext"),this.request({method:"ui/update-model-context",params:e},_o,r)}openLink(e,r){return this._assertInitialized("openLink"),this.request({method:"ui/open-link",params:e},og,r)}sendOpenLink=this.openLink;downloadFile(e,r){return this._assertInitialized("downloadFile"),this.request({method:"ui/download-file",params:e},ag,r)}requestTeardown(e={}){return this.notification({method:"ui/notifications/request-teardown",params:e})}requestDisplayMode(e,r){return this._assertInitialized("requestDisplayMode"),this.request({method:"ui/request-display-mode",params:e},gg,r)}sendSizeChanged(e){return this.notification({method:"ui/notifications/size-changed",params:e})}setupSizeChangedNotifications(){let e=!1,r=0,o=0,t=()=>{e||(e=!0,requestAnimationFrame(()=>{e=!1;let a=document.documentElement,s=a.style.height;a.style.height="max-content";let c=Math.ceil(a.getBoundingClientRect().height);a.style.height=s;let l=Math.ceil(window.innerWidth);(l!==r||c!==o)&&(r=l,o=c,this.sendSizeChanged({width:l,height:c}))}))};t();let i=new ResizeObserver(t);return i.observe(document.documentElement),i.observe(document.body),()=>i.disconnect()}async connect(e=new tg(window.parent,window.parent),r){if(this.transport)throw Error("App is already connected. Call close() before connecting again.");this._initializedSent=!1,await super.connect(e);try{let o=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:Xh}},bg,r);if(o===void 0)throw Error(`Server sent invalid initialize result: ${o}`);this._hostCapabilities=o.hostCapabilities,this._hostInfo=o.hostInfo,this._hostContext=o.hostContext,await this.notification({method:"ui/notifications/initialized"}),this._initializedSent=!0,this.options?.autoResize&&this.setupSizeChangedNotifications()}catch(o){throw this.close(),o}}}const kg="2.21.1",wg={version:kg},_r="tableauVizContainer";function Sg(n,e){const r=document.createElement("tableau-viz");return r.setAttribute("src",n),r.setAttribute("token",e),r.setAttribute("toolbar","hidden"),r}function xg(n,e,r){const o=document.getElementById(_r);if(!o){console.error(`[mcp-app] container element with id "${_r}" not found; cannot embed viz`);return}const t=Sg(n,e);t.addEventListener("firstvizsizeknown",i=>{const a=i.detail?.vizSize,s=a?.sheetSize?.maxSize?.height,c=a?.chromeHeight;if(typeof s!="number")return;const l=typeof c=="number"?c:0;t.style.height=`${s+l}px`}),t.addEventListener("vizloaderror",i=>{console.error("[mcp-app] tableau-viz reported a load error",i),r?.()}),o.replaceChildren(t)}const Ig=qe({content:Ua(qe({type:Za("text"),text:Gt()}))}),zg=qe({token:Gt()});async function Tg(n){if(!n.getHostCapabilities()?.serverTools)throw new Error("Cannot retrieve embed token: the MCP host does not support server tools (serverTools capability is unavailable).");const r=await n.callServerTool({name:"get-embed-token",arguments:{}});if(r.isError)throw new Error("Failed to get an embed token for the current authentication configuration.");const t=Ig.parse(r).content[0],i=JSON.parse(t.text);return zg.parse(i).token}function Og(n){return new Promise((e,r)=>{if(!("customElements"in window)){r(new Error("Custom elements are not available. Cannot access tableau-viz element"));return}if(customElements.get("tableau-viz")){e();return}const t=`${new URL(n).origin}/javascripts/api/tableau.embedding.3.latest.min.js`,i=document.createElement("script");i.type="module",i.src=t,i.onload=()=>{const a=customElements.whenDefined("tableau-viz"),s=new Promise((c,l)=>{setTimeout(()=>{l(new Error("Tableau Embedding API failed to load within 15 seconds"))},15e3)});Promise.race([a,s]).then(()=>e()).catch(c=>r(c))},i.onerror=()=>{console.error("Failed to load Tableau Embedding API from:",t),r(new Error(`Failed to load Tableau Embedding API from ${t}`))},document.head.appendChild(i)})}function Ia(n){if(n.querySelector(".open-in-tableau-error"))return;const e=document.createElement("div");e.className="open-in-tableau-error",e.textContent="The URL was unable to be opened.",n.appendChild(e)}function Ng(n){n.querySelector(".open-in-tableau-error")?.remove()}function jg(n,e,r){const o=r.querySelector("#openInTableauLink");o&&o.remove();const t=n.getHostCapabilities();if(!e||!t?.openLinks)return;const i=document.createElement("a");i.id="openInTableauLink",i.className="open-in-tableau",i.setAttribute("href",e),i.setAttribute("rel","noopener noreferrer"),i.setAttribute("aria-label","Open in Tableau (opens in a new browser tab)"),i.textContent="Open in Tableau ↗",i.onclick=async a=>{a.preventDefault();try{(await n.openLink({url:e})).isError?(console.warn("Open in Tableau link request denied by host",{url:e}),Ia(r)):Ng(r)}catch(s){console.warn("Open in Tableau link request failed",{url:e,error:s}),Ia(r)}},r.appendChild(i)}const Eg=`<svg width="171" height="165" viewBox="0 0 171 165" fill="none" xmlns="http://www.w3.org/2000/svg">
73
+ container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:m().optional().describe("User's language and region preference in BCP 47 format."),timeZone:m().optional().describe("User's timezone in IANA format."),userAgent:m().optional().describe("Host application identifier."),platform:C([u("web"),u("desktop"),u("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:h({touch:J().optional().describe("Whether the device supports touch input."),hover:J().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:h({top:P().describe("Top safe area inset in pixels."),right:P().describe("Right safe area inset in pixels."),bottom:P().describe("Bottom safe area inset in pixels."),left:P().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),yg=h({method:u("ui/notifications/host-context-changed"),params:sd.describe("Partial context update containing only changed fields.")});h({method:u("ui/update-model-context"),params:h({content:O(jt).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:L(m(),B().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});h({method:u("ui/initialize"),params:h({appInfo:Yn.describe("App identification (name and version)."),appCapabilities:hg.describe("Features and capabilities this app provides."),protocolVersion:m().describe("Protocol version this app supports.")})});var bg=h({protocolVersion:m().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:Yn.describe("Host application identification and version."),hostCapabilities:fg.describe("Features and capabilities provided by the host."),hostContext:sd.describe("Rich context about the host environment.")}).passthrough(),$g={target:"draft-2020-12"};async function Sa(n,e){let r=n["~standard"];if(r.jsonSchema)return r.jsonSchema[e]($g);if(r.vendor==="zod"){let{z:o}=await ld(()=>Promise.resolve().then(()=>uf),void 0,import.meta.url);return o.toJSONSchema(n,{io:e})}throw Error(`Schema (vendor: ${r.vendor}) does not implement Standard JSON Schema (~standard.jsonSchema). Use a library that does (zod v4, ArkType, Valibot) or wrap your schema accordingly.`)}async function xa(n,e,r=""){let o=await n["~standard"].validate(e);if(o.issues){let t=o.issues.map(i=>{let a=i.path?.map(s=>typeof s=="object"?s.key:s).join(".");return a?`${a}: ${i.message}`:i.message}).join("; ");throw Error(r+t)}return o.value}class Co extends Yh{_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;_registeredTools={};_initializedSent=!1;_assertInitialized(e){if(this._initializedSent)return;let r=`[ext-apps] App.${e}() called before connect() completed the ui/initialize handshake. Await app.connect() before calling this method, or move data loading to an ontoolresult handler.`;if(this.options?.strict)throw Error(r);console.warn(`${r}. This will throw in a future release.`)}eventSchemas={toolinput:cg,toolinputpartial:ug,toolresult:_g,toolcancelled:lg,hostcontextchanged:yg};static ONE_SHOT_EVENTS=new Set(["toolinput","toolinputpartial","toolresult","toolcancelled"]);_everHadListener=new Set;_assertHandlerTiming(e){if(!Co.ONE_SHOT_EVENTS.has(e)||this._everHadListener.has(e)||(this._everHadListener.add(e),!this._initializedSent))return;let r=`[ext-apps] "${String(e)}" handler registered after connect() completed the ui/initialize handshake. The host may have already sent this notification. Register handlers before calling app.connect().`;if(this.options?.strict)throw Error(r);console.warn(r)}setEventHandler(e,r){r&&this._assertHandlerTiming(e),super.setEventHandler(e,r)}addEventListener(e,r){this._assertHandlerTiming(e),super.addEventListener(e,r)}onEventDispatch(e,r){e==="hostcontextchanged"&&(this._hostContext={...this._hostContext,...r})}constructor(e,r={},o={autoResize:!0}){super(o),this._appInfo=e,this._capabilities=r,this.options=o,o.allowUnsafeEval||ee({jitless:!0}),this.setRequestHandler(Xn,t=>(console.log("Received ping:",t.params),{})),this.setEventHandler("hostcontextchanged",void 0)}registerCapabilities(e){if(this.transport)throw Error("Cannot register capabilities after transport is established");this._capabilities=Qh(this._capabilities,e)}registerTool(e,r,o){if(this._registeredTools[e])throw Error(`Tool ${e} is already registered`);let t=this,i=()=>{t._initializedSent&&t._capabilities.tools?.listChanged&&t.sendToolListChanged()},a=r.inputSchema!==void 0,s={title:r.title,description:r.description,inputSchema:r.inputSchema,outputSchema:r.outputSchema,annotations:r.annotations,_meta:r._meta,enabled:!0,enable(){this.enabled=!0,i()},disable(){this.enabled=!1,i()},update(c){Object.assign(this,c),i()},remove(){t._registeredTools[e]===s&&(delete t._registeredTools[e],i())},handler:async(c,l)=>{if(!s.enabled)throw Error(`Tool ${e} is disabled`);let p;if(a){let f=s.inputSchema,b=f?await xa(f,c??{},`Invalid input for tool ${e}: `):c??{};p=await o(b,l)}else p=await o(l);return s.outputSchema&&!p.isError&&(p.structuredContent=await xa(s.outputSchema,p.structuredContent,`Invalid output for tool ${e}: `)),p}};return this._registeredTools[e]=s,!this._capabilities.tools&&!this.transport&&this.registerCapabilities({tools:{listChanged:!0}}),this.ensureToolHandlersInitialized(),i(),s}_toolHandlersInitialized=!1;ensureToolHandlersInitialized(){this._toolHandlersInitialized||(this._toolHandlersInitialized=!0,this.oncalltool=async(e,r)=>{let o=this._registeredTools[e.name];if(!o)throw Error(`Tool ${e.name} not found`);return o.handler(e.arguments,r)},this.onlisttools=async(e,r)=>({tools:await Promise.all(Object.entries(this._registeredTools).filter(([o,t])=>t.enabled).map(async([o,t])=>{let i={name:o,title:t.title,description:t.description,inputSchema:t.inputSchema?await Sa(t.inputSchema,"input"):{type:"object",properties:{}}};return t.outputSchema&&(i.outputSchema=await Sa(t.outputSchema,"output")),t.annotations&&(i.annotations=t.annotations),t._meta&&(i._meta=t._meta),i}))}))}async sendToolListChanged(e={}){this._assertInitialized("sendToolListChanged"),await this.notification({method:"notifications/tools/list_changed",params:e})}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}get ontoolinput(){return this.getEventHandler("toolinput")}set ontoolinput(e){this.setEventHandler("toolinput",e)}get ontoolinputpartial(){return this.getEventHandler("toolinputpartial")}set ontoolinputpartial(e){this.setEventHandler("toolinputpartial",e)}get ontoolresult(){return this.getEventHandler("toolresult")}set ontoolresult(e){this.setEventHandler("toolresult",e)}get ontoolcancelled(){return this.getEventHandler("toolcancelled")}set ontoolcancelled(e){this.setEventHandler("toolcancelled",e)}get onhostcontextchanged(){return this.getEventHandler("hostcontextchanged")}set onhostcontextchanged(e){this.setEventHandler("hostcontextchanged",e)}_onteardown;get onteardown(){return this._onteardown}set onteardown(e){this.warnIfRequestHandlerReplaced("onteardown",this._onteardown,e),this._onteardown=e,this.replaceRequestHandler(pg,(r,o)=>{if(!this._onteardown)throw Error("No onteardown handler set");return this._onteardown(r.params,o)})}_oncalltool;get oncalltool(){return this._oncalltool}set oncalltool(e){this.warnIfRequestHandlerReplaced("oncalltool",this._oncalltool,e),this._oncalltool=e,this.replaceRequestHandler(rd,(r,o)=>{if(!this._oncalltool)throw Error("No oncalltool handler set");return this._oncalltool(r.params,o)})}_onlisttools;get onlisttools(){return this._onlisttools}set onlisttools(e){this.warnIfRequestHandlerReplaced("onlisttools",this._onlisttools,e),this._onlisttools=e,this.replaceRequestHandler(nd,(r,o)=>{if(!this._onlisttools)throw Error("No onlisttools handler set");return this._onlisttools(r.params,o)})}assertCapabilityForMethod(e){switch(e){case"sampling/createMessage":if(!this._hostCapabilities?.sampling)throw Error(`Host does not support sampling (required for ${e})`);break}}assertRequestHandlerCapability(e){switch(e){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${e})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${e} registered`)}}assertNotificationCapability(e){}assertTaskCapability(e){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(e){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(e,r){if(this._assertInitialized("callServerTool"),typeof e=="string")throw Error(`callServerTool() expects an object as its first argument, but received a string ("${e}"). Did you mean: callServerTool({ name: "${e}", arguments: { ... } })?`);return await this.request({method:"tools/call",params:e},er,{onprogress:()=>{},resetTimeoutOnProgress:!0,...r})}async readServerResource(e,r){return this._assertInitialized("readServerResource"),await this.request({method:"resources/read",params:e},Xl,r)}async listServerResources(e,r){return this._assertInitialized("listServerResources"),await this.request({method:"resources/list",params:e},Yl,r)}async createSamplingMessage(e,r){this._assertInitialized("createSamplingMessage");let o=e.tools?ad:od;return await this.request({method:"sampling/createMessage",params:e},o,r)}sendMessage(e,r){return this._assertInitialized("sendMessage"),this.request({method:"ui/message",params:e},sg,r)}sendLog(e){return this.notification({method:"notifications/message",params:e})}updateModelContext(e,r){return this._assertInitialized("updateModelContext"),this.request({method:"ui/update-model-context",params:e},_o,r)}openLink(e,r){return this._assertInitialized("openLink"),this.request({method:"ui/open-link",params:e},og,r)}sendOpenLink=this.openLink;downloadFile(e,r){return this._assertInitialized("downloadFile"),this.request({method:"ui/download-file",params:e},ag,r)}requestTeardown(e={}){return this.notification({method:"ui/notifications/request-teardown",params:e})}requestDisplayMode(e,r){return this._assertInitialized("requestDisplayMode"),this.request({method:"ui/request-display-mode",params:e},gg,r)}sendSizeChanged(e){return this.notification({method:"ui/notifications/size-changed",params:e})}setupSizeChangedNotifications(){let e=!1,r=0,o=0,t=()=>{e||(e=!0,requestAnimationFrame(()=>{e=!1;let a=document.documentElement,s=a.style.height;a.style.height="max-content";let c=Math.ceil(a.getBoundingClientRect().height);a.style.height=s;let l=Math.ceil(window.innerWidth);(l!==r||c!==o)&&(r=l,o=c,this.sendSizeChanged({width:l,height:c}))}))};t();let i=new ResizeObserver(t);return i.observe(document.documentElement),i.observe(document.body),()=>i.disconnect()}async connect(e=new tg(window.parent,window.parent),r){if(this.transport)throw Error("App is already connected. Call close() before connecting again.");this._initializedSent=!1,await super.connect(e);try{let o=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:Xh}},bg,r);if(o===void 0)throw Error(`Server sent invalid initialize result: ${o}`);this._hostCapabilities=o.hostCapabilities,this._hostInfo=o.hostInfo,this._hostContext=o.hostContext,await this.notification({method:"ui/notifications/initialized"}),this._initializedSent=!0,this.options?.autoResize&&this.setupSizeChangedNotifications()}catch(o){throw this.close(),o}}}const kg="2.24.0",wg={version:kg},_r="tableauVizContainer";function Sg(n,e){const r=document.createElement("tableau-viz");return r.setAttribute("src",n),r.setAttribute("token",e),r.setAttribute("toolbar","hidden"),r}function xg(n,e,r){const o=document.getElementById(_r);if(!o){console.error(`[mcp-app] container element with id "${_r}" not found; cannot embed viz`);return}const t=Sg(n,e);t.addEventListener("firstvizsizeknown",i=>{const a=i.detail?.vizSize,s=a?.sheetSize?.maxSize?.height,c=a?.chromeHeight;if(typeof s!="number")return;const l=typeof c=="number"?c:0;t.style.height=`${s+l}px`}),t.addEventListener("vizloaderror",i=>{console.error("[mcp-app] tableau-viz reported a load error",i),r?.()}),o.replaceChildren(t)}const Ig=qe({content:Ua(qe({type:Za("text"),text:Gt()}))}),zg=qe({token:Gt()});async function Tg(n){if(!n.getHostCapabilities()?.serverTools)throw new Error("Cannot retrieve embed token: the MCP host does not support server tools (serverTools capability is unavailable).");const r=await n.callServerTool({name:"get-embed-token",arguments:{}});if(r.isError)throw new Error("Failed to get an embed token for the current authentication configuration.");const t=Ig.parse(r).content[0],i=JSON.parse(t.text);return zg.parse(i).token}function Og(n){return new Promise((e,r)=>{if(!("customElements"in window)){r(new Error("Custom elements are not available. Cannot access tableau-viz element"));return}if(customElements.get("tableau-viz")){e();return}const t=`${new URL(n).origin}/javascripts/api/tableau.embedding.3.latest.min.js`,i=document.createElement("script");i.type="module",i.src=t,i.onload=()=>{const a=customElements.whenDefined("tableau-viz"),s=new Promise((c,l)=>{setTimeout(()=>{l(new Error("Tableau Embedding API failed to load within 15 seconds"))},15e3)});Promise.race([a,s]).then(()=>e()).catch(c=>r(c))},i.onerror=()=>{console.error("Failed to load Tableau Embedding API from:",t),r(new Error(`Failed to load Tableau Embedding API from ${t}`))},document.head.appendChild(i)})}function Ia(n){if(n.querySelector(".open-in-tableau-error"))return;const e=document.createElement("div");e.className="open-in-tableau-error",e.textContent="The URL was unable to be opened.",n.appendChild(e)}function Ng(n){n.querySelector(".open-in-tableau-error")?.remove()}function jg(n,e,r){const o=r.querySelector("#openInTableauLink");o&&o.remove();const t=n.getHostCapabilities();if(!e||!t?.openLinks)return;const i=document.createElement("a");i.id="openInTableauLink",i.className="open-in-tableau",i.setAttribute("href",e),i.setAttribute("rel","noopener noreferrer"),i.setAttribute("aria-label","Open in Tableau (opens in a new browser tab)"),i.textContent="Open in Tableau ↗",i.onclick=async a=>{a.preventDefault();try{(await n.openLink({url:e})).isError?(console.warn("Open in Tableau link request denied by host",{url:e}),Ia(r)):Ng(r)}catch(s){console.warn("Open in Tableau link request failed",{url:e,error:s}),Ia(r)}},r.appendChild(i)}const Eg=`<svg width="171" height="165" viewBox="0 0 171 165" fill="none" xmlns="http://www.w3.org/2000/svg">
74
74
  <g clip-path="url(#clip0_1_26)">
75
75
  <path d="M132.921 108.53C132.921 108.53 123.601 108.53 146.001 108.53C168.401 108.53 171 139.53 139 139.53C90.5 139.53 71.5 136.03 67 119.53C62.5 103.03 81.5 95.0303 89 105.03C96.5 115.03 90 124.03 83 133.53C76 143.03 79 157.53 95 157.53" stroke="#BEC7F6" stroke-width="2" stroke-linecap="round"/>
76
76
  <path d="M92 127.53H120V89.53H92V127.53Z" fill="#1966FF"/>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tableau/mcp-server",
3
3
  "description": "Helping agents see and understand data.",
4
- "version": "2.21.1",
4
+ "version": "2.24.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/tableau/tableau-mcp.git"
@@ -20,13 +20,19 @@
20
20
  },
21
21
  "exports": {
22
22
  ".": "./build/index.js",
23
- "./tracing": "./build/telemetry/tracing.js"
23
+ "./tracing": "./build/telemetry/tracing.js",
24
+ "./features/featureGateProvider": {
25
+ "types": "./build/features/featureGateProvider.d.ts"
26
+ },
27
+ "./telemetry/telemetryProvider": {
28
+ "types": "./build/telemetry/telemetryProvider.d.ts"
29
+ }
24
30
  },
25
31
  "scripts": {
26
- "build": "tsx src/scripts/build.ts",
27
- "build:desktop": "tsx src/scripts/build.ts --variant desktop",
28
- "build:combined": "tsx src/scripts/build.ts --variant combined",
29
- "build:dev": "tsx src/scripts/build.ts --dev",
32
+ "build": "tsx src/scripts/build.ts && tsc --project tsconfig.providers.json",
33
+ "build:desktop": "tsx src/scripts/build.ts --variant desktop && tsc --project tsconfig.providers.json",
34
+ "build:combined": "tsx src/scripts/build.ts --variant combined && tsc --project tsconfig.providers.json",
35
+ "build:dev": "tsx src/scripts/build.ts --dev && tsc --project tsconfig.providers.json",
30
36
  "build:docker": "docker build -t tableau-mcp .",
31
37
  ":build:mcpb": "npx -y @anthropic-ai/mcpb pack . tableau-mcp.mcpb",
32
38
  "build:mcpb": "run-s build:manifest :build:mcpb",