Help us shape the future of Go! Take the 2026 Go Developer Survey

app

package
v4.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 24, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package app is the startup assembly every entry point shares: open the profile, settle the OAuth application, build the HTTP transport, the token source and the GitLab client, refuse a mode the sign-in cannot serve, and wire the MCP server.

It lives outside package main so the commands, the tests and any later driver assemble the server the way the binary does, rather than each re-deriving the sequence and dropping a step on the way. Nothing here prints or exits; the caller decides what a failure means.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func InstanceKind

func InstanceKind(i instance.Instance) string

InstanceKind names an instance without naming its host: "gitlab.com", or "test instance" for the loopback stand-in.

func IsDisconnect

func IsDisconnect(err error) bool

IsDisconnect reports the ordinary end of a stdio session. The SDK reports a closed connection as JSON-RPC -32004 or -32003 with the EOF only as message text, so errors.Is(err, io.EOF) misses it and the process would exit non-zero, which hosts log as a crash. The code is matched, never the text.

func NewHTTPClient

func NewHTTPClient() *http.Client

NewHTTPClient builds the transport every call to the instance uses: proxies from the standard environment variables and the system's certificate authorities. No redirect is followed.

func SameInstance

func SameInstance(recorded string, inst instance.Instance) bool

SameInstance reports whether a profile's recorded instance is inst. A profile that records none has not signed in, and matches. One that records something unreadable, such as a URL an older build accepted, does not.

Types

type Options

type Options struct {
	// Env reads the environment; the credential store takes its
	// refresh-token override from it.
	Env func(string) string
	// Keyring is the OS keyring, or a fake in tests. nil means no
	// keyring: the token lives in the profile's file.
	Keyring credentials.Backend
	// Logger receives startup findings. Never the payload.
	Logger *slog.Logger
	// Version is this build's version.
	Version string
	// Warn receives credential warnings, such as every use of the
	// plaintext file. nil logs them.
	Warn func(string)
}

Options are the process-level inputs to Resolve and Assemble.

type Profile

type Profile struct {
	Name string
	Dir  userconfig.Dir
	// User is the stored profile state; HasUser says a file existed.
	User    userconfig.Config
	HasUser bool
	Store   *credentials.Store
}

Profile is one configured profile: its name, what the last login stored, and its credential store.

func OpenProfile

func OpenProfile(cfg config.Config, keyring credentials.Backend, env func(string) string, warn func(string)) (*Profile, error)

OpenProfile resolves the profile name (the one named, else "default"), reads its stored state and builds its credential store. warn receives the plaintext-file warning on every use of it.

type Runtime

type Runtime struct {
	Settings *Settings
	Client   *gapi.Client
	Startup  Startup
	Server   *mcp.Server
}

Runtime is an assembled server.

func Assemble

func Assemble(ctx context.Context, cfg config.Config, o Options) (*Runtime, error)

Assemble builds the server. It fails on a configuration that cannot work (a sign-in whose scopes the mode exceeds), and not on a missing sign-in or an unreachable instance: those surface per call.

func (*Runtime) Close

func (r *Runtime) Close()

Close waits for a sign-in refresh in progress and refuses any later one, so the process does not exit holding the only copy of a rotated pair. The server calls it before it exits.

func (*Runtime) Serve

func (r *Runtime) Serve(ctx context.Context, stdin io.Reader, stdout io.Writer) error

Serve runs one MCP session over the given streams. An ordinary disconnect is not an error.

type Settings

type Settings struct {
	Config  config.Config
	Profile *Profile
	// Instance is gitlab.com, or the loopback stand-in of
	// GITLAB_MCP_TEST_INSTANCE.
	Instance instance.Instance
	// ClientID is the OAuth application: the override, else the
	// profile's.
	ClientID string
	// HTTPClient carries the proxy.
	HTTPClient *http.Client
	// CredentialsErr is why the stored sign-in will not be used, or nil.
	// The server still starts without one, so tools/list works before
	// anyone signs in and every call says to log in.
	CredentialsErr error
	// contains filtered or unexported fields
}

Settings is the configuration settled against the profile: which application, which transport. The token source is unexported, and String and LogValue both render the same safe fields, because %+v reads unexported fields and a log line reads String.

func Resolve

func Resolve(cfg config.Config, o Options) (*Settings, error)

Resolve settles the configuration against the profile. It reads the profile and touches no network.

A profile signed in to another instance than this one keeps its token to itself, since a token is only ever sent to the instance that issued it: one signed in to the test instance never reaches gitlab.com, and the reverse.

func (*Settings) Application

func (s *Settings) Application() *auth.Application

Application is the OAuth application these settings sign in with.

func (*Settings) CheckScopes

func (s *Settings) CheckScopes(granted []string) error

CheckScopes refuses a configuration the sign-in cannot serve: a read_api token with the write tools on, above all (§9.4). An unknown grant passes, and the calls report what is missing.

func (*Settings) Client

func (s *Settings) Client(logger *slog.Logger, version string) (*gapi.Client, error)

Client builds the GitLab client for these settings.

func (*Settings) ClientWith

func (s *Settings) ClientWith(o gapi.Options) (*gapi.Client, error)

ClientWith builds a GitLab client for these settings with o's tuning. The instance and the transport are always these settings'; the token source and the header timeout are theirs unless o sets them.

func (Settings) LogValue

func (s Settings) LogValue() slog.Value

LogValue renders the settings for slog: the profile, the kind of instance and the flags. Never the host, the application id in full, the account or the token.

func (*Settings) Probe

func (s *Settings) Probe(ctx context.Context, logger *slog.Logger, version string) Startup

Probe reads the token's scopes. Registration needs them before the server exists, so they are read before serving; a failure is logged and left for the calls to report, so an instance that is down at start still gets a server.

Probe refreshes only when no login recorded the scopes: a host may kill the server before the MCP handshake, and a refresh cut short there spends the profile's refresh token. With the access token due, the scopes of the last login stand until the first call.

func (Settings) String

func (s Settings) String() string

String keeps %v and %+v to the fields LogValue shows.

func (*Settings) Tokens

func (s *Settings) Tokens() gapi.TokenSource

Tokens is the token source: the refreshing one, or one that answers every call with the reason there are no credentials.

type Startup

type Startup struct {
	// Granted is the token's scopes, read live or else from the last
	// login.
	Granted []string
}

Startup is what the server learned from the instance before serving.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL