Capability discovery, registration, and endpoint authentication
This document defines capability discovery, registration, and endpoint authentication in the current draft. JSON schemas define the wire grammar; the runtime obligations below apply even where JSON Schema cannot prove enforcement.
Discovery and honest capabilities
A harness MUST make its manifest available independently of session.start.
hooks/capabilities is a JSON-RPC request with params.protocolVersion; no session
or event is required. The correlated success result contains protocolVersion
and manifest. Discovery MUST NOT start a session or execute a model/tool call.
An authenticated discovery endpoint uses its configured transport authentication.
Discovery and interception success payloads cannot be combined in one response.
manifest.events declares exact events, delivery modes, and capabilities;
gaps identifies uncovered paths and reasons. transports, authentication,
toolPaths, contentCategories, and limits describe supported deployment
features, coverage, and nonnegative limits. Implementations MUST expose applicable
coverage and limits and MUST NOT interpret omitted coverage as universal support.
The manifest requires events, gaps, transports, authentication,
toolPaths, contentCategories, limits, managedPolicy, and
correlationIdentityFields. Unknown limits remain absent and MUST be explained
in gaps; absence never means unlimited. The limits object recognizes
maxUploadBytes, maxContinuations, minTimeoutMs, and maxTimeoutMs.
managedPolicy has scopes (user, project, managed) and disableable;
managed scope requires false. Correlation fields are string field paths, not
verified identity. Intercept entries require capabilities; observation-only
entries MUST NOT claim effects or an interception-only mode. Capability discovery is not an
identity assertion; a manifest MUST NOT contain an identity block.
Per-request advertisements MUST narrow manifest capabilities to the actual
boundary, path, permissions, and remaining allowance. Unsupported targets and
operations MUST fail explicitly; they MUST NOT be replaced by another operation.
The existing draft encoding uses modify.<target>.replace and .merge booleans;
at least one MUST be true for an advertised target. modify, flow, and inject
option blocks require their matching effect and vice versa. Empty target sets,
empty injection delivery choices, and unsupported operation values are invalid.
Unknown object fields are ignored; they do not advertise or authorize new effects
or operations. Unsupported effect types and operation values in responses MUST
reject the entire response atomically, without applying any member.
The receiver MUST apply ordered append without deduplication for message-list
and text-part-list merge, and shallow object merge only when the actual target
and supplied value are objects. Text and attachment bytes are not object merge
targets. Replace uses the target’s canonical shape. The
manifest is not proof that an effect was actually applied.
Registration
Subscriptions and their identifiers remain harness-local configuration. JSON-RPC IDs correlate pending requests; neither those IDs nor caller-supplied metadata authorize uploads. Upload authorization derives from independently configured credentials and receiver policy.
Receivers MUST ignore unknown registration and configuration fields, including fields in capability advertisements and control-state objects. They MUST validate recognized fields and MAY warn about ignored fields. Ignoring an unfamiliar field does not activate its semantics or relax validation of recognized fields, effect types, or operation values.
hooks[].transport configures event delivery; hooks[].authentication configures
that endpoint only. Subscriptions select intercept or observe. Interception
requires a timeout and failure policy. Observation MUST NOT specify them.
Matching subscriptions in both modes MAY coexist and MUST NOT be deduplicated
across modes. Wildcards are entire families (tool.*) or *, not arbitrary
patterns. An intercept wildcard selects only boundaries supporting interception.
Every intercept and observe subscription MUST specify content with a required
default and optional category-name keys using body, metadata, or omit.
The default MUST cover unfamiliar categories; no implicit content policy applies. includeNative defaults to false. Optional
filters.toolKinds and filters.paths are optimization hints, never grounds for
dropping calls of unknown kind. Managed scope MUST set disableable: false.
Implementations MUST advertise whether they honor scope and fail unsupported
mandatory policy rather than silently degrade.
hooks[].subscriptions[].upload has endpoint, timeoutMs, maxBytes, and an
optional independent auth object. It configures non-text, non-JSON media attachment uploads, not retrieval or
ordinary text delivery.
There is no backend contentReceiver compatibility alias. Absent upload
credentials MUST NOT inherit event credentials. A credential MAY be configured
for both endpoints only when its resource and permissions cover both. See
the binary upload binding for framing and confirmation.
Authentication bindings
Servers advertise authentication requirements; clients select identities and enforce
local trust policy. A server advertisement MUST NOT select a local secret, client
certificate, workload platform, or trusted issuer on the client’s behalf.
manifest.authentication lists implementation support, not per-endpoint requirements
or a negotiation protocol. hooks/capabilities is not an authentication bootstrap.
Remote HTTP MUST use TLS with receiver validation. Plain HTTP is reserved for an explicitly trusted local test/process boundary, never an implicit downgrade. Secret values MUST NOT occur in registration, events, native metadata, logs, denial reasons, or JSON-RPC error data. Credential references name deployment-managed secrets, not portable secret values. Payload identifiers and upload references MUST NOT grant authority.
HTTP without an explicit binding
When endpoint authentication is absent, the client MUST attempt the configured
endpoint without an HTTP credential, subject to local policy and TLS identity
selection below. Absence does not mean anonymous-only: a successful response may
be accepted, but an OAuth-protected endpoint MUST be handled using the protected
resource discovery procedure in MCP 2025-11-25 Authorization,
RFC 9728, and authorization-server
metadata (RFC 8414 or the OpenID
Connect Discovery fallback specified by MCP). This adopts that discovery procedure,
not MCP transport framing or arbitrary authentication negotiation.
OAuth-protected servers MUST publish RFC 9728 protected-resource metadata with at
least one authorization server and provide discovery through a 401 challenge’s
resource_metadata parameter or the standard well-known locations, as specified
by MCP. These are OAuth requirements, not a generic AHP auth advertisement format.
On HTTP 401, clients MUST parse WWW-Authenticate and use its resource_metadata
URL when present. Otherwise they MUST try the RFC 9728 well-known locations in
MCP’s order: endpoint-path-specific, then origin-root. Protected-resource metadata
identifies the resource and its authorization servers. Clients MUST validate the
resource identifier under RFC 9728 section 3.3, select an authorization server
per local trust policy, and discover its metadata using MCP’s ordered OAuth/OIDC
well-known locations. AHP defines no additional challenge, metadata field, or
method to negotiate bearer, mTLS, or workload credentials.
Discovery is untrusted input, not permission to send credentials. Clients MUST
validate HTTPS URLs, server certificates, exact discovered issuer identity,
resource/audience, scope requirements, and token validity. Challenge scopes describe
requirements, not consent: clients MUST request only locally permitted scopes and
MUST NOT assume scopes_supported is the required set for a particular request. Clients MUST request
resource-bound tokens using RFC 8707 and MUST NOT use a token for another resource.
Clients MUST apply local destination/SSRF policy to metadata, registration,
authorization, and token endpoints, including DNS resolution and every redirect;
metadata MUST NOT authorize access to otherwise forbidden local or private targets.
Redirects require explicit endpoint policy and MUST NOT forward credentials to a
different origin or resource. Clients MUST NOT send secrets, workload assertions,
or client credentials to arbitrary advertised URLs. A cached identity or token
MUST remain bound to its trusted issuer, resource, client, and authorized scope.
Client registration and selection of a supported OAuth flow remain client policy. Interactive authorization MUST use authorization code with PKCE and validated redirect URIs/state; unattended client credentials require explicit issuer support. Clients MAY expose host UI/callbacks to prepare or renew authorization, but these are not AHP methods, hook events, or effects. If interaction is unavailable, unsupported, denied, cancelled, or cannot complete within the remaining budget, authorization fails operationally; clients MUST NOT silently switch identities.
Explicit endpoint bindings
An explicit binding takes precedence over automatic HTTP discovery. Failure to resolve or use it MUST NOT trigger an automatic switch to OAuth, another binding, or unauthenticated delivery. Discovery within an explicit OAuth preset MUST obey its issuer, resource, scope, and client constraints.
bearer: configure exactly one oftokenEnvortokenRef, bound to this endpoint. If resolution fails, do not send the request. Send the resolved token in exactly one Authorization header. A challenge cannot choose a different local secret.oauth: an optional preset configures HTTPSissuer, protectedresource,clientId,flow, optionalscopes, and optionalclientSecretRef. It uses the standards-based discovery and validation above; it is not required merely to encounter an OAuth-protected endpoint.
Deployment-specific authentication
AHP-AUTH-001 — MUST. Portable endpoint authentication bindings MUST use bearer or oauth; workload identity, federation, and client-certificate configuration are deployment-specific, not portable AHP authentication variants.
Deployments MAY use workload identity, federation, or client certificates beneath or alongside AHP through HTTP/TLS configuration or credential-provider extensions. These mechanisms are outside portable AHP configuration and capability claims; AHP defines no workload profile requirement, plugin protocol, or discovery format for them. A credential provider MAY supply a token through a portable bearer reference without making its acquisition mechanism part of AHP.
TLS client certificate selection uses preconfigured identity and local endpoint/trust policy before HTTP; it MUST NOT depend on an HTTP challenge. Validate certificate chains, validity, intended usage, and receiver names. A certificate copied into an HTTP header does not establish a verified TLS identity. Resources MUST authorize the verified client principal. Deployment-specific workload/federation credentials MUST be validated for issuer proof, signature, audience, validity, and authorization under local trust policy. Deployment-specific authentication MUST preserve the credential isolation, trust validation, failure, deadline, cancellation, and no-downgrade requirements in this section.
Event and upload endpoints apply these rules independently, including discovery, explicit binding precedence, and token/cache resource boundaries. An absent upload binding MUST NOT inherit event credentials. Reuse requires explicit client policy and independently validated resource and permission coverage for both endpoints.
Failure and timing
Authentication resolution, discovery, acquisition, refresh, and validation failures are operational failures. The configured interception failure policy determines whether the underlying harness operation continues or is denied; it does not permit unauthenticated delivery or change the underlying operation. Observations remain best effort. Unsupported authentication MUST prevent authenticated retries and further delivery; an initial credential-free request is not a failure fallback. Protected servers MUST reject unauthorized requests before processing the event or storing uploaded bytes. Authentication retries MUST be bounded, occur only after an authentication rejection (not an ambiguous successful delivery), and respect cancellation.
The interception deadline starts at dispatch and includes any authentication work needed for that dispatch, including discovery, acquisition, refresh, interaction, and retries. No authentication step resets or extends the deadline. Cancellation MUST cancel the operation’s pending authentication wait and prevent late delivery. A harness-shared acquisition needed by other active callers need not be cancelled; the cancelled operation MUST NOT resume delivery when that acquisition completes. Authorization MAY be prepared before dispatch under a separate bounded, cancellable preparation budget; content upload authentication and transfer use the independent upload budget. Any enclosing hook-call budget also bounds preparation, authentication waits, and upload transfer. Pre-dispatch preparation MUST NOT become an unbounded wait hidden from policy. See failure semantics and uploads.
Authentication establishes the verified workload/client principal, not a human operator, organization, role, or delegation. Additional claims require trusted proof. Credential rotation and acquisition MUST NOT create hook lifecycle events.
Client authentication integration
An SDK MAY delegate credential acquisition and challenge handling to a harness-owned provider rather than implement an OAuth manager. Delegation does not relax the authentication requirements above. The provider receives the selected registration authentication binding, destination, backend identity, independent event/upload purpose, and operation cancellation context. Challenge handling includes the authentication response and an identity for the credential attempt so a stale rejection need not invalidate newer credentials. Secret values MUST NOT appear in diagnostics or credential-attempt identifiers.
The portable bearer and OAuth bindings both yield bearer credentials for the AHP HTTP endpoint. Environment variables and credential references are resolved by the configured provider; OAuth client secrets are used at the token endpoint, not sent as AHP endpoint credentials. Missing configured secrets and unsupported mechanisms fail explicitly, never by anonymous fallback. HTTP/TLS deployment extensions remain separate transport configuration.
The harness may own discovery policy, token exchange, refresh, coordination, persistence, and explicit authorization UI. SDK discovery/exchange helpers are optional conveniences; no particular token cache, refresh scheduler, browser implementation, or durable store interface is required by AHP. The protocol client retains responsibility for endpoint isolation, safe credential application, bounded challenged retry, and validation of the final response. Choosing an external provider does not authorize an otherwise unsafe replay.
Extension policy
Existing protocol envelopes retain their extension behavior. Authentication, capability, and control configuration objects MUST ignore unknown fields and validate recognized fields; implementations MAY warn about ignored fields. Unknown fields never authorize operations or credentials. Unknown effect types and operation values are unsupported semantics, not ignorable fields: a response containing them MUST be rejected atomically. Native payloads, tool arguments, and task state retain their own extension behavior.
Event-semantic capability bounds
Named definitions in capabilities.schema.json constrain both interception advertisements and discovery entries by event. They bound effects, modification targets, and flow operations; they do not create native capabilities. In particular, model.response.after supports response modification and flow stop, return is not a task-state mutation operation, and tool.before cannot request continuation. Message is valid at any interceptable event. General flow rules permit stop on supported turn/tool/permission/model boundaries even when an event-table row omits it. Dynamic advertisements MUST narrow these bounds to actual enforceable support.
Compaction before permits only modify(instructions); after permits only
modify(summary). A before return(summary) skips generation but retains all
applicable after-boundary controls and downstream application. The after event
is a result boundary before downstream installation/consumption, not proof of a
confirmed context update. Only advertise controls the native harness can enforce.
Elicitation modes and selection-aware inline text parts are defined by the pinned MCP
interaction binding. user.elicitation.request permits deny, return, and
message only; it does not advertise request modification. Its parsed MCP params
are not a model request message-list target. user.elicitation.result permits
modify(content) only over the parsed MCP answer object for an accepted form
result, not its action or whole result. user.message.outbound uses the same
content target name for canonical message.messages lists. Hosts MUST enforce
these boundary-specific types using the request-correlated response schemas;
the standalone effect schema’s typed alternatives do not grant cross-boundary
authority. See typed payload contracts. Object merge remains shallow;
ordinary model and user-message targets retain list append semantics.
tool.after modify(output) targets canonical items messages, with whole-list
replacement and ordered append merge, not an undeclared native JSON output
binding. Objects and bare parts are not output values.
No absent mapping permits invented operations or policy bypass.
return is bounded to tool.before, model.request.before,
context.compact.before, and user.elicitation.request. continue is bounded to
turn.finish.before and tool.after. Continuation advertisements include
nonnegative remainingContinuations and continuationCount; the static maximum
and dynamic allowance are enforceable runtime commitments. inject.context
advertises append: true and supported deliverAt values (now, next_turn).
Absent targets or false operations do not grant support. Optional request state
can carry flow, accumulated instructions, injections and candidate provenance,
but does not establish authenticated identity.
Coverage and deliberate exclusions
There are no implicit event bundles or capability tiers. Each advertised event, mode, effect, target, operation, path, content category, transport and authentication mechanism needs evidence of its actual implementation. Before and after coverage are independent. Synthesized observation coverage does not create interception support. Unsupported native paths remain explicit gaps, not invented standard capabilities. A legacy adapter’s manifest derives from its quirk registry, not from a catalogue count or a hand-authored synthetic test manifest.
This draft adds no required MCP inventory, agent entity, context ledger, reasoning lifecycle, durable deferred approval, retry effect, generic event collection, response-cycle accounting entity, replay/cursor/acknowledgement, content receipt-renewal protocol, or transactional rollback. HTTP, stdio and in-process bindings share logical messages; evidence for one deployment binding does not establish the others. External approval remains bounded by interception: there is no defer or reverse-resolution channel, and mandatory approval must fail closed. Late approval cannot authorize a later attempt.