envpact-mcp-server
August 13, 2026 · View on GitHub
Bring your private, Git-backed secrets vault to any AI coding agent — generate
.envfiles on demand, never paste an API key into a prompt again.
Model Context Protocol server for envpact — bring centralized secret management to AI coding agents (Cursor, Windsurf, Claude Code, Cline, Goose, ChatGPT Desktop, and any other MCP-aware client).
Stop pasting API keys into prompts. Let your agent generate
.envfiles from your private vault on demand.
Links: Repo · Live docs · envpact umbrella · Dashboard
Part of the envpact ecosystem.
⭐ If this is useful, please star the repo — it helps other developers find it.
Architecture
flowchart LR
subgraph agent["AI coding agent"]
A[Cursor / Windsurf / Claude Code / Cline]
end
subgraph mcp["envpact-mcp (this server)"]
T[MCP tools: generate_env, pull/push_secret,<br/>add_secret, rotate_secret, sync_github, ...]
end
vault[(~/.envpact/secrets/<br/>private GitHub vault)]
envf[.env file in project]
gha[GitHub Actions secrets]
A -- MCP stdio / HTTP --> T
T -- read/resolve --> vault
T -- write --> envf
T -- sync_github --> gha
worker["Cloudflare Worker<br/>(remote SSE / Streamable HTTP)"] -. same 11 tools .-> vault
A -. MCP over HTTP .-> worker
What it does
When you ask your AI agent "set up a Next.js project that uses
OpenAI and Stripe", modern agents can scaffold the code but get
stuck at the .env step. With envpact-mcp installed:
- The agent sees your project's
.env.examplerequirements. - It calls
generate_envand the file is written from your private vault. - New keys it discovers are added back to the vault via
add_secret/add_shared_secret. - Optionally syncs to GitHub Actions via
sync_githubso CI works end-to-end.
You never paste a secret into an agent prompt.
Installation
The MCP server is published to npm as envpact-mcp. Configure your
AI client:
Claude Desktop / Claude Code
~/.config/claude/claude_desktop_config.json:
{
"mcpServers": {
"envpact": {
"command": "npx",
"args": ["-y", "envpact-mcp"]
}
}
}
Cursor
.cursor/mcp.json in your project, or
~/.cursor/mcp.json globally:
{
"mcpServers": {
"envpact": {
"command": "npx",
"args": ["-y", "envpact-mcp"]
}
}
}
Windsurf
~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"envpact": {
"command": "npx",
"args": ["-y", "envpact-mcp"]
}
}
}
Cline (VS Code)
In Cline's MCP settings panel, add a stdio server with
command npx and args ["-y", "envpact-mcp"].
Prerequisites
You need an envpact vault. If you don't have one yet:
npx envpact-cli --init auto
# Creates chirag127/envpact-secrets (private) and clones it to
# ~/.envpact/secrets/ — same vault every component reads.
Available Tools
| Tool | Description |
|---|---|
generate_env | Resolve secrets, write .env for the current project. |
list_projects | List all projects in the vault. |
list_shared | List shared secret names (values are masked). |
add_secret | Add/update a project secret. |
add_shared_secret | Add/update a shared secret. |
rotate_secret | Rotate a shared secret; reports affected projects. |
sync_github | Push resolved secrets to GitHub Actions. |
pull_secret | Pull one key from vault → .env (per-key, conflict-safe). |
push_secret | Push one key from .env → vault (per-key, conflict-safe). |
sync_status | Report per-key sync status across .env.example. |
generate_global_env | Mirror every shared secret into ~/.envpact/.env (v3.1). |
Schema details: see SHARED_SPEC §7.
v3.1 UX additions
- Dual-render timestamps (UTC + IST). Every conflict refusal
from
pull_secret/push_secretand every entry insync_statusnow carries the canonical UTC ISO string AND a human IST rendering (YYYY-MM-DD HH:MM:SS IST). Conflict payloads also exposerecommended_side: "vault" | "local"set to whichever side is newer. The user keeps the final decision;recommended_sideis just a hint. - Global vault
.env.generate_global_envmirrors everyshared.*entry into a single file at~/.envpact/.env, generated from~/.envpact/.env.example.global(auto-created on first run, byte-faithful template format). Encrypted values emit# KEY: encryptedcomments; missing keys emit# KEY: not in vault. Output is mode 0600 (best-effort on Windows).
Per-key Sync (v3)
The vault is flat and single-environment per project with
{value, _modified_at} entries. The agent can sync one key at a
time without touching the rest of .env:
You: "Pull the latest OPENAI_API_KEY from the vault."
Agent: calls
pull_secret({key: 'OPENAI_API_KEY'})→ writes the new value to.env, updates.env.example.lock. If you'd edited.envsince the last sync, the call returns anisErrorpayload withstatus: 'local_newer'; the agent retries withforce: trueonly after asking you.
You: "What's the sync status of this project?"
Agent: calls
sync_status()→ reports each key assynced/local_newer/vault_newer/both_diverged/local_only/vault_only. NEVER returns values.
Example Agent Conversations
You: "Set up envpact for this project. The .env.example needs OPENAI_API_KEY and DATABASE_URL."
Agent: calls
generate_env→.envwritten, missingDATABASE_URL. Asks: "Should DATABASE_URL be a shared secret or project-specific?"You: "Shared, value is
postgres://prod-host/db."Agent: calls
add_shared_secret({key: 'DATABASE_URL', value: '...'}), thenadd_secret({project: 'this-app', key: 'DATABASE_URL', value: 'shared.DATABASE_URL'}), thengenerate_envagain. Done —.envcomplete.
You: "OPENAI_API_KEY was leaked. Rotate it everywhere."
Agent: calls
rotate_secret({key: 'OPENAI_API_KEY', new_value: 'sk-new...'})→ reports 12 affected projects. Callssync_githubfor each.
Remote / SSE Variant
A Cloudflare Worker variant supporting MCP over Streamable HTTP is
deployed at https://mcp.envpact.oriz.in/mcp and listed on
Smithery at https://smithery.ai/server/@chirag127/envpact-mcp.
The Worker exposes the same 11 tools, with two natural Worker
deviations: pull_secret returns the resolved value as the
response text body (no .env to write), and generate_global_env
returns the rendered global .env body as text instead of writing
to disk. See worker/README.md for the full deviation list.
Security Model
- Vault values never leave your machine in tool responses — only the tool params (e.g. when you ask the agent to set a value) carry plaintext.
list_sharedreturns only names; values are never echoed.- The MCP server reads/writes
~/.envpact/secrets/directly. The vault is your existing private GitHub repo. - All vault commits are signed-off (
-s) and authored byenvpact-mcp.
Tech stack
- Node.js (>=18), TypeScript/ESM, pnpm workspace.
- @modelcontextprotocol/sdk for the MCP server; zod for tool schemas.
- Cloudflare Worker (
worker/) for the remote SSE / Streamable-HTTP variant. - Packaged as
.mcpbbundle and published to npm asenvpact-mcp.
Repo structure
src/ # MCP server (stdio) — tool handlers
worker/ # Cloudflare Worker (remote SSE / Streamable HTTP variant)
mcpb/ # .mcpb bundle manifest + build
docs/ # full API + usage reference (served at *.oriz.in)
scripts/ # test + build-mcpb helpers
server.json # official MCP registry descriptor
smithery.yaml # Smithery listing config
Related projects — the envpact ecosystem
| Repo | Role |
|---|---|
| envpact | Core (Python) vault library |
| envpact-npm-cli | Zero-dependency Node CLI (envpact-cli) |
| envpact-mcp-server | MCP server for AI agents (this repo) |
| envpact-gh-action | GitHub Action — resolve secrets in CI |
| envpact-registry-publisher-npm-cli | Publish MCP servers to every registry |
Part of the oriz family
One of ~80 oriz projects — small, sharp, open-source tools. The live docs run $0 on the Cloudflare free tier.
Contributing
PRs welcome — see CONTRIBUTING.md. Conventional commits are the changelog.
Status
Stable. Published to npm; remote Worker variant listed on Smithery.
License
MIT © 2026 Chirag Singhal · chirag@oriz.in — see LICENSE.
Documentation
- Repo docs (
docs/README.md) — full API + usage reference for envpact-mcp - Project umbrella site — overview of all envpact components, security model, quick start
- Live dashboard — visual vault management