Documentation

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

in this browser console
  • 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
from the repository
  • npm run web — the full console against a live TrueForge harness
  • npm run cli — the terminal client
  • npm run mcp — the MCP tool server on :8791
  • npm run app — the API app with SQLite scan history
  • npm test — 18 suites, 211 tests
  • npm run scan:secrets — fails the build on anything credential-shaped

Install the strike team

A · packaged CLI
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.

B · from source
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
C · no API key demo

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).

VariableRequiredPurpose
OPENAI_API_KEY / ANTHROPIC_API_KEY / GEMINI_API_KEYone ofThe model. SENTINEL picks whichever it finds and selects a model from the harness's own catalog.
MODEL_PROVIDERoptionalForce a provider: openai · anthropic · google-gemini.
MODEL_IDoptionalForce a specific model. Leave unset and SENTINEL picks a sensible mid-tier model.
GITHUB_TOKENyesReading manifests, opening pull requests. Scope it to the repos you want touched.
SENTINEL_TARGET_REPOoptionalDefault repository, as owner/name.
DAYTONA_API_KEYrecommendedSandbox. Without it every patch is reported unverified.
SENTINEL_ALLOW_REMOTE_WRITESoptionalHard kill switch. false makes destructive tools refuse before any network call.
TRUEFORGE_URLoptionalHarness URL. Default http://127.0.0.1:8790.
SENTINEL_MCP_PORToptionalTool server port. Default 8791.
SENTINEL_WEB_PORToptionalWeb console port. Default 3000.
SENTINEL_MCP_TOKENoptionalShared secret the harness uses to call the tool server. Unset means a fresh random token every boot.
SENTINEL_DEMO_MODEL_URLoptionalPoint at the bundled scripted model for a keyless demo run.
SENTINEL_MCP_ALLOWED_ORIGINSoptionalExtra comma-separated origins allowed to POST /api/mcp from a browser (Origin validation is on by default).
NEXT_PUBLIC_SITE_URLoptionalAbsolute base URL, so metadata and llms.txt carry real links instead of relative ones.
NEXT_PUBLIC_WEBMCP_ORIGIN_TRIALoptionalChrome WebMCP origin-trial token for this exact host. Unset means no meta tag is emitted.
NO_COLORoptionalForce plain text in the CLI.

The 7 MCP tools

scan_dependenciesreadOnlyHint

Read package.json + lockfile, resolving real installed versions rather than declared ranges.

lookup_advisoriesreadOnlyHint

GitHub Advisory Database with OSV fallback; only matching version ranges count.

assess_blast_radiusreadOnlyHint

Patch / minor / major classification, advisories cleared, import-site usage.

summarise_triagereadOnlyHint

Collapse findings into one safe target version per package.

propose_patchreadOnlyHint

Regenerated package.json, range operators preserved. Writes only inside the sandbox.

open_pull_requestapproval required

Branch + commit + pull request. Generated branch name — the model never supplies a ref.

merge_pull_requestapproval required

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.

WebMCP · in the tab
  • 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, inputSchema and annotations, so the agent can see which ones are read-only before it chooses.
  • Input is validated against the schema before execute runs, and executeTool stringifies 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.
MCP · POST /api/mcp
  • Protocol 2026-07-28: no initialize handshake, no Mcp-Session-Id; version and identity ride in params._meta.
  • Routing headers Mcp-Method and Mcp-Name are required for modern clients and validated against the body — a mismatch is -32020 HeaderMismatch.
  • server/discover is implemented (it is mandatory now), and list results carry resultType, ttlMs and cacheScope.
  • Legacy clients still work: an initialize request is answered in the 2025-11-25 shape, and unknown versions come back as -32022 with the supported list so the client can retry rather than guess.
  • Origin is validated against same-origin plus SENTINEL_MCP_ALLOWED_ORIGINS; GET/DELETE answer 405 the way the stateless transport expects.
Connect it
ChatGPT (web, developer mode)

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.

ChatGPT desktop (built-in browser)

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, Claude Code, Cursor, Zed

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).

Your own client

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.

one request, end to end
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