Skip to content

Cherry-pick: perf: load less at startup (#934, #935, #937) - #941

Merged
alexmercerpo merged 3 commits into
mainfrom
perf/1.10.x-934-to-937-cherry-pick-main
Oct 21, 2026
Merged

alexmercerpo merged 3 commits into
mainfrom
perf/1.10.x-934-to-937-cherry-pick-main

Conversation

@frontegg-david

@frontegg-david frontegg-david commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Cherry-pick to main

This PR brings #934, #935 and #937, merged to release/1.10.x, to main as one PR. Each squash commit is picked in order with git cherry-pick -x, so every commit names its source. It replaces the per-PR cherry-picks the workflow opened (#938, #939 and #940), which I'm closing in favor of this one.

Release PR Commit on release/1.10.x What it changes
#934 5b541910e createInMemoryServer, the direct client and runWebStandardMcp use the @frontmcp/protocol module already loaded, instead of loading a second ESM copy of it and the MCP SDK (the #923 fix for the remaining three places).
#935 b7ee8319d js-yaml, semver and the @frontmcp/uipack root load on first use under require(), through #js-yaml, #semver and #uipack-render subpath imports. Worker and browser builds keep static imports.
#937 f13b8af46 The SSE transport (raw-body, content-type, iconv-lite, http-errors and others, 16 files) loads with the first SSE session.

All three applied without conflicts. The 26 files they change are identical to release/1.10.x, where each PR passed CI.

Results

From the release PRs, measured with the benchmark's harness:

Before After
Direct client connect(), time to connected (#934) 81.0 ms 15.1 ms
Direct client heap / RSS (#934) 40.6 / 146.4 MB 27.5 / 123.1 MB
createFetchHandler(), first tools/call after the SDK loads (#934) 101.9 ms 47.1 ms
Modules loaded, HTTP / stdio server (#935) 450 / 326 404 / 280
Cold start p50, stdio / HTTP (#935) 198.7 / 267.1 ms 190.6 / 257.0 ms
RSS after startup (#935) 147.4 MB 141.1 MB
Cold start p50, stdio (#937, 16 rounds) 176.9 ms 173.4 ms
RSS, stdio (#937) 125.2 MB 122.3 MB

Throughput is unchanged within the run-to-run spread.

Tests

Each release PR passed On Push, Package E2E, Performance and CodeQL, with no review comments left open. This branch has the same files, and CI runs here on main.

Summary by CodeRabbit

  • New Features

    • Added SDK access to YAML parsing, semantic-version utilities, and UI rendering helpers.
    • Added lazy loading for optional YAML, semver, UI rendering, and SSE transport functionality.
  • Performance

    • Reduced unnecessary startup loading by loading optional capabilities only when needed.
  • Bug Fixes

    • Improved transport initialization and validation for SSE, streamable HTTP, and stateless HTTP connections.
  • Tests

    • Expanded coverage for lazy loading, transport selection, and SSE lifecycle behavior.

…he loaded protocol module (#934)

createInMemoryServer(), the direct client's notification and elicitation
handlers, and runWebStandardMcp() took their classes and schemas from
`await import('@frontmcp/protocol')`. In a CommonJS process that import
resolves the package's `import` condition, so connect(), create() clients and
createFetchHandler() loaded a second, ESM copy of @frontmcp/protocol and,
through it, of the MCP SDK, on top of the CommonJS copy the SDK had already
required.

They now use the statically imported @frontmcp/protocol, as runStdio() does
since #923. In an ESM process the import resolves the same ESM module as before.

(cherry picked from commit 5b54191)
…under require() (#935)

A server loaded js-yaml (25 files), semver (23) and the @frontmcp/uipack root
at startup, for code most servers never run: SKILL.md and YAML config parsing,
the ESM loader's version ranges, and the auth-UI pages.

They now come through three subpath imports, #js-yaml, #semver and
#uipack-render, whose `require` variant reads each function from its package
the first time it is used, like @frontmcp/protocol's #client. The CommonJS
build keeps them external and ships both variants; the ESM and browser builds
resolve them at build time to the static variant, so those bundles import the
packages as before.

(cherry picked from commit b7ee831)
A stdio server initializes the scope's TransportService, and with it
TransportSSEAdapter, which defined RecreateableSSEServerTransport at startup.
Its base class reads POST bodies with raw-body and content-type, so a stdio
server loaded raw-body, content-type, iconv-lite, http-errors and their
dependencies (16 files) that it never uses.

TransportSSEAdapter now imports the transport as a type and loads it with
loadSseTransport(), which TransportService awaits where it creates the
LocalTransporter of an SSE session, as it does for the Streamable HTTP
transport since #924.

(cherry picked from commit f13b8af)
@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: agentfront/frontmcp/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 7e338459-0e0c-4200-b5f8-89f68f6b307e
📥 Commits

Reviewing files that changed from the base of the PR and between 691f254 and 34c9c89.

📒 Files selected for processing: 26
  • eslint.config.mjs
  • jest.imports-mapper.js
  • libs/sdk/package.json
  • libs/sdk/project.json
  • libs/sdk/src/auth/auth-ui/auth-ui.render.ts
  • libs/sdk/src/builtin/config/providers/config-loader.ts
  • libs/sdk/src/direct/direct-client.ts
  • libs/sdk/src/esm-loader/semver.utils.ts
  • libs/sdk/src/skill/sep-2640/sep-2640.builders.ts
  • libs/sdk/src/skill/skill-md-parser.ts
  • libs/sdk/src/third-party/__tests__/lazy-js-yaml.spec.ts
  • libs/sdk/src/third-party/__tests__/lazy-semver.spec.ts
  • libs/sdk/src/third-party/__tests__/lazy-uipack-render.spec.ts
  • libs/sdk/src/third-party/js-yaml.ts
  • libs/sdk/src/third-party/lazy-js-yaml.ts
  • libs/sdk/src/third-party/lazy-semver.ts
  • libs/sdk/src/third-party/lazy-uipack-render.ts
  • libs/sdk/src/third-party/semver.ts
  • libs/sdk/src/third-party/uipack-render.ts
  • libs/sdk/src/transport/__tests__/transport.registry.spec.ts
  • libs/sdk/src/transport/adapters/__tests__/transport.sse.adapter.load.spec.ts
  • libs/sdk/src/transport/adapters/transport.sse.adapter.ts
  • libs/sdk/src/transport/in-memory-server.ts
  • libs/sdk/src/transport/transport.registry.ts
  • libs/sdk/src/transport/web-standard-mcp.ts
  • tsconfig.base.json

Included review availability: This review used your included allowance. 2 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour.

📝 Walkthrough

The SDK adds internal aliases and ESM/CommonJS entry points for YAML, semver, and UI pack rendering. It replaces several runtime protocol import fallbacks with static imports and loads the SSE transport adapter on demand.

Changes: SDK Module Loading

Layer / File(s) Summary
Module aliases and build mappings
eslint.config.mjs, jest.imports-mapper.js, libs/sdk/package.json, libs/sdk/project.json, tsconfig.base.json
The project adds #js-yaml, #semver, and #uipack-render mappings for TypeScript, Jest, package imports, and the CommonJS build. The lint allowlist now includes #uipack-render.
Third-party exports and SDK imports
libs/sdk/src/third-party/*, libs/sdk/src/third-party/__tests__/*, libs/sdk/src/auth/auth-ui/auth-ui.render.ts, libs/sdk/src/builtin/config/providers/config-loader.ts, libs/sdk/src/esm-loader/semver.utils.ts, libs/sdk/src/skill/sep-2640/sep-2640.builders.ts, libs/sdk/src/skill/skill-md-parser.ts
The SDK adds eager and lazy exports for YAML, semver, and UI pack rendering. Related imports use the new aliases. Tests cover lazy loading and export parity.
Static protocol imports
libs/sdk/src/direct/direct-client.ts, libs/sdk/src/transport/in-memory-server.ts, libs/sdk/src/transport/web-standard-mcp.ts
These modules replace runtime ESM/CommonJS fallback imports with static protocol imports. The direct client also passes clientTransport to connect without an any cast.
On-demand SSE transport loading
libs/sdk/src/transport/adapters/transport.sse.adapter.ts, libs/sdk/src/transport/adapters/__tests__/transport.sse.adapter.load.spec.ts, libs/sdk/src/transport/transport.registry.ts, libs/sdk/src/transport/__tests__/transport.registry.spec.ts
The registry loads the SSE adapter for SSE transports. The adapter dynamically imports and caches the transport class. Tests cover loading behavior and transport creation.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Refactor

Sequence Diagram(s)

sequenceDiagram
  participant TransportService
  participant loadSseTransport
  participant RecreateableSSEServerTransport
  participant TransportSSEAdapter
  TransportService->>loadSseTransport: Load adapter for an SSE transport
  loadSseTransport->>RecreateableSSEServerTransport: Dynamically import and cache class
  TransportService->>TransportSSEAdapter: Create transport after loading
  TransportSSEAdapter->>RecreateableSSEServerTransport: Instantiate with transport arguments
Loading
Merge Risk: ⚪ Minimal · up to 34c9c

This change defers loading of several dependencies and reuses the already loaded protocol module to cut startup cost. No concrete merge-blocking risk remains after review.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 65.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 23 files. (3 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly identifies the startup-loading performance change and references the three cherry-picked source PRs.
Description check Passed The description explains the cherry-pick purpose, lists the three changes, reports benchmark results, and documents test status. It does not use the template headings, but it contains the required rat…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description explains the cherry-pick purpose, lists the three changes, reports benchmark results, and documents test status. It does not use the template headings, but it contains the required rationale, change summary, and validation information.

Full details: Docstring Coverage

Explanation

Docstring coverage is 60.00% which is insufficient. The required threshold is 65.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 23 files. (3 skipped: 3 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@github-actions

Copy link
Copy Markdown
Contributor

Performance Test Results

Status: ✅ All tests passed

Summary

Project Tests Passed Warnings Failed Leaks
✅ demo-e2e-agents 4 4 0 0 0
✅ demo-e2e-cache 11 11 0 0 0
✅ demo-e2e-codecall 4 4 0 0 0
✅ demo-e2e-config 4 4 0 0 0
✅ demo-e2e-direct 3 3 0 0 0
✅ demo-e2e-elicitation 1 1 0 0 0
✅ demo-e2e-errors 4 4 0 0 0
✅ demo-e2e-hooks 3 3 0 0 0
✅ demo-e2e-multiapp 4 4 0 0 0
✅ demo-e2e-notifications 3 3 0 0 0
✅ demo-e2e-openapi 2 2 0 0 0
✅ demo-e2e-providers 4 4 0 0 0
✅ demo-e2e-public 4 4 0 0 0
✅ demo-e2e-redis 15 15 0 0 0
✅ demo-e2e-remember 4 4 0 0 0
✅ demo-e2e-remote 5 5 0 0 0
✅ demo-e2e-serverless 2 2 0 0 0
✅ demo-e2e-skills 15 15 0 0 0
✅ demo-e2e-standalone 2 2 0 0 0
✅ demo-e2e-transport-recreation 3 3 0 0 0
✅ demo-e2e-ui 4 4 0 0 0

Total: 101 tests across 21 projects

📊 View full report in workflow run


Generated at: 2026-10-21T16:29:52.677Z
Commit: 1fa4be64

@alexmercerpo
alexmercerpo merged commit 7e69f1d into main Oct 21, 2026
45 checks passed
@alexmercerpo
alexmercerpo deleted the perf/1.10.x-934-to-937-cherry-pick-main branch October 21, 2026 16:40
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