Core Messages
Message Format
Section titled “Message Format”All PCP protocol messages use JSON-RPC 2.0 as the framing format. Every message includes a protocol version, a method identifier, structured parameters, and a correlation ID for response matching.
{ "jsonrpc": "2.0", "id": 1, "method": "query.capabilities", "params": { "app_id": "org.example.app", "tier": 1 }}The id field is a monotonically increasing integer supplied by the caller. Responses carry the same id so the caller can match them to outstanding requests. Notifications (pushed events) omit the id field entirely.
Message Categories
Section titled “Message Categories”PCP defines six message categories. Each category groups methods by purpose and permission scope.
| Category | Prefix | Purpose |
|---|---|---|
| Registration | register.* |
Declare capabilities and adapters to PCP Core |
| Query | query.* |
Request state, metadata, and context from the system |
| Invocation | invoke.* |
Execute capabilities and actions on target surfaces |
| Event | subscribe.* / unsubscribe.* |
Manage event subscriptions |
| Management | revoke.*, health.* |
Administrative and lifecycle operations |
| Response | (return value or error) | Success and error envelopes for all request types |
Registration Messages
Section titled “Registration Messages”Registration messages declare capabilities and adapter bindings to PCP Core. They run at startup or when an application gains focus.
register.capability
Section titled “register.capability”Registers a capability manifest for an application. The manifest declares what operations the application exposes and at what trust level.
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
app_id |
string | yes | Application identifier (reverse-DNS) |
manifest |
object | yes | Capability manifest object |
manifest.version |
string | yes | Manifest schema version |
manifest.capabilities |
array | yes | List of capability declarations |
manifest.signature |
string | yes | Manifest signature for validation |
Returns:
| Field | Type | Description |
|---|---|---|
registered |
boolean | Whether the manifest was accepted |
capability_ids |
array of string | IDs assigned to each registered capability |
Example request:
{ "jsonrpc": "2.0", "id": 1, "method": "register.capability", "params": { "app_id": "org.example.mail", "manifest": { "version": "1.0", "capabilities": [ { "name": "compose", "tier": 1, "trust_level": "confirm", "parameters": [ { "name": "recipient", "type": "string" }, { "name": "subject", "type": "string" }, { "name": "body", "type": "string" } ] } ], "signature": "a1b2c3d4..." } }}Example response:
{ "jsonrpc": "2.0", "id": 1, "result": { "registered": true, "capability_ids": ["org.example.mail.compose"] }}register.adapter
Section titled “register.adapter”Binds an adapter to a surface type. Adapters translate between native surface APIs and the PCP data model.
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
surface_type |
string | yes | Surface type this adapter handles (e.g. wayland, x11, atspi2) |
adapter_id |
string | yes | Unique adapter identifier |
supported_tiers |
array of integer | yes | Which capability tiers this adapter supports |
Returns:
| Field | Type | Description |
|---|---|---|
bound |
boolean | Whether the adapter was bound successfully |
adapter_id |
string | Confirmed adapter identifier |
Query Messages
Section titled “Query Messages”Query messages read state from PCP Core and the compositor. They are idempotent and carry no side effects.
query.capabilities
Section titled “query.capabilities”Returns the capability manifest for a given application or for all registered applications.
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
app_id |
string | no | Filter to a specific application. Omit for all. |
tier |
integer | no | Filter by capability tier. Omit for all. |
Returns:
| Field | Type | Description |
|---|---|---|
capabilities |
array of object | Matching capability declarations |
Example request:
{ "jsonrpc": "2.0", "id": 2, "method": "query.capabilities", "params": { "app_id": "org.example.mail" }}Example response:
{ "jsonrpc": "2.0", "id": 2, "result": { "capabilities": [ { "id": "org.example.mail.compose", "name": "compose", "tier": 1, "trust_level": "confirm", "app_id": "org.example.mail" } ] }}query.elements
Section titled “query.elements”Retrieves the semantic element tree for a surface. Elements are UI components with roles, labels, bounds, and actions.
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
surface_id |
string | yes | Target surface identifier |
focus_id |
string | no | Focus on a specific element subtree |
Returns:
| Field | Type | Description |
|---|---|---|
root |
object | Root element of the semantic tree |
root.children |
array | Child elements |
root.role |
string | Semantic role (button, text, list, etc.) |
root.label |
string | Accessible label |
root.bounds |
object | Bounding rectangle |
Example request:
{ "jsonrpc": "2.0", "id": 3, "method": "query.elements", "params": { "surface_id": "surface-42" }}Example response:
{ "jsonrpc": "2.0", "id": 3, "result": { "root": { "id": "el-0", "role": "window", "label": "Mail", "bounds": { "x": 0, "y": 0, "w": 800, "h": 600 }, "children": [ { "id": "el-1", "role": "button", "label": "Compose", "bounds": { "x": 10, "y": 50, "w": 100, "h": 30 }, "actions": ["activate"] } ] } }}query.surface
Section titled “query.surface”Returns metadata about a specific compositor surface.
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
surface_id |
string | yes | Target surface identifier |
Returns:
| Field | Type | Description |
|---|---|---|
surface_id |
string | Surface identifier |
app_id |
string | Owning application |
title |
string | Surface title |
state |
string | Surface state (focused, minimized, etc.) |
geometry |
object | Position and dimensions |
tier |
integer | Integration tier |
query.session_context
Section titled “query.session_context”Returns the current session context: user identity, active surfaces, focus state, and system conditions relevant to capability routing.
Parameters: None.
Returns:
| Field | Type | Description |
|---|---|---|
session_id |
string | Current session identifier |
focused_surface |
string or null | Currently focused surface ID |
active_surfaces |
array of string | All active surface IDs |
system_state |
object | System-level conditions (input mode, lock state, etc.) |
Invocation Messages
Section titled “Invocation Messages”Invocation messages execute capabilities and actions. They carry permission implications and may require confirmation before execution.
invoke.capability
Section titled “invoke.capability”Executes a named capability on a target application.
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
capability_id |
string | yes | Fully qualified capability identifier |
app_id |
string | yes | Target application |
source |
string | yes | Invocation source (see InvocationSource) |
params |
object | no | Capability-specific parameters |
Returns: A CapabilityResult object.
Example request:
{ "jsonrpc": "2.0", "id": 10, "method": "invoke.capability", "params": { "capability_id": "org.example.mail.compose", "app_id": "org.example.mail", "source": "SystemIntelligence", "params": { "recipient": "user@example.com", "subject": "Meeting notes", "body": "Here are the notes from today." } }}Example response (success):
{ "jsonrpc": "2.0", "id": 10, "result": { "status": "success", "data": { "message_id": "msg-789", "thread_id": "thread-12" } }}Example response (confirmation required):
{ "jsonrpc": "2.0", "id": 10, "error": { "code": -32005, "message": "Confirmation required", "data": { "capability_id": "org.example.mail.compose", "confirmation_type": "send", "undo_window_ms": 15000, "description": "Send email to user@example.com" } }}invoke.action
Section titled “invoke.action”Performs a structural action on a semantic element (activate, select, set value, scroll).
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
element_id |
string | yes | Target element identifier |
action |
string | yes | Action name (activate, select, set_value, scroll) |
value |
any | no | Action value (for set_value, select, etc.) |
surface_id |
string | yes | Surface containing the element |
Returns:
| Field | Type | Description |
|---|---|---|
executed |
boolean | Whether the action was performed |
result |
object | Action-specific result data |
Event Messages
Section titled “Event Messages”Event messages manage subscriptions to compositor and application events. Events are pushed from PCP Core to subscribers as JSON-RPC notifications.
subscribe.events
Section titled “subscribe.events”Subscribe to one or more event types for a surface or application.
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
event_types |
array of string | yes | Event types to subscribe to |
surface_id |
string | no | Scope to a specific surface |
app_id |
string | no | Scope to a specific application |
Returns:
| Field | Type | Description |
|---|---|---|
subscription_id |
string | Subscription identifier for later unsubscribe |
active_events |
array of string | Confirmed active event subscriptions |
Example request:
{ "jsonrpc": "2.0", "id": 20, "method": "subscribe.events", "params": { "event_types": ["surface.focus_changed", "element.state_changed"], "app_id": "org.example.mail" }}Pushed event (notification, no id):
{ "jsonrpc": "2.0", "method": "surface.focus_changed", "params": { "subscription_id": "sub-abc123", "surface_id": "surface-42", "focused": true, "timestamp": 1699876543 }}unsubscribe.events
Section titled “unsubscribe.events”Cancel an active event subscription.
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
subscription_id |
string | yes | Subscription to cancel |
Returns:
| Field | Type | Description |
|---|---|---|
cancelled |
boolean | Whether the subscription was cancelled |
Management Messages
Section titled “Management Messages”Management messages handle administrative operations: revoking application access, checking system health, and managing PCP Core state.
revoke.app
Section titled “revoke.app”Revokes all capabilities for an application. The application is removed from the capability registry and all active subscriptions are terminated.
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
app_id |
string | yes | Application to revoke |
reason |
string | no | Reason for revocation (logged to audit trail) |
Returns:
| Field | Type | Description |
|---|---|---|
revoked |
boolean | Whether the revocation succeeded |
terminated_subscriptions |
integer | Number of subscriptions terminated |
health.check
Section titled “health.check”Returns the health status of PCP Core, its adapters, and connected subsystems.
Parameters: None.
Returns:
| Field | Type | Description |
|---|---|---|
status |
string | Overall health status (ok, degraded, down) |
adapters |
array of object | Per-adapter health status |
uptime_ms |
integer | PCP Core uptime in milliseconds |
active_sessions |
integer | Number of active sessions |
pending_confirmations |
integer | Outstanding confirmation requests |
Response Model
Section titled “Response Model”Every PCP request returns either a success result or a structured error. The response envelope follows JSON-RPC 2.0 conventions with PCP-specific error codes.
Success Response
Section titled “Success Response”{ "jsonrpc": "2.0", "id": 1, "result": { "status": "success", "data": { } }}Error Response
Section titled “Error Response”{ "jsonrpc": "2.0", "id": 1, "error": { "code": -32004, "message": "Permission denied", "data": { } }}Error Codes
Section titled “Error Codes”PCP reserves the standard JSON-RPC error range (-32700 through -32603) and defines protocol-specific codes in the -32000 range.
Standard JSON-RPC Errors
Section titled “Standard JSON-RPC Errors”| Code | Name | Description |
|---|---|---|
| -32700 | PARSE_ERROR |
Invalid JSON was received by the server. |
| -32600 | INVALID_REQUEST |
The JSON sent is not a valid Request object. |
| -32601 | METHOD_NOT_FOUND |
The method does not exist or is not available. |
| -32602 | INVALID_PARAMS |
Invalid method parameter(s). |
| -32603 | INTERNAL_ERROR |
Internal JSON-RPC error. |
PCP Protocol Errors
Section titled “PCP Protocol Errors”| Code | Name | Description |
|---|---|---|
| -32000 | APP_NOT_FOUND |
Application with the specified ID is not running. |
| -32001 | SURFACE_NOT_FOUND |
Surface with the specified ID does not exist. |
| -32002 | ELEMENT_NOT_FOUND |
Element with the specified ID does not exist. |
| -32003 | ACTION_NOT_SUPPORTED |
The requested action is not supported by the element. |
| -32004 | PERMISSION_DENIED |
The requester does not have permission for this action. |
| -32005 | CONFIRMATION_REQUIRED |
Action requires user confirmation before execution. |
| -32006 | CONFIRMATION_DENIED |
User denied the confirmation request. |
| -32007 | CONFIRMATION_EXPIRED |
Confirmation window expired without response. |
| -32008 | TARGET_AMBIGUOUS |
Target resolution returned multiple candidates with similar confidence. |
| -32009 | EXECUTION_TIMEOUT |
Action did not complete within the timeout period. |
| -32010 | APP_UNRESPONSIVE |
Target application is not responding to requests. |
| -32011 | NO_ATSPI2_SUPPORT |
AT-SPI2 is not available for this element or application. |
| -32012 | INPUT_SIMULATION_FAILED |
Input simulation was attempted but failed. |
| -32015 | CAPABILITY_NOT_FOUND |
The requested capability does not exist for the target app. |
| -32016 | MANIFEST_INVALID |
Capability manifest failed validation. |
| -32017 | MANIFEST_SIGNATURE_INVALID |
Capability manifest signature verification failed. |
| -32018 | RATE_LIMITED |
Too many requests. Slow down. |
| -32019 | CAPTURE_FAILED |
Screen capture failed (surface not available). |
| -32020 | TEXT_TOO_LARGE |
Requested text range is too large. Use pagination. |
| -32025 | WINE_BRIDGE_ERROR |
Wine accessibility bridge reported an error. |
The data field in error responses carries additional context when available. For confirmation errors, it includes the confirmation type, undo window, and human-readable description. For target errors, it includes the identifier that failed to resolve.
Invocation Source
Section titled “Invocation Source”Every capability invocation carries an InvocationSource that identifies who initiated the action. This field is used by the permission model to determine trust boundaries and confirmation requirements.
pub enum InvocationSource { SystemIntelligence,}System Intelligence is currently the only invocation source. The enumeration exists as an extension point for future sources, such as external agents with restricted privilege or user-initiated macro playback.
Type Definitions
Section titled “Type Definitions”CapabilityResult
Section titled “CapabilityResult”The return type for successful capability invocations.
pub struct CapabilityResult { pub status: ResultStatus, pub data: Option<serde_json::Value>,}
pub enum ResultStatus { Success, Partial, Deferred,}Success means the capability completed fully. Partial indicates the capability executed but could not finish all requested operations. Deferred means the capability acknowledged the request and will complete asynchronously.
CapabilityError
Section titled “CapabilityError”The error type for failed capability invocations.
pub struct CapabilityError { pub code: i32, pub message: String, pub data: Option<serde_json::Value>,}The code field uses the PCP error code range defined above. The message is a human-readable description. The data field carries structured error context, such as the specific element that could not be found or the confirmation details that the user needs to respond to.
Wire Protocol
Section titled “Wire Protocol”PCP defines two transport modes. The choice of transport is determined by deployment context, not by message type. The same JSON-RPC message format applies regardless of transport.
In-Process Transport
Section titled “In-Process Transport”When System Intelligence and PCP Core run inside the compositor process, communication uses direct language-level function calls through trait objects. No serialization, no IPC, no socket. Data is shared via Arc<T> references with zero copy. This is the primary transport for embedded deployments.
External Transport
Section titled “External Transport”When PCP is accessed from an external process (debugging tool, test harness, or remote agent), messages serialize to JSON and travel over a Unix domain socket or TCP connection. The wire format is newline-delimited JSON-RPC 2.0, one message per line. Frame captures and other large binary payloads use shared memory file descriptors passed alongside the JSON message.
Both transports produce identical JSON-RPC messages at the application layer. The transport is an implementation detail, not a protocol concern.