/** * Langfuse observability for Frihet MCP server. * * Uses direct HTTP POST to the Langfuse ingestion API (no SDK dependency) * so it works identically in Node.js (stdio) and Cloudflare Workers (edge). * * Design: * - Fail-open: any Langfuse error logs a warning and lets the tool proceed. * - Data minimization: only bounded operational facts cross the telemetry * boundary. Tool input/output, arbitrary error text, and user/workspace * identity are never serialized. * - Fire-and-forget: traces are sent via waitUntil (Workers) or unref'd promise * (Node.js) so they never block tool responses. * * Environment variables (both Node.js stdio and Cloudflare Worker): * LANGFUSE_PUBLIC_KEY — pk-lf-... * LANGFUSE_SECRET_KEY — sk-lf-... * LANGFUSE_BASE_URL — https://langfuse.frihet.io (no trailing slash) * * Docs: https://langfuse.com/docs/api/reference/overview */ /** * Langfuse receives a Basic Authorization header, so its authority is exact. * The current product contract documents one hosted origin; arbitrary Frihet * subdomains and self-hosted overrides are intentionally not trusted here. */ export declare function normalizeLangfuseBaseUrl(value: string): string; /** * Called once from FrihetMCP.init() in the Worker to inject env vars. * Not needed in Node.js stdio mode (reads from process.env directly). */ export declare function initLangfuse(config: { publicKey?: string; secretKey?: string; baseUrl?: string; }): void; interface LangfuseSpanBody { id: string; traceId: string; name: string; startTime: string; endTime: string; metadata?: Record; level?: "DEFAULT" | "DEBUG" | "WARNING" | "ERROR"; statusMessage?: string; } interface LangfuseTraceBody { id: string; name: string; timestamp: string; metadata?: Record; tags?: string[]; } interface IngestionBatch { batch: Array<{ type: string; id: string; timestamp: string; body: LangfuseTraceBody | LangfuseSpanBody; }>; } interface StubMarker { stub: true; } /** * Inspect a resolved tool output for stub / not-implemented / unavailable * markers and return them if present, else null. * * A tool that catches its own 404 (or is a forward-compat stub) RETURNS a * fabricated body instead of throwing — so the try/catch in traceMCPTool never * runs and the call looks successful. These markers are the structural signal * that the "success" is fabricated: * - `_stub: true` → 404 → fallback stub body * - `_notImplemented: true` → forward-compat stub (endpoint not yet shipped) * - `_unavailable: true` → honest "backend endpoint not yet available" * - `_plannedEndpoint` → present on any of the above * * Checks both the top-level MCP tool result and its `structuredContent`, since * tools place the markers inside `structuredContent`. */ export declare function inspectStubMarker(output: unknown): StubMarker | null; interface TraceContext { /** MCP protocol version */ mcpVersion?: string; } /** * Set session-level protocol context. Client identity is intentionally absent. * Call once from server init; applies to all subsequent traces. */ export declare function setTraceContext(ctx: TraceContext): void; interface TracePayloadParams { toolName: string; isError: boolean; errorClass?: string; errorCode?: string; statusCode?: number; startTime: Date; endTime: Date; traceId: string; spanId: string; mcpVersion?: string; /** Fabricated-stub marker, or null on a genuine result. */ stub: StubMarker | null; } /** * Builds the Langfuse trace+span ingestion batch for a single tool call. * * CRITICAL (Trust): this builder is an allowlist. It has no input/output or * identity fields and ignores any extra runtime properties a caller supplies. * Exported so tests can assert the exact operational shape. */ export declare function buildTracePayload(p: TracePayloadParams): IngestionBatch; /** * Wraps a tool handler fn and sends a Langfuse trace+span for the call. * * Fail-open: if Langfuse is not configured or errors, fn runs unchanged. * Fire-and-forget: Langfuse POST never blocks the tool response. * * @param toolName Tool name (e.g. "create_invoice") * @param input Raw tool input args * @param fn Async tool handler to wrap * @returns Result of fn */ export declare function traceMCPTool(toolName: string, _input: unknown, fn: () => Promise): Promise; export {}; //# sourceMappingURL=observability.d.ts.map