diff --git a/.github/workflows/copilot-token-audit.lock.yml b/.github/workflows/copilot-token-audit.lock.yml index 4e9be857ab9..eb7585ce90b 100644 --- a/.github/workflows/copilot-token-audit.lock.yml +++ b/.github/workflows/copilot-token-audit.lock.yml @@ -79,6 +79,7 @@ jobs: comment_repo: "" lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} model: ${{ steps.generate_aw_info.outputs.model }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} steps: - name: Checkout actions folder uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -88,9 +89,11 @@ jobs: actions persist-credentials: false - name: Setup Scripts + id: setup uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} - name: Generate agentic run info id: generate_aw_info env: @@ -315,6 +318,7 @@ jobs: model: ${{ needs.activation.outputs.model }} output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} steps: - name: Checkout actions folder uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -324,9 +328,12 @@ jobs: actions persist-credentials: false - name: Setup Scripts + id: setup uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} - name: Set runtime paths id: set-runtime-paths run: | @@ -982,9 +989,12 @@ jobs: actions persist-credentials: false - name: Setup Scripts + id: setup uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1065,7 +1075,9 @@ jobs: await main(); detection: - needs: agent + needs: + - activation + - agent if: > always() && needs.agent.result != 'skipped' && (needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true') runs-on: ubuntu-latest @@ -1084,9 +1096,12 @@ jobs: actions persist-credentials: false - name: Setup Scripts + id: setup uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1220,6 +1235,7 @@ jobs: push_repo_memory: needs: + - activation - agent - detection if: > @@ -1244,9 +1260,12 @@ jobs: actions persist-credentials: false - name: Setup Scripts + id: setup uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -1305,6 +1324,7 @@ jobs: safe_outputs: needs: + - activation - agent - detection if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success' @@ -1338,9 +1358,12 @@ jobs: actions persist-credentials: false - name: Setup Scripts + id: setup uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1390,6 +1413,7 @@ jobs: update_cache_memory: needs: + - activation - agent - detection if: > @@ -1409,9 +1433,12 @@ jobs: actions persist-credentials: false - name: Setup Scripts + id: setup uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} - name: Download cache-memory artifact (default) id: download_cache_default uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 @@ -1436,7 +1463,9 @@ jobs: path: /tmp/gh-aw/cache-memory upload_assets: - needs: agent + needs: + - activation + - agent if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'upload_asset') runs-on: ubuntu-slim permissions: @@ -1454,9 +1483,12 @@ jobs: actions persist-credentials: false - name: Setup Scripts + id: setup uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/.github/workflows/copilot-token-optimizer.lock.yml b/.github/workflows/copilot-token-optimizer.lock.yml index d1b11a014d6..969c9c56934 100644 --- a/.github/workflows/copilot-token-optimizer.lock.yml +++ b/.github/workflows/copilot-token-optimizer.lock.yml @@ -74,6 +74,7 @@ jobs: comment_repo: "" lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} model: ${{ steps.generate_aw_info.outputs.model }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} steps: - name: Checkout actions folder uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -83,9 +84,11 @@ jobs: actions persist-credentials: false - name: Setup Scripts + id: setup uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} - name: Generate agentic run info id: generate_aw_info env: @@ -299,6 +302,7 @@ jobs: model: ${{ needs.activation.outputs.model }} output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} steps: - name: Checkout actions folder uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -308,9 +312,12 @@ jobs: actions persist-credentials: false - name: Setup Scripts + id: setup uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} - name: Set runtime paths id: set-runtime-paths run: | @@ -911,9 +918,12 @@ jobs: actions persist-credentials: false - name: Setup Scripts + id: setup uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -994,7 +1004,9 @@ jobs: await main(); detection: - needs: agent + needs: + - activation + - agent if: > always() && needs.agent.result != 'skipped' && (needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true') runs-on: ubuntu-latest @@ -1013,9 +1025,12 @@ jobs: actions persist-credentials: false - name: Setup Scripts + id: setup uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1149,6 +1164,7 @@ jobs: push_repo_memory: needs: + - activation - agent - detection if: > @@ -1173,9 +1189,12 @@ jobs: actions persist-credentials: false - name: Setup Scripts + id: setup uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -1234,6 +1253,7 @@ jobs: safe_outputs: needs: + - activation - agent - detection if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success' @@ -1267,9 +1287,12 @@ jobs: actions persist-credentials: false - name: Setup Scripts + id: setup uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} - name: Download agent output artifact id: download-agent-output continue-on-error: true diff --git a/docs/public/schemas/mcp-gateway-config.schema.json b/docs/public/schemas/mcp-gateway-config.schema.json index cda369b7a0b..65aea1d0995 100644 --- a/docs/public/schemas/mcp-gateway-config.schema.json +++ b/docs/public/schemas/mcp-gateway-config.schema.json @@ -278,10 +278,66 @@ "type": "integer", "description": "Keepalive ping interval in seconds for HTTP MCP backends. Sends periodic pings to prevent session expiry during long-running agent tasks. Set to -1 to disable keepalive pings. Unset or 0 uses the gateway default (1500 seconds = 25 minutes).", "minimum": -1 + }, + "opentelemetry": { + "$ref": "#/definitions/opentelemetryConfig", + "description": "Optional OpenTelemetry configuration for emitting distributed tracing spans for MCP calls. When configured, the gateway exports OTLP/HTTP traces to the specified collector endpoint." } }, "required": ["port", "domain", "apiKey"], "additionalProperties": false + }, + "opentelemetryConfig": { + "type": "object", + "description": "OpenTelemetry configuration for the MCP Gateway. When present, the gateway emits distributed tracing spans for each MCP tool invocation and exports them via OTLP/HTTP to the configured collector endpoint. Per MCP Gateway Specification section 4.1.3.6.", + "properties": { + "endpoint": { + "type": "string", + "description": "OTLP/HTTP endpoint URL for the OpenTelemetry collector (e.g., 'https://collector.example.com:4318/v1/traces'). MUST be an HTTPS URL. Supports variable expressions using '${VARIABLE_NAME}' syntax.", + "pattern": "^(https://.+|\\$\\{[A-Z_][A-Z0-9_]*\\})$", + "minLength": 1 + }, + "headers": { + "type": "object", + "description": "Additional HTTP headers sent with every OTLP export request (e.g., for authentication). Values may contain variable expressions using '${VARIABLE_NAME}' syntax.", + "additionalProperties": { + "type": "string" + }, + "default": {} + }, + "traceId": { + "type": "string", + "description": "Parent trace ID for W3C trace context propagation. When set, all gateway spans are attached as children of this trace. MUST be a 32-character lowercase hexadecimal string (128-bit W3C trace ID). Supports variable expressions.", + "oneOf": [ + { + "pattern": "^[0-9a-f]{32}$" + }, + { + "pattern": "^\\$\\{[A-Z_][A-Z0-9_]*\\}$" + } + ] + }, + "spanId": { + "type": "string", + "description": "Parent span ID for W3C trace context propagation. When set together with traceId, this span becomes the direct parent of the gateway root span. MUST be a 16-character lowercase hexadecimal string (64-bit W3C span ID). Ignored when traceId is not set. Supports variable expressions.", + "oneOf": [ + { + "pattern": "^[0-9a-f]{16}$" + }, + { + "pattern": "^\\$\\{[A-Z_][A-Z0-9_]*\\}$" + } + ] + }, + "serviceName": { + "type": "string", + "description": "Logical service name reported in the 'service.name' resource attribute of all emitted spans. Identifies the gateway in the tracing backend. Defaults to 'mcp-gateway' when not specified.", + "minLength": 1, + "default": "mcp-gateway" + } + }, + "required": ["endpoint"], + "additionalProperties": false } }, "examples": [ diff --git a/docs/src/content/docs/reference/mcp-gateway.md b/docs/src/content/docs/reference/mcp-gateway.md index 420adc6a35f..555323e8eb1 100644 --- a/docs/src/content/docs/reference/mcp-gateway.md +++ b/docs/src/content/docs/reference/mcp-gateway.md @@ -7,7 +7,7 @@ sidebar: # MCP Gateway Specification -**Version**: 1.9.0 +**Version**: 1.11.0 **Status**: Draft Specification **Latest Version**: [mcp-gateway](/gh-aw/reference/mcp-gateway/) **JSON Schema**: [mcp-gateway-config.schema.json](/gh-aw/schemas/mcp-gateway-config.schema.json) @@ -251,6 +251,7 @@ The `gateway` section is required and configures gateway-specific behavior: | `payloadSizeThreshold` | integer | No | Size threshold in bytes for storing payloads to disk (default: 524288 = 512KB) | | `trustedBots` | array[string] | No | Additional GitHub bot identity strings (e.g., `github-actions[bot]`) passed to the gateway and merged with its built-in trusted identity list. This field is additive — it extends the internal list but cannot remove built-in entries. | | `keepaliveInterval` | integer | No | Keepalive ping interval in seconds for HTTP MCP backends. Prevents session expiry during long-running tasks. Use `-1` to disable, `0` or unset for gateway default (1500s = 25 min), or a positive integer for a custom interval. | +| `opentelemetry` | object | No | OpenTelemetry configuration for emitting distributed tracing events for MCP calls. See Section 4.1.3.6 for details. | #### 4.1.3.1 Payload Directory Path Validation @@ -448,6 +449,73 @@ sandbox: - A value of `-1` disables keepalive pings entirely - Any positive integer sets the keepalive interval in seconds +#### 4.1.3.6 OpenTelemetry Configuration + +The optional `opentelemetry` object in the gateway configuration enables the gateway to emit distributed tracing events for MCP calls using the [OpenTelemetry](https://opentelemetry.io/) standard. When configured, the gateway creates spans for each MCP tool invocation and exports them to the designated collector endpoint. + +**Configuration Fields**: + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `endpoint` | string | Yes (when `opentelemetry` is present) | OTLP/HTTP endpoint URL for the OpenTelemetry collector (e.g., `https://collector.example.com:4318/v1/traces`). MUST use HTTPS. Supports variable expressions. | +| `headers` | object | No | Additional HTTP headers sent with every export request to the collector endpoint. Commonly used for authentication (e.g., `Authorization: "Bearer ${OTEL_TOKEN}"`). Values MAY contain variable expressions. | +| `traceId` | string | No | Parent trace ID for context propagation. When set, the gateway attaches all emitted spans as children of this trace, enabling correlation with an existing distributed trace. MUST be a 32-character lowercase hex string (128-bit W3C trace ID format). Supports variable expressions. | +| `spanId` | string | No | Parent span ID for context propagation. When set together with `traceId`, the gateway sets this span as the direct parent of its root span. MUST be a 16-character lowercase hex string (64-bit W3C span ID format). Ignored when `traceId` is not set. Supports variable expressions. | +| `serviceName` | string | No | Logical service name reported in the `service.name` resource attribute of all emitted spans. Identifies the gateway in the tracing backend. Defaults to `"mcp-gateway"` when not specified. | + +**Configuration Example**: + +```json +{ + "gateway": { + "port": 8080, + "domain": "localhost", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "opentelemetry": { + "endpoint": "https://collector.example.com:4318/v1/traces", + "headers": { + "Authorization": "Bearer ${OTEL_TOKEN}" + }, + "traceId": "${PARENT_TRACE_ID}", + "spanId": "${PARENT_SPAN_ID}", + "serviceName": "my-mcp-gateway" + } + } +} +``` + +**Tracing Behavior**: + +When `opentelemetry` is configured, the gateway MUST: + +1. Create a root span for the gateway process lifetime with `service.name` set to the configured `serviceName` +2. Create a child span for each MCP tool invocation with the following attributes: + - `mcp.server`: the server name as configured in `mcpServers` + - `mcp.method`: the JSON-RPC method name (e.g., `tools/call`) + - `mcp.tool`: the tool name when the method is `tools/call` + - `http.status_code`: the HTTP status code of the proxied response +3. Record span start and end timestamps accurately +4. Export completed spans to the configured `endpoint` using the OTLP/HTTP protocol +5. Apply any configured `headers` to every export request +6. Propagate W3C `traceparent` context when `traceId` and `spanId` are provided + +When `traceId` is supplied, the gateway MUST construct a valid W3C `traceparent` header and use it as the parent context for the root span. The trace flags field SHOULD be set to `01` (sampled) when the gateway has no upstream sampling decision available; implementations MAY propagate upstream sampling flags when they are available. When only `traceId` is supplied without `spanId`, the gateway MUST generate a random `spanId` for the `traceparent` header. + +**Failure Handling**: + +The gateway MUST NOT fail to start if the OpenTelemetry collector endpoint is unreachable. Export failures SHOULD be logged as warnings and MUST NOT affect MCP request processing. The gateway SHOULD implement an exponential back-off retry strategy for failed exports. + +**Requirements**: + +- `endpoint` MUST be present when the `opentelemetry` object is configured +- `endpoint` MUST be an HTTPS URL +- `traceId`, when provided, MUST be a 32-character lowercase hex string +- `spanId`, when provided, MUST be a 16-character lowercase hex string +- `spanId` SHOULD only be set when `traceId` is also set; if `spanId` is provided without `traceId` the gateway SHOULD log a warning and ignore `spanId` +- Export failures MUST NOT propagate errors to MCP clients + +**Compliance Test**: T-OTEL-001 through T-OTEL-009 (Section 10.1.10) + #### 4.1.3a Top-Level Configuration Fields The following fields MAY be specified at the top level of the configuration: @@ -1381,6 +1449,19 @@ A conforming implementation MUST pass the following test categories: - **T-LIFE-006**: In-flight request handling during shutdown - **T-LIFE-007**: New requests rejected after close initiated +#### 10.1.10 OpenTelemetry Tests + +- **T-OTEL-001**: Gateway starts successfully when `opentelemetry` is omitted +- **T-OTEL-002**: Gateway starts successfully when `opentelemetry` is configured with a valid endpoint +- **T-OTEL-003**: Reject `opentelemetry` configuration with missing `endpoint` field +- **T-OTEL-004**: Reject `opentelemetry` configuration with a non-HTTPS endpoint +- **T-OTEL-005**: Span emitted for each MCP tool invocation with required attributes (`mcp.server`, `mcp.method`, `mcp.tool`, `http.status_code`) +- **T-OTEL-006**: Configured `headers` are sent with every OTLP export request +- **T-OTEL-007**: W3C `traceparent` context propagated when both `traceId` and `spanId` are configured +- **T-OTEL-008**: Gateway generates random `spanId` in `traceparent` when only `traceId` is provided +- **T-OTEL-009**: Export failure does not affect MCP request processing or gateway availability +- **T-OTEL-010**: `serviceName` is reflected in `service.name` resource attribute of emitted spans + ### 10.2 Compliance Checklist | Requirement | Test ID | Level | Status | @@ -1396,6 +1477,7 @@ A conforming implementation MUST pass the following test categories: | Configuration output | T-OUT-* | 1 | Required | | Error handling | T-ERR-* | 1 | Required | | Gateway lifecycle | T-LIFE-* | 2 | Standard | +| OpenTelemetry | T-OTEL-* | 3 | Optional | ### 10.3 Test Execution @@ -1548,6 +1630,66 @@ The `registry` field documents the MCP server's installation location in an MCP - Registry-aware tooling can use this field for discovery and version management - The field complements other configuration fields like `container`, `entrypointArgs`, or `url` +#### A.6 Gateway with OpenTelemetry Tracing + +```json +{ + "mcpServers": { + "github": { + "container": "ghcr.io/github/github-mcp-server:latest", + "env": { + "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}" + } + } + }, + "gateway": { + "port": 8080, + "domain": "localhost", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "opentelemetry": { + "endpoint": "https://collector.example.com:4318/v1/traces", + "headers": { + "Authorization": "Bearer ${OTEL_TOKEN}" + }, + "serviceName": "my-workflow-gateway" + } + } +} +``` + +#### A.7 Gateway with OpenTelemetry and Parent Trace Context + +The following example propagates an existing distributed trace into the gateway, linking all MCP spans as children of a parent trace originating in another system: + +```json +{ + "mcpServers": { + "github": { + "container": "ghcr.io/github/github-mcp-server:latest", + "env": { + "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}" + } + } + }, + "gateway": { + "port": 8080, + "domain": "localhost", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "opentelemetry": { + "endpoint": "https://collector.example.com:4318/v1/traces", + "headers": { + "Authorization": "Bearer ${OTEL_TOKEN}" + }, + "traceId": "${PARENT_TRACE_ID}", + "spanId": "${PARENT_SPAN_ID}", + "serviceName": "my-workflow-gateway" + } + } +} +``` + +`PARENT_TRACE_ID` and `PARENT_SPAN_ID` are 32-character and 16-character lowercase hex strings respectively, typically injected as environment variables by the orchestrating system. + ### Appendix B: Gateway Lifecycle Examples #### B.1 Closing the Gateway @@ -1661,17 +1803,38 @@ Content-Type: application/json - **[RFC 2119]** Key words for use in RFCs to Indicate Requirement Levels - **[JSON-RPC 2.0]** JSON-RPC 2.0 Specification - **[MCP]** Model Context Protocol Specification +- **[W3C-TraceContext]** W3C Trace Context — Trace Context Level 2 (https://www.w3.org/TR/trace-context/) +- **[OTLP]** OpenTelemetry Protocol Specification — OTLP/HTTP Transport (https://opentelemetry.io/docs/specs/otlp/#otlphttp) ### Informative References - **[MCP-Config]** MCP Configuration Format - **[HTTP/1.1]** Hypertext Transfer Protocol -- HTTP/1.1 - **[gh-aw-audit]** [Audit Commands Reference](/gh-aw/reference/audit/) — Runtime MCP server health, guard policy analysis, and cross-run debugging +- **[OpenTelemetry]** OpenTelemetry — Observability framework (https://opentelemetry.io/) --- ## Change Log +### Version 1.11.0 (Draft) + +- **Added**: `opentelemetry` field to gateway configuration (Section 4.1.3, 4.1.3.6) + - Optional object for configuring OpenTelemetry distributed tracing of MCP calls + - `endpoint` (required when present): HTTPS OTLP/HTTP collector endpoint URL + - `headers`: Additional HTTP headers sent with every export request (e.g., `Authorization`) + - `traceId`: Parent trace ID (32-char lowercase hex) for W3C trace context propagation + - `spanId`: Parent span ID (16-char lowercase hex) for W3C trace context propagation + - `serviceName`: Logical service name in the `service.name` resource attribute (default: `"mcp-gateway"`) +- **Added**: Section 4.1.3.6 — OpenTelemetry Configuration + - Full field reference table with types, requirements, and descriptions + - Tracing behavior requirements (span attributes, W3C `traceparent` construction, export protocol) + - Failure handling requirements (export failures MUST NOT affect MCP processing) +- **Added**: Compliance test category 10.1.10 — OpenTelemetry Tests (T-OTEL-001 through T-OTEL-010) +- **Added**: OpenTelemetry example configurations (Appendix A.6, A.7) +- **Added**: Normative references for W3C Trace Context and OTLP +- **Updated**: JSON Schema with `opentelemetry` property and `opentelemetryConfig` definition in `gatewayConfig` + ### Version 1.10.0 (Draft) - **Added**: `keepaliveInterval` field to gateway configuration (Section 4.1.3, 4.1.3.5) diff --git a/pkg/workflow/schemas/mcp-gateway-config.schema.json b/pkg/workflow/schemas/mcp-gateway-config.schema.json index ac4d456084e..96cf225cfec 100644 --- a/pkg/workflow/schemas/mcp-gateway-config.schema.json +++ b/pkg/workflow/schemas/mcp-gateway-config.schema.json @@ -247,10 +247,66 @@ "type": "integer", "description": "Keepalive ping interval in seconds for HTTP MCP backends. Sends periodic pings to prevent session expiry during long-running agent tasks. Set to -1 to disable keepalive pings. Unset or 0 uses the gateway default (1500 seconds = 25 minutes).", "minimum": -1 + }, + "opentelemetry": { + "$ref": "#/definitions/opentelemetryConfig", + "description": "Optional OpenTelemetry configuration for emitting distributed tracing spans for MCP calls. When configured, the gateway exports OTLP/HTTP traces to the specified collector endpoint." } }, "required": ["port", "domain", "apiKey"], "additionalProperties": false + }, + "opentelemetryConfig": { + "type": "object", + "description": "OpenTelemetry configuration for the MCP Gateway. When present, the gateway emits distributed tracing spans for each MCP tool invocation and exports them via OTLP/HTTP to the configured collector endpoint. Per MCP Gateway Specification section 4.1.3.6.", + "properties": { + "endpoint": { + "type": "string", + "description": "OTLP/HTTP endpoint URL for the OpenTelemetry collector (e.g., 'https://collector.example.com:4318/v1/traces'). MUST be an HTTPS URL. Supports variable expressions using '${VARIABLE_NAME}' syntax.", + "pattern": "^(https://.+|\\$\\{[A-Z_][A-Z0-9_]*\\})$", + "minLength": 1 + }, + "headers": { + "type": "object", + "description": "Additional HTTP headers sent with every OTLP export request (e.g., for authentication). Values may contain variable expressions using '${VARIABLE_NAME}' syntax.", + "additionalProperties": { + "type": "string" + }, + "default": {} + }, + "traceId": { + "type": "string", + "description": "Parent trace ID for W3C trace context propagation. When set, all gateway spans are attached as children of this trace. MUST be a 32-character lowercase hexadecimal string (128-bit W3C trace ID). Supports variable expressions.", + "oneOf": [ + { + "pattern": "^[0-9a-f]{32}$" + }, + { + "pattern": "^\\$\\{[A-Z_][A-Z0-9_]*\\}$" + } + ] + }, + "spanId": { + "type": "string", + "description": "Parent span ID for W3C trace context propagation. When set together with traceId, this span becomes the direct parent of the gateway root span. MUST be a 16-character lowercase hexadecimal string (64-bit W3C span ID). Ignored when traceId is not set. Supports variable expressions.", + "oneOf": [ + { + "pattern": "^[0-9a-f]{16}$" + }, + { + "pattern": "^\\$\\{[A-Z_][A-Z0-9_]*\\}$" + } + ] + }, + "serviceName": { + "type": "string", + "description": "Logical service name reported in the 'service.name' resource attribute of all emitted spans. Identifies the gateway in the tracing backend. Defaults to 'mcp-gateway' when not specified.", + "minLength": 1, + "default": "mcp-gateway" + } + }, + "required": ["endpoint"], + "additionalProperties": false } }, "examples": [