Skip to main content
Glama
Faneraiy14
by Faneraiy14

workspace-status-mcp

Українською

An MCP server with four tools:

  • sweep_status — a one-call snapshot of every git repository under a given folder: branch, uncommitted changes, unpushed commits, and (optionally) the latest GitHub Actions CI conclusion. Replaces manually looping git status + gh run list over dozens of repos one at a time.

  • check_docs — flags which repos' Architecture/<repo>.txt doc is missing or stale. Doesn't write or regenerate anything itself (understanding a codebase well enough to document it is an LLM/human job, not a script's) — it just says where to look, so docs get updated deliberately instead of silently rotting.

  • write_doc — writes Architecture/<repo>.txt and stamps it with the repo's current commit hash, so check_docs can later measure staleness precisely (commits since write) instead of guessing from file mtime.

  • check_release_drift — for explicit (source repo, release repo) pairs, counts how many commits landed in the source since the release repo's last git tag, and how old the oldest one is. Cutting a release is usually a manual "whenever I remember" step (tag a version, push it, CI builds and publishes) — this answers "has anyone actually done that lately" without checking by hand.

Why

Working across ~50 repositories in the same workspace, "what actually needs attention right now" was a real recurring question — checked by hand, repo by repo, over and over in the same session. sweep_status answers it in one call and, by default, only returns repos that actually need a look (dirty working tree, unpushed commits, or a CI run that isn't a plain success) — clean repos are silently skipped so the answer stays short.

check_docs exists for the same reason, one level up: a per-project architecture doc is only useful if it's trusted, and it's only trusted if someone actually checks it's current. Comparing "last commit" to "doc's mtime" turns that from a thing you have to remember into a thing you can just ask.

Related MCP server: github-ops-mcp

Claude Code hook: check-docs-reminder

The tools above only help if something actually calls them. hooks/check-docs-reminder.mjs closes that gap: registered as a SessionStart + Stop hook in ~/.claude/settings.json, it runs checkDocs() itself against whatever repo Claude's current working directory is under (walking up to the nearest git root that's a direct child of the projects folder), and — only when that repo's doc is missing or stale — injects a one-line reminder into Claude's context via hookSpecificOutput.additionalContext. Silent otherwise (clean repos, or a cwd outside the projects folder, produce no output; likewise if the projects folder never had an Architecture/ folder at all — someone who's never opted into this convention doesn't get nagged about every repo being "missing"). SessionStart covers forgetting between sessions; Stop (which fires each time Claude's turn ends) re-checks every turn within the same session too, and self-quiets the moment write_doc actually gets called. Deliberately non-blocking — a stale doc is worth a nudge, not a halted turn.

Not hardcoded to any one person's folder layout, and works the same on Windows as Linux/macOS. Register it with the args array ("exec form" — spawned directly, no shell involved, so there's no bash-vs-PowerShell-vs-cmd syntax difference to worry about):

{
  "hooks": {
    "SessionStart": [{ "hooks": [{ "type": "command", "command": "node",
      "args": ["/path/to/workspace-status-mcp/hooks/check-docs-reminder.mjs", "SessionStart"] }] }],
    "Stop": [{ "hooks": [{ "type": "command", "command": "node",
      "args": ["/path/to/workspace-status-mcp/hooks/check-docs-reminder.mjs", "Stop"] }] }]
  }
}

Watch points

Not every repo necessarily lives under one root — one might get moved out of ~/Projects onto the Desktop, say, with its doc sitting right next to it there instead of in the central Architecture/ folder. The hook resolves "watch points" (projectsRoot + optional docsRoot pairs) in this order, using the first point whose projectsRoot contains the repo you're currently in:

  1. CLI args (args[2]/args[3] after the event name) — a one-off single-point override.

  2. The watch-points config file~/.claude/workspace-status-points.json by default (override the path with WATCH_POINTS_FILE). This is the normal way to manage this day to day:

    {
      "points": [
        { "projectsRoot": "/home/sviat/Projects" },
        { "projectsRoot": "/home/sviat/Desktop", "docsRoot": "/home/sviat/Desktop" }
      ]
    }

    Add a point, remove one (or all of them), or redirect an existing one just by editing this file — no code change, no re-registering the hook. A missing file, or an empty/absent points array, falls through to the next source below.

  3. PROJECTS_ROOT/DOCS_ROOT environment variables — single-point fallback for anyone registering the hook through a shell command instead of the args exec form.

  4. Default: a single point at <home>/Projects.

check_docs/sweep_status accept the same idea directly as points/roots arguments (see below) if you want to query multiple locations from a conversation without touching the config file.

Install

npm install

Requires the GitHub CLI (gh), authenticated, if you want CI status (check_ci: true, the default). Without it CI results just come back as null per repo.

Cross-platform — all four tools and the hook are plain Node.js (path.join, os.homedir(), no hardcoded /) shelling out to git/gh, both of which run natively on Windows too. No platform-specific code path.

Updating

There's no separate build or publish step — claude mcp add points straight at this checkout's src/server.js, so updating is just:

git pull && npm install

Take effect on the next new Claude Code session (each session spawns its own MCP server process, so an already-running session keeps using the code it started with).

Tool: sweep_status

Argument

Type

Default

Meaning

root

string

— (required unless roots)

Folder to scan, one level deep (e.g. /home/user/Projects)

roots

string[]

Several roots in one call instead of one root — results are merged (e.g. repos split between ~/Projects and elsewhere)

repos

string[]

all subfolders

Limit to specific repo names instead of scanning everything (matched across all roots)

check_ci

boolean

true

Also query GitHub Actions for each repo's latest run

only_attention

boolean

true

Only return repos that need a look; false returns everything

Each repo entry: name, path, branch, uncommittedFiles (count), ahead/behind (vs upstream, null if no upstream configured), hasUpstream, and ci ({status, conclusion, workflow, url} or null).

Tool: check_docs

Argument

Type

Default

Meaning

projectsRoot

string

— (required unless points)

Folder with the repos

docsRoot

string

<projectsRoot>/Architecture

Folder with the <repo>.txt docs

points

{projectsRoot, docsRoot?}[]

Several independent projectsRoot+docsRoot pairs in one call instead of one projectsRoot/docsRoot (e.g. a repo moved out of ~/Projects, doc sitting right next to it wherever it went)

repos

string[]

all subfolders

Limit to specific repo names (applied within each point independently)

only_attention

boolean

true

Only return missing/stale; false returns everything including current

Each repo entry: name, projectsRoot (which point it came from), docPath, status (missing / stale / current / no-commits), trackingMethod (commit if the doc was written via write_doc, mtime otherwise — see below), lastCommitAt, and either commitsSinceWrite/writtenAtCommit/writtenAt (commit tracking) or docUpdatedAt/staleBySeconds (mtime tracking, only on stale).

Tool: write_doc

Argument

Type

Default

Meaning

projectsRoot

string

— (required)

Folder with the repos

repo

string

— (required)

Repo folder name (e.g. "anylint")

content

string

— (required)

Full text to write to <repo>.txt

docsRoot

string

<projectsRoot>/Architecture

Folder with the <repo>.txt docs

Writes <repo>.txt and, next to it, .meta/<repo>.json with the repo's HEAD commit hash at write time. check_docs then reports the exact number of commits since the doc was written (git rev-list --count) instead of the coarser mtime-vs-last-commit-time comparison — the same pattern check_release_drift already uses for source→release drift. Docs written directly (e.g. via a plain file write, not this tool) keep using mtime tracking — there's no meta file to compare against.

Tool: check_release_drift

Argument

Type

Default

Meaning

projectsRoot

string

— (required)

Folder with the repos

pairs

{source, release}[]

— (required)

Explicit list of source→release folder-name pairs

only_attention

boolean

true

Only return drifted; false returns everything including current/no-tags

Each pair entry: source, release, status (drifted / current / no-tags), and on drifted: latestTag, tagCreatedAt, commitsSinceTag, oldestUnreleasedCommitAt, oldestUnreleasedAgeDays.

Architecture

  • src/sweep.js — all the logic: finds .git folders one level under a root (exported as findGitRepos, reused by docs.js), then for each one runs git branch/git status/git rev-list and (optionally) gh run list in parallel, batched at 8 repos at a time to avoid hammering the GitHub API. sweepStatus()'s roots (plural) runs findGitRepos per root and merges the results before filtering by repos/only_attention — so a repo name filter matches regardless of which root it actually lives under.

  • src/docs.jscheckDocs(): prefers commit-based tracking (.meta/<repo>.json, written by write_doc) when available; falls back to comparing git log -1 --format=%ct against the doc file's mtime for docs written directly. A repo with no commits yet reports no-commits rather than being silently lumped into missing or current. points (plural) checks each independent projectsRoot+docsRoot pair in turn and tags every result with which one it came from.

  • src/write-doc.jswriteDoc(): writes <repo>.txt plus .meta/<repo>.json ({commitHash, writtenAt}, HEAD at write time). Doesn't generate the text itself — understanding a codebase well enough to document it stays an LLM/human job.

  • src/server.js — registers all four tools with the MCP SDK over the stdio transport.

  • test/smoke.mjssweep_status against real local repos (no synthetic fixtures needed — the workspace itself already has clean, dirty, and upstream-less repos to test against), plus a roots (plural) case against a real root and a throwaway empty one.

  • test/docs.mjscheck_docs against temporary, throwaway git repos with controlled commit/file timestamps (real ~/Projects drifts over time, which would make a fixed test flaky), including both tracking methods and a points (plural) case.

  • test/write-doc.mjswriteDoc() against a temporary git repo: correct HEAD captured, .meta/ created on demand, empty content rejected.

  • test/hook.mjshooks/check-docs-reminder.mjs as a real subprocess (it's a CLI entry point, not a library function): silent outside any watch point, silent with no Architecture/ folder at all, reminds and resolves the right repo from a nested subdirectory, the watch-points config file driving two independent points at once, and an empty/absent points array in that file falling through to the next source.

  • src/release-drift.jscheckReleaseDrift(): finds the release repo's most recent tag via git for-each-ref --sort=-creatordate (sorted by actual tag time, not the semver-string sort -v:refname would give — v1.10 would otherwise sort before v1.9), then counts git log --since=@<tagTimestamp> in the source repo. The source↔release relationship isn't guessable from folder structure (no general rule "folder X releases folder Y"), so the caller passes pairs explicitly.

  • test/release-drift.mjs — temporary repos with explicit GIT_AUTHOR_DATE/GIT_COMMITTER_DATE per commit (not relying on real wall-clock gaps between commits made milliseconds apart in a test run, which git log --since's second-level granularity could otherwise make flaky), plus one live check against the real NyxilumLang→NyxilumNode pair that only asserts it doesn't throw.

License

MIT — Faneraiy14.

A
license - permissive license
A
quality
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Local-only GitHub Actions and CI maintenance scanner for AI-built apps. Exposes scan, explanation, and fix-planning tools to MCP clients; modifies nothing and makes no outbound requests by default.
    3
    63
    2
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    CI health reports for GitHub Actions: flaky tests named from logs, wasted compute priced in dollars, zombie crons, PR feedback time, plus 21 lint rules with safe auto-fixes. Read-only MCP tools wrap the same Go binary.
    MIT

View all related MCP servers

Related MCP Connectors

  • Living docs and MCP context for GitHub repos — conventions, gaps, and source-cited pages on merge.

  • Turn a GitHub repo or docs site into agent-ready context: pack it or search it, over MCP.

  • Revternal MCP — wraps the Revternal Developer Intelligence API

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Faneraiy14/workspace-status-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server