Wrap command-line tools in an MCP wrapper to separate secrets from the coding environment. Support introspection of tools and allow requests for additional cababilities.
  • Go 98%
  • Shell 1.1%
  • HTML 0.4%
  • CSS 0.2%
  • JavaScript 0.2%
  • Other 0.1%
Find a file
Peter Tillemans 6af5d9976f
Some checks failed
Publish documentation / publish (push) Successful in 42s
Lint / lint (push) Failing after 8m14s
Merge branch 'docs/defer-drift' into 'main'
docs/doctor: mark drift deferred rather than settled in 7.6

See merge request pti/wraptool!79
2026-08-14 09:41:37 +00:00
.claude/agents docs(agents): fold Phase 1 retro into the workflow — fix rounds, seams, MR sizing 2026-07-30 20:06:21 +00:00
.devcontainer docs(devcontainer): migrate repo, examples, and docs to the wiring-only feature 2026-08-06 11:57:25 +00:00
.forgejo/workflows fix(release): formula style, http instance URLs, Linux dependency note 2026-08-10 15:05:21 +00:00
cmd test(cmd): claim serve.state ownership in the reload test 2026-08-11 20:49:50 +00:00
design docs(doctor): mark drift deferred rather than settled in 7.6 2026-08-14 09:41:00 +00:00
docs Merge branch 'main' into 'fix/scaffold-git-command-scope-config' 2026-08-14 09:24:25 +00:00
examples/devcontainer fix(devcontainer): review round 1 — Windows guidance, source guard, gemini UX 2026-08-06 15:44:42 +00:00
features feat(features): tombstone wraptool-connect so its docs link stops 404ing 2026-08-07 15:02:17 +00:00
internal test(introspect): let time pass in Go, not in a subprocess shell 2026-08-13 14:51:33 +00:00
testdata fix(introspect): recognize description-less catalog entries in git-style help 2026-08-13 09:03:56 +00:00
.envrc build(guix): pin toolchain channels 2026-07-23 23:27:23 +00:00
.gitignore fix(doctor): close the round-3 seam holes in A1 2026-08-11 15:18:56 +00:00
.gitlab-ci.yml ci(gitlab): make release upload loop idempotent 2026-07-24 13:49:10 +00:00
.golangci.yml docs(design): reorganize design/ into subsystem subdirs with index 2026-07-30 16:18:42 +02:00
CHANGELOG.md docs(changelog): 0.7.0 notes, reconstruct 0.6.0, date 0.5.0 2026-08-13 14:19:49 +00:00
channels.scm fix(guix): evaluate channels expression directly 2026-07-23 23:32:08 +00:00
CLAUDE.md docs: adopt agent-facing, retiring AI-facing 2026-08-11 14:24:26 +00:00
go.mod build(deps): add semver and flock for the harness pool 2026-07-30 12:04:29 +00:00
go.sum build(deps): add semver and flock for the harness pool 2026-07-30 12:04:29 +00:00
LICENSE Add GPLv3 license 2026-05-16 01:24:55 +02:00
main.go feat(doctor): foundation engine, CLI, and one check (step A1) 2026-08-11 13:40:39 +00:00
manifest.scm fix(release): preserve annotated tags in CI 2026-07-24 10:42:26 +00:00
README.md docs: adopt agent-facing, retiring AI-facing 2026-08-11 14:24:26 +00:00
release-signing-key.asc feat(release): verify signed release tags 2026-07-24 10:21:23 +00:00
release-version fix(release): pin verified tag signer 2026-07-24 10:27:34 +00:00
test-container.sh Add Guix container integration test script 2026-05-16 01:22:32 +02:00
test-release-version.sh fix(release): pin verified tag signer 2026-07-24 10:27:34 +00:00

wraptool

An MCP server that places CLI tools and local stdio MCP servers behind a security policy, so coding agents can use credentialed host capabilities without direct access to the underlying credentials.

Why

Coding agents need CLI tools to be productive, but giving them direct access exposes API keys, SSH keys, kubeconfigs, and service account credentials to the model context. The same risk runs through everyday development: a postinstall hook or a compromised transitive dependency executes with your full credentials the moment you build, test, or bump a package. wraptool treats everything running in your workspace — the agent, its tool calls, and the build/test/dependency code they trigger — as untrusted, and bounds what it can reach:

  • Credentials stay isolated -- wraptool runs as a separate process with its own environment; secrets never enter the agent context.
  • Bounded blast radius -- inside wraptool up's throwaway container the agent, your build scripts, and the dependencies they pull in all run with no host credentials. A hijacked agent or a poisoned dependency can't steal your credentials or exceed the policy: raw host secrets (SSH keys, gcloud, kubeconfig, push access) never leave the host, and privileged git/kubectl happen only through wraptool's policy-allowed, constrained subcommands. A malicious payload still runs with the container's network and source tree, and can invoke the same approved tools the agent can — but policy, not the payload, bounds which operations reach the host.
  • Subcommand-level policy -- allow git commit but deny git push --force, with flag-level granularity and value constraints.
  • MCP-server filtering -- spawn credentialed local stdio MCP servers and expose only explicitly allowed upstream tool names under a stable prefix.
  • Auto-discovery -- wraptool parses --help output to generate MCP tool schemas with real descriptions.
  • Structured denial workflow -- denied commands trigger a capability-request flow that an operator approves from the CLI, so escalation always requires a human.

Quick start

Install a precompiled Linux, macOS, or Windows binary by following the installation guide, or build it from source (on Guix: guix time-machine -C channels.scm -- shell -m manifest.scm -- go build -o wraptool .):

go build -o wraptool .

Create ~/.config/wraptool/config.yaml listing the tools to expose (allow/deny rules, auth token) — see Getting started for a full example. Then pick how your agent reaches wraptool:

wraptool up          # or just `wraptool`, from any git repo

Brings up a credential-isolated container — a native Guix container built from your manifest.scm when Guix is available, otherwise a Dev Container — with your coding agent inside it (installed once: a shared pool for Guix, the wraptool feature for Dev Containers) wired to the wraptool server on the host. Secrets never enter the container: git push, gcloud, and kubectl run on the host through MCP. The host gateway is auto-detected — no URL to set.

2. Scaffold a committed Dev Container

wraptool init devcontainer --harness claude --lang go,node

Writes .devcontainer/devcontainer.json — base image + language features + the wraptool feature (installs the harness, writes its MCP wiring, and shares your harness login/skills across projects). Commit it; teammates get the same isolated box on "Reopen in Container" or wraptool up.

3. Minimal — agent on the host, no container

wraptool init --harness claude   # writes .mcp.json pointing at localhost
wraptool server start

The agent runs on the same host as wraptool, so 127.0.0.1:8717 is reachable. From inside a container it is not — loopback is the container's own, not the host's; use option 1 or 2, which detect the host gateway for you.

Review UI

An optional operator-facing dashboard (bound to 127.0.0.1, not agent-facing) reviews capability requests and provides full rule CRUD — edit a tool's allow/deny rules in the browser and the running server hot-reloads the change. See docs/web-ui.qmd.

wraptool review UI — the Rules view, with per-tool allow/deny rules and inline edit controls

Documentation

Full documentation lives in docs/, is rendered with Quarto, and is published at https://pti.pages.snamellit.com/wraptool/ from the Forgejo pages branch:

Page Source
Getting started docs/getting-started.qmd
Installation docs/installation.qmd
Configuration reference docs/configuration.qmd
CLI reference docs/cli-reference.qmd
MCP integration docs/mcp-integration.qmd
Architecture docs/architecture.qmd
Security model docs/security.qmd
Hot-reload & capability requests docs/hot-reload.qmd
Review UI docs/web-ui.qmd
Isolated environments docs/isolated-environments.md
Troubleshooting docs/troubleshooting.qmd
Contributing docs/contributing.qmd

Build the site locally

guix time-machine -C channels.scm -- shell -m manifest.scm -- quarto preview docs
guix time-machine -C channels.scm -- shell -m manifest.scm -- quarto render docs

The render writes docs/_site/, which is ignored and must not be committed to main. The deployment workflow publishes only that generated tree to the orphan pages branch.

License

GPLv3 -- see LICENSE.