Upgrade plugins
This page is evergreen guidance for keeping an activated plugin on the current context and activation contract. It does not describe release history.
Current context contract
Section titled “Current context contract”A plugin imports:
from memscope_mcp.extensions.base import ExtensionContext, LuaExtensionfrom memscope_mcp.plugins import PluginBaseRegistration uses these session-bound fields in this order when a migration diagnostic points to the contract:
ctx.sessionctx.table_factoryctx.hook_manager
The plugin stores state on its instance and uses lifecycle callbacks for process-bound resources. The raw runtime is private.
Replace unsupported access patterns:
| Do not use | Use |
|---|---|
ctx.lua |
ctx.table_factory for guarded result tables |
ctx.engine.lua |
ordinary values and ctx.table_factory |
ExtensionContext.lua |
ctx.session, ctx.table_factory, or ctx.hook_manager |
memscope_mcp.tools.hooking.HOOK_MANAGER |
ctx.hook_manager |
module-level SESSION |
the session passed through ctx.session and lifecycle callbacks |
| module/session globals for plugin state | attributes on the plugin instance |
openProcess remains a supported Lua attach alias, and DebugSession.modules remains a defensive compatibility view; neither exposes the raw Lua runtime or module-level globals.
Activation and refresh
Section titled “Activation and refresh”The runtime scans only $MEMSCOPE_HOME/plugins/*.py, nonrecursively, sorted by activated filename, excluding underscore-prefixed files. Bundled _contrib files are catalog/install sources, not an automatic second root.
memscope-mcp install-plugin <name> is non-overwriting by default; memscope-mcp install-plugin <name> --force overwrites the activated copy. Package upgrades preserve saved scripts and activated plugin copies; they do not rewrite scripts or refresh activated copies implicitly.
Structured migration diagnostic
Section titled “Structured migration diagnostic”An isolated plugin failure emits one record on the default stderr channel and one on the default session_log channel. The record uses the exact schema name memscope-plugin-diagnostic/v1 and one of these codes:
PLUGIN_CONTEXT_INCOMPATIBLE— a structurally recognized access to a removed Lua runtime or hook-manager global;PLUGIN_LOAD_FAILED— any other import, metadata, construction, registration, or ordinary plugin failure.
The record has these ordered top-level fields:
{ "schema": "memscope-plugin-diagnostic/v1", "severity": "warning", "code": "PLUGIN_LOAD_FAILED", "plugin": { "filename": "example.py", "declared_name": "example" }, "cause": { "type": "RuntimeError", "message": "Plugin failure details are not included; inspect the activated plugin locally." }, "guidance": { "url": "https://memscope.esrc.dev/plugins/upgrading/", "required_context_fields": [ "ctx.session", "ctx.table_factory", "ctx.hook_manager" ] }, "channel": "stderr"}The paired session-log record uses "channel": "session_log". Filename and declared-name values are bounded basenames/strings. Cause type and message are bounded; arbitrary paths, plugin-controlled exception text, and secrets are not exposed. Sink failures remain isolated.
The diagnostic guidance route is a canonical destination. It does not imply that a web site is deployed.
Repair checklist
Section titled “Repair checklist”- Inspect the activated filename named by the diagnostic.
- Replace raw runtime and global-manager access with the supported context fields.
- Move process state to the plugin instance.
- Add
on_process_attachedandon_process_detachingfor target-bound resources. - Run the plugin in a disposable
MEMSCOPE_HOME. - Check
listLuaFunctions("<plugin-name>")andgetLoadedExtensions()after restart. - Expect any
--forcecopy from a bundled source to overwrite the local file.
See Plugin authoring, Plugin lifecycle, Plugin troubleshooting, and Plugin API.