diff --git a/dist/src/index.js b/dist/src/index.js index f0cb0a7..6d814f6 100755 --- a/dist/src/index.js +++ b/dist/src/index.js @@ -11,7 +11,7 @@ import { SERVER_NAME, APP_VERSION } from './constants.js'; import { env } from './env.js'; import { createTemplateRenderer } from './tools/utils/templateRenderer.js'; import { createErrorTemplateRenderer } from './tools/utils/errorTemplateRenderer.js'; -import { createTelemetryClient, detectPaginationUsed, parseTelemetryFlag, TelemetrySession, } from './telemetry/index.js'; +import { createTelemetryClient, detectPaginationUsed, parseTelemetryFlag, TelemetrySession } from './telemetry/index.js'; const SUPPORTED_REGIONS = { us: 'https://api.postman.com', eu: 'https://api.eu.postman.com', @@ -134,7 +134,7 @@ async function run() { const tools = allGeneratedTools .filter((t) => enabledMethods.includes(t.method)) .sort(toolSorter); - const region = regionIndex !== -1 && regionIndex + 1 < args.length && isValidRegion(args[regionIndex + 1]) + const region = (regionIndex !== -1 && regionIndex + 1 < args.length && isValidRegion(args[regionIndex + 1])) ? args[regionIndex + 1] : 'us'; const telemetryEnabled = parseTelemetryFlag(process.env.POSTMAN_MCP_TELEMETRY) ?? false; @@ -224,14 +224,12 @@ async function run() { isError: result.isError ?? false, authMethod: 'api_key', paginationUsed, - meta: extra?._meta - ? { - trigger: extra._meta.trigger ?? '', - conversation_id: extra._meta.conversation_id ?? '', - task_type: extra._meta.task_type ?? '', - model_name: extra._meta.model_name ?? '', - } - : undefined, + meta: extra?._meta ? { + trigger: extra._meta.trigger ?? '', + conversation_id: extra._meta.conversation_id ?? '', + task_type: extra._meta.task_type ?? '', + model_name: extra._meta.model_name ?? '', + } : undefined, metaRaw, }); if (result.content?.[0]?.type === 'text') { @@ -246,14 +244,12 @@ async function run() { const errMsg = String(error?.message || error); logBoth(server, 'error', `Tool invocation failed: ${toolName}: ${errMsg}`, { toolName }); const errDurationMs = Date.now() - start; - const errorMeta = extra?._meta - ? { - trigger: extra._meta.trigger ?? '', - conversation_id: extra._meta.conversation_id ?? '', - task_type: extra._meta.task_type ?? '', - model_name: extra._meta.model_name ?? '', - } - : undefined; + const errorMeta = extra?._meta ? { + trigger: extra._meta.trigger ?? '', + conversation_id: extra._meta.conversation_id ?? '', + task_type: extra._meta.task_type ?? '', + model_name: extra._meta.model_name ?? '', + } : undefined; if (error instanceof McpError) { const httpStatus = error.data?.httpStatus; if (typeof httpStatus === 'number') { @@ -272,8 +268,7 @@ async function run() { ? 'RATE_LIMITED' : 'UPSTREAM_ERROR', errorStage: typeof httpStatus === 'number' && (httpStatus === 401 || httpStatus === 403) - ? 'auth' - : 'upstream', + ? 'auth' : 'upstream', errorUpstream: 'postman-api', rateLimited: typeof httpStatus === 'number' && httpStatus === 429, meta: errorMeta, diff --git a/dist/src/telemetry/client.js b/dist/src/telemetry/client.js index f455d73..51b377c 100644 --- a/dist/src/telemetry/client.js +++ b/dist/src/telemetry/client.js @@ -102,7 +102,8 @@ export class TelemetryClient { this.buffer.push(event); this.bufferSizeBytes += eventSize; this.resetIdleTimer(); - if (this.buffer.length >= MAX_BUFFER_COUNT || this.bufferSizeBytes >= MAX_BUFFER_BYTES) { + if (this.buffer.length >= MAX_BUFFER_COUNT || + this.bufferSizeBytes >= MAX_BUFFER_BYTES) { void this.flush(); } } diff --git a/dist/src/telemetry/session.js b/dist/src/telemetry/session.js index 2da8e6c..6503e8f 100644 --- a/dist/src/telemetry/session.js +++ b/dist/src/telemetry/session.js @@ -56,7 +56,9 @@ export class TelemetrySession { setToolNames(toolNames) { this.toolListCount = toolNames.length; const sorted = [...toolNames].sort(); - const hash = createHash('sha256').update(sorted.join(',')).digest('hex'); + const hash = createHash('sha256') + .update(sorted.join(',')) + .digest('hex'); this.toolsetSnapshotId = hash.substring(0, 12); } getToolListCount() { diff --git a/src/index.ts b/src/index.ts index 622fbc0..499027c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,13 +22,7 @@ import { ServerContext } from './tools/utils/toolHelpers.js'; import { env } from './env.js'; import { createTemplateRenderer } from './tools/utils/templateRenderer.js'; import { createErrorTemplateRenderer } from './tools/utils/errorTemplateRenderer.js'; -import { - createTelemetryClient, - detectPaginationUsed, - parseTelemetryFlag, - TelemetrySession, - type ITelemetryClient, -} from './telemetry/index.js'; +import { createTelemetryClient, detectPaginationUsed, parseTelemetryFlag, TelemetrySession, type ITelemetryClient } from './telemetry/index.js'; const SUPPORTED_REGIONS = { us: 'https://api.postman.com', @@ -206,20 +200,16 @@ async function run() { .sort(toolSorter); // Determine region for telemetry - const region: 'us' | 'eu' = - regionIndex !== -1 && regionIndex + 1 < args.length && isValidRegion(args[regionIndex + 1]) - ? (args[regionIndex + 1] as 'us' | 'eu') - : 'us'; + const region: 'us' | 'eu' = (regionIndex !== -1 && regionIndex + 1 < args.length && isValidRegion(args[regionIndex + 1])) + ? args[regionIndex + 1] as 'us' | 'eu' + : 'us'; // Telemetry is OFF by default for the open-source STDIO server. Users must // opt in explicitly with POSTMAN_MCP_TELEMETRY=true; any other value (or // unset) keeps telemetry disabled. const telemetryEnabled = parseTelemetryFlag(process.env.POSTMAN_MCP_TELEMETRY) ?? false; if (telemetryEnabled) { - log( - 'info', - 'Telemetry enabled (POSTMAN_MCP_TELEMETRY=true). Set POSTMAN_MCP_TELEMETRY=false to disable.' - ); + log('info', 'Telemetry enabled (POSTMAN_MCP_TELEMETRY=true). Set POSTMAN_MCP_TELEMETRY=false to disable.'); } const telemetry: ITelemetryClient = createTelemetryClient({ telemetryEnabled, @@ -334,14 +324,12 @@ async function run() { isError: result.isError ?? false, authMethod: 'api_key', paginationUsed, - meta: extra?._meta - ? { - trigger: (extra._meta as any).trigger ?? '', - conversation_id: (extra._meta as any).conversation_id ?? '', - task_type: (extra._meta as any).task_type ?? '', - model_name: (extra._meta as any).model_name ?? '', - } - : undefined, + meta: extra?._meta ? { + trigger: (extra._meta as any).trigger ?? '', + conversation_id: (extra._meta as any).conversation_id ?? '', + task_type: (extra._meta as any).task_type ?? '', + model_name: (extra._meta as any).model_name ?? '', + } : undefined, metaRaw, }); @@ -360,14 +348,12 @@ async function run() { logBoth(server, 'error', `Tool invocation failed: ${toolName}: ${errMsg}`, { toolName }); const errDurationMs = Date.now() - start; - const errorMeta = extra?._meta - ? { - trigger: (extra._meta as any).trigger ?? '', - conversation_id: (extra._meta as any).conversation_id ?? '', - task_type: (extra._meta as any).task_type ?? '', - model_name: (extra._meta as any).model_name ?? '', - } - : undefined; + const errorMeta = extra?._meta ? { + trigger: (extra._meta as any).trigger ?? '', + conversation_id: (extra._meta as any).conversation_id ?? '', + task_type: (extra._meta as any).task_type ?? '', + model_name: (extra._meta as any).model_name ?? '', + } : undefined; if (error instanceof McpError) { const httpStatus = (error.data as Record)?.httpStatus; @@ -382,16 +368,13 @@ async function run() { authMethod: 'api_key', paginationUsed, errorType: 'tool', - errorCode: - typeof httpStatus === 'number' && (httpStatus === 401 || httpStatus === 403) - ? 'AUTH_ERROR' - : typeof httpStatus === 'number' && httpStatus === 429 - ? 'RATE_LIMITED' - : 'UPSTREAM_ERROR', - errorStage: - typeof httpStatus === 'number' && (httpStatus === 401 || httpStatus === 403) - ? 'auth' - : 'upstream', + errorCode: typeof httpStatus === 'number' && (httpStatus === 401 || httpStatus === 403) + ? 'AUTH_ERROR' + : typeof httpStatus === 'number' && httpStatus === 429 + ? 'RATE_LIMITED' + : 'UPSTREAM_ERROR', + errorStage: typeof httpStatus === 'number' && (httpStatus === 401 || httpStatus === 403) + ? 'auth' : 'upstream', errorUpstream: 'postman-api', rateLimited: typeof httpStatus === 'number' && httpStatus === 429, meta: errorMeta, diff --git a/src/telemetry/client.ts b/src/telemetry/client.ts index a8c164a..3f435e9 100644 --- a/src/telemetry/client.ts +++ b/src/telemetry/client.ts @@ -1,5 +1,9 @@ import { TelemetrySession } from './session.js'; -import type { TelemetryEvent, SessionInitEvent, ToolCallEvent } from './types.js'; +import type { + TelemetryEvent, + SessionInitEvent, + ToolCallEvent, +} from './types.js'; /** * Options for constructing a TelemetryClient. @@ -124,7 +128,7 @@ export class TelemetryClient { params: { clientCapabilities: string[]; serverCapabilities: string[]; - } + }, ): void { const event: SessionInitEvent = { ...this.buildBaseEvent(session, 'session_init'), @@ -209,7 +213,7 @@ export class TelemetryClient { private buildBaseEvent( session: TelemetrySession, eventType: T, - conversationId?: string + conversationId?: string, ): { event_type: T; timestamp: string; @@ -263,7 +267,10 @@ export class TelemetryClient { this.resetIdleTimer(); // Auto-flush if thresholds exceeded - if (this.buffer.length >= MAX_BUFFER_COUNT || this.bufferSizeBytes >= MAX_BUFFER_BYTES) { + if ( + this.buffer.length >= MAX_BUFFER_COUNT || + this.bufferSizeBytes >= MAX_BUFFER_BYTES + ) { // Fire-and-forget flush void this.flush(); } @@ -277,9 +284,13 @@ export class TelemetryClient { * a single flush batch are assumed to share a region (true in practice — * a single pod targets a single region). */ - private async send(events: TelemetryEvent[], attempt: number): Promise { + private async send( + events: TelemetryEvent[], + attempt: number, + ): Promise { const region = events[0]?.region ?? 'us'; - const baseUrl = process.env[GATEWAY_BASE_URL_OVERRIDE_ENV] ?? GATEWAY_BASE_URL[region]; + const baseUrl = + process.env[GATEWAY_BASE_URL_OVERRIDE_ENV] ?? GATEWAY_BASE_URL[region]; const ingestUrl = `${baseUrl}${TELEMETRY_INGEST_PATH}`; try { diff --git a/src/telemetry/index.ts b/src/telemetry/index.ts index 132e1bb..1dc13aa 100644 --- a/src/telemetry/index.ts +++ b/src/telemetry/index.ts @@ -12,7 +12,7 @@ export type { ToolCallParams } from './client.js'; export interface ITelemetryClient { sessionInit( session: TelemetrySession, - params: { clientCapabilities: string[]; serverCapabilities: string[] } + params: { clientCapabilities: string[]; serverCapabilities: string[] }, ): void; toolCall(session: TelemetrySession, params: ToolCallParams): void; flush(): Promise; diff --git a/src/telemetry/noop.ts b/src/telemetry/noop.ts index 5924ab8..b8a7ff1 100644 --- a/src/telemetry/noop.ts +++ b/src/telemetry/noop.ts @@ -8,7 +8,7 @@ import type { TelemetrySession } from './session.js'; export class NoopTelemetryClient { sessionInit( _session: TelemetrySession, - _params: { clientCapabilities: string[]; serverCapabilities: string[] } + _params: { clientCapabilities: string[]; serverCapabilities: string[] }, ): void {} toolCall(_session: TelemetrySession, _params: ToolCallParams): void {} async flush(): Promise {} diff --git a/src/telemetry/session.ts b/src/telemetry/session.ts index 952e5b7..59ad359 100644 --- a/src/telemetry/session.ts +++ b/src/telemetry/session.ts @@ -131,7 +131,10 @@ export class TelemetrySession { } /** Stores client metadata received during the MCP initialize handshake. */ - setClientInfo(clientInfo: { name: string; version: string }, protocolVersion: string): void { + setClientInfo( + clientInfo: { name: string; version: string }, + protocolVersion: string, + ): void { this.clientName = clientInfo.name; this.clientVersion = clientInfo.version; this.protocolVersion = protocolVersion; @@ -155,7 +158,9 @@ export class TelemetrySession { setToolNames(toolNames: string[]): void { this.toolListCount = toolNames.length; const sorted = [...toolNames].sort(); - const hash = createHash('sha256').update(sorted.join(',')).digest('hex'); + const hash = createHash('sha256') + .update(sorted.join(',')) + .digest('hex'); this.toolsetSnapshotId = hash.substring(0, 12); }