( request: Request, _env: Env, ctx: ExecutionContext, handle: (tracedRequest: Request) => Promise<Response>, )
| 132 | }; |
| 133 | |
| 134 | const traceCloudMcpRequest = async ( |
| 135 | request: Request, |
| 136 | _env: Env, |
| 137 | ctx: ExecutionContext, |
| 138 | handle: (tracedRequest: Request) => Promise<Response>, |
| 139 | ): Promise<Response> => { |
| 140 | if (!installTracerProvider()) return handle(request); |
| 141 | |
| 142 | const url = new URL(request.url); |
| 143 | const inbound = parseTraceparent(request.headers.get("traceparent"), null); |
| 144 | const parentContext = inbound |
| 145 | ? trace.setSpanContext(context.active(), { |
| 146 | traceId: inbound.traceId, |
| 147 | spanId: inbound.spanId, |
| 148 | traceFlags: inbound.traceFlags, |
| 149 | isRemote: true, |
| 150 | }) |
| 151 | : context.active(); |
| 152 | |
| 153 | return tracer.startActiveSpan( |
| 154 | `http.server ${request.method}`, |
| 155 | { kind: SpanKind.SERVER }, |
| 156 | parentContext, |
| 157 | async (span) => { |
| 158 | span.setAttribute(ATTR_HTTP_REQUEST_METHOD, request.method); |
| 159 | span.setAttribute(ATTR_URL_FULL, request.url); |
| 160 | span.setAttribute(ATTR_URL_PATH, url.pathname); |
| 161 | span.setAttribute(ATTR_URL_SCHEME, url.protocol.replace(/:$/, "")); |
| 162 | // oxlint-disable-next-line executor/no-try-catch-or-throw -- adapter boundary; observe response/error for span status, keep trace export alive after the Agents bridge resolves or rejects |
| 163 | try { |
| 164 | const response = await handle(withTraceparent(request, span.spanContext())); |
| 165 | span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, response.status); |
| 166 | if (response.status >= 500) { |
| 167 | span.setStatus({ code: SpanStatusCode.ERROR, message: `HTTP ${response.status}` }); |
| 168 | } |
| 169 | return response; |
| 170 | } catch (err) { |
| 171 | // oxlint-disable-next-line executor/no-instanceof-error, executor/no-unknown-error-message -- adapter boundary: Cloudflare's fetch callback throws untyped; normalized only for the OTel span record, the original error is rethrown below |
| 172 | const cause = err instanceof Error ? err : String(err); |
| 173 | span.recordException(cause); |
| 174 | // oxlint-disable-next-line executor/no-unknown-error-message -- adapter boundary: same normalization as the recordException line above |
| 175 | const message = typeof cause === "string" ? cause : cause.message; |
| 176 | span.setStatus({ code: SpanStatusCode.ERROR, message }); |
| 177 | // oxlint-disable-next-line executor/no-try-catch-or-throw -- adapter boundary; preserve original error to Cloudflare runtime |
| 178 | throw err; |
| 179 | } finally { |
| 180 | span.end(); |
| 181 | ctx.waitUntil(flushTracerProvider()); |
| 182 | } |
| 183 | }, |
| 184 | ); |
| 185 | }; |
| 186 | |
| 187 | const mcpAgentHandler = makeCloudMcpAgentHandler(); |
| 188 |
no test coverage detected