MACP

API Reference

This is the reference for all 22 gRPC RPCs exposed by the MACP Runtime on macp.v1.MACPRuntimeService. The default endpoint is 127.0.0.1:50051, configurable via MACP_BIND_ADDR.

For protocol-level transport semantics, see the protocol transports documentation.

Protocol Handshake

Initialize

Every client session should begin with an Initialize call to negotiate the protocol version and discover runtime capabilities.

rpc Initialize(InitializeRequest) returns (InitializeResponse)

The client sends its supported protocol versions in descending preference order. The runtime selects the highest mutually supported version and returns it along with its identity, capabilities, and supported modes.

Request fields:

FieldTypeRequiredDescription
supported_protocol_versionsrepeated stringYesVersions in descending preference
client_infoClientInfoNoClient name, version, description
capabilitiesCapabilitiesNoClient capabilities

Response fields:

FieldTypeDescription
selected_protocol_versionstringSelected mutual version
runtime_infoRuntimeInfoname: "macp-runtime", version: "0.4.0"
capabilitiesCapabilitiesRuntime capabilities (streaming, cancellation, policy, etc.)
supported_modesrepeated stringAll supported mode identifiers
instructionsstringOptional human-readable guidance

Returns UNSUPPORTED_PROTOCOL_VERSION if no mutual version exists.

Capabilities advertised: sessions.stream, sessions.list_sessions, sessions.watch_sessions, cancellation.cancel_session, progress.progress, manifest.get_manifest, mode_registry.list_modes, mode_registry.list_changed, roots.list_roots, roots.list_changed, policy_registry.register_policy, policy_registry.list_policies, policy_registry.list_changed.

Message Transport

Send

The primary RPC for submitting messages. Accepts a single envelope and returns an acknowledgement indicating whether the message was accepted.

rpc Send(SendRequest) returns (SendResponse)

Envelope fields:

FieldTypeDescription
macp_versionstringMust be "1.0"
modestringMode identifier (empty for signals)
message_typestring"SessionStart", "Proposal", "Commitment", "Signal", etc.
message_idstringUnique ID for deduplication
session_idstringTarget session (empty for signals)
senderstringOverridden by runtime with authenticated identity
timestamp_unix_msint64Client timestamp (informational)
payloadbytesProtobuf-encoded mode-specific payload

Ack fields:

FieldTypeDescription
okboolWhether the message was accepted
duplicateboolTrue if message_id was already processed
message_idstringEcho of the submitted ID
session_idstringSession the message was applied to
accepted_at_unix_msint64Server acceptance timestamp
session_stateSessionStateSession state after processing
errorMACPErrorPresent when ok is false

The runtime overrides envelope.sender with the authenticated identity. If the envelope contains a non-empty sender that does not match the authenticated identity, the request is rejected with UNAUTHENTICATED.

StreamSession

Provides bidirectional streaming scoped to a single session. Clients send envelopes and receive all accepted envelopes for that session in real time.

rpc StreamSession(stream StreamSessionRequest) returns (stream StreamSessionResponse)

The first envelope on the stream binds it to a session_id. All subsequent envelopes must target the same session. Responses contain either an accepted envelope or an application-level error (the stream stays open for application errors). If the client falls behind the broadcast buffer, the stream terminates with ResourceExhausted.

Passive subscribe (RFC-MACP-0006-A1). A client may observe a session without sending envelopes by sending a request frame where envelope is absent and subscribe_session_id is set. The runtime replays the session's accepted history starting at log index after_sequence (0 = replay from session start) and then delivers live envelopes on the same stream. A single frame must not contain both an envelope and subscribe_session_id -- the stream terminates with InvalidArgument if both are set. Subscribes bind the stream to the given session just like a first envelope; mixing session IDs on the same stream is rejected. Authorization: the caller must be the session initiator, a declared participant, or hold the is_observer identity capability. Non-participants receive an inline FORBIDDEN error frame and the stream stays open.

Session Lifecycle

GetSession

Retrieves metadata and current state for a session.

rpc GetSession(GetSessionRequest) returns (GetSessionResponse)

Returns SessionMetadata with the session's mode, state, TTL deadline, bound versions, participants, per-participant activity summaries, and initiator identity. Only the session initiator and declared participants can query a session.

ListSessions

Enumerates metadata for every session currently held in the registry (including terminal sessions still within the retention window).

rpc ListSessions(ListSessionsRequest) returns (ListSessionsResponse)

Returns a sessions array of SessionMetadata entries. Authentication is required; the RPC is not filtered by caller identity, so callers should apply their own participation or tenancy checks before exposing results to end users.

WatchSessions

Server-streaming RPC for observing session lifecycle transitions across the runtime.

rpc WatchSessions(WatchSessionsRequest) returns (stream WatchSessionsResponse)

On connect, the runtime emits one Created event per session currently in the registry (initial sync), then streams live SessionLifecycleEvent entries as sessions are Created, Resolved, or Expired. Each event carries event_type, the current SessionMetadata snapshot, and observed_at_unix_ms. The underlying broadcast channel has a bounded capacity -- slow subscribers that fall behind will miss events, so consumers should reconcile with ListSessions on reconnect.

CancelSession

Allows the session initiator to terminate a session. This is a core control-plane operation -- mode authorization does not apply.

rpc CancelSession(CancelSessionRequest) returns (CancelSessionResponse)

Request fields: session_id (string), reason (string, optional).

Only the session initiator can cancel. The runtime writes a SessionCancelPayload to the log with cancelled_by set to the authenticated sender. If the session is already terminal, the current state is returned without error.

Discovery

GetManifest

Returns the runtime's full capability manifest, including all supported modes (standards-track and extensions), content types, and identity information.

rpc GetManifest(GetManifestRequest) returns (GetManifestResponse)

ListModes

Returns descriptors for standards-track modes only. Extension modes are excluded.

rpc ListModes(ListModesRequest) returns (ListModesResponse)

Each ModeDescriptor includes the mode identifier, version, title, description, determinism class, participant model, accepted message types, terminal message types, and schema URIs.

ListRoots

Discovers available resource roots.

rpc ListRoots(ListRootsRequest) returns (ListRootsResponse)

Returns a list of Root entries, each with a uri and name.

Extension Mode Lifecycle

ListExtModes

Returns descriptors for extension modes, including both built-in extensions (like ext.multi_round.v1) and dynamically registered ones.

rpc ListExtModes(ListExtModesRequest) returns (ListExtModesResponse)

RegisterExtMode

Dynamically registers a new extension mode. The mode identifier must not be empty, must not already exist, and must not use the reserved macp.mode.* namespace. Requires can_manage_mode_registry on the auth identity.

rpc RegisterExtMode(RegisterExtModeRequest) returns (RegisterExtModeResponse)

UnregisterExtMode

Removes a dynamically registered extension mode. Built-in modes cannot be unregistered.

rpc UnregisterExtMode(UnregisterExtModeRequest) returns (UnregisterExtModeResponse)

PromoteMode

Promotes an extension mode to standards-track status, optionally assigning a new identifier.

rpc PromoteMode(PromoteModeRequest) returns (PromoteModeResponse)

Governance Policy

RegisterPolicy

Registers a governance policy definition. The runtime validates the rules against the target mode's schema and enforces conditional constraints (for example, weighted algorithm requires a non-empty weights map). The built-in policy.default cannot be overwritten.

rpc RegisterPolicy(RegisterPolicyRequest) returns (RegisterPolicyResponse)

See the Policy page for JSON rule examples and validation details.

UnregisterPolicy, GetPolicy, ListPolicies

Standard CRUD operations for the policy registry. UnregisterPolicy cannot remove policy.default. ListPolicies accepts an optional mode filter.

rpc UnregisterPolicy(UnregisterPolicyRequest) returns (UnregisterPolicyResponse)
rpc GetPolicy(GetPolicyRequest) returns (GetPolicyResponse)
rpc ListPolicies(ListPoliciesRequest) returns (ListPoliciesResponse)

Streaming Watches

WatchModeRegistry

Server-streaming RPC that sends a notification on connection and then fires whenever the mode registry changes (register, unregister, or promote).

rpc WatchModeRegistry(WatchModeRegistryRequest) returns (stream WatchModeRegistryResponse)

WatchRoots

Server-streaming RPC for root change notifications.

rpc WatchRoots(WatchRootsRequest) returns (stream WatchRootsResponse)

WatchSignals

Server-streaming RPC that delivers ambient signal broadcasts. Signals have empty session_id and empty mode, carry a SignalPayload with signal_type, data, optional confidence, and optional correlation_session_id. Signals never enter session history.

rpc WatchSignals(WatchSignalsRequest) returns (stream WatchSignalsResponse)

WatchPolicies

Server-streaming RPC that fires when policies are registered or unregistered.

rpc WatchPolicies(WatchPoliciesRequest) returns (stream WatchPoliciesResponse)

Authentication

The runtime applies a resolver chain in this order:

  1. JWT bearer (when MACP_AUTH_ISSUER is set): Authorization: Bearer <jwt>. The JWT's sub claim becomes the sender; macp_scopes carries capability flags (allowed_modes, can_start_sessions, max_open_sessions, can_manage_mode_registry, is_observer).
  2. Static bearer (when MACP_AUTH_TOKENS_* is set): Authorization: Bearer <token> or x-macp-token: <token> header. The opaque token is mapped to an AuthIdentity via the configured token file.
  3. Dev-mode fallback (when neither JWT nor static bearer is configured): any Authorization: Bearer <value> header authenticates the caller as sender <value> with all capabilities. Intended only for local development.
  4. Reject: Returns UNAUTHENTICATED.

See the Getting Started guide for token configuration examples.

Rate Limiting

The runtime enforces per-sender sliding-window rate limits:

LimitDefaultEnvironment variable
Session starts per minute60MACP_SESSION_START_LIMIT_PER_MINUTE
Messages per minute600MACP_MESSAGE_LIMIT_PER_MINUTE

When a limit is exceeded, the runtime returns RATE_LIMITED.