Skip to content

Provide a more flexible transport #98

Closed

Description

@xtuc

The client / server architecture, as described by https://modelcontextprotocol.io/docs/concepts/architecture#overview, doesn't fit the serverless use-case (talking for Cloudflare's Workers AI), in which: either the client is running on a server or both client/server are running on the server.

Would it be possible to add a new transport layer that's essentially a JS API, not involving any IO?

Moreover, MCP server are hardcoding a transport: https://github.com/modelcontextprotocol/servers/blob/df0b733c7d086432de14504863c9c0288fc36686/src/gitlab/index.ts#L526-L527, which makes them not easily portable.

Activity

  1. jspahrsummers commented on Dec 7, 2024

    @jspahrsummers
    Member

    I think this issue is describing three different things:

    1. Agreed that the nature of the protocol is currently a poor fit for serverless deployments. I started State, and long-lived vs. short-lived connections #102 to discuss this in more detail.
    2. Transports are very easily written, so yes, it's possible to create a transport that runs whatever code you want instead of doing I/O.
    3. It's a good point that perhaps servers don't need to hardcode transports! Would welcome any thoughts on how to generalize this without dictating too much of how the server itself is implemented.
  2. added a commit that references this issue on Mar 12, 2025
  3. lirc571 commented on May 8, 2025

    @lirc571

    Agreed that server sdks can be refactored so it's possible to "import" a server and without spinning up an HTTP server or a dedicated process. Not sure if it fits in the protocol spec though. I see two possible ways to implement this:

    1. implement a new transport based on raw input/output streams (e.g. ReadableStream<Uint8Array> + WritableStream<Uint8Array>) and use json-rpc over it.
    2. make individual capabilities callable by the other side. A rough example would be:
    import createServerA from "server-a";
    
    const serverA = serverA({
      transport: null,
      clientParams: {
        capabilities: {
          sampling: ({
            messages: ...,
            modelPreferences: ...,
            ...,
          }): {
            result: AsyncIterable<string> & ReadableStream<string>,
            model: string,
            stopReason: string,
          } => {...},
        },
      },
    });
    
    const res = serverA.capabilities().tools.blahblah({ param: ... });

    The first option may be added to the protocol spec but it's quite ugly...
    The second option is not really a "protocol" and is language-specific so it may only fit in the SDK doc...

  4. localden commented on Dec 4, 2025

    @localden
    Contributor

    Closing this issue as it had not had any discussion for a while. If this is something that warrants additional discussion, let's refer to the #transports-wg channel in Discord.

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 request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions