VcsToolkit
A toolkit for automating Git, Jujutsu, and the major forges (GitHub, GitLab, Gitea) through CLI process execution.
VcsToolkit is an F# port of the Rust vcs-toolkit-rs
workspace. It drives the real git, jj, gh (and glab / tea) command-line
tools as subprocesses rather than binding to libraries, so it stays faithful to
whatever the installed CLIs actually do. Process execution is handled by
ProcessKit.
*Browse the documentation site* for the full API reference (generated from the XML doc comments of every package below) plus the architecture and examples guides.
Pre-release status: the APIs and
vcs-mcptool are implemented in this repository, but the firstVcsToolkit.*/vcs-mcppackages have not been published to NuGet.org yet. Clone and build the repository to evaluate them today; the NuGet.org install command below becomes available after the first release.
Requirements
- .NET 10.0 or later
- The CLI tools you intend to drive (
git,jj,gh, …) onPATH
Packages
The toolkit is split into one package per concern, mirroring the Rust workspace.
Package |
Source status |
Purpose |
|---|---|---|
|
Implemented |
Shared plumbing: argv injection guard, error classifiers, lock-contention retry, credential provisioning, the |
|
Implemented |
The git-format unified-diff model and parser, plus a tolerant |
|
Implemented |
The |
|
Implemented |
The Jujutsu ( |
|
Implemented |
The GitHub ( |
|
Implemented |
The GitLab ( |
|
Implemented |
The Gitea/Forgejo ( |
|
Implemented |
The backend-agnostic |
|
Implemented |
The unified forge facade over GitHub / GitLab / Gitea: one |
|
Implemented |
Throwaway git/jj sandboxes (and a seeded bare remote) for integration tests: a self-cleaning |
|
Implemented |
Filesystem-watch a git/jj repository and emit typed state-change events. A |
|
Implemented |
A Model Context Protocol server exposing the toolkit's typed git/jj + forge operations as agent-callable tools. The |
The vcs-mcp MCP server
The vcs-mcp binary (VcsToolkit.Mcp.Server) is packaged as a .NET global tool. After the
first NuGet release, the Model Context Protocol server will install with a single command:
|
Today, build the repository and create a local tool package instead:
|
Use dotnet tool update --global vcs-mcp or dotnet tool uninstall --global vcs-mcp for an
installed copy.
It speaks MCP over stdio — an agent harness launches it via an mcpServers config entry. Read
tools (repo_* / forge_* queries) are always available; the mutating tools stay disabled until
you opt in, either with --allow-write (enable all of them) or --allow-tools name,... (a named
subset):
|
Run vcs-mcp --help for the full flag list. The forge is auto-detected from the repository's
origin remote unless --forge overrides it, and the git client is hardened (repo hooks and
config disabled) so serving a repository you did not create cannot execute its hooks. The git /
jj and gh / glab / tea CLIs you intend to drive must be on PATH (see Requirements).
See docs/mcp-server.md for the full user guide: every CLI flag, the
complete repo_*/forge_* tool reference (arguments, read/write, destructive/idempotent
semantics), the WriteGate write policy and per-repo write lock, forge auto-detection, and an
example mcpServers configuration block.
Quick start
Install VcsToolkit.Core, then open a Git or Jujutsu repository. Repo.Open detects the
backend; CommitPaths accepts repository-root-relative paths and never commits an empty list.
open VcsToolkit.Core
let commitReadme repoDir =
task {
match Repo.Open repoDir with
| Error error -> return Error error
| Ok repo ->
match! repo.Snapshot() with
| Error error -> return Error error
| Ok snapshot ->
printfn "Current head: %A" snapshot.Head
return! repo.CommitPaths([ "README.md" ], "Document the quick start")
}
See the examples cookbook for repository, forge, watcher, conflict, and credential-provider examples.
Architecture
For the end-to-end trust model, typed-surface guarantees, raw-command escape hatches,
credential handling, Git/submodule hardening, and a deployment checklist for libraries and
vcs-mcp, see docs/security.md.
For the package dependency graph, what each layer is responsible for, the design principles that repeat across the wrapper clients (CLI subprocess driving, total/tolerant parsing, argv guards, credential provisioning, error classification, cancellation-safe cleanup), and the escape hatches available at each layer, see docs/architecture.md.
Already know the CLI command you need (git rebase --onto, jj parallelize, gh api) and
want to know whether it's covered by a typed method or needs the escape hatch? See
docs/command-index.md — a reverse index, one row per typed method and
the exact subcommand/flags it runs, plus each wrapper's "not modeled" list.
Building from source
VcsToolkit restores every dependency — ProcessKit (the runtime process-execution
layer) and, for the test projects, its split-out ProcessKit.Testing doubles — from
nuget.org. No extra feeds or setup are needed.
|
The source, API-index, and documentation consistency gates used by CI can also be run locally:
|
scripts/run-analyzers.ps1 runs the Ionide.Analyzers
rule set (via the pinned fsharp-analyzers tool) over every src/ project and fails on any
Warning/Error finding — the only F#-class static analysis available, since CodeQL has no F# support.
Publishing status
No public VcsToolkit.* or vcs-mcp release exists yet. The repository is currently at the
0.1.0 seed version; the release workflow will publish all library packages and the global tool
together on the first release. Until then, use a source build or the local packages produced by
dotnet pack.
Inter-package dependencies are now declared. Because cross-project references use
Reference + AssemblySearchPaths (per the repo conventions) rather than
ProjectReference, dotnet pack cannot see the sibling dependencies. So a post-pack
target (Directory.Build.targets) rewrites each packed
.nuspec to add its VcsToolkit.* siblings as NuGet dependencies at the build's version
— derived from the @(Reference) set, so it stays in sync automatically. A consumer of
VcsToolkit.Git now transitively restores VcsToolkit.CliSupport / VcsToolkit.Diff;
the facades declare their backends (Core → Git/Jj (+ CliSupport/Diff), Forge
→ GitHub/GitLab/Gitea, Watch → Core, Mcp → Core/Forge).
VcsToolkit.TestKit is self-contained (no sibling references).
ProcessKit and ProcessKit.Testing are both on nuget.org (pinned at 2.10.0), so a consumer of
any VcsToolkit.* package restores its ProcessKit (>= 2.10.0) runtime dependency cleanly — the
packages are ready to publish. The split-out ScriptedRunner / Reply test doubles now restore
from the published ProcessKit.Testing package too — a test-only dependency that never
reaches the published VcsToolkit.* packages, so it does not affect consumers. Nothing is
vendored and there is no local NuGet feed.
ProcessKit 2.10.0 compatibility
The upstream 2.10.0
changelog was reviewed. Its retry-backoff, extra-file-descriptor, per-run signal, configurable
soft-stop signal, CPU-time limit, and HTTP-client readiness APIs are additive and are not used by
VcsToolkit. ManagedClient still constructs ordinary Command values and invokes the JobRunner
through IProcessRunner's capture verbs; its explicit stdin payloads remain byte-based, and it
does not use idle timeouts, PTY sessions, readiness probes, streamed output, supervisors, or
process-group profiles.
The 2.10.0 fixes therefore require no source changes here. Consumers receive the corrected retry and readiness validation plus ProcessKit's platform runtime improvements transitively, while VcsToolkit's UTF-8 output and byte-exact stdin contracts remain unchanged.
Changelog
See CHANGELOG.md for the version history.
Contributing
See CONTRIBUTING.md for build/test instructions and conventions. To report a security issue, follow SECURITY.md — please do not open a public issue.
License
This project is licensed under the MIT License.
VcsToolkit