Skip to content

plugin.json reference

Layout Manifest
plugins/<Name>/<Name>.dll plugins/<Name>/plugin.json
plugins/<Name>.dll (loose) plugins/<Name>.plugin.json, if present
source folder plugins/<Name>/ plugins/<Name>/plugin.json, else the [assembly: McPlugin] attribute
source file plugins/<Name>.cs plugins/<Name>.plugin.json, else the [assembly: McPlugin] attribute
no manifest the [PluginInfo] attribute; the id is the lower-cased assembly name, with every character outside a-z 0-9 _ - replaced by _ (at most 32)

The manifest is read before any assembly is loaded: the server builds the dependency graph from manifests alone, then loads in order.

{
"id": "homes",
"name": "Homes",
"version": "1.2.0",
"api": "1.0",
"main": "Homes.HomesPlugin",
"authors": ["Ahmed"],
"description": "Set and teleport to homes.",
"website": "https://example.org",
"depends": ["economy >=1.2"],
"softDepends": ["permissions-ui"],
"loadBefore": ["chat-format"],
"permissions": [
{ "node": "homes.use", "default": "true", "description": "Use /home" }
]
}
Field Type Required Meaning
id string yes stable plugin id: lower-case [a-z0-9_-], 1 to 32 characters. Used for the data folder (plugins/<id>/data/), dependencies and logs. A second plugin with the same id is reported and skipped
name string no display name, also the log prefix (defaults to the id)
version string no plugin version, compared against dependants’ constraints (defaults to 0.0.0)
api string no the API version the plugin was built for, "major.minor". When missing the server assumes 1.0
main string no full name of the plugin class. Default: the first public, non-abstract IPlugin type with a parameterless constructor (a Plugin subclass)
authors string[] no
description string no one line
website string no
depends string[] no hard dependencies: the plugin is skipped if one is missing or too old
softDepends string[] no loaded first when present; the plugin works without them
loadBefore string[] no an edge from this plugin to the named one: this plugin loads first
permissions object[] no each permission node the plugin checks: node, default and description

The default of a permission is true, false, op (the default when absent), op:N (operator level N) or not_op (notop is also accepted).

Unknown fields are ignored (forward compatible). Malformed JSON, a missing or invalid id, an invalid api or permission default are reported with the file path and the line or key. An api the server cannot provide is refused.

A depends / softDepends entry may carry a constraint after the id: "economy >=1.2". Supported operators: >=, >, =, <, <= and ^1.2 (caret: same major, at least that version).

The server declares an API version (ApiVersion.Current, currently 1.0): minor = additive, major = breaking. A plugin loads when its major equals the server’s and its minor is at most the server’s, and is refused otherwise with a message such as plugin 'homes' needs API 1.4, this server provides 1.2. Within a major, no member is removed and no signature changes; new overloads are added instead of optional parameters, and events only gain fields.

A source plugin is a .cs file or a folder of .cs files that the server compiles when it starts (plugins.allow_source, on by default). Its metadata comes from a plugin.json next to the sources, or else from an assembly attribute in them. The attribute carries the same information as the manifest:

[assembly: McPlugin("homes", version: "1.2.0", depends: ["economy >=1.0"])]

Plugins are discovered in plugins/ and ordered by a topological sort of depends, softDepends (only if present) and loadBefore, ties broken by id so the order is deterministic.

Situation Result
missing hard dependency the plugin and everything depending on it is skipped: plugin 'homes' requires 'economy >=1.2' which is not installed
hard dependency too old or too new the same: plugin 'homes' requires 'economy >=1.2' but version 1.1.0 of 'economy' is installed
dependency cycle every plugin on the cycle is skipped and the cycle is printed: dependency cycle: a -> b -> c -> a
a plugin whose OnEnable throws reported as failed to enable; its dependents are skipped with that cause
unload reverse load order; hot reload of a plugin also reloads its hard dependents