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

mcpserver

package
v8.156.0 Latest Latest
Warning

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

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

Documentation

Overview

Package mcpserver is devctl serve: the agent-facing commands as MCP tools over streamable HTTP, acting on GitHub as the person who calls them.

A tool answers with the command's JSON document, devctl's envelope included, as structured content: the exit code is a field, and the call is an MCP error only for auth_required. A wait is one call that blocks until its verdict and sends notifications/progress on the caller's progressToken meanwhile, at an interval below the server's registered timeout, so the gateway restarts that timeout on each.

What only a laptop needs is not here: no version gate, no keychain or other credential store, no detached merge state on disk, no SIGHUP handling and no DEVCTL_TIME_SCALE.

Index

Constants

View Source
const (
	ToolReservationReserve = "reservation_reserve"
	ToolReservationList    = "reservation_list"
	ToolReservationExtend  = "reservation_extend"
	ToolReservationRelease = "reservation_release"
)

The reservation tools' names: devctl reservation reserve, list, extend and release, as the person. reap stays the CI bot's.

View Source
const (
	ToolPRWait        = "pr_wait"
	ToolPRMergeStatus = "pr_merge_status"
	ToolReleaseWait   = "release_wait"
)

The tools' names.

View Source
const Anonymous = "anonymous"

Anonymous is the login of a call refused before its grant named the caller: one without a grant, or one refused as usage.

View Source
const DefaultAudience = "dex-k8s-authenticator"

DefaultAudience is the client the API server of a Giant Swarm management cluster accepts OIDC tokens of.

View Source
const DefaultGitBaseURL = "https://github.com"

DefaultGitBaseURL is where GitCheckouts clone from.

View Source
const DefaultInstallationsTTL = 5 * time.Minute

DefaultInstallationsTTL is how long a token's installations are kept.

View Source
const DefaultNoProgressTimeout = 20 * time.Second

DefaultNoProgressTimeout bounds a wait called without a progressToken, which no progress keeps alive: below muster's default registered timeout of 30 s with headroom for pr_merge's merge call.

View Source
const DefaultProgressInterval = 10 * time.Second

DefaultProgressInterval is how often a wait reports progress: below muster's default registered timeout of 30 s with headroom.

View Source
const DefaultUsersTTL = 5 * time.Minute

DefaultUsersTTL is how long a token's user is kept.

View Source
const GrantHeaderPrefix = "X-Muster-Grant-" //nolint:gosec // G101: a header name, not a credential

GrantHeaderPrefix starts the header the gateway in front carries the person's token of one provider App in: muster attaches X-Muster-Grant-<app> for every App of the server's registration (spec.auth.providerApps) the person granted.

View Source
const IdentitySource = "platform"

IdentitySource is a promotion's identity source on the server: the token the platform handed over for the person.

View Source
const MaxTimeout = 55 * time.Minute

MaxTimeout bounds a wait's own timeout: below the hour muster keeps a progress-kept call alive at most, so the wait ends with devctl's own timeout verdict, not the gateway's.

View Source
const Name = "devctl"

Name is the server's name in its MCP implementation info.

View Source
const StatusGrantRequired = "grant_required"

StatusGrantRequired is the structuredContent status of a result that needs the person's grant of the Apps it names in "apps": muster answers it auth_required with each App's sign-in link (authUrl).

View Source
const ToolPRMerge = "pr_merge"

ToolPRMerge is the merge tool's name.

View Source
const ToolReleasePromote = "release_promote"

ToolReleasePromote is the promotion tool's name, served with Config.ReleasePromote only.

View Source
const ToolRolloutWait = "rollout_wait"

ToolRolloutWait is the rollout wait's name.

Variables

This section is empty.

Functions

func NoreplyEmail added in v8.156.0

func NoreplyEmail(c Caller) string

NoreplyEmail is the person's GitHub noreply address, the commits' author email: <id>+<login>@users.noreply.github.com.

Types

type Caller

type Caller struct {
	// Login is the person's GitHub login.
	Login string
	// ID is the person's GitHub user id, stable across a renamed login.
	ID int64
}

Caller is the person a call is made for, as GitHub names the holder of their grant's token.

type Checkouts added in v8.156.0

type Checkouts interface {
	// Clone checks out main of repository, owner/repo, into a new directory,
	// fetching and pushing with token and committing as author. remove
	// deletes the directory; the call runs it when it ends.
	Clone(ctx context.Context, repository, token string, author Caller) (dir string, remove func(), err error)
}

Checkouts give a reservation call a checkout of its GitOps repository of its own, as the person.

type Clusters added in v8.155.0

type Clusters interface {
	// Open is the client of installation's management cluster acting as the
	// caller in ctx, its requests going through wrap: auth_required without
	// the person's token, not_applicable for an installation the server does
	// not reach.
	Open(ctx context.Context, installation string, wrap func(http.RoundTripper) http.RoundTripper) (dynamic.Interface, error)
	// Installations are the names of the installations it reaches.
	Installations() []string
}

Clusters open an installation's management cluster as the person a call is made for.

type Config

type Config struct {
	// Version is the version the server reports: the binary's.
	Version string
	// Credentials answer the person's GitHub token; nil is [NoCredentials].
	Credentials Credentials
	// Clusters open an installation's management cluster as the person;
	// nil is [NoClusters].
	Clusters Clusters
	// Sources build the clients a wait reads with; nil is [GitHubSources]
	// over Endpoints.
	Sources Sources
	// Endpoints are GitHub's and the registries'; zero is
	// [agentcli.DefaultEndpoints].
	Endpoints agentcli.Endpoints
	// Clock is the waits' clock; nil is the wall clock at scale 1, never
	// DEVCTL_TIME_SCALE.
	Clock *agentcli.Clock
	// ProgressInterval is how often a wait reports progress; zero is
	// DefaultProgressInterval.
	ProgressInterval time.Duration
	// NoProgressTimeout bounds a wait called without a progressToken, so
	// it answers within the gateway's registered timeout; zero is
	// DefaultNoProgressTimeout.
	NoProgressTimeout time.Duration
	// Checkouts clone the GitOps repository of a reservation call; nil is
	// [GitCheckouts] from GitHub into the system's temporary directory.
	Checkouts Checkouts
	// Merges are the merges of this server pr_merge_status reads; nil is an
	// empty [mergejob.Memory]. pr_merge records its merges in them when they
	// take a Put, as a Memory does. Nothing is kept on disk.
	Merges mergejob.Jobs
	// ReleasePromote serves release_promote, the selector of the one tool
	// that cuts a stable release; off, the tool is not listed.
	ReleasePromote bool
	// Metrics count the calls; nil counts none.
	Metrics *Metrics
	// Logger logs one line per call; nil logs nothing.
	Logger *slog.Logger
}

Config configures a Server.

type Credentials

type Credentials interface {
	// GitHubToken is the person's token for the call in ctx; an
	// [agentcli.ExitCoder] of [agentcli.ExitAuthRequired] when the server
	// holds none for them.
	GitHubToken(ctx context.Context) (string, error)
}

Credentials answer the GitHub token of the person a call is made for.

type Dex added in v8.155.0

type Dex struct {
	// TokenEndpoint is Dex's token endpoint, https.
	TokenEndpoint string `json:"tokenEndpoint"`
	// Issuer is the issuer the exchanged token must name; empty is the
	// token endpoint without /token.
	Issuer string `json:"issuer,omitempty"`
	// ConnectorID is the connector of Dex that trusts the hub's Dex, which
	// issued the person's token.
	ConnectorID string `json:"connectorId"`
	// Audience is the client the API server accepts tokens of, asked for
	// as a cross-client audience; empty is dex-k8s-authenticator.
	Audience string `json:"audience,omitempty"`
	// ClientIDFile and ClientSecretFile hold the client the exchange
	// authenticates as, read when the server starts; without
	// ClientSecretFile the client is a public one.
	ClientIDFile     string `json:"clientIdFile"`
	ClientSecretFile string `json:"clientSecretFile,omitempty"`
}

Dex is the token exchange at an installation's Dex.

type DexExchange added in v8.155.0

type DexExchange struct {
	// Client sends the exchanges; nil is http.DefaultClient.
	Client *http.Client
	// Now is the clock of the exchanged tokens' expiry; nil is time.Now.
	Now func() time.Time
	// contains filtered or unexported fields
}

DexExchange opens the installations it was given as the person: it exchanges the person's token, which the gateway in front forwards in Authorization (muster's forwardToken), at the installation's Dex for a token its API accepts, and sends that with every request. The cluster answers by the person's access; the server holds no kubeconfig and no credential of a cluster.

func NewDexExchange added in v8.155.0

func NewDexExchange(installations []Installation) (*DexExchange, error)

NewDexExchange validates installations and reads their client files.

func ReadInstallations added in v8.155.0

func ReadInstallations(path string) (*DexExchange, error)

ReadInstallations reads the installations file: a JSON object with an "installations" list. The client files are read here, once.

func (*DexExchange) Installations added in v8.155.0

func (d *DexExchange) Installations() []string

Installations implements Clusters.

func (*DexExchange) Open added in v8.155.0

Open implements Clusters.

type GitCheckouts added in v8.156.0

type GitCheckouts struct {
	// BaseURL is the git host; empty is DefaultGitBaseURL.
	BaseURL string
	// Dir holds the clones; empty is the system's temporary directory.
	Dir string
}

GitCheckouts clone with git: a shallow clone of main from BaseURL into a new directory under Dir. The person's token is the clone's credential, in its own git configuration only, never on a command line; the author is the person's GitHub login and noreply address.

func (GitCheckouts) Clone added in v8.156.0

func (g GitCheckouts) Clone(ctx context.Context, repository, token string, author Caller) (string, func(), error)

Clone implements Checkouts.

type GitHubInstallations

type GitHubInstallations struct {
	BaseURL string
	Client  *http.Client
	TTL     time.Duration
	Now     func() time.Time
	// contains filtered or unexported fields
}

GitHubInstallations read GET /user/installations at BaseURL and keep each token's answer for TTL.

func (*GitHubInstallations) Owners

func (g *GitHubInstallations) Owners(ctx context.Context, token string) ([]string, error)

Owners implements Installations.

type GitHubSources

type GitHubSources struct {
	Endpoints agentcli.Endpoints
}

GitHubSources are the clients of GitHub and the registries at Endpoints. They hold no CircleCI client: the server has no CircleCI credential, so a pull request's CircleCI state is the commit statuses CircleCI posts to GitHub. The private registry is read anonymously.

func (GitHubSources) PRMerge

func (g GitHubSources) PRMerge(_ context.Context, token string, transport http.RoundTripper) (PRMergeSources, error)

PRMerge implements Sources.

func (GitHubSources) PRWait

func (g GitHubSources) PRWait(_ context.Context, token string, transport http.RoundTripper) (PRWaitSources, error)

PRWait implements Sources.

func (GitHubSources) ReleasePromote

func (g GitHubSources) ReleasePromote(_ context.Context, token string, transport http.RoundTripper) (*releasepromote.Sources, error)

ReleasePromote implements Sources: the person's token, never renewed.

func (GitHubSources) ReleaseWait

func (g GitHubSources) ReleaseWait(_ context.Context, token string, transport http.RoundTripper) (*releasewait.Sources, error)

ReleaseWait implements Sources: no CircleCI client, the wait reads CircleCI through the commit statuses of the tag's commit.

type GitHubUsers added in v8.154.1

type GitHubUsers struct {
	BaseURL string
	Client  *http.Client
	TTL     time.Duration
	Now     func() time.Time
	// contains filtered or unexported fields
}

GitHubUsers read GET /user at BaseURL and keep each token's answer for TTL: a token GitHub refuses is auth_required.

func (*GitHubUsers) User added in v8.154.1

func (g *GitHubUsers) User(ctx context.Context, token string) (Caller, error)

User implements Users.

type Installation added in v8.155.0

type Installation struct {
	// Name is the installation's name, the tool's argument.
	Name string `json:"name"`
	// APIServer is the URL of the management cluster's Kubernetes API.
	APIServer string `json:"apiServer"`
	// CAFile is the API's certificate authority, PEM; empty trusts the
	// system's roots.
	CAFile string `json:"caFile,omitempty"`
	// Dex is the installation's Dex.
	Dex Dex `json:"dex"`
}

Installation is one management cluster the server reaches as the person: its API, and its Dex, where the person's token is exchanged for one of that installation (RFC 8693) with the client the hub's muster presents there. The server holds no credential of the cluster itself.

type Installations

type Installations interface {
	Owners(ctx context.Context, token string) ([]string, error)
}

Installations answer the accounts a GitHub App is installed on that the holder of a user token of it reaches.

type Metrics

type Metrics struct {
	// contains filtered or unexported fields
}

Metrics are the server's call metrics, labelled with the tool, the caller's GitHub login and user id (Anonymous and empty for a call whose grant named none), the repository (owner/repo; empty for a tool that names none or an argument refused as usage) and the verdict.

func NewMetrics

func NewMetrics(registerer prometheus.Registerer) (*Metrics, error)

NewMetrics registers the server's metrics with registerer.

type MusterGrant

type MusterGrant struct {
	// App is the provider App's name in muster, the header's suffix.
	App string
	// GitHubApp is the GitHub App's name, as a refusal names it.
	GitHubApp string
	// Users answer the person the token acts as, the call's caller; nil
	// names none and accepts the token unchecked.
	Users Users
	// Installations answer the owners the App is installed on that the
	// person reaches; nil checks none.
	Installations Installations
}

MusterGrant is the person's token of the GitHub App muster keeps as App: muster attaches it to every call the person granted it for. The token names the caller: a call without one GitHub accepts is refused. The server stores no token and runs no sign-in.

func (MusterGrant) GitHubToken

func (g MusterGrant) GitHubToken(ctx context.Context) (string, error)

GitHubToken implements Credentials: the person's token of the App, with the caller it names put on the call; a grant_required auth_required without one or with one GitHub refuses, and not_applicable for a repository whose owner the App is not installed on.

type NoClusters added in v8.155.0

type NoClusters struct{}

NoClusters is the server that reaches no installation: every rollout wait is not_applicable.

func (NoClusters) Installations added in v8.155.0

func (NoClusters) Installations() []string

Installations implements Clusters.

func (NoClusters) Open added in v8.155.0

Open implements Clusters.

type NoCredentials

type NoCredentials struct{}

NoCredentials is the server with no hand-over of a person's token: every call that reads GitHub is auth_required.

func (NoCredentials) GitHubToken

func (NoCredentials) GitHubToken(context.Context) (string, error)

GitHubToken implements Credentials.

type PRMergeSources

type PRMergeSources struct {
	GitHub  prmerge.GitHub
	Rate    prwait.RateSource
	Entries prwait.EntryFinder
	// Policy is the repository's opt-out; nil reads the team files through
	// GitHub, a *githubclient.Client.
	Policy prmerge.Policy
}

PRMergeSources are what a merge reads and writes, its release wait aside, which reads Sources.ReleaseWait's.

type PRWaitSources

type PRWaitSources struct {
	GitHub  prwait.GitHub
	Rate    prwait.RateSource
	Entries prwait.EntryFinder
}

PRWaitSources are what a pull request wait reads.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is devctl serve's MCP server.

func New

func New(config Config) *Server

New returns the server of config with its tools registered.

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler is the streamable HTTP handler of the server, at every path. Sessions and listings need no grant, so a person who has not granted the App yet sees the tools; every tool call is refused without one.

func (*Server) MCP

func (s *Server) MCP() *server.MCPServer

MCP is the server's MCP server, for in-process clients.

type Sources

type Sources interface {
	PRWait(ctx context.Context, token string, transport http.RoundTripper) (PRWaitSources, error)
	PRMerge(ctx context.Context, token string, transport http.RoundTripper) (PRMergeSources, error)
	ReleaseWait(ctx context.Context, token string, transport http.RoundTripper) (*releasewait.Sources, error)
	ReleasePromote(ctx context.Context, token string, transport http.RoundTripper) (*releasepromote.Sources, error)
}

Sources build the clients of one call from the person's token; the requests go through transport.

type Users added in v8.154.1

type Users interface {
	User(ctx context.Context, token string) (Caller, error)
}

Users answer the GitHub user a token of the App acts as.

Jump to

Keyboard shortcuts

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