Skip to main content
Glama
summeredge

Local Review MCP

by summeredge

Local Review MCP

Current version

V0.1 Release Candidate / Phase 5.6.1

Related MCP server: local-code-mcp

Current capabilities

  • MCP Streamable HTTP runtime

  • nineteen read-only tools, including the workspace registry, review context, and interactive Session status tools

  • submit_goal Control Plane entry point with asynchronous exact-current-conversation binding

  • batch CLI and interactive Codex app-server Execution backends

  • normalized interactive Session events with read-only Session/Execution status queries

  • schema-validated MCP structured outputs and schema-v1 ReviewVerdict parsing

  • durable Extension delivery and review-completion channels with identity-bound receipts

  • MV3 Browser Extension/Fiber identity evidence and loopback Local Control Bridge

  • fixed loopback host

  • configurable fixed port

  • startup port conflict detection

  • Bearer-token authentication for all MCP HTTP requests

  • OAuth 2.1-compatible discovery, public-client registration, PKCE, and Bearer tokens

  • safe GET /health endpoint

  • Cloudflare Tunnel provider with managed lifecycle

  • a registry of authorized workspaces with legacy single-workspace compatibility

  • bounded workspace metadata, directory listing, and text-file reading

  • bounded literal or regular-expression search with ripgrep and Node fallback

  • read-only structured Git status and bounded diff review

  • optional Windows Supervisor with health monitoring and bounded recovery

  • optional Windows Tray status/actions and per-user startup registration

  • Remote MCP protocol, authentication, workspace-review, and restart E2E tests

Architecture

The Local MCP Server keeps the MCP Data Plane and the Control Plane separate:

MCP Read-only Data Plane
  Workspace / Git / Review Context / status / hash-only diagnostics

MCP Control Plane entry
  submit_goal
        |
        v
Pending Goal identity gate -> Goal -> Phase -> Task
        |
        v
Controlled Actuation -> Execution

The MCP server exposes nineteen read-only tools and the reviewed submit_goal entry point. Browser Extension/Fiber, Local Control Bridge, Dispatcher, Codex execution, and Review Loop work remain Control Plane capabilities; MCP does not provide general file-write, shell, commit, push, or agent-control operations.

Execution and review use these current paths:

batch:        Task -> Execution                 (Codex CLI)
interactive: Task -> Session -> provider Thread -> Turn -> Execution -> normalized Events

passed Execution -> Review Request -> Conversation Routing -> Review Delivery
                 -> Extension Delivery -> Extension Review Completion -> ReviewResult
                 -> ReviewVerdict -> AutoIteration -> complete | next Execution | human required

Request correlation (correlation_key -> conversation_id) is identity evidence only; ConversationRouting.conversation_id remains the authoritative Review Delivery target.

Session is the long-lived interactive context and stores the provider Thread ID. Turn is the provider-level unit for one interactive Execution. Batch execution continues through codex exec --json - and does not automatically create a Session. The Playwright Browser Worker remains an independent automation path for explicit diagnostics and compatibility; current integrated delivery and completion use the Extension/Bridge path, and the Worker is not an MCP Data Plane capability.

Completed ReviewResults are parsed as schema-v1 ReviewVerdict values; the integrated AutoIteration path handles APPROVE, ITERATE, and HUMAN_REQUIRED outcomes.

Interactive Execution and status

submit_goal supports execution_mode: "batch" | "interactive", defaulting to batch, plus optional provider model and reasoning_effort. Interactive Execution uses the Codex app-server backend, discovers the provider catalog with model/list, creates a Session and Thread, starts a Turn, and persists only normalized LRM events. It does not silently select the first model.

The Session status model is created, starting, active, running_turn, waiting_input, completed, failed, or terminated. The currently wired interactive path uses created -> starting -> active -> running_turn -> completed|failed; approval, user input, pause, and resume scheduling are not implemented. The compatible Execution status remains running, passed, or failed.

The read-only status tools are:

  • get_session_status by session_id or goal_id, including Session, Thread, model/effort, Goal, and current Execution status;

  • get_execution_status by execution_id, including proven Session/Thread/Turn association and bounded agent output;

  • list_session_events with ordered, paginated normalized events. Provider JSON-RPC payloads are not exposed.

Default endpoint

http://127.0.0.1:12080/mcp

Start the server with:

npm install
npm start -- --workspace <path> --token <token>

The port can be overridden with --port <number>. The token can also be provided through LOCAL_REVIEW_MCP_TOKEN. Token precedence is CLI, environment, then config file. A JSON config file can be provided with --config <path>:

{
  "port": 12080,
  "workspace": {
    "id": "project",
    "name": "Project",
    "path": "C:\\path\\to\\project"
  },
  "workspaces": [
    {
      "id": "project",
      "name": "Project",
      "path": "C:\\path\\to\\project"
    }
  ],
  "auth": { "token": "<token>" },
  "remote": { "enabled": false, "endpoint": "" },
  "supervisor": {
    "enabled": false,
    "healthIntervalSeconds": 30,
    "maxRestartAttempts": 3
  }
}

workspaces is optional for legacy configurations. When present, its entries are the only workspaces that MCP can select; the top-level workspace identity selects the active entry and is checked against the registry. A legacy string workspace remains supported for direct single-workspace startup.

Set supervisor.enabled to true to run the MCP runtime under the Windows Supervisor. It checks /health at the configured interval, performs at most maxRestartAttempts automatic restarts, and exposes Start, Stop, Restart, Open Log Folder, startup registration, and Exit from the Tray menu. Supervisor logs are stored under the user's local application data directory and contain only fixed lifecycle events.

Production Deployment

The supported deployment path is Windows → Local Review MCP → Cloudflare Tunnel → ChatGPT Web custom MCP connector.

Windows requirements

  • Windows PowerShell 5.1 or PowerShell 7.

  • Node.js with npm available as node --version and npm --version.

  • cloudflared on PATH when remote.enabled is true. Install it from the Cloudflare tunnel documentation.

  • A workspace directory that already exists and is readable. The deployment scripts never create it.

From the repository root, install dependencies and build the release runtime:

npm install
npm run build

Prepare the local production configuration. The example contains no real token, endpoint, or workspace:

Copy-Item .\config.production.example.json .\config.production.json

Edit config.production.json and set workspace to the project directory the connector may review. Set remote.tunnelName to the existing Cloudflare Named Tunnel name or UUID and remote.endpoint to its stable public HTTPS /mcp endpoint. Keep config.production.json local; .gitignore excludes it.

Set the bearer token in the process environment before starting. It is not stored in the repository:

$env:LOCAL_REVIEW_MCP_TOKEN = "<long-random-review-token>"

Make sure cloudflared is installed. The production Supervisor runs the configured Named Tunnel with its local credentials file. If the installation uses a tunnel token instead, set CLOUDFLARE_TUNNEL_TOKEN for that same configured tunnel. Do not put either token in source control.

Run the standard startup entry point:

.\scripts\start-production.ps1 -Config ".\config.production.json"

The entry point reads the configuration, runs preflight-check.ps1, then starts the existing Local Review MCP runtime. The runtime starts the Windows Supervisor when supervisor.enabled is true and starts the Cloudflare Tunnel when remote.enabled is true. It prints the local health endpoint and any ready remote endpoint without printing credentials.

The preflight check verifies Node/npm, installed dependencies, required config sections, workspace access, and port availability. A missing cloudflared is fatal only when remote access is enabled. It reports an occupied port and asks you to change port; it never auto-installs dependencies, creates a workspace, or selects another port.

Remote verification

After the tunnel reports a public endpoint, verify the deployment from a PowerShell process that has the remote URL and token:

$env:LOCAL_REVIEW_MCP_REMOTE_URL = "https://<public-hostname>/mcp"
$env:LOCAL_REVIEW_MCP_REMOTE_TOKEN = $env:LOCAL_REVIEW_MCP_TOKEN
.\scripts\verify-remote.ps1

verify-remote.ps1 checks that unauthenticated and wrong-token health requests return HTTP 401, the correct token returns status=ok, MCP initialize works, and tools/list matches its embedded tool allowlist. The current runtime advertises nineteen read-only tools plus submit_goal (20 registered tools); this script still contains the older fifteen-tool allowlist, so its final comparison is not a complete current-surface check. The remote test suite uses the current registered-tool fixture for that check.

Remote MCP Setup

Remote access is disabled by default. Enable the Cloudflare provider with:

{
  "remote": {
    "enabled": true,
    "provider": "cloudflare",
    "tunnelName": "<tunnel-name-or-uuid>",
    "endpoint": "https://<public-hostname>/mcp"
  }
}

Start the local runtime with an explicit workspace and token:

$env:LOCAL_REVIEW_MCP_TOKEN = "<long-random-review-token>"
npm start -- --workspace "C:\path\to\project" --config "settings.json"

Install cloudflared and configure an existing Named Tunnel. remote.tunnelName must contain its name or UUID, and remote.endpoint must contain the stable public HTTPS /mcp URL. The Supervisor runs cloudflared tunnel run for that tunnel and never creates a tunnel, changes DNS, or requests a temporary URL.

$env:LOCAL_REVIEW_MCP_TOKEN = "<long-random-review-token>"
# Optional when using token-based credentials for the configured Named Tunnel.
$env:CLOUDFLARE_TUNNEL_TOKEN = "<cloudflare-tunnel-token>"
npm start -- --workspace "C:\path\to\project" --config "settings.json"

The Cloudflare provider invokes only the installed cloudflared executable, does not upload configuration, and never logs credentials. The live endpoint is returned by the provider and owned by TunnelManager; remote.tunnelName and remote.endpoint are configuration inputs. No module hardcodes a tunnel hostname.

ChatGPT Web connector

  1. In ChatGPT Web, enable the workspace's developer/custom-app capability if the plan requires it, then open the Apps/Connectors settings and create a custom MCP app.

  2. Enter the HTTPS endpoint reported by TunnelManager or the authenticated /health response, using the /mcp path.

  3. Select the connector's OAuth authentication option. The server publishes MCP protected-resource metadata, authorization-server metadata, dynamic client registration, and PKCE endpoints under the same public origin.

  4. Scan the tools, confirm the read-only actions plus submit_goal, save the draft app, and select it from a new chat. Ask for a code review; ChatGPT should call workspace_list first, then review_summary, execution_output, workspace_info, git_status, git_diff, read_file, and search_text with a workspace_id when selecting a registered workspace.

Connector and browser readiness

For a real submit_goal handoff, keep the runtime, Tunnel (when remote access is enabled), Bridge, and the exact ChatGPT connector available. Run the local diagnostic after startup:

npm run diagnose:chatgpt-connector -- --config <config>

If the exact connector has just been created or adopted, call workspace_info through that exact OAuth connector and confirm it with the returned request ID:

npm run confirm:chatgpt-connector -- --config <config> --request-id <workspace_info.request_id>

Continue only when the diagnostic reports ok=true, connector.status=verified, connector.action=none, and ready remote/OAuth checks. The connector workflow in docs/chatgpt-connector-workflow.md covers exact-name checking, reauthorization, and adoption of an existing ChatGPT connector. Confirmation evidence is OAuth-authenticated workspace_info evidence for the current workspace and expires after ten minutes.

The unpacked MV3 extension is in extension/; it needs to be loaded manually in Chrome or Edge and has no build step. After reloading the extension, refresh the ChatGPT page so its content scripts are replaced, then use a concrete conversation route rather than the New Chat root:

https://chatgpt.com/c/<conversation_id>
https://chatgpt.com/g/<project>/c/<conversation_id>

The supported Project form is the one-segment route /g/<project>/c/<conversation_id>. fiber.js runs in the MAIN world and emits only bounded evidence from the current turn. For direct submit_goal, it accepts only the exact assistant tool request for api_tool.call_tool or Local_MCP_Connector.submit_goal whose args or arguments contains the strict UUID v4 correlation_key. It never substitutes assistant text, tool results, or message.metadata.request_id for that direct key. The content and background scripts additionally require Fiber/URL conversation equality, Chrome MessageSender.documentId, and the current navigation_epoch; stale, conflicting, and new-chat identities produce no canonical evidence. A raw WEB:* value is provisional and never becomes a canonical owner; only a valid same-model serverId$() result can resolve it to a canonical conversation ID.

The Local Control Bridge is a separate loopback Control Plane server on 127.0.0.1, discovered on ports 12081 through 12085, using protocol 3. It pairs one validated Extension Origin and authenticates protected identity, delivery, and completion transport with a process-local bearer token. GET /hello is discovery; protected identity evidence is posted to /identity-evidence. If the Bridge is unavailable, the MCP Data Plane can still start, but submit_goal cannot pass its Browser identity-channel readiness gate.

GET http://127.0.0.1:<port>/launcher/readiness is a loopback, static-token-protected status endpoint also shown by the Launcher. ready means the Bridge is available, the Extension is paired, and Extension presence was seen within the ten-second presence window. Presence is only channel readiness, not conversation proof. The Launcher may briefly retain a recent READY display during its presentation grace period, but submit_goal still checks live readiness and requires the exact Fiber/URL/document/epoch evidence above.

submit_goal does not accept conversation_id. The model must generate a fresh UUID v4 correlation_key for every call. The call first returns a durable acceptance receipt while a PendingGoalSubmission waits for matching canonical evidence (default TTL: two minutes); only then does Goal startup happen asynchronously. accepted is not Goal, Session, Execution, or review completion. If the key is not matched before expiry, no Goal is created. The read-only get_identity_trace and get_evidence_transport_trace tools expose hash-only, correlation-key-scoped diagnostics and never return raw payloads, tokens, cookies, or message text.

After identity matching, Goal preflight still checks runtime readiness, the active registered workspace identity, and verified Connector/OAuth/remote readiness; Browser presence alone never authorizes a Goal.

The exact ChatGPT Web menu labels and availability depend on the workspace plan. The MCP endpoint itself is /mcp; /health is an authenticated readiness check. OpenAI's current MCP and Connectors guide describes remote MCP server URLs and tool approval configuration.

At least one workspace is required. With a registry, the first entry is the legacy active workspace unless the top-level workspace matches another registered path. Without workspace_id, tools use that active workspace.

The current nineteen read-only tools are workspace_info, list_files, read_file, search_text, git_status, git_diff, workspace_get_info, workspace_list_files, workspace_read_file, workspace_search, workspace_review_context, workspace_list, review_summary, execution_output, get_session_status, get_execution_status, list_session_events, get_identity_trace, and get_evidence_transport_trace. The Control Plane tool submit_goal durably accepts a Goal and starts it after canonical Extension evidence proves the conversation. The five explicitly scoped workspace_* review tools require workspace_id; the other workspace-scoped tools preserve optional active-workspace behavior, while workspace_list has no workspace selector. Git tools are bound to the selected registered workspace, do not expose Git command arguments, and never perform write operations. workspace_list returns only each workspace's stable id and display name, never its local path. review_summary combines workspace metadata with Git status and diff counts. execution_output only reads .review/execution_output.json and returns {"available":false} when that file is absent; it never runs the recorded command or accepts a file path.

submit_goal requires a fresh correlation_key and accepts an optional workspace_id, title, goal, requirements, acceptance_criteria, max_iterations (default 2), execution_mode (default batch), model, and reasoning_effort. Its conversation_id is resolved internally from the exact Extension evidence chain; it is not caller-supplied.

The health endpoint requires the configured static Authorization: Bearer <token> even on localhost and through Cloudflare Tunnel. MCP requests accept either that legacy token or an OAuth access token. The health endpoint is http://127.0.0.1:<port>/health; it returns the status, stable workspace identifier, version, remote_status, endpoint_status, the public endpoint only when it is ready, and an oauth_registry summary. The health summary uses the relative oauth/clients.json location so it does not disclose local paths. The loopback-only, static-token-protected GET /oauth/clients endpoint returns the full registry path, load state, client count, and non-secret client summaries. DELETE /oauth/clients/<client_id> removes one registration and DELETE /oauth/clients clears registrations without deleting the registry file. The health endpoint never returns tokens, credentials, local IPs, or workspace absolute paths.

search_text accepts an optional workspace_id, query, workspace-relative path and glob, regex, case_sensitive, and limit. Searches are restricted to allowed text files up to 2 MiB, with at most 200 returned results and 500 preview characters per result.

E2E verification

The remote suite uses the same Streamable HTTP MCP client flow as a remote connector and covers initialize, tools/list, workspace registry selection, ordered workspace review, Bearer authentication, safe health metadata, sensitive-file denial, traversal/ absolute/drive/symlink path denial, and tunnel stop/restart. It creates a temporary sample-project Git workspace and never commits review changes.

Run the release-candidate checks locally:

npm run typecheck
npm test
npm run build

The Browser Worker review-submission diagnostic drives the complete local Review Delivery chain with a mock Page and does not require a ChatGPT login:

npm run diagnose:review-submission

The live Goal E2E diagnostic exercises the Extension-based Goal, delivery, review-completion, verdict, and terminal-state path for one concrete ChatGPT conversation:

npm run diagnose:goal-e2e -- --config config.production.json --conversation-id <conversation_id>

It requires the exact connector, an open target conversation, and a paired and present Extension. The automated Phase 5.6 review-loop test uses an in-process app-server test double; it verifies LRM lifecycle and verdict parsing, not live ChatGPT/browser delivery.

The interactive app-server smoke uses a temporary state root and requires the requested provider selection:

$env:CODEX_INTERACTIVE_MODEL = "gpt-5.6-luna"
$env:CODEX_INTERACTIVE_EFFORT = "max"
npm run test:interactive-goal

To probe an already deployed HTTPS endpoint with the optional remote test, provide LOCAL_REVIEW_MCP_REMOTE_URL and LOCAL_REVIEW_MCP_REMOTE_TOKEN only in the process environment before running the remote test. No token or public URL is stored in the repository.

LocalReviewLauncher

LocalReviewLauncher/README.md describes the independent PySide6 Windows launcher. start-launcher.cmd starts the existing scripts/start-production.ps1 entry point; the launcher does not replace or embed the MCP runtime. Its startup and status views cover Start/Stop/Refresh, Workspace Registry, configuration validation/open/backup, OAuth client status, MCP health, Tunnel/remote status, and Browser readiness through authenticated local HTTP checks.

The read-only Task Dashboard lists only interactive codex_app_server Sessions and shows Goal/Task, Session/Thread, model/effort, status, current Execution, and last update. The Session Viewer shows the current Execution and the paginated normalized Event Stream; adjacent agent-message deltas are aggregated for display and the rendered stream is capped at 500 rows. It refreshes every five seconds and provides an Open Codex Task locator using the proven Thread/Session IDs. The Launcher only observes lifecycle state and does not submit, stop, resume, approve, or control a Goal, Execution, Thread, or Turn. Separate cleanup actions can clear the display or remove completed/failed/terminated persisted task records; running Sessions are retained.

Security Notes

Local Review MCP provides read, search, review, and interactive status capabilities through its nineteen read-only tools, plus the reviewed submit_goal Control Plane entry point. It does not provide:

  • modify or write_file operations;

  • execute or shell operations;

  • direct agent or Codex/ChatGPT automation controls outside submit_goal.

Keep LOCAL_REVIEW_MCP_TOKEN, CLOUDFLARE_TUNNEL_TOKEN, and LOCAL_REVIEW_MCP_REMOTE_TOKEN in the process environment or another local secret store. Never commit tokens, .env files, Cloudflare credentials, private keys, or config.production.json.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    A local filesystem MCP server providing constrained file operations (read/write, directory management, search, metadata) within configurable directories, with read-only mode and zero runtime dependencies.
    2 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A minimal, security-focused MCP server that provides structured read/write access to exactly one local workspace, with built-in local Git checkpoints and rollback.
    1
    Apache 2.0