|
| 1 | +# Plugin Configuration |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +The `mcpd` daemon supports a plugin subsystem for extending request/response processing. |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## Plugin Categories |
| 10 | + |
| 11 | +!!! info Plugin execution order |
| 12 | + Within each category, plugins execute in the order they appear in the configuration file. |
| 13 | + |
| 14 | +Plugins are organized into categories and execute during specific phases of the request lifecycle. |
| 15 | + |
| 16 | +Categories execute in the order shown below for both request and response phases. |
| 17 | + |
| 18 | +| Order | Category | Purpose | Execution | |
| 19 | +|-------|------------------|----------------------------------------------|------------| |
| 20 | +| 1 | `observability` | Collect metrics and traces (non-blocking) | Parallel | |
| 21 | +| 2 | `authentication` | Validate client identity | Sequential | |
| 22 | +| 3 | `authorization` | Verify permissions after authentication | Sequential | |
| 23 | +| 4 | `rate_limiting` | Enforce request rate limits | Sequential | |
| 24 | +| 5 | `validation` | Check request/response structure and content | Sequential | |
| 25 | +| 6 | `content` | Transform request/response payloads | Sequential | |
| 26 | +| 7 | `audit` | Log compliance and security events | Sequential | |
| 27 | + |
| 28 | +--- |
| 29 | + |
| 30 | +## Plugin Execution Flows |
| 31 | + |
| 32 | +Plugins can execute during one or both flows/phases: |
| 33 | + |
| 34 | +* `request`: Executes during the request phase |
| 35 | +* `response`: Executes during the response phase |
| 36 | + |
| 37 | +--- |
| 38 | + |
| 39 | +## Configuration Format |
| 40 | + |
| 41 | +```toml |
| 42 | +[[servers]] |
| 43 | + name = "api-server" |
| 44 | + package = "uvx::[email protected]" |
| 45 | + tools = ["create", "read", "update", "delete"] |
| 46 | + |
| 47 | +[[plugins.authentication]] |
| 48 | + name = "jwt-auth" |
| 49 | + commit_hash = "abc123" |
| 50 | + required = true |
| 51 | + flows = ["request"] |
| 52 | + |
| 53 | +[[plugins.authentication]] |
| 54 | + name = "api-key-auth" |
| 55 | + flows = ["request", "response"] |
| 56 | + |
| 57 | +[[plugins.authorization]] |
| 58 | + name = "rbac" |
| 59 | + required = true |
| 60 | + flows = ["request"] |
| 61 | + |
| 62 | +[[plugins.observability]] |
| 63 | + name = "metrics" |
| 64 | + flows = ["request", "response"] |
| 65 | +``` |
| 66 | + |
| 67 | +--- |
| 68 | + |
| 69 | +## Plugin Fields |
| 70 | + |
| 71 | +| Field | Type | Required | Description | |
| 72 | +|---------------|---------|----------|------------------------------------------------------| |
| 73 | +| `name` | string | Yes | Name of the plugin binary in the plugins directory | |
| 74 | +| `commit_hash` | string | No | SHA/hash for validating plugin version | |
| 75 | +| `required` | boolean | No | Whether plugin failure should block the request | |
| 76 | +| `flows` | array | Yes | Execution phases: ["request"], ["response"], or both | |
| 77 | + |
| 78 | +--- |
| 79 | + |
| 80 | +## Execution Order |
| 81 | + |
| 82 | +Plugins execute in the order they appear in the configuration file within their category. |
| 83 | + |
| 84 | +```toml |
| 85 | +[[plugins.authentication]] |
| 86 | + name = "jwt-auth" |
| 87 | + flows = ["request"] |
| 88 | + |
| 89 | +[[plugins.authentication]] |
| 90 | + name = "api-key-auth" |
| 91 | + flows = ["request"] |
| 92 | +``` |
| 93 | + |
| 94 | +During the request phase, `jwt-auth` executes first, followed by `api-key-auth`. |
| 95 | + |
| 96 | +--- |
| 97 | + |
| 98 | +## Required Plugins |
| 99 | + |
| 100 | +!!! warning "Required Plugin Failures" |
| 101 | + If a required (serial) plugin fails or rejects a request/response, the overall request is rejected immediately. |
| 102 | + |
| 103 | +Mark plugins as required when their successful execution is critical: |
| 104 | + |
| 105 | +```toml |
| 106 | +[[plugins.authentication]] |
| 107 | + name = "jwt-auth" |
| 108 | + required = true |
| 109 | + flows = ["request"] |
| 110 | +``` |
| 111 | + |
| 112 | +When `required` is not specified or set to `false`, plugin failures are logged but do not block the request. |
| 113 | + |
| 114 | +--- |
| 115 | + |
| 116 | +## Content Mutation |
| 117 | + |
| 118 | +!!! info "Content Plugin Behavior" |
| 119 | + Only plugins in the `content` category may mutate requests or responses. Modified content is passed to the next plugin in the chain. |
| 120 | + |
| 121 | +Content plugins modify the request by setting the modified request in their response. Other plugin categories can only observe or reject requests. |
| 122 | + |
| 123 | +### Example Content Plugin Flow |
| 124 | + |
| 125 | +```toml |
| 126 | +[[plugins.content]] |
| 127 | + name = "encryption" |
| 128 | + flows = ["request"] |
| 129 | + |
| 130 | +[[plugins.content]] |
| 131 | + name = "compression" |
| 132 | + flows = ["request"] |
| 133 | +``` |
| 134 | + |
| 135 | +The `encryption` plugin processes the request first and may modify it. The modified request is then passed to the `compression` plugin. |
| 136 | + |
| 137 | +--- |
| 138 | + |
| 139 | +## Observability Plugin Execution |
| 140 | + |
| 141 | +!!! note "Parallel Execution" |
| 142 | + Observability plugins run in *parallel* and cannot modify requests or responses. |
| 143 | + |
| 144 | +Observability plugins are designed for metrics collection, tracing, and monitoring. They execute concurrently for performance. |
| 145 | + |
| 146 | +### Required Observability Plugins |
| 147 | + |
| 148 | +If any observability plugin is marked as `required`, request processing waits for all observability plugins to complete before aggregating results. |
| 149 | +If any required observability plugin fails, the request is rejected after all have completed. |
| 150 | + |
| 151 | +```toml |
| 152 | +[[plugins.observability]] |
| 153 | + name = "metrics" |
| 154 | + required = true |
| 155 | + flows = ["request", "response"] |
| 156 | + |
| 157 | +[[plugins.observability]] |
| 158 | + name = "tracing" |
| 159 | + flows = ["request", "response"] |
| 160 | +``` |
| 161 | + |
| 162 | +In this example, both `metrics` and `tracing` run in parallel, but the request will be rejected if `metrics` fails |
| 163 | +(once `metrics` and `tracing` have completed). |
| 164 | + |
| 165 | +--- |
| 166 | + |
| 167 | +## Multiple Plugins Per Category |
| 168 | + |
| 169 | +You can configure multiple plugins within the same category. They execute in the order defined: |
| 170 | + |
| 171 | +```toml |
| 172 | +[[plugins.authentication]] |
| 173 | + name = "jwt-auth" |
| 174 | + required = true |
| 175 | + flows = ["request"] |
| 176 | + |
| 177 | +[[plugins.authentication]] |
| 178 | + name = "api-key-auth" |
| 179 | + flows = ["request"] |
| 180 | + |
| 181 | +[[plugins.authentication]] |
| 182 | + name = "oauth2" |
| 183 | + flows = ["request"] |
| 184 | +``` |
| 185 | + |
| 186 | +Request processing order: `jwt-auth` → `api-key-auth` → `oauth2` |
| 187 | + |
| 188 | +--- |
| 189 | + |
| 190 | +## Minimal Configuration |
| 191 | + |
| 192 | +Plugins are optional. A configuration file without plugins is valid: |
| 193 | + |
| 194 | +```toml |
| 195 | +[[servers]] |
| 196 | + name = "simple-server" |
| 197 | + package = "uvx::[email protected]" |
| 198 | + tools = ["tool1"] |
| 199 | +``` |
| 200 | + |
| 201 | +--- |
| 202 | + |
| 203 | +## Complete Example |
| 204 | + |
| 205 | +```toml |
| 206 | +[[servers]] |
| 207 | + name = "production-api" |
| 208 | + package = "uvx::[email protected]" |
| 209 | + tools = ["create_user", "get_user", "update_user", "delete_user"] |
| 210 | + |
| 211 | +[[plugins.authentication]] |
| 212 | + name = "jwt-auth" |
| 213 | + commit_hash = "a1b2c3d4" |
| 214 | + required = true |
| 215 | + flows = ["request"] |
| 216 | + |
| 217 | +[[plugins.authorization]] |
| 218 | + name = "rbac" |
| 219 | + commit_hash = "e5f6g7h8" |
| 220 | + required = true |
| 221 | + flows = ["request"] |
| 222 | + |
| 223 | +[[plugins.rate_limiting]] |
| 224 | + name = "token-bucket" |
| 225 | + flows = ["request"] |
| 226 | + |
| 227 | +[[plugins.validation]] |
| 228 | + name = "schema-validator" |
| 229 | + required = true |
| 230 | + flows = ["request", "response"] |
| 231 | + |
| 232 | +[[plugins.content]] |
| 233 | + name = "encryption" |
| 234 | + flows = ["request", "response"] |
| 235 | + |
| 236 | +[[plugins.observability]] |
| 237 | + name = "prometheus-metrics" |
| 238 | + required = true |
| 239 | + flows = ["request", "response"] |
| 240 | + |
| 241 | +[[plugins.observability]] |
| 242 | + name = "distributed-tracing" |
| 243 | + flows = ["request", "response"] |
| 244 | + |
| 245 | +[[plugins.audit]] |
| 246 | + name = "compliance-logger" |
| 247 | + required = true |
| 248 | + flows = ["response"] |
| 249 | +``` |
| 250 | + |
| 251 | +### Execution Flow |
| 252 | + |
| 253 | +#### Request Phase |
| 254 | + |
| 255 | +1. `jwt-auth` (authentication) - sequential |
| 256 | +2. `rbac` (authorization) - sequential |
| 257 | +3. `token-bucket` (rate_limiting) - sequential |
| 258 | +4. `schema-validator` (validation) - sequential |
| 259 | +5. `encryption` (content) - sequential |
| 260 | +6. `prometheus-metrics` + `distributed-tracing` (observability) - parallel |
| 261 | + |
| 262 | +#### Response Phase |
| 263 | + |
| 264 | +1. `schema-validator` (validation) - sequential |
| 265 | +2. `encryption` (content) - sequential |
| 266 | +3. `prometheus-metrics` + `distributed-tracing` (observability) - parallel |
| 267 | +4. `compliance-logger` (audit) - sequential |
| 268 | + |
| 269 | +--- |
| 270 | + |
| 271 | +## Validation |
| 272 | + |
| 273 | +Plugin configurations are validated when the daemon starts or during hot reload. Common validation errors: |
| 274 | + |
| 275 | +* Empty plugin name |
| 276 | +* Missing or empty `flows` array |
| 277 | +* Invalid flow values (must be `request` or `response`) |
| 278 | +* Duplicate flow values |
0 commit comments