Skip to content

feat: wire Server B and add multi-project tests and documentation#662

Draft
DevonFulcher wants to merge 44 commits intomainfrom
df/multiproject-phase7-wiring
Draft

feat: wire Server B and add multi-project tests and documentation#662
DevonFulcher wants to merge 44 commits intomainfrom
df/multiproject-phase7-wiring

Conversation

@DevonFulcher
Copy link
Collaborator

@DevonFulcher DevonFulcher commented Mar 17, 2026

Why

Multi-project mode (Server B) needs to register all tool categories so that DBT_MCP_MULTI_PROJECT_ENABLED=true provides a fully functional MCP server. The previous phases (1-6) added the individual tool categories; this PR combines them and wires everything together with tests and documentation.

What

  • Server B wiring: server_multiproject.py now registers all multi-project tools:
    • Multi-project semantic layer (6 _for_project variants)
    • Multi-project discovery (18 tools with config_override)
    • Multi-project SQL (text_to_sql_for_project, execute_sql_for_project)
    • Multi-project admin API (list_jobs_for_project, list_jobs_runs_for_project) including list_projects for project discovery
    • Product docs and MCP server metadata (always available)
  • Entry point: main.py calls create_dbt_mcp_multiproject() when DBT_MCP_MULTI_PROJECT_ENABLED=true
  • Environment resolver: Extracts prod/dev environment resolution into reusable resolve_environments() helper
  • Tests: Tests covering Server B tool registration, environment resolution, and edge cases
  • Documentation: README updated with multi-project mode section and tool listings
  • Toolset tracking: multiproject_only_tools set in toolsets.py tracks all Server B-exclusive tools for validation

Notes

  • Project discovery on Server B uses the existing list_projects tool from the admin API (register_admin_api_tools), rather than a separate list_projects_and_environments discovery tool. The Toolset.PROJECT and list_projects_and_environments tool have been removed entirely.
  • Admin tools (list_jobs_for_project, list_jobs_runs_for_project) are registered on both Server A and Server B since they use the shared register_admin_api_tools() path
  • All 472 unit tests pass, ruff and mypy clean

Drafted by Claude Sonnet 4.6 under the direction of @DevonFulcher

DevonFulcher and others added 13 commits March 17, 2026 12:52
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This will be introduced in the first phase where it has non-empty content.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove get_config_for_project() from all config providers. Each
multiproject semantic layer tool now calls _resolve_sl_config_for_project()
which fetches credentials, builds the platform URL/headers, calls
get_environments_for_project() directly, and returns the config via
DefaultSemanticLayerConfigProvider._build_config().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add multi_project_only_toolsets set to toolsets.py and update
generate_docs.py to skip those toolsets when generating README
and diagram documentation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
diagram.d2 is already correct (multi-project toolset excluded).
Restoring d2.png to match the unchanged diagram source.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ools

Multi-project server cannot run alongside single-project server, so tools
share the same names (list_metrics, not list_metrics_for_project) and are
controlled by the same env vars (DISABLE_SEMANTIC_LAYER).

Remove MULTI_PROJECT_SEMANTIC_LAYER toolset, multi_project_only_toolsets,
and multi_project_tools variables. Remove disable/enable_multi_project_semantic_layer
settings fields. Remove multi_project_only_toolsets filtering from generate_docs.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@DevonFulcher DevonFulcher force-pushed the df/multiproject-phase7-wiring branch from 5936e5e to c0eb426 Compare March 17, 2026 18:53
DevonFulcher and others added 2 commits March 18, 2026 09:08
…erConfigProvider

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@DevonFulcher DevonFulcher force-pushed the df/multiproject-phase7-wiring branch from c95b01d to bb5b68c Compare March 18, 2026 14:31
DevonFulcher and others added 6 commits March 18, 2026 09:46
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nticLayerFetcher

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add config_override parameter to all discovery client methods (MetadataAPIClient,
PaginatedResourceFetcher, ModelsFetcher, ExposuresFetcher, SourcesFetcher,
MacrosFetcher, ResourceDetailsFetcher, LineageFetcher, ModelPerformanceFetcher)
to support per-call config overrides for multi-project mode.

Create tools_multiproject.py with all 18 discovery tools mirroring Server A,
each taking project_id as a required first parameter. Add get_config_for_project()
to ConfigProvider ABC for multi-project config resolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
DevonFulcher and others added 23 commits March 18, 2026 09:57
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add config_override parameter to all discovery client methods (MetadataAPIClient,
PaginatedResourceFetcher, ModelsFetcher, ExposuresFetcher, SourcesFetcher,
MacrosFetcher, ResourceDetailsFetcher, LineageFetcher, ModelPerformanceFetcher)
to support per-call config overrides for multi-project mode.

Create tools_multiproject.py with all 18 discovery tools mirroring Server A,
each taking project_id as a required first parameter. Add get_config_for_project()
to ConfigProvider ABC for multi-project config resolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… tools

Multi-project server cannot run alongside single-project server, so tools
share the same names (text_to_sql, not text_to_sql_for_project) and are
controlled by the same env vars (DISABLE_SQL, DISABLE_ADMIN_API).

Remove _FOR_PROJECT ToolName entries, remove from toolsets dict.
Rename multi-project tool functions and MCP names to match single-project.
Separate MULTIPROJECT_ADMIN_API_TOOLS from ADMIN_TOOLS.
Add register_multiproject_admin_api_tools function.
Remove unused _for_project prompt files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add config_override parameter to all discovery client methods (MetadataAPIClient,
PaginatedResourceFetcher, ModelsFetcher, ExposuresFetcher, SourcesFetcher,
MacrosFetcher, ResourceDetailsFetcher, LineageFetcher, ModelPerformanceFetcher)
to support per-call config overrides for multi-project mode.

Create tools_multiproject.py with all 18 discovery tools mirroring Server A,
each taking project_id as a required first parameter. Add get_config_for_project()
to ConfigProvider ABC for multi-project config resolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Register all multi-project tools in create_dbt_mcp_multiproject():
  list_projects_and_environments, 18 discovery tools, 6 semantic layer
  tools, text_to_sql_for_project, execute_sql_for_project,
  list_jobs_for_project, list_jobs_runs_for_project
- Add discovery/tools_multiproject.py with 18 discovery tools that accept
  project_id and use per-call config_override for environment resolution
- Update tool_names.py and toolsets.py with SQL and admin multi-project
  tool entries and multiproject_only_tools set
- Add unit tests for Server B in tests/unit/mcp/test_server_multiproject.py
- Add unit tests for resolve_environments() in tests/unit/project/
- Add multi-project mode documentation to README.md
- Add DBT_MCP_MULTI_PROJECT_ENABLED to .env.example

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…s on Server B

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add `multi_project_only_toolsets` to toolsets.py containing all
Server-B-only toolsets and filter them out during README and diagram
generation so they don't appear in public-facing docs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…uffix)

Multi-project tools reuse the same MCP tool names as single-project tools
(e.g., "list_metrics" not "list_metrics_for_project") — they just add a
project_id parameter. The multi-project server cannot run alongside the
single-project server, so there is no name collision.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add _resolve_project_environments and ProjectSemanticLayerConfigProvider
  to config_providers (lost during conflict resolution)
- Add get_config_for_project to DefaultProxiedToolConfigProvider
- Map _for_project tools to toolsets
- Fix server_multiproject imports and call signatures
- Update tests for renamed tool names
- Fix missing await on get_environments_for_project

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@DevonFulcher DevonFulcher force-pushed the df/multiproject-phase7-wiring branch from bb5b68c to 531c4ca Compare March 18, 2026 15:10
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