Multi-repo workspace manager with MCP server + web dashboard
Project description
project-hub
Multi-repo workspace manager that unifies local git state and GitLab forge data (MRs, pipelines, vulnerabilities) into a single MCP server + web dashboard.
Designed for engineers managing many repos under one parent directory.
Killer features
aka why I built this
Vulnerabilities that make sense. GitLab's vulnerability report is per-repo, noisy, and doesn't tell you what's already being fixed. project-hub aggregates vulns across all your repos, cross-references them with open MR branches to flag what's already fixed but not yet merged ("fixed in branch"), and lets you filter by severity, state, or hide already-handled ones. You see what actually needs work, not what's already in flight.
Stale branch detection. After merging an MR you often forget to switch back to the default branch locally. project-hub detects repos still sitting on stale feature branches and shows ahead/behind relative to the default branch — with a one-click checkout to clean up.
Events, not inbox. Stop reminding yourself to check your cluttered GitLab inbox. project-hub diffs state on every refresh cycle and surfaces what changed: new MR, pipeline failure, new vuln, auth expiry. Events live in a slide-in panel on the dashboard and persist across sessions until dismissed.
MCP-powered multi-repo agent. Everything visible in the dashboard is exposed as MCP tools. Claude Code sees your repos, MRs, pipelines, vulns, and events — and can act on them. Events surface as MCP notifications, making the agent proactive instead of reactive.
Features
- Unified dashboard — git status, MRs, pipelines, vulns across all repos in one view
- Merge request & pipeline views — cross-repo tables with filters (mine/all, failed only, current branches only)
- Per-repo detail page — MRs, pipelines, active vulns for a single repo
- Web UI (htmx) with real-time sync, sortable tables, persistent filters
- Non-destructive pull — conflict detection via
git merge-tree, no worktree mutations - Pin & reorder repos, drag-and-drop card layout
- Bulk actions — pull all, unstale all in one click
Quick start
cd ~/Projects # parent dir containing your repos
uvx project-hub init # creates .project-hub/
uvx project-hub auth login gitlab.com # store your PAT
uvx project-hub # launch dashboard (opens browser)
Use as MCP server (Claude Code)
From PyPI:
claude mcp add --scope user project-hub -- uvx project-hub --mcp
From source (picks up local changes without cache issues):
claude mcp add --scope user project-hub -- \
uv run --project /path/to/project-hub project-hub --mcp
Installing with --scope user is safe — the server adapts to the current directory:
| Directory state | Behavior |
|---|---|
Has .project-hub/ |
Active — full tools + refresh |
Parent has .project-hub/ |
Disabled — zero tools (sub-repo) |
Has .no-project-hub |
Disabled — zero tools (opt-out) |
| Neither | Dormant — only init tool |
touch ~/some-project/.no-project-hub # force disable in a specific dir
Then in Claude Code, the agent can call tools like list_repos, get_vulnerabilities, pull_safe, etc.
MCP tools
| Tool | Description |
|---|---|
init |
Bootstrap .project-hub/ workspace |
list_repos |
List discovered repos with forge info |
repo_status |
Git status (branch, ahead/behind, dirty) |
fetch_all |
Trigger full refresh cycle |
pull_safe |
Pull with conflict detection |
list_mrs |
Merge requests (substring repo filter) |
list_pipelines |
Pipelines (substring repo filter) |
get_vulnerabilities |
Vulns — defaults to high/critical + detected, includes solutions |
get_pipeline_jobs |
Jobs for a specific pipeline |
acknowledge_alerts |
Mark events as seen |
auth_status |
Check forge authentication |
auth_login |
Store PAT for a forge instance |
configure_forge |
Configure forge host mapping |
Web dashboard
| Route | Description |
|---|---|
/ |
Dashboard with repo cards, pinning, drag-and-drop, events panel |
/mrs |
Merge requests table (mine/all filter) |
/pipelines |
Pipelines table (failed only, current branches only) |
/vulns |
Vulnerabilities (severity, state, fixed-in-branch filters) |
/repo/{name} |
Per-repo detail: MRs, pipelines, active vulns |
/settings |
Exclude/include repos, rescan workspace |
All filters and table sort are persisted in localStorage.
Architecture
Single Python process, dual interfaces: MCP (stdio) + HTTP (FastAPI/htmx). Background asyncio task refreshes git+forge data on a TTL cycle, diffs with SQLite cache to generate events.
project_hub/
cli.py # Click entry points
core/
workspace.py # Orchestrator: discover -> refresh loop -> stop
cache.py # SQLite (WAL mode, aiosqlite)
config.py # YAML config with defaults
discovery.py # Scan for .git/ repos, classify forges
models.py # Dataclasses: Repo, MR, Pipeline, Vulnerability, Event
events.py # Diff old vs new state -> Event list
gitlab/
client.py # python-gitlab + GraphQL (vulnerabilities)
auth.py # PAT resolution chain
git/
ops.py # fetch, status, pull_safe (merge-tree conflict detection)
mcp/
server.py # FastMCP tools + resources
web/
app.py # FastAPI factory, routes, htmx fragments
templates/ # Jinja2 templates
static/ # CSS + vendored JS
Requirements
- Python 3.10+
- Git 2.38+ (for
git merge-tree --write-tree) - GitLab PAT with
read_apiscope
Testing
uv run pytest tests/ -v
License
Unlicense — public domain.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file project_hub-0.3.2.tar.gz.
File metadata
- Download URL: project_hub-0.3.2.tar.gz
- Upload date:
- Size: 315.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.1 {"installer":{"name":"uv","version":"0.11.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
128f2c535c533d2362635854d9b9bbec561f2971dd0df214313457e87803462c
|
|
| MD5 |
97e74c2a83205daed4085f7b05b12770
|
|
| BLAKE2b-256 |
c0805a24c0bb5f3aaa2faa5cf5833dc7bc1ddfaedc626f61d8a634b776ac1455
|
File details
Details for the file project_hub-0.3.2-py3-none-any.whl.
File metadata
- Download URL: project_hub-0.3.2-py3-none-any.whl
- Upload date:
- Size: 107.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.1 {"installer":{"name":"uv","version":"0.11.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
62f05350bdc4381c672f59e7c3f41fdcc2c2afc1f17844d62fbac1e6331c7024
|
|
| MD5 |
8b9279267794c665a610878214caafc7
|
|
| BLAKE2b-256 |
6b67be91a68a540c0c335668cea98dad8e610d995f1dee4d2245673b45c865f8
|