nodel-mcp
by mcartmel
README.md
# Nodel AI MCP Sidecar
Model Context Protocol sidecar for a local Nodel runtime. This release is an
independent unsupported preview (`v0.1.x`), is not affiliated with Museum Victoria,
and does **not** imply upstream endorsement.
The source and release repository is [`mcartmel/nodel-mcp`](https://github.com/mcartmel/nodel-mcp).
For compatibility, the v0.1 runtime, package, service, state paths, and release
artifacts remain named `nodel-ai`.
Clone the repository for development:
```sh
git clone https://github.com/mcartmel/nodel-mcp.git
```
Released archives and checksums are published on the [GitHub Releases](https://github.com/mcartmel/nodel-mcp/releases) page.
## Preview and Support Posture
- Supported shape: Linux + Node.js 22, with `systemd` as the supported service
manager.
- Support status: unsupported public preview, no SLA, and no commitment to review
issues or pull requests.
- Security posture: single-operator deployment patterns only (not multi-user,
multi-tenant).
- Compatibility stance: pre-1.0 MCP/HTTP interface; patch releases should avoid
intentional breaking changes, while minor releases may break with notes.
- Nodel baseline: 2.2.1.542 is the validated baseline compatibility target; other
versions are best effort until listed in the compatibility matrix.
## Quick Start (Read-Only by Default)
The v0.1 release path is a versioned GitHub Release archive. Extract it and run
the precompiled application without a build. Before starting, choose the Nodel
runtime to connect to and whether this sidecar should expose write tools.
1. Extract `nodel-ai-v<version>.tar.gz` and enter its directory.
2. Install production dependencies:
```sh
npm ci --omit=dev
```
3. Copy the example environment:
```sh
cp .env.example .env
```
4. Set the primary Nodel runtime in `.env`.
If Nodel and this sidecar run on the same host, keep the default:
```env
NODEL_BASE_URL=http://127.0.0.1:8085
```
If Nodel runs on another trusted host, replace it with that host's reachable
REST base URL, for example:
```env
NODEL_BASE_URL=http://nodel-host.example.internal:8085
```
`127.0.0.1` always means the sidecar's own network namespace. When running
the sidecar in a container or on another machine, use an address it can
actually reach. Do not point `NODEL_BASE_URL` at an untrusted service or
expose Nodel's REST port directly to an untrusted network.
5. Choose an access mode in `.env`.
No changes are required for read-only operation. To enable parameter,
binding, recipe/file, and action writes while retaining short-lived operator
approvals, set:
```env
NODEL_ENABLE_WRITES=true
NODEL_REQUIRE_WRITE_APPROVAL=true
```
Create and restart operations require one additional gate:
```env
NODEL_ENABLE_NODE_LIFECYCLE=true
```
Deletion is a separate, cumulative opt-in and requires all three gates:
```env
NODEL_ENABLE_WRITES=true
NODEL_ENABLE_NODE_LIFECYCLE=true
NODEL_ENABLE_DELETES=true
NODEL_REQUIRE_WRITE_APPROVAL=true
```
Keep `NODEL_REQUIRE_WRITE_APPROVAL=true` for normal operation. Approval IDs
are workflow controls, not authentication; keep the MCP listener loopback-only
or configure the token and reverse-proxy protections described below.
6. Start the service:
```sh
node dist/index.js
```
7. Confirm sidecar liveness and connectivity to the configured Nodel runtime:
```sh
curl -s http://127.0.0.1:8765/healthz
curl -s http://127.0.0.1:8765/readyz
```
`/healthz` confirms that the sidecar is running. `/readyz` confirms that it
can reach `NODEL_BASE_URL`. Add the configured bearer token when
`NODEL_MCP_TOKEN` is set.
For non-loopback access, use the tested Caddy renderer documented in
[`docs/operations.md`](docs/operations.md). Caddy is never bundled or
auto-installed; keep the out-of-band token in a `0600` `.env`.
**Host warning:** this host currently exposes plaintext/basic-auth `8080` and
unauthenticated `8085`. The host is not secure until those listeners are
firewalled or rebound; the renderer only warns.
The service is read-only by default. Write, lifecycle, and delete capabilities
are enabled independently and cumulatively through the gates above.
Release downloads also include `SHA256SUMS`, `SBOM.cdx.json`,
`dependency-licenses.json`, and `ARTIFACT-MANIFEST.json`. These files are both
inside the archive and attached as separate draft-release assets; checksums cover
all of them except `SHA256SUMS` itself.
## Required and Optional Environment
| Variable | Default | Purpose |
| ------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `NODEL_BASE_URL` | `http://127.0.0.1:8085` | Primary trusted Nodel REST base URL; defaults to Nodel in the sidecar's host/network namespace |
| `MCP_BIND_ADDRESS` | `127.0.0.1` | Listener bind address |
| `MCP_PORT` | `8765` | Listener port |
| `NODEL_MCP_TOKEN` | unset | Inbound bearer token for `/mcp` and `/readyz` |
| `MCP_ALLOWED_ORIGINS` | unset | Exact allowed browser Origins for HTTP requests |
| `NODEL_ALLOWED_RUNTIME_ORIGINS` | unset | Exact allowed runtime origins for explicit `runtimeUrl` operations. The `NODEL_BASE_URL` origin is always allowed. |
| `NODEL_STATE_DIR` | `.state` | Persistent approval/audit/backup state |
| `NODEL_ENABLE_WRITES` | `false` | Enable maintenance writes/actions |
| `NODEL_ENABLE_NODE_LIFECYCLE` | `false` | Enable `create_node`/`restart_node` when writes are enabled |
| `NODEL_ENABLE_DELETES` | `false` | Enable `delete_node` with lifecycle + writes |
| `NODEL_REQUIRE_WRITE_APPROVAL` | `true` | Require workflow approval ids for writes |
Set additional request/retention limits as needed:
- `MCP_REQUEST_BODY_LIMIT_BYTES` (default: 1048576)
- `NODEL_AUDIT_MAX_BYTES` (default: 10485760)
- `NODEL_AUDIT_RETENTION_FILES` (default: 5)
- `NODEL_BACKUP_RETENTION_DAYS` (default: 30)
- `NODEL_BACKUP_RETENTION_PER_NODE_KIND` (default: 50)
## Access Modes Reference
### Read-only
```sh
NODEL_ENABLE_WRITES=false
NODEL_ENABLE_NODE_LIFECYCLE=false
NODEL_ENABLE_DELETES=false
NODEL_REQUIRE_WRITE_APPROVAL=true
```
### Writes and actions
```sh
NODEL_ENABLE_WRITES=true
NODEL_ENABLE_NODE_LIFECYCLE=false
NODEL_ENABLE_DELETES=false
NODEL_REQUIRE_WRITE_APPROVAL=true
```
### Writes plus create/restart
```sh
NODEL_ENABLE_WRITES=true
NODEL_ENABLE_NODE_LIFECYCLE=true
NODEL_ENABLE_DELETES=false
NODEL_REQUIRE_WRITE_APPROVAL=true
```
### Delete mode
```sh
# Writes + lifecycle + deletes + approval must all be enabled for delete mode
NODEL_ENABLE_WRITES=true
NODEL_ENABLE_NODE_LIFECYCLE=true
NODEL_ENABLE_DELETES=true
NODEL_REQUIRE_WRITE_APPROVAL=true
```
Writes remain experimental and require operator workflow discipline.
## Trusted Network Access Model
- Loopback use (`127.0.0.1`) is the direct mode. For any non-loopback bind,
configure a high-entropy `NODEL_MCP_TOKEN` and set a strict
`MCP_ALLOWED_ORIGINS` allowlist.
- The sidecar rejects arbitrary caller-supplied hostnames and only contacts
configured/local-discovered endpoints.
- Use a reverse proxy for transport hardening where needed; this component does
not provide TLS termination.
If `NODEL_MCP_TOKEN` is present, send this header on MCP requests:
```http
Authorization: Bearer <NODEL_MCP_TOKEN>
```
### MCP endpoint behavior
- `GET /healthz`: unauthenticated liveness with minimal fields (`ok`, `version`).
- `GET /readyz`: protected Nodel readiness probe.
- `POST /mcp`: MCP Streamable HTTP endpoint behind token/origin policies.
When a token is configured, unauthenticated `/mcp` and `/readyz` requests must
return `401`; `/healthz` is the unauthenticated `200` preflight.
## Approval and Write Flow
This project treats write approval as a human workflow control, not a security
boundary. Operational flow is:
1. `read/propose` or `dryRun`
2. Operator review and confirmation
3. `nodel.approve_write` as a fallback when MCP elicitation is unavailable
4. Apply tool with `approvalId`
5. Read-back / readiness verification based on tool capability
`nodel.request_write_approval` is the MCP-native path when supported by the
client and falls back to manual confirmation guidance when unsupported.
## Operations and Service Deployment
A release may be run directly (`node dist/index.js`) or under `systemd`.
### Recommended service layout
The system installer supports configurable paths:
- App directory: configurable (example `/opt/nodel-ai`)
- Env file: configurable (example `/etc/nodel-ai.env`)
- State directory: configurable (example `/var/lib/nodel-ai`)
The user and system installers render units with configurable paths and service
account. User defaults use the extracted directory, `.env`, and `.state`; system
defaults use `/opt/nodel-ai`, `/etc/nodel-ai.env`, and `/var/lib/nodel-ai`.
- `scripts/install-systemd-user.sh`
- `scripts/install-systemd-system.sh`
For service guidance and recovery steps (backups, log interpretation, upgrade,
rollback, health/readiness, and turning writes back off), see
[`docs/operations.md`](docs/operations.md).
## Tools
The README no longer maintains a manual tool list. Use the generated
reference to avoid drift:
- [`docs/tool-reference.generated.md`](docs/tool-reference.generated.md)
The list is generated from canonical tool definitions and includes capability,
stability, and gate information.
## MCP Client Configuration
Point MCP clients at `http://127.0.0.1:8765/mcp` for local testing.
### Minimal JSON config example
```json
{
"mcp": {
"nodel": {
"type": "remote",
"url": "http://127.0.0.1:8765/mcp"
}
}
}
```
Add bearer auth in the MCP client only when `NODEL_MCP_TOKEN` is configured.
Codex clients should use `bearer_token_env_var = "NODEL_MCP_TOKEN"`, never a
literal token in client configuration.
## Documentation
- [`docs/architecture.md`](docs/architecture.md): trust boundaries and contract
model
- [`docs/security-model.md`](docs/security-model.md): security assumptions and
failure model
- [`docs/operations.md`](docs/operations.md): operational runbooks
- [`docs/operations.md#trusted-reverse-proxy-tls-example-caddy`](docs/operations.md#trusted-reverse-proxy-tls-example-caddy): tested Caddy renderer and rollout workflow
- [`docs/migration-v0.1.md`](docs/migration-v0.1.md): migration from an earlier local build
to `v0.1.x`
- [`docs/releasing.md`](docs/releasing.md): maintainer release procedure
- [`SUPPORT.md`](SUPPORT.md), [`SECURITY.md`](SECURITY.md),
[`CHANGELOG.md`](CHANGELOG.md),
[`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md)
## Compatibility and Compatibility Notes
Before `1.0.0`, patch releases should avoid intentional breaking changes.
Before enabling writes, complete the migration checklist in
[`docs/migration-v0.1.md`](docs/migration-v0.1.md).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues