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 MdxpDispatcher in src/core/bridge/mdxp-dispatcher.ts validates all requests using Zod schemas before execution
  • Three transport layers—HTTP POST, WebSocket, and in-process—expose the same API surface
  • The @motrix/mdxp package 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:

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 →