Skip to main content

Plugins

mage-remote-run supports a plugin system that allows you to extend its functionality with custom commands and event hooks. Plugins are standard Node.js modules that export a default function.

Managing Plugins

You can manage plugins using the plugin command namespace.

Register a Plugin

To register an installed plugin (either global or local):

mage-remote-run plugin register <package-name-or-path>

Examples:

# Register a globally installed npm package
mage-remote-run plugin register mage-remote-run-plugin-audit

# Register a local plugin by absolute path
mage-remote-run plugin register /path/to/my-plugin

Unregister a Plugin

To remove a plugin from the configuration:

mage-remote-run plugin unregister <package-name-or-path>

List Plugins

To see all currently registered plugins:

mage-remote-run plugin list

Developing Plugins

A plugin is a JavaScript module (ESM) that exports a default asynchronous function. This function receives an context object containing the application state and helpers.

Plugin Structure

Create a new directory for your plugin and initialize it:

mkdir my-plugin
cd my-plugin
npm init -y

Ensure package.json has "type": "module".

Create an index.js:

import chalk from 'chalk';

/**
* @param {Object} context
* @param {import('commander').Command} context.program - The Commander.js program instance
* @param {Object} context.config - The user configuration object
* @param {Object|null} context.profile - The active profile (if any)
* @param {import('events').EventEmitter} context.eventBus - The application event bus
* @param {Object} context.EVENTS - Event name constants
*/
export default async function(context) {
const { program, eventBus, EVENTS } = context;

// 1. Register a new command
program.command('hello')
.description('Say hello from a plugin')
.option('-n, --name <name>', 'Name to greet', 'World')
.action((options) => {
console.log(chalk.green(`Hello ${options.name}!`));
});

// 2. Hook into application events
eventBus.on(EVENTS.BEFORE_COMMAND, (data) => {
const { thisCommand, actionCommand, profile } = data;
// Logic to execute before any command runs
// e.g., Logging, validation, etc.
});
}

Available Events

EVENTS.INIT (init)

Triggered after plugins are loaded and before commands are fully processed.

  • Payload: The appContext object (program, config, profile, eventBus, EVENTS).

EVENTS.BEFORE_COMMAND (beforeCommand)

Triggered right before a command action is executed.

  • Payload:
    • thisCommand: The command object attached to the listener (Commander internal).
    • actionCommand: The specific command being executed (Commander internal).
    • profile: The active mage-remote-run profile object (or null).

EVENTS.AFTER_COMMAND (afterCommand)

Triggered right after a command action has finished execution.

  • Payload: Same as EVENTS.BEFORE_COMMAND.

EVENTS.MCP_START (mcpStart)

Triggered when the MCP server initializes (but before it starts listening or connecting).

  • Payload:
    • server: The McpServer instance.
    • options: The options passed to the mcp command.

Context Isolation

When running as an MCP server, mage-remote-run creates isolated contexts for tool discovery and execution.

  • Plugins are loaded into these isolated contexts.
  • Events emitted within a tool execution (like BEFORE_COMMAND) are scoped to that execution's event bus.
  • Global events like MCP_START are emitted on the main process event bus and are received by the plugin instance loaded at startup.

MCP Support

Commands registered by plugins are automatically discovered and exposed as tools when mage-remote-run is running as an MCP (Model Context Protocol) server. This allows AI agents to utilize your plugin's functionality without additional configuration.

Example

Check out the examples/hello-world-plugin directory in the repository for a complete working example.