github-mcp-server icon indicating copy to clipboard operation
github-mcp-server copied to clipboard

feat: Add multi-user mode with streamable HTTP transport support

Open devendershekhawat opened this issue 6 months ago โ€ข 9 comments

Closes: #471

Overview

This PR introduces a completely new multi-user mode to the GitHub MCP Server, enabling HTTP-based deployments where multiple users can authenticate with their own GitHub tokens per request.

Changes Made

๐Ÿ—๏ธ New Multi-User Architecture

  • Added new multi-user command that starts an HTTP server
  • Created MultiUserStreamableHttpServerConfig for multi-user HTTP configuration
  • Implemented RunMultiUserStreamableHttpServer function for multi-user HTTP mode
  • Added port configuration support with --port flag (defaults to 8080)

๐Ÿ”ง Implementation Details

  • HTTP Server Setup: Uses server.NewStreamableHTTPServer() from mcp-go library
  • Per-Request Auth: Brand new authentication model with tokens extracted from each request
  • Multi-User Toolsets: Created new toolset implementations that handle per-request authentication
  • Port Binding: Configurable via command line flag or environment variable
  • Error Handling: Proper error propagation and logging for multi-user scenarios

๐Ÿ“ Command Interface

# New multi-user mode with HTTP transport
./github-mcp-server multi-user --port 8080

# Existing single-user modes still work
./github-mcp-server stdio                    # Single-user stdio
./github-mcp-server streamable-http          # Single-user HTTP (if it exists)

๐Ÿณ Docker Support

# Updated Dockerfile supports new multi-user HTTP mode
CMD ["./github-mcp-server", "multi-user", "--port", "8080", "--toolsets=repos,issues,users,pull_requests"]

Key Features

๐Ÿ‘ฅ Multi-Tenant Support

  • No global GitHub token required - tokens provided per request
  • Simultaneous users - multiple users can use the server with their own authentication
  • Per-request context - each request is handled with the appropriate user's permissions

๐ŸŒ Production Ready

  • HTTP-based transport for better integration with web services
  • Configurable port binding for containerized deployments
  • Load balancer friendly - stateless request handling

Testing

โœ… Manual Testing

  • [x] New multi-user command starts HTTP server correctly
  • [x] HTTP server responds on configured port
  • [x] Endpoint validation: /mcp endpoint accepts MCP protocol requests
  • [x] Port configuration: Custom port binding with --port flag works
  • [x] Multi-user auth: Per-request token extraction functions properly
  • [x] Backward compatibility: Existing single-user modes unaffected

๐Ÿงช Test Commands

# Start multi-user server (no global token needed)
./github-mcp-server multi-user --port 8080

# Test HTTP endpoint with user token in request
curl -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_GITHUB_TOKEN" \
     -d '{"jsonrpc":"2.0","id":"test","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' \
     http://localhost:8080/mcp

๐Ÿ“Š Expected Response

{
  "jsonrpc": "2.0",
  "id": "test",
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "tools": {},
      "resources": {}
    },
    "serverInfo": {
      "name": "github-mcp-server",
      "version": "dev"
    }
  }
}

Benefits

๐ŸŒ Enterprise Ready

  1. Multi-Tenant: One server instance can serve multiple users/teams
  2. Cloud-Native: Enables containerized deployments with proper HTTP endpoints
  3. Scalable: Works seamlessly behind reverse proxies and load balancers
  4. Web Integration: Direct HTTP API for web applications and microservices

๐Ÿ”’ Security Model

  • โœ… Per-request authentication with individual GitHub tokens
  • โœ… No shared credentials or global tokens
  • โœ… Each user operates with their own GitHub permissions
  • โœ… Stateless request handling for better security

โšก Performance & Scalability

  • ๐Ÿš€ HTTP transport optimized for distributed scenarios
  • ๐Ÿ“ˆ Enables horizontal scaling with multiple server instances
  • ๐Ÿ”„ Better integration with modern observability and monitoring tools
  • ๐Ÿ’ซ Stateless architecture supports auto-scaling

Backward Compatibility

  • โœ… Existing single-user functionality completely unchanged
  • โœ… All existing command line flags preserved
  • โœ… No breaking changes to existing deployments
  • โœ… New multi-user mode is additive only

Files Changed

Core Implementation

  • internal/ghmcp/server.go: Added multi-user server implementation with HTTP support
  • cmd/github-mcp-server/main.go: Added new multi-user command with port configuration

Multi-User Toolsets

  • Added new multi-user toolset implementations that extract auth tokens from request context
  • Created multi-user variants of existing GitHub API integrations

Docker Support

  • Dockerfile: Updated to support new multi-user HTTP mode deployments

Architecture Comparison

Before (Single-User Only)

[MCP Client] โ†’ [stdio/HTTP] โ†’ [GitHub MCP Server] โ†’ [GitHub API]
                                    โ†‘
                              Global GitHub Token

After (Multi-User Option)

[User A] โ†’ [HTTP Request + Token A] โ†’ [Multi-User Server] โ†’ [GitHub API as User A]
[User B] โ†’ [HTTP Request + Token B] โ†’ [Multi-User Server] โ†’ [GitHub API as User B]
[User C] โ†’ [HTTP Request + Token C] โ†’ [Multi-User Server] โ†’ [GitHub API as User C]

Configuration Examples

VS Code MCP Configuration (Multi-User HTTP Mode)

{
  "mcpServers": {
    "github-multi-user": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-p", "8080:8080",
        "ghcr.io/github/github-mcp-server",
        "multi-user", "--port", "8080"
      ]
    }
  }
}

Kubernetes Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: github-mcp-server-multi-user
spec:
  replicas: 3
  selector:
    matchLabels:
      app: github-mcp-server-multi-user
  template:
    metadata:
      labels:
        app: github-mcp-server-multi-user
    spec:
      containers:
      - name: github-mcp-server
        image: ghcr.io/github/github-mcp-server:latest
        args: ["multi-user", "--port", "8080"]
        ports:
        - containerPort: 8080
        # Note: No global GitHub token needed for multi-user mode

Future Enhancements

This foundation enables several future improvements:

  • ๐Ÿ“Š HTTP-based health checks and metrics endpoints
  • ๐Ÿ” Enhanced authentication mechanisms (OAuth, JWT)
  • ๐Ÿ“ OpenAPI specification for the HTTP API
  • ๐ŸŽฏ Request routing and user-based rate limiting
  • ๐Ÿ‘ฅ User session management and caching

Checklist

  • [x] Code follows project style guidelines
  • [x] Self-review of code completed
  • [x] Manual testing performed
  • [x] Backward compatibility verified
  • [x] Documentation updated (command help)
  • [x] Docker support confirmed
  • [x] No breaking changes introduced
  • [x] New multi-user mode works as expected

Deployment Impact

Zero Risk to Existing Users

  • โœ… Completely additive feature - no existing functionality modified
  • โœ… Backward compatible - existing single-user deployments unaffected
  • โœ… Optional feature - users can continue using existing modes

Rollout Strategy

  1. Phase 1: Release new multi-user command as opt-in feature
  2. Phase 2: Update documentation with multi-user deployment examples
  3. Phase 3: Gather feedback and iterate on multi-user capabilities
  4. Phase 4: Consider additional multi-user enhancements based on usage

This PR introduces a completely new operational mode that makes the GitHub MCP Server suitable for enterprise and multi-tenant deployments, while maintaining full backward compatibility with existing single-user usage patterns.

devendershekhawat avatar Jun 04 '25 05:06 devendershekhawat

I prefer the use of Header Authorization. Is it recommended to use the token as a tool parameter, because the model does not know what the token value is when it is called?

ycjcl868 avatar Jun 04 '25 09:06 ycjcl868

That is true. For http, authorization should only be in headers and sent on every single request as headers, as mentioned. The agent should also not have access to the token.

For transparency, as mentioned previously in response to related issues, we are working on a remote server, and we use this local one as a library, rather than make it work for both.

We will be releasing that soon.

Thank you for the contribution though, it's appreciated. We just will wait for our remote release before we decide what to do here.

SamMorrowDrums avatar Jun 04 '25 19:06 SamMorrowDrums

That is true. For http, authorization should only be in headers and sent on every single request as headers, as mentioned. The agent should also not have access to the token.

For transparency, as mentioned previously in response to related issues, we are working on a remote server, and we use this local one as a library, rather than make it work for both.

We will be releasing that soon.

Thank you for the contribution though, it's appreciated. We just will wait for our remote release before we decide what to do here.

Will remote server like https://mcp.github.com be released? That's great!

ycjcl868 avatar Jun 05 '25 05:06 ycjcl868

I will leave this hanging until the announcement...

SamMorrowDrums avatar Jun 05 '25 06:06 SamMorrowDrums

@devendershekhawat thank you for the high quality pr ๐ŸŽ†

We have now https://github.com/github/github-mcp-server?tab=readme-ov-file#remote-github-mcp-server released.

tonytrg avatar Jun 16 '25 10:06 tonytrg

@devendershekhawat thank you for the high quality pr ๐ŸŽ†

We have now https://github.com/github/github-mcp-server?tab=readme-ov-file#remote-github-mcp-server released.

bad request: missing required Authorization header, hope listTools can return tool names, request Authorization header when calling the tool.

ycjcl868 avatar Jun 16 '25 14:06 ycjcl868

bad request: missing required Authorization header, hope listTools can return tool names, request Authorization header when calling the tool.

@ycjcl868 sorry do you mean, the listTools endpoint should not require authorization? We currently require authorization on every request, and you can configure dynamically what tools are available on your end https://github.com/github/github-mcp-server/blob/main/docs/remote-server.md

Might this be what you envisioned? If so leave a comment and we can think about implementing it.

tonytrg avatar Jun 17 '25 11:06 tonytrg

bad request: missing required Authorization header, hope listTools can return tool names, request Authorization header when calling the tool.

@ycjcl868 sorry do you mean, the listTools endpoint should not require authorization? We currently require authorization on every request, and you can configure dynamically what tools are available on your end https://github.com/github/github-mcp-server/blob/main/docs/remote-server.md

Might this be what you envisioned? If so leave a comment and we can think about implementing it.

I think list_tools shouldn't require a Github Token, token should only be filled in when necessary.

ycjcl868 avatar Jun 19 '25 08:06 ycjcl868

Is there any estimate of when this will be merged?

FernandoPazCavalcante avatar Nov 13 '25 04:11 FernandoPazCavalcante