This repository is public. Native secret scanning, push protection, private vulnerability reporting, CodeQL, and branch protection (four required checks, no force pushes or branch deletion) are all enabled — see .github/PUBLIC_RELEASE_CHECKLIST.md for exactly what was verified and when.
A governed MCP control plane for discovering, validating, executing, and debugging approved n8n workflows from Claude, ChatGPT, Codex, and compatible MCP clients.
Pre-1.0, deliberately: v1.0.0 waits on two maintainer-only actions (a real hosted
OpenAI connector call, and PyPI trusted-publisher registration), not on unfinished
engineering. Full detail below.
Status: v1 release candidate, public repository, pre-release GitHub tag — deliberately not final, not abandoned. All nine product phases are implemented and the local release gate is green: registry, MCP server (stdio + Streamable HTTP), n8n integration, execution, and the full operator CLI (
db,registry,operations,audit,health,serve). The reproducible, Docker-based live-n8n harness (docs/LIVE_N8N_TESTING.md) has been run for real (2026-08-28, 8/8 passed). A GitHub Release exists as a marked pre-release. Exactly two named things block cutting a final, non-candidatev1.0.0, both requiring the maintainer's own action rather than further engineering: (1) a real hosted OpenAI connector call, against a public TLS endpoint with real credentials — the protocol shape is already automated in CI (tests/integration/test_mcp_http_openai_compat.py), but an actual hosted request has never been made; (2) a PyPI "trusted publisher" registered for this repository — a human, PyPI-account-holder action — before which.github/workflows/release.yml'spypijob stays disabled (if: false) by design. Neither is a code change. See docs/BUILD_PLAN.md section 12 for the phase checklist, docs/V1_LIMITATIONS.md for what v1 deliberately does not do, and CHANGELOG.md for the full history.Tag naming has drifted and the final tag should fix it deliberately: the three release-candidate tags cut so far are
v1.0.0-rc1,v1.0.0-rc2, thenv1.0.0rc3— the third dropped the hyphen beforerc. PEP 440 normalizes both forms to the same version, but they are not guaranteed to sort identically in every tool that compares tags as plain strings rather than parsing them as PEP 440 versions. The finalv1.0.0tag carries norcsuffix at all, so this specific ambiguity resolves itself then — but if another release candidate is cut before that, use the hyphenated form (v1.0.0-rc4) to match the first two, not the third.v2 (organizations, RBAC, environments, team approvals, governed retry, structural diffs, metrics/audit query, alert hooks, external audit anchoring) is merged and individually tested stage by stage — docs/V2_TRACEABILITY.md tracks each one. Stage 11's integration, migration, security, and load review is complete: it found and fixed a real cross-organization audit-log isolation bug (confirmed exploitable, now closed and regression-tested), and it left a narrower, related finding open as documented residual scope. See docs/STAGE_11_RELEASE_REPORT.md for the full findings and go/no-go recommendation — this stage produces a recommendation, not a release.
| Client / target | Transport | Evidence |
|---|---|---|
| MCP stdio clients (Claude Desktop and similar) | stdio | ✅ Automated on every CI push — scripts/release_smoke.sh runs a full MCP session against the built wheel (reference mcp Python client v2.1.1, last verified 2026-08-28) |
| Generic MCP client | Streamable HTTP | ✅ Built-wheel MCP session verified (phase 9, one-time manual run) |
OpenAI Responses API mcp tool shape |
Streamable HTTP | 🟢 Automated on every CI test run — a real MCP session against the documented Authorization+Origin headers shape, with bearer/Origin enforcement exercised (tests/integration/test_mcp_http_openai_compat.py); 🟡 an actual hosted OpenAI request is still pending a public TLS endpoint and credentials |
| n8n 2.35.7 self-hosted | REST + webhook | ✅ Empirically verified; the repeatable Docker harness has been run for real (2026-08-28, 8/8 passed) — see docs/COMPATIBILITY_MATRIX.md |
"MCP session verified" always means the reference mcp protocol client, not a
vendor's own GUI application — Claude Desktop's own process has not been separately
launched in any of this testing. See
examples/mcp-clients/README.md and
scripts/mcp_session_smoke.py for exactly what each
check covers.
n8n Operator is for GTM engineers, revenue-operations teams, and agent builders who want an AI client to run a small, reviewed set of automations—not inherit unrestricted access to an entire n8n instance. It is especially useful when a workflow can write to a CRM, contact a customer, mutate production data, or otherwise needs an approval and an audit trail.
flowchart LR
Client["Claude, ChatGPT, Codex<br/>or another MCP client"]
Operator["n8n Operator<br/>validate · preflight · approve · audit"]
Registry["Reviewed workflow registry"]
Human["Human approver"]
N8N["n8n workflow engine"]
Client -->|"MCP tool call"| Operator
Registry -->|"allowlisted contract"| Operator
Operator -->|"decision context"| Human
Human -->|"approve / reject"| Operator
Operator -->|"one governed dispatch"| N8N
N8N -->|"correlated result"| Operator
Operator -->|"redacted result"| Client
n8n is an excellent workflow engine and a poor agent surface. Pointing an LLM at a raw n8n instance hands it an unbounded, unversioned, credential-bearing remote-execution primitive: the workflow list is discovered at runtime, the input contract is implicit in the node graph, failures surface as raw execution JSON, and every webhook is a live production side effect.
n8n Operator is the place to stand between "the model decided to do a thing" and "the thing happened."
| Discover | Only workflows an operator explicitly registered, with human-authored descriptions, risk classes, and input schemas. |
| Validate | Arguments checked against a declared JSON Schema before anything reaches n8n. |
| Preflight | Target verified live, active, and unmodified since registration, before approval is sought — and again immediately before dispatch. |
| Execute | An explicit prepare → approve → execute lifecycle with single-use handles, idempotency, and a durable audit trail. |
| Debug | Redacted, structured execution traces — enough to diagnose, not enough to exfiltrate. |
| Operate | A CLI for approval, cancellation, history, and a chain-verifiable audit export — no browser required. |
- Expose a workflow that is not in the registry, however live it is on the instance.
- Accept a raw n8n workflow ID, URL, or payload in any tool argument.
- Return a credential, token, n8n ID, or instance URL in any tool result.
- Let an MCP client approve its own operation — approval is out-of-band, always.
- Retry anything automatically. Ambiguous outcomes surface as
UNKNOWNfor a human. - Edit workflows (v1 and v2). Authoring stays in the n8n UI.
Full list with the "why" behind each one: docs/WHAT_THIS_REFUSES_TO_DO.md.
Seven annotated, sanitized GTM automation patterns — read-only reporting, lead enrichment, CRM upsert, lead routing, campaign audience sync, customer communication, and data-quality exception reporting — plus real, runnable versions of the three v2 user journeys in docs/ARCHITECTURE.md section 11. No credentials or live n8n instance needed to try them:
n8n-operator registry validate --path examples/registry/starter-kits/gtm-starter-kits.yamlSee docs/GTM_STARTER_KITS.md for the full tour, and docs/OPERATOR_GUIDE.md for the timed, clean-machine path from this command to a working local staging environment (measured under two minutes).
Requires Python 3.12. Not on PyPI yet (deliberately — see the status note above); install from the tagged release:
git clone --branch v1.0.0rc3 https://github.com/katekruger/n8n-operator.git
cd n8n-operator
uv tool install .Contributors can instead run commands from the checkout with
uv run n8n-operator ....
1. Initialize the database. This also seeds the v1 default principal — do this before anything else.
n8n-operator db init2. Write or copy a registry. examples/registry/workflows.example.yaml
is a fully annotated starting point; docs/WORKFLOW_REGISTRY.md
is the authoring reference. Validate before loading:
n8n-operator registry validate --path ./workflows.yaml
n8n-operator registry reload --path ./workflows.yaml3. Configure the n8n connection (only needed for serve/health, not for db/
registry/operations/audit):
export N8N_OPERATOR_N8N_BASE_URL=https://your-n8n-instance.example.com
export N8N_OPERATOR_N8N_API_KEY=... # or env:NAME / keyring:SERVICE/ACCOUNT
n8n-operator health # confirms the instance is reachable4. Run the server.
n8n-operator serve stdio # Claude Desktop and any subprocess-launching MCP host
n8n-operator serve http # a remote Streamable HTTP MCP client (see below)No n8n instance yet? scripts/demo.sh walks through discovery,
validation, and the audit trail against a scratch database — nothing above step 3
required. Run it:
scripts/demo.shexamples/mcp-clients/ has ready-to-copy configs for Claude
Desktop (stdio) and a generic remote Streamable HTTP client. Both transports were
verified against a real build; hosted OpenAI connector verification is still pending. See
examples/mcp-clients/README.md for the details each
one needs (a non-loopback serve http bind requires a bearer token and an Origin
allowlist — boundary B9 — the server refuses to start otherwise).
Anything above read_only needs a human decision before it runs. The CLI is the
canonical channel (ADR-010):
n8n-operator operations list # what's pending
n8n-operator operations approve <operation_id> # renders the full decision context firstn8n-operator serve approval runs a convenience loopback web page over the same
decision — never the only way to decide an operation.
| Document | What it covers |
|---|---|
| BUILD_PLAN.md | Normative. Product definition, version boundaries, state machine, registry schema, tool inventory, storage model, security boundaries, tests, acceptance criteria, phase checklist. |
| ARCHITECTURE.md | Components, layering, request flows, data trust, persistence, configuration. |
| THREAT_MODEL.md | Assets, trust boundaries, STRIDE analysis, LLM-specific threats, residual risks. |
| WORKFLOW_REGISTRY.md | How to register a workflow, and how to classify it correctly. |
| MCP_TOOLS.md | Normative for tool arguments, results, and the error taxonomy. |
| N8N_COMPATIBILITY.md | Empirical n8n API findings behind ADR-008/ADR-009. |
| COMPATIBILITY_MATRIX.md | Tested n8n versions and feature support, at a glance. |
| LIVE_N8N_TESTING.md | How to run the real-instance compatibility gate. |
| V1_LIMITATIONS.md | Plain-language index of what v1 deliberately doesn't do. |
| RECONCILING_UNKNOWN.md | Step-by-step manual procedure for resolving an UNKNOWN operation. |
| GTM_STARTER_KITS.md | Annotated starter-kit registry, real journey walkthroughs, and what to customize before production use. |
| OPERATOR_GUIDE.md | Clean-machine path from a fresh checkout to a working local staging environment, timed. |
| APPROVER_GUIDE.md | What to read before deciding, self-approval and quorum rules, the web approval page. |
| LEAST_PRIVILEGE.md | Three worked role/scope policy packs — startup, centralized RevOps, Series C multi-approver. |
| MCP_CLIENT_RECIPES.md | The literal tool-call JSON for every step of a client session, using only the 20-tool surface. |
| TROUBLESHOOTING.md | Symptom-to-cause decision tree. |
| WHAT_THIS_REFUSES_TO_DO.md | Every deliberate refusal, why, and which threat it closes. |
| RELEASE_ROLLBACK.md | How to roll back a bad GitHub Release or yank a bad PyPI package. |
| SECURITY.md | How to report a vulnerability. |
| CONTRIBUTING.md | Development setup, the PR gate, and house conventions. |
| ADR | Decision |
|---|---|
| 001 | Portable, transport-agnostic core; MCP is an adapter |
| 002 | Default-deny YAML workflow registry |
| 003 | Operation handles as single-use capabilities |
| 004 | SQLite in v1, PostgreSQL in v2, one schema throughout |
| 005 | No automatic retries in v1 |
| 006 | Server-owned n8n credentials |
| 007 | Deterministic enforcement before LLM judgment |
| 008 | Conservative workflow-definition canonicalization |
| 009 | Dispatch correlation and indeterminate outcomes |
| 010 | Approval delivery and expiry semantics |
| 011 | Core argument limits and idempotency namespaces |
| 012 | Governed retry and external audit anchoring |
| 013 | Organization is the tenant; membership, not principal attribute |
| 014 | Operator validates OIDC bearer tokens itself, no proxy delegation |
| 015 | Four-role RBAC: workflow-scope AND environment-scope AND capability |
| 016 | Environment overlays adjust reach and gating only, never the contract |
| 017 | Team approval quorum: snapshotted eligibility, no self-approval |
| 018 | Notification/alert delivery: at-least-once, dedup, content-free payloads |
| 019 | Metrics pre-filtered by scope before aggregation, no low-sample percentiles |
| 020 | Keep single-use token-link approval, no OIDC-authenticated web session |
| 021 | External anchoring: protects DB-only tampering, publish is manual |
v1 — single user, one n8n instance, SQLite, stdio and remote Streamable HTTP MCP, CLI, YAML registry, read-only inspection, input validation, preflight, prepare/approve/execute, local approval page, idempotency, audit log. No retries, no workflow editing.
v2 — PostgreSQL, multiple users and organizations, OAuth/OIDC, RBAC, multiple n8n environments, team approvals, monitoring, governed retries, workflow definition diffs.
v3 — declarative workflow compiler, evaluation lab, governed workflow changes, remediation assistant, template library, enterprise controls.
Full boundary table: BUILD_PLAN.md section 3. Known v1-specific gaps and their practical consequences: V1_LIMITATIONS.md.
Requires Python 3.12 and uv. See CONTRIBUTING.md for the full guide; the short version:
uv sync --all-extras --devuv run pytest -m "not live_n8n"uv run ruff check . && uv run ruff format --check . && uv run mypyuv run python scripts/check_docs_consistency.pyThe last command enforces that the documentation set agrees with itself and with the repository tree — state names, transition IDs, tool inventory, acceptance criteria, cross-document links, and the published file tree. It runs in CI and as a contract test.
Apache-2.0. See LICENSE.