Skip to content

Commit 95fb4e3

Browse files
authored
Merge pull request #3 from quantstruct/heartbeat
add heartbeat interval for GET requests to MCP server
2 parents 58e4b5e + 1fc20c6 commit 95fb4e3

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

cmd/github-mcp-server/main.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"os"
77
"strings"
8+
"time"
89

910
"github.com/github/github-mcp-server/internal/ghmcp"
1011
"github.com/github/github-mcp-server/pkg/github"
@@ -84,6 +85,9 @@ var (
8485
return fmt.Errorf("failed to unmarshal toolsets: %w", err)
8586
}
8687

88+
// Pre-compute heartbeat interval
89+
hbInterval, _ := time.ParseDuration(viper.GetString("http_heartbeat_interval"))
90+
8791
httpServerConfig := ghmcp.HttpServerConfig{
8892
Version: version,
8993
Host: viper.GetString("host"),
@@ -101,6 +105,7 @@ var (
101105
AppPrivateKey: appPrivateKey,
102106
EnableGitHubAppAuth: enableGitHubAppAuth,
103107
InstallationIDHeader: viper.GetString("installation_id_header"),
108+
HeartbeatInterval: hbInterval,
104109
}
105110

106111
return ghmcp.RunHTTPServer(httpServerConfig)
@@ -133,6 +138,7 @@ func init() {
133138
httpCmd.Flags().String("http-address", ":8080", "HTTP server address to bind to")
134139
httpCmd.Flags().String("http-mcp-path", "/mcp", "HTTP path for MCP endpoint")
135140
httpCmd.Flags().Bool("http-enable-cors", false, "Enable CORS for cross-origin requests")
141+
httpCmd.Flags().String("http-heartbeat-interval", "15s", "Interval for SSE heartbeats on GET listener (e.g., 15s; set 0 to disable)")
136142

137143
// Bind flags to viper
138144
_ = viper.BindPFlag("toolsets", rootCmd.PersistentFlags().Lookup("toolsets"))
@@ -149,6 +155,7 @@ func init() {
149155
_ = viper.BindPFlag("http_address", httpCmd.Flags().Lookup("http-address"))
150156
_ = viper.BindPFlag("http_mcp_path", httpCmd.Flags().Lookup("http-mcp-path"))
151157
_ = viper.BindPFlag("http_enable_cors", httpCmd.Flags().Lookup("http-enable-cors"))
158+
_ = viper.BindPFlag("http_heartbeat_interval", httpCmd.Flags().Lookup("http-heartbeat-interval"))
152159

153160
// Add subcommands
154161
rootCmd.AddCommand(stdioCmd)

internal/ghmcp/http_server.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ type HttpServerConfig struct {
6666

6767
// Custom header name to read installation ID from (defaults to "X-GitHub-Installation-ID")
6868
InstallationIDHeader string
69+
70+
// HeartbeatInterval controls how often the server sends SSE heartbeat pings on the GET listener
71+
// Set to 0 to disable heartbeats
72+
HeartbeatInterval time.Duration
6973
}
7074

7175
const installationContextKey = "installation_id"
@@ -96,7 +100,12 @@ func RunHTTPServer(cfg HttpServerConfig) error {
96100
return fmt.Errorf("failed to create MCP server: %w", err)
97101
}
98102

99-
httpServer := server.NewStreamableHTTPServer(ghServer)
103+
// Configure the streamable HTTP server with optional heartbeat pings
104+
var httpOpts []server.StreamableHTTPOption
105+
if cfg.HeartbeatInterval > 0 {
106+
httpOpts = append(httpOpts, server.WithHeartbeatInterval(cfg.HeartbeatInterval))
107+
}
108+
httpServer := server.NewStreamableHTTPServer(ghServer, httpOpts...)
100109

101110
logrusLogger := logrus.New()
102111
if cfg.LogFilePath != "" {

0 commit comments

Comments
 (0)