Documentation
¶
Overview ¶
The 2026-07-28 spec-readiness pass. It runs only against a remote that already answered a conformant initialize, and adds a handful of read-only, list-level JSON-RPC calls: a stateless tools/list, server/discover, a header-mismatch check, a subscriptions/listen existence check, one GET, a resources/read of a sentinel URI that cannot exist, and a fetch of the public OAuth protected-resource metadata. No call authenticates and no call executes a tool, so the zero-key pledge holds by construction; the sentinel read mirrors what mcp-spec-check ships as a standard check.
Ruleset: strategy/mcp-readiness-2026-07/RULESET.md in the RoninForge planning repo, compiled from the 2026-07-28 draft changelog and re-diffed against the published final text on 2026-08-03 with no verdict-bearing rule changed. RulesetVersion pins which revision of the rules produced a verdict. The numeric error codes still accept both the RC and the renumbered final values, and must keep doing so: servers built against the RC are real and still enforcing, so narrowing to the final numbers would silently reclassify them as not enforcing at all.
Package probe is the keyless MCP-server health engine. For a given server it runs only public, unauthenticated signals - repository liveness (GitHub API), package publication (npm, PyPI, Docker Hub anon), and remote reachability (a plain GET plus a capability-only MCP `initialize` handshake) - and classifies the server as healthy, degraded, dead, or unknown.
It never authenticates to a probed server and never executes a tool. Any GitHub token supplied is used solely against the public GitHub API as a higher-rate-limit measurement instrument, exactly as a human running `gh` would. Nothing here touches a user secret. This keeps the zero-key pledge true by construction.
Index ¶
Constants ¶
const ( ReadinessReady = "ready" ReadinessNeedsMigration = "needs-migration" ReadinessAtRisk = "at-risk" )
Readiness verdict values, per the ruleset: first match wins in the order at-risk, ready, needs-migration. A server with no conformant remote gets no ReadinessSignal at all, which is the "unknown" bucket.
const DefaultUserAgent = "akashi (mcp health probe; keyless; +https://roninforge.org)"
DefaultUserAgent identifies akashi politely to every third party it probes.
const HTTPClientTimeout = 60 * time.Second
HTTPClientTimeout is a whole-request backstop on every probe client.
It is NOT the probe's normal budget: RemoteTimeout, RequestTimeout and the per-server context all expire long before it, so in ordinary operation it never fires. It exists because a context deadline cannot protect a call that never receives the context, and at least one such call is on the hot path. The MCP Go SDK tears a failed session down in streamableClientConn.Close, which issues its session-delete request on a context-free client, by design: cleanup must not be skipped just because the caller's context was already cancelled. Against an endpoint that completes a TCP handshake and then never answers, that request has nothing to bound it.
Lived consequence, 2026-08-03: one such endpoint hung a worker on the final server of a 19,788-server census. The per-server 60s deadline had already expired and could not help. The pool drained, the WaitGroup never completed, and the run sat blocked in probeAll for 95 minutes with no summary written, after four and a half hours of good work.
const RulesetVersion = "2026-07-28"
RulesetVersion identifies the readiness ruleset a verdict was computed under.
Re-diffed against the final specification text on 2026-08-03: every verdict-bearing rule is unchanged from the RC, the error renumbering landed exactly as the ruleset anticipated (and the probe already accepts both numbers), and the only removal absent from the ruleset is not keylessly observable. So no rule changed here, only the name: what was provisional is now confirmed.
Censuses already stamped "2026-07-28-rc" keep that stamp. It names the revision that actually computed them, and rewriting a published record to look tidier is the one edit a provenance dataset must never make.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Check ¶
type Check struct {
Name string `json:"name"`
Status Status `json:"status"`
Detail string `json:"detail,omitempty"`
}
Check is one line in the human-readable report.
type Engine ¶
type Engine struct {
HTTP *http.Client
// UserAgent is sent on every request.
UserAgent string
// GitHubToken, when set, is sent only to api.github.com to raise the rate
// limit. It is never sent to a probed server.
GitHubToken string
// Now supplies the clock; overridable in tests.
Now func() time.Time
// RemoteTimeout bounds each remote-endpoint request.
RemoteTimeout time.Duration
// RequestTimeout bounds each registry/repo/package request.
RequestTimeout time.Duration
// ProbeTools runs the go-sdk tools/list conformance probe on reachable,
// conformant remotes. Default true; a bulk scan can disable it for speed.
ProbeTools bool
// ProbeReadiness runs the 2026-07-28 spec-readiness pass against the
// first conformant remote. Default true.
ProbeReadiness bool
// ValidateServerJSON validates a registry server's server.json against its
// declared JSON Schema. Default true.
ValidateServerJSON bool
// contains filtered or unexported fields
}
Engine runs keyless probes. The zero value is not usable; call NewEngine.
type PackageSignal ¶
type PackageSignal struct {
Type string `json:"type"` // npm|pypi|oci
ID string `json:"id"`
Status string `json:"status"` // published|missing|unpublished|unprobed|error
HTTPStatus int `json:"httpStatus,omitempty"`
Latest string `json:"latest,omitempty"`
Detail string `json:"detail,omitempty"`
}
PackageSignal is the raw package probe result for one entrypoint.
type ReadinessSignal ¶ added in v0.4.0
type ReadinessSignal struct {
RulesetVersion string `json:"rulesetVersion"`
URL string `json:"url"`
// Stateless core (B2, B3): does the server answer without a handshake,
// and does it implement the new required discovery RPC.
StatelessAccepted bool `json:"statelessAccepted"`
DiscoverSupported bool `json:"discoverSupported"`
DiscoverVersions []string `json:"discoverVersions,omitempty"`
// Sessions (B1): whether the initialize response minted an
// Mcp-Session-Id, and whether requests are rejected without it.
SessionIssued bool `json:"sessionIssued"`
SessionRequired bool `json:"sessionRequired"`
// Streams (B4, D2): the new listen RPC, and what a plain GET returns.
// "legacy-sse" means the pre-Streamable-HTTP endpoint event was seen.
SubscriptionsListen bool `json:"subscriptionsListen"`
GetStream string `json:"getStream,omitempty"` // legacy-sse|sse|405|other
// Capability-derived (B6, D1).
TasksExperimental bool `json:"tasksExperimental"`
LoggingDeclared bool `json:"loggingDeclared"`
// tools/list result conformance (B8, B11). Advisory, never verdict-blocking.
ResultTypePresent bool `json:"resultTypePresent"`
CacheMetaPresent bool `json:"cacheMetaPresent"`
// Routing headers (B10, B13). The enforced values record which numeric
// code came back, distinguishing RC-beta builds from final builds.
HeaderEnforcement string `json:"headerEnforcement,omitempty"` // enforced-32020|enforced-32001|ignored|unknown
// Resource error code migration (B12). 0 when not tested (no resources
// capability declared).
ResourceNotFoundCode int `json:"resourceNotFoundCode,omitempty"`
// Auth metadata (A1): public RFC 9728 protected-resource metadata.
ProtectedResourceMetadata bool `json:"protectedResourceMetadata"`
// Declared layer (D2): the transport the registry declares for this
// remote, verdict-bearing when it is the deprecated "sse".
DeclaredTransport string `json:"declaredTransport,omitempty"`
Verdict string `json:"verdict"`
Reasons []string `json:"reasons,omitempty"`
Warnings []string `json:"warnings,omitempty"`
}
ReadinessSignal is the raw 2026-07-28 readiness evidence for one server, gathered from its first conformant remote, plus the verdict derived from it. Every field is an observable; the verdict is a pure function of them.
type RemoteSignal ¶
type RemoteSignal struct {
URL string `json:"url"`
Type string `json:"type,omitempty"`
Status string `json:"status"` // reachable|unreachable|server_error|not_found
HTTPStatus int `json:"httpStatus,omitempty"`
Conformance string `json:"conformance,omitempty"` // initialize_ok|auth_gated|reachable_nonconformant
Probe string `json:"probe,omitempty"` // get|initialize
IDEchoed *bool `json:"idEchoed,omitempty"` // did the initialize response echo the JSON-RPC id
Detail string `json:"detail,omitempty"`
// tools/list probe, run with the official MCP client after a conformant
// initialize. A completed session that lists tools is the strongest keyless
// proof that this is a real, working MCP server.
ToolsStatus string `json:"toolsStatus,omitempty"` // ok|empty|error|connect_failed
ToolCount int `json:"toolCount,omitempty"`
ToolNames []string `json:"toolNames,omitempty"`
// initialize-response evidence, persisted only on a conformant handshake
// (Conformance == initialize_ok). These are the raw observables a spec-
// readiness classification is computed from downstream; the probe records,
// it does not judge.
ProtocolVersion string `json:"protocolVersion,omitempty"` // version the server answered with
Capabilities []string `json:"capabilities,omitempty"` // sorted top-level server capability keys
SessionIssued *bool `json:"sessionIssued,omitempty"` // response carried an Mcp-Session-Id header
// contains filtered or unexported fields
}
RemoteSignal is the raw remote-endpoint probe result.
type RepoSignal ¶
type RepoSignal struct {
Kind string `json:"kind"` // github|other|none
Status string `json:"status"` // alive|archived|missing|error|unprobed|none
HTTPStatus int `json:"httpStatus,omitempty"`
Archived bool `json:"archived,omitempty"`
PushedAt string `json:"pushedAt,omitempty"`
AgeDays *int `json:"ageDays,omitempty"`
Stars *int `json:"stars,omitempty"`
License string `json:"license,omitempty"`
URL string `json:"url,omitempty"`
Detail string `json:"detail,omitempty"`
}
RepoSignal is the raw repository probe result.
type Result ¶
type Result struct {
Name string `json:"name"`
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
RegistryStatus string `json:"registryStatus,omitempty"`
Version string `json:"version,omitempty"`
Verdict Verdict `json:"verdict"`
Reasons []string `json:"reasons"`
Checks []Check `json:"checks"`
Signals Signals `json:"signals"`
AliveEntrypoints int `json:"aliveEntrypoints"`
ProbedEntrypoints int `json:"probedEntrypoints"`
CheckedAt string `json:"checkedAt"` // YYYY-MM-DD, UTC
// Readiness is the 2026-07-28 spec-readiness pass, run against the first
// conformant remote. Nil when the server has no keylessly reachable MCP
// endpoint: that is the "unknown" bucket, absence of evidence recorded as
// absence. Orthogonal to Verdict, which stays a pure health measure.
Readiness *ReadinessSignal `json:"readiness,omitempty"`
}
Result is the per-server probe outcome: a verdict, the reasons behind it, a display-ready check list, and the raw signals for machine consumers. Title and Description are carried through unchanged from the registry (see registry.Server) so a downstream index page has a human title and a meta description without a second registry lookup; both are empty when the target was not resolved from the registry (a bare repo or remote URL) or when the registry itself has no title for that server.
type ServerJSONSignal ¶ added in v0.2.0
type ServerJSONSignal struct {
Status string `json:"status"` // valid|invalid|no_schema|absent|error
Schema string `json:"schema,omitempty"`
Errors []string `json:"errors,omitempty"`
}
ServerJSONSignal is the result of validating the server's published server.json against its declared JSON Schema.
type Signals ¶
type Signals struct {
Repo RepoSignal `json:"repo"`
Packages []PackageSignal `json:"packages"`
Remotes []RemoteSignal `json:"remotes"`
ServerJSON ServerJSONSignal `json:"serverJson"`
}
Signals is the full raw evidence behind a verdict.
type Verdict ¶
type Verdict string
Verdict is the overall health classification of a server.
const ( Healthy Verdict = "healthy" // at least one live entrypoint and nothing broken Degraded Verdict = "degraded" // usable, but something is broken Dead Verdict = "dead" // registry-deleted, or every probed entrypoint is broken Unknown Verdict = "unknown" // only un-probeable entrypoints declared )
Verdict values, from best to worst health.