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

mcpserver

package
v8.154.1 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: 25 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 (
	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 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.

Variables

This section is empty.

Functions

This section is empty.

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 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
	// 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
	// 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 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 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 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