Skip to content

Conversation

@frontegg-david
Copy link
Contributor

@frontegg-david frontegg-david commented Dec 14, 2025

Summary by CodeRabbit

  • New Features

    • Introduces a unified request context (FrontMcpContext) with tracing, context-aware fetch, logging, timing, and a specific error when no context is available.
    • Provider model consolidated to CONTEXT scope (replacing SESSION/REQUEST); session cache, per-context lifecycle, and explicit cleanup added.
    • OpenAPI/adapters updated to accept ctx for per-request auth/headers/body mapping.
  • Documentation

    • Expanded guides, examples, and migration notes for request context, provider scope changes, and adapter auth updates.
  • Tests

    • New unit tests covering SessionKey, context storage, and provider scope behaviors.

✏️ Tip: You can customize this high-level summary in your review settings.

@frontegg-david frontegg-david changed the title feat: Add support for request context management and session key vali… feat: Add support for request context management and session key validation Dec 14, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 14, 2025

Walkthrough

Replaces the SessionProvider model with a unified FrontMcpContext backed by AsyncLocalStorage; removes the old SessionProvider export; adds FrontMcpContext, storage/provider tokens, trace-context utilities, session-key validation, session/context-scoped provider caching and locks, flow/adapter integrations, docs, and tests.

Changes

Cohort / File(s) Summary
Context core & tracing
libs/sdk/src/context/frontmcp-context.ts, libs/sdk/src/context/frontmcp-context-storage.ts, libs/sdk/src/context/frontmcp-context.provider.ts, libs/sdk/src/context/trace-context.ts, libs/sdk/src/context/index.ts
Add FrontMcpContext class and types, AsyncLocalStorage-based FrontMcpContextStorage (run/runFromHeaders/runWithContext/getStore/updateAuthInfo), DI token/provider (FRONTMCP_CONTEXT), trace context parsing/generation, metadata extraction, and consolidated exports/aliases.
RequestContext (legacy-compatible)
libs/sdk/src/context/request-context.ts, libs/sdk/src/context/request-context-storage.ts, libs/sdk/src/context/request-context.provider.ts
Add RequestContext types & storage/provider as backward-compatible aliases with run/runFromHeaders/runWithContext/getStore/updateAuthInfo helpers.
SessionKey & tests
libs/sdk/src/context/session-key.provider.ts, libs/sdk/src/context/__tests__/session-key.test.ts
Add SessionKey class with validation, constants and unit tests covering validation and edge cases.
Remove old SessionProvider & re-exports
libs/sdk/src/common/providers/session.provider.ts, libs/sdk/src/common/index.ts
Remove deprecated SessionProvider implementation and its re-export from the common index.
Execution & Flow interfaces
libs/sdk/src/common/interfaces/execution-context.interface.ts, libs/sdk/src/common/interfaces/flow.interface.ts
Add FrontMcpContext accessors (context getter, tryGetContext, getAuthInfo, contextLogger) and context-aware fetch delegation to ExecutionContextBase and FlowBase.
Provider registry: context/session cache & locks
libs/sdk/src/provider/provider.registry.ts, libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
Implement context/session-scoped provider stores, build locks, LRU/TTL eviction, cleanup APIs, normalization of SESSION/REQUEST→CONTEXT, buildViews/getScoped, lifecycle methods, and extensive tests (concurrency, isolation, compatibility).
Flow instance & HTTP integration
libs/sdk/src/flows/flow.instance.ts, libs/sdk/src/scope/flows/http.request.flow.ts, libs/sdk/src/flows/flow.registry.ts
Wrap flow execution in FrontMcpContext storage, derive sessionId/scope/requestId from headers or generate anon IDs, merge context-provided provider views into flow deps, and propagate context/auth/session metadata through HTTP flow and registry.
Scope providers update
libs/sdk/src/scope/scope.instance.ts, libs/sdk/src/front-mcp/front-mcp.providers.ts
Replace SessionProvider registration with RequestContextStorage (GLOBAL) and register FrontMcpContextProvider in default/global providers.
Notification service cleanup
libs/sdk/src/notification/notification.service.ts
Invoke scope.providers.cleanupSession(sessionId) during terminateSession() to clear per-session/context provider caches.
Adapters & OpenAPI changes
libs/adapters/src/openapi/openapi.tool.ts, libs/adapters/src/openapi/openapi.security.ts, libs/adapters/src/openapi/openapi.types.ts, libs/adapters/src/openapi/__tests__/*, apps/demo/src/apps/expenses/providers/session-redis.provider.ts
Migrate mapper and security resolver signatures to accept ctx: FrontMcpContext (use ctx.authInfo, ctx.sessionId, ctx.traceContext), update tool code, types, tests, and demo provider constructor accordingly.
SDK public API & errors
libs/sdk/src/index.ts, libs/sdk/src/errors/mcp.error.ts
Re-export new context/tracing APIs from SDK index and add RequestContextNotAvailableError.
Docs, examples & navigation
docs/draft/docs/extensibility/request-context.mdx, docs/draft/docs/extensibility/providers.mdx, docs/draft/docs/adapters/openapi-adapter.mdx, docs/draft/docs/servers/tools.mdx, docs/draft/docs.json, docs/draft/blog/*.mdx, libs/sdk/src/tool/README.md
Add comprehensive RequestContext and context-scoped provider documentation, migrate examples to ctx, deprecate SESSION/REQUEST scopes in docs, and update navigation.
Provider metadata & types docs
libs/sdk/src/provider/provider.types.ts, libs/sdk/src/common/metadata/provider.metadata.ts
Add documentation and deprecation notes for ProviderScope members and provider views; no runtime signature changes.
Build config
libs/ui/project.json
Add externals entries to esbuildOptions for native/large packages.
Minor/test scaffolding
libs/adapters/src/openapi/__tests__/openapi-security-unit.spec.ts, apps/demo/src/apps/expenses/providers/session-redis.provider.ts
Update tests and demo provider to use/match FrontMcpContext signatures.
sequenceDiagram
    actor Client
    participant HTTP as HTTP Router
    participant CtxStore as FrontMcpContextStorage
    participant FlowReg as FlowRegistry
    participant ProvReg as ProviderRegistry
    participant FlowInst as FlowInstance / FlowClass

    Client->>HTTP: request (headers, body)
    HTTP->>CtxStore: runFromHeaders(headers, args, fn)
    CtxStore->>CtxStore: parseTraceContext(), extractMetadata()
    CtxStore->>HTTP: execute handler inside AsyncLocalStorage (FrontMcpContext)
    HTTP->>FlowReg: runFlow(..., ctx)
    FlowReg->>ProvReg: buildViews(sessionKey, contextProviders)
    ProvReg->>ProvReg: acquireSessionLock / build context providers
    ProvReg-->>FlowReg: ProviderViews (global + context)
    FlowReg->>FlowInst: construct with merged deps (includes FRONTMCP_CONTEXT)
    FlowInst->>CtxStore: access FrontMcpContext (getAuthInfo, fetch, marks, storage)
    FlowInst-->>Client: response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Areas to focus on:
    • provider.registry.ts: lock correctness, eviction, concurrency, and memory/resource cleanup
    • frontmcp-context-storage.ts / request-context-storage.ts: AsyncLocalStorage boundaries, header parsing, and updateAuthInfo semantics
    • flow.instance.ts / flow.registry.ts: merging context-provided deps, fallback paths when context absent
    • Removal of SessionProvider and re-exports: ensure backward-compatibility aliases and deprecations are correct
    • OpenAPI adapter changes: verify mapper/resolver signatures, types, and tests reflect the ctx transition

Possibly related PRs

Poem

🐇 In tunnels of async light I hop,

I carry session keys that never drop.
Traces hum and contexts sing,
Providers wake at context's ring.
A rabbit cheers — new flows take wing!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: introducing FrontMcpContext for unified request context management and SessionKey for validated session key handling, replacing the previous session-scoped provider model.
Docstring Coverage ✅ Passed Docstring coverage is 88.89% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add-support-for-session-context

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c0af634 and d2ed3b2.

📒 Files selected for processing (2)
  • libs/sdk/src/common/metadata/provider.metadata.ts (1 hunks)
  • libs/sdk/src/context/frontmcp-context.provider.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • libs/sdk/src/context/frontmcp-context.provider.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Enable strict TypeScript mode with no any types without strong justification - use unknown instead for generic type defaults
Avoid non-null assertions (!) - use proper error handling and throw specific errors instead
Use specific error classes with MCP error codes instead of generic errors
Use type parameters with constraints instead of unconstrained generics, and prefer unknown over any for generic type defaults
Follow the preset pattern for hierarchical configurations across the codebase

Files:

  • libs/sdk/src/common/metadata/provider.metadata.ts
libs/{sdk,adapters,plugins,cli}/src/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

libs/{sdk,adapters,plugins,cli}/src/**/*.ts: Return strictly typed MCP protocol responses (GetPromptResult, ReadResourceResult, etc.) instead of unknown for execute() and read() methods
Validate URIs per RFC 3986 at metadata level using Zod validation with custom refinements
Use getCapabilities() for dynamic capability exposure instead of hardcoding capabilities in adapters
Use changeScope instead of scope for change event properties to avoid confusion with the Scope class
Validate hooks match their entry type and fail fast with InvalidHookFlowError for unsupported flows
Don't mutate rawInput in flows - use state.set() for managing flow state instead

Files:

  • libs/sdk/src/common/metadata/provider.metadata.ts
libs/**

⚙️ CodeRabbit configuration file

libs/**: Contains publishable SDK libraries. Review for API correctness, breaking changes, and consistency with docs. When public APIs change, ensure there is a matching docs/draft/docs/** update (not direct edits under docs/docs/**).

Files:

  • libs/sdk/src/common/metadata/provider.metadata.ts
🧠 Learnings (2)
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Use `changeScope` instead of `scope` for change event properties to avoid confusion with the Scope class

Applied to files:

  • libs/sdk/src/common/metadata/provider.metadata.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Use FrontMCP's TypeScript-first schema validation framework philosophy - all types should align with MCP protocol definitions

Applied to files:

  • libs/sdk/src/common/metadata/provider.metadata.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (2)
libs/sdk/src/common/metadata/provider.metadata.ts (2)

14-35: Enum docs and deprecation notes for ProviderScope look consistent

The added documentation around GLOBAL, CONTEXT, and the deprecation of SESSION/REQUEST is clear and matches the new context-based model. Calling out that the deprecated values map to CONTEXT internally should make migration much easier, without changing the runtime surface.


37-44: frontMcpProviderMetadataSchema remains aligned with ProviderMetadata

The reshaped z.object declaration preserves the previous shape (id, name, description, scope) and keeps scope defaulting to ProviderScope.GLOBAL, with .passthrough() maintaining backward compatibility for extra keys. This matches the ProviderMetadata interface and the SDK’s TS-first schema pattern.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
libs/adapters/src/openapi/openapi.tool.ts (1)

108-119: Verify auth data is properly validated before use.

authInfo from ctx.getAuthInfo() is passed directly to both injectTransformedValues and resolveToolSecurity without null checks. While resolveToolSecurity does validate authInfo.token is a string (lines 125-126 in openapi.security.ts), and injectTransformedValues has error handling via safeInject for transform failures, there's no upfront validation that authInfo itself is non-null or that required fields exist. Consider adding a guard at line 104 to ensure authInfo is valid before proceeding, or document the assumption that ctx.getAuthInfo() always returns a valid AuthInfo object.

🧹 Nitpick comments (10)
libs/sdk/src/context/request-context.provider.ts (1)

41-52: Consider removing the as any type assertion.

The factory logic is correct, but the as any assertion at line 52 bypasses TypeScript's type checking. This suggests a potential mismatch with the ProviderFactoryType definition.

If the type assertion is necessary due to framework limitations, consider adding a comment explaining why it's required.

libs/sdk/src/scope/flows/http.request.flow.ts (1)

109-122: Prefer randomUUID() for fallback requestId and avoid Math.random identifiers.
Line 111 fallback can collide under load; use randomUUID() (or a monotonic counter) if ctx is missing.

libs/sdk/src/provider/__tests__/provider-session-scope.test.ts (3)

24-27: Avoid any in tests (strict TS).
Line 25: target: any can be unknown (or abstract new (...args: unknown[]) => unknown) since it’s unused.


241-276: Use Jest fake timers for deterministic timing tests.
Real setTimeout/Date.now() can be flaky under CI contention; switch these to jest.useFakeTimers() + jest.advanceTimersByTime() and (if needed) stub Date.now().

Also applies to: 377-396


345-376: Reduce test iteration count with a configurable cache size for LRU eviction tests.

All three LRU eviction tests (lines 345–376, 397–428, 787–813) use MAX_SIZE = 10000 with 10,000-iteration loops to fill the session cache before triggering eviction. These loops can slow CI unnecessarily. Since ProviderRegistry.MAX_SESSION_CACHE_SIZE is a private constant with no test-only override, consider adding a constructor parameter or test helper to use a smaller cache size (e.g., 10–50 entries) for these tests while keeping production code unchanged.

libs/sdk/src/context/request-context-storage.ts (1)

185-198: extractClientIp() should handle array header values too.
If upstream adapters ever pass string[], you’ll miss client IP. Consider accepting string | string[] and using the first value.

libs/sdk/src/context/request-context.ts (1)

17-28: Normalize RequestMetadata.customHeaders defensively (JS/runtime callers can omit it).
Right now you rely on TS to enforce customHeaders, but at runtime args.metadata can still be missing it, yielding undefined downstream.

   constructor(args: RequestContextArgs) {
@@
-    this.metadata = args.metadata ?? { customHeaders: {} };
+    const md = args.metadata;
+    this.metadata = {
+      ...md,
+      customHeaders: md?.customHeaders ?? {},
+    };

Also applies to: 94-105

libs/sdk/src/provider/provider.registry.ts (3)

41-65: Cache sizing/TTL constants should be configurable (or at least justified) for SDK consumers.
MAX_SESSION_CACHE_SIZE = 10000 + 1h TTL can be large depending on provider weight and deployment style.


933-934: New request/session build paths introduce additional any—prefer unknown (or tighten generics) per TS guidelines.
In particular: sessionStore as Map<Token, any> and const args: any[] = [] weaken type guarantees for new code paths.

Also applies to: 969-1023


1034-1075: Resolution order is sensible; consider enriching failure errors with scope + session/request context.
Cannot resolve dependency ... from views can be hard to debug; including the provider scope + whether SESSION/REQUEST stores had it would cut triage time.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e9bb89c and 8a1d3b0.

📒 Files selected for processing (26)
  • apps/demo/src/apps/expenses/providers/session-redis.provider.ts (2 hunks)
  • docs/draft/docs.json (1 hunks)
  • docs/draft/docs/adapters/openapi-adapter.mdx (1 hunks)
  • docs/draft/docs/extensibility/providers.mdx (1 hunks)
  • docs/draft/docs/extensibility/request-context.mdx (1 hunks)
  • docs/draft/docs/servers/tools.mdx (2 hunks)
  • libs/adapters/src/openapi/openapi.tool.ts (4 hunks)
  • libs/sdk/src/common/index.ts (0 hunks)
  • libs/sdk/src/common/interfaces/execution-context.interface.ts (3 hunks)
  • libs/sdk/src/common/interfaces/flow.interface.ts (2 hunks)
  • libs/sdk/src/common/providers/session.provider.ts (0 hunks)
  • libs/sdk/src/context/__tests__/session-key.test.ts (1 hunks)
  • libs/sdk/src/context/index.ts (1 hunks)
  • libs/sdk/src/context/request-context-storage.ts (1 hunks)
  • libs/sdk/src/context/request-context.provider.ts (1 hunks)
  • libs/sdk/src/context/request-context.ts (1 hunks)
  • libs/sdk/src/context/session-key.provider.ts (1 hunks)
  • libs/sdk/src/context/trace-context.ts (1 hunks)
  • libs/sdk/src/flows/flow.instance.ts (4 hunks)
  • libs/sdk/src/index.ts (1 hunks)
  • libs/sdk/src/notification/notification.service.ts (1 hunks)
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts (1 hunks)
  • libs/sdk/src/provider/provider.registry.ts (4 hunks)
  • libs/sdk/src/scope/flows/http.request.flow.ts (3 hunks)
  • libs/sdk/src/scope/scope.instance.ts (2 hunks)
  • libs/ui/project.json (2 hunks)
💤 Files with no reviewable changes (2)
  • libs/sdk/src/common/index.ts
  • libs/sdk/src/common/providers/session.provider.ts
🧰 Additional context used
📓 Path-based instructions (8)
docs/draft/docs/**

⚙️ CodeRabbit configuration file

docs/draft/docs/**: This folder holds the draft/source docs that humans are expected to edit. When authors want to add or change documentation, they should do it here. The Codex workflow uses these drafts, together with the code diff, to generate the latest docs under docs/docs/. As a reviewer: - Encourage contributors to add/update content here instead of docs/docs/. - It is fine to do structural/content feedback here (clarity, examples, etc).

Files:

  • docs/draft/docs/adapters/openapi-adapter.mdx
  • docs/draft/docs/extensibility/providers.mdx
  • docs/draft/docs/extensibility/request-context.mdx
  • docs/draft/docs/servers/tools.mdx
docs/**

⚙️ CodeRabbit configuration file

docs/**: Repository documentation for the SDK, using MDX and hosted by Mintlify. See more specific rules for: - docs/docs/** (latest rendered docs, automation-only) - docs/v/** (archived versions, read-only) - docs/draft/docs/** (human-editable drafts) - docs/blogs/** (blogs, human edited) - docs/docs.json (Mintlify navigation)

Files:

  • docs/draft/docs/adapters/openapi-adapter.mdx
  • docs/draft/docs/extensibility/providers.mdx
  • docs/draft/docs/extensibility/request-context.mdx
  • docs/draft/docs.json
  • docs/draft/docs/servers/tools.mdx
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Enable strict TypeScript mode with no any types without strong justification - use unknown instead for generic type defaults
Avoid non-null assertions (!) - use proper error handling and throw specific errors instead
Use specific error classes with MCP error codes instead of generic errors
Use type parameters with constraints instead of unconstrained generics, and prefer unknown over any for generic type defaults
Follow the preset pattern for hierarchical configurations across the codebase

Files:

  • libs/sdk/src/notification/notification.service.ts
  • libs/sdk/src/context/__tests__/session-key.test.ts
  • libs/sdk/src/context/request-context.provider.ts
  • libs/sdk/src/index.ts
  • libs/sdk/src/common/interfaces/flow.interface.ts
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
  • libs/adapters/src/openapi/openapi.tool.ts
  • libs/sdk/src/context/index.ts
  • libs/sdk/src/context/trace-context.ts
  • libs/sdk/src/context/session-key.provider.ts
  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/context/request-context-storage.ts
  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/context/request-context.ts
  • libs/sdk/src/provider/provider.registry.ts
  • libs/sdk/src/scope/flows/http.request.flow.ts
  • apps/demo/src/apps/expenses/providers/session-redis.provider.ts
  • libs/sdk/src/scope/scope.instance.ts
libs/{sdk,adapters,plugins,cli}/src/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

libs/{sdk,adapters,plugins,cli}/src/**/*.ts: Return strictly typed MCP protocol responses (GetPromptResult, ReadResourceResult, etc.) instead of unknown for execute() and read() methods
Validate URIs per RFC 3986 at metadata level using Zod validation with custom refinements
Use getCapabilities() for dynamic capability exposure instead of hardcoding capabilities in adapters
Use changeScope instead of scope for change event properties to avoid confusion with the Scope class
Validate hooks match their entry type and fail fast with InvalidHookFlowError for unsupported flows
Don't mutate rawInput in flows - use state.set() for managing flow state instead

Files:

  • libs/sdk/src/notification/notification.service.ts
  • libs/sdk/src/context/__tests__/session-key.test.ts
  • libs/sdk/src/context/request-context.provider.ts
  • libs/sdk/src/index.ts
  • libs/sdk/src/common/interfaces/flow.interface.ts
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
  • libs/adapters/src/openapi/openapi.tool.ts
  • libs/sdk/src/context/index.ts
  • libs/sdk/src/context/trace-context.ts
  • libs/sdk/src/context/session-key.provider.ts
  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/context/request-context-storage.ts
  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/context/request-context.ts
  • libs/sdk/src/provider/provider.registry.ts
  • libs/sdk/src/scope/flows/http.request.flow.ts
  • libs/sdk/src/scope/scope.instance.ts
libs/**

⚙️ CodeRabbit configuration file

libs/**: Contains publishable SDK libraries. Review for API correctness, breaking changes, and consistency with docs. When public APIs change, ensure there is a matching docs/draft/docs/** update (not direct edits under docs/docs/**).

Files:

  • libs/sdk/src/notification/notification.service.ts
  • libs/sdk/src/context/__tests__/session-key.test.ts
  • libs/sdk/src/context/request-context.provider.ts
  • libs/sdk/src/index.ts
  • libs/sdk/src/common/interfaces/flow.interface.ts
  • libs/ui/project.json
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
  • libs/adapters/src/openapi/openapi.tool.ts
  • libs/sdk/src/context/index.ts
  • libs/sdk/src/context/trace-context.ts
  • libs/sdk/src/context/session-key.provider.ts
  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/context/request-context-storage.ts
  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/context/request-context.ts
  • libs/sdk/src/provider/provider.registry.ts
  • libs/sdk/src/scope/flows/http.request.flow.ts
  • libs/sdk/src/scope/scope.instance.ts
**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.test.ts: Achieve and maintain 95%+ test coverage across all metrics (statements, branches, functions, lines)
Test all code paths including errors, constructor validation, and error class instanceof checks

Files:

  • libs/sdk/src/context/__tests__/session-key.test.ts
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
libs/*/src/index.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use barrel exports (index.ts) to export all public API surface without legacy exports or aliases

Files:

  • libs/sdk/src/index.ts
apps/demo/**

⚙️ CodeRabbit configuration file

apps/demo/**: apps/demo directory contains a demo application for testing purposes. It can be used as a reference for SDK usage examples.

Files:

  • apps/demo/src/apps/expenses/providers/session-redis.provider.ts
🧠 Learnings (8)
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.test.ts : Test all code paths including errors, constructor validation, and error class `instanceof` checks

Applied to files:

  • libs/sdk/src/context/__tests__/session-key.test.ts
📚 Learning: 2025-11-26T15:23:04.965Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-11-26T15:23:04.965Z
Learning: Applies to libs/ui/src/**/*.test.ts : Test behavior across platform configurations (OpenAI, Claude, Gemini, ngrok) where applicable

Applied to files:

  • libs/sdk/src/context/__tests__/session-key.test.ts
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
📚 Learning: 2025-11-26T15:23:04.965Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-11-26T15:23:04.965Z
Learning: Applies to libs/ui/src/components/**/*.test.ts : Write validation tests covering invalid variant/options, unknown properties, and valid option acceptance

Applied to files:

  • libs/sdk/src/context/__tests__/session-key.test.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/*/src/index.ts : Use barrel exports (index.ts) to export all public API surface without legacy exports or aliases

Applied to files:

  • libs/sdk/src/index.ts
  • libs/sdk/src/context/index.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Validate hooks match their entry type and fail fast with InvalidHookFlowError for unsupported flows

Applied to files:

  • libs/sdk/src/common/interfaces/flow.interface.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Don't mutate rawInput in flows - use state.set() for managing flow state instead

Applied to files:

  • libs/sdk/src/common/interfaces/flow.interface.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Use `changeScope` instead of `scope` for change event properties to avoid confusion with the Scope class

Applied to files:

  • libs/sdk/src/context/index.ts
  • libs/sdk/src/scope/flows/http.request.flow.ts
  • libs/sdk/src/scope/scope.instance.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Create shared base classes for common functionality across context types (ExecutionContextBase provides get(), tryGet(), scope, fail(), mark(), fetch())

Applied to files:

  • libs/sdk/src/common/interfaces/execution-context.interface.ts
🧬 Code graph analysis (10)
libs/sdk/src/notification/notification.service.ts (1)
libs/testing/src/client/mcp-test-client.ts (1)
  • sessionId (206-208)
libs/sdk/src/context/__tests__/session-key.test.ts (1)
libs/sdk/src/context/session-key.provider.ts (1)
  • SessionKey (25-62)
libs/sdk/src/common/interfaces/flow.interface.ts (3)
libs/sdk/src/context/index.ts (2)
  • RequestContext (17-17)
  • RequestContextStorage (20-20)
libs/sdk/src/context/request-context.ts (1)
  • RequestContext (60-258)
libs/sdk/src/index.ts (2)
  • RequestContext (16-16)
  • RequestContextStorage (19-19)
libs/adapters/src/openapi/openapi.tool.ts (4)
libs/sdk/src/common/interfaces/execution-context.interface.ts (1)
  • authInfo (89-91)
libs/sdk/src/context/request-context.ts (1)
  • authInfo (111-113)
libs/adapters/src/openapi/openapi.types.ts (1)
  • InputTransformContext (13-20)
libs/adapters/src/openapi/openapi.security.ts (1)
  • resolveToolSecurity (282-325)
libs/sdk/src/context/session-key.provider.ts (2)
libs/sdk/src/context/index.ts (1)
  • SessionKey (26-26)
libs/sdk/src/index.ts (1)
  • SessionKey (25-25)
libs/sdk/src/common/interfaces/execution-context.interface.ts (4)
libs/sdk/src/context/request-context.ts (2)
  • authInfo (111-113)
  • RequestContext (60-258)
libs/sdk/src/context/index.ts (2)
  • RequestContext (17-17)
  • REQUEST_CONTEXT (23-23)
libs/sdk/src/index.ts (2)
  • RequestContext (16-16)
  • REQUEST_CONTEXT (20-20)
libs/sdk/src/context/request-context.provider.ts (1)
  • REQUEST_CONTEXT (30-30)
libs/sdk/src/provider/provider.registry.ts (2)
libs/sdk/src/common/interfaces/internal/registry.interface.ts (1)
  • ProviderViews (74-81)
libs/sdk/src/context/session-key.provider.ts (1)
  • SessionKey (25-62)
libs/sdk/src/scope/flows/http.request.flow.ts (1)
libs/sdk/src/auth/session/record/session.base.ts (1)
  • user (157-159)
apps/demo/src/apps/expenses/providers/session-redis.provider.ts (3)
libs/sdk/src/context/index.ts (1)
  • SessionKey (26-26)
libs/sdk/src/context/session-key.provider.ts (1)
  • SessionKey (25-62)
libs/sdk/src/index.ts (1)
  • SessionKey (25-25)
libs/sdk/src/scope/scope.instance.ts (3)
libs/sdk/src/context/index.ts (2)
  • RequestContextStorage (20-20)
  • RequestContextProvider (23-23)
libs/sdk/src/index.ts (1)
  • RequestContextStorage (19-19)
libs/sdk/src/context/request-context.provider.ts (1)
  • RequestContextProvider (41-52)
🪛 Biome (2.1.2)
libs/sdk/src/provider/provider.registry.ts

[error] 991-991: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)

🔇 Additional comments (36)
libs/ui/project.json (1)

46-47: Clarify the relationship between external bundling changes and RequestContext feature.

The addition of external packages (onnxruntime-*, esbuild, @huggingface/transformers) to both build targets is unclear in the context of a PR focused on RequestContext and session key validation. These appear to be AI/ML-related dependencies.

Please verify:

  1. Why these external dependencies are needed for the RequestContext feature
  2. Whether these packages are actually imported or used by the UI library code
  3. Whether documentation needs to be updated to reflect these bundling changes and any new consumer requirements

Additionally, marking esbuild as external is unusual since it's typically a dev-only dependency. Please clarify the intent there.

Also applies to: 89-90

docs/draft/docs/adapters/openapi-adapter.mdx (1)

187-191: LGTM! Clear documentation of auth data flow.

The informational block accurately describes that authInfo is sourced from the authenticated request context and that authentication is verified before tool execution. This aligns with the broader request context changes in the PR.

libs/sdk/src/context/__tests__/session-key.test.ts (1)

1-137: LGTM! Comprehensive test coverage for SessionKey validation.

The test suite thoroughly covers:

  • Constructor validation with edge cases (empty, null, undefined, length limits)
  • Valid and invalid character patterns
  • Static validation method
  • Constants verification
  • Edge cases for special characters (colons)

All critical paths are tested, aligning with the 95%+ coverage requirement.

Based on learnings, the test suite follows best practices for error class validation and covers all code paths including constructor validation and error scenarios.

libs/sdk/src/context/trace-context.ts (1)

1-162: LGTM! Solid W3C Trace Context implementation.

The implementation correctly:

  • Parses W3C traceparent headers with proper validation
  • Falls back to custom headers and generation
  • Validates trace IDs (32 hex chars, not all zeros)
  • Validates parent IDs (16 hex chars, not all zeros)
  • Generates trace contexts with proper formatting
  • Creates child span contexts while preserving trace ID

All functions follow the W3C Trace Context specification accurately.

docs/draft/docs.json (1)

112-112: LGTM! Navigation update for new documentation page.

The addition of the request-context documentation page to the Extensibility group is correctly positioned and aligns with the new request context features introduced in this PR.

libs/sdk/src/notification/notification.service.ts (1)

418-421: LGTM! Critical session cleanup to prevent memory leaks.

The addition of scope.providers.cleanupSession(sessionId) ensures that session-scoped providers are properly cleaned up when sessions are terminated. This prevents memory leaks from terminated sessions that would otherwise remain cached indefinitely.

The placement is correct: cleanup occurs after unregistering the server but before tracking the termination, ensuring proper resource management.

libs/adapters/src/openapi/openapi.tool.ts (1)

103-104: LGTM! Unified auth retrieval pattern.

The change to use ctx.getAuthInfo() aligns with the SDK's unified authentication access pattern introduced in this PR. This ensures consistent auth data sourcing across all tool executions.

libs/sdk/src/index.ts (1)

14-26: LGTM! Clean public API exports for request context.

The new export block properly exposes the request context API (RequestContext, tracing utilities, SessionKey) following the barrel export pattern. No legacy exports or aliases are introduced, adhering to coding guidelines.

As per coding guidelines, the barrel exports cleanly expose the public API surface without legacy exports or aliases.

docs/draft/docs/servers/tools.mdx (2)

398-399: LGTM! Clear deprecation notice.

The comment properly marks this.authInfo as deprecated and directs users to prefer this.requestContext.authInfo, aligning with the unified auth access pattern introduced in this PR.


440-484: LGTM! Comprehensive request context documentation.

The new section provides excellent examples of using the request context API, including:

  • Tracing with W3C Trace Context (requestId, traceId, parentId)
  • Authentication access via ctx.authInfo
  • Session identification
  • Performance timing with mark() and elapsed()
  • Request metadata access

The examples are clear, practical, and demonstrate the full capabilities of the request context feature.

libs/sdk/src/scope/scope.instance.ts (2)

18-18: LGTM: Import aligns with new context module.

The import correctly references the new RequestContextStorage and RequestContextProvider from the context module barrel.


273-282: LGTM: Clear migration to global RequestContextStorage.

The comments effectively explain the architectural decision:

  • RequestContextStorage is GLOBAL because it manages AsyncLocalStorage infrastructure
  • RequestContextProvider factory (REQUEST scope) retrieves per-request data from the storage

The scope separation is correct and well-documented.

libs/sdk/src/context/session-key.provider.ts (4)

1-24: LGTM: Clear documentation with security rationale.

The JSDoc effectively explains the DI injection pattern and articulates the security concerns (memory bombs, log injection, cache exhaustion) that validation prevents.


27-27: LGTM: Reasonable max length for session keys.

256 characters is a sensible defensive limit that accommodates typical session ID formats (UUIDs, short JWTs, namespaced IDs) while preventing memory exhaustion attacks.


29-35: LGTM: Restrictive pattern prevents injection attacks.

The regex pattern correctly allows safe characters for session IDs while blocking special characters that could enable log injection or other attacks. Colon support for namespaced IDs (e.g., "anon:uuid") is a good design choice.


44-61: LGTM: Solid validation with clear error messages.

The validation logic is defensive and fails fast at construction time. The static validate() method enables early validation before instantiation, and the constructor correctly delegates to avoid duplication.

docs/draft/docs/extensibility/request-context.mdx (3)

25-101: LGTM: Code examples align with implementation.

The examples correctly demonstrate:

  • this.requestContext getter usage
  • this.get(REQUEST_CONTEXT) alternative
  • Safe access via tryGetRequestContext()
  • REQUEST-scoped factory provider pattern

All examples are consistent with the implementation.


73-111: LGTM: W3C Trace Context documentation is accurate.

The documented headers and format align with W3C Trace Context standards. The example for propagating trace context to downstream services is functional, though the span ID generation from requestId is somewhat ad-hoc (line 98).


224-266: LGTM: API reference is comprehensive and accurate.

The tables correctly document the RequestContext API, including the important note that authInfo is Partial<AuthInfo> because it's progressively populated during the request lifecycle.

apps/demo/src/apps/expenses/providers/session-redis.provider.ts (2)

2-2: LGTM: Clean migration to SessionKey pattern.

The import and constructor signature correctly adopt the new SessionKey class for DI injection in SESSION-scoped providers, aligning with the documented pattern.

Also applies to: 12-12


13-13: LGTM: Session ID access updated correctly.

The migration from sessionProvider.session!.id to sessionKey.value is correct. The normalization logic (trim, whitespace→underscore, colon→underscore) is defensive, though whitespace replacement is redundant since SessionKey.validate() already rejects whitespace.

libs/sdk/src/context/request-context.provider.ts (1)

30-30: LGTM: Global symbol registry prevents token duplication.

Using Symbol.for('frontmcp:REQUEST_CONTEXT') ensures the token is accessible across module boundaries and prevents DI token collisions through namespacing.

docs/draft/docs/extensibility/providers.mdx (3)

76-154: LGTM: Request Context documentation is accurate and complete.

The examples correctly demonstrate both access patterns (this.requestContext and this.get(REQUEST_CONTEXT)), and the API table provides a helpful quick reference with a link to the full guide.


158-258: LGTM: SESSION provider guidance is comprehensive.

The documentation clearly explains:

  • SessionKey injection pattern
  • Practical Redis example
  • Critical multi-pod deployment considerations

The warning about pod-local behavior and guidance for cross-pod data sharing via Redis are essential for production deployments.


213-216: Excellent: Critical multi-pod deployment warning.

This warning prevents a common production pitfall. Clearly distinguishing between pod-local SESSION providers and shared transport state (via Redis) will save developers from debugging distributed state issues.

libs/sdk/src/context/index.ts (1)

1-26: LGTM: Clean barrel exports with helpful documentation.

The exports follow the clean barrel pattern without aliases or legacy exports. The JSDoc header provides a helpful overview of the module's purpose and key exports.

Based on learnings, this aligns with the barrel export guidelines.

libs/sdk/src/common/interfaces/flow.interface.ts (3)

7-8: LGTM: Proper use of type-only import.

Line 7 uses import type for RequestContext (type-only), while line 8 imports RequestContextStorage as a value (needed at runtime). This optimizes tree-shaking.


87-96: LGTM: Fail-fast context access is correct.

The getter correctly retrieves RequestContextStorage from the DI container and calls getStoreOrThrow() to fail fast when context is unavailable. The JSDoc clearly documents the error behavior.


98-109: LGTM: Safe context access for optional scenarios.

The try-catch wrapper correctly handles cases where RequestContext might not be available (initialization, non-HTTP flows). This provides a graceful fallback without disrupting execution.

libs/sdk/src/provider/__tests__/provider-session-scope.test.ts (1)

47-161: Coverage looks strong for buildViews validation + caching behaviors.
Early validation, SESSION caching, and REQUEST non-caching are well covered and aligned with the PR goals.

libs/sdk/src/flows/flow.instance.ts (1)

218-227: Verify SESSION provider precedence over GLOBAL-provided tokens.
The current code (lines 223–226) only adds SESSION providers when !mergedDeps.has(token). Since deps contains GLOBAL bindings, SESSION providers cannot override GLOBAL, resulting in REQUEST > GLOBAL > SESSION precedence. In a standard hierarchical DI system, the expected precedence should be REQUEST > SESSION > GLOBAL. If SESSION scope should override GLOBAL scope, change the condition to unconditionally set SESSION providers.

libs/sdk/src/context/request-context.ts (4)

166-170: Logger prefixing looks good for correlating request/trace quickly.
Slicing IDs keeps log lines readable.


1-6: Public API addition: ensure matching docs are added under docs/draft/docs/** (not docs/docs/**).
This is a new core SDK API and should be documented as part of the release surface.

# Check for corresponding draft docs updates describing RequestContext/RequestContextStorage usage.
fd -a "docs" .
rg -n "RequestContext|REQUEST_CONTEXT|RequestContextStorage" docs -S

Also applies to: 50-59


115-126: The @internal JSDoc comments are already present—verify if stripInternal should be enabled in tsconfig to enforce them.

updateAuthInfo() (line 121) and updateSessionMetadata() (line 151) are already marked with @internal but are exported through the public RequestContext API. If these should truly be internal, enable stripInternal in the TypeScript compiler options to automatically exclude them from generated .d.ts files; otherwise, document them as intentional public methods and remove @internal.

Likely an incorrect or invalid review comment.


33-48: sessionId is appropriately required in RequestContextArgs.

All flow execution paths provide sessionId automatically: either from the mcp-session-id header or generated as anon:{UUID} for anonymous requests. This pattern is intentional (see flow.instance.ts lines 177–178) to prevent session collision in unauthenticated flows. Callers never fabricate values; the system ensures sessionId is always available before RequestContext construction.

libs/sdk/src/provider/provider.registry.ts (1)

1085-1094: getScoped() lookup order matches the documented precedence.
Nice, simple API for callers once they have ProviderViews.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (6)
libs/sdk/src/flows/flow.instance.ts (1)

90-95: Remaining as any cast breaks strict TypeScript guarantees.

Line 93 still uses { request, response, next } as any which was flagged in a previous review. Consider introducing a typed interface for middleware input to maintain type safety.

+// At top of file or in common types
+interface HttpMiddlewareInput {
+  request: ServerRequest;
+  response: unknown; // or specific response type
+  next: () => void;
+}

// In runWithContext call
-            { request, response, next } as any,
+            { request, response, next } as HttpMiddlewareInput,
libs/sdk/src/context/request-context-storage.ts (1)

141-146: Previous review feedback implemented correctly.

The updateAuthInfo method now mutates the existing context in place via current.updateAuthInfo(authInfo), preserving internal state (marks, store, sessionMetadata) as suggested in prior review.

libs/sdk/src/provider/provider.registry.ts (4)

215-223: Background cleanup initialization looks correct with dispose() now available.

The cleanup is correctly started only for scope-level registries (with parentProviders). The dispose() method at lines 812-821 addresses the lifecycle concern from prior review.

Verify that dispose() is called during scope teardown:

#!/bin/bash
# Check if dispose() is called in scope teardown logic
rg -n "\.dispose\(\)|providers\.dispose" libs/sdk/src --type=ts -C 2

700-719: LRU eviction correctly skips locked sessions.

The eviction logic properly protects sessions being actively built. While the cache can temporarily exceed MAX_SESSION_CACHE_SIZE if all sessions are locked (as noted in prior review), this edge case is unlikely in practice and self-corrects once locks release.


873-880: Timer leak fix correctly implemented.

The clearTimeout(timeoutHandle) after Promise.race properly prevents timer leaks when existing.promise wins the race. This addresses the prior review concern.


932-973: Session key validation now uses InvalidInputError via SessionKey.validate().

The prior review concern about using MCP-coded error classes is addressed—SessionKey.validate() (shown in relevant snippets) throws InvalidInputError. The try-finally pattern correctly ensures lock release even on error.

🧹 Nitpick comments (1)
libs/sdk/src/scope/flows/http.request.flow.ts (1)

231-250: Duplicate AuthInfo mapping - consider extracting to a helper.

This mapping (lines 235-246) duplicates the logic in checkAuthorization (lines 178-189). Consider extracting to a shared helper function like buildAuthInfoFromAuthorization(authorization) to ensure consistency and reduce maintenance burden.

// Example helper (could be a private method or utility function)
private buildAuthInfoFromAuthorization(authorization: { token: string; user?: { sub?: string; exp?: number }; session?: { id?: string; payload?: unknown } }): Partial<AuthInfo> {
  return {
    token: authorization.token,
    clientId: authorization.user?.sub,
    scopes: [],
    expiresAt: authorization.user?.exp ? authorization.user.exp * 1000 : undefined,
    extra: {
      user: authorization.user,
      sessionId: authorization.session?.id,
      sessionPayload: authorization.session?.payload,
    },
  };
}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a1d3b0 and 527016a.

📒 Files selected for processing (8)
  • libs/sdk/src/common/interfaces/execution-context.interface.ts (3 hunks)
  • libs/sdk/src/context/request-context-storage.ts (1 hunks)
  • libs/sdk/src/context/request-context.ts (1 hunks)
  • libs/sdk/src/context/session-key.provider.ts (1 hunks)
  • libs/sdk/src/errors/mcp.error.ts (1 hunks)
  • libs/sdk/src/flows/flow.instance.ts (4 hunks)
  • libs/sdk/src/provider/provider.registry.ts (4 hunks)
  • libs/sdk/src/scope/flows/http.request.flow.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Enable strict TypeScript mode with no any types without strong justification - use unknown instead for generic type defaults
Avoid non-null assertions (!) - use proper error handling and throw specific errors instead
Use specific error classes with MCP error codes instead of generic errors
Use type parameters with constraints instead of unconstrained generics, and prefer unknown over any for generic type defaults
Follow the preset pattern for hierarchical configurations across the codebase

Files:

  • libs/sdk/src/errors/mcp.error.ts
  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/context/session-key.provider.ts
  • libs/sdk/src/scope/flows/http.request.flow.ts
  • libs/sdk/src/context/request-context.ts
  • libs/sdk/src/provider/provider.registry.ts
  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/context/request-context-storage.ts
libs/{sdk,adapters,plugins,cli}/src/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

libs/{sdk,adapters,plugins,cli}/src/**/*.ts: Return strictly typed MCP protocol responses (GetPromptResult, ReadResourceResult, etc.) instead of unknown for execute() and read() methods
Validate URIs per RFC 3986 at metadata level using Zod validation with custom refinements
Use getCapabilities() for dynamic capability exposure instead of hardcoding capabilities in adapters
Use changeScope instead of scope for change event properties to avoid confusion with the Scope class
Validate hooks match their entry type and fail fast with InvalidHookFlowError for unsupported flows
Don't mutate rawInput in flows - use state.set() for managing flow state instead

Files:

  • libs/sdk/src/errors/mcp.error.ts
  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/context/session-key.provider.ts
  • libs/sdk/src/scope/flows/http.request.flow.ts
  • libs/sdk/src/context/request-context.ts
  • libs/sdk/src/provider/provider.registry.ts
  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/context/request-context-storage.ts
libs/**

⚙️ CodeRabbit configuration file

libs/**: Contains publishable SDK libraries. Review for API correctness, breaking changes, and consistency with docs. When public APIs change, ensure there is a matching docs/draft/docs/** update (not direct edits under docs/docs/**).

Files:

  • libs/sdk/src/errors/mcp.error.ts
  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/context/session-key.provider.ts
  • libs/sdk/src/scope/flows/http.request.flow.ts
  • libs/sdk/src/context/request-context.ts
  • libs/sdk/src/provider/provider.registry.ts
  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/context/request-context-storage.ts
🧠 Learnings (10)
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Use specific error classes with MCP error codes instead of generic errors

Applied to files:

  • libs/sdk/src/errors/mcp.error.ts
  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/provider/provider.registry.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Create shared base classes for common functionality across context types (ExecutionContextBase provides get(), tryGet(), scope, fail(), mark(), fetch())

Applied to files:

  • libs/sdk/src/common/interfaces/execution-context.interface.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Return strictly typed MCP protocol responses (GetPromptResult, ReadResourceResult, etc.) instead of `unknown` for `execute()` and `read()` methods

Applied to files:

  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/provider/provider.registry.ts
  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Avoid non-null assertions (`!`) - use proper error handling and throw specific errors instead

Applied to files:

  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-11-05T15:00:47.800Z
Learnt from: frontegg-david
Repo: agentfront/frontmcp PR: 11
File: libs/core/src/auth/jwks/jwks.service.ts:62-0
Timestamp: 2025-11-05T15:00:47.800Z
Learning: In the FrontMCP codebase (libs/core/src/auth/jwks/jwks.service.ts), the verifyGatewayToken method intentionally skips signature verification when running in development-only no-auth mode, using decodeJwtPayloadSafe instead of jwtVerify. This is a deliberate design for local development convenience and should not be flagged as a security issue when the PR or code context indicates development/no-auth mode.

Applied to files:

  • libs/sdk/src/scope/flows/http.request.flow.ts
  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Use FrontMCP's TypeScript-first schema validation framework philosophy - all types should align with MCP protocol definitions

Applied to files:

  • libs/sdk/src/provider/provider.registry.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Don't mutate rawInput in flows - use state.set() for managing flow state instead

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Enable strict TypeScript mode with no `any` types without strong justification - use `unknown` instead for generic type defaults

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Use type parameters with constraints instead of unconstrained generics, and prefer `unknown` over `any` for generic type defaults

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Validate hooks match their entry type and fail fast with InvalidHookFlowError for unsupported flows

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
🧬 Code graph analysis (4)
libs/sdk/src/errors/mcp.error.ts (1)
libs/sdk/src/errors/index.ts (1)
  • InternalMcpError (5-5)
libs/sdk/src/context/session-key.provider.ts (3)
libs/sdk/src/context/index.ts (1)
  • SessionKey (26-26)
libs/sdk/src/index.ts (1)
  • SessionKey (25-25)
libs/sdk/src/errors/mcp.error.ts (1)
  • InvalidInputError (223-240)
libs/sdk/src/scope/flows/http.request.flow.ts (2)
libs/testing/src/client/mcp-test-client.ts (2)
  • request (818-867)
  • session (210-226)
libs/sdk/src/auth/session/record/session.base.ts (1)
  • user (157-159)
libs/sdk/src/provider/provider.registry.ts (3)
libs/sdk/src/common/interfaces/internal/registry.interface.ts (1)
  • ProviderViews (74-81)
libs/sdk/src/context/session-key.provider.ts (1)
  • SessionKey (27-64)
libs/sdk/src/context/index.ts (1)
  • SessionKey (26-26)
🪛 Biome (2.1.2)
libs/sdk/src/provider/provider.registry.ts

[error] 1020-1020: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (29)
libs/sdk/src/context/session-key.provider.ts (2)

46-58: LGTM - Clean validation implementation with specific error class.

The validation logic is well-structured with clear security rationale. Minor note: the value.length === 0 check on line 47 is technically redundant since !value already covers empty strings, but keeping it explicit improves readability.


27-64: Well-designed value object with appropriate security constraints.

Good use of InvalidInputError per coding guidelines. The static validate() method enables early validation before cache operations, and the constructor ensures all instances are valid.

libs/sdk/src/scope/flows/http.request.flow.ts (2)

110-124: Good use of cryptographic randomUUID for fallback request IDs.

Using randomUUID() instead of Math.random() prevents collision risks under load. The sessionId fallback chain is clear, with 'no-session' explicitly documented as a logging fallback only.


170-191: AuthInfo mapping correctly converts JWT exp to milliseconds.

The expiresAt: user.exp ? user.exp * 1000 : undefined conversion (line 183) aligns with the SDK's millisecond-based comparisons. The extra fields provide useful context for downstream consumers.

libs/sdk/src/errors/mcp.error.ts (1)

361-371: LGTM - Well-structured specific error class for missing request context.

The RequestContextNotAvailableError follows the established error pattern, uses a specific MCP error code (REQUEST_CONTEXT_NOT_AVAILABLE), and provides an actionable default message. This is the correct approach per coding guidelines.

libs/sdk/src/common/interfaces/execution-context.interface.ts (3)

53-68: Good implementation using the typed MCP error.

The requestContext getter now throws RequestContextNotAvailableError instead of a generic Error, addressing the previous review comment. The implementation correctly catches any provider resolution failure and throws the specific error.


92-107: Progressive auth info pattern with proper fallback.

Returning Partial<AuthInfo> correctly reflects that auth info is populated progressively during the request lifecycle. The preference for requestContext.authInfo with fallback to _authInfo provides backward compatibility.


70-81: Safe fallback pattern for optional context access.

The tryGetRequestContext() method provides a non-throwing alternative for code paths where context may not be available (e.g., during initialization). This is a good defensive pattern.

libs/sdk/src/flows/flow.instance.ts (2)

174-195: Session ID derivation correctly handles empty strings.

The implementation properly trims and checks for non-empty strings before using the header value, generating anon:${randomUUID()} for anonymous sessions. The authInfo: {} is correctly typed as Partial<AuthInfo> since it's progressively populated.


201-231: Appropriate error for missing session context.

The RequestContextNotAvailableError with a specific message (lines 211-213) correctly indicates a bug in context propagation rather than a user error. The view merging logic (lines 223-231) correctly prioritizes request-scoped providers.

libs/sdk/src/context/request-context.ts (7)

1-13: LGTM - Clean module setup with proper imports.

Good use of createHash for the session ID hashing fix from prior review feedback. The imports are minimal and appropriate.


14-48: Well-structured interfaces with good documentation.

The type definitions are clean with appropriate optionality. The Partial<AuthInfo> correctly models the progressive population pattern.


94-111: Good defensive initialization with proper defaults.

The defensive normalization of customHeaders (lines 101-107) is a smart safeguard against runtime type issues. The initial timing mark setup is clean.


129-132: Correct merge semantics for progressive auth info updates.

The spread-based merge preserves existing fields while allowing updates. This correctly supports the progressive population pattern documented in the interface.


194-198: Clean timing API with sensible fallbacks.

The fallback to timestamp for missing from marks and Date.now() for missing to marks provides ergonomic defaults without throwing on missing marks.


225-227: Type assertion in get<T> is acceptable for this pattern.

While the generic is unconstrained, this is a standard pattern for typed key-value stores where the caller knows the stored type. The as T | undefined cast correctly preserves the undefined case.


257-268: Session ID hashing correctly implemented.

The SHA-256 hash with 12-character truncation provides sufficient entropy for log correlation (48 bits) while preventing accidental exposure of user-identifying session identifiers. Good implementation of prior review feedback.

libs/sdk/src/context/request-context-storage.ts (3)

1-34: Good module structure with properly scoped AsyncLocalStorage.

The module-level storage instance with DI-only access pattern is correct. The @Provider decorator with ProviderScope.GLOBAL correctly scopes the storage manager.


56-98: Clean implementation of context propagation methods.

The three run methods correctly handle both sync and async callbacks. runFromHeaders properly combines header-derived trace context with caller-provided args.


174-194: Good header parsing with proper handling of array values.

The extractClientIp correctly handles comma-separated x-forwarded-for lists and array header values from various adapters. Note that this IP is for observability purposes—not for authorization decisions—so header spoofing isn't a security concern here.

libs/sdk/src/provider/provider.registry.ts (9)

41-65: Well-designed session cache infrastructure with appropriate constants.

The static configuration constants (MAX_SESSION_CACHE_SIZE, SESSION_CACHE_TTL_MS, SESSION_CLEANUP_INTERVAL_MS, SESSION_LOCK_TIMEOUT_MS) are sensible defaults. The generation counter for lock versioning is a good approach to prevent zombie lock releases.


727-762: Session cleanup methods correctly handle lock resolution.

Both methods properly resolve lock promises before deletion, preventing hung waiters. The pattern of resolving before clearing is correct for graceful cleanup.


768-787: Good interval lifecycle management with process exit handling.

The unref() call ensures the cleanup interval doesn't prevent graceful process shutdown—important for serverless environments. The guard against double-start is correct.


812-821: Comprehensive dispose method addresses lifecycle concerns.

The dispose() method properly cleans up all resources: stops the cleanup interval, clears session stores, and resolves all pending locks. This addresses the lifecycle hook requirement from prior review.


885-889: Good overflow protection for lock generation counter.

While reaching MAX_SAFE_INTEGER is practically impossible at normal operation rates, this defensive check is good practice for long-running systems.


998-1058: Request-scoped provider building follows existing patterns.

The method correctly builds providers with access to session and global views for dependency resolution. The static analysis hint about React hooks at line 1020 is a false positive—this is provider registry code, not React component code.


1063-1104: Correct dependency resolution order across provider views.

The resolution priority (request → session → global → instances → build) correctly implements the scoped provider model. Parent hierarchy lookup for global providers is properly handled.


1114-1123: Clean synchronous API for scoped provider retrieval.

The getScoped<T> method provides a type-safe way to retrieve providers from views with the correct resolution order. The fallback to instances handles global providers not explicitly in the views.


25-25: SessionKey integration enables session validation and injection.

The import enables both early validation in buildViews and injection of SessionKey into session stores for SESSION-scoped provider access.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
libs/adapters/src/openapi/openapi.tool.ts (1)

102-202: FrontMcpContext wiring is good, but option callback signatures become breaking

Routing everything through toolCtx.context and passing ctx into InputTransformContext, resolveToolSecurity, headersMapper, and bodyMapper aligns well with the new FrontMcpContext model and gives mappers access to richer state (trace, session, metadata, etc.).

However, this also changes the runtime shape of the first argument passed to user-supplied callbacks:

  • Previously: headersMapper(authInfo, headers) / bodyMapper(authInfo, body) and transform ctx carrying authInfo.
  • Now: headersMapper(ctx, headers) / bodyMapper(ctx, body) and transform ctx carrying a FrontMcpContext.

Existing consumers (especially plain JS) that treat the first parameter as authInfo (e.g. authInfo.token) will now receive a different object and may fail at runtime, even if their TypeScript types are updated.

Consider one of:

  • Keeping callbacks backward-compatible by passing both, e.g. headersMapper(ctx, headers) but with ctx exposing authInfo and clearly documenting the change, and bumping a major version for the adapter; or
  • Introducing new callbacks (e.g. contextHeadersMapper) and deprecating the old authInfo-based ones over time instead of hard-switching semantics.

Also, in a future pass you may want to evaluate whether using ctx.fetch here (with explicit opt-out for security headers to avoid conflicts with OpenAPI mapping) would improve trace propagation, but that’s optional and can be deferred.

libs/adapters/src/openapi/openapi.types.ts (1)

527-531: Documentation example uses inconsistent parameter name.

The example at line 528 still shows (authInfo) as the parameter name, but the updated signature at line 475 uses (ctx: FrontMcpContext). This inconsistency could confuse developers.

   *   authProviderMapper: {
-  *     'GitHubAuth': (authInfo) => authInfo.user?.githubToken,
+  *     'GitHubAuth': (ctx) => ctx.authInfo.user?.githubToken,
   *   },
docs/draft/docs/adapters/openapi-adapter.mdx (2)

662-688: Multi-Tenant SaaS example uses outdated API signature.

This example still uses (authInfo, headers) and (authInfo, body) signatures, but the API has changed to (ctx, headers) and (ctx, body). This will cause TypeScript errors for users copying this example.

-     headersMapper: (authInfo, headers) => {
+     headersMapper: (ctx, headers) => {
+       const authInfo = ctx.authInfo;
        // Add tenant ID to all requests
        if (authInfo.user?.tenantId) {
          headers.set('x-tenant-id', authInfo.user.tenantId);
        }

        // Add user authorization
        if (authInfo.token) {
          headers.set('authorization', `Bearer ${authInfo.token}`);
        }

        return headers;
      },
-     bodyMapper: (authInfo, body) => {
+     bodyMapper: (ctx, body) => {
+       const authInfo = ctx.authInfo;
        // Add user context to all mutations
        return {
          ...body,
          tenantId: authInfo.user?.tenantId,
          userId: authInfo.user?.id,
          timestamp: new Date().toISOString(),
        };
      },

704-715: Expense Management example uses outdated API signature.

Same issue as the Multi-Tenant example - uses (authInfo, headers) instead of (ctx, headers).

-     headersMapper: (authInfo, headers) => {
-       const token = authInfo.token;
+     headersMapper: (ctx, headers) => {
+       const token = ctx.authInfo.token;
        if (token) {
          headers.set('authorization', `Bearer ${token}`);
        }
        return headers;
      },
♻️ Duplicate comments (3)
libs/sdk/src/flows/flow.instance.ts (2)

90-95: as any cast still present for middleware flow input.

This was flagged in a previous review. Replace { request, response, next } as any with a properly typed interface (e.g., HttpMiddlewareInput) or use unknown with runtime validation to maintain strict TypeScript guarantees.


221-225: Add a comment justifying the type cast safety.

Per previous review feedback, add a brief comment explaining that instance as Type is safe because buildViews() guarantees properly constructed provider instances:

     // Merge context-scoped providers into deps for resolution by FlowClass
     const mergedDeps = new Map(deps);
+    // Type cast is safe: buildViews() returns instances constructed by ProviderRegistry,
+    // which ensures all context-scoped providers are valid provider instances.
     for (const [token, instance] of views.context) {
       mergedDeps.set(token, instance as Type);
     }
libs/sdk/src/provider/provider.registry.ts (1)

719-738: LRU eviction can temporarily exceed max cache size when all sessions are locked.

If every cached session has an active lock, evictOldestSession() evicts nothing and the cache grows beyond MAX_SESSION_CACHE_SIZE. Consider a fallback such as queuing the new session creation until a lock clears, or logging a warning when this edge case occurs.

🧹 Nitpick comments (6)
libs/sdk/src/common/interfaces/execution-context.interface.ts (1)

61-67: Clarify comment: throws error instead of falling back.

The comment at line 65 says "Fallback" but the code immediately throws RequestContextNotAvailableError. This is misleading—the code doesn't fall back; it throws a specific error when context is unavailable.

Apply this diff to clarify the comment:

   } catch {
-    // Fallback: context not available, likely called during initialization
+    // Context not available (likely called during initialization or outside request scope)
     throw new RequestContextNotAvailableError();
libs/sdk/src/provider/provider.types.ts (1)

3-30: ProviderViews docs clearly express the new CONTEXT model

The added documentation cleanly explains global vs context and marks session/request as deprecated aliases. The note that both alias context is useful; just ensure the implementation always passes the same Map instance for context, session, and request so the aliasing guarantee in the comments remains true.

libs/sdk/src/flows/flow.instance.ts (1)

246-246: Consider typing context instead of any.

context: any bypasses TypeScript checks for all subsequent usages. Per coding guidelines favoring strict TypeScript, consider using FlowCtxOf<Name> or a more specific type to catch type errors at compile time.

libs/sdk/src/scope/flows/http.request.flow.ts (1)

169-191: Context auth update is duplicated in router stage.

The ctx.updateAuthInfo() call here (Lines 178-189) is nearly identical to the one in router (Lines 235-246). If checkAuthorization always runs before router (per the plan), the second update may be redundant. Consider:

  1. Removing the duplicate in router if auth info doesn't change, or
  2. Extracting a helper method to avoid code duplication.
private buildAuthInfo(authorization: { token: string; user: { sub?: string; exp?: number }; session?: { id?: string; payload?: unknown } }) {
  return {
    token: authorization.token,
    clientId: authorization.user?.sub,
    scopes: [],
    expiresAt: authorization.user?.exp ? authorization.user.exp * 1000 : undefined,
    extra: {
      user: authorization.user,
      sessionId: authorization.session?.id,
      sessionPayload: authorization.session?.payload,
    },
  };
}
libs/sdk/src/provider/__tests__/provider-session-scope.test.ts (1)

43-46: Remove unused getPrivate helper or add tests that use it.

The getPrivate helper is defined but doesn't appear to be used in any of the test cases. Either remove it to keep the test file clean, or add tests that actually need to access private members.

-  // Helper to access private members for testing
-  const getPrivate = (registry: ProviderRegistry, prop: string) => {
-    return (registry as any)[prop];
-  };
libs/sdk/src/context/frontmcp-context.provider.ts (1)

47-58: Consider documenting the type assertion limitation more specifically.

The as any cast at Line 58 is justified, but the comment could be more specific about which limitation it addresses (e.g., "Type assertion needed because ProviderFactoryType doesn't support readonly tuple inference for inject()"). This helps future maintainers understand when/if the cast can be removed.

-} as any; // Type assertion needed due to ProviderFactoryType limitations
+} as any; // Type assertion needed: ProviderFactoryType cannot infer readonly tuple from inject()
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 527016a and 356285e.

📒 Files selected for processing (23)
  • docs/draft/blog/11-2025/mcp-run-out-of-socket.mdx (1 hunks)
  • docs/draft/blog/11-2025/openapi-mcp-security-nightmare.mdx (7 hunks)
  • docs/draft/docs/adapters/openapi-adapter.mdx (10 hunks)
  • docs/draft/docs/extensibility/providers.mdx (3 hunks)
  • docs/draft/docs/extensibility/request-context.mdx (1 hunks)
  • libs/adapters/src/openapi/__tests__/openapi-security-unit.spec.ts (25 hunks)
  • libs/adapters/src/openapi/openapi.security.ts (7 hunks)
  • libs/adapters/src/openapi/openapi.tool.ts (4 hunks)
  • libs/adapters/src/openapi/openapi.types.ts (7 hunks)
  • libs/sdk/src/common/interfaces/execution-context.interface.ts (4 hunks)
  • libs/sdk/src/common/interfaces/flow.interface.ts (2 hunks)
  • libs/sdk/src/common/metadata/provider.metadata.ts (1 hunks)
  • libs/sdk/src/context/frontmcp-context-storage.ts (1 hunks)
  • libs/sdk/src/context/frontmcp-context.provider.ts (1 hunks)
  • libs/sdk/src/context/frontmcp-context.ts (1 hunks)
  • libs/sdk/src/context/index.ts (1 hunks)
  • libs/sdk/src/flows/flow.instance.ts (4 hunks)
  • libs/sdk/src/index.ts (1 hunks)
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts (1 hunks)
  • libs/sdk/src/provider/provider.registry.ts (5 hunks)
  • libs/sdk/src/provider/provider.types.ts (1 hunks)
  • libs/sdk/src/scope/flows/http.request.flow.ts (4 hunks)
  • libs/sdk/src/tool/README.md (5 hunks)
✅ Files skipped from review due to trivial changes (1)
  • libs/sdk/src/common/metadata/provider.metadata.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • libs/sdk/src/common/interfaces/flow.interface.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Enable strict TypeScript mode with no any types without strong justification - use unknown instead for generic type defaults
Avoid non-null assertions (!) - use proper error handling and throw specific errors instead
Use specific error classes with MCP error codes instead of generic errors
Use type parameters with constraints instead of unconstrained generics, and prefer unknown over any for generic type defaults
Follow the preset pattern for hierarchical configurations across the codebase

Files:

  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/index.ts
  • libs/adapters/src/openapi/__tests__/openapi-security-unit.spec.ts
  • libs/sdk/src/context/frontmcp-context.provider.ts
  • libs/sdk/src/scope/flows/http.request.flow.ts
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
  • libs/sdk/src/context/frontmcp-context.ts
  • libs/sdk/src/context/frontmcp-context-storage.ts
  • libs/sdk/src/context/index.ts
  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/adapters/src/openapi/openapi.types.ts
  • libs/sdk/src/provider/provider.types.ts
  • libs/adapters/src/openapi/openapi.security.ts
  • libs/sdk/src/provider/provider.registry.ts
  • libs/adapters/src/openapi/openapi.tool.ts
libs/{sdk,adapters,plugins,cli}/src/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

libs/{sdk,adapters,plugins,cli}/src/**/*.ts: Return strictly typed MCP protocol responses (GetPromptResult, ReadResourceResult, etc.) instead of unknown for execute() and read() methods
Validate URIs per RFC 3986 at metadata level using Zod validation with custom refinements
Use getCapabilities() for dynamic capability exposure instead of hardcoding capabilities in adapters
Use changeScope instead of scope for change event properties to avoid confusion with the Scope class
Validate hooks match their entry type and fail fast with InvalidHookFlowError for unsupported flows
Don't mutate rawInput in flows - use state.set() for managing flow state instead

Files:

  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/index.ts
  • libs/adapters/src/openapi/__tests__/openapi-security-unit.spec.ts
  • libs/sdk/src/context/frontmcp-context.provider.ts
  • libs/sdk/src/scope/flows/http.request.flow.ts
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
  • libs/sdk/src/context/frontmcp-context.ts
  • libs/sdk/src/context/frontmcp-context-storage.ts
  • libs/sdk/src/context/index.ts
  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/adapters/src/openapi/openapi.types.ts
  • libs/sdk/src/provider/provider.types.ts
  • libs/adapters/src/openapi/openapi.security.ts
  • libs/sdk/src/provider/provider.registry.ts
  • libs/adapters/src/openapi/openapi.tool.ts
libs/**

⚙️ CodeRabbit configuration file

libs/**: Contains publishable SDK libraries. Review for API correctness, breaking changes, and consistency with docs. When public APIs change, ensure there is a matching docs/draft/docs/** update (not direct edits under docs/docs/**).

Files:

  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/index.ts
  • libs/adapters/src/openapi/__tests__/openapi-security-unit.spec.ts
  • libs/sdk/src/context/frontmcp-context.provider.ts
  • libs/sdk/src/scope/flows/http.request.flow.ts
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
  • libs/sdk/src/context/frontmcp-context.ts
  • libs/sdk/src/context/frontmcp-context-storage.ts
  • libs/sdk/src/context/index.ts
  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/tool/README.md
  • libs/adapters/src/openapi/openapi.types.ts
  • libs/sdk/src/provider/provider.types.ts
  • libs/adapters/src/openapi/openapi.security.ts
  • libs/sdk/src/provider/provider.registry.ts
  • libs/adapters/src/openapi/openapi.tool.ts
libs/*/src/index.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use barrel exports (index.ts) to export all public API surface without legacy exports or aliases

Files:

  • libs/sdk/src/index.ts
docs/draft/docs/**

⚙️ CodeRabbit configuration file

docs/draft/docs/**: This folder holds the draft/source docs that humans are expected to edit. When authors want to add or change documentation, they should do it here. The Codex workflow uses these drafts, together with the code diff, to generate the latest docs under docs/docs/. As a reviewer: - Encourage contributors to add/update content here instead of docs/docs/. - It is fine to do structural/content feedback here (clarity, examples, etc).

Files:

  • docs/draft/docs/extensibility/request-context.mdx
  • docs/draft/docs/adapters/openapi-adapter.mdx
  • docs/draft/docs/extensibility/providers.mdx
docs/**

⚙️ CodeRabbit configuration file

docs/**: Repository documentation for the SDK, using MDX and hosted by Mintlify. See more specific rules for: - docs/docs/** (latest rendered docs, automation-only) - docs/v/** (archived versions, read-only) - docs/draft/docs/** (human-editable drafts) - docs/blogs/** (blogs, human edited) - docs/docs.json (Mintlify navigation)

Files:

  • docs/draft/docs/extensibility/request-context.mdx
  • docs/draft/blog/11-2025/mcp-run-out-of-socket.mdx
  • docs/draft/blog/11-2025/openapi-mcp-security-nightmare.mdx
  • docs/draft/docs/adapters/openapi-adapter.mdx
  • docs/draft/docs/extensibility/providers.mdx
**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.test.ts: Achieve and maintain 95%+ test coverage across all metrics (statements, branches, functions, lines)
Test all code paths including errors, constructor validation, and error class instanceof checks

Files:

  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
🧠 Learnings (13)
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Don't mutate rawInput in flows - use state.set() for managing flow state instead

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Return strictly typed MCP protocol responses (GetPromptResult, ReadResourceResult, etc.) instead of `unknown` for `execute()` and `read()` methods

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/adapters/src/openapi/openapi.types.ts
  • libs/adapters/src/openapi/openapi.security.ts
  • libs/sdk/src/provider/provider.registry.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Enable strict TypeScript mode with no `any` types without strong justification - use `unknown` instead for generic type defaults

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Use type parameters with constraints instead of unconstrained generics, and prefer `unknown` over `any` for generic type defaults

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Validate hooks match their entry type and fail fast with InvalidHookFlowError for unsupported flows

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Avoid non-null assertions (`!`) - use proper error handling and throw specific errors instead

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-11-05T15:00:47.800Z
Learnt from: frontegg-david
Repo: agentfront/frontmcp PR: 11
File: libs/core/src/auth/jwks/jwks.service.ts:62-0
Timestamp: 2025-11-05T15:00:47.800Z
Learning: In the FrontMCP codebase (libs/core/src/auth/jwks/jwks.service.ts), the verifyGatewayToken method intentionally skips signature verification when running in development-only no-auth mode, using decodeJwtPayloadSafe instead of jwtVerify. This is a deliberate design for local development convenience and should not be flagged as a security issue when the PR or code context indicates development/no-auth mode.

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/scope/flows/http.request.flow.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Use FrontMCP's TypeScript-first schema validation framework philosophy - all types should align with MCP protocol definitions

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/index.ts
  • libs/adapters/src/openapi/__tests__/openapi-security-unit.spec.ts
  • libs/sdk/src/context/frontmcp-context.ts
  • libs/adapters/src/openapi/openapi.types.ts
  • libs/adapters/src/openapi/openapi.security.ts
  • libs/sdk/src/provider/provider.registry.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/*/src/index.ts : Use barrel exports (index.ts) to export all public API surface without legacy exports or aliases

Applied to files:

  • libs/sdk/src/index.ts
  • libs/sdk/src/context/index.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Use `changeScope` instead of `scope` for change event properties to avoid confusion with the Scope class

Applied to files:

  • libs/sdk/src/index.ts
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
  • libs/sdk/src/context/index.ts
  • libs/adapters/src/openapi/openapi.tool.ts
📚 Learning: 2025-11-26T15:23:04.965Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-11-26T15:23:04.965Z
Learning: Applies to libs/ui/src/**/*.test.ts : Test behavior across platform configurations (OpenAI, Claude, Gemini, ngrok) where applicable

Applied to files:

  • libs/adapters/src/openapi/__tests__/openapi-security-unit.spec.ts
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Create shared base classes for common functionality across context types (ExecutionContextBase provides get(), tryGet(), scope, fail(), mark(), fetch())

Applied to files:

  • libs/sdk/src/common/interfaces/execution-context.interface.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Use specific error classes with MCP error codes instead of generic errors

Applied to files:

  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/provider/provider.registry.ts
🧬 Code graph analysis (4)
libs/adapters/src/openapi/__tests__/openapi-security-unit.spec.ts (4)
libs/sdk/src/common/interfaces/execution-context.interface.ts (1)
  • authInfo (88-90)
libs/sdk/src/context/frontmcp-context.ts (3)
  • authInfo (230-232)
  • FrontMcpContext (133-489)
  • FrontMcpContext (495-495)
libs/adapters/src/openapi/openapi.security.ts (1)
  • createSecurityContextFromAuth (34-144)
libs/adapters/src/openapi/__tests__/fixtures.ts (1)
  • mockAuthInfo (229-238)
libs/sdk/src/provider/__tests__/provider-session-scope.test.ts (2)
libs/sdk/src/context/session-key.provider.ts (1)
  • SessionKey (27-64)
libs/sdk/src/provider/provider.registry.ts (1)
  • ProviderRegistry (27-1119)
libs/sdk/src/provider/provider.registry.ts (5)
libs/sdk/src/common/interfaces/execution-context.interface.ts (1)
  • scope (134-136)
libs/sdk/src/scope/scope.instance.ts (1)
  • providers (298-300)
libs/sdk/src/provider/provider.types.ts (1)
  • ProviderViews (13-31)
libs/sdk/src/context/session-key.provider.ts (1)
  • SessionKey (27-64)
libs/sdk/src/utils/index.ts (2)
  • isPromise (34-34)
  • tokenName (34-34)
libs/adapters/src/openapi/openapi.tool.ts (2)
libs/adapters/src/openapi/openapi.types.ts (1)
  • InputTransformContext (13-20)
libs/adapters/src/openapi/openapi.security.ts (1)
  • resolveToolSecurity (283-326)
🪛 Biome (2.1.2)
libs/sdk/src/provider/provider.registry.ts

[error] 1020-1020: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (41)
libs/sdk/src/common/interfaces/execution-context.interface.ts (3)

70-81: LGTM: Safe context access patterns.

The tryGetContext() method and contextLogger getter provide safe ways to access context with appropriate fallback behavior. The implementation correctly handles cases where context may not be available (e.g., during initialization).

Also applies to: 109-121


167-183: LGTM: Context-aware fetch with graceful degradation.

The enhanced fetch() implementation correctly delegates to context.fetch() when available (providing auto-injection of Authorization, traceparent, x-request-id, and custom headers) and gracefully falls back to standard fetch otherwise. The documentation clearly explains the behavior.


20-20: Documentation for authInfo breaking change is present.

The type change from AuthInfo to Partial<AuthInfo> for ExecutionContextBaseArgs.authInfo has been documented in docs/draft/docs/extensibility/request-context.mdx, which explains that "authInfo is Partial because authentication information is progressively populated during the request lifecycle." Additional docs in docs/draft/docs/servers/tools.mdx document the deprecation of this.authInfo in favor of this.requestContext.authInfo. The documentation updates satisfy the coding guideline requirement for SDK breaking changes.

docs/draft/docs/extensibility/request-context.mdx (1)

1-385: FrontMcpContext docs look coherent and aligned with the new context model

The page does a good job covering access patterns, tracing, timing, storage, and auth/logging surfaces, and the API reference matches the exported types (requestId, traceContext, sessionId, authInfo, metadata, fetch, etc.). Just make sure the documented defaults (e.g., autoInjectAuthHeaders, autoInjectTracingHeaders, requestTimeout) stay in lockstep with FrontMcpContext’s implementation over time to avoid drift.

docs/draft/blog/11-2025/mcp-run-out-of-socket.mdx (1)

176-179: Scope terminology updated correctly to GLOBAL/CONTEXT

The DI + decorators card now references GLOBAL and CONTEXT scopes, which matches the new provider scope model and broader docs. Looks good.

libs/adapters/src/openapi/__tests__/openapi-security-unit.spec.ts (1)

8-493: Tests correctly adapt to FrontMcpContext-based auth resolution

Using a lightweight createMockContext that populates authInfo (plus basic ids) is a clean way to exercise createSecurityContextFromAuth against the new FrontMcpContext signature. This keeps tests focused on auth behavior without over-mocking the entire context surface. If future tests start relying on trace/metadata, you can extend the helper in one place.

libs/sdk/src/index.ts (1)

14-33: Context barrel exports are well-structured and follow the index.ts guidelines

Re-exporting FrontMcpContext, the Context alias, storage, provider token, request metadata, and trace helpers from ./context gives consumers a single, coherent entry point and matches the barrel-export guidance for libs/*/src/index.ts. No behavioral changes, and the surface is appropriately grouped under a “unified context” comment.

docs/draft/docs/extensibility/providers.mdx (1)

20-277: Provider docs now accurately reflect CONTEXT scope and FrontMcpContext usage

The updates clearly communicate the move to GLOBAL/CONTEXT scopes, deprecate SESSION/REQUEST, and show practical patterns for accessing FrontMcpContext (via getter and FRONTMCP_CONTEXT) from tools and CONTEXT-scoped providers. The Redis/session examples and session metadata snippet align with the unified context design and should be very helpful for users.

libs/sdk/src/tool/README.md (1)

134-261: Tool system README is consistent with the unified context provider model

The documentation now correctly describes provider views as context + global with resolution order context → global, the default bindProvider scope as 'context', and the use of a single context map per invocation (unified session+request). This matches the ProviderViews/interface changes and should help contributors reason about DI behavior.

libs/sdk/src/flows/flow.instance.ts (1)

163-194: LGTM - runWithContext implementation is well-structured.

The session ID extraction correctly handles empty strings (Lines 179-180), and the method properly wraps the flow execution in AsyncLocalStorage context. The fallback for backward compatibility when storage is unavailable is appropriate.

libs/sdk/src/scope/flows/http.request.flow.ts (2)

105-137: LGTM - traceRequest improvements are well-implemented.

Good improvements:

  • Using randomUUID() instead of Math.random() for request IDs (Line 113)
  • Proper fallback chain for sessionId with clear documentation (Lines 121-123)
  • Trace context propagation for correlation (Line 127)

230-251: Session metadata update is appropriately placed here.

The ctx.updateSessionMetadata(authorization.session.payload) at Lines 247-249 is correctly placed in the router stage since it depends on the full authorization flow. The overall context enrichment pattern is good.

libs/sdk/src/provider/__tests__/provider-session-scope.test.ts (3)

107-132: Good test for fresh-per-request behavior.

This test correctly validates that CONTEXT-scoped providers are built fresh on each buildViews() call, confirming no caching between requests. The counter-based approach is a clean way to verify instantiation count.


382-421: Excellent concurrent context isolation test.

This test validates that parallel buildViews() calls create isolated contexts without contention. Using unique build IDs to verify instance uniqueness is a robust approach.


1-14: Well-documented test file header.

The header clearly documents what the tests cover and the relationship to the unified FrontMcpContext model. This helps maintainers understand the test scope.

libs/sdk/src/context/frontmcp-context.provider.ts (1)

31-36: LGTM - Token definition with backward-compatible alias.

Using Symbol.for() ensures the token is shareable across module boundaries. The REQUEST_CONTEXT alias with @deprecated JSDoc is a clean approach for backward compatibility.

libs/adapters/src/openapi/openapi.security.ts (2)

34-42: LGTM - Clean migration to context-based security resolution.

The function signature change from authInfo to ctx: FrontMcpContext is a good improvement, providing access to the full request context (sessionId, traceId, etc.) beyond just auth info. The priority chain (custom resolver → provider mapper → static auth → default) is well-documented.


314-322: Excellent error message with actionable solutions.

The error message clearly identifies the problem and provides four specific solutions with code examples. This will significantly help developers debug authentication configuration issues.

libs/adapters/src/openapi/openapi.types.ts (4)

4-4: LGTM! Import addition aligns with the context refactoring.

The FrontMcpContext import is correctly added to support the new unified context model across adapter callbacks.


13-20: Good: InputTransformContext now uses unified FrontMcpContext.

The change from authInfo: AuthInfo to ctx: FrontMcpContext provides a richer context including session ID, trace context, and more metadata beyond just authentication.


411-426: LGTM! Header and body mapper signatures updated consistently.

Both headersMapper and bodyMapper now accept FrontMcpContext as the first parameter, and the JSDoc comments are updated to reflect the new structure including authInfo, sessionId, traceId, etc.


439-475: LGTM! Security resolver and auth provider mapper signatures updated.

The example code correctly demonstrates accessing ctx.authInfo to extract authentication data, maintaining backward compatibility in usage patterns while providing the richer context object.

docs/draft/blog/11-2025/openapi-mcp-security-nightmare.mdx (2)

238-240: LGTM! Blog examples updated consistently with new context pattern.

The authProviderMapper examples correctly demonstrate the new (ctx) => ctx.authInfo.user?.token pattern, matching the updated type signatures.


384-413: LGTM! Headers and body mapper examples demonstrate ctx usage well.

The examples show proper extraction of authInfo from ctx and also demonstrate the new ctx.traceContext.traceId for observability, which is a nice addition enabled by the unified context.

libs/sdk/src/context/frontmcp-context.ts (4)

99-120: LGTM! Session key validation is well-designed.

The validation enforces reasonable constraints: max 256 characters, alphanumeric with common delimiters (-_.:) for flexibility, and clear error messages via InvalidInputError.


423-434: Good privacy practice: Session ID is hashed in log output.

The toLogContext() method correctly hashes the session ID using SHA-256 before including it in logs, preventing accidental exposure of user-identifying session identifiers while still allowing correlation.


453-488: Well-designed context-aware fetch with proper header precedence.

The fetch method correctly:

  1. Only sets headers if not already present (respecting caller overrides)
  2. Auto-injects auth and tracing headers based on config flags
  3. Injects custom headers from request metadata
  4. Applies timeout via AbortSignal

271-278: The supportsElicit: true is correct and safe—TypeScript's type contract guarantees sendElicitRequest exists.

The TransportRef type definition requires sendElicitRequest as a non-optional property, and the setTransport() method enforces strict type checking. All transport adapters implement this method, and TypeScript prevents creating a TransportRef without it. The suggested runtime check is unnecessary and contradicts the type system's guarantees.

Likely an incorrect or invalid review comment.

docs/draft/docs/adapters/openapi-adapter.mdx (2)

97-103: LGTM! Parameter documentation updated correctly.

The headersMapper and bodyMapper parameter fields now correctly document the FrontMcpContext type and mention the available properties (authInfo, sessionId, traceContext).


187-192: Good addition: Info block explaining ctx parameter structure.

This clarifies what's available in the ctx parameter for users implementing these callbacks.

libs/sdk/src/context/index.ts (1)

1-68: LGTM! Well-organized barrel exports with clear deprecation notices.

The module organization is excellent:

  • Primary exports (FrontMcpContext, ContextStorage) are clearly separated
  • Backward compatibility exports are marked with @deprecated JSDoc
  • The alias Context provides a convenient short name
  • Follows the barrel exports pattern per coding guidelines
libs/sdk/src/context/frontmcp-context-storage.ts (3)

1-26: LGTM!

The module documentation clearly explains the purpose and usage pattern. Imports are appropriate, and the module-level AsyncLocalStorage instance is correctly scoped for singleton access.


148-193: LGTM - Header extraction logic is well-implemented.

The extractMetadata and extractClientIp functions correctly:

  • Filter custom headers by x-frontmcp- prefix with case normalization
  • Handle both string and array header values for x-forwarded-for
  • Parse comma-separated IP lists correctly (taking the first/client IP)
  • Fall back through multiple IP header sources

141-145: Context propagation is correct.

The method properly mutates the context in place via updateAuthInfo(), which uses object spread to merge partial auth info fields: this._authInfo = { ...this._authInfo, ...authInfo }. Since the same FrontMcpContext object remains in AsyncLocalStorage, no re-entry is needed.

libs/sdk/src/provider/provider.registry.ts (7)

215-222: LGTM - Background cleanup appropriately scoped.

Starting cleanup only for scope-level registries (those with parentProviders) is correct since SESSION providers are stored in scope registries. The dispose() method at lines 831-840 properly addresses the lifecycle concern from the previous review.


239-260: LGTM - Scope normalization for backwards compatibility.

The normalizeScope helper correctly maps deprecated SESSION and REQUEST scopes to the unified CONTEXT scope while preserving GLOBAL scope unchanged.


831-840: LGTM - Proper resource cleanup in dispose().

The dispose() method correctly:

  • Stops the cleanup interval
  • Clears session stores for GC
  • Resolves pending lock promises to prevent hung awaits

This addresses the lifecycle concern from the previous review.


865-916: LGTM - Lock acquisition with timeout and generation-based release.

The implementation correctly:

  • Clears the timeout handle after Promise.race (line 898) to prevent timer leaks
  • Uses generation numbers to prevent zombie lock releases
  • Handles overflow with MAX_SAFE_INTEGER check
  • Uses a re-check loop to handle TOCTOU race conditions

This addresses the previous review concern about timer leaks.


1009-1052: Biome static analysis hint is a false positive.

The Biome warning about "hooks being called conditionally" at line 1020 is incorrect. This is backend TypeScript code in a DI/provider registry, not React code. The variable out is a standard assignment, not a React hook call.


1101-1118: LGTM - getScoped provides clean view-based provider lookup.

The method correctly searches context → global → instances with appropriate error messaging when a provider isn't found.


954-993: No action needed. SessionKey.validate() already throws InvalidInputError for all validation failures (empty string, exceeds max length, invalid characters). The implementation at lines 48, 51, and 54-56 of libs/sdk/src/context/session-key.provider.ts correctly uses the MCP error class as required by the coding guidelines.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
libs/sdk/src/provider/provider.registry.ts (1)

41-57: Session cache infrastructure may be unused with unified context model.

The sessionStores, sessionBuildLocks, and related constants are defined but buildViews() creates a fresh contextStore per call (line 825) with the comment "We don't cache context providers because they're per-request."

These structures only appear used by:

  • cleanupSession() / cleanupExpiredSessions() - for explicit cleanup
  • getSessionCacheStats() - returns 0 size per tests
  • dispose() - clears them

Consider documenting that these are retained for backwards compatibility APIs or removing if truly unused.

libs/sdk/src/flows/flow.instance.ts (1)

91-96: as any cast still present for middleware flow input.

Per previous review and coding guidelines, replace as any with a typed interface or unknown with narrowing.

Consider defining a middleware input type:

+interface HttpMiddlewareInput {
+  request: ServerRequest;
+  response: ServerResponse;
+  next: () => void;
+}
+
 const result = await this.runWithContext(
   contextStorage,
   request,
-  { request, response, next } as any,
+  { request, response, next } as HttpMiddlewareInput,
   new Map(),
 );
🧹 Nitpick comments (6)
docs/draft/docs/adapters/openapi-adapter.mdx (2)

97-103: Standardize optional chaining patterns in callback examples for clarity.

The documentation shows inconsistent use of optional chaining when accessing ctx.authInfo:

  • authProviderMapper examples (lines 165-171): ctx.authInfo.user?.githubToken (no chaining on authInfo)
  • SaaS headersMapper/bodyMapper examples (lines 664-670): ctx.authInfo?.user?.tenantId (chaining on authInfo)

Per the Info block (lines 187-191), authentication is "verified and auth fields are populated" by execution time. If authInfo is guaranteed to exist, examples should consistently omit the ?. before authInfo for clarity. If it's not guaranteed in some contexts, the documentation should explicitly state when the optional chaining is necessary.

Apply this pattern consistently across all examples:

- headersMapper: (ctx, headers) => {
-   const authInfo = ctx.authInfo;
-   if (authInfo?.token) {

+ headersMapper: (ctx, headers) => {
+   const authInfo = ctx.authInfo;
+   if (authInfo.token) {

Or, if defensive coding is preferred:

- authProviderMapper: {
-   GitHubAuth: (ctx) => ctx.authInfo.user?.githubToken,
+ authProviderMapper: {
+   GitHubAuth: (ctx) => ctx.authInfo?.user?.githubToken,

Also applies to: 255-283


187-191: Add import guidance for FrontMcpContext type.

The Info block introduces FrontMcpContext as the parameter type passed to callbacks. While documentation doesn't require imports, adding a note about where developers should import this type would improve clarity. Consider adding a brief line such as: "Import FrontMcpContext from @frontmcp/sdk" (or the actual export path).

libs/sdk/src/flows/flow.registry.ts (1)

105-114: Consider adding type guard instead of any cast.

Per coding guidelines, any types should be avoided. The (input as any)?.ctx pattern loses type safety. Consider defining a type guard or a more specific type for MCP handler inputs:

-    // Extract session info from MCP handler context (input.ctx.authInfo)
-    // MCP handlers pass { request, ctx } where ctx has authInfo
-    const mcpCtx = (input as any)?.ctx;
-    const authInfo = mcpCtx?.authInfo;
+    // Extract session info from MCP handler context (input.ctx.authInfo)
+    // MCP handlers pass { request, ctx } where ctx has authInfo
+    const mcpCtx = this.extractMcpContext(input);
+    const authInfo = mcpCtx?.authInfo;

Then add a private helper with proper typing:

private extractMcpContext(input: unknown): { authInfo?: Partial<AuthInfo> } | undefined {
  if (typeof input === 'object' && input !== null && 'ctx' in input) {
    const ctx = (input as { ctx?: unknown }).ctx;
    if (typeof ctx === 'object' && ctx !== null) {
      return ctx as { authInfo?: Partial<AuthInfo> };
    }
  }
  return undefined;
}

This preserves backward compatibility while improving type safety. Based on coding guidelines requiring no any types without strong justification.

libs/sdk/src/provider/__tests__/provider-session-scope.test.ts (1)

25-27: Minor: Consider using unknown instead of any for the decorator target.

Per coding guidelines, any should be avoided without justification. For test fixtures, this is acceptable, but consider:

 function Injectable() {
-  return function (target: any) {};
+  return function (target: unknown) {};
 }
libs/sdk/src/flows/flow.instance.ts (1)

222-226: Type cast from views.context is safe.

The instance as Type cast is justified because buildViews() constructs all providers through ProviderRegistry, which guarantees valid instances. Consider adding a brief comment for clarity:

 // Merge context-scoped providers into deps for resolution by FlowClass
 const mergedDeps = new Map(deps);
+// Cast is safe: buildViews() guarantees properly constructed provider instances
 for (const [token, instance] of views.context) {
   mergedDeps.set(token, instance as Type);
 }
libs/sdk/src/provider/provider.registry.ts (1)

913-917: Error handling during context-scoped provider construction.

The error re-throw preserves the original message which aids debugging. Consider using a specific error class for consistency with MCP error patterns:

 } catch (e: any) {
   const msg = e?.message ?? e;
   console.error(`Failed constructing (context-scoped):`, msg);
-  throw new Error(`Failed constructing (context-scoped) ${tokenName(token)}: ${msg}`);
+  throw new ProviderResolutionError(`Failed constructing (context-scoped) ${tokenName(token)}: ${msg}`);
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 356285e and c0af634.

📒 Files selected for processing (13)
  • apps/demo/src/apps/expenses/providers/session-redis.provider.ts (1 hunks)
  • docs/draft/docs/adapters/openapi-adapter.mdx (12 hunks)
  • libs/adapters/src/openapi/openapi.security.ts (7 hunks)
  • libs/adapters/src/openapi/openapi.types.ts (8 hunks)
  • libs/sdk/src/common/interfaces/execution-context.interface.ts (4 hunks)
  • libs/sdk/src/context/frontmcp-context-storage.ts (1 hunks)
  • libs/sdk/src/context/frontmcp-context.provider.ts (1 hunks)
  • libs/sdk/src/flows/flow.instance.ts (6 hunks)
  • libs/sdk/src/flows/flow.registry.ts (2 hunks)
  • libs/sdk/src/front-mcp/front-mcp.providers.ts (2 hunks)
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts (1 hunks)
  • libs/sdk/src/provider/provider.registry.ts (5 hunks)
  • libs/sdk/src/scope/flows/http.request.flow.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • libs/adapters/src/openapi/openapi.types.ts
  • libs/adapters/src/openapi/openapi.security.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Enable strict TypeScript mode with no any types without strong justification - use unknown instead for generic type defaults
Avoid non-null assertions (!) - use proper error handling and throw specific errors instead
Use specific error classes with MCP error codes instead of generic errors
Use type parameters with constraints instead of unconstrained generics, and prefer unknown over any for generic type defaults
Follow the preset pattern for hierarchical configurations across the codebase

Files:

  • libs/sdk/src/flows/flow.registry.ts
  • libs/sdk/src/scope/flows/http.request.flow.ts
  • libs/sdk/src/front-mcp/front-mcp.providers.ts
  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/context/frontmcp-context.provider.ts
  • libs/sdk/src/context/frontmcp-context-storage.ts
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
  • libs/sdk/src/flows/flow.instance.ts
  • apps/demo/src/apps/expenses/providers/session-redis.provider.ts
  • libs/sdk/src/provider/provider.registry.ts
libs/{sdk,adapters,plugins,cli}/src/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

libs/{sdk,adapters,plugins,cli}/src/**/*.ts: Return strictly typed MCP protocol responses (GetPromptResult, ReadResourceResult, etc.) instead of unknown for execute() and read() methods
Validate URIs per RFC 3986 at metadata level using Zod validation with custom refinements
Use getCapabilities() for dynamic capability exposure instead of hardcoding capabilities in adapters
Use changeScope instead of scope for change event properties to avoid confusion with the Scope class
Validate hooks match their entry type and fail fast with InvalidHookFlowError for unsupported flows
Don't mutate rawInput in flows - use state.set() for managing flow state instead

Files:

  • libs/sdk/src/flows/flow.registry.ts
  • libs/sdk/src/scope/flows/http.request.flow.ts
  • libs/sdk/src/front-mcp/front-mcp.providers.ts
  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/context/frontmcp-context.provider.ts
  • libs/sdk/src/context/frontmcp-context-storage.ts
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/provider/provider.registry.ts
libs/**

⚙️ CodeRabbit configuration file

libs/**: Contains publishable SDK libraries. Review for API correctness, breaking changes, and consistency with docs. When public APIs change, ensure there is a matching docs/draft/docs/** update (not direct edits under docs/docs/**).

Files:

  • libs/sdk/src/flows/flow.registry.ts
  • libs/sdk/src/scope/flows/http.request.flow.ts
  • libs/sdk/src/front-mcp/front-mcp.providers.ts
  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/context/frontmcp-context.provider.ts
  • libs/sdk/src/context/frontmcp-context-storage.ts
  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/provider/provider.registry.ts
docs/draft/docs/**

⚙️ CodeRabbit configuration file

docs/draft/docs/**: This folder holds the draft/source docs that humans are expected to edit. When authors want to add or change documentation, they should do it here. The Codex workflow uses these drafts, together with the code diff, to generate the latest docs under docs/docs/. As a reviewer: - Encourage contributors to add/update content here instead of docs/docs/. - It is fine to do structural/content feedback here (clarity, examples, etc).

Files:

  • docs/draft/docs/adapters/openapi-adapter.mdx
docs/**

⚙️ CodeRabbit configuration file

docs/**: Repository documentation for the SDK, using MDX and hosted by Mintlify. See more specific rules for: - docs/docs/** (latest rendered docs, automation-only) - docs/v/** (archived versions, read-only) - docs/draft/docs/** (human-editable drafts) - docs/blogs/** (blogs, human edited) - docs/docs.json (Mintlify navigation)

Files:

  • docs/draft/docs/adapters/openapi-adapter.mdx
**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.test.ts: Achieve and maintain 95%+ test coverage across all metrics (statements, branches, functions, lines)
Test all code paths including errors, constructor validation, and error class instanceof checks

Files:

  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
apps/demo/**

⚙️ CodeRabbit configuration file

apps/demo/**: apps/demo directory contains a demo application for testing purposes. It can be used as a reference for SDK usage examples.

Files:

  • apps/demo/src/apps/expenses/providers/session-redis.provider.ts
🧠 Learnings (12)
📚 Learning: 2025-11-05T15:00:47.800Z
Learnt from: frontegg-david
Repo: agentfront/frontmcp PR: 11
File: libs/core/src/auth/jwks/jwks.service.ts:62-0
Timestamp: 2025-11-05T15:00:47.800Z
Learning: In the FrontMCP codebase (libs/core/src/auth/jwks/jwks.service.ts), the verifyGatewayToken method intentionally skips signature verification when running in development-only no-auth mode, using decodeJwtPayloadSafe instead of jwtVerify. This is a deliberate design for local development convenience and should not be flagged as a security issue when the PR or code context indicates development/no-auth mode.

Applied to files:

  • libs/sdk/src/scope/flows/http.request.flow.ts
  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Use FrontMCP's TypeScript-first schema validation framework philosophy - all types should align with MCP protocol definitions

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.providers.ts
  • libs/sdk/src/context/frontmcp-context-storage.ts
  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/provider/provider.registry.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Create shared base classes for common functionality across context types (ExecutionContextBase provides get(), tryGet(), scope, fail(), mark(), fetch())

Applied to files:

  • libs/sdk/src/common/interfaces/execution-context.interface.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Use specific error classes with MCP error codes instead of generic errors

Applied to files:

  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/context/frontmcp-context-storage.ts
  • libs/sdk/src/provider/provider.registry.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Return strictly typed MCP protocol responses (GetPromptResult, ReadResourceResult, etc.) instead of `unknown` for `execute()` and `read()` methods

Applied to files:

  • libs/sdk/src/common/interfaces/execution-context.interface.ts
  • libs/sdk/src/context/frontmcp-context-storage.ts
  • libs/sdk/src/flows/flow.instance.ts
  • libs/sdk/src/provider/provider.registry.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Avoid non-null assertions (`!`) - use proper error handling and throw specific errors instead

Applied to files:

  • libs/sdk/src/context/frontmcp-context-storage.ts
  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-11-26T15:23:04.965Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-11-26T15:23:04.965Z
Learning: Applies to libs/ui/src/**/*.test.ts : Test behavior across platform configurations (OpenAI, Claude, Gemini, ngrok) where applicable

Applied to files:

  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Use `changeScope` instead of `scope` for change event properties to avoid confusion with the Scope class

Applied to files:

  • libs/sdk/src/provider/__tests__/provider-session-scope.test.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Don't mutate rawInput in flows - use state.set() for managing flow state instead

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Enable strict TypeScript mode with no `any` types without strong justification - use `unknown` instead for generic type defaults

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Use type parameters with constraints instead of unconstrained generics, and prefer `unknown` over `any` for generic type defaults

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Validate hooks match their entry type and fail fast with InvalidHookFlowError for unsupported flows

Applied to files:

  • libs/sdk/src/flows/flow.instance.ts
🧬 Code graph analysis (4)
libs/sdk/src/flows/flow.registry.ts (5)
libs/sdk/src/context/frontmcp-context.ts (1)
  • flow (291-293)
libs/sdk/src/common/interfaces/flow.interface.ts (1)
  • FlowOutputOf (11-11)
libs/sdk/src/common/interfaces/execution-context.interface.ts (2)
  • authInfo (88-90)
  • scope (134-136)
libs/testing/src/client/mcp-test-client.ts (1)
  • sessionId (206-208)
libs/sdk/src/context/frontmcp-context-storage.ts (1)
  • FrontMcpContextStorage (202-202)
libs/sdk/src/scope/flows/http.request.flow.ts (2)
libs/testing/src/client/mcp-test-client.ts (3)
  • request (818-867)
  • sessionId (206-208)
  • session (210-226)
libs/sdk/src/auth/session/record/session.base.ts (1)
  • user (157-159)
libs/sdk/src/front-mcp/front-mcp.providers.ts (1)
libs/sdk/src/context/frontmcp-context-storage.ts (1)
  • FrontMcpContextStorage (202-202)
libs/sdk/src/flows/flow.instance.ts (8)
libs/sdk/src/context/frontmcp-context-storage.ts (1)
  • FrontMcpContextStorage (202-202)
libs/sdk/src/context/index.ts (2)
  • FrontMcpContextStorage (34-34)
  • FRONTMCP_CONTEXT (38-38)
libs/sdk/src/index.ts (2)
  • FrontMcpContextStorage (21-21)
  • FRONTMCP_CONTEXT (23-23)
libs/sdk/src/common/interfaces/server.interface.ts (1)
  • ServerRequest (6-14)
libs/sdk/src/common/interfaces/flow.interface.ts (3)
  • FlowInputOf (10-10)
  • FlowOutputOf (11-11)
  • context (93-96)
libs/sdk/src/context/frontmcp-context.ts (1)
  • scope (306-308)
libs/sdk/src/errors/mcp.error.ts (1)
  • RequestContextNotAvailableError (365-371)
libs/sdk/src/context/frontmcp-context.provider.ts (1)
  • FRONTMCP_CONTEXT (31-31)
🪛 Biome (2.1.2)
libs/sdk/src/provider/provider.registry.ts

[error] 880-880: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (24)
docs/draft/docs/adapters/openapi-adapter.mdx (1)

1-827: Approve comprehensive documentation migration to FrontMcpContext.

The documentation update comprehensively and consistently reflects the migration from direct authInfo parameters to the unified FrontMcpContext (ctx) pattern. All major examples (authProviderMapper, headersMapper, bodyMapper, securityResolver) are updated with correct signatures. The new Info block effectively explains the context structure and guarantee that authentication fields are pre-populated. The security risk classifications and best practices remain accurate under the new API.

libs/sdk/src/scope/flows/http.request.flow.ts (3)

110-136: LGTM! Context-aware request tracing with proper fallbacks.

The implementation correctly:

  • Uses tryGetContext() to safely access context without throwing
  • Falls back to randomUUID() for request ID generation (better than Math.random() for collision avoidance)
  • Derives sessionId from context first, then header, with a logging-only fallback
  • Truncates traceId appropriately for log output

169-191: AuthInfo population correctly handles unit conversion.

The expiresAt: user.exp ? user.exp * 1000 : undefined correctly converts JWT exp (seconds) to milliseconds, aligning with Date.now() comparisons elsewhere in the codebase. The extra object appropriately preserves user and session details for downstream access.


230-237: Session metadata propagation looks correct.

The guard authorization.session?.payload ensures safe access before calling updateSessionMetadata. This complements the auth info set in checkAuthorization.

libs/sdk/src/front-mcp/front-mcp.providers.ts (1)

27-28: LGTM! FrontMcpContextStorage correctly added to global providers.

The FrontMcpContextStorage is GLOBAL-scoped and needs to be registered at the global level to enable context propagation across all flows. The change aligns with the new context management architecture.

libs/sdk/src/flows/flow.registry.ts (2)

118-131: LGTM! Context wrapping implementation is well-structured.

The flow execution is correctly wrapped with contextStorage.run(), and the context initialization includes all necessary fields (sessionId, scopeId, authInfo). The Promise.resolve() wrapper ensures consistent Promise return type.


133-143: LGTM! Graceful fallback for missing context storage.

The try-catch pattern in getContextStorage() ensures backward compatibility when FrontMcpContextStorage is not registered. This is appropriate for a gradual migration path.

apps/demo/src/apps/expenses/providers/session-redis.provider.ts (1)

6-14: LGTM! Clean migration from SessionProvider to FrontMcpContext.

The provider correctly:

  • Updates scope from SESSION to CONTEXT to match the new model
  • Uses ctx.sessionId directly instead of sessionProvider.session!.id (eliminates the non-null assertion)
  • Maintains the same key prefixing logic with proper sanitization

This demonstrates the recommended pattern for migrating existing session-scoped providers.

libs/sdk/src/context/frontmcp-context.provider.ts (1)

31-36: LGTM! Proper deprecation pattern for backward compatibility.

Using Symbol.for() ensures the token is globally unique and can be resolved across module boundaries. The deprecated REQUEST_CONTEXT alias allows gradual migration of existing code.

libs/sdk/src/provider/__tests__/provider-session-scope.test.ts (1)

42-473: Comprehensive test coverage for the unified context model.

The test suite thoroughly covers:

  • SessionKey validation (empty, max length, invalid characters)
  • Context injection and aliasing (session/request → context)
  • Fresh per-request instantiation (no caching)
  • Scope normalization (SESSION/REQUEST → CONTEXT)
  • Context isolation and global provider sharing
  • Error propagation and getScoped behavior
  • Cross-scope dependencies and concurrent context builds
  • Backwards compatibility for session cache helpers
  • Dispose idempotency
libs/sdk/src/common/interfaces/execution-context.interface.ts (3)

61-68: Proper use of typed MCP error class.

The context getter correctly throws RequestContextNotAvailableError instead of a generic Error, addressing the previous review comment. The catch-all pattern appropriately handles any provider resolution failure.


88-107: Well-structured progressive auth info resolution.

The getAuthInfo() method properly:

  • Returns Partial<AuthInfo> (addressing previous review concern)
  • Prefers context source when available
  • Falls back gracefully for backward compatibility

The deprecation notice on the authInfo getter is clear.


177-183: Context-aware fetch delegation looks correct.

The fallback to standard fetch when context is unavailable maintains backward compatibility while enabling context-aware header injection when available.

libs/sdk/src/flows/flow.instance.ts (3)

176-181: Session ID handling now correctly handles empty strings.

The fix properly addresses the previous review concern:

  • Empty strings are now explicitly handled ('' ?? 'fallback' issue fixed)
  • Trimming prevents whitespace-only session IDs
  • Anonymous sessions get unique UUIDs to prevent data leakage

207-214: Proper error handling with typed MCP error.

The RequestContextNotAvailableError is correctly used with a descriptive message explaining the invariant violation. The comment explains this should never happen in normal operation.


247-249: Type erasure explanation is helpful.

The comment explaining why FlowBase<any> is used (runtime type erasure) provides good context for maintainers.

libs/sdk/src/context/frontmcp-context-storage.ts (4)

44-60: Clean AsyncLocalStorage wrapper with proper DI integration.

The FrontMcpContextStorage is correctly scoped as GLOBAL since it manages the storage mechanism itself, not the per-context data. The run() method creates a fresh context for each invocation.


115-123: Properly uses typed MCP error class.

The getStoreOrThrow() method now throws RequestContextNotAvailableError instead of a generic Error, addressing the previous review comment.


176-196: Robust client IP extraction with proper edge case handling.

The extractClientIp() function correctly handles:

  • Comma-separated x-forwarded-for lists (takes first IP)
  • Array header values from some adapters
  • Fallback to x-real-ip
  • Safe undefined return when no IP is found

144-148: Unable to verify mutation safety claims — file not found in repository.

The file libs/sdk/src/context/frontmcp-context-storage.ts could not be located in the current codebase. Verify that:

  1. The file path is correct
  2. If this is a new file in a PR, ensure it's staged for review
  3. Once available, confirm that FrontMcpContext.updateAuthInfo() has thread-safe mutation semantics and that no concurrent code paths assume immutability of authInfo during callback execution
libs/sdk/src/provider/provider.registry.ts (4)

208-216: Background cleanup timer lifecycle properly managed.

The startSessionCleanup() is called only for scope-level registries (with parentProviders), and the timer is properly unref()ed to allow graceful process exit. This addresses the previous review concern about orphaned intervals.


240-248: Clean scope normalization implementation.

The normalizeScope() method correctly maps deprecated SESSION and REQUEST scopes to CONTEXT, enabling backwards compatibility while unifying the scope model.


775-784: Proper dispose implementation addressing lifecycle concerns.

The dispose() method correctly:

  • Stops the cleanup interval
  • Clears session stores
  • Resolves pending locks to prevent hung promises

This addresses the previous review concern about orphaned intervals and memory leaks.


814-817: No action needed—SessionKey.validate() already uses InvalidInputError.

SessionKey.validate() correctly throws InvalidInputError for all validation failures (empty keys, exceeded length, invalid characters), as shown in the JSDoc and implementation. The code already follows the proper error handling guidelines.

@frontegg-david frontegg-david merged commit 99029fc into main Dec 15, 2025
3 checks passed
@frontegg-david frontegg-david deleted the add-support-for-session-context branch December 15, 2025 03:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants