feat: make HTTP streamable stateless mode configurable via FASTMCP_STATELESS env#212
Open
SpongeRobert wants to merge 1 commit intofirecrawl:mainfrom
Open
feat: make HTTP streamable stateless mode configurable via FASTMCP_STATELESS env#212SpongeRobert wants to merge 1 commit intofirecrawl:mainfrom
SpongeRobert wants to merge 1 commit intofirecrawl:mainfrom
Conversation
…LESS Follows the env var convention already used by `firecrawl-fastmcp` / `punkpeye/fastmcp`. Default behavior is preserved (`stateless: true`). ## Motivation MCP clients built on the official `modelcontextprotocol/go-sdk` (`StreamableClientTransport`) expect stateful session semantics. When connecting to a firecrawl-mcp instance running in `HTTP_STREAMABLE_SERVER` mode, the client receives a `Mcp-Session-Id` header in the initialize response, passes it back on subsequent requests — but because the server is stateless, it replies "session not found" and the connection fails. This prevents self-hosted Firecrawl integrations with Go-based MCP clients (e.g. picoclaw / internal AI agents) from working out of the box. Downstream users are forced to patch the compiled JS. ## Change `src/index.ts:1259`: `stateless: true` → `stateless: process.env.FASTMCP_STATELESS !== 'false'` Plus a short README note explaining when to set `FASTMCP_STATELESS=false`. Backward compatible — default remains stateless. Stateful mode is opt-in. ## Testing - Built locally (`pnpm run build`) — compiled JS contains the expected `FASTMCP_STATELESS !== 'false'` expression. - Runtime with `FASTMCP_STATELESS=false`: server log changes from "Starting server in stateless mode" to "server is running on HTTP Stream" (FastMCP's stateful path). - Integration with `modelcontextprotocol/go-sdk` v1.4.1 `StreamableClientTransport`: client successfully connects, lists tools (12), and calls scrape/crawl tools end-to-end after this change.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes the HTTP streamable
statelessoption configurable viaFASTMCP_STATELESSenv var, matching the convention already used by the underlyingfirecrawl-fastmcp/punkpeye/fastmcpframework. Default behavior is preserved (stateless: true).Motivation
MCP clients built on the official
modelcontextprotocol/go-sdk(StreamableClientTransport) expect stateful session semantics. When connecting to a firecrawl-mcp instance running inHTTP_STREAMABLE_SERVERmode, the client receives aMcp-Session-Idheader in the initialize response, then passes it back on subsequent requests — but because the server is stateless, it repliessession not foundand the connection fails.This prevents self-hosted Firecrawl integrations with Go-based MCP clients (e.g. picoclaw-based agents) from working out of the box. Downstream users are currently forced to patch the compiled JS to work around it.
Change
src/index.ts:1259— single-line change:Plus a short README note explaining when to set
FASTMCP_STATELESS=false.Backward compatible — default remains
true(stateless). Stateful mode is opt-in viaFASTMCP_STATELESS=false.Testing
pnpm install --frozen-lockfile && pnpm run build); compiled JS contains the expectedFASTMCP_STATELESS !== 'false'expression.FASTMCP_STATELESS=false, the server log changes fromStarting server in stateless modetoserver is running on HTTP Stream(FastMCP's stateful path).modelcontextprotocol/go-sdkv1.4.1StreamableClientTransport: client successfully connects, lists all tools (12), and callsfirecrawl_scrape/firecrawl_crawl/firecrawl_search/firecrawl_mapend-to-end after applying this change.Alternatives considered
FASTMCP_STATELESSenv: chosen — matches the documented FastMCP convention (see punkpeye/fastmcp README § Stateless Mode), backward compatible, no breaking changes.