Skip to content

Add end-to-end tests and improve documentation for stdio transport#482

Open
frontegg-david wants to merge 3 commits into
mainfrom
sdkenhancements
Open

Add end-to-end tests and improve documentation for stdio transport#482
frontegg-david wants to merge 3 commits into
mainfrom
sdkenhancements

Conversation

@frontegg-david
Copy link
Copy Markdown
Contributor

@frontegg-david frontegg-david commented Jun 5, 2026

Summary by CodeRabbit

  • New Features

    • Added stdio transport support, allowing servers to run without binding TCP ports—enabling multiple instances on the same machine without port conflicts.
    • CLI bundles now support --stdio mode for direct stdin/stdout communication.
  • Documentation

    • Enhanced deployment guides with clarified stdio configuration and safest setup patterns.
    • Expanded skill catalog descriptions across auth, config, testing, observability, and deployment topics.
  • Tests

    • Added end-to-end test coverage for stdio transport functionality and HTTP port validation.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 5, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR extends FrontMCP with stdio-only transport support, allowing servers to operate over stdin/stdout without binding HTTP/TCP ports. The decorator gains a FRONTMCP_STDIO flag to route execution, runStdio() accepts both config objects and @FrontMcp-decorated classes, and comprehensive E2E tests and documentation guide deployment patterns.

Changes

Stdio Transport with Decorated Class Support

Layer / File(s) Summary
TCP port probe testing utility
libs/testing/src/raw-client/port-probe.ts, libs/testing/src/raw-client/index.ts, libs/testing/src/index.ts
New isTcpPortListening(port, host?, timeoutMs?) function probes TCP connectivity with socket-level fallback handling; re-exported through testing module barrel for E2E assertions.
FrontMcpInstance.runStdio signature and config resolution
libs/sdk/src/front-mcp/front-mcp.ts, libs/sdk/src/index.ts, libs/sdk/src/front-mcp/__tests__/run-stdio-input.spec.ts
New ConfigOrServerClass type allows runStdio() to accept either @FrontMcp-decorated classes or plain config objects. resolveConfigInput() helper extracts decorator metadata or passes through configs; throws InternalMcpError when metadata is missing. HTTP binding is explicitly disabled (http: undefined, serve: false) in stdio mode.
@FrontMcp decorator stdio mode routing
libs/sdk/src/common/decorators/front-mcp.decorator.ts, libs/sdk/src/common/decorators/__tests__/front-mcp-stdio.decorator.spec.ts
Decorator checks FRONTMCP_STDIO environment flag and routes to runStdio(metadata) when enabled and serve: true, exiting with code 1 on failure. Routing occurs before existing serverless/HTTP bootstrap logic. Test suite verifies routing decisions across stdio/default/disabled/metadata-only modes.
E2E test suites and demo entrypoints
apps/e2e/demo-e2e-stdio-transport/src/stdio-class-entrypoint.ts, apps/e2e/demo-e2e-cli-exec/e2e/cli-stdio.e2e.spec.ts, apps/e2e/demo-e2e-stdio-transport/e2e/stdio-no-http-port.e2e.spec.ts
Stdio entrypoint guards decorator side effects using FRONTMCP_SCHEMA_EXTRACT and invokes FrontMcpInstance.runStdio(DecoratedClass). Two E2E suites verify MCP tool availability and confirm HTTP/TCP ports remain unbound across CLI and class-based stdio execution paths.
SDK reference documentation
docs/frontmcp/sdk-reference/core/frontmcp-instance.mdx, docs/frontmcp/sdk-reference/decorators/frontmcp.mdx
Documents new runStdio(optionsOrClass) signature, warns about decorator import-time HTTP auto-start unless FRONTMCP_STDIO=1 is set, clarifies safe setup patterns (config-only modules, dedicated stdio entrypoints), and updates Claude Desktop integration examples to show dist/stdio.js and config-only server modules.
Deployment and client integration documentation
docs/frontmcp/deployment/mcp-clients.mdx, libs/skills/catalog/frontmcp-deployment/references/mcp-client-integration.md
Clarifies that stdio mode disables HTTP/TCP binding, avoiding port conflicts. Documents two approaches: CLI bundle with --stdio flag, and --target node runner with FRONTMCP_STDIO=1. Adds warnings against running raw server modules with --stdio.
Skill catalog description updates
libs/skills/catalog/**/SKILL.md, libs/skills/catalog/skills-manifest.json
Expanded descriptions for 12 skills to more precisely enumerate scope, use cases, and deliverables. Updated frontmatter for auth-ui, authorities, channels, config, deployment, development, extensibility, guides, observability, production-readiness, setup, and testing skills to clarify technical boundaries, integration patterns, and coverage areas.

Sequence Diagram(s)

sequenceDiagram
  participant ClientCode as Client Code
  participant runStdio as runStdio(input)
  participant resolveInput as resolveConfigInput
  participant getDecor as getDecoratorConfig
  participant StdioServer as Stdio Server
  
  ClientCode->>runStdio: pass `@FrontMcp` class or config
  runStdio->>resolveInput: resolve input
  resolveInput->>getDecor: extract metadata
  alt Has `@FrontMcp` metadata
    getDecor->>resolveInput: return config
    resolveInput->>runStdio: resolved config
  else Missing metadata
    getDecor->>resolveInput: throw InternalMcpError
    resolveInput-->>ClientCode: error
  end
  runStdio->>runStdio: set FRONTMCP_STDIO=1
  runStdio->>runStdio: disable HTTP (http:undefined)
  runStdio->>StdioServer: start with resolved config
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

  • agentfront/frontmcp#448: Directly addresses the feature request for stdio transport with decorator support, including FrontMcpInstance.runStdio accepting decorated classes and FRONTMCP_STDIO env flag handling.
  • agentfront/frontmcp#450: Resolves the mismatch by enabling FrontMcpInstance.runStdio to accept decorated server classes via resolveConfigInput and getDecoratorConfig.

Possibly related PRs

  • agentfront/frontmcp#481: Shares identical E2E test suites for stdio transport coverage (cli-stdio.e2e.spec.ts and stdio-no-http-port.e2e.spec.ts), port-probe utilities, and stdio entrypoint patterns.

Poem

🐰 A clever rabbit builds a tunnel through the code,
No ports need binding when stdio's the road,
Decorators and classes now hop side by side,
While E2E tests keep the promises verified!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 65.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main changes: adding end-to-end tests for stdio transport and improving related documentation.
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.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sdkenhancements
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch sdkenhancements

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

Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@libs/sdk/src/front-mcp/front-mcp.ts`:
- Around line 515-520: The stdio guard (stdioServing) is set to true before
initialization completes in runStdio(), causing retries to be ignored if startup
throws; change runStdio() so stdioServing is only set after successful
initialization or ensure you wrap initialization in try/catch and reset
stdioServing = false on any thrown error so a failed startup does not leave the
guard sticky (refer to runStdio() and the stdioServing variable and the
process.env['FRONTMCP_STDIO'] set-up).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6c11d076-7abc-4711-a81b-4fc723910dca

📥 Commits

Reviewing files that changed from the base of the PR and between de54865 and c2a5d54.

⛔ Files ignored due to path filters (2)
  • libs/cli/src/commands/build/exec/__tests__/runner-script.spec.ts is excluded by !**/build/**
  • libs/cli/src/commands/build/exec/runner-script.ts is excluded by !**/build/**
📒 Files selected for processing (28)
  • apps/e2e/demo-e2e-cli-exec/e2e/cli-stdio.e2e.spec.ts
  • apps/e2e/demo-e2e-stdio-transport/e2e/stdio-no-http-port.e2e.spec.ts
  • apps/e2e/demo-e2e-stdio-transport/src/stdio-class-entrypoint.ts
  • docs/frontmcp/deployment/mcp-clients.mdx
  • docs/frontmcp/sdk-reference/core/frontmcp-instance.mdx
  • docs/frontmcp/sdk-reference/decorators/frontmcp.mdx
  • libs/sdk/src/common/decorators/__tests__/front-mcp-stdio.decorator.spec.ts
  • libs/sdk/src/common/decorators/front-mcp.decorator.ts
  • libs/sdk/src/front-mcp/__tests__/run-stdio-input.spec.ts
  • libs/sdk/src/front-mcp/front-mcp.ts
  • libs/sdk/src/index.ts
  • libs/skills/catalog/frontmcp-auth-ui/SKILL.md
  • libs/skills/catalog/frontmcp-authorities/SKILL.md
  • libs/skills/catalog/frontmcp-channels/SKILL.md
  • libs/skills/catalog/frontmcp-config/SKILL.md
  • libs/skills/catalog/frontmcp-deployment/SKILL.md
  • libs/skills/catalog/frontmcp-deployment/references/mcp-client-integration.md
  • libs/skills/catalog/frontmcp-development/SKILL.md
  • libs/skills/catalog/frontmcp-extensibility/SKILL.md
  • libs/skills/catalog/frontmcp-guides/SKILL.md
  • libs/skills/catalog/frontmcp-observability/SKILL.md
  • libs/skills/catalog/frontmcp-production-readiness/SKILL.md
  • libs/skills/catalog/frontmcp-setup/SKILL.md
  • libs/skills/catalog/frontmcp-testing/SKILL.md
  • libs/skills/catalog/skills-manifest.json
  • libs/testing/src/index.ts
  • libs/testing/src/raw-client/index.ts
  • libs/testing/src/raw-client/port-probe.ts

Comment on lines +515 to +520
process.env['FRONTMCP_STDIO'] = '1';
if (stdioServing) {
console.error('[FrontMCP] runStdio() called more than once; ignoring the duplicate stdio connection.');
return;
}
stdioServing = true;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Reset the stdio guard on startup failure.

If initialization throws after setting stdioServing = true, subsequent runStdio() retries in the same process are permanently ignored. This makes recoverable startup failures sticky.

💡 Proposed fix
     process.env['FRONTMCP_STDIO'] = '1';
     if (stdioServing) {
       console.error('[FrontMCP] runStdio() called more than once; ignoring the duplicate stdio connection.');
       return;
     }
     stdioServing = true;
+    let startupSucceeded = false;
+    try {
 
     // Dynamically import to avoid bundling issues
     const { StdioServerTransport, McpServer } = await import('`@frontmcp/protocol`');
@@
     // Create stdio transport and connect
     const transport = new StdioServerTransport();
     await mcpServer.connect(transport);
+    startupSucceeded = true;
@@
     process.on('SIGINT', shutdownHandler);
     process.on('SIGTERM', shutdownHandler);
+    } catch (err) {
+      if (!startupSucceeded) stdioServing = false;
+      throw err;
+    }
   }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@libs/sdk/src/front-mcp/front-mcp.ts` around lines 515 - 520, The stdio guard
(stdioServing) is set to true before initialization completes in runStdio(),
causing retries to be ignored if startup throws; change runStdio() so
stdioServing is only set after successful initialization or ensure you wrap
initialization in try/catch and reset stdioServing = false on any thrown error
so a failed startup does not leave the guard sticky (refer to runStdio() and the
stdioServing variable and the process.env['FRONTMCP_STDIO'] set-up).

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.

1 participant