Skip to content

streamable server support #110

Closed
Closed

Description

@stallent

So now that we have the client working pretty well with the latest streamable http spec, i'm starting to work on upgrading our servers to support the server side of said spec.

I believe we may have a design issue, or maybe (hopefully) i'm missing something. The current design of the client->transport ->->-> a server works fine because typically a client app would have a single instance of a client (per server to connect to). That coupling becomes an issue on the server side, though. A server needs to allow more than one client to connect to it, and then any given client needs to be able to have multiple connections open within its session.

I've been studying the official TS streamable server code and of course while the syntax will be vastly different, i think i have a handle on the direction we need to go to do it properly. Basically, the server needs to allow multiple transports to be added (vs just one like it is currently). Each connection from a client would create a new transport which would be added to the server for that session. The GETs (which are all just one direction, server->client) would sit in there and all general messages would get written to all of them. The POSTs would also add their own transports to that session's server, but they would be shorter lived and let the server write to just that one transport, identified by the incoming id of the POST request. The spec explicitly states a client can have mutliple connections open so while we don't necessarily have to match the exact approach of the TS implementation, we must do something at least remotely similar.

Have you given this area much thought and if so, what are the thoughts? If not, I may go ahead and work on a POC in my fork

Activity

  1. mattt commented on May 9, 2025

    @mattt
    Contributor

    Hi @stallent. Thanks for giving this some thought.

    My mental model is that server transport will manage a pool of connections to one or more clients. The specific implementation of that transport will depend on which web framework you build on top of. But at a high-level, it should look similar to this Swift NIO example chat server, where you have a dictionary of channels by client ID.

    Does that track for you?

  2. stallent commented on May 9, 2025

    @stallent
    ContributorAuthor

    Partially. I think my struggles with that approach is you now have to maintain a fully functioning HTTP Server in front of it. Is that something that is within the scope or purview of this framework? I have a hunch devs wanting to deploy Swift servers are gonna prefer to go with the Vapor/Hummingbird frameworks where they already have all the things needed for HTTP (auth, sessions, persistence, middleware blah blah blah). Our are all containerized Hummingbird servers deployed to various clouds and k8 clusters

  3. mattt commented on May 9, 2025

    @mattt
    Contributor

    @stallent Yeah, I think that's correct. Instead of pulling in Vapor or Hummingbird into this SDK, you'd install a hummingbird-mcp or vapor-mcp package, which would provide a transport and APIs to mount MCP servers at a particular route.

  4. added
    enhancementNew feature or request
    questionFurther information is requested
    on May 9, 2025
  5. stallent commented on May 9, 2025

    @stallent
    ContributorAuthor

    Correct. In fact, creating a mcp-hummingbird is exactly what i was going to do. But i think we would require some changes to the Server regardless, though. Either the server needs allow multiple transports, or we need to be able to inject some state into the server (the latter would be so we can have a server/transport per connection, but don't wanna re-init each server). Several ways to skin that cat, so to speak, but i believe changes in the server class will be required regardless.

  6. stallent commented on May 9, 2025

    @stallent
    ContributorAuthor

    i'll proceed with a POC on a fork for us to look at and assess. Won't open a PR or anything.

  7. mattt commented on May 9, 2025

    @mattt
    Contributor

    @stallent Sounds good! Excited to see what you come up with.

  8. stallent commented on May 11, 2025

    @stallent
    ContributorAuthor

    making solid progress. should have POS POC up tomorrow at some point

  9. stallent commented on May 12, 2025

    @stallent
    ContributorAuthor

    Alright. I have something minimal to look at that supports the streamable server spec and hopefully spurs discussion.

    I used the official TS server and transport code as an implementation guide so my code somewhat mimics that. Its worth noting that the TS client puts a lot more of the mcp types and knowledge in the transport vs being exclusively in the server. To mimic that for the moment i had to add some redundant json decoding in the transport. Figured i'd start with that vs making larger changes to the Server class.

    The changes to the swift-sdk are in the streamable_server branch of my fork here:
    https://github.com/stallent/swift-sdk/tree/streamable_server

    with the specific changes being this commit:
    stallent@164ec48

    The Hummingbird part isn't yet in a re-usable package for and at the moment, but otherwise should illustrate full usage.
    https://github.com/stallent/hummingbird-mcp

  10. rosecoder commented on Jul 4, 2025

    @rosecoder

    Hi @stallent! Do you need any support completing this? I have some use cases for this so would love to help. Let me know what's left to do or any challenges I can look into!

  11. stallent commented on Jul 5, 2025

    @stallent
    ContributorAuthor

    Hello @rosecoder. Happy to you get something usable. We were somewhat waiting on feedback from Mattt before opening a PR since it requires some small architectural changes to his base to do it reasonably. I have been running off a variant of my fork for months and its working just fine, so if you want to work with me to polish up a HummingbirdMCP package based on my fork would be very happy to do so.

  12. johnmorrell commented on Jul 24, 2025

    @johnmorrell

    @stallent thanks for your work on this we are looking into building an Swift MCP Server and currently use Hummingbird for our APIs so this would be an ideal solution.

  13. stallent commented on Jul 25, 2025

    @stallent
    ContributorAuthor

    @johnmorrell happy to help as needed.

  14. johnmorrell commented on Jul 25, 2025

    @johnmorrell

    Thanks @stallent I was able to get a POC up and running on AWS Lambda and integrated in to MS Copilot. The main issue I hit which I think relates more to Lambda was with the use of consumeWithInboundCloseHandler which was working locally but crashing when run in Lambda:

    https://github.com/stallent/hummingbird-mcp/blob/eedf2f19056c9fbe643a5d342df3e66258723d55/Sources/App/StreamableMCPController.swift#L89

    I was able to get it running replacing this with withTaskCancellationHandler but not sure on the implications of this.

  15. ronaldmannak commented on Sep 16, 2025

    @ronaldmannak

    This looks great, but the origin is now many commits ahead. @mattt, is there a chance we can merge the streaming changes before the forks diverge any further?

  16. stallent commented on Sep 16, 2025

    @stallent
    ContributorAuthor

    @ronaldmannak i can at least get my branch sync'd up and verified tomorrow. Further improvements are close to bubbling up to the top of my prio list anyway/

  17. ronaldmannak commented on Sep 16, 2025

    @ronaldmannak

    @stallent no rush, I've manually merged and synced the two and everything seems to be working. It would just be a bit easier if it was a single repo :) Thanks for the great work!

  18. sebsto commented on Oct 5, 2025

    @sebsto
    Contributor

    @mattt what is missing to merge @stallent work in the project ? Let us know if there are any blocker that we can help with

  19. stallent commented on Oct 10, 2025

    @stallent
    ContributorAuthor

    @ronaldmannak @sebsto fwiw i sync'd up my fork of this repo just to ensure it was the latest and still worked. I also fixed a tiny issue in my hummingbird example where the latest mcp inspector from anthro complains if the server says it supports logging, but doesn't respond to the "logging/setLevel" method. Haven't looked into supporting that so for the moment just return nil for logging.

  20. ronaldmannak commented on Oct 10, 2025

    @ronaldmannak

    @stallent that's great. Thanks!

  21. DePasqualeOrg commented on Jan 4, 2026

    @DePasqualeOrg

    I've implemented this functionality in my PR #175. I'd love to hear your feedback if you're able to test it.

  22. stallent commented on Feb 25, 2026

    @stallent
    ContributorAuthor

    Closing as we have a path now!

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestquestionFurther information is requested

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions