safe-bifrost
v0.3.0
Published
A secure local MCP bridge: clients save plans, local agents execute tasks, and results are returned through workspace-scoped files.
Maintainers
Readme
Safe-Bifrost
Current release: v0.3.0. See v0.3.0 release notes.
Safe-Bifrost is a local Model Context Protocol (MCP) bridge for safe plan-and-execute coding workflows.
It lets ChatGPT, Codex, Claude, or another MCP client save a plan, create a workspace-scoped task, let a local agent execute it, and then read back the result, git diff, test log, and task status.
Why
Many local coding bridges give the upstream model broad shell access. Safe-Bifrost takes a narrower route:
ChatGPT Web or another MCP client
-> Safe-Bifrost MCP tools
-> save_plan / create_task
-> watcher finds pending tasks
-> local agent executes
-> result.md / result.json / diff.patch / verify.json / status.json
-> client reviews the resultThe MCP client can plan and review, but it does not receive a general shell tool.
Features
- MCP stdio server with workspace-scoped tools.
- Optional HTTP MCP server bound to
127.0.0.1. - ChatGPT Connector / OpenAI Secure MCP Tunnel workflow.
- Automatic watcher for pending tasks.
- Local runner that captures
result.md,git.diff,test.log, andstatus.json. - Task phases, heartbeat timestamps, progress reports, cancellation, forced termination, and bounded task timeouts.
- Server-side
wait_for_tasklong polling so ChatGPT can remain in one tool loop until the agent reaches a terminal state. - Structured
result.json,verify.json,diff.patch, andget_task_summaryacceptance evidence. - Workspace-wide before/after fingerprints that fail a task when changes are
detected outside its explicit
repo_path. - Before/after file fingerprints for stronger change evidence.
- File reads contained to one configured
workspaceRoot. - Sensitive file blocking for
.env, tokens, SSH keys, credentials, cookies, and similar paths. - Low-risk plan storage: ordinary build/test/release language is accepted; explicit credential theft, destructive disk deletion, and backdoor plans are blocked.
- Task artifacts are returned with secret-like values redacted instead of failing the entire read.
- Agent command allowlist through
safe-bifrost.config.json. - Test command exact-match allowlist.
- Windows-friendly helper scripts.
- Read-only
doctorcommand for local setup diagnostics.
MCP Tools
Safe-Bifrost exposes these tools:
list_workspaceread_workspace_filesave_planget_planhealth_checklist_agentscreate_taskget_task_statusget_resultget_result_jsonget_diffget_test_loglist_taskscancel_taskkill_taskretry_taskget_task_progresswait_for_taskget_task_summaryget_task_stdout_tailaudit_task
Install
Requirements:
- Node.js 18 or newer
- npm
- Git, if you want
git.diff - A configured local coding agent such as
opencodeorcodex
Windows PowerShell:
cd path\to\safe-bifrost
npm.cmd ci
npm.cmd run build
npm.cmd testLinux, macOS, or WSL:
cd safe-bifrost
npm ci
npm run build
npm testConfigure
Create safe-bifrost.config.json in the project root. Do not commit this
file.
{
"workspaceRoot": "D:/path/to/test-or-project-workspace",
"plansDir": ".safe-bifrost/plans",
"tasksDir": ".safe-bifrost/tasks",
"agents": {
"opencode": {
"command": "opencode",
"args": ["run", "{prompt}"]
}
},
"allowedTestCommands": [
"npm test",
"npm run lint",
"npm run format:check",
"npm run build",
"npm run dist",
"npm run doctor"
],
"maxReadFileBytes": 200000,
"defaultTaskTimeoutSeconds": 900,
"maxTaskTimeoutSeconds": 3600,
"httpPort": 7331
}Important rules:
- Use a small project directory for
workspaceRoot. - Do not set
workspaceRootto a drive root, home directory, Desktop, Downloads, or Documents. - Do not place secrets inside the workspace.
- Keep agent commands and test commands narrow.
Run Locally
Build first:
npm.cmd run buildRun the stdio MCP server:
$env:SAFE_BIFROST_CONFIG = "path\to\safe-bifrost.config.json"
node dist\index.jsRun the watcher in another terminal:
$env:SAFE_BIFROST_CONFIG = "path\to\safe-bifrost.config.json"
npm.cmd run watchRun the HTTP MCP server for local tunnel mode:
$env:SAFE_BIFROST_CONFIG = "path\to\safe-bifrost.config.json"
npm.cmd run start:httpThe HTTP server binds only to 127.0.0.1.
ChatGPT Connector
The intended ChatGPT flow is:
ChatGPT Web
-> ChatGPT Connector
-> OpenAI Secure MCP Tunnel
-> Safe-Bifrost MCP server
-> watcher
-> local agentFor stdio tunnel mode on Windows, use the launcher:
scripts/safe-bifrost-mcp-stdio.cmdThis wrapper sets SAFE_BIFROST_CONFIG, changes into the Safe-Bifrost project
root, and starts node dist/index.js. It prevents tunnel-client from using
the tunnel-client directory as the MCP workspace.
One-Click Windows Launcher
For local development, run:
Start-SafeBifrost-Tunnel.cmdThe launcher:
- asks for your tunnel runtime API key on first use, then stores it encrypted
with Windows DPAPI under
%APPDATA%\safe-bifrost - asks for a tunnel ID if
SAFE_BIFROST_TUNNEL_IDis not already set - starts the watcher in a separate PowerShell window
- runs
tunnel-client doctor - starts
tunnel-client run
Optional environment variables:
$env:SAFE_BIFROST_TUNNEL_ID = "tunnel_xxx"
$env:TUNNEL_CLIENT_EXE = "C:\path\to\tunnel-client.exe"
$env:OPENCODE_BIN_DIR = "C:\path\to\opencode-ai\bin"
$env:HTTPS_PROXY = "http://127.0.0.1:7892"
$env:SAFE_BIFROST_CREDENTIAL_PATH = "C:\private\safe-bifrost-key.dpapi"The saved key is bound to the current Windows user and computer. It is never
written to the repository or printed to logs. To remove it, run
Reset-SafeBifrost-Tunnel-Key.cmd.
Never commit API keys, runtime keys, tunnel IDs, local account names, or private workspace IDs.
Demo
See docs/demo.md for a privacy-safe ChatGPT connector demo and expected outputs.
Troubleshooting
ChatGPT lists the tunnel-client directory
If list_workspace returns only tunnel-client.exe, the MCP child process did
not receive SAFE_BIFROST_CONFIG or started from the wrong working directory.
Fix: use scripts/safe-bifrost-mcp-stdio.cmd as the tunnel MCP command, then
restart tunnel-client.
ChatGPT tool call times out
Check the tunnel-client UI at:
http://127.0.0.1:8080/uiIf logs show:
unsupported_country_region_territory
403 Forbiddenthen the current proxy exit region is not supported by the OpenAI API control plane. Change to a supported region and restart tunnel-client.
ChatGPT stops after create_task
An MCP server cannot send a new message into ChatGPT after the assistant turn
has ended. Do not rely on a prompt that says only "wait and check later".
Immediately call wait_for_task after create_task. If its response contains
continuation_required: true, call it again in the same assistant turn. When
terminal: true, use the included summary and then call audit_task for the
independent review. Each wait is capped at 30 seconds to stay below common
connector and tunnel request timeouts.
If logs show direct connection timeouts to api.openai.com, set a proxy:
$env:HTTPS_PROXY = "http://127.0.0.1:7892"ChatGPT Connector creation fails
Verify:
- tunnel-client is running
- the tunnel is associated with the correct ChatGPT workspace
- the connector uses
Channel, notServer URL - authentication is set to
Noneunless you have implemented OAuth - browser translation extensions are disabled on Platform pages
Recommended Workflow
Start with health_check and list_agents. create_task requires an explicit
repo_path; it never silently falls back to the workspace root. Prefer
verify_commands from the exact schema allowlist. Immediately enter the
wait_for_task loop and keep calling it while continuation_required is true.
Use cancel_task for graceful cancellation or kill_task for immediate
termination. Final acceptance starts with get_task_summary, followed by
audit_task and any detailed artifacts needed for review.
Do not use the entire workspaceRoot as the task repository unless that is
truly the intended repository. Prefer a relative subdirectory such as
desktop-pet-wangzai; absolute paths are also accepted when they resolve
inside workspaceRoot.
Recommended create_task arguments (add the plan_id returned by
save_plan):
{
"agent": "opencode",
"repo_path": "desktop-pet-wangzai",
"verify_commands": [
"npm run lint",
"npm run format:check",
"npm test",
"npm run dist"
]
}list_workspace— explore the projectsave_plan— ChatGPT writes the implementation plancreate_taskwithrepo_pathandverify_commandswait_for_task— repeat in the same turn untilterminal: trueget_task_summary— inspect scope, verification, files, and artifactsget_result_json/get_diff/get_test_log— inspect detailed evidenceaudit_task— independent verification (checks claims vs reality)
Important:
task donemeans the agent finished executing — it does NOT mean the work is correct or complete.failed_scope_violationtakes precedence over acceptance. Reviewrollback_scope_violation_plan.md; Safe-Bifrost never auto-rolls back concurrent/user edits.failed_verificationmeans at least one independent allow-listed command failed; inspectverify.logbefore retrying.audit_taskprovides an independent review, but still requires human judgment.- Local
result.mdclaims aboutnpm publish,git push, orGitHub releaseare unverified.- Publishing, tagging, pushing, and npm publish must be confirmed manually.
- Before running
doctor, createsafe-bifrost.config.jsonfrom the example template.
Task artifacts
result.md: human-readable execution report and agent output.result.json: structured status, paths, changed files, scope evidence, verification state, warnings, errors, and next steps for tools.verify.json: one structured record per independently executed allow-listed verification command, including cwd, exit code, output tails, and timing.verify.log: readable form of the same independent verification evidence.diff.patch: full textual patch captured after the task;get_difftruncates only its response when necessary and returnsdiff_patch_pathplus file stats.rollback_scope_violation_plan.md: review-only list of repo-external changes; it never includes normal in-repo changes and never performs rollback itself.
Security Model
Safe-Bifrost intentionally avoids general shell execution through MCP tools.
- MCP clients cannot pass arbitrary shell commands.
- Agent commands must be configured ahead of time.
- Test commands must match
allowedTestCommandsexactly. - File reads are contained to
workspaceRoot. - Sensitive file names are blocked even inside the workspace.
- The runner does not commit, push, delete files, or reset repositories.
- HTTP mode binds to
127.0.0.1only.
This is still a local automation bridge. Treat connector access as powerful and use a dedicated test workspace first.
Development
Windows PowerShell:
npm.cmd run build
npm.cmd test
npm.cmd run test:mcp
npm.cmd run test:http-mcp
npm.cmd run doctor
npm.cmd run pack:cleanPackage checks:
npm.cmd run verify:package
npm.cmd run pack:cleanThe clean archive excludes:
node_modules/.safe-bifrost/*.log.envsafe-bifrost.config.json- local release artifacts
Roadmap
- [x] stdio MCP server
- [x] plan and task CRUD
- [x] runner and watcher
- [x] HTTP MCP server
- [x] ChatGPT Connector tunnel docs
- [x] doctor command
- [ ] worktree isolation
- [ ] multi-agent task queue
- [ ] dashboard
License
MIT
