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)
errChan := make(chan error, 2) log.Infof("Network mode: Created streamable HTTP server")
// Start HTTP server on port log.Infof("Network mode: Creating SSE server...")
go func() { sseServer := server.NewSSEServer(mcpServer,
httpServer := server.NewStreamableHTTPServer(mcpServer) server.WithSSEEndpoint("/sse"),
log.Infof("Gitea MCP HTTP server listening on :%d", flag.Port) server.WithMessageEndpoint("/message"),
if err := httpServer.Start(fmt.Sprintf(":%d", flag.Port)); err != nil { )
errChan <- fmt.Errorf("HTTP server error: %w", err) log.Infof("Network mode: Created SSE server")
}
}() // Create custom HTTP mux
log.Infof("Network mode: Creating HTTP mux...")
// Start SSE server on port+1 mux := http.NewServeMux()
go func() { mux.Handle("/mcp", streamableServer)
sseServer := server.NewSSEServer(mcpServer) mux.Handle("/", sseServer)
ssePort := flag.Port + 1 log.Infof("Network mode: Configured HTTP routes")
log.Infof("Gitea MCP SSE server listening on :%d", ssePort)
if err := sseServer.Start(fmt.Sprintf(":%d", ssePort)); err != nil { // Start single HTTP server
errChan <- fmt.Errorf("SSE server error: %w", err) log.Infof("Gitea MCP Server running in network mode:")
} log.Infof(" http: http://%s/mcp", addr)
}() log.Infof(" sse: http://%s/sse", addr)
err := http.ListenAndServe(fmt.Sprintf(":%d", flag.Port), mux)
// Wait for first error log.Errorf("Network mode: ListenAndServe returned with error: %v", err)
return <-errChan return err
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