# Plan 17-02: CLI Scaffolding Command and Project Templates

```yaml
wave: 2
depends_on: [17-01]
requirements: [DEVX-02, DEVX-06, DEVX-07]
files_modified:
  - cargo-pmcp/src/main.rs
  - cargo-pmcp/src/commands/mod.rs
  - cargo-pmcp/src/commands/app.rs (NEW)
  - cargo-pmcp/src/templates/mcp_app.rs (NEW)
  - cargo-pmcp/src/templates/mod.rs
autonomous: true
```

## Objective

Implement the `cargo pmcp app new <name>` scaffolding command that generates a complete MCP Apps project with server code, a `widgets/` directory containing a starter widget, Cargo.toml, and README. The scaffolded project uses `WidgetDir` from Plan 17-01, includes documented bridge API patterns, and has `WidgetCSP` helper examples in `main.rs`.

## Context

- @cargo-pmcp/src/main.rs — CLI entry point (needs `App` subcommand)
- @cargo-pmcp/src/commands/new.rs — Existing `new` command (reference for directory creation patterns, error-if-exists semantics)
- @cargo-pmcp/src/templates/ — Template module (needs mcp_app template)
- @src/server/mcp_apps/ — WidgetDir and MCP Apps types (templates reference these)
- @.planning/phases/17-widget-authoring-dx-and-scaffolding/17-CONTEXT.md — User decisions (locked)

## must_haves

1. `cargo pmcp app new my-app` creates a directory with `src/main.rs`, `widgets/hello.html`, `Cargo.toml`, `README.md`
2. Scaffolded project compiles out of the box with `cargo build`
3. README explains bridge API, stateless widget pattern, and CSP configuration
4. `main.rs` includes commented `WidgetCSP` helper examples
5. Post-scaffold message prints next steps: `cd my-app`, `cargo pmcp preview`, URL

## Tasks

<task id="17-02-A" type="auto">
<name>App subcommand and scaffolding template</name>

<files>
- cargo-pmcp/src/main.rs
- cargo-pmcp/src/commands/mod.rs
- cargo-pmcp/src/commands/app.rs (NEW)
- cargo-pmcp/src/templates/mcp_app.rs (NEW)
- cargo-pmcp/src/templates/mod.rs
</files>

<action>
**Part 1 — Add `App` subcommand to CLI:**

In `cargo-pmcp/src/main.rs`, add a new `App` variant to the `Commands` enum:
```rust
/// MCP Apps project management
App {
    #[command(subcommand)]
    command: commands::app::AppCommand,
},
```

Create `cargo-pmcp/src/commands/app.rs` with:
```rust
#[derive(Subcommand)]
pub enum AppCommand {
    /// Create a new MCP Apps project
    New {
        /// Name of the project
        name: String,
        /// Directory to create project in (defaults to current directory)
        #[arg(long)]
        path: Option<String>,
    },
}
```

Per CONTEXT.md decisions:
- Invocation: `cargo pmcp app new <name>` — under `app` namespace, leaving room for future `app build`, `app test`
- One-shot generation, no interactive prompts
- Creates new directory (`./my-app/`) — error if directory already exists, matching `cargo new` semantics
- After scaffolding: print next steps like `cargo init` does

Wire the `execute` function in the main match arm.

**Part 2 — MCP App project template:**

Create `cargo-pmcp/src/templates/mcp_app.rs` that generates these files:

1. **`Cargo.toml`** — Minimal dependency set:
   ```toml
   [package]
   name = "{name}"
   version = "0.1.0"
   edition = "2021"

   [dependencies]
   pmcp = { version = "1.10", features = ["mcp-apps"] }
   tokio = { version = "1", features = ["full"] }
   serde = { version = "1", features = ["derive"] }
   serde_json = "1"
   schemars = "0.8"
   async-trait = "0.1"
   tracing-subscriber = "0.3"
   ```
   Pin to crates.io version per CONTEXT.md decision (not workspace path dep).

2. **`src/main.rs`** — Starter server using builder pattern matching chess/map examples:
   - Imports `WidgetDir` from `pmcp::server::mcp_apps`
   - Defines a simple `hello` tool that returns a greeting with the provided name
   - Uses `WidgetDir::new("widgets")` for resource handling
   - Includes commented `WidgetCSP` helper examples showing how to configure Content Security Policy:
     ```rust
     // === WidgetCSP Configuration ===
     // Uncomment to restrict widget content security:
     // use pmcp::server::mcp_apps::WidgetCSP;
     // let csp = WidgetCSP::new()
     //     .default_src("'self'")
     //     .script_src("'self' 'unsafe-inline'")
     //     .style_src("'self' 'unsafe-inline'")
     //     .connect_src("'self' http://localhost:*");
     ```
   - Binds to `0.0.0.0:3000` with `StreamableHttpServer`
   - Uses `tracing_subscriber::init()` for dev logging

3. **`widgets/hello.html`** — Starter widget demonstrating the bridge pattern:
   - Clean HTML5 document with inline CSS for a card layout
   - A text input for a name and a "Say Hello" button
   - JavaScript that calls `window.mcpBridge.callTool("hello", { name: inputValue })` on button click
   - Displays the tool response in a result div
   - NO bridge script tag (server auto-injects it via `WidgetDir`)
   - Includes HTML comments explaining the stateless pattern: `<!-- This widget uses the stateless pattern: all state lives in the browser, tool calls are pure functions -->`

4. **`README.md`** — Developer documentation covering (per CONTEXT.md DEVX-06):
   - **Bridge API** section: documents `callTool(name, args)`, `getState()`, `setState(state)`, and lifecycle events with code examples
   - **Stateless Widget Pattern** section: explains that widgets hold state in-browser, tool calls include full state, server processes without sessions
   - **CSP Configuration** section: explains `WidgetCSP` helper, when to use it, default policy, and how to customize
   - **Project Structure** section: explains `widgets/` directory convention, auto-discovery, and hot reload behavior
   - **Getting Started** section: `cargo build`, `cargo run`, `cargo pmcp preview --url http://localhost:3000`

**Part 3 — Post-scaffold output:**

After generating all files, print:
```
Created MCP Apps project 'my-app'

  Next steps:
    cd my-app
    cargo build
    cargo run &
    cargo pmcp preview --url http://localhost:3000 --open

  Add widgets by dropping .html files in the widgets/ directory.
  Preview auto-refreshes — just reload your browser.
```

Register the template module in `cargo-pmcp/src/templates/mod.rs`.
</action>

<verify>
  <automated>cargo build -p cargo-pmcp 2>&1 | head -20</automated>
</verify>

<done>
- `cargo pmcp app new test-app` creates directory with `src/main.rs`, `widgets/hello.html`, `Cargo.toml`, `README.md`
- Error printed if directory already exists (no overwrite)
- Scaffolded `Cargo.toml` pins pmcp to crates.io version
- `main.rs` uses `WidgetDir` and includes commented `WidgetCSP` examples
- `widgets/hello.html` demonstrates `callTool` bridge pattern without inline bridge script
- `README.md` documents bridge API, stateless pattern, and CSP configuration
- Post-scaffold message prints exact next-step commands
</done>
</task>
