Skip to content

Commit a9041ad

Browse files
prachi-shah-harnessHarness
authored andcommitted
feat: [ML-1255]: deploy mcp as http service (#190)
* change cmd from server to http-server * feat: [ML-1255]: deploy mcp as http service
1 parent 7f237c3 commit a9041ad

File tree

2 files changed

+20
-70
lines changed

2 files changed

+20
-70
lines changed

Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@ ENV XDG_CACHE_HOME=/data
3939
COPY --from=builder /app/cmd/harness-mcp-server/harness-mcp-server /app/harness-mcp-server
4040
COPY --from=cert-image /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
4141

42-
ENTRYPOINT [ "/app/harness-mcp-server", "stdio" ]
42+
ENTRYPOINT [ "/app/harness-mcp-server"]
43+
CMD ["stdio"]

cmd/harness-mcp-server/main.go

Lines changed: 18 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,15 @@ var (
4444
Version: fmt.Sprintf("Version: %s\nCommit: %s\nBuild Date: %s", version, commit, date),
4545
}
4646

47-
serverCmd = &cobra.Command{
48-
Use: "server",
49-
Short: "Start MCP as a standalone server",
50-
Long: `Start a standalone MCP server with HTTP or stdio transport.`,
47+
httpServerCmd = &cobra.Command{
48+
Use: "http-server",
49+
Short: "Start MCP as a standalone server with HTTP transport",
50+
Long: `Start a standalone MCP server with HTTP transport`,
5151
RunE: func(_ *cobra.Command, _ []string) error {
5252
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
5353
defer stop()
5454

55-
transportMode := viper.GetString("transport")
56-
var transportType enum.TransportType
57-
if transportMode == "" {
58-
transportType = enum.TransportStdio
59-
} else {
60-
transportType = enum.ParseTransportType(transportMode)
61-
}
55+
transportType := enum.TransportHTTP
6256

6357
var toolsets []string
6458
err := viper.UnmarshalKey("toolsets", &toolsets)
@@ -90,7 +84,7 @@ var (
9084
EnableModules: enableModules,
9185
}
9286

93-
return runMCPServer(ctx, cfg)
87+
return runHTTPServer(ctx, cfg)
9488
},
9589
}
9690

@@ -170,7 +164,7 @@ var (
170164
// Move this out to middleware once we move to streamable HTTP
171165
session, err := auth.AuthenticateSession(bearerToken, mcpSecret)
172166
if err != nil {
173-
return fmt.Errorf("Failed to authenticate session: %w", err)
167+
return fmt.Errorf("failed to authenticate session: %w", err)
174168
}
175169

176170
// Store the authenticated session in the context
@@ -179,13 +173,13 @@ var (
179173
var toolsets []string
180174
err = viper.UnmarshalKey("toolsets", &toolsets)
181175
if err != nil {
182-
return fmt.Errorf("Failed to unmarshal toolsets: %w", err)
176+
return fmt.Errorf("failed to unmarshal toolsets: %w", err)
183177
}
184178

185179
var enableModules []string
186180
err = viper.UnmarshalKey("enable_modules", &enableModules)
187181
if err != nil {
188-
return fmt.Errorf("Failed to unmarshal enabled modules: %w", err)
182+
return fmt.Errorf("failed to unmarshal enabled modules: %w", err)
189183
}
190184

191185
cfg := config.Config{
@@ -262,10 +256,8 @@ func init() {
262256
rootCmd.PersistentFlags().String("log-file", "", "Path to log file")
263257
rootCmd.PersistentFlags().Bool("debug", false, "Enable debug logging")
264258

265-
// Add transport configuration flags to server command
266-
serverCmd.PersistentFlags().String("transport", "stdio", "Transport mode: 'stdio' or 'http'")
267-
serverCmd.PersistentFlags().Int("http-port", 8080, "HTTP server port (when transport is 'http')")
268-
serverCmd.PersistentFlags().String("http-path", "/mcp", "HTTP server path (when transport is 'http')")
259+
httpServerCmd.PersistentFlags().Int("http-port", 8080, "HTTP server port (when transport is 'http')")
260+
httpServerCmd.PersistentFlags().String("http-path", "/mcp", "HTTP server path (when transport is 'http')")
269261

270262
// Add stdio-specific flags
271263
stdioCmd.Flags().String("base-url", "https://app.harness.io", "Base URL for Harness")
@@ -318,9 +310,8 @@ func init() {
318310
_ = viper.BindPFlag("debug", rootCmd.PersistentFlags().Lookup("debug"))
319311

320312
// Bind transport configuration flags to viper
321-
_ = viper.BindPFlag("transport", serverCmd.PersistentFlags().Lookup("transport"))
322-
_ = viper.BindPFlag("http_port", serverCmd.PersistentFlags().Lookup("http-port"))
323-
_ = viper.BindPFlag("http_path", serverCmd.PersistentFlags().Lookup("http-path"))
313+
_ = viper.BindPFlag("http_port", httpServerCmd.PersistentFlags().Lookup("http-port"))
314+
_ = viper.BindPFlag("http_path", httpServerCmd.PersistentFlags().Lookup("http-path"))
324315

325316
// Bind stdio-specific flags to viper
326317
_ = viper.BindPFlag("base_url", stdioCmd.Flags().Lookup("base-url"))
@@ -367,7 +358,7 @@ func init() {
367358
_ = viper.BindPFlag("rbac_svc_secret", internalCmd.Flags().Lookup("rbac-svc-secret"))
368359

369360
// Add subcommands
370-
rootCmd.AddCommand(serverCmd)
361+
rootCmd.AddCommand(httpServerCmd)
371362
rootCmd.AddCommand(stdioCmd)
372363
stdioCmd.AddCommand(internalCmd)
373364
}
@@ -398,15 +389,15 @@ func initLogger(outPath string, debug bool) error {
398389
return nil
399390
}
400391

401-
// runMCPServer starts the MCP server with the specified transport (stdio or http)
402-
func runMCPServer(ctx context.Context, config config.Config) error {
392+
// runHTTPServer starts the MCP server with http transport
393+
func runHTTPServer(ctx context.Context, config config.Config) error {
403394
err := initLogger(config.LogFilePath, config.Debug)
404395
if err != nil {
405396
return fmt.Errorf("failed to initialize logger: %w", err)
406397
}
407398

408-
slog.Info("Starting server (runMCPServer)", "transport", config.Transport)
409-
slog.Info("Using config (runMCPServer)", "config", config)
399+
slog.Info("Starting server (runHTTPServer)", "transport", config.Transport)
400+
slog.Info("Using config (runHTTPServer)", "config", config)
410401

411402
// Define beforeInit function to add client info to user agent
412403
beforeInit := func(_ context.Context, _ any, message *mcp.InitializeRequest) {
@@ -435,16 +426,6 @@ func runMCPServer(ctx context.Context, config config.Config) error {
435426
// Set the guidelines prompts
436427
prompts.RegisterPrompts(harnessServer)
437428

438-
// Handle different transport modes
439-
if config.Transport == "http" {
440-
return runHTTPServer(ctx, harnessServer, config)
441-
} else {
442-
return runMCPStdioServer(ctx, harnessServer, config)
443-
}
444-
}
445-
446-
// runHTTPServer starts the MCP server with HTTP transport
447-
func runHTTPServer(ctx context.Context, harnessServer *server.MCPServer, config config.Config) error {
448429
// Create HTTP server
449430
httpServer := server.NewStreamableHTTPServer(harnessServer)
450431
// Start server
@@ -546,38 +527,6 @@ func runStdioServer(ctx context.Context, config config.Config) error {
546527
return nil
547528
}
548529

549-
// runMCPStdioServer is the internal function that handles stdio transport with an existing server
550-
func runMCPStdioServer(ctx context.Context, harnessServer *server.MCPServer, config config.Config) error {
551-
// Create stdio server
552-
stdioServer := server.NewStdioServer(harnessServer)
553-
554-
// Set error logger
555-
stdioServer.SetErrorLogger(slog.NewLogLogger(slog.Default().Handler(), slog.LevelError))
556-
557-
// Start listening for messages
558-
errC := make(chan error, 1)
559-
go func() {
560-
in, out := io.Reader(os.Stdin), io.Writer(os.Stdout)
561-
errC <- stdioServer.Listen(ctx, in, out)
562-
}()
563-
564-
// Output startup message
565-
slog.Info("Harness MCP Server running on stdio (runMCPStdioServer)", "version", version)
566-
567-
// Wait for shutdown signal
568-
select {
569-
case <-ctx.Done():
570-
slog.Info("shutting down server...")
571-
case err := <-errC:
572-
if err != nil {
573-
slog.Error("error running server", "error", err)
574-
return fmt.Errorf("error running server: %w", err)
575-
}
576-
}
577-
578-
return nil
579-
}
580-
581530
func main() {
582531
if err := rootCmd.Execute(); err != nil {
583532
fmt.Println(err)

0 commit comments

Comments
 (0)