Skip to content
This repository was archived by the owner on May 16, 2025. It is now read-only.

Conversation

@leo237
Copy link
Contributor

@leo237 leo237 commented Apr 22, 2025

Description

Adds support for Streamable HTTP. Related to #59

Fixes # (issue)

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)

How Has This Been Tested?

  1. Tests are added
  2. Manually tested with a Streamable HTTP server

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

@benjamincburns benjamincburns changed the title Feature/streamable http feat: support StreamableHttpTransport May 6, 2025
@benjamincburns benjamincburns changed the title feat: support StreamableHttpTransport feat: support StreamableHTTPTransport May 6, 2025
@benjamincburns benjamincburns changed the title feat: support StreamableHTTPTransport feat: support StreamableHTTPClientTransport May 6, 2025
@benjamincburns
Copy link
Contributor

Per the MCP spec, the streamable HTTP transport is meant to replace the SSE transport. Per their backward compatibility guide, clients should attempt to connect to URLs as though they are streamable HTTP first, and then fall back to SSE.

Doing this would fix another problem. Prior to this change the transport type can be inferred from the structure of the config entry. That is, the transport key of the config was optional, and should remain so. Supporting this fallback behavior would allow for that to continue.

@benjamincburns
Copy link
Contributor

I pushed some updates for the above feedback, but I only had time last night to rework some of the tests. IIRC there are 3 tests still failing. We should also make updates to the README & examples to drop the transport field (it's optional and not necessary in 99% of cases).

@benjamincburns benjamincburns force-pushed the feature/streamable-http branch from 7b94c69 to b33a2de Compare May 12, 2025 17:53
@benjamincburns
Copy link
Contributor

benjamincburns commented May 12, 2025

The build is green, however I added a new example to capture the Streamable HTTPs w/ fallback to SSE behavior, and it's not running successfully on the default (Streamable HTTP) case. Seems to work fine for the SSE case, however.

@Dandelion-F
Copy link

Dandelion-F commented May 13, 2025

When would this PR be merged? I'm in an urgent need of it. 🙏

@benjamincburns
Copy link
Contributor

OK, I think this is ready to go, but because I've mostly rewritten the original PR I need to request an internal review from another colleague.

@benjamincburns benjamincburns force-pushed the feature/streamable-http branch from 2002b2e to 9be061b Compare May 13, 2025 18:27
@benjamincburns benjamincburns force-pushed the feature/streamable-http branch from 9be061b to 0f42f28 Compare May 13, 2025 18:35
Comment on lines +221 to +222
| `prefixToolNameWithServerName` | boolean | `true` | If true, prefixes all tool names with the server name (e.g., `serverName__toolName`) |
| `additionalToolNamePrefix` | string | `mcp` | Additional prefix to add to tool names (e.g., `prefix__serverName__toolName`) |
Copy link
Contributor

Choose a reason for hiding this comment

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

These defaults weren't actually changed in this PR (see checks in tests to verify) - just updated in README and config schema to reflect the actual defaults

Comment on lines +351 to +353
const conf = client.config;
expect(conf.additionalToolNamePrefix).toBe("mcp");
expect(conf.prefixToolNameWithServerName).toBe(true);
Copy link
Contributor

Choose a reason for hiding this comment

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

Added this during test troubleshooting because the defaults reverted due to me accidentally setting default(...).optional() in the zod schema updates (needs to be .optional().default(...) else the defaults aren't applied during parsing).

@@ -0,0 +1,173 @@
import express from "express";
Copy link
Contributor

Choose a reason for hiding this comment

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

Added this file for manual testing & for use via the added example because we don't yet have an integration suite.

Comment on lines +652 to +657
if (code == null) {
const m = streamableError.message.match(/\(HTTP (\d\d\d)\)/);
if (m && m.length > 1) {
code = parseInt(m[1], 10);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This is probably the grossest part - I needed this during early testing because for some reason the code property of the error wasn't being set. It appears that it is being set now, but I decided to leave it in for reliability.

@benjamincburns
Copy link
Contributor

When would this PR be merged? I'm in an urgent need of it. 🙏

@Dandelion-F will depend on code review - if all goes well it could be merged/released within a few hours.

@benjamincburns benjamincburns force-pushed the feature/streamable-http branch from 6b352ee to 84f0f70 Compare May 13, 2025 19:28
url: "http://localhost:8000/sse",
},
server3: {
transport: "streamable",
Copy link
Contributor

Choose a reason for hiding this comment

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

(nit) why "streamable" and not "streamable-http" or "streamable_http"?

Copy link
Contributor

Choose a reason for hiding this comment

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

I didn't decide the key - honestly I think http is better since this option should be used for all HTTP endpoints (including SSE). Will change to that.

Copy link
Contributor

Choose a reason for hiding this comment

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

Changed - will likely need to add strings to this union as other popular client configs come out and decide they want to use some other key, however.

@benjamincburns benjamincburns merged commit 68f130e into langchain-ai:main May 13, 2025
@benjamincburns
Copy link
Contributor

(code was approved internally by @vbarda)

Thanks for kicking this off @leo237!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants