Understanding the MDXP JSON-RPC 2.0 Protocol in Motrix
MDXP (Motrix Download eXchange Protocol) is a JSON-RPC 2.0-based wire protocol that enables standardized communication between the Motrix desktop application, CLI tools, browser extensions, and headless servers through a single, version-stable API.
The MDXP JSON-RPC 2.0 protocol serves as the communication backbone for the agalwood/Motrix download manager, unifying how different components exchange download commands, task status updates, and error information across multiple transport layers.
What is the MDXP JSON-RPC 2.0 Protocol?
MDXP defines a strict contract for remote procedure calls within the Motrix ecosystem. Unlike ad-hoc IPC mechanisms, the protocol specifies exact method names, request/response schemas, and error codes that every component must follow.
According to the Motrix source code, the protocol enforces JSON-RPC 2.0 compliance on all messages, requiring each payload to include standard fields like jsonrpc: "2.0", method, params, and id. Motrix-specific extensions include custom error codes defined in the @motrix/mdxp package, such as ErrorCodes.CapabilityNotSupported and ErrorCodes.InvalidParams.
How Motrix Implements MDXP
The implementation centers on a centralized dispatcher that validates every request against Zod schemas before execution, ensuring type safety across language boundaries.
Core Dispatcher Architecture
The MdxpDispatcher class in src/core/bridge/mdxp-dispatcher.ts acts as the central registry for all JSON-RPC method handlers. When a request arrives, the dispatcher validates the payload against the registered Zod schema exactly once, then invokes the handler with typed arguments and a MdxpSessionContext object.
This architecture guarantees that CLI tools, browser extensions, and internal UI processes all consume the same validated API surface. The dispatcher handles both synchronous returns and asynchronous errors, serializing responses back into standard JSON-RPC 2.0 format.
Transport Layers
Motrix exposes the MDXP protocol through three primary transports:
- HTTP POST endpoint (
POST /mdxp): Used by the CLI (@motrix/cli) for unary requests and the headless server for remote pairing flows (/mdxp/pair/*) - WebSocket connections (
ws://<host>:<port>/mdxp): Enables real-time bidirectional communication for browser extensions at the default port 16801 - In-process connections: Internal UI components use the same dispatcher without network overhead, maintaining architectural consistency
The src/core/bridge/web-socket-bridge-server.ts file implements the WebSocket transport, forwarding incoming JSON-RPC messages to the dispatcher and returning serialized responses.
Using the MDXP Protocol
Developers interact with MDXP through the @motrix/mdxp package, which provides connection factories and type definitions.
Creating a Client Connection
The createMdxpConnection function establishes a communication channel with the Motrix desktop application:
import { createMdxpConnection } from '@motrix/mdxp'
const mdxp = createMdxpConnection({
endpoint: 'http://127.0.0.1:16801', // default MDXP bridge port
token: process.env.MOTRIX_MDXP_TOKEN, // optional for remote LAN access
})
// Submit a new download task
await mdxp.call('download/submit', {
uri: 'https://example.com/file.iso',
saveDir: '/Users/me/Downloads',
})
// Retrieve current tasks
const tasks = await mdxp.call('task/list', {})
console.log(tasks)
Source: src/core/bridge/__tests__/unary-mdxp.test.ts demonstrates this pattern for JSON-RPC-over-HTTP clients.
Registering Method Handlers
Server-side components register handlers using the dispatcher's type-safe registration API:
import { MdxpDispatcher } from './mdxp-dispatcher'
import { DownloadSubmitParamsSchema } from '@motrix/mdxp'
const dispatcher = new MdxpDispatcher()
dispatcher.register(
'download/submit',
DownloadSubmitParamsSchema,
async (params, ctx) => {
// params is fully typed and validated by Zod
const taskId = await ctx.downloadManager.submit(params)
return { taskId }
}
)
Source: src/core/bridge/mdxp-dispatcher.ts contains the core implementation of this registration system.
WebSocket Bridge Implementation
The WebSocket server wraps the dispatcher to handle persistent connections:
import { WebSocket } from 'ws'
ws.on('message', async (msg: string) => {
const response = await this.dispatcher.handleMessage(msg)
ws.send(JSON.stringify(response))
})
Source: src/core/bridge/web-socket-bridge-server.ts shows how raw WebSocket messages convert to JSON-RPC responses.
Key Components and File Structure
| File Path | Responsibility |
|---|---|
src/core/bridge/mdxp-dispatcher.ts |
Central registry for method validation and dispatch using Zod schemas |
src/core/bridge/web-socket-bridge-server.ts |
WebSocket transport layer for browser extensions and remote agents |
src/main/bridge/index.ts |
Entry point that initializes the MDXP bridge and binds HTTP/WS servers |
src/core/bridge/__tests__/mdxp-dispatcher.test.ts |
Unit tests verifying schema validation, error codes, and method routing |
These files collectively ensure that the MDXP JSON-RPC 2.0 protocol operates as a single source of truth across the entire Motrix ecosystem.
Summary
- MDXP is a JSON-RPC 2.0 protocol that standardizes communication between Motrix components
- The
MdxpDispatcherinsrc/core/bridge/mdxp-dispatcher.tsvalidates all requests using Zod schemas before execution - Three transport layers—HTTP POST, WebSocket, and in-process—expose the same API surface
- The
@motrix/mdxppackage provides TypeScript types and connection factories for client implementations - Default communication occurs on port 16801 with optional token-based authentication for remote access
Frequently Asked Questions
What transport mechanisms does the MDXP protocol support?
The MDXP JSON-RPC 2.0 protocol supports HTTP POST requests for unary calls, WebSocket connections for real-time streaming, and in-process communication for internal UI components. The HTTP endpoint at /mdxp handles CLI requests, while WebSocket connections at /mdxp serve browser extensions, all unified through the same dispatcher logic in src/core/bridge/mdxp-dispatcher.ts.
How does Motrix ensure type safety in MDXP messages?
Motrix uses Zod schemas generated in the @motrix/mdxp package to validate every incoming JSON-RPC request. The MdxpDispatcher validates payloads against schemas like DownloadSubmitParamsSchema before handlers receive typed arguments, preventing runtime errors and ensuring that method signatures remain consistent across the desktop app, CLI, and extensions.
Can external applications communicate with Motrix using MDXP?
Yes, external applications can communicate with Motrix by connecting to the MDXP bridge endpoint at ws://localhost:16801/mdxp or http://localhost:16801/mdxp. For remote access over LAN, applications must provide an authentication token via the MOTRIX_MDXP_TOKEN environment variable or request headers. The headless server also exposes pairing endpoints at /mdxp/pair/* for device-code flows.
Where are MDXP error codes defined in the Motrix codebase?
MDXP-specific error codes such as ErrorCodes.CapabilityNotSupported and ErrorCodes.InvalidParams are defined in the @motrix/mdxp package, which bundles the protocol's Zod schemas and TypeScript types. These error codes follow the JSON-RPC 2.0 specification while extending it with Motrix-specific failure states for download operations and capability mismatches.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →