> ## Documentation Index
> Fetch the complete documentation index at: https://hitspec.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP server

> Expose bounded fetch, live web search, and explicit durable capture over stdio

Run Hitspec as a workspace-scoped Model Context Protocol server:

```bash theme={null}
hitspec mcp serve --workspace /absolute/path/to/api-workspace
```

stdout is reserved exclusively for MCP JSON-RPC. The server does not start run
history or a file watcher or execute shell hooks or database assertions. In
v2.18.0, web search and durable capture are registered only when their
operator-owned provider and artifact sink, respectively, are configured at
startup.

## Tools

| Tool                      | Purpose                                                                                    | Registered when                 |
| ------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------- |
| `hitspec_fetch`           | Fetch one direct URL or one saved request as `raw`, `text`, `markdown`, or `json`.         | Always                          |
| `hitspec_search_web`      | Search the live public web and return normalized discovery candidates without persistence. | A search provider is configured |
| `hitspec_capture_webpage` | GET one public webpage, render Markdown, and preserve it in file.cheap.                    | An artifact sink is configured  |
| `hitspec_list_requests`   | List names, methods, source lines, and tags in workspace Hitspec files.                    | Always                          |
| `hitspec_validate`        | Parse and structurally validate one workspace file without executing it.                   | Always                          |

Hitspec is the only model-visible web surface. Tavily is the initial internal
search provider and can be replaced without changing these tool names or
schemas.

### `hitspec_fetch` input

| Field         | Type    | Applies to    | Default and behavior                                                                                 |
| ------------- | ------- | ------------- | ---------------------------------------------------------------------------------------------------- |
| `url`         | string  | Direct URL    | HTTP(S) URL. Supply exactly one of `url` or `file`.                                                  |
| `file`        | string  | Saved request | Workspace-relative `.http` or `.hitspec` file. Supply exactly one of `file` or `url`.                |
| `name`        | string  | Saved request | Selects a uniquely named request. Mutually exclusive with `index`.                                   |
| `index`       | integer | Saved request | Selects a request by its one-based position. Mutually exclusive with `name`.                         |
| `environment` | string  | Saved request | Environment name. Defaults to the config's default environment, then `dev`.                          |
| `env_file`    | string  | Saved request | Workspace-relative dotenv file.                                                                      |
| `config_file` | string  | Saved request | Workspace-relative Hitspec config file.                                                              |
| `method`      | string  | Direct URL    | HTTP method. Defaults to `GET`, or `POST` when `body` is non-empty.                                  |
| `headers`     | object  | Direct URL    | Map of request header names to string values.                                                        |
| `body`        | string  | Direct URL    | UTF-8 request body.                                                                                  |
| `format`      | string  | Both          | `text`. Accepts `raw`, `text`, `markdown`, or `json`.                                                |
| `no_follow`   | boolean | Both          | `false`. When true, stops at the first redirect. Redirect chains otherwise have a fixed limit of 10. |

A file containing multiple requests requires `name` or `index`. A saved request
that declares `@depends` is rejected. Assertions, captures, conditions, hooks,
shell blocks, database assertions, and `@waitFor` are not executed.
`hitspec_fetch` never persists the response; use `hitspec_capture_webpage` for a
durable artifact.

### Live web search and capture

`hitspec_search_web` has this provider-neutral tool input:

| Field             | Type      | Default and behavior                                                                                                                       |
| ----------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `query`           | string    | Required; maximum 512 Unicode characters.                                                                                                  |
| `max_results`     | integer   | `5`; accepts 1–10.                                                                                                                         |
| `language`        | string    | Optional BCP 47 language hint. A provider returns an explicit error when it cannot apply the filter; Tavily does not currently support it. |
| `freshness`       | string    | `any`; accepts `any`, `day`, `week`, `month`, or `year`.                                                                                   |
| `include_domains` | string\[] | Optional; at most 20 normalized public domains.                                                                                            |
| `exclude_domains` | string\[] | Optional; at most 20 normalized public domains. A domain cannot appear in both lists.                                                      |

The tool does not accept a provider, endpoint, API key, authorization header,
arbitrary headers, generated-answer switch, or raw-content switch. Tavily is an
internal adapter selected by the server operator, not a separate model-visible
tool.

The JSON document is capped at 64 KiB. It contains `kind: "discovery"`,
normalized `query`, `results`, and `truncated`. Each result contains only
`title`, `url`, `domain`, `snippet`, optional `published_at`, and a response-local
`citation_id`. `truncated` is `true` whenever candidates are
omitted by the result limit or response cap; for the latter, Hitspec removes
trailing results. Provider-specific request IDs and scores, generated answers,
raw page content, and credentials are never exposed. Search snippets are
discovery candidates, not verified or durable evidence.

`hitspec_capture_webpage` has this compatibility-preserving input:

| Field   | Type      | Default and behavior                                                       |
| ------- | --------- | -------------------------------------------------------------------------- |
| `url`   | string    | Required public HTTP(S) webpage URL.                                       |
| `name`  | string    | Optional file.cheap stash name; defaults to the HTML title.                |
| `tags`  | string\[] | Optional extra tags; `web` and `markdown` are always included.             |
| `ttl`   | string    | Optional file.cheap retention such as `24h`, `7d`, `30d`, or `2026-12-31`. |
| `index` | boolean   | `true`; index the Markdown immediately for `fcheap search`.                |

The tool performs one public-network GET, renders static HTML as Markdown, and
saves it through the fixed file.cheap adapter. It returns a compact receipt,
not the page body or rendered Markdown:

```json theme={null}
{
  "url": "https://example.com/docs",
  "final_url": "https://example.com/docs",
  "title": "Example documentation",
  "http_status": 200,
  "content_type": "text/html",
  "markdown_bytes": 1842,
  "stash": {
    "id": "stash-id",
    "name": "Example documentation",
    "status": "saved",
    "created_at": "2026-07-13T12:00:00Z",
    "tags": ["web", "markdown"],
    "content_hash": "e3b0c442...",
    "file_count": 1,
    "total_size": 1842,
    "index_requested": true,
    "indexed": true
  }
}
```

The stash object includes `file_count` and `total_size` and may also include
`expires_at`. Inspect `status`, `indexed`, and `failed` when present before
deciding whether follow-up is needed.

### Request discovery and validation input

* `hitspec_list_requests` accepts an optional `path`: a workspace-relative
  directory or `.http`/`.hitspec` file. It defaults to the workspace root and
  searches directories recursively. If any discovered Hitspec file is invalid,
  the tool returns an error instead of an incomplete list.
* `hitspec_validate` requires `file`, a workspace-relative `.http` or `.hitspec`
  file. Its result reports the file, validity, request count, and parse or
  structural errors.

Saved file, dotenv, config, and discovery paths are workspace-relative and are
checked after symlink resolution.

### Tool result content

Every successful tool call includes an MCP `TextContent` representation so
clients that do not pass through structured output can still consume it:

* `hitspec_fetch` with `raw` returns a JSON text envelope containing sanitized
  source, status, content type, byte size, `encoding: "base64"`, and `data`.
* `text` and `markdown` return their rendered documents as text content. `json`
  returns the machine-safe response envelope serialized as text content.
* Discovery and validation return their JSON documents serialized as text
  content.
* Search returns the bounded discovery JSON as text content. Webpage capture
  also publishes its typed compact receipt as structured content when the client
  supports it.

## Server flags

| Flag                      | Default            | Behavior                                                                                                                  |
| ------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------- |
| `--workspace`             | `.`                | Fixes the filesystem boundary exposed to all tools. Use an absolute path in client configuration.                         |
| `--max-body-bytes`        | `1048576` (1 MiB)  | Maximum fetched response-body size.                                                                                       |
| `--timeout`               | `30s`              | Maximum duration of one HTTP request.                                                                                     |
| `--allow-private-network` | `false`            | Allows private, loopback, and other non-public targets; it also enables the standard saved-request modes described below. |
| `--search-provider`       | `none`             | Live search provider. Currently `none` or `tavily`; may also come from `HITSPEC_SEARCH_PROVIDER`.                         |
| `--fcheap-path`           | unset              | Fixed file.cheap executable for webpage capture; may also come from `HITSPEC_FCHEAP_PATH`.                                |
| `--fcheap-stash-dir`      | file.cheap default | Optional fixed stash directory; may also come from `HITSPEC_FCHEAP_STASH_DIR`.                                            |

Tavily authentication comes only from the server process's `TAVILY_API_KEY`.
The key is never accepted as a tool argument or returned in output. The
file.cheap child receives an allowlisted environment that excludes this key.

## Limits and network policy

* The default body limit is 1 MiB (`--max-body-bytes`). Crossing it is an error,
  never a truncated success.
* The default request timeout is 30 seconds (`--timeout`).
* Direct URLs and saved requests allow only public HTTP(S) destinations by
  default. The initial host, redirects, DNS answers, and dial target are checked.
* URL credentials are rejected and response provenance omits URL query strings.
* A saved request that uses digest, AWS, or OAuth2 authentication, multipart
  data, or a configured proxy is rejected under the public-only policy. The
  proxy is not silently ignored.
* Redirect chains are limited to 10; callers can set `no_follow` to disable
  redirects entirely.

To test a local API, the person starting the server must grant that authority:

```bash theme={null}
hitspec mcp serve \
  --workspace "$PWD" \
  --allow-private-network
```

This operator grant also switches saved requests to the standard Hitspec HTTP
client, enabling configured proxies and digest, AWS, OAuth2, and multipart
request modes. Grant it only to agents and workspaces that need that authority.

`hitspec_fetch` and durable webpage capture are intentionally not marked
read-only because HTTP requests and artifact writes can have external effects.
The discovery-only `hitspec_search_web` tool is marked read-only and open-world.

## Approval boundaries

| Tool                      | Recommended policy                                                                                      |
| ------------------------- | ------------------------------------------------------------------------------------------------------- |
| `hitspec_search_web`      | Eligible for AUTO only when this exact bounded tool is explicitly allowlisted.                          |
| `hitspec_capture_webpage` | Treat as a public-network read plus durable write; allowlist only when both effects are approved.       |
| `hitspec_fetch`           | Keep approval-gated because callers can choose methods, headers, and bodies. It never persists content. |

AUTO never enables private-network access or relaxes URL, redirect, DNS, body,
or workspace checks.

## Direct MCP client configuration

```json theme={null}
{
  "mcpServers": {
    "hitspec": {
      "command": "hitspec",
      "args": [
        "mcp", "serve",
        "--workspace", "/absolute/api-workspace",
        "--search-provider", "tavily",
        "--fcheap-path", "/absolute/path/to/fcheap"
      ]
    }
  }
}
```

Inject `TAVILY_API_KEY` into the server process through the MCP host or tvault;
do not write its value into this configuration.

See [Agent artifact workflow](/integrations/agent-artifacts) for MCPHub, Local
Agent, and file.cheap composition.
