From 91fcecd17e5335ed392cdb8d670ab23438f9be1b Mon Sep 17 00:00:00 2001
From: Andrew Gillis <gillis.andrew@gmail.com>
Date: Tue, 15 Apr 2025 21:40:34 +0000
Subject: [PATCH 1/4] feat: add token source flag, gh cli auth

---
 cmd/github-mcp-server/main.go | 70 +++++++++++++++++++++++++++--------
 go.mod                        |  3 ++
 go.sum                        |  4 ++
 3 files changed, 61 insertions(+), 16 deletions(-)

diff --git a/cmd/github-mcp-server/main.go b/cmd/github-mcp-server/main.go
index 5ca0e21cd..ac384b6d7 100644
--- a/cmd/github-mcp-server/main.go
+++ b/cmd/github-mcp-server/main.go
@@ -9,6 +9,7 @@ import (
 	"os/signal"
 	"syscall"
 
+	"github.com/cli/go-gh/pkg/auth"
 	"github.com/github/github-mcp-server/pkg/github"
 	iolog "github.com/github/github-mcp-server/pkg/log"
 	"github.com/github/github-mcp-server/pkg/translations"
@@ -24,9 +25,12 @@ var version = "version"
 var commit = "commit"
 var date = "date"
 
+var root_command_name = "github-mcp-server"
+var default_token_source = "env"
+
 var (
 	rootCmd = &cobra.Command{
-		Use:     "server",
+		Use:     root_command_name,
 		Short:   "GitHub MCP Server",
 		Long:    `A GitHub MCP server that handles various tools and resources.`,
 		Version: fmt.Sprintf("Version: %s\nCommit: %s\nBuild Date: %s", version, commit, date),
@@ -75,6 +79,7 @@ func init() {
 	rootCmd.PersistentFlags().Bool("enable-command-logging", false, "When enabled, the server will log all command requests and responses to the log file")
 	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.)")
+	rootCmd.PersistentFlags().String("token-source", default_token_source, "Authentication token source (e.g. env, gh)")
 
 	// Bind flag to viper
 	_ = viper.BindPFlag("toolsets", rootCmd.PersistentFlags().Lookup("toolsets"))
@@ -84,6 +89,7 @@ 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("token-source", rootCmd.PersistentFlags().Lookup("token-source"))
 
 	// Add subcommands
 	rootCmd.AddCommand(stdioCmd)
@@ -126,21 +132,9 @@ func runStdioServer(cfg runConfig) error {
 	defer stop()
 
 	// Create GH client
-	token := viper.GetString("personal_access_token")
-	if token == "" {
-		cfg.logger.Fatal("GITHUB_PERSONAL_ACCESS_TOKEN not set")
-	}
-	ghClient := gogithub.NewClient(nil).WithAuthToken(token)
-	ghClient.UserAgent = fmt.Sprintf("github-mcp-server/%s", version)
-
-	host := viper.GetString("host")
-
-	if host != "" {
-		var err error
-		ghClient, err = ghClient.WithEnterpriseURLs(host, host)
-		if err != nil {
-			return fmt.Errorf("failed to create GitHub client with host: %w", err)
-		}
+	ghClient, err := newGitHubClient()
+	if err != nil {
+		cfg.logger.Fatalf("failed to create GitHub client: %v", err)
 	}
 
 	t, dumpTranslations := translations.TranslationHelper()
@@ -229,6 +223,50 @@ func runStdioServer(cfg runConfig) error {
 	return nil
 }
 
+func getToken(host string) (string, error) {
+	token_source := viper.GetString("token-source")
+	switch token_source {
+	case "env":
+		token := os.Getenv("GITHUB_PERSONAL_ACCESS_TOKEN")
+		if token == "" {
+			return "", fmt.Errorf("GITHUB_PERSONAL_ACCESS_TOKEN not set")
+		}
+		return token, nil
+	case "gh":
+		token, err := auth.TokenForHost(host)
+		if err == "default" {
+			return "", fmt.Errorf("no token found for host: %s", host)
+		}
+		return token, nil
+	}
+	return "", fmt.Errorf("unknown token source: %s", token_source)
+}
+
+func getHost() string {
+	host := os.Getenv("GH_HOST")
+	if host == "" {
+		host = viper.GetString("gh-host")
+	}
+	return host
+}
+
+func newGitHubClient() (*gogithub.Client, error) {
+	host := getHost()
+	token, err := getToken(host)
+	if err != nil {
+		return nil, fmt.Errorf("failed to get token: %w", err)
+	}
+	ghClient := gogithub.NewClient(nil).WithAuthToken(token)
+	if host != "" {
+		ghClient, err = ghClient.WithEnterpriseURLs(host, host)
+		if err != nil {
+			return nil, fmt.Errorf("failed to create GitHub client with host: %w", err)
+		}
+	}
+	ghClient.UserAgent = fmt.Sprintf("github-mcp-server/%s", version)
+	return ghClient, nil
+}
+
 func main() {
 	if err := rootCmd.Execute(); err != nil {
 		fmt.Println(err)
diff --git a/go.mod b/go.mod
index 7c09fba91..e44deb157 100644
--- a/go.mod
+++ b/go.mod
@@ -14,8 +14,11 @@ require (
 	github.com/stretchr/testify v1.10.0
 )
 
+require github.com/cli/safeexec v1.0.0 // indirect
+
 require (
 	github.com/Microsoft/go-winio v0.6.2 // indirect
+	github.com/cli/go-gh v1.2.1
 	github.com/containerd/log v0.1.0 // indirect
 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
 	github.com/distribution/reference v0.6.0 // indirect
diff --git a/go.sum b/go.sum
index 3378b4fd6..9006fcad7 100644
--- a/go.sum
+++ b/go.sum
@@ -4,6 +4,10 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo
 github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
 github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
 github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/cli/go-gh v1.2.1 h1:xFrjejSsgPiwXFP6VYynKWwxLQcNJy3Twbu82ZDlR/o=
+github.com/cli/go-gh v1.2.1/go.mod h1:Jxk8X+TCO4Ui/GarwY9tByWm/8zp4jJktzVZNlTW5VM=
+github.com/cli/safeexec v1.0.0 h1:0VngyaIyqACHdcMNWfo6+KdUYnqEr2Sg+bSP1pdF+dI=
+github.com/cli/safeexec v1.0.0/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q=
 github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
 github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
 github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=

From f09cbc5499f2d9e7a7b69995f3894f5c5e8cc9a7 Mon Sep 17 00:00:00 2001
From: Andrew Gillis <gillis.andrew@gmail.com>
Date: Tue, 15 Apr 2025 22:17:45 +0000
Subject: [PATCH 2/4] pick more appropriate variable name for token source

---
 cmd/github-mcp-server/main.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/cmd/github-mcp-server/main.go b/cmd/github-mcp-server/main.go
index ac384b6d7..ca5352f8a 100644
--- a/cmd/github-mcp-server/main.go
+++ b/cmd/github-mcp-server/main.go
@@ -233,8 +233,8 @@ func getToken(host string) (string, error) {
 		}
 		return token, nil
 	case "gh":
-		token, err := auth.TokenForHost(host)
-		if err == "default" {
+		token, source := auth.TokenForHost(host)
+		if source == "default" {
 			return "", fmt.Errorf("no token found for host: %s", host)
 		}
 		return token, nil

From 4d43299538a41ff3c2dac4e5506cf862b7f9de7b Mon Sep 17 00:00:00 2001
From: Andrew Gillis <gillis.andrew@gmail.com>
Date: Tue, 15 Apr 2025 22:19:25 +0000
Subject: [PATCH 3/4] adjust variable names

---
 cmd/github-mcp-server/main.go | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/cmd/github-mcp-server/main.go b/cmd/github-mcp-server/main.go
index ca5352f8a..85cf0eb55 100644
--- a/cmd/github-mcp-server/main.go
+++ b/cmd/github-mcp-server/main.go
@@ -25,12 +25,12 @@ var version = "version"
 var commit = "commit"
 var date = "date"
 
-var root_command_name = "github-mcp-server"
-var default_token_source = "env"
+var rootCommandName = "github-mcp-server"
+var defaultTokenSource = "env"
 
 var (
 	rootCmd = &cobra.Command{
-		Use:     root_command_name,
+		Use:     rootCommandName,
 		Short:   "GitHub MCP Server",
 		Long:    `A GitHub MCP server that handles various tools and resources.`,
 		Version: fmt.Sprintf("Version: %s\nCommit: %s\nBuild Date: %s", version, commit, date),
@@ -79,7 +79,7 @@ func init() {
 	rootCmd.PersistentFlags().Bool("enable-command-logging", false, "When enabled, the server will log all command requests and responses to the log file")
 	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.)")
-	rootCmd.PersistentFlags().String("token-source", default_token_source, "Authentication token source (e.g. env, gh)")
+	rootCmd.PersistentFlags().String("token-source", defaultTokenSource, "Authentication token source (e.g. env, gh)")
 
 	// Bind flag to viper
 	_ = viper.BindPFlag("toolsets", rootCmd.PersistentFlags().Lookup("toolsets"))
@@ -224,8 +224,8 @@ func runStdioServer(cfg runConfig) error {
 }
 
 func getToken(host string) (string, error) {
-	token_source := viper.GetString("token-source")
-	switch token_source {
+	tokenSource := viper.GetString("token-source")
+	switch tokenSource {
 	case "env":
 		token := os.Getenv("GITHUB_PERSONAL_ACCESS_TOKEN")
 		if token == "" {

From 83d3aae44d381b5beb0ac574b4fe042caf6f9c51 Mon Sep 17 00:00:00 2001
From: Andrew Gillis <gillis.andrew@gmail.com>
Date: Tue, 15 Apr 2025 22:20:28 +0000
Subject: [PATCH 4/4] fix missed variable rename

---
 cmd/github-mcp-server/main.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cmd/github-mcp-server/main.go b/cmd/github-mcp-server/main.go
index 85cf0eb55..5c689f003 100644
--- a/cmd/github-mcp-server/main.go
+++ b/cmd/github-mcp-server/main.go
@@ -239,7 +239,7 @@ func getToken(host string) (string, error) {
 		}
 		return token, nil
 	}
-	return "", fmt.Errorf("unknown token source: %s", token_source)
+	return "", fmt.Errorf("unknown token source: %s", tokenSource)
 }
 
 func getHost() string {