Every surface, in one place.
This console is the web front end of the SENTINEL strike team: live advisory triage, the eight-stage mission runner with a real approval gate, the Daytona verify stage, and the WebMCP OMNI-LAB. The CLI and the MCP tool server live in the repository.
What runs where
- Live dependency triage — real GitHub Advisory / OSV data, no key needed
- The eight-stage mission with the approval gate
- Real pull-request opening (needs a GitHub token in the vault, behind the gate)
- Real Daytona sandbox verification (needs a Daytona key in the vault)
- The OMNI-LAB — five laboratories, 17 WebMCP tools, real SHA-256 / HMAC
- Key vault — keys stay in localStorage, sent only to this app's proxy routes
npm run web— the full console against a live TrueForge harnessnpm run cli— the terminal clientnpm run mcp— the MCP tool server on :8791npm run app— the API app with SQLite scan historynpm test— 18 suites, 211 testsnpm run scan:secrets— fails the build on anything credential-shaped
Install the strike team
npm install --global \ https://github.com/geohot0199/sentinental/raw/refs/tags/v0.2.0/releases/sentinel-strike-team-v0.2.0.tgz sentinel --help
Requires Node.js ≥ 22.14.
npx @truefoundry/trueforge@latest # the harness git clone https://github.com/geohot0199/sentinental.git cd sentinental && npm install cp .env.example .env # add your keys npm run web # console on :3000
A scripted model endpoint ships with the repo, so you can see the whole path — real advisory data, real tools, real approval gate — without spending anything. In this console, the same experience is the default: with no keys at all, the scan and mission stations run on live public advisory data.
Configuration
In the console these live in the key vault (browser localStorage). In the repository they live in .env — git-ignored, read in exactly one place (src/core/config.ts).
| Variable | Required | Purpose |
|---|---|---|
| OPENAI_API_KEY / ANTHROPIC_API_KEY / GEMINI_API_KEY | one of | The model. SENTINEL picks whichever it finds and selects a model from the harness's own catalog. |
| MODEL_PROVIDER | optional | Force a provider: openai · anthropic · google-gemini. |
| MODEL_ID | optional | Force a specific model. Leave unset and SENTINEL picks a sensible mid-tier model. |
| GITHUB_TOKEN | yes | Reading manifests, opening pull requests. Scope it to the repos you want touched. |
| SENTINEL_TARGET_REPO | optional | Default repository, as owner/name. |
| DAYTONA_API_KEY | recommended | Sandbox. Without it every patch is reported unverified. |
| SENTINEL_ALLOW_REMOTE_WRITES | optional | Hard kill switch. false makes destructive tools refuse before any network call. |
| TRUEFORGE_URL | optional | Harness URL. Default http://127.0.0.1:8790. |
| SENTINEL_MCP_PORT | optional | Tool server port. Default 8791. |
| SENTINEL_WEB_PORT | optional | Web console port. Default 3000. |
| SENTINEL_MCP_TOKEN | optional | Shared secret the harness uses to call the tool server. Unset means a fresh random token every boot. |
| SENTINEL_DEMO_MODEL_URL | optional | Point at the bundled scripted model for a keyless demo run. |
| SENTINEL_MCP_ALLOWED_ORIGINS | optional | Extra comma-separated origins allowed to POST /api/mcp from a browser (Origin validation is on by default). |
| NEXT_PUBLIC_SITE_URL | optional | Absolute base URL, so metadata and llms.txt carry real links instead of relative ones. |
| NEXT_PUBLIC_WEBMCP_ORIGIN_TRIAL | optional | Chrome WebMCP origin-trial token for this exact host. Unset means no meta tag is emitted. |
| NO_COLOR | optional | Force plain text in the CLI. |
The 7 MCP tools
Read package.json + lockfile, resolving real installed versions rather than declared ranges.
GitHub Advisory Database with OSV fallback; only matching version ranges count.
Patch / minor / major classification, advisories cleared, import-site usage.
Collapse findings into one safe target version per package.
Regenerated package.json, range operators preserved. Writes only inside the sandbox.
Branch + commit + pull request. Generated branch name — the model never supplies a ref.
Squash-merge an open pull request. Gated like every irreversible action.
The agent bridge
Two doors, one contract. In a browser tab the tools are registered on document.modelContext (WebMCP, W3C Web Machine Learning CG — the getter moved from navigator to document in the May 2026 draft, so the alias is resolved too). Outside a browser the identical contract is served as a remote MCP server over stateless Streamable HTTP.
- Registered through
registerTool(tool, { signal }), the spec signature — promise-based, abortable, and rejecting on a duplicate name rather than silently overwriting. - Every tool carries
title,inputSchemaandannotations, so the agent can see which ones are read-only before it chooses. - Input is validated against the schema before
executeruns, andexecuteToolstringifies the result the way the spec says an agent will receive it. - Requires a secure context. Chrome: public origin trial (149–156). ChatGPT desktop built-in browser and ChatGPT Sites: supported since 2026-08-25. Firefox/Safari: no implementation yet.
- No native surface? A spec-shaped polyfill is installed for in-page agents and the console — and it is labelled in-page only, never as agent-visible.
POST /api/mcp- Protocol
2026-07-28: noinitializehandshake, noMcp-Session-Id; version and identity ride inparams._meta. - Routing headers
Mcp-MethodandMcp-Nameare required for modern clients and validated against the body — a mismatch is-32020 HeaderMismatch. server/discoveris implemented (it is mandatory now), and list results carryresultType,ttlMsandcacheScope.- Legacy clients still work: an
initializerequest is answered in the 2025-11-25 shape, and unknown versions come back as-32022with the supported list so the client can retry rather than guess. Originis validated against same-origin plusSENTINEL_MCP_ALLOWED_ORIGINS; GET/DELETE answer 405 the way the stateless transport expects.
Settings → Apps & Connectors → Advanced → Developer mode on → Create. URL: https://your-host/api/mcp. Transport: Streamable HTTP. Auth: No authentication, or OAuth once you set SENTINEL_MCP_TOKEN. Plus and Pro may be limited to read/fetch tools; Business and Enterprise get the full set.
Nothing to install. Open the site in the desktop app's browser and ask ChatGPT or Codex to use the site's tools — it reads the registered WebMCP surface, with the usual website-access and sensitive-action confirmations in front.
claude mcp add --transport http sentinel https://your-host/api/mcp — or the same url in Cursor's mcp.json. Read the tool list once and it is cached for five minutes (ttlMs).
POST one JSON-RPC object per request with the three headers above. scripts/mcp-conformance.mjs in this repository is a 90-line working example you can copy.
Prove it without an agent: run npm run check:mcp against a running deployment, or press Run the check in the Bridge station. Both exercise the same handleRpc() the endpoint runs in production.
POST /api/mcp
content-type: application/json
mcp-protocol-version: 2026-07-28
mcp-method: tools/call
mcp-name: lookup_advisories
{
"jsonrpc": "2.0",
"id": 7,
"method": "tools/call",
"params": {
"name": "lookup_advisories",
"arguments": { "packageName": "lodash", "installedVersion": "4.17.20" },
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": { "name": "my-agent", "version": "1.0" },
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
200 ok
{
"jsonrpc": "2.0",
"id": 7,
"result": {
"resultType": "complete",
"content": [{ "type": "text", "text": "{ "matchCount": 3, ... }" }],
"structuredContent": { "packageName": "lodash", "source": "github", "matchCount": 3, "matches": [...] },
"isError": false,
"_meta": { "io.modelcontextprotocol/serverInfo": { "name": "sentinel-web", "version": "1.0.0" } }
}
}Deploying this console
The console is a standard Next.js App Router project — Vercel detects it automatically.
# from the repository root vercel # or: import the repo in the Vercel dashboard # optional server-side environment variables (Project → Settings → Env Vars): # SENTINEL_ALLOW_REMOTE_WRITES=false # server kill switch, overrides the browser # GITHUB_TOKEN=… # server-side default token # DAYTONA_API_KEY=… # server-side sandbox key # TRUEFORGE_URL=… # a reachable TrueForge harness
API routes proxy every upstream call (advisories, GitHub, Daytona, the harness probe) — the browser never talks to a third party directly. Browser-vault keys are used per-request and never stored server-side.
Control and safety
- The approval policy is declared on the tool, once — both front ends inherit it.
- Destructive handlers check the kill switch before any network call.
- Branch names are generated and validated against git's ref rules — the model never supplies a ref.
- The web API only accepts approvals for tool calls actually raised by the pipeline.
- Denial is the default: empty input, EOF, Escape, and unparseable answers all deny.
- Two-layer redaction scrubs every log line, tool result and SSE frame.