Skip to content

Add Workspace-Aware Support#200

Merged
ravitemer merged 15 commits into
mainfrom
feat/per-project-hub
Jul 18, 2025
Merged

Add Workspace-Aware Support#200
ravitemer merged 15 commits into
mainfrom
feat/per-project-hub

Conversation

@ravitemer
Copy link
Copy Markdown
Owner

Description

This PR introduces workspace-aware MCP Hub functionality, enabling project-specific MCP server configurations. This addresses several key issues including project-local configs, variable interpolation, and multi-project isolation.

Main View

image

Config View

image

Related issues:

#148
#183
#196

🏠 Workspace Detection

  • Smart Discovery: Automatically detects project roots using configurable markers
  • Flexible Config Files: Support for .vscode/mcp.json, .cursor/mcp.json, mcp.json, .mcphub/servers.json
  • Dynamic Port Allocation: Hash-based port generation with conflict resolution
  • One Hub Per Workspace: Enforces single hub instance per project directory if marker files are found

🎨 UI Improvements

  • Grouped Server Display: Servers organized by config source (Global vs Project)
  • Multi-Config Editor: Tab-based interface for editing different config files
  • Source Indicators: Visual indicators showing server origins
  • Enhanced Marketplace: Choose config destination when installing servers

Configuration

-- New workspace configuration
workspace = {
    enabled = true,
    look_for = { ".vscode/mcp.json", ".cursor/mcp.json", "mcp.json", ".mcphub/servers.json" },
    port_range = { min = 40000, max = 41000 }
}

Server Launch Flow

  1. Context Resolution: Detect workspace vs global mode
  2. Config Discovery: Find project-local config files
  3. Port Management: Generate/discover workspace-specific port
  4. Hub Launch: Start with merged configs (globalproject)
  5. Cache Registration: Register in global workspace cache

Config Merging Strategy

  • Global First: Load global config as base
  • Project Override: Project configs override global settings
  • Source Tracking: Each server tagged with config_source field

Related Issue(s)

Screenshots

Checklist

  • I've read the contributing guidelines and have adhered to them in this PR
  • I've updated the README and/or relevant docs pages
  • I've run make test to ensure all tests pass
  • I've run make format to format the code
  • I've run make docs to update the vimdoc pages

@ravitemer ravitemer force-pushed the feat/per-project-hub branch from 1429f74 to a6b7073 Compare July 15, 2025 02:46
@ravitemer ravitemer force-pushed the feat/per-project-hub branch from aa51f47 to 94a5072 Compare July 15, 2025 15:11
@ravitemer ravitemer marked this pull request as ready for review July 15, 2025 16:48
@ravitemer ravitemer force-pushed the feat/per-project-hub branch 3 times, most recently from 45dd23a to a9f5fb2 Compare July 17, 2025 17:46
@ravitemer ravitemer force-pushed the feat/per-project-hub branch from b38eb9c to 195e5ed Compare July 18, 2025 05:20
ravitemer added a commit that referenced this pull request Jul 18, 2025
### Added

- ** Workspace-Aware MCP Hub**: project-local configuration support
(#148, #183, #196, #200)
  - **Smart Project Detection**: Automatically detects project
boundaries using `.mcphub/servers.json`, `.vscode/mcp.json`,
`.cursor/mcp.json`
  - **Isolated Hub Instances**: Each workspace gets its own mcp-hub
process with unique ports (40000-41000 range)
  - **Configuration Merging**: Project configs automatically override
global settings while preserving global servers
  - **Automatic Switching**: Seamlessly switches between workspace hubs
on directory changes (`DirChanged` events)
  - **Dynamic Port Allocation**: Hash-based port generation with
conflict resolution and custom port assignment support

- ** Global Environment Variables**: Universal environment injection for
all MCP servers (#183)
  - **Flexible Configuration**: Support for both table and
function-based global_env configuration
  - **Context-Aware Variables**: Function receives workspace context
(port, config files, workspace mode)
  - **Mixed Format Support**: Array-style (`"VAR"`) and hash-style (`KEY
= "value"`) entries
  - **Automatic Resolution**: Environment variables resolved when hub
starts with project context

- **ƒÄ¿ Enhanced UI Experience**: Complete workspace management
interface
  - **Active Hubs Section**: View and manage all running workspace hub
instances
  - **Grouped Server Display**: Servers organized by config source
(Global vs Project) with visual indicators
  - **Multi-Config Editor**: Tab-based interface for editing different
config files (global and project)
  - **Workspace Actions**: Expand/collapse details, kill processes,
change directories, view configuration files

### Enhanced

- **Directory Change Handling**: Proper hub switching when changing
directories in Neovim
- **Config File Watching**: Enhanced file watching to handle multiple
configuration sources
- Some common expected keymaps like `<Cr>`, `o` and `<Esc>` work along
with the `l` and `k` keys

### Fixed

- **Multi-Project Isolation**: Solves the fundamental issue of MCP
servers working in wrong project directories
- **Environment Variable Access**: Addresses user session variables
(like `DBUS_SESSION_BUS_ADDRESS`) not being available to MCP servers

### Migration Guide

Existing configurations work without changes. To enable workspace
features:

```lua
require("mcphub").setup({
  workspace = {
    enabled = true, -- Default: true
    look_for = { ".mcphub/servers.json", ".vscode/mcp.json",
".cursor/mcp.json" },
    reload_on_dir_changed = true,
    port_range = { min = 40000, max = 41000 },
    get_port = nil, -- Optional custom port function
  },
  global_env = {
    "DBUS_SESSION_BUS_ADDRESS", -- Array-style: uses os.getenv()
    API_KEY = os.getenv("API_KEY"), -- Hash-style: explicit value
  }
})
```
@ravitemer ravitemer merged commit c233abf into main Jul 18, 2025
5 checks passed
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