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
- type Caller
- type Config
- type Credentials
- type GitHubInstallations
- type GitHubSources
- func (g GitHubSources) PRMerge(_ context.Context, token string, transport http.RoundTripper) (PRMergeSources, error)
- func (g GitHubSources) PRWait(_ context.Context, token string, transport http.RoundTripper) (PRWaitSources, error)
- func (g GitHubSources) ReleasePromote(_ context.Context, token string, transport http.RoundTripper) (*releasepromote.Sources, error)
- func (g GitHubSources) ReleaseWait(_ context.Context, token string, transport http.RoundTripper) (*releasewait.Sources, error)
- type Installations
- type Metrics
- type MusterGrant
- type NoCredentials
- type OIDCVerifier
- type PRMergeSources
- type PRWaitSources
- type Server
- type Sources
- type Verifier
Constants ¶
const ( ToolPRWait = "pr_wait" ToolPRMergeStatus = "pr_merge_status" ToolReleaseWait = "release_wait" )
The tools' names.
const Anonymous = "anonymous"
Anonymous is the subject of a call no verified caller made.
const DefaultInstallationsTTL = 5 * time.Minute
DefaultInstallationsTTL is how long a token's installations are kept.
const DefaultProgressInterval = 10 * time.Second
DefaultProgressInterval is how often a wait reports progress: below muster's default registered timeout of 30 s with headroom.
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.
const IdentitySource = "platform"
IdentitySource is a promotion's identity source on the server: the token the platform handed over for the person.
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.
const Name = "devctl"
Name is the server's name in its MCP implementation info.
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).
const ToolPRMerge = "pr_merge"
ToolPRMerge is the merge tool's name.
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 {
// Subject is the token's sub, the person's stable identity at the
// issuer.
Subject string
// Email is the token's email claim, when it carries one.
Email string
}
Caller is the person a call is made for, as the ID token the gateway in front forwards names them (muster's forwardToken).
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
// 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
// Verifier checks the ID token the gateway forwards on every request
// and names the caller; nil verifies none, and every call is
// anonymous.
Verifier Verifier
// 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 ¶
Owners implements Installations.
type GitHubSources ¶
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 Installations ¶
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 verified caller's subject (Anonymous without a verifier), the repository (owner/repo; empty for a tool that names none or an argument refused as usage) and the verdict. The caller's email is in the log line only.
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
// 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 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; a grant_required auth_required without one, 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 OIDCVerifier ¶
type OIDCVerifier struct {
// contains filtered or unexported fields
}
OIDCVerifier accepts an ID token its issuer signed for one of its audiences.
func NewOIDCVerifier ¶
func NewOIDCVerifier(ctx context.Context, client *http.Client, issuer string, audiences []string) (*OIDCVerifier, error)
NewOIDCVerifier discovers issuer's signing keys through client (nil is http.DefaultClient) and accepts its ID tokens for any of audiences.
func NewStaticOIDCVerifier ¶
func NewStaticOIDCVerifier(issuer string, keys oidc.KeySet, audiences []string) (*OIDCVerifier, error)
NewStaticOIDCVerifier accepts issuer's ID tokens signed by keys for any of audiences, with no discovery.
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.
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.