# Hen

Run API requests as files, from the command line or through MCP.

Hen keeps request definitions, assertions, captures, dependencies, and protocol-specific behavior in a single `.hen` file. It works well for local exploration, CI, and editor or agent integrations.

## Table of Contents

- [Quick Example](#quick-example)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [CLI](#cli)
- [MCP Server](#mcp-server)
- [Authoring Model](#authoring-model)
- [Examples](#examples)

## Quick Example

```text
name = Test Collection File
description = A collection of mock requests for testing this syntax.

$ API_KEY = $(./get_secret.sh)
$ USERNAME = $(echo $USER)
$ API_ORIGIN = https://lorem-api.com/api
$ ROLE = [admin, user, guest]

---

Some descriptive title for the prompt.

POST {{ API_ORIGIN }}/echo

* Authorization = {{ API_KEY }}
? query_param_1 = value

~~~ application/json
{
  "username": "{{ USERNAME }}",
  "password": "[[ password ]]",
  "role": "{{ ROLE }}"
}
~~~

^ & status == 200

! sh ./callback.sh
```

This single file can define variables, prompt inputs, mapped requests, assertions, and callbacks. Add `> requires:` when later requests depend on earlier ones, and use response captures to thread values through a collection.

## Installation

```bash
cargo install hen
```

This installs both `hen` and `hen-mcp`.

### Container Image

The repository also ships a container image that includes both binaries.

Build it locally with Docker:

```bash
docker build -t hen:latest .
```

## Quick Start

Verify a collection without executing shell commands or network requests:

```bash
hen verify ./examples/lorem.hen
```

Run every request in a collection non-interactively:

```bash
hen run ./examples/lorem.hen all --non-interactive
```

Emit machine-readable output for scripts or CI:

```bash
hen run ./examples/lorem.hen all --non-interactive --output json
```

## CLI

Hen has two primary commands:

- `hen run` executes a collection or request.
- `hen verify` parses and validates a collection without making requests.

The default `hen [PATH] [SELECTOR]` form still works for interactive terminal use, but `hen run ...` is the clearer choice for CI and automation.

### Selection and prompts

- If a directory contains one `.hen` file, Hen selects it automatically.
- If a collection contains multiple requests, provide an index or `all` to bypass the picker.
- The text CLI prompts for unresolved `[[ prompt ]]` placeholders.
- `--non-interactive` disables selection prompts and fails when required prompt values are missing.
- Use repeated `--input key=value` flags to provide prompt values up front.

### Useful options

- `--output text|json|ndjson|junit` selects human or machine-readable output.
- `--parallel` runs independent requests concurrently.
- `--max-concurrency N` throttles parallel execution.
- `--continue-on-error` keeps unaffected dependency branches running.
- `--benchmark N` benchmarks a request instead of running it once.
- `--export` renders the request as a curl command.

### Schema validation

Hen supports collection-local `scalar` and `schema` declarations plus built-in targets such as `UUID`, `EMAIL`, `NUMBER`, `DATE`, `DATE_TIME`, `TIME`, and `URI`.

```text
scalar HANDLE = string & len(3..24) & pattern(/^[a-z][a-z0-9_]*$/)

schema User {
  id: UUID
  email: EMAIL
  handle: HANDLE
}
```

For the full declaration grammar and more examples, see [syntax-reference.md](syntax-reference.md) and the schema examples under [examples/](examples/).

## MCP Server

Hen also ships with `hen-mcp`, a stdio MCP server for editors and agents. It is intentionally non-interactive:

- use `hen` for terminal-first, prompt-driven workflows
- use `hen-mcp` when an MCP client needs structured access
- provide any `[[ prompt ]]` values explicitly through tool inputs

### Running the server

If `hen-mcp` is on your `PATH`:

```bash
hen-mcp
```

From a checkout of this repository:

```bash
cargo run --bin hen-mcp
```

For normal MCP client usage, prefer a compiled binary:

```bash
cargo build --release
./target/release/hen-mcp
```

### Example configuration

VS Code uses `.vscode/mcp.json`:

```json
{
  "servers": {
    "hen": {
      "type": "stdio",
      "command": "/absolute/path/to/hen-mcp"
    }
  },
  "inputs": []
}
```

Claude Code uses `.mcp.json`:

```json
{
  "mcpServers": {
    "hen": {
      "type": "stdio",
      "command": "/absolute/path/to/hen-mcp"
    }
  }
}
```

If `hen-mcp` is installed globally, `command` can simply be `hen-mcp`.

### Exposed MCP surface

- `run_hen`: run a collection or request non-interactively
- `verify_hen_syntax`: validate a file or inline source without execution
- `get_hen_authoring_guide`: return built-in usage or syntax docs
- `hen://authoring-guide` and `hen://readme`: built-in resources for clients that read docs directly

## Authoring Model

Hen files are plain text collections made of a preamble and one or more requests separated by `---`.

### Core concepts

- Variables: `$ NAME = value`, shell substitutions with `$(...)`, prompt placeholders with `[[ name ]]`, and simple arrays for mapped requests.
- Requests: HTTP by default, plus explicit `protocol = graphql`, `protocol = mcp`, `protocol = sse`, and `protocol = ws`.
- Captures: `& body.token -> $TOKEN` stores response data for later requests, assertions, and callbacks.
- Assertions: `^` lines validate status, headers, body fields, structural JSON matches, and schema targets.
- Dependencies: `> requires: Request Name` creates a DAG so setup requests run before dependents.
- Fragments: `<< file.hen` reuses shared request snippets or declarations.
- Callbacks: `!` lines run shell commands after request execution.
- Guards: `[predicate]` can gate assertions or fragment imports.

### Protocol support

- HTTP: ordinary request and response workflows.
- GraphQL: GraphQL-over-HTTP with `operation`, `variables`, and `~~~graphql` documents.
- MCP: MCP-over-HTTP authoring with generated JSON-RPC envelopes and reusable sessions.
- SSE: named streaming sessions with `receive` steps and timeout windows.
- WebSocket: `open`, `send`, `exchange`, and `receive` flows over a named session.

### Full syntax guide

The complete authoring grammar lives in [syntax-reference.md](syntax-reference.md). That file covers:

- variables and prompts
- headers, query parameters, form data, and body blocks
- protocol-specific directives
- declarations, captures, assertions, callbacks, and dependencies

## Examples

The fastest way to learn the format is to run the included examples:

- [examples/lorem.hen](examples/lorem.hen): basic HTTP requests
- [examples/json_response_captures.hen](examples/json_response_captures.hen): captures and JSON paths
- [examples/filtered_selector_variables.hen](examples/filtered_selector_variables.hen): selector variables in captures and assertions
- [examples/schema_scalar_checks.hen](examples/schema_scalar_checks.hen): scalar validation
- [examples/schema_object_validation.hen](examples/schema_object_validation.hen): object schema validation
- [examples/schema_root_array_validation.hen](examples/schema_root_array_validation.hen): root-array schemas
- [examples/schema_fragment_reuse.hen](examples/schema_fragment_reuse.hen): declaration reuse through fragments
- [examples/structural_json_matching.hen](examples/structural_json_matching.hen): structural JSON assertions
- [examples/graphql_protocol.hen](examples/graphql_protocol.hen): GraphQL authoring
- [examples/mcp_protocol.hen](examples/mcp_protocol.hen): MCP-over-HTTP sessions
- [examples/sse_protocol.hen](examples/sse_protocol.hen): server-sent events
- [examples/ws_protocol.hen](examples/ws_protocol.hen): WebSocket sessions
