Creating Plugins
Build custom plugins to extend FrontMCP with cross-cutting capabilities like caching, authorization, logging, and more.Plugin Architecture
FrontMCP plugins use the@Plugin decorator and typically extend DynamicPlugin. They can:
- Register providers — Services available to the plugin and exported to the host app
- Contribute tools, resources, and skills — Add capabilities when the plugin is attached
- Intercept flows via hooks — Run code before/after specific stages using
@ToolHookand@ListToolsHook - Accept configuration — Via
init()for runtime customization - Extend metadata — Add custom fields to tool metadata
Basic Plugin
Registering a Plugin
Attach plugins at the app level:Adding Hooks
Plugins intercept flow stages using@ToolHook and @ListToolsHook decorators:
Hook Timing
.Will(stage)— runs before the stage.Did(stage)— runs after the stage
Priority
Lower numbers run first:Dynamic Providers
For plugins that create providers based on configuration:Options named like plugin metadata, and option-derived tools
init(options) spreads your options into the plugin’s metadata, so an option whose name matches a list-valued metadata key (tools, resources, prompts, skills, adapters, plugins, exports) used to be read as that list. RememberPlugin.init({ tools: { enabled: true } }) crashed at startup for that reason. A value that is not an array under one of those keys is now an option and is left out of the metadata; an array still contributes, as before.
A plugin that registers tools only when an option asks for it declares static dynamicTools(options), the counterpart of dynamicProviders. Its tools are added to the ones from @Plugin({ tools }) and from an array tools option:
dynamicTools runs for init(options); init({ inject, useFactory }) takes its tools from the @Plugin metadata, since the options are not known until the factory runs.
Extending Tool Metadata
Plugins can add custom fields to tool metadata via global type augmentation:cache), declare it with
enforcesMetadata on the plugin class whose hooks enforce it:
requireMfa and no hook of such a plugin reaches it (in tools/call for tools and
agents, resources/read for resources, prompts/get for prompts, skills:filter for skills) refuses to start with
UnenforcedMetadataError. The key is known as soon as the plugin class is loaded. FrontMCP’s own approval and
featureFlag fields are checked even when their plugin is never loaded.
Contributing Tools and Skills
Plugins can contribute tools and skills via the@Plugin decorator:
Publishing Plugins
package.json
Next Steps
Plugin Guide
Full plugin API reference with hooks, scopes, and DynamicPlugin details
Create a Plugin
Step-by-step tutorial building a real-world plugin
Cache Plugin
Study the built-in cache plugin implementation
Community
Share your plugin with the community