Plugins - Installation & Usage
Note
Plugins as such receive no support by the main developers of MeshCentral. If you experience problems with MeshCentral please make sure to disable all plugins before further troubleshooting!
Use Cases
Certain feature requests may not be suitable for all MeshCentral users and thus are available as a plugin. Furthermore users can develop their own plugins - as described further below - to extend functionality or benefit from integrating MeshCentral into their existing application environment.
List of publically available plugins
https://github.com/topics/meshcentral-plugin
Installation of a plugin
- First please make sure that you enable plugins in the configuration
"plugins": { "enabled": true },
- Restart MeshCentral if you needed to change the configuration.
- Log into MeshCentral as full administrator.
- Go my
My Server->Plugins, then hit the Download plugin button. - A dialog opens requesting a URL, e.g. put in: https://raw.githubusercontent.com/ryanblenis/MeshCentral-ScriptTask/master/config.json
- The plugin pops up in the plugin list below the download button, you can now configure and enable/disable it.
Plugins - Development & Hooks
Note
Plugins as such receive no support by the main developers of MeshCentral. If you experience problems with MeshCentral please make sure to disable all plugins before further troubleshooting!
Overview
Not all feature requests may be suitable for all MeshCentral users and thus can't be integrated into MeshCentral directly. Hwoever, Instead of maintaining a complete fork of MeshCentral it is much easier to extend MeshCentral's functionality using hooks and writing plugins for it.
Anatomy of a plugin:
- plugin_name/
-- config.json
-- plugin_name.js
-- modules_meshcore/ // optional
--- plugin_name.js // optional
Plugin Configuration File
A valid JSON object within a file named config.json in the root folder of your project. An example:
{
"name": "Plugin Name",
"shortName": "plugin_name",
"version": "0.0.0",
"author": "Author Name",
"description": "Short Description of the plugin",
"hasAdminPanel": false,
"homepage": "https://www.example.com",
"changelogUrl": "https://raw.githubusercontent.com/User/Project/master/changelog.md",
"configUrl": "https://raw.githubusercontent.com/User/Project/master/config.json",
"downloadUrl": "https://github.com/User/Project/archive/master.zip",
"repository": {
"type": "git",
"url": "https://github.com/User/Project.git"
},
"versionHistoryUrl": "https://api.github.com/repos/User/Project/tags",
"meshCentralCompat": ">0.4.3"
}
Configuration File Properties
| Field | Required | Type | Description |
|---|---|---|---|
| name | Yes | string | a human-readable name for the plugin |
| shortName | Yes | string | an alphanumeric, unique short identifier for the plugin (will be used to access your functions throughout the project |
| version | Yes | string | the current version of the plugin |
| author | No | string | the author's name |
| description | Yes | string | a short, human-readable description of what the plugin does |
| hasAdminPanel | Yes | boolean | true or false, indicates whether or not the plugin will offer its own administrative interface |
| homepage | Yes | string | the URL of the projects homepage |
| changelogUrl | Yes | string | the URL to the changelog of the project |
| configUrl | Yes | string | the URL to the config.json of the project |
| downloadUrl | Yes | string | the URL to a ZIP of the project (used for installation/upgrades) |
| repository | Yes | JSON object | contains the following attributes |
| repository.type | Yes | string | valid values are git and in the future, npm will also be supported. |
| repository.url | Yes | string | the URL to the project's repository |
| versionHistoryUrl | No | string | the URL to the project's versions/tags |
| meshCentralCompat | Yes | string | the minimum version string of required compatibility with the MeshCentral server, can be formatted as "0.1.2-c" or ">=0.1.2-c". Currently only supports minimum version, not full semantic checking. |
Plugin Hooks
In essence, hooks are locations in the code which enable developers to tap into a module to either provide alternative behavior or to respond to an event.
These are separated into the following categories depending on the type of functionality the plugin should offer.
- Web UI, to modify the MeshCentral admin interface
- Back End, to modify core functionality of the server and communicate with the Web UI layer as well as the Mesh Agent (Node) layer to send commands and data
- Mesh Agent (Node), to introduce functionality to each agent
Web UI Hooks
onDeviceRefreshEnd: called when a device is selected in the MeshCentral web interfaceregisterPluginTab: callable when a device is selected in the MeshCentral web interface to register a new tab for plugin data, if required. Accepts an object, or function that returns an object, with the following properties: { tabId: "yourShortNameHere", tabTitle: "Your Display Name"}. A tab and div with the associated ID and title will be created for your useonDesktopDisconnect: called when a remote desktop session is disconnectedonWebUIStartupEnd: called when the page has loaded for the first time after a login / refreshgoPageStart: called before page changes take effect. Passes 2 arguments (: int, : Event) goPageEnd: called after page changes take effect. Passes 2 arguments (: int, : Event)
Exports
Any function can be exported to the Web UI layer by adding the name of the function to an exports array in the plugin object.
Back End Hooks
server_startup: called once when the server starts (or when the plugin is first installed)hook_agentCoreIsStable: called once when an agent initially checks inhook_processAgentData: called each time an agent transmits data back to the serverhook_userLoggedIn: called when a user has logged into the web interfacehook_setupHttpHandlers: called before all http handlers are setup
Mesh Agent
Use of the optional file plugin_name.js in the optional folder modules_meshcore will include the file in the default meshcore file sent to each endpoint. This is useful to add functionality on each of the endpoints.
Plugin Permissions
Plugins can define custom permissions that administrators can manage through MeshCentral's permissions dialog. This allows fine-grained access control at three levels: Global, Mesh (Device Group), and Node (Device).
Registering Permissions
Use registerPermissions to define what permissions your plugin supports:
parent.registerPermissions('plugin_name', {
'can_access': {
title: 'Access Plugin',
desc: 'Can access the plugin functionality',
default: 'allowed'
},
'can_edit': {
title: 'Edit',
desc: 'Can edit values',
default: 'allowed'
},
'can_delete': {
title: 'Delete',
desc: 'Can delete values',
default: 'denied'
}
});
Each permission has:
- key: Unique identifier for the permission (e.g., can_access, can_edit)
- title: Human-readable name shown in the UI
- desc: Description shown in the UI
- default: Default state when no explicit permission is set
Default Value States
The default field controls what happens when no explicit permission is set. Valid values are:
| Value | Description |
|---|---|
allowed |
Users have permission by default |
denied |
Users are denied by default |
Permission Cascade
Permissions follow a hierarchy where lower levels inherit from higher ones:
- Global - Applied to all users across all meshes and nodes
- Mesh (Device Group) - Applied to users within a specific mesh
- Node (Device) - Applied to users on a specific node
When a permission is set to inherited or is not configured, the system looks up the hierarchy:
- Node → Mesh → Global → Default (from permission definition)
Checking Permissions
Use getAccessPermissions to check if a user has a specific permission. This is function async and returns a function that can be called to check individual permissions:
// Check permissions - pass nodeid to resolve mesh automatically
var hasAccess = await obj.getAccessPermissions(userObj, nodeId);
// Check specific permission
if (!hasAccess('can_access')) {
// Return error response (see Error Handling below)
return;
}
// Continue with action...
The getAccessPermissions function:
- Accepts user object and a context object or string of the nodeId
- Context can include:
- nodeid: Node ID to check (mesh will be resolved automatically)
- meshid: Mesh ID to check directly
- Returns a function that takes a permission key and returns true/false
Complete Example
See the MeshCentral-RegEdit plugin for a complete working example that implements:
- Permission registration with multiple permission levels
- Async permission checking in serveraction
- Detailed error messages for permission denied scenarios
Structure
Much of MeshCentral revolves around returning objects for your structures, and plugins are no different. Within your plugin you can traverse all the way up to the web server and MeshCentral Server classes to access all the functionality those layers provide. This is done by passing the current object to newly created objects, and assigning that reference to a parent variable within that object.
Ping-Pong
If you build a plugin which makes use of meshrelay.ashx, keep in mind to either handle ping-pong messages (serverPing, serverPong) on the control channel or to request MeshCentral to not send such messages through sending the noping=1 parameter in the connection URL. For a deeper sight search for "PING/PONG" in meshrelay.js.
Versioning
Versioning your plugin correctly and consistently is essential to ensure users of your plugin are prompted to upgrade when it is available. Semantic versioning is recommended.
Changelog
A changelog is highly recommended so that your users know what's changed since their last version.
Sample Plugin
MeshCentral-Sample is a simple plugin that, upon disconnecting from remote desktop, prompts the user to enter a manual event (note), pre-filled in with the date and timestamp.