in cmd/github-mcp-server/main.go [131:238]
func runStdioServer(cfg runConfig) error {
// Create app context
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
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)
}
}
t, dumpTranslations := translations.TranslationHelper()
beforeInit := func(_ context.Context, _ any, message *mcp.InitializeRequest) {
ghClient.UserAgent = fmt.Sprintf("github-mcp-server/%s (%s/%s)", version, message.Params.ClientInfo.Name, message.Params.ClientInfo.Version)
}
getClient := func(_ context.Context) (*gogithub.Client, error) {
return ghClient, nil // closing over client
}
hooks := &server.Hooks{
OnBeforeInitialize: []server.OnBeforeInitializeFunc{beforeInit},
}
// Create server
ghServer := github.NewServer(version, server.WithHooks(hooks))
enabled := cfg.enabledToolsets
dynamic := viper.GetBool("dynamic_toolsets")
if dynamic {
// filter "all" from the enabled toolsets
enabled = make([]string, 0, len(cfg.enabledToolsets))
for _, toolset := range cfg.enabledToolsets {
if toolset != "all" {
enabled = append(enabled, toolset)
}
}
}
// Create default toolsets
toolsets, err := github.InitToolsets(enabled, cfg.readOnly, getClient, t)
context := github.InitContextToolset(getClient, t)
if err != nil {
stdlog.Fatal("Failed to initialize toolsets:", err)
}
// Register resources with the server
github.RegisterResources(ghServer, getClient, t)
// Register the tools with the server
toolsets.RegisterTools(ghServer)
context.RegisterTools(ghServer)
if dynamic {
dynamic := github.InitDynamicToolset(ghServer, toolsets, t)
dynamic.RegisterTools(ghServer)
}
stdioServer := server.NewStdioServer(ghServer)
stdLogger := stdlog.New(cfg.logger.Writer(), "stdioserver", 0)
stdioServer.SetErrorLogger(stdLogger)
if cfg.exportTranslations {
// Once server is initialized, all translations are loaded
dumpTranslations()
}
// Start listening for messages
errC := make(chan error, 1)
go func() {
in, out := io.Reader(os.Stdin), io.Writer(os.Stdout)
if cfg.logCommands {
loggedIO := iolog.NewIOLogger(in, out, cfg.logger)
in, out = loggedIO, loggedIO
}
errC <- stdioServer.Listen(ctx, in, out)
}()
// Output github-mcp-server string
_, _ = fmt.Fprintf(os.Stderr, "GitHub MCP Server running on stdio\n")
// Wait for shutdown signal
select {
case <-ctx.Done():
cfg.logger.Infof("shutting down server...")
case err := <-errC:
if err != nil {
return fmt.Errorf("error running server: %w", err)
}
}
return nil
}