docs: clarify plugin inheritance in README
Rewrite the Plugin System section to make the extends/inheritance mechanism clear — show that default extends gate + content-pipeline, explain hook inheritance and conflict resolution rules. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
37
README.md
37
README.md
@@ -149,29 +149,46 @@ mcpctl apply -f state.yaml
|
||||
|
||||
## Plugin System (ProxyModel)
|
||||
|
||||
ProxyModel is mcpctl's plugin system. Each project is assigned a **plugin** that controls how Claude interacts with its servers. Plugins are composed from two layers: **TypeScript plugins** (MCP middleware hooks) and **YAML pipelines** (content transformation stages).
|
||||
ProxyModel is mcpctl's plugin system. Each project is assigned a **plugin** that controls how Claude interacts with its servers.
|
||||
|
||||
There are two layers:
|
||||
- **Plugins** — TypeScript hooks that intercept MCP requests/responses (gating, tool filtering, etc.)
|
||||
- **Pipelines** — YAML-defined content transformation stages (pagination, summarization, etc.)
|
||||
|
||||
### Built-in Plugins
|
||||
|
||||
| Plugin | Includes gating | Content pipeline | Description |
|
||||
Plugins compose through inheritance. A plugin can `extend` another plugin and inherit all its hooks:
|
||||
|
||||
```
|
||||
gate → gating only (begin_session + prompt delivery)
|
||||
content-pipeline → content transformation only (pagination, section-split)
|
||||
default → extends both gate AND content-pipeline (inherits all hooks from both)
|
||||
```
|
||||
|
||||
| Plugin | Gating | Content pipeline | Description |
|
||||
|--------|:-:|:-:|---|
|
||||
| **default** | Yes | Yes | Gate + content pipeline. The default for all projects. |
|
||||
| **gate** | Yes | No | Gating only — `begin_session` gate with prompt delivery. |
|
||||
| **content-pipeline** | No | No | Content transformation only — no gating. |
|
||||
| **gate** | Yes | No | `begin_session` gate with prompt delivery |
|
||||
| **content-pipeline** | No | Yes | Content transformation (paginate, section-split) |
|
||||
| **default** | Yes | Yes | Extends both — gate + content pipeline combined |
|
||||
|
||||
The `default` plugin doesn't reimplement anything — it inherits the gating hooks from `gate` and the content hooks from `content-pipeline`. Custom plugins can extend built-in ones the same way.
|
||||
|
||||
**Gating** means Claude initially sees only a `begin_session` tool. After calling it with a task description, relevant prompts are delivered and the full tool list is revealed. This keeps Claude's context focused.
|
||||
|
||||
```bash
|
||||
# Create a gated project (default behavior)
|
||||
# Gated with content pipeline (default — extends gate + content-pipeline)
|
||||
mcpctl create project home --server my-ha --proxy-model default
|
||||
|
||||
# Create an ungated project (direct tool access, no gate)
|
||||
mcpctl create project tools --server grafana --proxy-model content-pipeline
|
||||
# Ungated, content pipeline only
|
||||
mcpctl create project tools --server my-grafana --proxy-model content-pipeline
|
||||
|
||||
# Gated only, no content transformation
|
||||
mcpctl create project docs --server my-docs --proxy-model gate
|
||||
```
|
||||
|
||||
### Plugin Hooks
|
||||
|
||||
TypeScript plugins intercept MCP requests/responses at specific lifecycle points:
|
||||
Plugins intercept MCP requests/responses at specific lifecycle points. When a plugin extends another, it inherits all the parent's hooks. If both parent and child define the same hook, the child's version wins.
|
||||
|
||||
| Hook | When it fires |
|
||||
|------|--------------|
|
||||
@@ -186,7 +203,7 @@ TypeScript plugins intercept MCP requests/responses at specific lifecycle points
|
||||
| `onPromptsList` | `prompts/list` — can filter prompts |
|
||||
| `onPromptGet` | `prompts/get` — can intercept prompt reads |
|
||||
|
||||
Plugins compose via `extends` — the `default` plugin extends both `gate` and `content-pipeline`, inheriting all their hooks.
|
||||
When multiple parents define the same hook, lifecycle hooks (`onSessionCreate`, `onSessionDestroy`) chain sequentially. All other hooks require the child to override — otherwise it's a conflict error.
|
||||
|
||||
### Content Pipelines
|
||||
|
||||
|
||||
Reference in New Issue
Block a user