Content-Length: 9781 | pFad | http://github.com/github/github-mcp-server/pull/779.diff

thub.com diff --git a/cmd/github-mcp-server/main.go b/cmd/github-mcp-server/main.go index cad002666..73095764d 100644 --- a/cmd/github-mcp-server/main.go +++ b/cmd/github-mcp-server/main.go @@ -59,6 +59,23 @@ var ( return ghmcp.RunStdioServer(stdioServerConfig) }, } + + webCmd = &cobra.Command{ + Use: "web", + Short: "Start web server with login page", + Long: `Start a web server that serves a simple login page with username and password fields.`, + RunE: func(_ *cobra.Command, _ []string) error { + port := viper.GetString("port") + if port == "" { + port = "8080" + } + + webServerConfig := ghmcp.WebServerConfig{ + Port: port, + } + return ghmcp.RunWebServer(webServerConfig) + }, + } ) func init() { @@ -76,6 +93,9 @@ func init() { rootCmd.PersistentFlags().Bool("export-translations", false, "Save translations to a JSON file") rootCmd.PersistentFlags().String("gh-host", "", "Specify the GitHub hostname (for GitHub Enterprise etc.)") + // Add web-specific flags + webCmd.Flags().String("port", "8080", "Port to serve the web interface on") + // Bind flag to viper _ = viper.BindPFlag("toolsets", rootCmd.PersistentFlags().Lookup("toolsets")) _ = viper.BindPFlag("dynamic_toolsets", rootCmd.PersistentFlags().Lookup("dynamic-toolsets")) @@ -84,9 +104,11 @@ func init() { _ = viper.BindPFlag("enable-command-logging", rootCmd.PersistentFlags().Lookup("enable-command-logging")) _ = viper.BindPFlag("export-translations", rootCmd.PersistentFlags().Lookup("export-translations")) _ = viper.BindPFlag("host", rootCmd.PersistentFlags().Lookup("gh-host")) + _ = viper.BindPFlag("port", webCmd.Flags().Lookup("port")) // Add subcommands rootCmd.AddCommand(stdioCmd) + rootCmd.AddCommand(webCmd) } func initConfig() { diff --git a/internal/ghmcp/server.go b/internal/ghmcp/server.go index d993b130a..6816aa8bd 100644 --- a/internal/ghmcp/server.go +++ b/internal/ghmcp/server.go @@ -11,6 +11,7 @@ import ( "os/signal" "strings" "syscall" + "time" "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/github" @@ -251,6 +252,239 @@ func RunStdioServer(cfg StdioServerConfig) error { return nil } +type WebServerConfig struct { + // Port to serve the web interface on + Port string +} + +// RunWebServer starts a simple HTTP server with a login page +func RunWebServer(cfg WebServerConfig) error { + // Create app context + ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) + defer stop() + + mux := http.NewServeMux() + + // Serve the login page + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/" { + http.NotFound(w, r) + return + } + w.Header().Set("Content-Type", "text/html") + _, _ = w.Write([]byte(loginPageHTML)) + }) + + // Serve basic CSS + mux.HandleFunc("/style.css", func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "text/css") + _, _ = w.Write([]byte(loginPageCSS)) + }) + + // Handle login form submission (just echo back for now) + mux.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + username := r.FormValue("username") + _ = r.FormValue("password") // password not used in this basic implementation + + // For now, just display a simple response + w.Header().Set("Content-Type", "text/html") + fmt.Fprintf(w, ` + + + Login Attempt + + + +
+

Login Attempt

+

Username: %s

+

Password: ***

+

Note: This is just a UI mockup. No actual authentication is performed.

+ Back to Login +
+ + + `, username) + }) + + server := &http.Server{ + Addr: ":" + cfg.Port, + Handler: mux, + ReadHeaderTimeout: 30 * time.Second, // 30 seconds, prevents Slowloris attacks + } + + // Start server in a goroutine + errC := make(chan error, 1) + go func() { + fmt.Printf("Starting web server on http://localhost:%s\n", cfg.Port) + errC <- server.ListenAndServe() + }() + + // Wait for shutdown signal + select { + case <-ctx.Done(): + fmt.Println("Shutting down web server...") + return server.Shutdown(context.Background()) + case err := <-errC: + if err != nil && err != http.ErrServerClosed { + return fmt.Errorf("error running web server: %w", err) + } + } + + return nil +} + +// loginPageHTML contains the HTML for the simple login page +const loginPageHTML = ` + + + + + GitHub MCP Server - Login + + + +
+
+

GitHub MCP Server

+

Login

+
+
+ + +
+
+ + +
+ +
+

This is a basic login interface for future authentication features.

+
+
+ +` + +// loginPageCSS contains the CSS styling for the login page +const loginPageCSS = ` +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; + background-color: #f6f8fa; + color: #24292f; + line-height: 1.5; +} + +.container { + display: flex; + align-items: center; + justify-content: center; + min-height: 100vh; + padding: 20px; +} + +.login-form { + background: white; + border: 1px solid #d0d7de; + border-radius: 6px; + padding: 32px; + box-shadow: 0 8px 24px rgba(140, 149, 159, 0.2); + max-width: 400px; + width: 100%; +} + +h1 { + text-align: center; + margin-bottom: 8px; + color: #0969da; + font-size: 24px; +} + +h2 { + text-align: center; + margin-bottom: 24px; + color: #656d76; + font-size: 20px; + font-weight: normal; +} + +.form-group { + margin-bottom: 16px; +} + +label { + display: block; + margin-bottom: 8px; + font-weight: 600; + font-size: 14px; +} + +input[type="text"], +input[type="password"] { + width: 100%; + padding: 12px; + border: 1px solid #d0d7de; + border-radius: 6px; + font-size: 14px; + transition: border-color 0.2s; +} + +input[type="text"]:focus, +input[type="password"]:focus { + outline: none; + border-color: #0969da; + box-shadow: 0 0 0 3px rgba(9, 105, 218, 0.1); +} + +.login-btn { + width: 100%; + background-color: #238636; + color: white; + border: none; + border-radius: 6px; + padding: 12px; + font-size: 14px; + font-weight: 600; + cursor: pointer; + transition: background-color 0.2s; +} + +.login-btn:hover { + background-color: #2ea043; +} + +.login-btn:active { + background-color: #1a7f37; +} + +.note { + text-align: center; + margin-top: 24px; + font-size: 12px; + color: #656d76; + font-style: italic; +} + +a { + color: #0969da; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} +` + type apiHost struct { baseRESTURL *url.URL graphqlURL *url.URL








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/github/github-mcp-server/pull/779.diff

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy