Skip to content

feat(config): support user MCP settings merge#2976

Open
Eilen6316 wants to merge 1 commit into
bytedance:mainfrom
Eilen6316:issue2949-user-mcp-config
Open

feat(config): support user MCP settings merge#2976
Eilen6316 wants to merge 1 commit into
bytedance:mainfrom
Eilen6316:issue2949-user-mcp-config

Conversation

@Eilen6316
Copy link
Copy Markdown
Contributor

@Eilen6316 Eilen6316 commented May 15, 2026

Summary

Refs #2949.

This is the first small PR for user-level MCP settings support. It only adds the configuration-layer foundation and intentionally does not change the current default MCP loading behavior yet.

Multi-stage plan

  1. Add backend config support for reading and merging user-level mcp_settings.json.
  2. Wire user context into MCP tool loading and make the MCP tools cache user-aware to avoid cross-user config reuse.
  3. Add user-level MCP config GET/PUT APIs.
  4. Add a Settings UI for editing user-level MCP config.

This PR

  • Adds ExtensionsConfig.user_mcp_settings_path(user_id) for .deer-flow/users/<user_id>/mcp_settings.json.
  • Adds optional user_id / user_config_path arguments to ExtensionsConfig.from_file().
  • Merges only the user config mcpServers into the global config.
  • Keeps global skills and other extension-level fields owned by the global config.
  • Uses field-level overlay for same-name MCP servers, so a user can override selected fields without restating the whole global server config.
  • Preserves existing behavior when no user_id or user_config_path is passed.

Tests

  • uv run pytest tests/test_extensions_config_user_mcp.py tests/test_runtime_paths.py
  • uvx ruff check .
  • uvx ruff format --check .

@Eilen6316
Copy link
Copy Markdown
Contributor Author

Detailed rollout plan for #2949:

This PR is intentionally scoped as stage 1 only. It adds the configuration-layer foundation for user-level MCP settings, but it does not yet change runtime MCP tool loading, cache behavior, APIs, or frontend settings.

Stage 1: configuration foundation, covered by this PR

  • Add a stable user-level MCP settings path: .deer-flow/users/<user_id>/mcp_settings.json.
  • Allow ExtensionsConfig.from_file() to optionally merge user-level MCP settings through user_id or an explicit user_config_path.
  • Merge only the mcpServers section from the user file into the global extensions config.
  • Keep global skills and other extension-level fields owned by the global config.
  • Preserve current behavior when no user-level settings are requested.
  • Add focused tests for path resolution, unsafe user ids, merge behavior, missing global config, invalid JSON, and invalid schema shapes.

Stage 2: runtime MCP loading and cache isolation

  • Resolve the current user id from the agent run context or runtime config.
  • Pass the resolved user id into the MCP tool loading path.
  • Make the MCP tools cache user-aware, so tools loaded for one user cannot be reused by another user.
  • Include both global config mtime and user config mtime in cache invalidation.
  • Add regression tests proving different users can have different MCP server sets without cross-user leakage.

Stage 3: user-level MCP config APIs

  • Add user-scoped GET and PUT endpoints for the current user MCP settings.
  • Keep the existing global /api/mcp/config behavior separate from user-level config.
  • Ensure user-level APIs only read and write the current user settings file.
  • Add validation and error handling for invalid JSON or invalid MCP server config payloads.
  • Add tests covering read, write, missing config, and user isolation behavior.

Stage 4: frontend settings integration

  • Add a Settings entry for user-level MCP configuration.
  • Make the UI distinction clear between global MCP config and user-level overrides.
  • Allow users to add or edit user-specific MCP servers without modifying global config.
  • Document that same-name user MCP servers override global server fields.
  • Keep static website mode and permission constraints in mind.

The main risk area is stage 2. MCP tools are currently cached globally, so user-level config must not be wired into runtime loading until the cache is made user-aware. That is why this first PR stops at the config layer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant