Skip to content

Conversation

@frontegg-david
Copy link
Contributor

@frontegg-david frontegg-david commented Jan 11, 2026

Summary by CodeRabbit

  • New Features

    • Programmatic direct MCP server, stdio server mode, and in-memory MCP server for client integration.
    • SDK adds direct/in-memory APIs and transport types, plus runtime auth update support.
    • Demo Notes app with note creation/listing, summarization prompt, and demo entrypoints for direct/stdio modes.
  • Tests

    • Extensive end-to-end tests covering direct usage, in-memory client workflows, stdio transport, auth propagation, concurrency, and lifecycle behaviors.
  • Chores

    • New e2e project configs, TypeScript/webpack build setup, and CI workflow enhancements.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 11, 2026

📝 Walkthrough

Walkthrough

Adds a transport-free Direct MCP server and in-memory transport factory, stdio server support, an E2E Notes demo app (tools/resources/prompts) with comprehensive direct+stdio tests and configs, SDK type/export expansions, and CI workflow adjustments for ngrok and publishing.

Changes

Cohort / File(s) Summary
Direct MCP types & impl
libs/sdk/src/direct/direct.types.ts, libs/sdk/src/direct/direct-server.ts, libs/sdk/src/direct/index.ts
New DirectMcpServer API and DirectMcpServerImpl implementing transport-free flows (listTools, callTool, prompts, resources, dispose) with DirectCallOptions/auth handling.
FrontMcp enhancements
libs/sdk/src/front-mcp/front-mcp.ts
Parse config via metadata schema; add createDirect() returning a DirectMcpServer and runStdio() to run MCP over stdio; disable HTTP for direct/stdio modes.
In-memory transport
libs/sdk/src/transport/in-memory-server.ts, libs/sdk/src/transport/index.ts, libs/sdk/src/transport/transport.types.ts
Add createInMemoryServer() producing linked client/server transports with runtime setAuthInfo and close(), export types; extend TransportType with 'in-memory' and 'stdio'.
SDK public exports & metadata types
libs/sdk/src/index.ts, libs/sdk/src/common/metadata/front-mcp.metadata.ts
Re-export direct/in-memory APIs and transport types; add FrontMcpConfigType and FrontMcpConfigInput type aliases.
E2E demo app (Notes)
apps/e2e/demo-e2e-direct/src/apps/notes/*
.../index.ts, .../data/notes.store.ts, .../tools/*.tool.ts, .../resources/*.resource.ts, .../prompts/*.prompt.ts
New Notes app: in-memory notes store, create-note & list-notes tools (zod-validated), notes list resource, and summarize-notes prompt.
E2E server & stdio entrypoint
apps/e2e/demo-e2e-direct/src/main.ts, apps/e2e/demo-e2e-direct/src/stdio-entrypoint.ts
Add serverConfig for the demo and a stdio entrypoint that calls FrontMcpInstance.runStdio(serverConfig).
E2E tests & configs
apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts, .../stdio-transport.e2e.test.ts, .../jest.e2e.config.ts, .../project.json, .../tsconfig*.json, .../webpack.config.js
Add comprehensive direct + stdio E2E tests, Jest e2e config, Nx project config, tsconfigs, and webpack build config.
Small removal
apps/e2e/demo-e2e-public/src/main.ts
Removed custom auth transport block, leaving mode: 'public'.
CI workflow update
.github/workflows/pr-testing-registry.yml
Add optional ngrok_domain input, switch to npm-installed ngrok with validation and token handling, adjust PR package naming/publish logic and registry messaging.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant DirectServer as DirectMcpServerImpl
    participant Scope
    participant Flow as Flow System
    participant Handler as Tool/Resource/Prompt

    Client->>DirectServer: callTool(name, args, options{authContext})
    DirectServer->>Scope: runFlow("callTool", { sessionId, authInfo, payload })
    Scope->>Flow: dispatch flow
    Flow->>Handler: invoke handler
    Handler-->>Flow: return output / throw
    Flow-->>Scope: FlowControl.respond(output)
    Scope-->>DirectServer: respond payload
    DirectServer-->>Client: CallToolResult
Loading
sequenceDiagram
    participant CLI
    participant StdioEntrypoint
    participant FrontMcp as FrontMcpInstance
    participant MCP as MCP Server
    participant StdioTransport as Stdio ServerTransport
    participant OS as OS Signals

    CLI->>StdioEntrypoint: start
    StdioEntrypoint->>FrontMcp: runStdio(serverConfig)
    FrontMcp->>MCP: init MCP server with capabilities
    FrontMcp->>StdioTransport: create & attach transport
    FrontMcp->>OS: register SIGINT/SIGTERM handlers
    OS->>FrontMcp: SIGINT/SIGTERM
    FrontMcp->>MCP: graceful shutdown
    FrontMcp-->>StdioEntrypoint: resolve
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through flows both near and far,
Direct calls now skip the HTTP bar.
Notes were penned and prompts replied,
In-memory bridges kept state inside.
Tests raced concurrent — a bright little star. ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the primary change: adding end-to-end tests for direct usage and stdio transport in FrontMCP, which aligns with the substantial test additions and new functionality introduced throughout the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 66.67% which is sufficient. The required threshold is 65.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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: 7

🤖 Fix all issues with AI agents
In @apps/e2e/demo-e2e-direct/src/apps/notes/tools/create-note.tool.ts:
- Line 31: The current ID generation for the note (id: `note-${Date.now()}` in
create-note.tool.ts) risks collisions under concurrent E2E runs; replace this
with a true UUID generator (e.g., use crypto.randomUUID() or the project's UUID
helper in @frontmcp/utils if available) so the id becomes unique (e.g., prefixed
with "note-") and update any imports accordingly.

In @apps/e2e/demo-e2e-direct/src/main.ts:
- Around line 12-23: The port value parsed with parseInt can be NaN; validate
the parsed result (the port constant created from parseInt(process.env['PORT']
?? '3015', 10)) and fall back to the default (3015) when it's not a finite
positive integer before passing it into the FrontMcp http config; update the
port variable (or introduce validatedPort) and use that in the FrontMcp({ http:
{ port: validatedPort }}) for the Server class to ensure the server always
receives a valid port.

In @apps/e2e/demo-e2e-direct/tsconfig.app.json:
- Around line 12-13: tsconfig.app.json currently excludes e2e tests via the
"exclude" array so e2e tests get no static type-checking; add a solution by
creating a separate tsconfig.e2e.json that includes "e2e/**/*.ts" and extends
the base config (so e2e files are type-checked without affecting app build) and
then add a CI/run target named "typecheck:e2e" (or a package script) that runs
tsc --noEmit -p tsconfig.e2e.json; alternatively, if you prefer a single config,
adjust the "include" to cover "e2e/**/*.ts" for a dedicated typecheck job, but
prefer the separate tsconfig.e2e.json plus the "typecheck:e2e" target for
clarity and CI integration.

In @libs/sdk/src/front-mcp/front-mcp.ts:
- Around line 97-101: The code is casting raw config to FrontMcpConfigType which
bypasses Zod defaults; instead call frontMcpMetadataSchema.parse(options) to
validate and apply defaults before constructing a FrontMcpInstance (replace the
cast in createForGraph and any other places that cast FrontMcpConfigInput to
FrontMcpConfigType, e.g., the other factory/constructor call around the later
cast), and pass the parsed result into the FrontMcpInstance constructor so
providers/tools/serve defaults are correctly applied.

In @libs/sdk/src/index.ts:
- Around line 149-160: The export statements are emitting runtime bindings for
two type-only interfaces: change the exports for CreateInMemoryServerOptions and
InMemoryServerResult to type-only exports (use "export type {
CreateInMemoryServerOptions, InMemoryServerResult }") wherever you currently
export them alongside createInMemoryServer/transport values (e.g., the module
that exports createInMemoryServer and the transport index), so the bundler/TS
emit treats them as types only and no runtime values are emitted.

In @libs/sdk/src/transport/index.ts:
- Around line 32-35: Add documentation for the newly exported public API symbols
by creating or updating files under docs/draft/docs to describe TransportType,
TransportKey, createInMemoryServer, CreateInMemoryServerOptions, and
InMemoryServerResult; include a brief overview of the in-memory server feature,
usage examples for createInMemoryServer (setup, common options from
CreateInMemoryServerOptions, and returned InMemoryServerResult shape), and links
or cross-references to transport.types and in-memory-server implementations so
consumers can find detailed type and behavior info.
🧹 Nitpick comments (13)
apps/e2e/demo-e2e-direct/e2e/stdio-transport.e2e.test.ts (2)

76-96: Strengthen assertions to validate response structure.

The tool invocation tests verify that operations don't error but don't validate the actual response content. Consider adding assertions to verify response shape and expected data.

💡 Example: Add response structure validation
 // Create a note
 const createResult = await client!.callTool({
   name: 'create-note',
   arguments: { title: 'Stdio Test Note', content: 'Created via stdio transport' },
 });

 expect(createResult).toBeDefined();
 expect(createResult.isError).not.toBe(true);
+expect(createResult.content).toBeDefined();
+expect(Array.isArray(createResult.content)).toBe(true);

 // List notes
 const listResult = await client!.callTool({
   name: 'list-notes',
   arguments: {},
 });

 expect(listResult).toBeDefined();
 expect(listResult.isError).not.toBe(true);
+expect(listResult.content).toBeDefined();
+expect(Array.isArray(listResult.content)).toBe(true);
+expect(listResult.content.length).toBeGreaterThanOrEqual(1);

21-44: Silent error swallowing in cleanup could mask issues.

The afterEach hook silently ignores all errors during client and transport cleanup. While this prevents cleanup failures from affecting test results, it could hide legitimate issues like resource leaks or improper shutdown sequences.

Consider logging suppressed errors to aid debugging:

💡 Suggested improvement
 afterEach(async () => {
   // Cleanup client first
   if (client) {
     try {
       await client.close();
     } catch (err) {
-      // Ignore close errors
+      // Log but don't fail on close errors
+      console.warn('Client close error (non-fatal):', err);
     }
     client = null;
   }

   // Cleanup transport (this kills the spawned process)
   if (transport) {
     try {
       await transport.close();
     } catch (err) {
-      // Ignore close errors
+      console.warn('Transport close error (non-fatal):', err);
     }
     transport = null;
   }

   // Give process time to cleanup
   await new Promise((resolve) => setTimeout(resolve, 200));
 });
apps/e2e/demo-e2e-direct/src/main.ts (1)

14-36: Avoid config drift: @FrontMcp({...}) and serverConfig are already diverging.

Right now serverConfig differs from the decorator config (http missing; logging.enableConsole only in one place). Consider defining one config object and reusing it for both the decorator and exports (optionally overriding http/logging per entrypoint).

Possible refactor
 import { FrontMcp, LogLevel } from '@frontmcp/sdk';
 import { NotesApp } from './apps/notes';

-const port = parseInt(process.env['PORT'] ?? '3015', 10);
+const portFromEnv = Number(process.env['PORT']);
+const port = Number.isFinite(portFromEnv) ? portFromEnv : 3015;
+
+export const serverConfig = {
+  info: { name: 'Demo E2E Direct', version: '0.1.0' },
+  apps: [NotesApp],
+  logging: { level: LogLevel.Verbose, enableConsole: true },
+  http: { port },
+  auth: { mode: 'public' as const },
+};

 @FrontMcp({
-  info: { name: 'Demo E2E Direct', version: '0.1.0' },
-  apps: [NotesApp],
-  logging: { level: LogLevel.Verbose },
-  http: { port },
-  auth: {
-    mode: 'public',
-  },
+  ...serverConfig,
 })
 export default class Server {}
-
-/**
- * Export the configuration for direct usage testing.
- * This allows tests to import the config directly.
- */
-export const serverConfig = {
-  info: { name: 'Demo E2E Direct', version: '0.1.0' },
-  apps: [NotesApp],
-  logging: { level: LogLevel.Verbose, enableConsole: true },
-  auth: {
-    mode: 'public' as const,
-  },
-};
apps/e2e/demo-e2e-direct/project.json (1)

8-35: Nx targets look coherent for a Node E2E demo; small maintainability tweak for serve.

Consider referencing the configured outputPath to reduce coupling to the literal dist path.

Example tweak
     "serve": {
       "executor": "nx:run-commands",
       "dependsOn": ["build"],
       "options": {
-        "command": "node dist/apps/e2e/demo-e2e-direct/main.js",
+        "command": "node {options.outputPath}/main.js",
         "cwd": "{workspaceRoot}"
       }
     },
apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts (2)

179-183: Consider adding error type verification.

While checking the error message is good, per testing guidelines, consider also verifying the error type using instanceof checks for better test coverage.

💡 Suggested enhancement
      it('should throw after dispose', async () => {
        await server.dispose();

-        await expect(server.listTools()).rejects.toThrow('disposed');
+        await expect(server.listTools()).rejects.toThrow();
+        try {
+          await server.listTools();
+        } catch (error) {
+          expect(error).toBeInstanceOf(Error);
+          expect(error.message).toContain('disposed');
+        }
      });

347-366: Enhance concurrent test to verify ID uniqueness.

This test exercises concurrent note creation (which is great!), but doesn't verify that all created notes have unique IDs. Given the ID collision risk identified in create-note.tool.ts, this test should verify uniqueness to catch potential race conditions.

🧪 Suggested enhancement
      const results = await Promise.all(promises);

      // All should succeed
      results.forEach((result) => {
        expect(result.isError).not.toBe(true);
      });

+      // Verify all notes have unique IDs
+      const listResult = await server.callTool('list-notes', {});
+      const notes = JSON.parse(listResult.content[0].text).notes;
+      const ids = notes.map(n => n.id);
+      const uniqueIds = new Set(ids);
+      expect(uniqueIds.size).toBe(10);

      await server.dispose();
libs/sdk/src/front-mcp/front-mcp.ts (2)

249-257: Signal handlers may swallow errors during shutdown.

The async callbacks for SIGINT and SIGTERM do not catch errors from mcpServer.close(). If closing fails, the error is silently ignored before process.exit(0). Consider wrapping in try-catch and logging failures, or using a non-zero exit code on error.

Proposed improvement for graceful shutdown
     // Handle graceful shutdown
     process.on('SIGINT', async () => {
+      try {
         await mcpServer.close();
-      process.exit(0);
+        process.exit(0);
+      } catch {
+        process.exit(1);
+      }
     });
     process.on('SIGTERM', async () => {
+      try {
         await mcpServer.close();
-      process.exit(0);
+        process.exit(0);
+      } catch {
+        process.exit(1);
+      }
     });

241-243: The any cast is justified but could be narrowed.

The eslint-disable comment documents the any usage. The MCP SDK handler type incompatibility is a known limitation. Consider adding a brief inline comment explaining why this cast is necessary for maintainability.

libs/sdk/src/transport/in-memory-server.ts (2)

106-134: Capability building logic is duplicated with runStdio.

This capability detection and serverOptions construction is nearly identical to lines 203-233 in front-mcp.ts. Consider extracting a shared helper function (e.g., buildMcpServerOptions(scope)) to centralize this logic and avoid drift.

// Example shared helper in a common module
export function buildMcpServerOptions(scope: Scope) {
  const hasRemoteApps = scope.apps?.getApps().some((app) => app.isRemote) ?? false;
  const hasPrompts = scope.prompts.hasAny() || hasRemoteApps;
  const hasResources = scope.resources.hasAny() || hasRemoteApps;
  // ... rest of capability building
  return serverOptions;
}

144-158: Multiple any casts are necessary but warrant documentation.

The MCP SDK's handler types don't align directly with the wrapped handler signature. The eslint-disable comments are present, but a brief code comment explaining why these casts are unavoidable would help future maintainers understand this isn't technical debt to address.

libs/sdk/src/direct/direct-server.ts (3)

82-84: Use a specific MCP error class for disposed state check.

Per coding guidelines for libs/{sdk,adapters}/**, use specific error classes with MCP error codes instead of generic errors. The disposed check throws a generic Error.

Proposed fix
     if (this._isDisposed) {
-      throw new Error('DirectMcpServer has been disposed');
+      throw new InternalMcpError('DirectMcpServer has been disposed');
     }

38-47: The double cast as unknown as Partial<AuthInfo> may hide type mismatches.

The cast through unknown bypasses all type checking. If the AuthInfo interface changes upstream, this code won't surface compile-time errors. Consider either:

  1. Defining a local type that matches the expected shape
  2. Using a type assertion function with runtime validation

The comment on line 38 explains the intent, but this pattern is fragile.


175-180: Empty catch block silently ignores cleanup errors.

While cleanup errors are often non-critical, silently swallowing them makes debugging harder. Consider logging the error at debug level or adding a comment explaining why errors are intentionally ignored.

Proposed improvement
       try {
         await this.scope.transportService.destroy();
-      } catch {
-        // Ignore cleanup errors
+      } catch (error) {
+        // Cleanup errors are non-critical - log for debugging but don't propagate
+        // since the server is being disposed anyway
       }
📜 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 9f74ee8 and 064d34e.

📒 Files selected for processing (25)
  • apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts
  • apps/e2e/demo-e2e-direct/e2e/stdio-transport.e2e.test.ts
  • apps/e2e/demo-e2e-direct/jest.e2e.config.ts
  • apps/e2e/demo-e2e-direct/project.json
  • apps/e2e/demo-e2e-direct/src/apps/notes/data/notes.store.ts
  • apps/e2e/demo-e2e-direct/src/apps/notes/index.ts
  • apps/e2e/demo-e2e-direct/src/apps/notes/prompts/summarize-notes.prompt.ts
  • apps/e2e/demo-e2e-direct/src/apps/notes/resources/notes-list.resource.ts
  • apps/e2e/demo-e2e-direct/src/apps/notes/tools/create-note.tool.ts
  • apps/e2e/demo-e2e-direct/src/apps/notes/tools/list-notes.tool.ts
  • apps/e2e/demo-e2e-direct/src/main.ts
  • apps/e2e/demo-e2e-direct/src/stdio-entrypoint.ts
  • apps/e2e/demo-e2e-direct/tsconfig.app.json
  • apps/e2e/demo-e2e-direct/tsconfig.json
  • apps/e2e/demo-e2e-direct/webpack.config.js
  • apps/e2e/demo-e2e-public/src/main.ts
  • libs/sdk/src/common/metadata/front-mcp.metadata.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/direct/direct.types.ts
  • libs/sdk/src/direct/index.ts
  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/index.ts
  • libs/sdk/src/transport/in-memory-server.ts
  • libs/sdk/src/transport/index.ts
  • libs/sdk/src/transport/transport.types.ts
💤 Files with no reviewable changes (1)
  • apps/e2e/demo-e2e-public/src/main.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use strict TypeScript mode with no any types without strong justification
Avoid non-null assertions (!) - use proper error handling and type guards instead
Use @frontmcp/utils for cryptographic operations instead of node:crypto directly
Use @frontmcp/utils for file system operations instead of fs/promises or node:fs directly

Files:

  • libs/sdk/src/transport/transport.types.ts
  • apps/e2e/demo-e2e-direct/src/apps/notes/data/notes.store.ts
  • apps/e2e/demo-e2e-direct/src/apps/notes/index.ts
  • apps/e2e/demo-e2e-direct/jest.e2e.config.ts
  • libs/sdk/src/direct/index.ts
  • libs/sdk/src/transport/index.ts
  • apps/e2e/demo-e2e-direct/src/apps/notes/prompts/summarize-notes.prompt.ts
  • libs/sdk/src/front-mcp/front-mcp.ts
  • apps/e2e/demo-e2e-direct/e2e/stdio-transport.e2e.test.ts
  • apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts
  • libs/sdk/src/transport/in-memory-server.ts
  • libs/sdk/src/direct/direct-server.ts
  • apps/e2e/demo-e2e-direct/src/stdio-entrypoint.ts
  • apps/e2e/demo-e2e-direct/src/apps/notes/tools/list-notes.tool.ts
  • libs/sdk/src/common/metadata/front-mcp.metadata.ts
  • libs/sdk/src/direct/direct.types.ts
  • libs/sdk/src/index.ts
  • apps/e2e/demo-e2e-direct/src/apps/notes/tools/create-note.tool.ts
  • apps/e2e/demo-e2e-direct/src/apps/notes/resources/notes-list.resource.ts
  • apps/e2e/demo-e2e-direct/src/main.ts
libs/{sdk,adapters}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

libs/{sdk,adapters}/**/*.{ts,tsx}: Use specific error classes with MCP error codes instead of generic errors
Use getCapabilities() for dynamic capability exposure instead of hardcoding capabilities

Files:

  • libs/sdk/src/transport/transport.types.ts
  • libs/sdk/src/direct/index.ts
  • libs/sdk/src/transport/index.ts
  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/transport/in-memory-server.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/common/metadata/front-mcp.metadata.ts
  • libs/sdk/src/direct/direct.types.ts
  • libs/sdk/src/index.ts
libs/sdk/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

libs/sdk/**/*.{ts,tsx}: Prefer interface for defining object shapes in TypeScript, avoid any types
Use type parameters with constraints instead of unconstrained generics with any defaults
Validate URIs per RFC 3986 at metadata level using isValidMcpUri refinement
Use changeScope instead of scope in change event properties to avoid confusion with Scope class
Fail fast on invalid hook flows by validating hooks match their entry type
Centralize record types in common/records and import from there, not from module-specific files
Return strictly typed MCP protocol responses (e.g., Promise<GetPromptResult>) instead of Promise<unknown> for MCP entry methods
Use unknown instead of any for generic type parameter defaults (not for MCP protocol types)
Create shared base classes for common functionality like ExecutionContextBase for ToolContext and ResourceContext
Do not mutate rawInput in flows - use state.set() for managing flow state instead
Validate inputs and outputs through parseOutput/safeParseOutput methods in validation flows

Files:

  • libs/sdk/src/transport/transport.types.ts
  • libs/sdk/src/direct/index.ts
  • libs/sdk/src/transport/index.ts
  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/transport/in-memory-server.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/common/metadata/front-mcp.metadata.ts
  • libs/sdk/src/direct/direct.types.ts
  • libs/sdk/src/index.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/transport/transport.types.ts
  • libs/sdk/src/direct/index.ts
  • libs/sdk/src/transport/index.ts
  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/transport/in-memory-server.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/common/metadata/front-mcp.metadata.ts
  • libs/sdk/src/direct/direct.types.ts
  • libs/sdk/src/index.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.test.{ts,tsx}: Achieve 95%+ test coverage across all metrics (statements, branches, functions, lines)
Use Jest for testing with 95%+ coverage requirement and 100% test pass rate
Do not use prefixes like 'PT-001' in test names
Do not skip constructor validation tests for error classes and types
Include instanceof checks in tests for error classes to verify proper error hierarchy

Files:

  • apps/e2e/demo-e2e-direct/e2e/stdio-transport.e2e.test.ts
  • apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts
libs/*/src/index.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Export everything users need through barrel exports (index.ts), do not add backwards compatibility aliases

Files:

  • libs/sdk/src/index.ts
🧠 Learnings (26)
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Centralize record types in common/records and import from there, not from module-specific files

Applied to files:

  • apps/e2e/demo-e2e-direct/src/apps/notes/data/notes.store.ts
  • libs/sdk/src/direct/index.ts
  • apps/e2e/demo-e2e-direct/tsconfig.app.json
  • libs/sdk/src/common/metadata/front-mcp.metadata.ts
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Applies to libs/uipack/**/index.{ts,js} : Export all public APIs through appropriate entry points (frontmcp/uipack, frontmcp/uipack/adapters, frontmcp/uipack/theme, etc.)

Applied to files:

  • apps/e2e/demo-e2e-direct/src/apps/notes/index.ts
  • libs/sdk/src/direct/index.ts
  • apps/e2e/demo-e2e-direct/tsconfig.json
  • apps/e2e/demo-e2e-direct/webpack.config.js
  • apps/e2e/demo-e2e-direct/src/stdio-entrypoint.ts
  • libs/sdk/src/common/metadata/front-mcp.metadata.ts
  • libs/sdk/src/index.ts
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/src/universal/**/*.{ts,tsx} : Universal app shell (UniversalApp, FrontMCPProvider) must provide platform-agnostic React context and initialization

Applied to files:

  • apps/e2e/demo-e2e-direct/src/apps/notes/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Create shared base classes for common functionality like ExecutionContextBase for ToolContext and ResourceContext

Applied to files:

  • apps/e2e/demo-e2e-direct/src/apps/notes/index.ts
  • apps/e2e/demo-e2e-direct/src/apps/notes/tools/list-notes.tool.ts
  • apps/e2e/demo-e2e-direct/src/apps/notes/tools/create-note.tool.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.test.{ts,tsx} : Use Jest for testing with 95%+ coverage requirement and 100% test pass rate

Applied to files:

  • apps/e2e/demo-e2e-direct/jest.e2e.config.ts
  • apps/e2e/demo-e2e-direct/tsconfig.app.json
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Applies to libs/uipack/**/{theme,adapters,bundler}/**/*.{test,spec}.{ts,tsx,js,jsx} : Test behavior across all supported platform configurations (OpenAI, Claude, etc.)

Applied to files:

  • apps/e2e/demo-e2e-direct/jest.e2e.config.ts
  • apps/e2e/demo-e2e-direct/tsconfig.json
  • apps/e2e/demo-e2e-direct/e2e/stdio-transport.e2e.test.ts
  • apps/e2e/demo-e2e-direct/tsconfig.app.json
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*.ts : Extend tool metadata using `declare global` pattern to allow tools to specify plugin-specific options in their decorators

Applied to files:

  • apps/e2e/demo-e2e-direct/jest.e2e.config.ts
  • apps/e2e/demo-e2e-direct/tsconfig.json
  • apps/e2e/demo-e2e-direct/tsconfig.app.json
  • apps/e2e/demo-e2e-direct/src/apps/notes/tools/list-notes.tool.ts
  • apps/e2e/demo-e2e-direct/src/apps/notes/tools/create-note.tool.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.test.{ts,tsx} : Do not use prefixes like 'PT-001' in test names

Applied to files:

  • apps/e2e/demo-e2e-direct/jest.e2e.config.ts
  • apps/e2e/demo-e2e-direct/tsconfig.app.json
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*.ts : Use proper ES module imports instead of `require()` for SDK imports; avoid dynamic require of `frontmcp/sdk` modules

Applied to files:

  • libs/sdk/src/direct/index.ts
  • libs/sdk/src/front-mcp/front-mcp.ts
  • apps/e2e/demo-e2e-direct/src/stdio-entrypoint.ts
  • libs/sdk/src/common/metadata/front-mcp.metadata.ts
  • libs/sdk/src/direct/direct.types.ts
  • libs/sdk/src/index.ts
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*plugin.ts : Use module augmentation for context properties via `declare module 'frontmcp/sdk'` combined with runtime plugin metadata `contextExtensions`, not module-level side effects

Applied to files:

  • libs/sdk/src/direct/index.ts
  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/common/metadata/front-mcp.metadata.ts
  • libs/sdk/src/direct/direct.types.ts
  • libs/sdk/src/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/*/src/index.ts : Export everything users need through barrel exports (index.ts), do not add backwards compatibility aliases

Applied to files:

  • libs/sdk/src/direct/index.ts
  • libs/sdk/src/transport/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Return strictly typed MCP protocol responses (e.g., `Promise<GetPromptResult>`) instead of `Promise<unknown>` for MCP entry methods

Applied to files:

  • libs/sdk/src/direct/index.ts
  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/transport/in-memory-server.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/common/metadata/front-mcp.metadata.ts
  • libs/sdk/src/direct/direct.types.ts
  • libs/sdk/src/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.{ts,tsx} : Use `frontmcp/utils` for cryptographic operations instead of `node:crypto` directly

Applied to files:

  • libs/sdk/src/direct/index.ts
  • libs/sdk/src/front-mcp/front-mcp.ts
  • apps/e2e/demo-e2e-direct/src/stdio-entrypoint.ts
  • libs/sdk/src/common/metadata/front-mcp.metadata.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.{ts,tsx} : Use strict TypeScript mode with no `any` types without strong justification

Applied to files:

  • apps/e2e/demo-e2e-direct/tsconfig.json
  • apps/e2e/demo-e2e-direct/tsconfig.app.json
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*.ts : Configure approval requirements on tools using the `approval` decorator property with fields: `required`, `defaultScope`, `category`, `riskLevel`, and `approvalMessage`

Applied to files:

  • apps/e2e/demo-e2e-direct/tsconfig.json
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.{ts,tsx} : Use `frontmcp/utils` for file system operations instead of `fs/promises` or `node:fs` directly

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts
  • apps/e2e/demo-e2e-direct/src/stdio-entrypoint.ts
  • libs/sdk/src/common/metadata/front-mcp.metadata.ts
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/src/bundler/**/*.{ts,tsx} : The bundler module must re-export utilities from frontmcp/uipack/bundler and provide SSR component bundling functionality

Applied to files:

  • apps/e2e/demo-e2e-direct/webpack.config.js
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/src/**/*.test.{ts,tsx} : Use React Testing Library for component tests and include SSR/hydration tests for all interactive components

Applied to files:

  • apps/e2e/demo-e2e-direct/tsconfig.app.json
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Applies to libs/uipack/**/{package.json,*.ts,*.tsx,*.js,*.jsx} : Do not add React dependencies to frontmcp/uipack - it must remain React-free. Use frontmcp/ui for React components.

Applied to files:

  • apps/e2e/demo-e2e-direct/tsconfig.app.json
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.test.{ts,tsx} : Include `instanceof` checks in tests for error classes to verify proper error hierarchy

Applied to files:

  • apps/e2e/demo-e2e-direct/tsconfig.app.json
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Applies to libs/uipack/**/{src}/**/*.{ts,tsx} : Do not use `any` type without justification in TypeScript code

Applied to files:

  • apps/e2e/demo-e2e-direct/tsconfig.app.json
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*plugin.ts : Extend ExecutionContextBase with plugin-specific properties using module declaration (`declare module 'frontmcp/sdk'`) combined with `contextExtensions` in plugin metadata

Applied to files:

  • libs/sdk/src/common/metadata/front-mcp.metadata.ts
  • libs/sdk/src/direct/direct.types.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Use `unknown` instead of `any` for generic type parameter defaults (not for MCP protocol types)

Applied to files:

  • libs/sdk/src/common/metadata/front-mcp.metadata.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/{sdk,adapters}/**/*.{ts,tsx} : Use specific error classes with MCP error codes instead of generic errors

Applied to files:

  • libs/sdk/src/common/metadata/front-mcp.metadata.ts
  • libs/sdk/src/direct/direct.types.ts
  • libs/sdk/src/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Nx-based monorepo build system - use commands like `nx build sdk`, `nx test ast-guard`, `nx run-many -t test`

Applied to files:

  • apps/e2e/demo-e2e-direct/project.json
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/{sdk,adapters}/**/*.{ts,tsx} : Use `getCapabilities()` for dynamic capability exposure instead of hardcoding capabilities

Applied to files:

  • libs/sdk/src/index.ts
🧬 Code graph analysis (9)
apps/e2e/demo-e2e-direct/src/apps/notes/prompts/summarize-notes.prompt.ts (3)
libs/sdk/src/index.ts (1)
  • GetPromptResult (34-34)
apps/e2e/demo-e2e-direct/src/apps/notes/data/notes.store.ts (1)
  • notesStore (32-32)
apps/e2e/demo-e2e-orchestrated/src/apps/notes/prompts/summarize-notes.prompt.ts (1)
  • SummarizeNotesPrompt (19-38)
apps/e2e/demo-e2e-direct/webpack.config.js (1)
libs/uipack/src/handlebars/index.ts (1)
  • join (419-419)
apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts (4)
apps/e2e/demo-e2e-direct/src/apps/notes/data/notes.store.ts (1)
  • notesStore (32-32)
libs/sdk/src/direct/direct.types.ts (1)
  • DirectMcpServer (85-170)
apps/e2e/demo-e2e-direct/src/main.ts (1)
  • serverConfig (29-36)
libs/sdk/src/transport/in-memory-server.ts (1)
  • createInMemoryServer (89-177)
libs/sdk/src/transport/in-memory-server.ts (2)
libs/sdk/src/scope/scope.instance.ts (1)
  • Scope (37-384)
libs/sdk/src/transport/mcp-handlers/index.ts (1)
  • createMcpHandlers (17-56)
apps/e2e/demo-e2e-direct/src/stdio-entrypoint.ts (2)
libs/sdk/src/front-mcp/front-mcp.ts (1)
  • FrontMcpInstance (10-259)
apps/e2e/demo-e2e-direct/src/main.ts (1)
  • serverConfig (29-36)
apps/e2e/demo-e2e-direct/src/apps/notes/tools/list-notes.tool.ts (3)
libs/cli/src/templates/3rd-party-integration/src/tools/example.list.ts (1)
  • inputSchema (12-17)
apps/e2e/demo-e2e-direct/src/apps/notes/tools/create-note.tool.ts (1)
  • Tool (22-41)
apps/e2e/demo-e2e-direct/src/apps/notes/data/notes.store.ts (1)
  • notesStore (32-32)
apps/e2e/demo-e2e-direct/src/apps/notes/tools/create-note.tool.ts (3)
libs/cli/src/templates/3rd-party-integration/src/tools/example.list.ts (1)
  • inputSchema (12-17)
apps/e2e/demo-e2e-direct/src/apps/notes/tools/list-notes.tool.ts (1)
  • Tool (22-36)
apps/e2e/demo-e2e-direct/src/apps/notes/data/notes.store.ts (1)
  • notesStore (32-32)
apps/e2e/demo-e2e-direct/src/apps/notes/resources/notes-list.resource.ts (1)
apps/e2e/demo-e2e-direct/src/apps/notes/data/notes.store.ts (1)
  • notesStore (32-32)
apps/e2e/demo-e2e-direct/src/main.ts (1)
apps/e2e/demo-e2e-public/src/main.ts (1)
  • FrontMcp (6-15)
⏰ 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). (4)
  • GitHub Check: Lint & Format Checks
  • GitHub Check: Build Libraries
  • GitHub Check: Package E2E (Verdaccio)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (19)
apps/e2e/demo-e2e-direct/jest.e2e.config.ts (1)

1-44: LGTM!

The Jest e2e configuration is well-structured with appropriate settings for end-to-end testing. The sequential execution (maxWorkers: 1), extended timeout (60s), and decorator support align well with the direct MCP server testing requirements.

libs/sdk/src/direct/direct.types.ts (1)

1-170: LGTM!

The type definitions are well-structured and follow all coding guidelines:

  • Uses interface for object shapes as recommended
  • All MCP methods return strictly typed Promise<XxxResult> responses
  • No any types used
  • Comprehensive JSDoc documentation with usage examples

The design provides a clean, type-safe API for transport-free MCP server access.

Based on coding guidelines requiring strictly typed MCP protocol responses.

apps/e2e/demo-e2e-direct/tsconfig.json (1)

1-15: LGTM!

Standard TypeScript project references configuration with proper decorator support for the SDK.

apps/e2e/demo-e2e-direct/src/apps/notes/data/notes.store.ts (1)

8-30: No thread safety concerns. The NotesStore class operations are safe despite concurrent test scenarios. JavaScript's single-threaded event loop ensures that all Map operations (set, get, delete) execute atomically, even when concurrent async calls are made via Promise.all(). The "concurrent" test operations are concurrent at the network/Promise level, not at the actual JavaScript execution level, so synchronization mechanisms are not required.

apps/e2e/demo-e2e-direct/src/stdio-entrypoint.ts (1)

11-18: LGTM! Clean stdio entrypoint implementation.

The entrypoint is well-structured with proper ES module imports, clear error handling, and appropriate process exit behavior. The inline documentation provides helpful usage examples for both development and production scenarios.

libs/sdk/src/transport/transport.types.ts (1)

7-7: LGTM! Appropriate transport type extension.

The addition of 'in-memory' and 'stdio' to the TransportType union properly supports the new transport modes introduced in this PR. This is a non-breaking public API extension that enables the direct usage and stdio transport capabilities.

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

1-9: LGTM! Proper barrel export pattern.

The module correctly exports the Direct MCP Server API surface using type-only exports for interfaces and a concrete export for the implementation. This follows SDK best practices and provides a clean public API entry point.

As per coding guidelines: properly exports public APIs through appropriate entry points.

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

218-222: LGTM! Proper configuration type exports.

The new type exports correctly leverage Zod's z.infer and z.input utilities to provide distinct types for configuration before and after defaults are applied. The inline comments clearly document the distinction between input and output types, which improves developer experience when using the SDK.

apps/e2e/demo-e2e-direct/src/apps/notes/index.ts (1)

1-14: Clean app registration; wiring is straightforward and readable.

apps/e2e/demo-e2e-direct/src/apps/notes/tools/create-note.tool.ts (1)

5-17: LGTM: Well-structured schemas.

The schemas properly use .strict() to prevent extra properties and include helpful descriptions for API documentation.

apps/e2e/demo-e2e-direct/src/apps/notes/resources/notes-list.resource.ts (1)

25-32: LGTM: Clean resource implementation.

The resource properly implements the ResourceContext pattern with a clear output schema and straightforward execution logic.

apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts (2)

1-24: LGTM: Well-documented test file with proper setup.

The file header clearly explains the purpose and use cases. The beforeEach cleanup ensures test isolation.


20-392: Excellent E2E test coverage.

The test suite comprehensively covers:

  • Direct server lifecycle and operations
  • In-memory transport and MCP client integration
  • Tool, resource, and prompt operations
  • Auth context propagation and dynamic updates
  • Concurrent operations
  • Error handling and cleanup

This aligns well with the PR objectives for testing direct usage and transport capabilities.

apps/e2e/demo-e2e-direct/webpack.config.js (1)

1-28: LGTM: Well-configured webpack setup for E2E testing.

The configuration is appropriate for a Node.js E2E test application:

  • Development mode with source maps for debugging
  • External dependencies properly handled
  • Building from source for accurate testing
  • No optimization for faster builds
libs/sdk/src/front-mcp/front-mcp.ts (1)

133-150: LGTM! The createDirect method is well-documented and properly validates scopes.

The implementation correctly disables HTTP transport, validates that at least one scope exists before returning, and wraps the scope in DirectMcpServerImpl. The JSDoc examples are helpful for users.

libs/sdk/src/transport/in-memory-server.ts (2)

1-11: LGTM! Proper imports following coding guidelines.

The use of @frontmcp/utils for randomUUID instead of node:crypto directly aligns with the coding guidelines.


167-176: LGTM! Clean API surface with proper cleanup.

The returned object provides a clear interface with clientTransport, setAuthInfo, and close. The close method correctly unregisters from the notification service before closing the server.

apps/e2e/demo-e2e-direct/src/apps/notes/tools/list-notes.tool.ts (1)

1-36: LGTM! Well-structured tool following established patterns.

The ListNotesTool follows the same structure as CreateNoteTool shown in the relevant code snippets. The zod schemas are properly defined, type inference is used correctly, and the tool decorator configuration is complete. The underscore prefix on _input correctly signals the unused parameter.

libs/sdk/src/direct/direct-server.ts (1)

109-163: LGTM! All MCP operations return strictly typed protocol responses.

The methods listTools, callTool, listResources, listResourceTemplates, readResource, listPrompts, and getPrompt all return properly typed MCP protocol results (e.g., Promise<ListToolsResult>, Promise<CallToolResult>). This follows the coding guideline to "return strictly typed MCP protocol responses instead of Promise<unknown> for MCP entry methods."

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: 12

🤖 Fix all issues with AI agents
In @.github/workflows/pr-testing-registry.yml:
- Around line 22-26: The workflow currently concatenates the user-controlled
input inputs.ngrok_domain into NGROK_CMD and executes it, enabling command
injection; fix by validating/sanitizing ngrok_domain (allow only a strict
whitelist pattern such as [a-z0-9.-]+, reject empty or dangerous characters like
;|&$`<>\"\' and spaces), and stop building a shell string—pass the domain as a
separate argument to the ngrok invocation or use the runner’s exec/array-style
command form so it is not interpreted by a shell; update the NGROK_CMD usage and
any other concatenations in the workflow (including the referenced block around
lines 142-169) to use this safe-argument approach and input validation.
- Around line 411-495: The printed install commands incorrectly reference a
scoped CLI package @frontmcp/cli but the actual CLI is unscoped frontmcp; update
the npm and yarn lists in the Print install commands step to remove any "npm
install @frontmcp/cli@$VERSION" and "yarn add @frontmcp/cli@$VERSION" entries
and replace them where appropriate with the unscoped frontmcp references (e.g.,
use npm install -g frontmcp@$VERSION --registry=$REGISTRY and npx
--registry=$REGISTRY frontmcp@$VERSION), and adjust the .npmrc note text so it
explicitly states the CLI is unscoped and must be installed with the --registry
flag.
- Around line 224-240: PKG_NAME can be set to the string "null" when jq returns
null; change the jq call to capture its output into a temp variable (e.g.,
PKG_NAME_RAW=$(jq -r '.name // empty' "libs/$pkg/dist/package.json"
2>/dev/null)) and then set PKG_NAME="${PKG_NAME_RAW:-@frontmcp/$pkg}" (or
explicitly test for empty/"null" and fallback) before publishing; update the
PKG_NAME assignment in the loop that builds LIBS_PACKAGES so missing or null
names use the default @frontmcp/$pkg rather than "null".
- Around line 138-141: Replace the global installation of the wrong package by
changing the install command to use the official, pinned ngrok SDK: replace the
current `npm install -g ngrok` invocation with `npm install -g
@ngrok/ngrok@1.5.2` so the subsequent `npx ngrok` commands (the ones that run
`config add-authtoken`, `--domain`, `--log=stdout` in the workflow) use the
maintained @ngrok/ngrok package and a fixed version to avoid breaking changes.

In @apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts:
- Around line 189-288: The test uses unsafe any casts for scope and auth info;
fix by importing the concrete Scope class and UserClaim type, retrieve the scope
via const scopeEntry = frontMcp.getScopes()[0]; narrow it with a runtime check
(e.g., if (!(scopeEntry instanceof Scope)) throw) and then pass the narrowed
scope to createInMemoryServer instead of using "as any", and replace
setAuthInfo({...} as any) with a fully-formed UserClaim object (including
required fields like sub and any other mandatory properties) so setAuthInfo is
called with the proper UserClaim type.

In @libs/sdk/src/direct/direct-server.ts:
- Around line 69-72: buildHandlerContext currently ignores
DirectCallOptions.metadata so request metadata never reaches flows/handlers;
update buildHandlerContext (the method that returns { authInfo }) to extract
options?.metadata and include it in the returned context object (e.g., return {
authInfo, metadata: options?.metadata }) so handlers can access it as part of
ctx, or if you prefer to drop support remove metadata from the DirectCallOptions
type and all callers—preferably wire options.metadata into the ctx returned by
buildHandlerContext.
- Around line 77-103: The runFlow method currently casts flowName to any when
calling this.scope.runFlowForOutput and throws a generic InternalMcpError for
non-respond FlowControl cases; update runFlow to type flowName to the proper
flow union (e.g., FlowName or the known flow type used by
scope.runFlowForOutput) instead of using "as any", call
this.scope.runFlowForOutput with the correctly typed flowName, and when catching
a FlowControl with types like "fail" or "abort" include the FlowControl
output/details in the thrown InternalMcpError (e.g., include e.output or
stringify it) so failures surface actionable information.
- Around line 28-47: In buildAuthInfo, avoid coercing a missing token into an
empty string and remove the double-cast: construct a Partial<AuthInfo> object
and only add the token property when authContext?.token is defined (omit token
entirely for unauth calls), keep sessionId/user/scopes/clientId/extra as before
(use user.sub for clientId), and return the object typed as Partial<AuthInfo>
without using "as unknown as Partial<AuthInfo>".

In @libs/sdk/src/front-mcp/front-mcp.ts:
- Around line 142-160: In createDirect (public static async createDirect)
replace the generic throw new Error('No scopes initialized...') with throwing an
InternalMcpError so SDK consumers get MCP-specific errors; locate the
createDirect method on FrontMcpInstance usage, import or reference
InternalMcpError, and throw new InternalMcpError('No scopes initialized. Ensure
at least one app is configured.') (or equivalent message) instead of Error to
follow libs/sdk error conventions.

In @libs/sdk/src/index.ts:
- Around line 148-161: The new public exports (DirectMcpServer,
DirectAuthContext, DirectCallOptions, DirectRequestMetadata,
createInMemoryServer, CreateInMemoryServerOptions, InMemoryServerResult,
TransportType, TransportKey) were added to the SDK but lack corresponding
documentation; add concise doc pages for each exported type/function describing
purpose, API surface, parameters/types, and a short usage example, and register
those pages in the docs navigation/TOC so they appear under the public SDK docs;
ensure the docs mention how DirectMcpServer differs from HTTP server usage and
show createInMemoryServer example for testing/integration, and include type
references for CreateInMemoryServerOptions/InMemoryServerResult and
TransportType/TransportKey.

In @libs/sdk/src/transport/index.ts:
- Around line 31-33: The current export re-exports TransportType and
TransportKey as value exports which can introduce runtime artifacts; change the
export to type-only re-exports for TransportType and TransportKey (e.g., use
export type { TransportType, TransportKey } from './transport.types') while
keeping SupportedTransport as a normal export from
'./adapters/transport.local.adapter' so only the type definitions are
re-exported at compile time.
🧹 Nitpick comments (5)
apps/e2e/demo-e2e-direct/project.json (1)

36-52: Clarify the distinction between "test" and "test:e2e" targets.

Both targets use the same Jest configuration file (jest.e2e.config.ts) but differ primarily in the runInBand option and output paths. This creates potential confusion about which target to use.

Consider:

  • If both targets serve distinct purposes, document the difference (e.g., parallel vs. sequential execution) in comments or README
  • If one is redundant, consolidate to a single target
  • Alternatively, use different config files if they're meant for different test suites
apps/e2e/demo-e2e-direct/tsconfig.e2e.json (1)

1-9: Looks good for E2E type-checking; exclude: [] is likely unnecessary.

Minor: omitting exclude entirely keeps the config simpler unless you’re intentionally overriding an inherited exclude list. Based on learnings, keep strict TS inherited from the base config.

apps/e2e/demo-e2e-direct/src/main.ts (1)

12-15: Harden port validation (upper bound + integer).

parseInt gives an integer, but adding an explicit <= 65535 bound avoids odd configs.

Proposed diff
-const rawPort = parseInt(process.env['PORT'] ?? '3015', 10);
-const port = Number.isFinite(rawPort) && rawPort > 0 ? rawPort : 3015;
+const rawPort = Number.parseInt(process.env['PORT'] ?? '3015', 10);
+const port = Number.isInteger(rawPort) && rawPort > 0 && rawPort <= 65535 ? rawPort : 3015;
libs/sdk/src/transport/index.ts (1)

66-79: Export shape is clear; consider consolidating ./in-memory-server exports.

Optional cleanup: re-export function + types in one statement to reduce repetition.

apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts (1)

348-405: Make concurrent test cleanup resilient (dispose/close in finally).

If an expectation fails, the server/client may leak and cascade failures in later tests.

Proposed diff
   it('should handle concurrent tool calls via createDirect', async () => {
-      const server = await FrontMcpInstance.createDirect(serverConfig);
+      const server = await FrontMcpInstance.createDirect(serverConfig);
+      try {
         // Create multiple notes concurrently
         const promises = Array.from({ length: 10 }, (_, i) =>
           server.callTool('create-note', {
             title: `Concurrent Note ${i}`,
             content: `Content ${i}`,
           }),
         );
 
         const results = await Promise.all(promises);
         ...
-      await server.dispose();
+      } finally {
+        await server.dispose();
+      }
     });
📜 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 064d34e and 00cc1a6.

📒 Files selected for processing (11)
  • .github/workflows/pr-testing-registry.yml
  • apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts
  • apps/e2e/demo-e2e-direct/e2e/stdio-transport.e2e.test.ts
  • apps/e2e/demo-e2e-direct/project.json
  • apps/e2e/demo-e2e-direct/src/apps/notes/tools/create-note.tool.ts
  • apps/e2e/demo-e2e-direct/src/main.ts
  • apps/e2e/demo-e2e-direct/tsconfig.e2e.json
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/index.ts
  • libs/sdk/src/transport/index.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/e2e/demo-e2e-direct/src/apps/notes/tools/create-note.tool.ts
  • apps/e2e/demo-e2e-direct/e2e/stdio-transport.e2e.test.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use strict TypeScript mode with no any types without strong justification
Avoid non-null assertions (!) - use proper error handling and type guards instead
Use @frontmcp/utils for cryptographic operations instead of node:crypto directly
Use @frontmcp/utils for file system operations instead of fs/promises or node:fs directly

Files:

  • apps/e2e/demo-e2e-direct/src/main.ts
  • apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts
  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/transport/index.ts
  • libs/sdk/src/index.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.test.{ts,tsx}: Achieve 95%+ test coverage across all metrics (statements, branches, functions, lines)
Use Jest for testing with 95%+ coverage requirement and 100% test pass rate
Do not use prefixes like 'PT-001' in test names
Do not skip constructor validation tests for error classes and types
Include instanceof checks in tests for error classes to verify proper error hierarchy

Files:

  • apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts
libs/{sdk,adapters}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

libs/{sdk,adapters}/**/*.{ts,tsx}: Use specific error classes with MCP error codes instead of generic errors
Use getCapabilities() for dynamic capability exposure instead of hardcoding capabilities

Files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/transport/index.ts
  • libs/sdk/src/index.ts
libs/sdk/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

libs/sdk/**/*.{ts,tsx}: Prefer interface for defining object shapes in TypeScript, avoid any types
Use type parameters with constraints instead of unconstrained generics with any defaults
Validate URIs per RFC 3986 at metadata level using isValidMcpUri refinement
Use changeScope instead of scope in change event properties to avoid confusion with Scope class
Fail fast on invalid hook flows by validating hooks match their entry type
Centralize record types in common/records and import from there, not from module-specific files
Return strictly typed MCP protocol responses (e.g., Promise<GetPromptResult>) instead of Promise<unknown> for MCP entry methods
Use unknown instead of any for generic type parameter defaults (not for MCP protocol types)
Create shared base classes for common functionality like ExecutionContextBase for ToolContext and ResourceContext
Do not mutate rawInput in flows - use state.set() for managing flow state instead
Validate inputs and outputs through parseOutput/safeParseOutput methods in validation flows

Files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/transport/index.ts
  • libs/sdk/src/index.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/front-mcp/front-mcp.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/transport/index.ts
  • libs/sdk/src/index.ts
libs/*/src/index.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Export everything users need through barrel exports (index.ts), do not add backwards compatibility aliases

Files:

  • libs/sdk/src/index.ts
🧠 Learnings (29)
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.{ts,tsx} : Use strict TypeScript mode with no `any` types without strong justification

Applied to files:

  • apps/e2e/demo-e2e-direct/tsconfig.e2e.json
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.test.{ts,tsx} : Use Jest for testing with 95%+ coverage requirement and 100% test pass rate

Applied to files:

  • apps/e2e/demo-e2e-direct/tsconfig.e2e.json
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.test.{ts,tsx} : Do not use prefixes like 'PT-001' in test names

Applied to files:

  • apps/e2e/demo-e2e-direct/tsconfig.e2e.json
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.test.{ts,tsx} : Do not skip constructor validation tests for error classes and types

Applied to files:

  • apps/e2e/demo-e2e-direct/tsconfig.e2e.json
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Applies to libs/uipack/**/{theme,adapters,bundler}/**/*.{test,spec}.{ts,tsx,js,jsx} : Test behavior across all supported platform configurations (OpenAI, Claude, etc.)

Applied to files:

  • apps/e2e/demo-e2e-direct/tsconfig.e2e.json
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.test.{ts,tsx} : Include `instanceof` checks in tests for error classes to verify proper error hierarchy

Applied to files:

  • apps/e2e/demo-e2e-direct/tsconfig.e2e.json
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Applies to libs/uipack/**/index.{ts,js} : Export all public APIs through appropriate entry points (frontmcp/uipack, frontmcp/uipack/adapters, frontmcp/uipack/theme, etc.)

Applied to files:

  • apps/e2e/demo-e2e-direct/src/main.ts
  • .github/workflows/pr-testing-registry.yml
  • libs/sdk/src/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.{ts,tsx} : Use `frontmcp/utils` for file system operations instead of `fs/promises` or `node:fs` directly

Applied to files:

  • apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts
  • libs/sdk/src/front-mcp/front-mcp.ts
  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*.ts : Use proper ES module imports instead of `require()` for SDK imports; avoid dynamic require of `frontmcp/sdk` modules

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • .github/workflows/pr-testing-registry.yml
  • libs/sdk/src/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Return strictly typed MCP protocol responses (e.g., `Promise<GetPromptResult>`) instead of `Promise<unknown>` for MCP entry methods

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/transport/index.ts
  • libs/sdk/src/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.{ts,tsx} : Use `frontmcp/utils` for cryptographic operations instead of `node:crypto` directly

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/index.ts
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*plugin.ts : Use module augmentation for context properties via `declare module 'frontmcp/sdk'` combined with runtime plugin metadata `contextExtensions`, not module-level side effects

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Use `unknown` instead of `any` for generic type parameter defaults (not for MCP protocol types)

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/src/react/hooks/**/*.{ts,tsx} : MCP bridge hooks (useMcpBridge, useCallTool, useToolInput, useToolOutput, useTheme) must be properly typed and handle loading/error states

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Validate inputs and outputs through parseOutput/safeParseOutput methods in validation flows

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Use type parameters with constraints instead of unconstrained generics with `any` defaults

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*plugin.ts : Extend ExecutionContextBase with plugin-specific properties using module declaration (`declare module 'frontmcp/sdk'`) combined with `contextExtensions` in plugin metadata

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Applies to libs/uipack/**/{package.json,*.ts,*.tsx,*.js,*.jsx} : Do not add React dependencies to frontmcp/uipack - it must remain React-free. Use frontmcp/ui for React components.

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/package.json : The frontmcp/ui package requires React as a peer dependency (^18.0.0 || ^19.0.0)

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Organize code following the frontmcp/uipack directory structure (adapters/, bundler/, theme/, renderers/, validation/, etc.)

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/package.json : Entry points must match the documented paths: frontmcp/ui/react, frontmcp/ui/renderers, frontmcp/ui/render, frontmcp/ui/universal, frontmcp/ui/bundler, frontmcp/ui/bridge, frontmcp/ui/components, frontmcp/ui/layouts, frontmcp/ui/web-components

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Applies to libs/uipack/**/{build,bundler}/**/*.{ts,tsx,js,jsx} : For server-side MDX rendering with bundled React, use frontmcp/ui/renderers instead of frontmcp/uipack/renderers

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Nx-based monorepo build system - use commands like `nx build sdk`, `nx test ast-guard`, `nx run-many -t test`

Applied to files:

  • apps/e2e/demo-e2e-direct/project.json
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/{sdk,adapters}/**/*.{ts,tsx} : Use specific error classes with MCP error codes instead of generic errors

Applied to files:

  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/transport/index.ts
  • libs/sdk/src/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/*/src/index.ts : Export everything users need through barrel exports (index.ts), do not add backwards compatibility aliases

Applied to files:

  • libs/sdk/src/transport/index.ts
  • libs/sdk/src/index.ts
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/src/bundler/**/*.{ts,tsx} : The bundler module must re-export utilities from frontmcp/uipack/bundler and provide SSR component bundling functionality

Applied to files:

  • libs/sdk/src/index.ts
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/src/renderers/**/*.renderer.ts : Server-side renderers must export both named exports (ReactRenderer, MdxRenderer) and default instances (reactRenderer, mdxRenderer) with consistent interface patterns

Applied to files:

  • libs/sdk/src/index.ts
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*.ts : Avoid using `node:crypto` directly; always use `frontmcp/utils` for cross-platform cryptographic support

Applied to files:

  • libs/sdk/src/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Centralize record types in common/records and import from there, not from module-specific files

Applied to files:

  • libs/sdk/src/index.ts
🧬 Code graph analysis (4)
apps/e2e/demo-e2e-direct/src/main.ts (1)
apps/e2e/demo-e2e-public/src/main.ts (1)
  • FrontMcp (6-15)
apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts (7)
apps/e2e/demo-e2e-direct/src/apps/notes/data/notes.store.ts (1)
  • notesStore (32-32)
libs/sdk/src/index.ts (3)
  • DirectMcpServer (154-154)
  • FrontMcpInstance (21-21)
  • createInMemoryServer (157-157)
libs/sdk/src/direct/direct.types.ts (1)
  • DirectMcpServer (85-170)
libs/sdk/src/front-mcp/front-mcp.ts (1)
  • FrontMcpInstance (17-280)
apps/e2e/demo-e2e-direct/src/main.ts (1)
  • serverConfig (37-37)
libs/sdk/src/transport/index.ts (1)
  • createInMemoryServer (66-66)
libs/sdk/src/transport/in-memory-server.ts (1)
  • createInMemoryServer (89-177)
libs/sdk/src/front-mcp/front-mcp.ts (5)
libs/sdk/src/common/metadata/front-mcp.metadata.ts (2)
  • FrontMcpConfigInput (222-222)
  • frontMcpMetadataSchema (211-213)
libs/sdk/src/direct/direct.types.ts (1)
  • DirectMcpServer (85-170)
libs/sdk/src/direct/direct-server.ts (1)
  • DirectMcpServerImpl (53-183)
libs/sdk/src/scope/scope.instance.ts (1)
  • Scope (37-384)
libs/sdk/src/transport/mcp-handlers/index.ts (1)
  • createMcpHandlers (17-56)
libs/sdk/src/direct/direct-server.ts (2)
libs/sdk/src/direct/direct.types.ts (3)
  • DirectAuthContext (22-34)
  • DirectMcpServer (85-170)
  • DirectCallOptions (51-56)
libs/sdk/src/common/interfaces/flow.interface.ts (1)
  • FlowControl (19-43)
⏰ 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). (4)
  • GitHub Check: Lint & Format Checks
  • GitHub Check: Build Libraries
  • GitHub Check: Package E2E (Verdaccio)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (7)
apps/e2e/demo-e2e-direct/project.json (3)

1-6: LGTM - Well-structured project metadata.

The project metadata follows Nx conventions with clear, descriptive tags that will aid in filtering and organizing e2e test projects.


7-27: LGTM - Appropriate build configuration.

The build target is correctly configured for a Node.js application with webpack and TypeScript. The generatePackageJson: true option ensures the app can be deployed standalone, which is appropriate for an e2e test application.


28-35: LGTM - Serve target correctly configured.

The serve target properly depends on the build target and runs the compiled application from the workspace root.

apps/e2e/demo-e2e-direct/src/main.ts (1)

20-25: Nice: shared baseConfig reduces drift between HTTP + direct usage.

This matches the goal of keeping demo config consistent across transports.

Also applies to: 27-37

apps/e2e/demo-e2e-direct/e2e/direct-usage.e2e.test.ts (1)

20-186: Strong coverage of direct tool/resource/prompt surface; disposal behavior is asserted.

The structure maps well to the new API surface (direct + lifecycle).

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

104-110: Good: parse config for graph creation to apply defaults consistently.

libs/sdk/src/direct/direct-server.ts (1)

169-182: Dispose is idempotent and best-effort cleanup is reasonable here.

@agentfront agentfront deleted a comment from github-actions bot Jan 11, 2026
@github-actions
Copy link
Contributor

PR Testing Registry Stopped

The temporary npm registry for this PR has been shut down.

Reason: Workflow cancelled

To start a new registry, trigger the "PR Testing Registry" workflow again.

@agentfront agentfront deleted a comment from github-actions bot Jan 11, 2026
@agentfront agentfront deleted a comment from github-actions bot Jan 11, 2026
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

Caution

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

⚠️ Outside diff range comments (1)
.github/workflows/pr-testing-registry.yml (1)

138-193: Shell injection vulnerability in ngrok command construction—use bash arrays instead of string concatenation.

The code builds NGROK_CMD as a string and uses unquoted variable expansion ($NGROK_CMD --domain=$NGROK_DOMAIN followed by $NGROK_CMD --log=stdout), allowing command/argument injection via inputs.ngrok_domain.

Additionally:

  • After npm install -g ngrok, use the ngrok command directly instead of npx ngrok to avoid version mismatches or unexpected behavior.
  • Replace string concatenation with bash arrays and quote expansions to prevent shell injection.
Safer execution with bash arrays
-          if [ -n "${NGROK_AUTH_TOKEN:-}" ]; then
+          if [ -n "${NGROK_AUTH_TOKEN:-}" ]; then
             echo "Configuring ngrok with auth token..."
-            npx ngrok config add-authtoken "$NGROK_AUTH_TOKEN"
+            ngrok config add-authtoken "$NGROK_AUTH_TOKEN"
           else
             echo "::warning::NGROK_AUTH_TOKEN not configured. Using ngrok without authentication (random URLs, rate limits may apply)."
           fi

-          NGROK_CMD="npx ngrok http 4873"
+          NGROK_CMD=(ngrok http 4873)
           if [ -n "${NGROK_DOMAIN:-}" ]; then
             if [ -z "${NGROK_AUTH_TOKEN:-}" ]; then
               echo "::error::Custom domain requires NGROK_AUTH_TOKEN to be configured"
               exit 1
             fi
             echo "Using custom domain: $NGROK_DOMAIN"
-            NGROK_CMD="$NGROK_CMD --domain=$NGROK_DOMAIN"
+            NGROK_CMD+=(--domain="$NGROK_DOMAIN")
           fi

           # Start ngrok
-          $NGROK_CMD --log=stdout > /tmp/ngrok.log 2>&1 &
+          "${NGROK_CMD[@]}" --log=stdout > /tmp/ngrok.log 2>&1 &
🤖 Fix all issues with AI agents
In @.github/workflows/pr-testing-registry.yml:
- Around line 417-503: The workflow prints install commands that reference the
non-existent scoped package @frontmcp/cli and use Yarn Berry's unsupported
--registry flag; update the printed commands by removing any "npm install/yarn
add @frontmcp/cli" entries and replace CLI references with the unscoped package
name frontmcp where appropriate (e.g., npm install -g frontmcp@${VERSION} and
npx frontmcp@${VERSION}), and change all Yarn examples to instruct configuring
registry in .yarnrc.yml (use npmRegistryServer and npmScopes for @frontmcp)
rather than using --registry flags in the yarn add/global commands; keep the
.npmrc instructions for scoped packages as-is and ensure any remaining CLI
instructions that require a registry use npm (or npx --registry) instead of Yarn
flags.
🧹 Nitpick comments (1)
.github/workflows/pr-testing-registry.yml (1)

22-26: Good addition, but treat ngrok_domain as untrusted input when building shell commands later.
You use this input to construct a command string later; ensure it can’t inject flags/commands via whitespace/shell metacharacters.

📜 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 00cc1a6 and 1a48521.

📒 Files selected for processing (1)
  • .github/workflows/pr-testing-registry.yml
🧰 Additional context used
🧠 Learnings (8)
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Applies to libs/uipack/**/{package.json,*.ts,*.tsx,*.js,*.jsx} : Do not add React dependencies to frontmcp/uipack - it must remain React-free. Use frontmcp/ui for React components.

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Applies to libs/uipack/**/index.{ts,js} : Export all public APIs through appropriate entry points (frontmcp/uipack, frontmcp/uipack/adapters, frontmcp/uipack/theme, etc.)

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*.ts : Use proper ES module imports instead of `require()` for SDK imports; avoid dynamic require of `frontmcp/sdk` modules

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/package.json : The frontmcp/ui package requires React as a peer dependency (^18.0.0 || ^19.0.0)

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.{ts,tsx} : Use `frontmcp/utils` for file system operations instead of `fs/promises` or `node:fs` directly

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Organize code following the frontmcp/uipack directory structure (adapters/, bundler/, theme/, renderers/, validation/, etc.)

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/package.json : Entry points must match the documented paths: frontmcp/ui/react, frontmcp/ui/renderers, frontmcp/ui/render, frontmcp/ui/universal, frontmcp/ui/bundler, frontmcp/ui/bridge, frontmcp/ui/components, frontmcp/ui/layouts, frontmcp/ui/web-components

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Applies to libs/uipack/**/{build,bundler}/**/*.{ts,tsx,js,jsx} : For server-side MDX rendering with bundled React, use frontmcp/ui/renderers instead of frontmcp/uipack/renderers

Applied to files:

  • .github/workflows/pr-testing-registry.yml
⏰ 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). (4)
  • GitHub Check: Build Libraries
  • GitHub Check: Lint & Format Checks
  • GitHub Check: Package E2E (Verdaccio)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (4)
.github/workflows/pr-testing-registry.yml (4)

200-206: PR version derivation from libs/sdk/package.json is sensible and semver-friendly.
<current>-pr.<num>.<sha> should work well as a prerelease identifier.


231-246: Nice improvement: publishing/logging the real package name from dist/package.json.
This should make publish summaries and troubleshooting more accurate (especially for the non-scoped frontmcp CLI).


296-326: No changes needed. npx --registry=<url> is a supported npm CLI flag and works as written in the code. The flag is correctly positioned before the positional argument (frontmcp@...), which is the required syntax. The code snippet follows documented npx/npm practices and requires no adjustment.

Likely an incorrect or invalid review comment.


28-31: The pull-requests: write permission is sufficient for github.rest.issues.createComment.
GitHub's REST API documentation explicitly allows either issues: write or pull-requests: write for the create-comment endpoint. The workflow currently has the correct permission to post PR comments, and issues: write is not required.

Likely an incorrect or invalid review comment.

@github-actions
Copy link
Contributor

PR Testing Registry Stopped

The temporary npm registry for this PR has been shut down.

Reason: Timeout reached

To start a new registry, trigger the "PR Testing Registry" workflow again.

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

🤖 Fix all issues with AI agents
In @libs/sdk/src/front-mcp/front-mcp.ts:
- Line 160: Change the getScopes() return type from ScopeEntry[] to Scope[] in
both ScopeRegistry.getScopes and ScopeRegistryInterface.getScopes so callers no
longer need to assert types; update the signatures and any related type
imports/usages to reflect Scope[] and remove the unsafe cast at the
DirectMcpServerImpl construction (the new return type guarantees scopes[0] is a
Scope).

In @libs/sdk/src/transport/index.ts:
- Around line 67-80: Add new draft docs under docs/draft/docs that document the
three new public SDK transport exports: createInMemoryServer,
CreateInMemoryServerOptions, and InMemoryServerResult. Provide a brief overview
of each symbol, show usage examples for creating and tearing down an in-memory
MCP server, demonstrate configuring options via CreateInMemoryServerOptions, and
show how to consume the returned InMemoryServerResult (client transport, auth
setter, close), plus integration snippets for the SDK client, LangChain adapter,
and unit/integration testing patterns. Keep the files under docs/draft/docs/**
(not docs/docs/**), include headings, short code snippets, and a simple “when to
use” section for each API.
🧹 Nitpick comments (3)
libs/sdk/src/front-mcp/front-mcp.ts (1)

264-279: Signal handler exits with code 0 even on error.

The SIGINT and SIGTERM handlers call process.exit(0) even when mcpServer.close() throws an error (lines 268, 276). This masks cleanup failures with a success exit code.

Consider using process.exit(1) when errors occur during shutdown to signal that the process did not terminate cleanly.

♻️ Proposed fix
 process.on('SIGINT', async () => {
   try {
     await mcpServer.close();
+    process.exit(0);
   } catch (err) {
     console.error('Error closing MCP server:', err);
+    process.exit(1);
   }
-  process.exit(0);
 });
 process.on('SIGTERM', async () => {
   try {
     await mcpServer.close();
+    process.exit(0);
   } catch (err) {
     console.error('Error closing MCP server:', err);
+    process.exit(1);
   }
-  process.exit(0);
 });
libs/sdk/src/direct/direct-server.ts (2)

39-39: Redundant fallback in clientId assignment.

Line 39 uses user.sub ?? 'direct', but user.sub is already guaranteed to be a string by line 37's logic (authContext.user.sub ?? 'direct'). The additional ?? 'direct' fallback here is redundant.

♻️ Simplify to remove redundant fallback
-  const clientId = user.sub ?? 'direct';
+  const clientId = user.sub;

116-117: Potential error from JSON.stringify on circular references.

Line 117 uses JSON.stringify(e.output) which could throw a TypeError if e.output contains circular references. While unlikely in practice, this could mask the original flow control error with a JSON serialization error.

♻️ Add safe stringification
-        const details = e.output ? `: ${JSON.stringify(e.output)}` : '';
+        const details = e.output 
+          ? `: ${JSON.stringify(e.output, (key, value) => 
+              typeof value === 'object' && value !== null ? '[Circular]' : value
+            )}` 
+          : '';
         throw new InternalMcpError(`Flow ended with ${e.type}${details}`);

Or simply omit the output stringification:

-        const details = e.output ? `: ${JSON.stringify(e.output)}` : '';
-        throw new InternalMcpError(`Flow ended with ${e.type}${details}`);
+        throw new InternalMcpError(`Flow ended with ${e.type}`);
📜 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 1a48521 and 19f7dd1.

📒 Files selected for processing (4)
  • .github/workflows/pr-testing-registry.yml
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/transport/index.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use strict TypeScript mode with no any types without strong justification
Avoid non-null assertions (!) - use proper error handling and type guards instead
Use @frontmcp/utils for cryptographic operations instead of node:crypto directly
Use @frontmcp/utils for file system operations instead of fs/promises or node:fs directly

Files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/transport/index.ts
libs/{sdk,adapters}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

libs/{sdk,adapters}/**/*.{ts,tsx}: Use specific error classes with MCP error codes instead of generic errors
Use getCapabilities() for dynamic capability exposure instead of hardcoding capabilities

Files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/transport/index.ts
libs/sdk/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

libs/sdk/**/*.{ts,tsx}: Prefer interface for defining object shapes in TypeScript, avoid any types
Use type parameters with constraints instead of unconstrained generics with any defaults
Validate URIs per RFC 3986 at metadata level using isValidMcpUri refinement
Use changeScope instead of scope in change event properties to avoid confusion with Scope class
Fail fast on invalid hook flows by validating hooks match their entry type
Centralize record types in common/records and import from there, not from module-specific files
Return strictly typed MCP protocol responses (e.g., Promise<GetPromptResult>) instead of Promise<unknown> for MCP entry methods
Use unknown instead of any for generic type parameter defaults (not for MCP protocol types)
Create shared base classes for common functionality like ExecutionContextBase for ToolContext and ResourceContext
Do not mutate rawInput in flows - use state.set() for managing flow state instead
Validate inputs and outputs through parseOutput/safeParseOutput methods in validation flows

Files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/transport/index.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/front-mcp/front-mcp.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/transport/index.ts
🧠 Learnings (29)
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*.ts : Use proper ES module imports instead of `require()` for SDK imports; avoid dynamic require of `frontmcp/sdk` modules

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • .github/workflows/pr-testing-registry.yml
  • libs/sdk/src/transport/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Return strictly typed MCP protocol responses (e.g., `Promise<GetPromptResult>`) instead of `Promise<unknown>` for MCP entry methods

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/transport/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.{ts,tsx} : Use `frontmcp/utils` for file system operations instead of `fs/promises` or `node:fs` directly

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*plugin.ts : Use module augmentation for context properties via `declare module 'frontmcp/sdk'` combined with runtime plugin metadata `contextExtensions`, not module-level side effects

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.{ts,tsx} : Use `frontmcp/utils` for cryptographic operations instead of `node:crypto` directly

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/transport/index.ts
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*plugin.ts : Extend ExecutionContextBase with plugin-specific properties using module declaration (`declare module 'frontmcp/sdk'`) combined with `contextExtensions` in plugin metadata

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Use `unknown` instead of `any` for generic type parameter defaults (not for MCP protocol types)

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/direct/direct-server.ts
  • libs/sdk/src/transport/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Validate inputs and outputs through parseOutput/safeParseOutput methods in validation flows

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/direct/direct-server.ts
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/src/react/hooks/**/*.{ts,tsx} : MCP bridge hooks (useMcpBridge, useCallTool, useToolInput, useToolOutput, useTheme) must be properly typed and handle loading/error states

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/direct/direct-server.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/{sdk,adapters}/**/*.{ts,tsx} : Use specific error classes with MCP error codes instead of generic errors

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/direct/direct-server.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Validate URIs per RFC 3986 at metadata level using `isValidMcpUri` refinement

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Applies to libs/uipack/**/{src}/**/*.{ts,tsx,js,jsx} : Do not expose internal error details in public APIs - use sanitized error messages

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*.ts : Do not expose internal error details in public-facing error messages

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/src/react/hooks/**/*.{ts,tsx} : Component hooks must properly handle loading and error states when calling MCP tools

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*.ts : Avoid using `node:crypto` directly; always use `frontmcp/utils` for cross-platform cryptographic support

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/transport/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.{ts,tsx} : Avoid non-null assertions (`!`) - use proper error handling and type guards instead

Applied to files:

  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/direct/direct-server.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/direct/direct-server.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Do not mutate rawInput in flows - use state.set() for managing flow state instead

Applied to files:

  • libs/sdk/src/direct/direct-server.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Fail fast on invalid hook flows by validating hooks match their entry type

Applied to files:

  • libs/sdk/src/direct/direct-server.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Use yarn as the package manager for the monorepo

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/package.json : The frontmcp/ui package requires React as a peer dependency (^18.0.0 || ^19.0.0)

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Organize code following the frontmcp/uipack directory structure (adapters/, bundler/, theme/, renderers/, validation/, etc.)

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/package.json : Entry points must match the documented paths: frontmcp/ui/react, frontmcp/ui/renderers, frontmcp/ui/render, frontmcp/ui/universal, frontmcp/ui/bundler, frontmcp/ui/bridge, frontmcp/ui/components, frontmcp/ui/layouts, frontmcp/ui/web-components

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/*/src/index.ts : Export everything users need through barrel exports (index.ts), do not add backwards compatibility aliases

Applied to files:

  • libs/sdk/src/transport/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to libs/sdk/**/*.{ts,tsx} : Centralize record types in common/records and import from there, not from module-specific files

Applied to files:

  • libs/sdk/src/transport/index.ts
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.{ts,tsx} : Use strict TypeScript mode with no `any` types without strong justification

Applied to files:

  • libs/sdk/src/transport/index.ts
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Applies to libs/uipack/**/{src}/**/*.{ts,tsx} : Do not use `any` type without justification in TypeScript code

Applied to files:

  • libs/sdk/src/transport/index.ts
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*.ts : Avoid using `any` type without justification in TypeScript files

Applied to files:

  • libs/sdk/src/transport/index.ts
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/src/**/*.{ts,tsx} : Avoid using any type without justification; all props, return types, and generics must be properly typed

Applied to files:

  • libs/sdk/src/transport/index.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). (4)
  • GitHub Check: Build Libraries
  • GitHub Check: Lint & Format Checks
  • GitHub Check: Package E2E (Verdaccio)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (8)
libs/sdk/src/transport/index.ts (1)

32-33: LGTM: Type-only exports are correctly structured.

The type-only exports for TransportType and TransportKey follow TypeScript best practices and are consistent with the existing export pattern in this barrel file.

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

256-256: LGTM - Type cast justification is clear.

The comment on lines 253-255 properly explains why the any cast is necessary here - the MCP SDK's handler type expects a specific context shape, but the wrapped handlers preserve all context properties via pass-through.

libs/sdk/src/direct/direct-server.ts (2)

127-181: LGTM - Strictly typed MCP protocol responses.

All operation methods correctly return strictly typed MCP protocol response types (Promise<ListToolsResult>, Promise<CallToolResult>, etc.) as required by the coding guidelines.


187-200: LGTM - Proper resource cleanup with defensive coding.

The dispose method implements proper cleanup with:

  • Idempotent behavior (safe to call multiple times)
  • Defensive check for transportService existence
  • Best-effort cleanup that doesn't throw
  • Appropriate use of console.debug for non-critical warnings
.github/workflows/pr-testing-registry.yml (4)

143-157: LGTM - Robust domain validation prevents injection.

The domain validation properly prevents command injection by:

  • Allowing only safe characters (alphanumeric, dots, hyphens)
  • Explicitly rejecting shell metacharacters that could enable command injection
  • Validating the format before use

173-189: LGTM - Safe command construction prevents shell injection.

The ngrok command construction uses bash arrays with proper expansion ("${NGROK_ARGS[@]}") which safely prevents shell injection even with untrusted input. Combined with the earlier domain validation, this provides defense-in-depth.


256-262: LGTM - Dynamic package name detection handles scoped and non-scoped packages.

The logic correctly handles both scoped (@frontmcp/*) and non-scoped (frontmcp CLI) packages by reading the actual package name from the built package.json, with a sensible fallback for missing names.


322-352: LGTM - Clear documentation distinguishes scoped vs non-scoped packages.

The documentation correctly explains that:

  • The CLI (frontmcp) is non-scoped and requires --registry flag
  • SDK packages (@frontmcp/*) are scoped and work with .npmrc configuration

This helps prevent common user confusion when installing from the test registry.

…d improve installation instructions for Yarn
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

📜 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 19f7dd1 and 16c9772.

📒 Files selected for processing (1)
  • .github/workflows/pr-testing-registry.yml
🧰 Additional context used
🧠 Learnings (8)
📚 Learning: 2025-11-16T22:47:05.139Z
Learnt from: frontegg-david
Repo: agentfront/frontmcp PR: 50
File: docs/docs/v/0.1/getting-started/welcome.mdx:2-3
Timestamp: 2025-11-16T22:47:05.139Z
Learning: In the agentfront/frontmcp repository, the docs/docs/v/** directory governance rule prohibiting manual edits applies to already-frozen releases, but does not preclude initial setup and bootstrap commits that establish the versioned docs structure.

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Use yarn as the package manager for the monorepo

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-06T02:34:55.689Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/plugins/CLAUDE.md:0-0
Timestamp: 2026-01-06T02:34:55.689Z
Learning: Applies to libs/plugins/**/*.ts : Use proper ES module imports instead of `require()` for SDK imports; avoid dynamic require of `frontmcp/sdk` modules

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/package.json : The frontmcp/ui package requires React as a peer dependency (^18.0.0 || ^19.0.0)

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-06T17:16:04.304Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:16:04.304Z
Learning: Applies to **/*.{ts,tsx} : Use `frontmcp/utils` for file system operations instead of `fs/promises` or `node:fs` directly

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Organize code following the frontmcp/uipack directory structure (adapters/, bundler/, theme/, renderers/, validation/, etc.)

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2025-12-24T00:41:41.819Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-12-24T00:41:41.819Z
Learning: Applies to libs/ui/package.json : Entry points must match the documented paths: frontmcp/ui/react, frontmcp/ui/renderers, frontmcp/ui/render, frontmcp/ui/universal, frontmcp/ui/bundler, frontmcp/ui/bridge, frontmcp/ui/components, frontmcp/ui/layouts, frontmcp/ui/web-components

Applied to files:

  • .github/workflows/pr-testing-registry.yml
📚 Learning: 2026-01-04T14:35:18.366Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/uipack/CLAUDE.md:0-0
Timestamp: 2026-01-04T14:35:18.366Z
Learning: Applies to libs/uipack/**/{build,bundler}/**/*.{ts,tsx,js,jsx} : For server-side MDX rendering with bundled React, use frontmcp/ui/renderers instead of frontmcp/uipack/renderers

Applied to files:

  • .github/workflows/pr-testing-registry.yml
⏰ 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). (4)
  • GitHub Check: Build Libraries
  • GitHub Check: Lint & Format Checks
  • GitHub Check: Package E2E (Verdaccio)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (7)
.github/workflows/pr-testing-registry.yml (7)

22-26: LGTM! Well-defined optional input.

The ngrok domain input is properly structured with clear description and sensible defaults.


143-157: Solid domain validation for injection prevention.

The two-tier validation approach (format check + dangerous character rejection) effectively prevents command injection. The regex requirement for at least 2 alphanumeric characters is strict but appropriate for ngrok domains.


159-214: Excellent security improvements with array-based command construction.

The refactored ngrok setup properly prevents shell injection via array expansion and validates auth token requirements for custom domains. The optional auth token with warnings provides good user experience.


244-304: Robust package name derivation with proper fallback handling.

The updated publishing logic correctly derives package names from dist/package.json with appropriate fallback to scoped naming. The use of jq's // empty operator combined with bash null/empty checks provides solid error handling.


305-376: Excellent documentation improvements for registry usage.

The expanded artifact documentation clearly explains the distinction between scoped and unscoped packages, provides comprehensive install commands, and includes helpful configuration examples. This significantly improves the user experience.


443-524: Helpful addition for user guidance and debugging.

The comprehensive install commands step provides clear, actionable guidance for different package managers and package types. The repeated emphasis on CLI scoping requirements helps prevent common user errors.


215-228: Version calculation logic is sound.

All packages in the monorepo share consistent versioning (currently 0.7.2), confirming the assumption that the SDK package.json can serve as the authoritative source for the PR version base. The prerelease version format follows semver conventions correctly.

@agentfront agentfront deleted a comment from github-actions bot Jan 11, 2026
@agentfront agentfront deleted a comment from github-actions bot Jan 11, 2026
@frontegg-david frontegg-david merged commit 0e981ac into main Jan 11, 2026
25 of 26 checks passed
@frontegg-david frontegg-david deleted the support-direct-usage branch January 11, 2026 17:25
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