Full SMR Migration Scope
Date: 2026-04-03

Purpose

This document scopes the full migration of Synth Managed Research public API,
SDK, and MCP logic out of `synth-ai` and into `managed-research`.

Target End State

`managed-research` becomes the single public source of truth for:

- Python SDK for SMR control-plane operations
- SMR MCP server and tool schemas
- public SMR schema sync and generated/public models

After cutover:

- `synth-ai` depends on `managed-research`
- `synth-ai` stops owning SMR source directly
- any remaining `synth-ai` SMR imports become compatibility shims only

Current Live Implementation In `synth-ai`

Core files:

- `synth_ai/sdk/managed_research.py` - 3978 lines
- `synth_ai/mcp/managed_research_server.py` - 4592 lines

Companion SDK files:

- `synth_ai/sdk/managed_research_projects.py`
- `synth_ai/sdk/managed_research_runtime.py`
- `synth_ai/sdk/managed_research_events.py`
- `synth_ai/sdk/managed_research_git.py`
- `synth_ai/sdk/managed_research_interactivity.py`
- `synth_ai/sdk/managed_research_sublinear.py`

Total currently scoped migration surface:

- about 8.9k lines across the main public SDK and MCP files

Live Public Surface Inventory

1. Python SDK

Primary entrypoint:

- `synth_ai.sdk.managed_research.SmrControlClient`

Main capability groups currently implemented:

- project lifecycle
- project status and project state
- project repos and git wiring
- bindings, pools, and runtime/environment resolution
- project events and messages
- milestones and experiments
- run creation and run lifecycle
- actor control
- runtime inbox/context
- approvals and questions
- artifacts and logs
- project usage and run usage
- provider keys and execution preferences
- GitHub, Linear, Codex subscription, and Sublinear integrations

Representative SDK methods currently present:

- project APIs:
  - `create_project`
  - `list_projects`
  - `get_project`
  - `get_project_status`
  - `get_project_state`
  - `pause_project`
  - `resume_project`
  - `archive_project`
  - `unarchive_project`
- binding/runtime APIs:
  - `get_binding`
  - `promote_binding`
  - `get_pool_context`
  - `get_capacity_lane_preview`
  - `set_execution_preferences`
  - `merge_project_execution`
- repo/git APIs:
  - `get_project_repos`
  - `add_project_repo`
  - `remove_project_repo`
  - `get_project_git_status`
  - `git_get_status`
  - `git_list_tree`
  - `git_read_file`
  - `git_get_diff`
  - `git_create_branch`
  - `git_write_files`
  - `git_upload_files`
  - `git_create_commit`
  - `git_push`
  - `git_list_pull_requests`
  - `git_open_pull_request`
  - `git_comment_on_pull_request`
- run/actor/runtime APIs:
  - `trigger_run`
  - `list_runs`
  - `list_jobs`
  - `get_run`
  - `get_run_usage`
  - `get_run_actors`
  - `pause_run`
  - `resume_run`
  - `stop_run`
  - `control_actor`
  - `list_runtime_messages`
  - `enqueue_runtime_message`
  - `list_runtime_context`
  - `publish_runtime_context`
  - `get_run_logs`
  - `search_victoria_logs`
  - `get_run_results`
  - `list_run_artifacts`
  - `get_artifact`
  - `get_artifact_content_*`
  - `list_run_pull_requests`
- approval/question APIs:
  - `list_project_questions`
  - `respond_question`
  - `list_project_approvals`
  - `resolve_approval`
- milestone/experiment APIs:
  - `create_project_milestone`
  - `get_project_milestone`
  - `patch_project_milestone`
  - `transition_project_milestone`
  - `create_project_experiment`
  - `get_project_experiment`
  - `patch_project_experiment`
- funding/provider APIs:
  - `set_provider_key`
  - `provider_key_status`
  - `get_usage`
  - `get_usage_overview`
  - `set_agent_config`
- external integration APIs:
  - `link_org_github`
  - `github_org_status`
  - `github_org_oauth_start`
  - `github_org_oauth_callback`
  - `github_org_disconnect`
  - `linear_oauth_start`
  - `linear_oauth_callback`
  - `linear_status`
  - `linear_disconnect`
  - `linear_list_teams`
  - `provision_project_sublinear`
  - `get_project_sublinear_status`
  - `sublinear_*`
  - `codex_subscription_*`

2. MCP Server

Primary entrypoint:

- `synth_ai.mcp.managed_research_server`

Current size:

- 105 MCP tools

The live tool surface includes:

- health/setup:
  - `smr_health_check`
- project lifecycle:
  - `smr_list_projects`
  - `smr_get_project`
  - `smr_get_project_status`
  - `smr_create_project`
  - `smr_pause_project`
  - `smr_resume_project`
  - `smr_archive_project`
  - `smr_unarchive_project`
- binding/runtime:
  - `smr_get_binding`
  - `smr_promote_binding`
  - `smr_get_pool_context`
  - `smr_get_capacity_lane_preview`
  - `smr_set_execution_preferences`
  - `smr_merge_project_execution`
  - `smr_get_orchestrator_status`
- run control:
  - `smr_trigger_run`
  - `smr_list_runs`
  - `smr_list_jobs`
  - `smr_get_run`
  - `smr_get_run_usage`
  - `smr_get_run_actors`
  - `smr_pause_run`
  - `smr_resume_run`
  - `smr_stop_run`
  - `smr_get_run_results`
- runtime messaging:
  - `smr_list_runtime_messages`
  - `smr_enqueue_runtime_message`
  - `smr_list_runtime_context`
  - `smr_publish_runtime_context`
  - `smr_control_actor`
- artifacts/logs:
  - `smr_get_run_logs`
  - `smr_search_project_logs`
  - `smr_list_run_artifacts`
  - `smr_get_artifact`
  - `smr_get_artifact_content`
  - `smr_list_run_pull_requests`
- approvals/questions:
  - `smr_list_project_questions`
  - `smr_respond_question`
  - `smr_list_project_approvals`
  - `smr_resolve_approval`
- milestones/experiments:
  - `smr_list_project_milestones`
  - `smr_create_project_milestone`
  - `smr_get_project_milestone`
  - `smr_patch_project_milestone`
  - `smr_transition_project_milestone`
  - `smr_list_project_experiments`
  - `smr_create_project_experiment`
  - `smr_get_project_experiment`
  - `smr_patch_project_experiment`
- repo/git/project collaboration:
  - `smr_get_project_repos`
  - `smr_add_project_repo`
  - `smr_remove_project_repo`
  - `smr_get_project_git_status`
  - `smr_list_project_events`
  - `smr_get_project_event`
  - `smr_post_project_message`
  - `smr_git_*`
- provider:
  - `smr_set_provider_key`
  - `smr_provider_key_status`
  - `smr_get_usage`
  - `smr_get_usage_overview`
  - `smr_set_agent_config`
- external integrations:
  - `smr_github_org_*`
  - `smr_linear_*`
  - `smr_codex_subscription_*`
  - `smr_sublinear_*`
- additional operational tools:
  - `smr_get_project_state`
  - `smr_list_resources`
  - `smr_pause_resource`

Dependency Seams To Untangle

Direct `synth-ai` dependencies currently present:

In `synth_ai/sdk/managed_research.py`:

- `synth_ai.core.utils.env.get_api_key`
- `synth_ai.core.utils.urls.BACKEND_URL_BASE`
- `synth_ai.core.utils.urls.normalize_backend_base`
- `synth_ai.sdk.container.auth.encrypt_for_backend`
- `synth_ai.sdk.managed_research_events.SmrEventsClient`
- `synth_ai.sdk.managed_research_git.SmrGitClient`
- `synth_ai.sdk.managed_research_interactivity.SmrInteractivityClient`
- `synth_ai.sdk.managed_research_projects.SmrProjectsClient`
- `synth_ai.sdk.managed_research_runtime.SmrRuntimeClient`
- `synth_ai.sdk.managed_research_sublinear.SmrSublinearClient`

In `synth_ai/mcp/managed_research_server.py`:

- `synth_ai.__version__`
- `synth_ai.core.utils.env.get_api_key`
- `synth_ai.sdk.managed_research.SmrControlClient`

Migration Interpretation

The migration is not a blind file move. There are 3 categories of work:

1. Direct moves

These can likely move with minimal changes:

- most of the SMR SDK request/response logic
- most MCP tool schemas and handlers

2. Re-home shared helpers

These need package-local replacements in `managed-research`:

- API key resolution helper
- backend URL normalization/defaulting
- backend encryption helper for secure provider-key flows
- package version exposure

3. Decide ownership boundaries

These need an explicit product decision, not just code motion:

- GitHub org OAuth helpers
- Linear OAuth helpers
- Codex subscription helpers
- Sublinear provisioning and task helpers
- resource listing/pause operational APIs
- Data Factory flows, which are explicitly out of scope for migration

Proposed Package Layout In `managed-research`

- `managed_research/__init__.py`
- `managed_research/version.py`
- `managed_research/sdk/__init__.py`
- `managed_research/sdk/client.py`
- `managed_research/sdk/projects.py`
- `managed_research/sdk/runtime.py`
- `managed_research/sdk/events.py`
- `managed_research/sdk/git.py`
- `managed_research/sdk/interactivity.py`
- `managed_research/sdk/sublinear.py`
- `managed_research/sdk/integrations.py`
- `managed_research/mcp/server.py`
- `managed_research/mcp/tools/...`
- `managed_research/models/...`
- `managed_research/transport/...`
- `managed_research/_internal/env.py`
- `managed_research/_internal/urls.py`
- `managed_research/_internal/crypto.py`

Recommended Migration Tranches

Tranche 1: Foundation

- create package-local env/url/version helpers
- move base transport + auth helpers
- move typed/public models

Deliverable:

- importable package with no runtime dependency on `synth_ai.core.utils.*`

Tranche 2: Core SDK

- move `SmrControlClient`
- move project/run/usage/approval/artifact/log methods
- move the small companion client modules

Deliverable:

- `managed_research.sdk` provides the canonical client

Tranche 3: MCP server

- move `managed_research_server.py`
- split tool registration into smaller tool modules by domain
- point MCP server to `managed_research.sdk`

Deliverable:

- MCP server modules work without `synth-ai`

Tranche 4: Compatibility and cutover

- add compatibility imports in `synth-ai`
- optionally keep `synth-ai-mcp-managed-research` as a thin wrapper for one release
- update docs and examples
- publish package and cut consumers over

Deliverable:

- `managed-research` is source of truth
- `synth-ai` is adapter/consumer

Recommended Keep-or-Move Decision Matrix

Move now:

- core project APIs
- run lifecycle APIs
- usage APIs
- approvals/questions APIs
- artifacts/logs APIs
- project messaging/milestones/experiments
- MCP server

Move if we want `managed-research` to be the full public product surface:

- GitHub org OAuth and linking
- Linear OAuth and team listing
- Codex subscription flows
- Sublinear provisioning and task/comment APIs

Potentially leave behind temporarily behind shims:

- any code that still requires broader Synth CLI or account bootstrap behavior
- all Data Factory endpoints, helpers, and MCP tools
- all standalone CLI surfaces

Known Risks

- `managed_research.py` is too large right now for safe long-term ownership as a
  single file; migration should include decomposition.
- MCP tool coverage is broad enough that parity drift is a real risk unless we
  add automated tool-surface checks.
- Integration ownership is ambiguous: some surfaces are "managed research"
  product behavior, but some feel like broader Synth account/product plumbing.
- There are already active worktree changes in this repo, so migration work
  should avoid blindly restoring deleted historical files.

Non-Goals For The First Cut

- Re-architecting the SMR backend API
- Redesigning the MCP protocol
- Renaming every command and endpoint at once
- Perfect modularization before first working cutover
- Carrying Data Factory support into `managed-research`

Immediate Execution Plan

1. Add package-local helper modules for env/url/version/crypto.
2. Copy the live `synth_ai.sdk.managed_research*` files into `managed_research`
   with import rewrites only, excluding Data Factory methods and helpers.
3. Copy the live MCP server into `managed_research.mcp.server`.
4. Remove Data Factory MCP tools from the migrated server surface.
5. Add compatibility wrappers in `synth-ai`.
6. Run package builds and import smoke checks.
7. Only after parity is reached, start cleanup/refactor splits.

Explicit Data Factory Exclusions

Do not migrate these SDK methods:

- `get_starting_data_upload_urls`
- `upload_starting_data_files`
- `upload_starting_data_directory`
- `trigger_data_factory_run`
- `data_factory_finalize`
- `data_factory_finalize_status`
- `data_factory_publish`

Do not migrate these MCP tools:

- `smr_get_starting_data_upload_urls`
- `smr_upload_starting_data`
- `smr_trigger_data_factory`
- `smr_data_factory_finalize`
- `smr_data_factory_finalize_status`
- `smr_data_factory_publish`

Practical Recommendation

Do not try to "rebuild" the package from the old 0.1.0 code. Use the current
live `synth-ai` implementation as the migration source, move it with minimal
behavior changes, then refactor in place inside `managed-research`.
