$npx -y skills add czlonkowski/n8n-skills --skill n8n-multi-instanceUse when an n8n-mcp account targets more than one n8n instance — i.e. the n8n_instances tool is available, the user mentions multiple n8n instances or environments (prod vs staging, several teams or clients), a workflow / datatable / credential / execution call returns an unexp
| 1 | # Working with multiple n8n instances over MCP |
| 2 | |
| 3 | When the `n8n_instances` tool is available, the user has **multi-instance mode** on: one MCP |
| 4 | connection can reach several n8n instances (e.g. `prod`, `staging`, or one per client/team). |
| 5 | Every other n8n tool (`n8n_get_workflow`, `n8n_list_workflows`, `n8n_update_partial_workflow`, |
| 6 | `n8n_manage_datatable`, `n8n_manage_credentials`, `n8n_executions`, `n8n_test_workflow`, …) runs |
| 7 | against **whichever instance this session is currently targeting**. There is no per-call instance |
| 8 | argument: you change the target only by switching. Target the wrong instance and a read returns the |
| 9 | wrong data and a write lands in the wrong place — usually with **no error** (the one exception is an |
| 10 | ambiguous credential write, which fails closed; see below). So target deliberately. |
| 11 | |
| 12 | If the `n8n_instances` tool is **not** present, the account is single-instance: ignore this skill |
| 13 | and use the n8n tools directly. |
| 14 | |
| 15 | ## Golden rules |
| 16 | |
| 17 | Six rules. Each prevents a class of silent misroute. |
| 18 | |
| 19 | 1. **Discover first.** Call `n8n_instances({mode:"list"})` before acting so you know the instance |
| 20 | names and which one is `current`. |
| 21 | 2. **Switch by name to your target** before doing work on a non-default instance: |
| 22 | `n8n_instances({mode:"switch", name:"<instance name>"})`. The match is case-insensitive. |
| 23 | 3. **Switch in its own turn.** Never put a `switch` and a dependent operation in the **same |
| 24 | parallel tool-call batch**. Calls in one batch have no guaranteed order, so the dependent call |
| 25 | can be resolved against the *previous* instance before the switch's session state is visible. |
| 26 | Switch, let it return, *then* operate. |
| 27 | 4. **Verify before high-stakes ops.** Immediately before creating/updating/deleting **credentials** |
| 28 | (and before destructive workflow edits), confirm `current` is the instance you intend — primary |
| 29 | check is `n8n_instances({mode:"list"})`. The system fail-closes only the *ambiguous* credential |
| 30 | case (rule 6); an explicit switch to the **wrong** instance still writes there silently, so this |
| 31 | check is on you. |
| 32 | 5. **An unexpected `NOT_FOUND` is almost always a wrong-instance misroute, not a deletion.** Don't |
| 33 | recreate the object. Re-check the current instance and retry (see Recovery). |
| 34 | 6. **On `INSTANCE_AMBIGUOUS`, switch on *this* session, then retry.** The system is refusing to |
| 35 | write a secret because this session never picked a target itself. Comply — run `switch` here to |
| 36 | confirm the instance, then retry the write. Don't work around it or retry blindly. |
| 37 | |
| 38 | ## Core workflow |
| 39 | |
| 40 | ``` |
| 41 | 1. n8n_instances({mode:"list"}) # see available[] + current + default |
| 42 | 2. n8n_instances({mode:"switch", name:"prod"}) # bind THIS session to "prod" |
| 43 | → returns { previous, current }; confirm current.name == "prod" |
| 44 | 3. (do your work) n8n_list_workflows / n8n_get_workflow / n8n_manage_datatable / ... |
| 45 | 4. Before a credential write or a delete: |
| 46 | n8n_instances({mode:"list"}) → re-confirm current, THEN n8n_manage_credentials({action:"create", ...}) |
| 47 | ``` |
| 48 | |
| 49 | To move to another instance, just `switch` again. The whole session follows the switch. |
| 50 | |
| 51 | ## The `n8n_instances` tool |
| 52 | |
| 53 | Two modes (`mode` is required and enum-validated): |
| 54 | |
| 55 | - `{mode:"list"}` → `{ current, default, available }`, no side effects. |
| 56 | - `current` and `default` are each one instance `{ id, name, url, isDefault }` (or `null`). |
| 57 | - `available` is every instance, each with an extra `isCurrent` boolean. Match by **`name`**; |
| 58 | never hard-code `id`. |
| 59 | - `{mode:"switch", name:"<name>"}` → `{ previous, current }`, and binds this session to the named |
| 60 | instance. `name` is case-insensitive. |
| 61 | |
| 62 | ### Error envelope (from the `n8n_instances` tool) |
| 63 | |
| 64 | Every error returns `{ error: "<CODE>", message, … }`. The ones you'll actually hit: |
| 65 | |
| 66 | | Code | When | What to do | |
| 67 | |---|---|---| |
| 68 | | `UNKNOWN_INSTANCE` | `name` matches no instance | Pick a name from the `available` list in the error payload and retry. | |
| 69 | | `NAME_REQUIRED` | `switch` with no `name` | Re-call with a `name` (the error lists the valid ones in `available`). | |
| 70 | | `MULTI_INSTANCE_DISABLED` | multi-instance mode is off | Th |