dev-rebased: fork→main port, web admin completion, workspace machine binding - #204
Closed
crimsonsunset wants to merge 148 commits into
Closed
dev-rebased: fork→main port, web admin completion, workspace machine binding#204crimsonsunset wants to merge 148 commits into
crimsonsunset wants to merge 148 commits into
Conversation
Autonomous decisions: - Reverted packages/ui/src/components/layout/Sidebar.tsx and AppShell.tsx to main versions — main is ahead of i18n on these files (accent strip, hint prop, group-hover animations); porting i18n's older versions would have been a regression. - Ported apps/desktop/src/lib/api/ shim files (app.ts, configExport.ts, settings.ts, transport.ts, oauth.ts, serverClone.ts, workspaceAppearances.ts, fetch-api.ts/helpers/types) — required by backend/shell/index.ts and build-info.helpers.ts; all are @deprecated re-export shims pointing at the new backend facade. - In api/index.ts: selective named exports from oauth.ts instead of export * — avoids duplicate symbol conflicts with existing gateway.ts which still exports OAuthClient, RegistrationType, UpdateClientRequest, and the OAuth client CRUD functions; only oauth.ts-unique additions (flushPendingDeepLink, ConsentRequestDetails, getPendingConsent, approveOAuthConsent) are re-exported. - Ported scripts/build-date.helpers.mjs alongside the spec'd scripts — it is a peer dependency of build-stamp.mjs and build-web-admin.mjs; omitting it would make those scripts fail at runtime. - Updated apps/desktop/src/lib/api/index.ts to export new api shim modules — required so backend/index.ts export * from '../api' resolves all symbols the facade depends on.
…epositories Ports the fork's storage schema onto main, renumbered 020-031 to sit after upstream's 016-019. Extends InstalledServer (cloned_from, display_name_override, default_params(+strategy), update_policy, pinned_version, latest_available_version, version_checked_at, current_version), WorkspaceBinding (client_id, label), and FeatureSetMember (surfaced) additively, with the SQLite repos round-tripping the new columns. Adds embedding_repository + workspace_appearance_repository and their core traits/entity. Autonomous decisions: - Kept main's exact-match WorkspaceBinding resolution (find_exact_for_roots); did NOT port i18n's longest-prefix + client-scope resolver — per orchestrator Choice A. client_id/label are persisted additively but stay global (None) today; per-client routing is a later gateway phase. - Did not wire the new repos into ApplicationServices — i18n itself doesn't wire them there, and their consumers (gateway embedding/discovery services, workspace-appearance commands) land in later phases. Repos are crate-exported and unit-tested. - Kept main's stronger InstalledServerRepository semantics (build_server -> Result, careful decrypt error distinction) rather than porting i18n's signatures; only the 9 new columns were added to the existing install/update CRUD. Did not add i18n's set_display_name_override/update_version_cache trait methods (later-phase consumers). - Renamed migration 027's internal "-- Migration 023:" comment to 027 to match the renumbered filename. - New feature-set members default surfaced=false at every construction site, matching migration 023's DEFAULT 0 and the entity constructors. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Port the web admin HTTP server stack from the i18n branch to main, reconciled with Phase 1–2 divergences. Autonomous decisions: - Stubbed Phase 5/6/7 features (version probing, clone_server, display name override, public URL persistence, workspace icon upload via the `image` crate) with descriptive errors and ponytail comments — avoids pulling in unported dependencies while preserving the API surface. - Replaced `WorkspaceBinding::new_scoped_multi` (Phase 6) with `new_multi` + manual client_id assignment using the existing API. - Replaced `find_longest_prefix_match` (not yet added to the repo trait) with an inline prefix-scan over `list_for_space`. - Used `option_env!` for MCPMUX_BUILD_* env vars so `cargo check` works outside CI without those variables set. - Added admin settings keys and methods to `AppSettingsService` in mcpmux-core (get/set admin_enabled, admin_port, trust_cf_access, cf_team_domain) — minimal extension, no breaking changes. - Added `space_repository()` accessor to `SpaceService` to avoid exposing the private `repository` field. - Added `test-utils` feature flag to mcpmux-gateway Cargo.toml, used by the ported `#[cfg(feature = "test-utils")]` test helpers. - Wired admin server startup into lib.rs setup closure; registered `reload_admin_server` Tauri command; integrated `emit_ui_channel` into the gateway domain-event bridge for SSE fan-in. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
- Add macos_dock.rs: set_dock_visible() wraps ActivationPolicy + dock visibility, cfg-gated #[cfg(target_os = "macos")] with a no-op stub for other platforms - Add macos_permissions.rs: ensure_contacts_registered() triggers CNContactStore TCC prompt on first launch so McpMux appears in System Settings → Privacy & Security → Contacts; no-op on non-macOS - Add main_window.rs: show_main_window() / hide_main_window_to_tray() helpers used by tray, deep-link focus, and close-to-tray handler - Add Info.plist: NSContactsUsageDescription, NSCalendarsUsageDescription, NSRemindersUsageDescription, NSAppleEventsUsageDescription TCC keys - Wire lib.rs: declare new modules, call ensure_contacts_registered() + set_dock_visible(false) in setup, use main_window helpers throughout - Add commands/workspace_appearance.rs: list/upsert/delete workspace appearances + upload/resolve icon file commands - Register workspace_appearance in commands/mod.rs and invoke_handler - Add DomainEvent::WorkspaceAppearanceChanged to mcpmux-core and handle in gateway ui_events + desktop gateway bridge - Add target-specific macOS Cargo deps: objc2, objc2-foundation, objc2-contacts, block2 Autonomous decisions: - WorkspaceBinding.icon check in maybe_remove_orphaned_icon_file deferred to Phase 7 (field not yet on the entity); left a ponytail: comment - DomainEvent::WorkspaceAppearanceChanged added now (minimal addition alongside Phase 2 entity) to unblock the commands compiling Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Port dev's split meta_tools module layout and supporting gateway services from the i18n branch (supersedes upstream consolidated files per plan Decision #6): - Split meta_tools modules: invoke_*, search_tools(_index), list_servers, meta_tool_common, disclosure_*, feature_set_tools, bind_workspace, set_workspace_root, token_budget, approval_broker/types, diagnose_*. - Gateway services: tool_discovery*, embedding, embedding_warmer, discovery_rank, prompt_discovery, resource_discovery. - Wire embedding warmer into MCPNotifier on connect / feature-refresh. - Add WorkspaceBinding::new_scoped_multi and a client-scoped-with-global -fallback find_longest_prefix_match default impl; use it in the admin effective-features bridge. - Additive FeatureService grant helpers, ToolCallResult.structured_content, routing format helpers, session_roots search cache. - Reconcile meta_tool_approval Tauri command with the always-approve broker. package_version / server_version_probe deferred to Phase 6. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
- New Rust services: package_version, server_version_probe, server_clone - New domain events: ServerVersionChecked, ServerUpdateAvailable - InstalledServerRepository: set_display_name_override, update_version_cache - ServerAppService: clone_server, is_clone_id_available, suggest_clone_suffix, list_clone_dependents, set_display_name_override, update_config extended with update_policy + pinned_version - pool/transport/resolution: TransportResolutionOptions with update-policy - New Tauri commands: get_build_info, set_server_display_name, clone_server, is_clone_id_available, suggest_clone_suffix, list_clone_dependents, update_server_package, get/update_server_update_settings, check_all_server_updates, check_server_version - Frontend: CloneAccountModal, UninstallSourceWithClonesDialog, ServerActionMenu (clone + update actions), ServerUpdatesSection, ServerPendingUpdatesList, BuildStampPanel, StaleBuildBanner, use-build-stamp.hook, server-update-policy.helpers, server-pending-updates.helpers, server-display-name.helpers - ServersPage: clone-aware uninstall, handleLockToCurrentVersion, handleUpdateNow, handleCheckForUpdate wired end-to-end - build.rs: embed git SHA, branch, commit/build timestamps Signed-off-by: crimsonsunset <jsangio1@gmail.com>
- Add features/dashboard/ (DashboardPage, DashboardQuickLinks, DashboardRecentActivity, DashboardServerHealth, DashboardStatCards, dashboard.helpers, useDashboardData, index) - Add /dashboard nav entry in navigation.ts + App.tsx route - Port SourceBadge (add clonedFrom prop), source-badge.helpers.ts, AddServerMenu, ServerEnabledToggle, ServersCountSummary, ServersFiltersPopover, servers-page.helpers — hardcoded English - Wire workspace appearances into WorkspacesPage (load/persist icons for unmapped roots, card + inspector live preview, upload via pickPath) - Extend ServerIcon to resolve local:workspace-icons refs - Add SpacePanel slide-out editor in features/spaces/ - Add AboutSection to features/settings/ - Add useMetaToolEvents, useOAuthClientEvents, useWorkspaceEvents shims - Reconcile useServerManager to use useDomainEvents subscribe facade - Add pendingServersFilter state/action/selector to appStore - Add update_space Tauri command + SpaceService.update + updateSpace API - Wire resolveInstalledDisplayName into registryStore.mergeServers SpaceSwitcher already uses spaceAccentTint + space.icon (no change needed). pnpm validate clean; no react-i18next in this phase. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Port react-i18next infrastructure and stringified UI from i18n branch onto the reconciled Phases 1–7 port branch. Reconcile nav IA, meta-tools, workspaces, registry analytics, and Phase 5–7 locale keys while keeping port functionality intact. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Dashboard is the sole default nav with accent stat tiles, onboarding strip, and live stat refresh; Home page and nav entry are removed. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Detect fork v16–27 ledger, apply upstream v16–19 SQL, and stamp v31 without re-running fork migrations that would duplicate columns. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
My Servers, Search, Bundles, Projects, and Clients labels with matching icons; Bundles keeps a FeatureSets tooltip; e2e selectors updated. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Autonomous decisions: - Meta-tool fixes (7e1ab44, de5ccb4, e428dcf) — no patch; dev-rebased already matches dev functionally - Server-update probe fixes (d0d0232, 92e340f, c489692) — no patch; package_version, server_version_probe, and resolution.rs already aligned - ServersPage / server-update-policy.helpers — no patch; shouldShowPackageUpdate already present; kept i18n getUpdatePolicyOptions over dev's hardcoded UPDATE_POLICY_OPTIONS - write_runtime.rs — manual patch from 7414f75; wire version_probe, apply_package_update on explicit update, post-update probe to clear stale badges Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Autonomous decisions: - Delegate openSpaceConfigFile, openUrl, addToVscode/addToCursor to shell — desktop-only commands need web-safe fallbacks without new HTTP routes - Fix update_space route to accept flat Tauri args or nested input — Tauri IPC uses flat fields while admin REST expects a JSON body Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Wire missing admin API bridges and fetch-api routes so the web SPA can load spaces, registry, and settings without Tauri invoke. Re-export transport-aware domain events, enable SSE after data sync, and guard remaining listen() call sites for admin-http mode. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Autonomous decisions: - Run prep after backend auto-start — keeps fail-fast health check without breaking cold-start flow - Honor MCPMUX_ADMIN_PORT in Vite proxy — matches dev script port env convention - prep subcommand is health-check only — no port-guard utility exists in repo; Phase 1 scope is liveness Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Wire five config-export admin endpoints matching fetch-api.routes.ts: preview, paths, check, backup, and export. Bridge logic mirrors the existing Tauri config_export commands via ConfigExporter and enabled server resolution through ApplicationServices. Autonomous decisions: - POST handlers live in handlers/write.rs; bridge logic consolidated in command_bridge/read.rs per plan (check/backup/export delegate there). - Enabled servers resolved via list_for_space + filter rather than adding installed_server_repo to AdminBridgeCtx. - Export always writes unmasked credentials, matching desktop Tauri behavior. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Route oauth-consent-request and oauth-client-changed through emit_ui_channel so web admin SSE receives them, and align BuiltinServerConfigChanged SSE mapping to builtin-server-config-changed. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Guard native openDialog/pickPath calls with isTauri() and show text path inputs on web admin so base dirs, server config paths, and workspace icons/roots work without crashing the browser. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Remove superseded export_config, connect_server, and disconnect_server_v2 apiCall/Tauri paths; extend admin-transport tests for builtins, config-export routes, direct SSE channels, and dead-command guard. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Document the five-phase web admin completion work and apply rustfmt drift from Phases 2–3 command bridge and ui_events changes. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
…ion plan Partial Phase 1 work: list_tools uses get_advertised_tools_for_grants again. Includes database.rs formatting cleanup and the planning doc. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Restore get_advertised_prompts_for_grants and get_advertised_resources_for_grants in facade.rs; wire list_prompts, get_prompt, list_resources, and read_resource to filter through surfaced feature IDs (list_tools already fixed in 93e6bef). Autonomous decisions: - Used get_fetchable_prompts / get_readable_resources as invokable base — matches dev branch and existing facade aliases Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Restore dev hard-cut model on call_tool, get_prompt, and read_resource: non-surfaced invokable features redirect to meta-tool paths; inactive tools get bind_feature_set hints via list_inactive_discovery_tools. Re-export format_direct_* helpers from pool/mod.rs. Restore structured_content passthrough on call_tool results. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Restore file-key credential migration at startup, WorkspaceNeedsBinding collision_client_id alongside space_locked, and OAuth refresh dedup singleton. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Autonomous decisions: - Marked surfacing Phases 1–3 complete with commit SHAs (126fa2f, b131a3f, 6c4d6b7) - Audited post-port Phases 1–2 as complete (784cd41, 9747c71); Phase 3 manual QA documented - No code fixes needed — all automated gates passed on HEAD manual QA required: full post-port Phase 3 feature walkthrough (dashboard, i18n, spaces, servers, feature sets, workspaces, clients, registry, builtins, settings, meta-tools via MCP client, web admin SSE/CF Access, surfacing smoke test) Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Land label/icon metadata on workspace bindings, appearance commands, and Projects UI ahead of machine-binding work on feat branch. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Test called the undefined render() instead of the i18n-aware helper used elsewhere in the file, failing every run. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Expose inbound_clients.machine_id in the Connections page (chip on cards, picker + inline create in the side panel), make machine selection skippable during OAuth consent, and fix the inline create form defaulting the icon so the save button isn't stuck disabled. Also drop the hostname autofill in that form since it misleadingly suggested the local machine's hostname for remote connections. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Close enrichment and rank timing blind spots, and log include_inactive/scope usage so cold vs warm baselines can drive the next perf pass. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Warm path no longer full-space feature-resolves for enrichment; session index is Arc-shared and warmer embeds in one batch. Measured warm HogQL ~346ms → ~33ms. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Record Phase 1.5 hybrid keep decision, Phase 1 after numbers, and Phase 2 unlock criteria so the ticket is closed without implying FTS work next. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
Surface session_id, X-Mcpmux-Workspace, pin/clobber, and resolved root so we can prove whether Agents Window shares MCP sessions across workspaces. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
A roots-capable session reporting multiple folders (no pinned X-Mcpmux-Workspace header) was silently resolving to the first matching binding instead of holding until unambiguous. Reuses the existing PendingRoots pattern; mcpmux_set_workspace_root or a header pin remains the escape hatch. Reconciles the Agents Window spike doc with its actual finding (session isolation works; this gate is the fix for the real bug it surfaced) and flips the stale status on the rootless declare-root gate doc, which already shipped Jul 23. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
mcpmux_bind_current_workspace was still first-root-wins on unpinned multi-root sessions, so a gait agent could offer to mutate sync2hire. Refuse until one root is pinned, list candidates in the error and in mcpmux_list_servers PendingRoots notes, and log pre-approval binds. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
A phantom root (moved/deleted folder still reported by a stale client source, e.g. an orphaned background-agent worker) alongside a real one was holding sessions at PendingRoots indefinitely. If exactly one reported root still exists on disk, narrow to it and resolve normally instead of waiting on the client to pin a header. Genuine ambiguity — zero or multiple surviving roots — still holds at PendingRoots. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
…am reconciliation
- New doc assesses SEP-2567/2575/2577 (sessionless MCP, handshake
removal, roots deprecation) against mcpmux's architecture; rmcp is
pinned at 1.5.0 so none of it is wire-visible yet, but the
resolver's ranked-signal design already anticipates the shift.
- Upstream client-mapping reconciliation doc was stale ("Planning —
not started") despite all 4 phases having shipped Jul 17; updated
status and added a Resolution section with the landing commits.
Signed-off-by: crimsonsunset <jsangio1@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reference PR against upstream
mainshowing everything ondev-rebased: the 8-phase fork→upstream port, workspace machine-binding (#8), a client↔Space/FeatureSet mapping feature independently reconciled against upstream's own version of it, the Cursor globalmcp-remotebridge, and assorted hardening.Not for merging yet — opened purely so
main's reviewers can see the diff. Currently fast-forwardable:mainmerged its own client-mapping feature directly (#201/#202/#203/#205/#206) on Jul 15, which briefly put this branch in a real (non-fast-forward) divergence frommain; that was reconciled by mergingmainintodev-rebasedon Jul 17 (eb5ae35), andmainhasn't moved since —git merge-baseresolves exactly tomain's current tip again.Unlike this diff, the fork-internal
dev-rebased→devswap (#7) has unrelated histories against the olddevline and needs a squash/reset, not a merge.115 commits · 458 files · +56,979 / −11,462 (140 files / +21,965/−2,348 in
crates/, 206 files / +23,886/−7,705 inapps/) · base:main@87df4a2(Jul 15,#203)Review guide
458 files is a lot as one diff. Every link below is a plain commit-range compare on the fork (
crimsonsunset/mcp-mux, since intermediate commits don't exist onmain) — no rebasing, just the branch's own commit boundaries. Each renders like a normal PR-sized diff.A — Fork → upstream port, one link per phase (Jun 23–24)
Mostly the fork's existing code being adapted onto
main's structure, not new product behavior.B — Post-port fixes, surfacing regression, web admin completion (Jun 24)
7d9c6e6...4ddc339 — 112 files, +3,825/−1,791
Worth a close read: the surfacing-regression fix is the security-relevant part — the rebase briefly exposed ~2228 tools on the gateway instead of the ~5 meta tools it should advertise, fixed across 4 phases (
93e6bef,126fa2f,b131a3f,6c4d6b7).C — Workspace binding label/icon port, migration 032 (Jun 25)
4ddc339...18a7976 — 23 files, +472/−73
D — Workspace machine binding (Jun 25 – Jul 1)
18a7976...e38a390 — 169 files, +11,390/−3,289
Or skip straight to #8 — already reviewable as its own PR with its own history and test plan. Headline: machine catalog + machine-scoped resolver, deny-by-default (breaking change — unmapped folders/clients now get zero tools instead of the Starter fallback), grouped multi-machine project cards, cross-machine adopt flow.
E — Config-sync hardening + client↔Space/FeatureSet mapping reconciliation (Jul 7–17)
e38a390...eb5ae35 — 65 files, +4,121/−462, 19 commits
Two distinct pieces on one link: config-sync/server-editing fixes (Jul 7), then a client-mapping feature the fork built independently that turned out to duplicate what upstream shipped as
#201–#206— reconciled by mergingmainin rather than discarding either side's work.F — Cursor bridge, server-def editing, revocation + session hardening, connection icons (Jul 20)
eb5ae35...0b52f0f — 33 files, +1,077/−44, 10 commits
Scope
Fork → upstream port (Jun 23–24)
Full plan:
docs/planning/dev-to-main-port.mdPost-port completion
lib/apiinvoke→apiCallmigration (web admin transport parity)Plan:
docs/planning/dev-rebased-post-port-completion.mdSurfacing regression fix
The rebase dropped the advertised/surfaced filtering layer, exposing ~2228 tools instead of ~5 meta tools on the gateway MCP endpoint.
93e6beflist_tools→get_advertised_tools_for_grants(initial fix + planning doc)126fa2fget_advertised_prompts/resources_for_grants; wire list/fetch pathsb131a3fcall_tool/get_prompt/read_resource;structured_contentpassthrough6c4d6b7collision_client_id+space_lockedonWorkspaceNeedsBinding, OAuth refresh dedup59fcc09Plan:
docs/planning/dev-rebased-surfacing-regressions.mdWeb admin completion
Plan:
docs/planning/web-admin-completion.mdWorkspace binding label/icon port (migration 032)
Ports label/icon metadata onto
workspace_bindings, the base migrations 033–035 (machine binding) build on.Workspace machine-scoped bindings + deny-by-default
Merged into
dev-rebasedJul 1 as #8 (62 commits, 168 files, +11,338/−3,288) — see that PR for its own detailed review and rebase-conflict-resolution table. Headline scope:machinescatalog +machine_idscope onworkspace_bindingsandinbound_clients(migrations 033–035)X-Mcpmux-Machine-Id) → client machine → local machine → globalwouterURL routing replacing Zustand-only nav; web admin OAuth SSE hub consolidation; remote gateway public-URL + tunnel consent support; OAuth consent UX (machine naming on first connect)Config sync + server-definition hardening
sync-updatedevent for the UIPlan:
docs/planning/user-config-sync-collision-fix.mdClient↔Space/FeatureSet mapping + upstream reconciliation
The fork built this independently of upstream, which shipped equivalent behavior directly to
mainas#201/#202/#203/#205/#206on Jul 15 — the two implementations genuinely diverged and were reconciled by mergingmainintodev-rebased, not by discarding either side.830c2ecmcpk_Bearer, migration036) — no routing changes9af05c0binding_type(migration037) + resolver Tier 2 id-binding lookup3401053locked_space_id(migration038) as a resolver Tier 0 narrowing filter, not a bypass3eb678cauth_disabledfix,structuredContent/_metapassthrough fix, non-localhost consent bannereb5ae35upstream/main(through#215) intodev-rebasedDecisions preserved over upstream's originals: kept
Unboundas the sole deny terminus everywhere (rejectedSpaceDefault/Starter fallback for API-key clients too); Space lock narrows the existing resolver tiers instead of early-exiting past them; kept fork nav labels (Clients/Projects/Bundles, noApps→Clients/Workspaces→Mappingrename); migrations landed as036–038(fork numbering), superseding upstream's020–022outright rather than keeping both.Merge conflict resolution: ~24 files conflicted (resolver, repositories, domain, Tauri commands, Clients/Workspaces UI, tests) — all resolved in favor of the fork's reconciled implementation since it's a strict superset. Also caught two real bugs the raw merge would've introduced: a new upgrade-path regression test referenced upstream's migration numbers and would have dropped this fork's migrations
20–35on rollback instead of just36–38; three e2e specs asserted upstream's rejected"Mapping"nav label instead of the fork's actual"Projects". Took upstream's unrelated CI hardening and new API-key e2e test as-is.Plan:
docs/planning/upstream-client-mapping-reconciliation.mdCustom server definition editing
Cursor global
mcp-remotebridgeNew onboarding path for Cursor: one global
~/.cursor/mcp.jsonentry usingmcp-remote+${workspaceFolder}header interpolation, so every Cursor window routes to the right Workspace binding without a per-project MCP config. Motivated by Cursor'srootscapability reporting being unreliable in practice.1b970f9) — manual spike confirmingmcp-remote(--allow-http,--header) reaches the gateway and workspace-header routing resolves correctly across two windowse48885c) — desktop UI: mints an API key and renders/copies the ready-to-pastemcp.jsonsnippet from the Clients pagebda7e04) — docs: manual verification guide (docs/manual/cursor-workspace-bridge.md) + recommendation surfaced in the existing workspace-header-routing and remote-access docsPlan:
docs/planning/cursor-workspace-routing-bridge.mdRevocation + session hardening, connection icons
Found and fixed during manual QA of the Cursor bridge above:
b66cc54—~home-shorthand in a reported/pinned workspace root was rejected as "not absolute" instead of expanded, breaking bridge routing for any path typed or reported with a tilde53d28df—mcp-remote's HTTP session churn (client-side timeout → retry → new session) was piling up stale sessions per(client_id, workspace_root)on reconnect, amplifyinglist_changednotification fan-out; new sessions now supersede the prior one for the same paira55081e— revoking a client only invalidated its row ininbound_clients; the JWT it already held stayed cryptographically valid until expiry, so a revoked bridge client kept retrying auth and popping browser tabs. The gateway now checks client existence on every authenticated request and rejects immediately (401) once the row is gone;ClientDeletedalso proactively drops the client's live session bookkeeping8894960—last_seen(Connections page "live" dot) was only stamped by the/oauth/tokengrant flow, which API-key clients (bridge included) never hit; now stamped on every authenticated request regardless of auth mode0b52f0f— Connections page: per-client emoji icon override (newclient_iconcolumn, migration039), editable via the same shared emoji-picker component Machines/Spaces/FeatureSets already use, falling back to the existing logo/known-client-name resolution when unsetKey technical decisions
list_*usesget_advertised_*(surfaced FeatureSet members only); non-surfaced tools reachable viamcpmux_invoke_tool. Hard-cut guards on direct calls to non-surfaced tools returnuse_invoke_tool/bind_feature_setredirect hints.WorkspaceNeedsBindingcarries bothcollision_client_id(collision UX) andspace_locked(scoped Space picker).WorkspaceBindingis canonical; reported root, client identity, and machine are ranked match signals, none mandatory — absence of all resolves toUnbound(zero tools), not a silent Starter fallback.client_id(OAuth app) andmachine_id(physical host) are two independent, stacked scope axes onWorkspaceBindingrather than one unified caller-identity concept. Tracked as a follow-up indocs/planning/workspace-machine-binding.md.dev-rebased→devswap (unrelated histories, needs squash/reset), this diff against upstreammainis currently a clean fast-forward.mcp-remote, disambiguated by(client_id, workspace_root)rather than one client per project — session superseding on reconnect keeps that from piling up stale sessions.Test plan
pnpm validateclean ondev-rebasedpnpm test:ts— 345/345 (per feat: replace changesets with release-plz for Tauri releases #8)pnpm test:rust— 850 passed, 2 skipped (per Jul 17 reconciliation)pnpm lint+cargo clippy --workspace -- -D warningscargo check/clippyclean onmcpmux-storage/mcpmux-gateway/mcpmux-core/mcpmux(Jul 20 additions)039applied and exercised against a live dev gateway —last_seenadvancing for a real bridge client,client_iconround-trippingpnpm dev:web:adminsmoke — admin API on:45819use_invoke_toolredirect hintWorkspaceNeedsBindingfiresX-Mcpmux-Machine-Idbinds and resolves independently (see feat: replace changesets with release-plz for Tauri releases #8 test plan)${workspaceFolder}routing via the globalmcp-remotebridge in real CursorNo CI ran against this branch/fork — all of the above is self-reported from local runs, not an automated gate.
Docs
docs/planning/dev-to-main-port.mddocs/planning/dev-rebased-post-port-completion.mddocs/planning/dev-rebased-surfacing-regressions.mddocs/planning/web-admin-completion.mddocs/planning/workspace-machine-binding.mddocs/planning/deny-by-default-bindable-callers.mddocs/planning/per-device-machine-header.mddocs/planning/meta-tools-machine-scoped-binding.mddocs/planning/projects-grouped-machine-cards.mddocs/planning/workspace-binding-project-adopt.mddocs/planning/sidesheet-panel-identity-header.mddocs/planning/user-config-sync-collision-fix.mddocs/planning/upstream-client-mapping-reconciliation.mddocs/planning/cursor-workspace-routing-bridge.mddocs/manual/cursor-workspace-bridge.mddocs/guide/remote-access.mdxRelated
dev-rebased→devswap (unrelated histories, squash/reset; closed without merging)dev-rebasedJul 10b52f0fondev-rebasedUpdate log
e38a390(93 commits / 435 files)eb5ae35: reconciled independent client-mapping feature against upstream's#201–#206, landed directly onmainJul 150b52f0f: config-sync hardening, custom server-def editing, Cursor globalmcp-remotebridge, revocation/session hardening, connection-icon override