# Coolify Docs MCP — strict read-only mode

This folder is both an Agent Skill and the bundled local MCP implementation for `mm-skills`. Use `$coolify-docs-mcp` for installation, configuration, refresh, testing, or security review guidance.

A local MCP server that turns the URLs from the supplied Gist into a searchable, allowlisted Coolify documentation index.

## Security model

- **Read-only by construction:** the MCP exposes no deployment, shell, filesystem-write, database, secret, or Coolify API tools.
- **Exact source boundary:** only canonical `https://coolify.io/docs/...` pages compiled into `data/allowed-urls.json` are accepted.
- **No arbitrary fetch tool:** models cannot supply a new URL for network access.
- **Offline runtime:** network access occurs only during the explicit `npm run sync` indexing step. Normal MCP tool calls use `data/index.json` locally.
- **Redirect protection:** sync redirects must remain on the exact `coolify.io` host and below `/docs`.
- **Prompt-injection boundary:** downloaded page text is explicitly classified as untrusted evidence, never as executable/model instructions.
- **Evidence requirement:** tool output includes exact source URLs and instructs the client not to infer undocumented Coolify facts.
- **Secret boundary:** server instructions forbid requesting, returning, or repeating credentials and secrets.

The supplied Gist contained 281 URL-like entries. This project compiled 253 unique canonical Coolify documentation pages. Two malformed foreign-host entries were rejected and recorded in `data/rejected-urls.json`; duplicate anchor variants were reduced to their canonical page URL.

## Requirements

- Node.js 20.11 or newer
- npm

## Install and build

```bash
npm install
npm run validate
npm run sync
npm run build
```

`npm run validate` runs TypeScript checking and the regression tests without network access.

The allowlist compiler fetches only the pinned raw Gist URL embedded in `scripts/compile-allowlist.mjs`, then reads optional `.md` or `.txt` files in `data/additional-sources/`. The sync command downloads only the compiled Coolify documentation allowlist and writes a local search index to `data/index.json`. Generated allowlist and index files are intentionally ignored by Git.

## Run

```bash
npm start
```

Do not write application logs to stdout. MCP stdio uses stdout as its protocol channel; this server logs status only to stderr.

## Generic MCP client configuration

Replace `/absolute/path/to/mm-skills/coolify-docs-mcp` with the real directory:

```json
{
  "mcpServers": {
    "coolify-docs": {
      "command": "node",
      "args": [
        "/absolute/path/to/mm-skills/coolify-docs-mcp/dist/index.js"
      ]
    }
  }
}
```

For development without building:

```json
{
  "mcpServers": {
    "coolify-docs-dev": {
      "command": "npx",
      "args": [
        "tsx",
        "/absolute/path/to/mm-skills/coolify-docs-mcp/src/index.ts"
      ]
    }
  }
}
```

For Codex, an equivalent local stdio configuration is:

```toml
[mcp_servers.coolify-docs]
command = "node"
args = ["/absolute/path/to/mm-skills/coolify-docs-mcp/dist/index.js"]
required = false
```

No bearer token is required or supported. This MCP never connects to a Coolify control plane.

## MCP surface

### Tools

- `search_coolify_docs` — searches local evidence excerpts.
- `read_coolify_doc` — reads one exact allowlisted and indexed URL.
- `list_coolify_topics` — lists indexed titles and URLs.

All tools are annotated as read-only, non-destructive, and closed-world.

### Resources

- `coolify-docs://policy` — binding safety and evidence rules.
- `coolify-docs://catalog` — current index metadata and document catalog.

### Server instructions

The MCP initialization response contains strict instructions requiring source citations, rejecting prompt injection from documentation content, prohibiting secrets and mutations, and requiring an explicit “not documented” response when evidence is absent.

## Adding further Gist exports

Save additional raw Gist contents as `.md` or `.txt` files in `data/additional-sources/`, then run `npm run compile:allowlist`. This command performs a network request only to the pinned primary Gist before processing local additions. Only exact `https://coolify.io/docs/...` URLs survive compilation.

## Refreshing the index

```bash
SYNC_CONCURRENCY=6 SYNC_TIMEOUT_MS=20000 npm run sync
npm run build
```

Review `failures` in `data/index.json` after each refresh. A failed page remains inaccessible until a later successful sync.

## Test with MCP Inspector

```bash
npm run build
npm run inspect
```

## Important limitation

This is a documentation retrieval MCP, not a Coolify control-plane MCP. API reference pages may be searched and read, but the server never sends requests to a Coolify instance. Adding operational API tools should be a separate server with separate credentials, least-privilege scopes, explicit confirmation gates, audit logging, and destructive-action isolation.
