Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @copilotkit/pathfinder

## 1.13.1

### Patch Changes

- **Streamable HTTP JSON Response**: Enabled `enableJsonResponse` on the Streamable HTTP MCP transport for compatibility with clients that cannot parse SSE-formatted responses (notably OpenAI Codex CLI). Fully MCP spec-compliant — the spec allows servers to return either `application/json` or `text/event-stream` for single-message responses

## 1.13.0

### Minor Changes
Expand Down
26 changes: 26 additions & 0 deletions docs/clients/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,32 @@ <h2>Verifying the Connection</h2>

<p>Try asking your agent to run a simple command like <code>find / -name "*.md" | head -5</code> to verify the bash tool is working, or ask a question about your docs to test semantic search.</p>

<h2>Known Concerns</h2>

<h3>SSE Parsing Bugs in Some MCP Clients</h3>

<p>Some MCP clients have bugs handling SSE-formatted responses from Streamable HTTP endpoints. This can cause initialization failures, connection drops, or cryptic errors when connecting to Pathfinder's <code>/mcp</code> endpoint.</p>

<p>The most notable example is <strong>OpenAI Codex CLI</strong>, which uses the <code>rmcp</code> Rust SDK internally. That SDK's SSE parser does not correctly handle the <code>text/event-stream</code> content type that MCP servers typically return for single-message exchanges over Streamable HTTP.</p>

<h3>Pathfinder's Mitigation</h3>

<p>Pathfinder enables <code>enableJsonResponse: true</code> on its Streamable HTTP transport. This causes the server to return <code>Content-Type: application/json</code> instead of SSE-wrapped responses for single-message exchanges (i.e., requests where the server sends exactly one response and does not need to stream). This is fully compliant with the MCP specification, which states that servers MAY return either format for non-streaming responses.</p>

<p>This setting works around the client-side bugs transparently — no configuration needed on your end.</p>

<h3>stdio Bridge Workaround</h3>

<p>If you still encounter connection issues with a particular client, you can use <a href="https://github.com/anthropics/mcp-remote">mcp-remote</a> as a stdio bridge. This converts the HTTP transport into a local stdio pipe, which every MCP client supports reliably:</p>

<div class="code-block"><span class="comment"># Codex CLI — ~/.codex/config.toml</span>

[<span class="key">mcp_servers.pathfinder</span>]
<span class="key">command</span> = <span class="value">"npx"</span>
<span class="key">args</span> = [<span class="value">"mcp-remote@latest"</span>, <span class="value">"--http"</span>, <span class="value">"--allow-http"</span>, <span class="value">"https://mcp.copilotkit.ai/mcp"</span>]</div>

<p>Replace the URL with your own Pathfinder instance's <code>/mcp</code> endpoint. The <code>--http</code> flag tells mcp-remote to use Streamable HTTP (not SSE), and <code>--allow-http</code> permits non-TLS connections if you're running locally.</p>

</main>
<aside class="page-toc" id="page-toc"></aside>
</div>
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@copilotkit/pathfinder",
"version": "1.13.0",
"version": "1.13.1",
"description": "The knowledge server for AI agents — index docs, code, Notion, Slack, and Discord into searchable, agent-accessible knowledge via MCP. Supports OpenAI, Ollama, and local transformers.js embeddings.",
"type": "module",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const program = new Command();
program
.name("pathfinder")
.description("The knowledge server for AI agents")
.version("1.13.0");
.version("1.13.1");

program
.command("init")
Expand Down
1 change: 1 addition & 0 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,7 @@ app.post("/mcp", bearerMiddleware, async (req: Request, res: Response) => {
const initOutcome: { rejected: boolean } = { rejected: false };
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => preSid,
enableJsonResponse: true,
onsessioninitialized: (sid) => {
// Registration moved here intentionally — we can't populate
// transports[sid] before the transport object exists, and the SDK
Expand Down
Loading