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 +31 -2
- package/README.md +6 -6
- package/package.json +4 -4
- package/src/config.js +2 -2
- package/src/index.d.ts +3 -3
- package/src/instrument.js +43 -8
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).
|
|
13
|
-
by
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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 `
|
|
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 `
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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 `
|
|
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
|
-
* `
|
|
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 `
|
|
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 {
|
|
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
|
|
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
|
|
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
|
-
|
|
1018
|
-
|
|
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
|