mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-04-25 11:18:22 +00:00
* feat(mcp): support custom tool interceptors via extensions_config.json
Add a generic extension point for registering custom MCP tool
interceptors through `extensions_config.json`. This allows downstream
projects to inject per-request header manipulation, auth context
propagation, or other cross-cutting concerns without modifying
DeerFlow source code.
Interceptors are declared as Python callable paths in a new
`mcpInterceptors` array field and loaded via the existing
`resolve_variable` reflection mechanism:
```json
{
"mcpInterceptors": [
"my_package.mcp.auth:build_auth_interceptor"
]
}
```
Each entry must resolve to a no-arg builder function that returns an
async interceptor compatible with `MultiServerMCPClient`'s
`tool_interceptors` interface.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test(mcp): add unit tests for custom tool interceptors
Cover all branches of the mcpInterceptors loading logic:
- valid interceptor loaded and appended to tool_interceptors
- multiple interceptors loaded in declaration order
- builder returning None is skipped
- resolve_variable ImportError logged and skipped
- builder raising exception logged and skipped
- absent mcpInterceptors field is safe (no-op)
- custom interceptors coexist with OAuth interceptor
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix(mcp): validate mcpInterceptors type and fix lint warnings
Address review feedback:
1. Validate mcpInterceptors config value before iterating:
- Accept a single string and normalize to [string]
- Ignore None silently
- Log warning and skip for non-list/non-string types
2. Fix ruff F841 lint errors in tests:
- Rename _make_mock_env to _make_patches, embed mock_client
- Remove unused `as mock_cls` bindings where not needed
- Extract _get_interceptors() helper to reduce repetition
3. Add two new test cases for type validation:
- test_mcp_interceptors_single_string_is_normalized
- test_mcp_interceptors_invalid_type_logs_warning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(mcp): validate interceptor return type and fix import mock path
Address review feedback:
1. Validate builder return type with callable() check:
- callable interceptor → append to tool_interceptors
- None → silently skip (builder opted out)
- non-callable → log warning with type name and skip
2. Fix test mock path: resolve_variable is a top-level import in
tools.py, so mock deerflow.mcp.tools.resolve_variable instead of
deerflow.reflection.resolve_variable to correctly intercept calls.
3. Add test_custom_interceptor_non_callable_return_logs_warning to
cover the new non-callable validation branch.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs(mcp): add mcpInterceptors example and documentation
- Add mcpInterceptors field to extensions_config.example.json
- Add "Custom Tool Interceptors" section to MCP_SERVER.md with
configuration format, example interceptor code, and edge case
behavior notes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: IECspace <IECspace@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
100 lines
3.5 KiB
Markdown
100 lines
3.5 KiB
Markdown
# MCP (Model Context Protocol) Configuration
|
||
|
||
DeerFlow supports configurable MCP servers and skills to extend its capabilities, which are loaded from a dedicated `extensions_config.json` file in the project root directory.
|
||
|
||
## Setup
|
||
|
||
1. Copy `extensions_config.example.json` to `extensions_config.json` in the project root directory.
|
||
```bash
|
||
# Copy example configuration
|
||
cp extensions_config.example.json extensions_config.json
|
||
```
|
||
|
||
2. Enable the desired MCP servers or skills by setting `"enabled": true`.
|
||
3. Configure each server’s command, arguments, and environment variables as needed.
|
||
4. Restart the application to load and register MCP tools.
|
||
|
||
## OAuth Support (HTTP/SSE MCP Servers)
|
||
|
||
For `http` and `sse` MCP servers, DeerFlow supports OAuth token acquisition and automatic token refresh.
|
||
|
||
- Supported grants: `client_credentials`, `refresh_token`
|
||
- Configure per-server `oauth` block in `extensions_config.json`
|
||
- Secrets should be provided via environment variables (for example: `$MCP_OAUTH_CLIENT_SECRET`)
|
||
|
||
Example:
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"secure-http-server": {
|
||
"enabled": true,
|
||
"type": "http",
|
||
"url": "https://api.example.com/mcp",
|
||
"oauth": {
|
||
"enabled": true,
|
||
"token_url": "https://auth.example.com/oauth/token",
|
||
"grant_type": "client_credentials",
|
||
"client_id": "$MCP_OAUTH_CLIENT_ID",
|
||
"client_secret": "$MCP_OAUTH_CLIENT_SECRET",
|
||
"scope": "mcp.read",
|
||
"refresh_skew_seconds": 60
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## Custom Tool Interceptors
|
||
|
||
You can register custom interceptors that run before every MCP tool call. This is useful for injecting per-request headers (e.g., user auth tokens from the LangGraph execution context), logging, or metrics.
|
||
|
||
Declare interceptors in `extensions_config.json` using the `mcpInterceptors` field:
|
||
|
||
```json
|
||
{
|
||
"mcpInterceptors": [
|
||
"my_package.mcp.auth:build_auth_interceptor"
|
||
],
|
||
"mcpServers": { ... }
|
||
}
|
||
```
|
||
|
||
Each entry is a Python import path in `module:variable` format (resolved via `resolve_variable`). The variable must be a **no-arg builder function** that returns an async interceptor compatible with `MultiServerMCPClient`’s `tool_interceptors` interface, or `None` to skip.
|
||
|
||
Example interceptor that injects auth headers from LangGraph metadata:
|
||
|
||
```python
|
||
def build_auth_interceptor():
|
||
async def interceptor(request, handler):
|
||
from langgraph.config import get_config
|
||
metadata = get_config().get("metadata", {})
|
||
headers = dict(request.headers or {})
|
||
if token := metadata.get("auth_token"):
|
||
headers["X-Auth-Token"] = token
|
||
return await handler(request.override(headers=headers))
|
||
return interceptor
|
||
```
|
||
|
||
- A single string value is accepted and normalized to a one-element list.
|
||
- Invalid paths or builder failures are logged as warnings without blocking other interceptors.
|
||
- The builder return value must be `callable`; non-callable values are skipped with a warning.
|
||
|
||
## How It Works
|
||
|
||
MCP servers expose tools that are automatically discovered and integrated into DeerFlow’s agent system at runtime. Once enabled, these tools become available to agents without additional code changes.
|
||
|
||
## Example Capabilities
|
||
|
||
MCP servers can provide access to:
|
||
|
||
- **File systems**
|
||
- **Databases** (e.g., PostgreSQL)
|
||
- **External APIs** (e.g., GitHub, Brave Search)
|
||
- **Browser automation** (e.g., Puppeteer)
|
||
- **Custom MCP server implementations**
|
||
|
||
## Learn More
|
||
|
||
For detailed documentation about the Model Context Protocol, visit:
|
||
https://modelcontextprotocol.io |