Documentation
¶
Overview ¶
Package scan drains the whole official MCP registry and runs the same keyless probe.Engine that "akashi check" uses against every server, so a bulk census and a single check are always the same measurement over the same struct. It only adds what a census needs on top of that: bounded concurrency, a checkpointed JSONL so an interrupted run resumes without re-probing, and an aggregate summary. It never reimplements a probe or changes a verdict.
Index ¶
Constants ¶
const DefaultConcurrency = 8
DefaultConcurrency is a modest worker pool size: polite to the registry, package indexes, and remote endpoints a census touches, while still finishing a full drain of the registry in a practical amount of time.
const DefaultTimeout = 60 * time.Second
DefaultTimeout bounds one server's full probe set. It mirrors the default "akashi check" uses for the same overall budget.
const RecordsFile = "records.jsonl"
RecordsFile is the JSONL filename written inside --out: one probe.Result per line, the exact fields "akashi check <server> --json" prints.
const SummaryFile = "summary.json"
SummaryFile is the aggregate-report filename written inside --out.
Variables ¶
This section is empty.
Functions ¶
func NewGitHubBackoffTransport ¶
func NewGitHubBackoffTransport(base http.RoundTripper) http.RoundTripper
NewGitHubBackoffTransport wraps base with GitHub rate-limit backoff. A nil base falls back to http.DefaultTransport.
Types ¶
type Breakdown ¶
type Breakdown struct {
Total int `json:"total"`
Counts map[probe.Verdict]int `json:"counts"`
Rates map[probe.Verdict]float64 `json:"rates"`
}
Breakdown is a verdict census over some population: the whole run, or one segment of it (see Summary.Segments). Rates are Counts[v] / Total; Total is the denominator.
type NameIssue ¶
NameIssue is one validation category over the drained server names: how many names fell into it, and a bounded sample of the offending names for spot-checking.
type NameIssues ¶
type NameIssues struct {
// BadCharset counts names containing a character outside
// nameCharsetRe (for example an uppercase letter or a space).
BadCharset NameIssue `json:"badCharset"`
// BadShape counts names that are not exactly one "/" splitting a
// non-empty namespace segment (containing at least one ".") from a
// non-empty local segment, with neither segment starting with ".".
BadShape NameIssue `json:"badShape"`
// CaseCollisions counts names that are distinct but identical to
// another name in this run once lowercased, which would collide as
// the same file. An exact (case-sensitive) repeat of the same name is
// not a collision by itself; registry.Drain already dedupes those
// before validateNames ever sees the list.
CaseCollisions NameIssue `json:"caseCollisions"`
}
NameIssues summarizes registry names that would not survive the planned two-segment <namespace>/<name> page routing, or that would collide on a case-insensitive filesystem once rendered to that path. It is purely informational: see validateNames, which never fails a scan over it.
type Options ¶
type Options struct {
// Out is the output directory. Required. RecordsFile and SummaryFile are
// written inside it.
Out string
// Limit caps how many servers are drained from the registry. 0 means the
// whole registry.
Limit int
// Concurrency is the worker pool size. <= 0 falls back to
// DefaultConcurrency.
Concurrency int
// Timeout bounds one server's full probe set. <= 0 falls back to
// DefaultTimeout.
Timeout time.Duration
// Progress receives one line per completed server ("1234/13886 name
// verdict"), plus a startup line noting how many were already recorded.
// A nil Progress disables progress reporting.
Progress io.Writer
}
Options configures one census run.
type Summary ¶
type Summary struct {
RegistryBaseURL string `json:"registryBaseUrl"`
AkashiVersion string `json:"akashiVersion"`
Concurrency int `json:"concurrency"`
Limit int `json:"limit"` // 0 means the whole registry
StartedAt string `json:"startedAt"`
FinishedAt string `json:"finishedAt"`
// Overall is the verdict census across every server this run targeted.
Overall Breakdown `json:"overall"`
// Segments key the same kind of census by a defining trait. "remote"
// (servers that declare at least one hosted remote endpoint) is the
// headline: a reachable, conformant remote is the strongest keyless
// liveness proof a census can gather, since its domain is verified simply
// by being probed live over HTTPS.
Segments map[string]Breakdown `json:"segments"`
// NameIssues flags registry names that would not survive the planned
// <namespace>/<name> per-server page routing (see validateNames). It is
// a heads-up for the index build, not a scan failure: every server is
// still probed and recorded regardless of what this reports.
NameIssues NameIssues `json:"nameIssues"`
}
Summary is the aggregate report written to SummaryFile alongside RecordsFile. It carries enough reproducibility parameters that a "State of MCP" index built from it can cite exactly how the numbers were produced.
func Run ¶
func Run(ctx context.Context, client *registry.Client, eng *probe.Engine, opts Options) (Summary, error)
Run drains the registry (respecting opts.Limit), probes every server that is not already recorded in an existing RecordsFile under opts.Out, appends each freshly probed result as it completes, and writes SummaryFile once the whole targeted population has a record.
client and eng are pre-configured by the caller (base URL, GitHub token, HTTP transport); Run only orchestrates draining, concurrency, and checkpointing around them. eng is shared across the whole worker pool: its HTTP client and schema cache are safe for concurrent use.