Core Concepts
Flows
Named execution pipelines with defined stages (e.g.,
tools:call-tool, http:request)Hook Types
Will (before), Did (after), Around (wrap), Stage (one more step of the stage)
Priority
Within a stage, a lower priority runs first, for Will, Did and Stage hooks alike
Context
The running flow, typed
FlowCtxOf<'flow-name'>: its typed state, logger and provider lookupHook Types
- Will (Before)
- Did (After)
- Around (Wrap)
- Stage (Step)
Runs before a stage executes. Use for:
- Input validation
- Pre-processing
- Short-circuiting execution
- Setting up context
Available Flows
FrontMCP provides pre-defined hooks for common flows. Each flow has its own stages; a hook names one of them:tools/list does not stop a client that knows its name from calling it; gate the call in tools:call-tool too.
You can also create custom flows using
FlowHooksOf('custom-flow-name') for application-specific pipelines.Complete Examples
Example 1: Request Validation & Auditing
Example 2: Error Handling & Retries
AnAround hook sees a failing stage as a rejected next(), and can call next() again to retry it. A Did hook runs only after its stage succeeded, so failures are logged here.
Example 3: Data Transformation Pipeline
Priority System
Priority sets the order within a stage: a lower priority runs first, for Will, Did and Stage hooks alike. Hooks with the same priority run in the order they were registered.
-1000). To run a Did hook after everything else, give it a very high one (1000).
Flow Context
A hook receives the running flow, typedFlowCtxOf<'flow-name'>. It has:
state- The flow’s state, typed per flow (tool,toolContext,input,authInfo,resultMeta, … fortools:call-tool)rawInput- The input the flow was started withlogger- Logger instance for this flowget(token)- Resolves a providerrespond(output)/fail(error)- End the flow with an output or an error
error or metrics member: a Did hook runs only after its stage succeeded, so observe failures from an Around hook. See Hook Context for details.
randomUUID comes from @frontmcp/utils.
Hook Registry API
For advanced use cases, you can programmatically access hooks using the Hook Registry API. This is useful when building custom flow orchestration or when you need to dynamically query which hooks are registered.Accessing the Hook Registry
The registry is the scope’shooks. A hook reaches the scope by resolving the ScopeEntry token; inside a tool, resource or prompt it is this.scope.
Registry Methods
- getFlowHooks
- getFlowHooksForOwner
- getFlowStageHooks
- getClsHooks
Retrieves the plugin and provider hooks registered for a specific flow.
Example: Owner-Scoped Hook Filtering
Best Practices
1. Use Plugins for Reusable Hooks
1. Use Plugins for Reusable Hooks
Package related hooks into plugins to reuse across multiple apps:
2. Set Appropriate Priorities
2. Set Appropriate Priorities
- Validation: Low priority (1-20)
- Transformation: Medium priority (40-60)
- Logging/Metrics (Did hooks): High priority (90-100)
3. Handle Errors Gracefully
3. Handle Errors Gracefully
Throw an MCP error class: a public error such as
InvalidInputError reaches the client with its message and code. A plain Error becomes a generic server error, and in production the client sees only its error id.4. Keep Per-Call Data in the Hook, Not the State
4. Keep Per-Call Data in the Hook, Not the State
The flow state accepts only the keys the flow declares, and a plugin serves every call, so
this is shared. Keep per-call data in a local variable of an Around hook, or in a WeakMap keyed on ctx when separate hooks share it:5. Avoid Heavy Computation in Hooks
5. Avoid Heavy Computation in Hooks
Hooks run for every tool execution. Keep them fast:
- Use caching for expensive operations
- Delegate heavy work to background jobs
- Consider async/non-blocking operations
Links & Resources
Plugin Documentation
Learn more about FrontMCP plugins
Tool Documentation
Understand tool lifecycle and execution
Cache Plugin
See hooks in action with the Cache Plugin