Skip to main content
DeerFlow supports two types of extensions: Skills (specialized agent workflows) and MCP Servers (external context providers). Both are configured through config.yaml and extensions_config.json.

Configuration Files

config.yaml

Skills Directory: Configure where skills are located and how they’re mounted in sandboxes

extensions_config.json

Enable/Disable State: Control which skills and MCP servers are active

Skills Configuration

Skills are specialized workflows and prompts that enhance agent capabilities for specific tasks.

Directory Configuration (config.yaml)

config.yaml
skills:
  # Path to skills directory on the host
  # Relative paths are resolved from current working directory
  # If not specified, defaults to ../skills relative to backend directory
  path: /absolute/path/to/custom/skills
  
  # Path where skills are mounted in the sandbox container
  # This is used by the agent to access skills in both local and Docker sandbox
  container_path: /mnt/skills
path
string
Path to the skills directory on the host machine.
  • Can be absolute (/home/user/skills) or relative (../skills)
  • Relative paths are resolved from the current working directory
  • If not specified, defaults to ../skills relative to the backend directory
container_path
string
default:"/mnt/skills"
Path where skills are mounted inside the sandbox container.The agent uses this path to access skills in both local and Docker sandboxes.

Skills Directory Structure

skills/
├── public/              # Built-in skills
│   ├── pdf-processing/
│   │   ├── SKILL.md     # Skill definition
│   │   └── scripts/     # Helper scripts
│   └── frontend-design/
│       └── SKILL.md
└── custom/              # User-defined skills
    └── my-skill/
        └── SKILL.md

Enable/Disable Skills (extensions_config.json)

Control which skills are active:
extensions_config.json
{
  "skills": {
    "pdf-processing": {
      "enabled": true
    },
    "frontend-design": {
      "enabled": true
    },
    "my-custom-skill": {
      "enabled": false  // Disabled
    }
  }
}
Default Behavior: If a skill is not listed in extensions_config.json, it’s enabled by default for public and custom categories.

Programmatic Access

Check if a skill is enabled:
from src.config.extensions_config import get_extensions_config

config = get_extensions_config()

# Check if skill is enabled
if config.is_skill_enabled("pdf-processing", "public"):
    print("PDF processing skill is enabled")

# Get skill container path
from src.config.app_config import get_app_config
app_config = get_app_config()
path = app_config.skills.get_skill_container_path(
    skill_name="pdf-processing",
    category="public"
)
print(f"Skill path in container: {path}")
# Output: /mnt/skills/public/pdf-processing

MCP (Model Context Protocol) Configuration

MCP servers provide external context, tools, and data sources to agents. DeerFlow supports three transport types:

stdio

Local process communication via stdin/stdout

HTTP

RESTful HTTP communication

SSE

Server-Sent Events for streaming

Configuration (extensions_config.json)

All MCP servers are configured in extensions_config.json:
extensions_config.json
{
  "mcpServers": {
    "filesystem": {
      "enabled": true,
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/files"],
      "env": {},
      "description": "Provides filesystem access within allowed directories"
    },
    "github": {
      "enabled": true,
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "$GITHUB_TOKEN"
      },
      "description": "GitHub MCP server for repository operations"
    },
    "postgres": {
      "enabled": false,
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"],
      "description": "PostgreSQL database access"
    }
  }
}

Common Fields

enabled
boolean
default:"true"
required
Whether this MCP server is active. Set to false to temporarily disable.
type
string
required
Transport protocol: stdio, http, or sse
description
string
Human-readable description of what this MCP server provides

stdio Transport

For local processes that communicate via stdin/stdout:
{
  "my-stdio-server": {
    "enabled": true,
    "type": "stdio",
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path"],
    "env": {
      "API_KEY": "$MY_API_KEY"
    },
    "description": "Local filesystem access"
  }
}
command
string
required
Executable command to start the MCP server (e.g., npx, python, /usr/bin/my-server)
args
array
Command-line arguments passed to the command
env
object
Environment variables for the MCP server process.Values starting with $ are resolved from the host environment:
"env": {
  "API_KEY": "$MY_API_KEY",  // Resolved from host
  "DEBUG": "true"            // Literal value
}

HTTP Transport

For RESTful HTTP-based MCP servers:
{
  "my-http-server": {
    "enabled": true,
    "type": "http",
    "url": "https://api.example.com/mcp",
    "headers": {
      "Authorization": "Bearer $API_TOKEN",
      "X-Custom-Header": "value"
    },
    "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"
    },
    "description": "External HTTP MCP server"
  }
}
url
string
required
Base URL of the MCP server
headers
object
HTTP headers sent with requests. Supports environment variable resolution with $VAR_NAME.
oauth
object
OAuth configuration for automatic token management. See OAuth Configuration below.

SSE (Server-Sent Events) Transport

For streaming MCP servers using Server-Sent Events:
{
  "my-sse-server": {
    "enabled": true,
    "type": "sse",
    "url": "https://api.example.com/mcp",
    "headers": {
      "Authorization": "Bearer $API_TOKEN"
    },
    "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 mcp.write",
      "audience": "https://api.example.com",
      "refresh_skew_seconds": 60
    },
    "description": "Streaming SSE MCP server"
  }
}
SSE servers use the same fields as HTTP servers.

OAuth Configuration

For HTTP and SSE transports, DeerFlow can automatically manage OAuth tokens:
{
  "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",
    "refresh_token": "$MCP_REFRESH_TOKEN",
    "scope": "mcp.read mcp.write",
    "audience": "https://api.example.com",
    "token_field": "access_token",
    "token_type_field": "token_type",
    "expires_in_field": "expires_in",
    "default_token_type": "Bearer",
    "refresh_skew_seconds": 60,
    "extra_token_params": {
      "resource": "https://api.example.com"
    }
  }
}
oauth.enabled
boolean
default:"true"
Enable OAuth token management
oauth.token_url
string
required
OAuth token endpoint URL
oauth.grant_type
string
default:"client_credentials"
OAuth grant type: client_credentials or refresh_token
oauth.client_id
string
OAuth client ID (supports $VAR_NAME for environment variables)
oauth.client_secret
string
OAuth client secret (supports $VAR_NAME)
oauth.refresh_token
string
OAuth refresh token (for refresh_token grant type, supports $VAR_NAME)
oauth.scope
string
OAuth scope (space-separated list of permissions)
oauth.audience
string
OAuth audience (provider-specific, e.g., Auth0)
oauth.token_field
string
default:"access_token"
Field name containing the access token in the token response
oauth.token_type_field
string
default:"token_type"
Field name containing the token type in the token response
oauth.expires_in_field
string
default:"expires_in"
Field name containing the expiry duration (in seconds) in the token response
oauth.default_token_type
string
default:"Bearer"
Default token type when missing in the token response
oauth.refresh_skew_seconds
integer
default:"60"
Refresh the token this many seconds before expiry to avoid race conditions
oauth.extra_token_params
object
Additional form parameters sent to the token endpoint

OAuth Grant Types

Most common for server-to-server authentication:
{
  "oauth": {
    "enabled": true,
    "token_url": "https://auth.example.com/oauth/token",
    "grant_type": "client_credentials",
    "client_id": "$CLIENT_ID",
    "client_secret": "$CLIENT_SECRET",
    "scope": "api.read api.write"
  }
}

Environment Variable Resolution

Both env fields (for stdio) and OAuth configuration support environment variable resolution:
{
  "mcpServers": {
    "github": {
      "type": "stdio",
      "env": {
        "GITHUB_TOKEN": "$GITHUB_TOKEN"  // Resolved from host environment
      }
    },
    "my-api": {
      "type": "http",
      "headers": {
        "Authorization": "Bearer $API_KEY"  // Resolved from host environment
      },
      "oauth": {
        "client_id": "$OAUTH_CLIENT_ID",     // Resolved from host environment
        "client_secret": "$OAUTH_SECRET"     // Resolved from host environment
      }
    }
  }
}
Set these variables in your environment:
export GITHUB_TOKEN="ghp_..."
export API_KEY="key_..."
export OAUTH_CLIENT_ID="client_..."
export OAUTH_SECRET="secret_..."
If a referenced environment variable is not set, DeerFlow will raise a ValueError during configuration loading.

Programmatic Access

from src.config.extensions_config import get_extensions_config

config = get_extensions_config()

# Get all enabled MCP servers
enabled_servers = config.get_enabled_mcp_servers()
for name, server_config in enabled_servers.items():
    print(f"Server: {name}")
    print(f"  Type: {server_config.type}")
    print(f"  Description: {server_config.description}")

# Get specific MCP server
if "github" in config.mcp_servers:
    github = config.mcp_servers["github"]
    if github.enabled:
        print(f"GitHub MCP: {github.command} {' '.join(github.args)}")

# Check skill status
if config.is_skill_enabled("pdf-processing", "public"):
    print("PDF processing skill is enabled")

Examples

Official MCP Servers

{
  "filesystem": {
    "enabled": true,
    "type": "stdio",
    "command": "npx",
    "args": [
      "-y",
      "@modelcontextprotocol/server-filesystem",
      "/home/user/documents"
    ],
    "description": "Access to /home/user/documents"
  }
}

Custom Skills Example

Create a custom skill:
  1. Create skill directory:
    mkdir -p skills/custom/my-skill
    
  2. Create SKILL.md:
    skills/custom/my-skill/SKILL.md
    # My Custom Skill
    
    This skill provides specialized capabilities for...
    
    ## Instructions
    
    When the user asks for..., follow these steps:
    1. ...
    2. ...
    
  3. Enable in extensions_config.json:
    {
      "skills": {
        "my-skill": {
          "enabled": true
        }
      }
    }
    

Troubleshooting

Ensure all referenced environment variables are set:
# Check if variable is set
echo $GITHUB_TOKEN

# Add to .env file
echo "GITHUB_TOKEN=ghp_..." >> .env
Verify the command is available:
# Test the command manually
npx -y @modelcontextprotocol/server-github --help

# Check npx is installed
which npx
Check the skills path configuration:
skills:
  path: /absolute/path/to/skills  # Ensure this exists
# Verify skills directory exists
ls -la /absolute/path/to/skills
Check OAuth configuration:
  • Verify token_url is correct
  • Ensure client_id and client_secret are set
  • Check scope matches provider requirements
  • Review provider’s OAuth documentation

Next Steps

Memory Configuration

Set up the memory system

Creating Skills

Build custom skills

Build docs developers (and LLMs) love