2 Commits

Author SHA1 Message Date
b3nw
c2fac7754c fix: resolve network mode SSE and logging issues
- Fixes 404 errors on /sse and /message endpoints in network mode.
- Updates dev container and go.mod to use a compatible Go version.
- Restores and improves startup logging for all transport modes.
2025-07-14 02:01:29 +00:00
b3nw
f714887d1c feat: add network mode for combined HTTP and SSE endpoints
Add new 'network' transport mode that serves both HTTP and SSE protocols
on the same port with different URL paths:
- HTTP endpoint: /mcp
- SSE endpoint: /sse

Changes:
- Add network mode to operation/operation.go using http.ServeMux routing
- Update cmd/cmd.go flag descriptions to include network option
- Update README.md with network mode documentation and examples
- Update config.json with network mode configuration examples

The network mode allows clients to choose between HTTP or SSE protocols
without requiring separate server instances or ports. This provides
better resource utilization and simpler deployment.

Backward compatibility maintained - all existing modes (stdio, http, sse)
work unchanged.

Based on v0.3.0 for clean upstream compatibility.
2025-07-13 21:54:56 +00:00
9 changed files with 54 additions and 85 deletions

View File

@@ -133,32 +133,25 @@ To configure the MCP server for Gitea, add the following to your MCP configurati
} }
``` ```
- **network mode** (provides both HTTP and SSE endpoints) - **sse mode**
Start the server in network mode:
```bash
gitea-mcp -t network --host https://gitea.com --token <your-token> --port 8080
```
Then configure your MCP client with either endpoint:
**HTTP endpoint:**
```json ```json
{ {
"mcpServers": { "mcpServers": {
"gitea": { "gitea": {
"url": "http://localhost:8080/mcp" "url": "http://localhost:8080/sse"
} }
} }
} }
``` ```
**SSE endpoint:** - **http mode**
```json ```json
{ {
"mcpServers": { "mcpServers": {
"gitea": { "gitea": {
"url": "http://localhost:8081/sse" "url": "http://localhost:8080/mcp"
} }
} }
} }

View File

@@ -20,14 +20,14 @@ func init() {
flag.StringVar( flag.StringVar(
&flagPkg.Mode, &flagPkg.Mode,
"t", "t",
"network", "stdio",
"Transport type (stdio, http, sse, or network). Network mode starts both HTTP and SSE servers", "Transport type (stdio, sse, http, or network)",
) )
flag.StringVar( flag.StringVar(
&flagPkg.Mode, &flagPkg.Mode,
"transport", "transport",
"network", "stdio",
"Transport type (stdio, http, sse, or network). Network mode starts both HTTP and SSE servers", "Transport type (stdio, sse, http, or network)",
) )
flag.StringVar( flag.StringVar(
&host, &host,
@@ -39,7 +39,7 @@ func init() {
&port, &port,
"port", "port",
8080, 8080,
"Network server port (used for both HTTP and SSE endpoints)", "see or http port",
) )
flag.StringVar( flag.StringVar(
&token, &token,

View File

@@ -1,6 +1,6 @@
{ {
"mcpServers": { "mcpServers": {
"gitea-stdio": { "gitea": {
"command": "gitea-mcp", "command": "gitea-mcp",
"args": { "args": {
"-t": "stdio", "-t": "stdio",
@@ -11,12 +11,6 @@
"GITEA_HOST": "https://gitea.com", "GITEA_HOST": "https://gitea.com",
"GITEA_ACCESS_TOKEN": "<your personal access token>" "GITEA_ACCESS_TOKEN": "<your personal access token>"
} }
},
"gitea-network-http": {
"url": "http://localhost:8080/mcp"
},
"gitea-network-sse": {
"url": "http://localhost:8081/sse"
} }
} }
} }

BIN
gitea-mcp-network Executable file

Binary file not shown.

BIN
gitea-mcp-v0.3.0 Executable file

Binary file not shown.

4
go.mod
View File

@@ -1,6 +1,8 @@
module gitea.com/gitea/gitea-mcp module gitea.com/gitea/gitea-mcp
go 1.24.0 go 1.23.0
toolchain go1.23.11
require ( require (
code.gitea.io/sdk/gitea v0.21.0 code.gitea.io/sdk/gitea v0.21.0

View File

@@ -2,6 +2,7 @@ package operation
import ( import (
"fmt" "fmt"
"net/http"
"gitea.com/gitea/gitea-mcp/operation/issue" "gitea.com/gitea/gitea-mcp/operation/issue"
"gitea.com/gitea/gitea-mcp/operation/pull" "gitea.com/gitea/gitea-mcp/operation/pull"
@@ -42,53 +43,56 @@ func RegisterTool(s *server.MCPServer) {
func Run() error { func Run() error {
mcpServer = newMCPServer(flag.Version) mcpServer = newMCPServer(flag.Version)
RegisterTool(mcpServer) RegisterTool(mcpServer)
addr := fmt.Sprintf("127.0.0.1:%d", flag.Port)
switch flag.Mode { switch flag.Mode {
case "stdio": case "stdio":
if err := server.ServeStdio(mcpServer); err != nil { if err := server.ServeStdio(mcpServer); err != nil {
return err 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": case "sse":
sseServer := server.NewSSEServer(mcpServer) sseServer := server.NewSSEServer(mcpServer)
log.Infof("Gitea MCP SSE server listening on :%d", flag.Port) log.Infof("Gitea MCP Server running:")
log.Infof(" sse: http://%s/", addr)
if err := sseServer.Start(fmt.Sprintf(":%d", flag.Port)); err != nil { if err := sseServer.Start(fmt.Sprintf(":%d", flag.Port)); err != nil {
return err return err
} }
case "http":
httpServer := server.NewStreamableHTTPServer(mcpServer)
log.Infof("Gitea MCP Server running:")
log.Infof(" http: http://%s/", addr)
if err := httpServer.Start(fmt.Sprintf(":%d", flag.Port)); err != nil {
return err
}
case "network": case "network":
// Network mode: start both HTTP and SSE servers concurrently // Network mode: serve both HTTP and SSE on same port with different URLs
log.Infof("Starting Gitea MCP server in network mode") log.Infof("Network mode: Creating streamable HTTP server...")
streamableServer := server.NewStreamableHTTPServer(mcpServer)
log.Infof("Network mode: Created streamable HTTP server")
errChan := make(chan error, 2) log.Infof("Network mode: Creating SSE server...")
sseServer := server.NewSSEServer(mcpServer,
server.WithSSEEndpoint("/sse"),
server.WithMessageEndpoint("/message"),
)
log.Infof("Network mode: Created SSE server")
// Start HTTP server on port // Create custom HTTP mux
go func() { log.Infof("Network mode: Creating HTTP mux...")
httpServer := server.NewStreamableHTTPServer(mcpServer) mux := http.NewServeMux()
log.Infof("Gitea MCP HTTP server listening on :%d", flag.Port) mux.Handle("/mcp", streamableServer)
if err := httpServer.Start(fmt.Sprintf(":%d", flag.Port)); err != nil { mux.Handle("/", sseServer)
errChan <- fmt.Errorf("HTTP server error: %w", err) log.Infof("Network mode: Configured HTTP routes")
}
}()
// Start SSE server on port+1 // Start single HTTP server
go func() { log.Infof("Gitea MCP Server running in network mode:")
sseServer := server.NewSSEServer(mcpServer) log.Infof(" http: http://%s/mcp", addr)
ssePort := flag.Port + 1 log.Infof(" sse: http://%s/sse", addr)
log.Infof("Gitea MCP SSE server listening on :%d", ssePort) err := http.ListenAndServe(fmt.Sprintf(":%d", flag.Port), mux)
if err := sseServer.Start(fmt.Sprintf(":%d", ssePort)); err != nil { log.Errorf("Network mode: ListenAndServe returned with error: %v", err)
errChan <- fmt.Errorf("SSE server error: %w", err) return err
}
}()
// Wait for first error
return <-errChan
default: default:
return fmt.Errorf("invalid transport type: %s. Must be 'stdio', 'http', 'sse' or 'network'", flag.Mode) return fmt.Errorf("invalid transport type: %s. Must be 'stdio', 'sse', 'http' or 'network'", flag.Mode)
} }
return nil return nil
} }

View File

@@ -45,7 +45,7 @@ func Default() *zap.Logger {
MaxAge: 30, MaxAge: 30,
})) }))
if flag.Mode == "http" || flag.Mode == "sse" { if flag.Mode == "http" || flag.Mode == "sse" || flag.Mode == "network" {
wss = append(wss, zapcore.AddSync(os.Stdout)) wss = append(wss, zapcore.AddSync(os.Stdout))
} }

View File

@@ -1,24 +0,0 @@
# Releases
## v0.5.0-combined - Network Mode
This directory contains binary releases for the combined server implementation.
### Features
- Network mode with both HTTP and SSE endpoints available simultaneously
- HTTP endpoint on specified port (/mcp)
- SSE endpoint on port+1 (/sse)
- Backward compatibility with stdio, http, sse modes
### Usage
```bash
# Download and make executable
chmod +x gitea-mcp-combined
# Start network mode
./gitea-mcp-combined -t network --host https://gitea.ext.ben.io --token <token> --port 8080
```
### Endpoints
- HTTP: http://localhost:8080/mcp
- SSE: http://localhost:8081/sse