Files
computer-playbook/roles/web-app-flowise/tasks/utils/mcp.yml
kevinveenbirkenbach a8f0c74fd6 fix(flowise): tolerate a provider that has not come up yet
Fediwall#1 of run 33923190220 dies in flowise's MCP registry reconcile:
"FAILED authorizing web-app-prometheus: 400 ... Failed to connect to Custom
MCP server: SSE error: request to http://prometheusmcp:8080/mcp failed,
reason: connect ECONNREFUSED", thirty retries apart. web-app-prometheus sits
in that round's preload closure, so discovery offers it, but the log carries
no web-app-prometheus task at all: the role never ran and its sidecar never
served.

Discovery cannot see that. endpoint_unreachable rejects a provider whose
declaration lacks a port or path, a static check; nothing probes whether the
provider is listening. The platform answers runtime absence with
MCP_RECONCILE_STRICT instead, and 001aeda0b1 states the rule: a rejection
"stays non-fatal in the app pass, where a provider may still be waiting", and
"becomes fatal at the reconciliation stage, where every provider has already
run". sys-svc-mcp-reconcile sets the flag true around its loop and false after;
the group_vars default is false.

flowise's registry task never consulted it, so its own early pass failed the
play on a provider that the later convergence would have reached. It now fails
only when strict, which is exactly the reconciliation stage. The retries stay,
so a provider that appears late in the same pass is still picked up, and the
password and identity tasks above keep failing hard because they address
flowise's own container rather than a foreign one.

Two client roles that never had this problem show the shape: web-app-hermes
and web-app-openclaw call the same file from their own 00_core.yml and carry
no retries/until at all. An earlier attempt in this series deleted the call
from flowise and openwebui as a duplicate of the central stage; fifteen roles
make that call, hermes and openclaw among them, so the duplication is the
convention and that change was withdrawn.
2026-09-08 19:57:12 +02:00

94 lines
3.2 KiB
YAML

---
- name: "🔍 Resolve {{ application_id }} hosting node + container id"
ansible.builtin.include_tasks: "{{ lookup('path_absolute', 'roles/sys-svc-compose/tasks/utils/swarm/resolve_host_cid.yml') }}"
vars:
resolve_service_key: "{{ entity_name }}"
resolve_output_prefix: FLOWISE
resolve_compose_cid: "{{ FLOWISE_CONTAINER }}"
- name: "🔐 Converge the password of the Flowise MCP API identity"
ansible.builtin.command:
argv:
- container
- exec
- -i
- -e
- "NODE_PATH={{ FLOWISE_NODE_MODULES }}"
- -e
- "FLOWISE_ADMIN_EMAIL={{ FLOWISE_API_BOT_USER.email }}"
- -e
- "FLOWISE_ADMIN_PASSWORD={{ FLOWISE_API_BOT_PASSWORD }}"
- "{{ FLOWISE_LOCAL_CID }}" # nocheck: container-exec-resolver
- node
- "-"
stdin: "{{ lookup('file', 'javascript/reconcile/identity_password.js') }}"
register: flowise_mcp_password
retries: 30
delay: 10
until: flowise_mcp_password.rc == 0
changed_when: flowise_mcp_password.stdout.startswith('CHANGED')
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
delegate_to: "{{ FLOWISE_HOST_NODE }}"
run_once: true
- name: "🔑 Mint the scoped Flowise API identity for the MCP registry"
ansible.builtin.command:
argv:
- container
- exec
- -i
- -e
- "FLOWISE_BASE=http://localhost:{{ FLOWISE_PORT_INTERNAL }}"
- -e
- "FLOWISE_ADMIN_EMAIL={{ FLOWISE_API_BOT_USER.email }}"
- -e
- "FLOWISE_ADMIN_PASSWORD={{ FLOWISE_API_BOT_PASSWORD }}"
- -e
- "FLOWISE_ADMIN_NAME={{ FLOWISE_API_BOT_USER.username }}"
- -e
- "FLOWISE_API_KEY_NAME={{ FLOWISE_MCP_API_KEY_NAME }}"
- "{{ FLOWISE_LOCAL_CID }}" # nocheck: container-exec-resolver
- python3
- "-"
stdin: "{{ lookup('file', 'python/mint_mcp_api_key.py') }}"
register: flowise_mcp_identity
retries: 30
delay: 10
until: flowise_mcp_identity.rc == 0
changed_when: flowise_mcp_identity.stdout.startswith('CHANGED')
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
delegate_to: "{{ FLOWISE_HOST_NODE }}"
run_once: true
- name: "🔌 Reconcile the custom MCP server registry"
ansible.builtin.command:
argv:
- container
- exec
- -i
- -e
- "FLOWISE_BASE=http://localhost:{{ FLOWISE_PORT_INTERNAL }}"
- -e
- "FLOWISE_API_KEY={{ (flowise_mcp_identity.stdout_lines | last | from_json).api_key }}"
- -e
- "FLOWISE_WORKSPACE={{ (flowise_mcp_identity.stdout_lines | last | from_json).workspace_id }}"
- -e
- "FLOWISE_MCP_DESIRED={{ FLOWISE_MCP_DESIRED | to_json }}"
- -e
- "FLOWISE_MCP_TRANSPORT={{ FLOWISE_MCP_TRANSPORT }}"
- -e
- "FLOWISE_MCP_FIXTURE={{ FLOWISE_MCP_FIXTURE | to_json }}"
- "{{ FLOWISE_LOCAL_CID }}" # nocheck: container-exec-resolver
- python3
- "-"
stdin: "{{ lookup('file', 'python/reconcile/mcp_servers.py') }}"
register: flowise_mcp_registry
retries: 30
delay: 10
until: flowise_mcp_registry.rc == 0
failed_when: flowise_mcp_registry.rc != 0 and (MCP_RECONCILE_STRICT | bool)
changed_when: flowise_mcp_registry.stdout.startswith('CHANGED')
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
delegate_to: "{{ FLOWISE_HOST_NODE }}"
run_once: true