Skip to content

Commit 53d2e76

Browse files
Copilotf
andcommitted
Add streamable HTTP transport support
Co-authored-by: f <[email protected]>
1 parent c95e12f commit 53d2e76

File tree

4 files changed

+69
-5
lines changed

4 files changed

+69
-5
lines changed

cmd/mcptools/commands/new.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const (
1515
sdkTypeScript = "ts"
1616
transportStdio = "stdio"
1717
transportSSE = "sse"
18+
transportHTTP = "http"
1819
)
1920

2021
// NewCmd returns a new 'new' command for scaffolding MCP projects.
@@ -30,7 +31,7 @@ func NewCmd() *cobra.Command {
3031
Examples:
3132
mcp new tool:hello_world resource:file prompt:hello
3233
mcp new tool:hello_world --sdk=ts
33-
mcp new tool:hello_world --transport=stdio|sse`,
34+
mcp new tool:hello_world --transport=stdio|sse|http`,
3435
SilenceUsage: true,
3536
RunE: func(_ *cobra.Command, args []string) error {
3637
if len(args) == 0 {
@@ -48,8 +49,8 @@ Examples:
4849
}
4950

5051
// Validate transport flag
51-
if transportFlag != "" && transportFlag != transportStdio && transportFlag != transportSSE {
52-
return fmt.Errorf("unsupported transport: %s (supported options: stdio, sse)", transportFlag)
52+
if transportFlag != "" && transportFlag != transportStdio && transportFlag != transportSSE && transportFlag != transportHTTP {
53+
return fmt.Errorf("unsupported transport: %s (supported options: stdio, sse, http)", transportFlag)
5354
}
5455

5556
// Set default transport if not specified
@@ -84,7 +85,7 @@ Examples:
8485

8586
// Add flags
8687
cmd.Flags().StringVar(&sdkFlag, "sdk", "", "Specify the SDK to use (ts)")
87-
cmd.Flags().StringVar(&transportFlag, "transport", "", "Specify the transport to use (stdio, sse)")
88+
cmd.Flags().StringVar(&transportFlag, "transport", "", "Specify the transport to use (stdio, sse, http)")
8889

8990
return cmd
9091
}
@@ -128,6 +129,8 @@ func createProjectStructure(components map[string]string, sdk, transport string)
128129
var serverTemplateFile string
129130
if transport == transportSSE {
130131
serverTemplateFile = filepath.Join(templatesDir, "server_sse.ts")
132+
} else if transport == transportHTTP {
133+
serverTemplateFile = filepath.Join(templatesDir, "server_http.ts")
131134
} else {
132135
// Use stdio by default
133136
serverTemplateFile = filepath.Join(templatesDir, "server_stdio.ts")

cmd/mcptools/commands/root.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const (
1616
FlagHelp = "--help"
1717
FlagHelpShort = "-h"
1818
FlagServerLogs = "--server-logs"
19+
FlagTransport = "--transport"
1920
)
2021

2122
// entity types.
@@ -34,6 +35,9 @@ var (
3435
ParamsString string
3536
// ShowServerLogs is a flag to show server logs.
3637
ShowServerLogs bool
38+
// TransportOption is the transport option for HTTP connections, valid values are "sse" and "http".
39+
// Default is "http" (streamable HTTP).
40+
TransportOption = "http"
3741
)
3842

3943
// RootCmd creates the root command.
@@ -48,6 +52,7 @@ It allows you to discover and call tools, list resources, and interact with MCP-
4852
cmd.PersistentFlags().StringVarP(&FormatOption, "format", "f", "table", "Output format (table, json, pretty)")
4953
cmd.PersistentFlags().
5054
StringVarP(&ParamsString, "params", "p", "{}", "JSON string of parameters to pass to the tool (for call command)")
55+
cmd.PersistentFlags().StringVar(&TransportOption, "transport", "http", "HTTP transport type (http, sse)")
5156

5257
return cmd
5358
}

cmd/mcptools/commands/utils.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,17 @@ var CreateClientFunc = func(args []string, _ ...client.ClientOption) (*client.Cl
4747
var err error
4848

4949
if len(args) == 1 && IsHTTP(args[0]) {
50-
c, err = client.NewSSEMCPClient(args[0])
50+
// Validate transport option for HTTP URLs
51+
if TransportOption != "http" && TransportOption != "sse" {
52+
return nil, fmt.Errorf("invalid transport option: %s (supported: http, sse)", TransportOption)
53+
}
54+
55+
if TransportOption == "sse" {
56+
c, err = client.NewSSEMCPClient(args[0])
57+
} else {
58+
// Default to streamable HTTP
59+
c, err = client.NewStreamableHttpClient(args[0])
60+
}
5161
if err != nil {
5262
return nil, err
5363
}
@@ -91,6 +101,7 @@ var CreateClientFunc = func(args []string, _ ...client.ClientOption) (*client.Cl
91101

92102
// ProcessFlags processes command line flags, sets the format option, and returns the remaining
93103
// arguments. Supported format options: json, pretty, and table.
104+
// Supported transport options: http and sse.
94105
//
95106
// For example, if the input arguments are ["tools", "--format", "pretty", "npx", "-y",
96107
// "@modelcontextprotocol/server-filesystem", "~"], it would return ["npx", "-y",
@@ -104,6 +115,9 @@ func ProcessFlags(args []string) []string {
104115
case (args[i] == FlagFormat || args[i] == FlagFormatShort) && i+1 < len(args):
105116
FormatOption = args[i+1]
106117
i += 2
118+
case args[i] == FlagTransport && i+1 < len(args):
119+
TransportOption = args[i+1]
120+
i += 2
107121
case args[i] == FlagServerLogs:
108122
ShowServerLogs = true
109123
i++

templates/ts/server_http.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
3+
import express from "express";
4+
import { z } from "zod";
5+
import { randomUUID } from "crypto";
6+
7+
// Initialize server
8+
const server = new McpServer({
9+
name: "PROJECT_NAME",
10+
version: "1.0.0"
11+
});
12+
13+
// Initialize components here
14+
// COMPONENT_INITIALIZATION
15+
16+
// Setup Express app
17+
const app = express();
18+
19+
// Enable JSON parsing for request bodies
20+
app.use(express.json());
21+
22+
// Create a streamable HTTP transport
23+
const transport = new StreamableHTTPServerTransport({
24+
// Enable session management with auto-generated UUIDs
25+
sessionIdGenerator: () => randomUUID(),
26+
// Optional: Enable JSON response mode for simple request/response
27+
enableJsonResponse: false
28+
});
29+
30+
// Handle all HTTP methods on the root path
31+
app.all("/", async (req, res) => {
32+
await transport.handleRequest(req, res, req.body);
33+
});
34+
35+
// Connect the server to the transport
36+
await server.connect(transport);
37+
38+
// Start HTTP server
39+
const port = 3000;
40+
app.listen(port, () => {
41+
console.log(`MCP server running on http://localhost:${port}`);
42+
});

0 commit comments

Comments
 (0)