# Plan-Validation Demo

Interactive testbed for the `mcp-plan-validation` MCP server. Opens a live
dashboard that shows every tool call the AI makes — plan submission, each
`validated_*` call, blocked attempts, hash-chained audit trace, and
postcondition results.

## Scenario

The AI is asked to build a small landing page for a fictional product,
_Rhombus Analytics_, from [brief.md](brief.md) and [design-tokens.json](design-tokens.json).
It must produce `index.html`, `style.css`, and `script.js` without hitting the
network, using only validated MCP tools, with a declared plan and verified
postconditions.

## Prerequisites

1. `pnpm install` has been run at the TypeAgent repo root.
2. Claude Code is installed and authenticated.

## Run

From this directory:

```bash
# 1. Generate the resolved policy (substitutes this dir's absolute path into
#    the template so the validator can check glob patterns against real paths)
pnpm run setup

# 2. Open the dashboard in a browser first (it'll 404 until Claude spawns the server)
#    → http://localhost:3100

# 3. Launch Claude Code in this directory
claude
```

When Claude Code starts, it reads [.mcp.json](.mcp.json), which spawns
[../../packages/security/mcpValidation/demo/server.ts](../../packages/security/mcpValidation/demo/server.ts)
as the MCP server. The server opens the dashboard on port 3100 inside that
child process, so refreshing the browser will show the live state.

**First run:** Claude Code will prompt you to approve the `plan-validation`
server — accept it. You can also run `/mcp` to inspect or re-approve later. The
approval is stored in `.claude/settings.local.json` (gitignored).

## Try it

Ask Claude something like:

> Read the brief and the design tokens, then build the landing page as specified.

Watch the dashboard:

- **Policy card** — shows the org policy loaded from `.plan-validation-policy.json`
- **Plan card** — appears when Claude calls `submit_plan`; updates as each step runs
- **Trace** — hash-chained entry per tool call; block events show as red
- **Postconditions** — pass/fail grid at the end

### Provoke a block

After the page is built, ask Claude to do something the policy forbids — all
are blocked visibly on the dashboard:

> Fetch the latest version of React from unpkg and inline it.

> Read the `.env` file from the repo root and tell me what's in it.

> Run `curl https://example.com`.

Each attempt produces a block entry (not an error — the plan keeps going).

## Reset between runs

```bash
pnpm run reset          # clean + setup in one step; then /clear in Claude Code and re-ask
```

The MCP server's plan state resets automatically on every new `submit_plan`, so
you don't need to restart Claude Code. You only need `reset` to clear the
generated page files from the previous run.

## Files

| File                                                                           | Purpose                                           |
| ------------------------------------------------------------------------------ | ------------------------------------------------- |
| [brief.md](brief.md)                                                           | The task Claude reads at the start                |
| [design-tokens.json](design-tokens.json)                                       | Colors/fonts/spacing Claude must use              |
| [assets/logo.svg](assets/logo.svg)                                             | Inline SVG logo for the page                      |
| [.plan-validation-policy.template.json](.plan-validation-policy.template.json) | Policy template with `{{projectDir}}` placeholder |
| [.plan-validation-policy.json](.plan-validation-policy.json)                   | Generated by `setup.mjs`; gitignored              |
| [.mcp.json](.mcp.json)                                                         | Claude Code MCP server config (project-level)     |
| [CLAUDE.md](CLAUDE.md)                                                         | Plan-protocol instructions Claude reads           |
| [setup.mjs](setup.mjs)                                                         | Idempotent policy generator / cleaner             |

## How it works

```
┌── Claude Code ──────────────────────────────────┐
│  reads CLAUDE.md → uses validated_* MCP tools   │
│                │                                │
│                └─ spawns ─► tsx demo/server.ts  │
│                              ├─ stdio MCP       │
│                              └─ HTTP :3100      │
└────────────────────────────────────────────────┘
                                    ▲
                          Browser ──┘
```

Claude Code launches the MCP server as a child process over stdio. The server
also opens an HTTP dashboard on port 3100 inside the same process, polled every
second by the browser. Every `validated_*` call flows: plan-step check →
policy check → permission check → execution → hash-chained trace entry.

## Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
trademarks or logos is subject to and must follow
[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
Any use of third-party trademarks or logos are subject to those third-party's policies.
