How the Codex Plugin Communicates with the Codex App Server via JSON-RPC

The Codex plugin uses a typed JSON-RPC 2.0 client that serializes requests to a configurable broker or direct HTTP endpoint while maintaining a persistent WebSocket or Server-Sent Events channel to receive asynchronous notifications from the server.

The openai/codex-plugin-cc repository implements a type-safe communication layer that enables bidirectional data flow between the Codex plugin and the Codex app server. This architecture leverages generated TypeScript definitions to enforce strict contracts for remote procedure calls and real-time event handling.

Type-Safe Method Definitions

The communication protocol relies on compile-time type checking to ensure all JSON-RPC exchanges match the server's expected interface.

The AppServerMethodMap Interface

The plugins/codex/scripts/lib/app-server-protocol.d.ts file exports AppServerMethodMap, a comprehensive TypeScript interface that maps every available RPC method to its request parameters and response shape. This map validates calls such as thread/start against the ThreadStartParams type before serialization, preventing malformed payloads from reaching the network layer.

The CodexAppServerClient Architecture

The client implementation handles transport logic, request lifecycle management, and notification routing.

Client Configuration

The CodexAppServerClient accepts an options object defined by CodexAppServerClientOptions. By default, the client targets the broker endpoint at http://localhost:3000/broker, though it can be reconfigured to communicate directly with the app server's HTTP endpoint when broker functionality is disabled.

import {
  CodexAppServerClient,
  CodexAppServerClientOptions,
} from "./app-server-protocol";

const opts: CodexAppServerClientOptions = {
  brokerEndpoint: "http://localhost:3000/broker",
  clientInfo: { name: "my-codex-plugin", version: "1.0.0" },
};

const client = new CodexAppServerClient(opts);

Sending JSON-RPC Requests

When invoking a method, the client constructs a standard JSON-RPC 2.0 payload containing the jsonrpc, id, method, and params fields. The client POSTs this payload to the configured endpoint and returns a Promise that resolves with the typed response.

import { ThreadStartParams } from "./app-server-protocol";

const startParams: ThreadStartParams = {
  // Parameters matching the generated type definition
};

client
  .request("thread/start", startParams)
  .then((response) => {
    console.log("Thread started:", response.threadId);
  })
  .catch((err) => console.error("RPC error:", err));

Internally, the client generates a payload structure identical to:

{
  "jsonrpc": "2.0",
  "id": "a1b2c3d4",
  "method": "thread/start",
  "params": {
    // Fields from ThreadStartParams
  }
}

Bidirectional Communication Channels

The architecture supports full-duplex communication through separate mechanisms for synchronous requests and asynchronous events.

WebSocket and Server-Sent Events

To receive server-initiated messages, the client establishes a persistent connection using either WebSocket or Server-Sent Events (SSE). This channel remains open to listen for notifications that lack an id field, distinguishing them from request responses according to the JSON-RPC 2.0 specification.

Notification Handling

The AppServerNotificationHandler interface processes incoming messages defined by the ServerNotification type in app-server-protocol.d.ts. The client delegates notifications such as turn/start and review/start to registered callbacks that can update UI state or trigger follow-up RPC calls.

client.onNotification((msg) => {
  switch (msg.method) {
    case "turn/start":
      console.log("Turn started:", msg.params);
      break;
    case "review/start":
      console.log("Review started:", msg.params);
      break;
    // Handle additional notifications as needed
  }
});

Key Source Files

The JSON-RPC implementation spans several critical files in the repository:

  • plugins/codex/scripts/lib/app-server-protocol.d.ts: Contains the AppServerMethodMap, ServerNotification, and CodexAppServerClientOptions type definitions that enforce compile-time contracts.
  • plugins/codex/scripts/lib/app-server-client.ts: Implements the concrete CodexAppServerClient class responsible for HTTP transport, JSON serialization, and notification dispatching.
  • plugins/codex/scripts/lib/app-server-types/*: Houses generated models (.generated/app-server-types/...) that feed the protocol definitions with concrete data structures for request and response payloads.

Summary

  • The Codex plugin uses JSON-RPC 2.0 to communicate with the Codex app server through a strictly typed client architecture.
  • The AppServerMethodMap in app-server-protocol.d.ts provides compile-time validation for all RPC methods and their payloads.
  • The CodexAppServerClient sends HTTP POST requests to a broker endpoint (default http://localhost:3000/broker) or directly to the app server, serializing ThreadStartParams and other types into standard JSON-RPC requests.
  • WebSocket or SSE connections enable the client to receive asynchronous notifications via the AppServerNotificationHandler, processing events like turn/start without polling.
  • Generated types in app-server-types ensure end-to-end type safety between the plugin and the Codex app server.

Frequently Asked Questions

What protocol does the Codex plugin use to communicate with the app server?

The Codex plugin uses JSON-RPC 2.0 as defined in plugins/codex/scripts/lib/app-server-protocol.d.ts. This protocol structures all remote method calls with a standard envelope containing jsonrpc, id, method, and params fields, enabling both request-response patterns and server-pushed notifications.

How does the Codex plugin handle asynchronous events from the server?

The plugin establishes a persistent connection via WebSocket or Server-Sent Events to listen for notifications. The AppServerNotificationHandler processes incoming messages that lack a JSON-RPC id field—such as turn/start and review/start—allowing the server to push real-time updates without the client explicitly polling.

Where are the TypeScript type definitions for the JSON-RPC methods located?

All type definitions reside in plugins/codex/scripts/lib/app-server-protocol.d.ts, which exports AppServerMethodMap and ServerNotification interfaces. Supporting generated models are stored in the app-server-types subdirectory, providing concrete types for parameters and return values used in the JSON-RPC exchange.

Can the Codex plugin communicate directly with the app server without a broker?

Yes. While the default CodexAppServerClientOptions configuration routes requests through a broker at http://localhost:3000/broker, the client can be reconfigured to send HTTP requests directly to the Codex app server's endpoint. This flexibility allows the plugin to operate in brokerless environments when necessary.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →