|
| 1 | + |
1 | 2 | # Plugin Framework Specification |
2 | 3 |
|
3 | 4 | **Version**: 1.0 |
@@ -257,6 +258,97 @@ The `conditions` array contains objects that specify when plugins should execute |
257 | 258 | | `user_patterns` | `string[]` | Execute for users matching regex patterns | `["admin_.*", ".*@company.com"]` | |
258 | 259 | | `content_types` | `string[]` | Execute for specific content types | `["application/json", "text/plain"]` | |
259 | 260 |
|
| 261 | +The plugin framework uses **hybrid AND/OR condition evaluation** for precise control over plugin execution. |
| 262 | + |
| 263 | +#### Evaluation Logic |
| 264 | + |
| 265 | +**Behavior:** |
| 266 | +- **Within a condition object**: ALL fields must match (AND logic) |
| 267 | +- **Across condition objects**: ANY object can match (OR logic) |
| 268 | + |
| 269 | +This enables expressions like: `(tenant=X AND tool=Y) OR (server=Z AND user=W)` |
| 270 | + |
| 271 | +**Evaluation Order within each condition object:** |
| 272 | +1. GlobalContext conditions (server_id, tenant_id, user_patterns) |
| 273 | +2. Payload-specific conditions (tools, prompts, resources, agents) |
| 274 | + |
| 275 | +**Short-circuit:** |
| 276 | +- Within a condition object: Evaluation stops at the first non-matching field (fail-fast) |
| 277 | +- Across condition objects: Evaluation stops at the first fully matching object (first-match-wins) |
| 278 | + |
| 279 | +#### Configuration Examples |
| 280 | + |
| 281 | +#### Single Condition Object |
| 282 | + |
| 283 | +```yaml |
| 284 | +plugins: |
| 285 | + - name: "TenantFilter" |
| 286 | + conditions: |
| 287 | + - tenant_ids: ["healthcare", "finance"] |
| 288 | + # Executes ONLY for healthcare OR finance tenants |
| 289 | +``` |
| 290 | + |
| 291 | +#### Multiple Fields in Single Condition (AND Logic) |
| 292 | + |
| 293 | +```yaml |
| 294 | +plugins: |
| 295 | + - name: "PIIFilterPlugin" |
| 296 | + conditions: |
| 297 | + - tenant_ids: ["healthcare"] |
| 298 | + tools: ["patient_data_reader"] |
| 299 | + server_ids: ["prod-server"] |
| 300 | + # Executes ONLY when ALL match: |
| 301 | + # - tenant = healthcare AND |
| 302 | + # - tool = patient_data_reader AND |
| 303 | + # - server = prod-server |
| 304 | +``` |
| 305 | + |
| 306 | +#### Multiple Condition Objects (OR Logic) |
| 307 | + |
| 308 | +```yaml |
| 309 | +plugins: |
| 310 | + - name: "SecurityPlugin" |
| 311 | + conditions: |
| 312 | + - tenant_ids: ["enterprise"] |
| 313 | + tools: ["sensitive_tool"] |
| 314 | + - server_ids: ["prod-server"] |
| 315 | + user_patterns: ["admin_.*"] |
| 316 | + # Executes when: |
| 317 | + # (tenant=enterprise AND tool=sensitive_tool) OR |
| 318 | + # (server=prod-server AND user matches admin_.*) |
| 319 | + # |
| 320 | + # This means the plugin runs if EITHER: |
| 321 | + # - Request is from enterprise tenant using sensitive_tool, OR |
| 322 | + # - Request is on prod-server from a user matching admin_.* |
| 323 | +``` |
| 324 | + |
| 325 | +### Use Cases |
| 326 | + |
| 327 | +| Scenario | Configuration Pattern | |
| 328 | +|----------|----------------------| |
| 329 | +| Tenant-specific plugin | `tenant_ids: ["tenant1"]` | |
| 330 | +| Tool-specific security | `tools: ["sensitive_tool"]` | |
| 331 | +| Multi-factor control | `tenant_ids: [...], tools: [...], user_patterns: [...]` (all in one object) | |
| 332 | +| Production-only | `server_ids: ["prod-server"]` | |
| 333 | +| Admin-only operations | `user_patterns: ["admin_.*"]` | |
| 334 | +| Multiple independent scenarios | Multiple condition objects with different field combinations | |
| 335 | + |
| 336 | +#### Debugging Condition Evaluation |
| 337 | + |
| 338 | +Enable debug logging to see condition evaluation details: |
| 339 | + |
| 340 | +```bash |
| 341 | +LOG_LEVEL=DEBUG python -m mcpgateway.main |
| 342 | +``` |
| 343 | + |
| 344 | +Log output includes: |
| 345 | +- Number of condition objects being evaluated |
| 346 | +- Which condition object is being checked (1/N, 2/N, etc.) |
| 347 | +- GlobalContext mismatch details (server_id, tenant_id, user) |
| 348 | +- Payload mismatch details (tool name, prompt_id, etc.) |
| 349 | +- Success message when condition fully matches |
| 350 | +- Final execution decision (execute or skip) |
| 351 | + |
260 | 352 | #### MCP Configuration Fields |
261 | 353 |
|
262 | 354 | For external plugins (`kind: "external"`), the `mcp` object configures the MCP server connection: |
@@ -1010,6 +1102,93 @@ class PluginCondition(BaseModel): |
1010 | 1102 | content_types: Optional[list[str]] = None # Execute for specific content types |
1011 | 1103 | ``` |
1012 | 1104 |
|
| 1105 | +#### Content Type Filtering |
| 1106 | + |
| 1107 | +Plugins can be configured to execute only for specific content types using the `content_types` condition. This enables fine-grained control over when plugins process requests based on the HTTP `Content-Type` header. |
| 1108 | + |
| 1109 | +**Configuration Example:** |
| 1110 | + |
| 1111 | +```yaml |
| 1112 | +plugins: |
| 1113 | + - name: "JsonValidator" |
| 1114 | + kind: "plugins.json_validator.JsonValidator" |
| 1115 | + hooks: ["tool_pre_invoke"] |
| 1116 | + conditions: |
| 1117 | + - content_types: ["application/json"] |
| 1118 | +``` |
| 1119 | +
|
| 1120 | +**Matching Behavior:** |
| 1121 | +
|
| 1122 | +- **Case-insensitive**: `APPLICATION/JSON` matches `application/json` |
| 1123 | +- **Parameter stripping**: `application/json; charset=utf-8` matches `application/json` |
| 1124 | +- **Multiple types**: Supports OR logic - plugin executes if any content type matches |
| 1125 | +- **Permissive default**: If `content_types` is not specified or request has no Content-Type header, plugin executes normally |
| 1126 | + |
| 1127 | +**Common Content Types:** |
| 1128 | + |
| 1129 | +| Content Type | Description | Use Case | |
| 1130 | +|--------------|-------------|----------| |
| 1131 | +| `application/json` | JSON data | API requests, structured data validation | |
| 1132 | +| `text/plain` | Plain text | Simple text processing, logging | |
| 1133 | +| `text/html` | HTML documents | Web scraping, content extraction | |
| 1134 | +| `application/xml` | XML data | Legacy API integration, SOAP services | |
| 1135 | +| `multipart/form-data` | File uploads | File validation, virus scanning | |
| 1136 | +| `application/x-www-form-urlencoded` | Form submissions | Form data validation | |
| 1137 | + |
| 1138 | +**Example: JSON-Only Security Plugin** |
| 1139 | + |
| 1140 | +```yaml |
| 1141 | +plugins: |
| 1142 | + - name: "JsonSecurityScanner" |
| 1143 | + kind: "plugins.security.json_scanner.JsonSecurityScanner" |
| 1144 | + hooks: ["tool_pre_invoke", "tool_post_invoke"] |
| 1145 | + mode: "enforce" |
| 1146 | + priority: 10 |
| 1147 | + conditions: |
| 1148 | + - content_types: ["application/json"] |
| 1149 | + server_ids: ["production-api"] |
| 1150 | +``` |
| 1151 | + |
| 1152 | +**Example: Multi-Format Data Validator** |
| 1153 | + |
| 1154 | +```yaml |
| 1155 | +plugins: |
| 1156 | + - name: "DataValidator" |
| 1157 | + kind: "plugins.validation.data_validator.DataValidator" |
| 1158 | + hooks: ["tool_pre_invoke"] |
| 1159 | + conditions: |
| 1160 | + - content_types: |
| 1161 | + - "application/json" |
| 1162 | + - "application/xml" |
| 1163 | + - "text/csv" |
| 1164 | +``` |
| 1165 | + |
| 1166 | +**Combined Conditions:** |
| 1167 | + |
| 1168 | +Content type filtering works seamlessly with other conditions: |
| 1169 | + |
| 1170 | +```yaml |
| 1171 | +plugins: |
| 1172 | + - name: "TeamJsonProcessor" |
| 1173 | + kind: "plugins.processors.json_processor.JsonProcessor" |
| 1174 | + hooks: ["tool_pre_invoke"] |
| 1175 | + conditions: |
| 1176 | + - content_types: ["application/json"] |
| 1177 | + tenant_ids: ["team-alpha", "team-beta"] |
| 1178 | + tools: ["data_analysis", "report_generation"] |
| 1179 | +``` |
| 1180 | + |
| 1181 | +**Security Considerations:** |
| 1182 | + |
| 1183 | +!!! warning "Content-Type Spoofing" |
| 1184 | + Clients can set arbitrary Content-Type headers. Use `content_types` for filtering and optimization, not as a security boundary. Combine with other conditions (server_ids, tenant_ids) for defense-in-depth. |
| 1185 | + |
| 1186 | +**Performance Benefits:** |
| 1187 | + |
| 1188 | +- **Reduced overhead**: Skip expensive processing for irrelevant content types |
| 1189 | +- **Targeted validation**: Apply format-specific validators only when needed |
| 1190 | +- **Resource optimization**: Prevent unnecessary plugin execution |
| 1191 | + |
1013 | 1192 | ## Hook Reference Documentation |
1014 | 1193 |
|
1015 | 1194 | The plugin framework provides two main categories of hooks, each documented in detail in separate files: |
|
0 commit comments