opentel-mcp 0.18.0 → 0.18.1

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.18.1
4
+
5
+ A patch release: no new features and no change to the signals or metrics
6
+ (no new attribute or metric label keys).
7
+
8
+ ### Fixed
9
+
10
+ - **No more deprecation warnings on install.** `@opentelemetry/sdk-trace-node`
11
+ and `@opentelemetry/sdk-trace-base` are deprecated upstream (`npm warn
12
+ deprecated ... Use @opentelemetry/sdk-trace package`). The dev-mode tracer
13
+ (`setupNodeSdk: true`) now uses the supported `@opentelemetry/sdk-trace`
14
+ (`TracerProvider`). The old `NodeTracerProvider.register()` also installed
15
+ the global async-context manager and the W3C trace-context + baggage
16
+ propagator, so those are now registered explicitly, with
17
+ `@opentelemetry/context-async-hooks` and `@opentelemetry/core` as direct
18
+ dependencies (both were already in the install tree). Span processors, the
19
+ stderr exporter, OTLP export, `flushOnExit` and the single-shutdown guarantee
20
+ are unchanged, and `OTEL_BSP_*` batch tuning keeps working. One difference
21
+ to know about: the replacement SDK package no longer reads `OTEL_TRACES_SAMPLER*`
22
+ and `OTEL_SPAN_*_LIMIT` from the environment, so the dev-mode provider
23
+ always uses the default sampler (parent-based, always on) and default span
24
+ limits. Only hosts that set those variables *and* use `setupNodeSdk: true`
25
+ are affected; hosts that bring their own provider are not.
26
+
27
+ ### Release process
28
+
29
+ - **First release published with npm provenance via the release workflow.**
30
+ 0.18.0 (and earlier) were published manually and carry no provenance.
31
+
3
32
  ## 0.18.0
4
33
 
5
34
  Security observability: five small signals that help you notice some attacks
@@ -9,8 +38,8 @@ of it records tool arguments, result content, tool descriptions or matched
9
38
  secrets (derived signals only: booleans, counts, type names, hashes, tool
10
39
  names). Every new feature is off by default except the auth failure counter,
11
40
  which adds no new data. No new metric label keys. Python (0.1.0) is not
12
- affected; these signals are JS-only (ADR 034). This is the first release made
13
- by the signed release workflow (npm provenance, SBOM).
41
+ affected; these signals are JS-only (ADR 034). (Correction, see 0.18.1: this
42
+ release was published by hand and has no npm provenance or SBOM.)
14
43
 
15
44
  ### Security
16
45
 
package/README.md CHANGED
@@ -429,7 +429,7 @@ SigNoz's local OTLP endpoint:
429
429
  import { metrics, trace } from '@opentelemetry/api';
430
430
  import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
431
431
  import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
432
- import { NodeTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-node';
432
+ import { TracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace';
433
433
  import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
434
434
  import { resourceFromAttributes } from '@opentelemetry/resources';
435
435
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
@@ -447,7 +447,7 @@ const meterProvider = new MeterProvider({
447
447
  });
448
448
  metrics.setGlobalMeterProvider(meterProvider);
449
449
 
450
- const tracerProvider = new NodeTracerProvider({
450
+ const tracerProvider = new TracerProvider({
451
451
  resource,
452
452
  spanProcessors: [new BatchSpanProcessor(new OTLPTraceExporter({ url: 'http://localhost:4318/v1/traces' }))],
453
453
  });
@@ -464,7 +464,7 @@ instrumentMcpServer(server, {});
464
464
  Protocol — the wire format traces/metrics travel over) endpoint; point it
465
465
  at your own collector in production. `@opentelemetry/exporter-metrics-otlp-http`
466
466
  is a host-app dependency — opentel-mcp doesn't bundle it. `@opentelemetry/sdk-metrics`,
467
- `@opentelemetry/sdk-trace-node`, and `@opentelemetry/exporter-trace-otlp-http`
467
+ `@opentelemetry/sdk-trace`, and `@opentelemetry/exporter-trace-otlp-http`
468
468
  are already runtime dependencies of opentel-mcp itself (`@opentelemetry/sdk-metrics`
469
469
  as of v0.15.0, for the dev-mode metrics path below; the other two for
470
470
  `setupNodeSdk: true`'s dev tracing path, same as before), so no extra
@@ -537,7 +537,7 @@ nothing — your application owns its providers and its shutdown. Design:
537
537
  as of this feature — not an optional peer, not a dynamic import with a
538
538
  fallback path. See ADR 023's "Dependency strategy" section for the full
539
539
  reasoning: its own transitive dependencies were already in this package's
540
- tree via `@opentelemetry/resources`/`@opentelemetry/sdk-trace-node`, so
540
+ tree via `@opentelemetry/resources`/`@opentelemetry/sdk-trace`, so
541
541
  this adds no new package beyond itself.
542
542
 
543
543
  #### Using the Prometheus exporter instead of OTLP — `service.name` needs an extra option
@@ -2957,7 +2957,7 @@ truth: `src/config.js`.
2957
2957
 
2958
2958
  [^9]: `{ enabled?: boolean; pricingTable?: PricingTable; extractor?: UsageExtractor; budget?: { perSessionUsd?: number; perToolUsd?: number } }`, all fields optional and individually defaulted — `{ enabled: true, pricingTable: DEFAULT_PRICING, extractor: defaultExtractor }` with budget tracking off.
2959
2959
  [^2]: Required only when `setupNodeSdk` is `true`. Has no effect otherwise — the host app's registered `TracerProvider` owns the resource; passing it anyway logs a one-time `diag.warn`.
2960
- [^3]: Creates and registers a `NodeTracerProvider` that always prints to stderr (safe alongside stdio-transport servers — ADR 003), additionally exporting via OTLP/HTTP if `exporterUrl` is set.
2960
+ [^3]: Creates and registers a `TracerProvider` that always prints to stderr (safe alongside stdio-transport servers — ADR 003), additionally exporting via OTLP/HTTP if `exporterUrl` is set.
2961
2961
  [^4]: Only takes effect when `setupNodeSdk` is `true`.
2962
2962
 
2963
2963
  ## Ordering constraint
@@ -3314,7 +3314,7 @@ one looping agent apart from several unrelated callers of that same tool.
3314
3314
 
3315
3315
  ### Quick dev setup
3316
3316
 
3317
- `setupNodeSdk: true` sets up a `NodeTracerProvider` that prints spans to
3317
+ `setupNodeSdk: true` sets up a `TracerProvider` that prints spans to
3318
3318
  stderr (safe alongside stdio-transport MCP servers — see ADR 003),
3319
3319
  optionally plus an OTLP exporter if `exporterUrl` is provided. No separate
3320
3320
  OTel SDK setup needed — `serviceName` is required in this mode, since it
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opentel-mcp",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
4
4
  "description": "One-line OpenTelemetry instrumentation for Model Context Protocol (MCP) servers",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -67,17 +67,17 @@
67
67
  }
68
68
  },
69
69
  "dependencies": {
70
+ "@opentelemetry/context-async-hooks": "^2.9.0",
71
+ "@opentelemetry/core": "^2.9.0",
70
72
  "@opentelemetry/exporter-trace-otlp-http": "^0.220.0",
71
73
  "@opentelemetry/resources": "^2.9.0",
72
74
  "@opentelemetry/sdk-metrics": "^2.9.0",
73
- "@opentelemetry/sdk-trace-node": "^2.9.0"
75
+ "@opentelemetry/sdk-trace": "^2.9.0"
74
76
  },
75
77
  "devDependencies": {
76
78
  "@modelcontextprotocol/sdk": "1.32.1",
77
79
  "@modelcontextprotocol/server": "2.3.1",
78
80
  "@opentelemetry/api": "^1.9.0",
79
- "@opentelemetry/context-async-hooks": "^2.9.0",
80
- "@opentelemetry/sdk-trace-base": "^2.9.0",
81
81
  "@vitest/coverage-v8": "^4.1.12",
82
82
  "js-yaml": "^4.3.1",
83
83
  "typescript": "^7.0.2",
package/src/config.js CHANGED
@@ -41,7 +41,7 @@ import { resolveToolIntegrityConfig } from './tool-integrity/config.js';
41
41
 
42
42
  /**
43
43
  * @typedef {object} InstrumentOptions
44
- * @property {string} [serviceName] - Names the resource of the NodeTracerProvider this library creates.
44
+ * @property {string} [serviceName] - Names the resource of the TracerProvider this library creates.
45
45
  * Required (and must be a non-empty string) when `setupNodeSdk` is true. Has no effect when `setupNodeSdk`
46
46
  * is false or omitted — in that mode, resource attributes (including `service.name`) come from whatever
47
47
  * TracerProvider the host application has already registered; passing `serviceName` anyway is harmless but
@@ -55,7 +55,7 @@ import { resolveToolIntegrityConfig } from './tool-integrity/config.js';
55
55
  * @opentelemetry/api behavior — so this flag exists for opting out even when one *is* registered, not as a
56
56
  * substitute for that default.
57
57
  * @property {boolean} [setupNodeSdk=false] - When true, instrumentMcpServer() creates and registers its own
58
- * NodeTracerProvider (always exporting to stderr — safe alongside stdio-transport MCP servers, see ADR 003;
58
+ * TracerProvider (always exporting to stderr — safe alongside stdio-transport MCP servers, see ADR 003;
59
59
  * additionally to `exporterUrl` via OTLP/HTTP if set). When false (the default), spans are emitted via
60
60
  * whatever OpenTelemetry TracerProvider the host application
61
61
  * has already registered globally — or dropped silently if none has been registered. This default keeps
package/src/index.d.ts CHANGED
@@ -9,7 +9,7 @@ import type { ObservationState } from './observation/types.d.ts';
9
9
  */
10
10
  export interface InstrumentOptions {
11
11
  /**
12
- * Names the resource of the `NodeTracerProvider` this library creates.
12
+ * Names the resource of the `TracerProvider` this library creates.
13
13
  *
14
14
  * Required (and must be a non-empty string) when `setupNodeSdk` is `true` —
15
15
  * omitting it in that mode throws at runtime. Has no effect when
@@ -56,7 +56,7 @@ export interface InstrumentOptions {
56
56
 
57
57
  /**
58
58
  * When `true`, {@link instrumentMcpServer} creates and registers its own
59
- * `NodeTracerProvider` (always exporting to stderr; additionally to
59
+ * `TracerProvider` (always exporting to stderr; additionally to
60
60
  * `exporterUrl` via OTLP/HTTP if set).
61
61
  *
62
62
  * **Also stands up a dev-mode `MeterProvider` (ADR 023,
@@ -488,7 +488,7 @@ export type DuckTypedMcpServer = {
488
488
  * @param options - Instrumentation options.
489
489
  * @returns The same object that was passed in, for chaining. When
490
490
  * `options.setupNodeSdk` is `true`, the returned object also gets a
491
- * `shutdown()` method that flushes and shuts down the `NodeTracerProvider`
491
+ * `shutdown()` method that flushes and shuts down the `TracerProvider`
492
492
  * created for it — call it during your process's own shutdown sequence to
493
493
  * avoid losing buffered spans. As of v0.15.0 (ADR 023), when dev-mode
494
494
  * metrics were also set up (`enableMetrics` not `false`, and no
package/src/instrument.js CHANGED
@@ -4,9 +4,11 @@
4
4
 
5
5
  import { createRequire } from 'node:module';
6
6
  import { randomUUID } from 'node:crypto';
7
- import { trace, metrics, diag, SpanStatusCode, SpanKind } from '@opentelemetry/api';
7
+ import { trace, metrics, context, propagation, diag, SpanStatusCode, SpanKind } from '@opentelemetry/api';
8
8
  import { getV1Sdk, getV2Sdk } from './sdk/detect.js';
9
- import { NodeTracerProvider, SimpleSpanProcessor, BatchSpanProcessor } from '@opentelemetry/sdk-trace-node';
9
+ import { TracerProvider, SimpleSpanProcessor, BatchSpanProcessor } from '@opentelemetry/sdk-trace';
10
+ import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks';
11
+ import { CompositePropagator, W3CTraceContextPropagator, W3CBaggagePropagator, getNumberFromEnv } from '@opentelemetry/core';
10
12
  import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
11
13
  import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
12
14
  import { resourceFromAttributes } from '@opentelemetry/resources';
@@ -350,7 +352,7 @@ function detectServerKind(input) {
350
352
  * @returns {*} The same object that was passed in, for chaining. When
351
353
  * `options.setupNodeSdk` is true, the inner Server (and, when instrumenting
352
354
  * an McpServer, the outer object too) gets a `shutdown()` method that
353
- * flushes and shuts down the NodeTracerProvider created for it — call it
355
+ * flushes and shuts down the TracerProvider created for it — call it
354
356
  * during your process's own shutdown sequence to avoid losing buffered
355
357
  * spans. When `setupNodeSdk` is false (the default), no `shutdown()` is
356
358
  * attached; lifecycle of the global provider belongs to whoever
@@ -980,9 +982,29 @@ export function __resetMeterProviderWarnedForTests() {
980
982
  warnedMeterProviderAlreadyRegistered = false;
981
983
  }
982
984
 
985
+ /**
986
+ * The deprecated sdk-trace-base BatchSpanProcessor read the spec's
987
+ * OTEL_BSP_* variables itself; the sdk-trace one only takes explicit
988
+ * options, so the same four are read here to keep tuning via env working.
989
+ * Unset (or invalid) values are omitted, leaving the SDK defaults.
990
+ */
991
+ function batchProcessorConfigFromEnv() {
992
+ /** @type {Record<string, number>} */
993
+ const config = {};
994
+ const read = (key, name) => {
995
+ const value = getNumberFromEnv(name);
996
+ if (value !== undefined) config[key] = value;
997
+ };
998
+ read('maxQueueSize', 'OTEL_BSP_MAX_QUEUE_SIZE');
999
+ read('maxExportBatchSize', 'OTEL_BSP_MAX_EXPORT_BATCH_SIZE');
1000
+ read('scheduledDelayMillis', 'OTEL_BSP_SCHEDULE_DELAY');
1001
+ read('exportTimeoutMillis', 'OTEL_BSP_EXPORT_TIMEOUT');
1002
+ return config;
1003
+ }
1004
+
983
1005
  /**
984
1006
  * Resolves the Tracer to use for this server, optionally standing up an
985
- * owned NodeTracerProvider (and, per ADR 023, an owned dev-mode
1007
+ * owned TracerProvider (and, per ADR 023, an owned dev-mode
986
1008
  * MeterProvider) first.
987
1009
  *
988
1010
  * @param {import('@modelcontextprotocol/sdk/server/index.js').Server} server
@@ -994,9 +1016,9 @@ function setupTracer(server, resolved) {
994
1016
  // StderrSpanExporter, not ConsoleSpanExporter — stdio-transport MCP
995
1017
  // servers write JSON-RPC to stdout, so diagnostic span output must go
996
1018
  // to stderr instead or it corrupts the protocol stream. See ADR 003.
997
- const spanProcessors = [new SimpleSpanProcessor(new StderrSpanExporter())];
1019
+ const spanProcessors = [new SimpleSpanProcessor({ exporter: new StderrSpanExporter() })];
998
1020
  if (resolved.exporterUrl) {
999
- spanProcessors.push(new BatchSpanProcessor(new OTLPTraceExporter({ url: resolved.exporterUrl })));
1021
+ spanProcessors.push(new BatchSpanProcessor({ exporter: new OTLPTraceExporter({ url: resolved.exporterUrl }), ...batchProcessorConfigFromEnv() }));
1000
1022
  }
1001
1023
 
1002
1024
  // ADR 016 point 3: only attached when DEFAULT_PRICING is actually
@@ -1014,8 +1036,21 @@ function setupTracer(server, resolved) {
1014
1036
  // mode — one Resource construction, not two independently-built ones.
1015
1037
  const resource = resourceFromAttributes({ 'service.name': resolved.serviceName, ...pricingResourceAttributes });
1016
1038
 
1017
- const provider = new NodeTracerProvider({ resource, spanProcessors });
1018
- provider.register();
1039
+ // @opentelemetry/sdk-trace-node (deprecated) bundled a NodeTracerProvider
1040
+ // whose register() also installed the global async context manager and
1041
+ // W3C propagator; the replacement sdk-trace TracerProvider has no
1042
+ // register(), so the same three globals are set explicitly here to keep
1043
+ // dev-mode behavior (async context propagation, trace-context
1044
+ // propagation) identical. Each setter is first-wins and returns false
1045
+ // when something is already registered — same as register() did.
1046
+ const provider = new TracerProvider({ resource, spanProcessors });
1047
+ trace.setGlobalTracerProvider(provider);
1048
+ const contextManager = new AsyncLocalStorageContextManager();
1049
+ contextManager.enable();
1050
+ context.setGlobalContextManager(contextManager);
1051
+ propagation.setGlobalPropagator(
1052
+ new CompositePropagator({ propagators: [new W3CTraceContextPropagator(), new W3CBaggagePropagator()] }),
1053
+ );
1019
1054
 
1020
1055
  // ADR 023 (v0.15.0): dev-mode metrics. Only attempted when metrics
1021
1056
  // aren't separately opted out via enableMetrics: false — a host who's