From e3f7405cd8e8d1a8f74b6baaf684764874006068 Mon Sep 17 00:00:00 2001 From: b3nw Date: Sun, 13 Jul 2025 17:26:12 +0000 Subject: [PATCH] feat: add network mode with combined HTTP and SSE endpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add new 'network' transport mode that serves both HTTP and SSE endpoints simultaneously - HTTP endpoint available on specified port (/mcp) - SSE endpoint available on port+1 (/sse) - Maintain backward compatibility with stdio, http, sse modes - Update documentation and examples for new network mode - Default to network mode for improved user experience 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- README.md | 27 +++++++++++++++++---------- cmd/cmd.go | 10 +++++----- config.json | 8 +++++++- operation/operation.go | 42 +++++++++++++++++++++++++++++++++++------- 4 files changed, 64 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 3bb5267..1c64039 100644 --- a/README.md +++ b/README.md @@ -133,20 +133,16 @@ To configure the MCP server for Gitea, add the following to your MCP configurati } ``` -- **sse mode** +- **network mode** (provides both HTTP and SSE endpoints) -```json -{ - "mcpServers": { - "gitea": { - "url": "http://localhost:8080/sse" - } - } -} +Start the server in network mode: +```bash +gitea-mcp -t network --host https://gitea.com --token --port 8080 ``` -- **http mode** +Then configure your MCP client with either endpoint: +**HTTP endpoint:** ```json { "mcpServers": { @@ -157,6 +153,17 @@ To configure the MCP server for Gitea, add the following to your MCP configurati } ``` +**SSE endpoint:** +```json +{ + "mcpServers": { + "gitea": { + "url": "http://localhost:8081/sse" + } + } +} +``` + **Default log path**: `$HOME/.gitea-mcp/gitea-mcp.log` > [!NOTE] diff --git a/cmd/cmd.go b/cmd/cmd.go index 233bae9..87efb02 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -20,14 +20,14 @@ func init() { flag.StringVar( &flagPkg.Mode, "t", - "stdio", - "Transport type (stdio, sse or http)", + "network", + "Transport type (stdio, http, sse, or network). Network mode starts both HTTP and SSE servers", ) flag.StringVar( &flagPkg.Mode, "transport", - "stdio", - "Transport type (stdio, sse or http)", + "network", + "Transport type (stdio, http, sse, or network). Network mode starts both HTTP and SSE servers", ) flag.StringVar( &host, @@ -39,7 +39,7 @@ func init() { &port, "port", 8080, - "see or http port", + "Network server port (used for both HTTP and SSE endpoints)", ) flag.StringVar( &token, diff --git a/config.json b/config.json index da71873..4fe85df 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "mcpServers": { - "gitea": { + "gitea-stdio": { "command": "gitea-mcp", "args": { "-t": "stdio", @@ -11,6 +11,12 @@ "GITEA_HOST": "https://gitea.com", "GITEA_ACCESS_TOKEN": "" } + }, + "gitea-network-http": { + "url": "http://localhost:8080/mcp" + }, + "gitea-network-sse": { + "url": "http://localhost:8081/sse" } } } \ No newline at end of file diff --git a/operation/operation.go b/operation/operation.go index c571202..981e488 100644 --- a/operation/operation.go +++ b/operation/operation.go @@ -42,25 +42,53 @@ func RegisterTool(s *server.MCPServer) { func Run() error { mcpServer = newMCPServer(flag.Version) RegisterTool(mcpServer) + switch flag.Mode { case "stdio": if err := server.ServeStdio(mcpServer); err != nil { return err } - case "sse": - sseServer := server.NewSSEServer(mcpServer) - log.Infof("Gitea MCP SSE server listening on :%d", flag.Port) - if err := sseServer.Start(fmt.Sprintf(":%d", flag.Port)); err != nil { - return err - } case "http": httpServer := server.NewStreamableHTTPServer(mcpServer) log.Infof("Gitea MCP HTTP server listening on :%d", flag.Port) if err := httpServer.Start(fmt.Sprintf(":%d", flag.Port)); err != nil { return err } + case "sse": + sseServer := server.NewSSEServer(mcpServer) + log.Infof("Gitea MCP SSE server listening on :%d", flag.Port) + if err := sseServer.Start(fmt.Sprintf(":%d", flag.Port)); err != nil { + return err + } + case "network": + // Network mode: start both HTTP and SSE servers concurrently + log.Infof("Starting Gitea MCP server in network mode") + + errChan := make(chan error, 2) + + // Start HTTP server on port + go func() { + httpServer := server.NewStreamableHTTPServer(mcpServer) + log.Infof("Gitea MCP HTTP server listening on :%d", flag.Port) + if err := httpServer.Start(fmt.Sprintf(":%d", flag.Port)); err != nil { + errChan <- fmt.Errorf("HTTP server error: %w", err) + } + }() + + // Start SSE server on port+1 + go func() { + sseServer := server.NewSSEServer(mcpServer) + ssePort := flag.Port + 1 + log.Infof("Gitea MCP SSE server listening on :%d", ssePort) + if err := sseServer.Start(fmt.Sprintf(":%d", ssePort)); err != nil { + errChan <- fmt.Errorf("SSE server error: %w", err) + } + }() + + // Wait for first error + return <-errChan default: - return fmt.Errorf("invalid transport type: %s. Must be 'stdio', 'sse' or 'http'", flag.Mode) + return fmt.Errorf("invalid transport type: %s. Must be 'stdio', 'http', 'sse' or 'network'", flag.Mode) } return nil }