From 5ae478272f037f32ef17577d0c00522907c24477 Mon Sep 17 00:00:00 2001 From: admin Date: Sat, 29 Aug 2026 20:31:09 -0700 Subject: [PATCH 1/3] =?UTF-8?q?Add=20FlowAgent=20MCP=20image=20(Dockerfile?= =?UTF-8?q?=20+=20entrypoint)=20=E2=80=94=20build=20only,=20not=20wired=20?= =?UTF-8?q?to=20any=20stack=20yet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Part 1/3 of FlowAgent (Power Automate MCP) integration into the mcpo service (NOT mcpo-critical). This PR only adds the image build artifacts; it does not modify ai.yaml, mcpo/config.json, or the Woodpecker deploy pipeline, so no live service is affected by merging this alone. Background: mcpo/config.json previously had a dead/abandoned "powerautomate" entry (npm package powerautomate-mcp, never onboarded to the secrets pipeline) that will be replaced by this in a follow-up PR. This build produces a self-contained image with: - azure-cli, for non-interactive `az login --service-principal` at container start (see entrypoint.sh) - FlowAgent's self-contained MCP engine (server/mcp.mjs from microsoft/power-platform-skills — official MIT-licensed Microsoft repo), pinned via FLOWAGENT_REF build arg rather than tracking `main`, so builds stay reproducible until deliberately bumped. Requires (added in follow-up PRs, not yet live): - Woodpecker secrets: flowagent_azure_client_id, flowagent_azure_tenant_id, flowagent_azure_client_secret (Pattern C, Docker secrets via _FILE) - Azure AD App Registration with Power Automate + Dataverse permissions, admin-consented (manual, outside GitOps — see secrets/flowagent.secrets.example) --- mcpo/flowagent/Dockerfile | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 mcpo/flowagent/Dockerfile diff --git a/mcpo/flowagent/Dockerfile b/mcpo/flowagent/Dockerfile new file mode 100644 index 0000000..edfa2d2 --- /dev/null +++ b/mcpo/flowagent/Dockerfile @@ -0,0 +1,21 @@ +FROM ghcr.io/open-webui/mcpo:main + +# Azure CLI — required for non-interactive service-principal auth +# (`az login --service-principal`) performed by entrypoint.sh at container +# start. FlowAgent's auth model is Azure CLI + MSAL; see +# https://github.com/microsoft/power-platform-skills/blob/main/plugins/power-automate/references/connection-patterns.md +RUN apk add --no-cache py3-pip curl \ + && pip install --no-cache-dir --break-system-packages azure-cli + +# FlowAgent self-contained MCP bundle (stdio transport, all tools inlined, +# Node 18+ only — no npm install / remote host needed at runtime). +# Pinned to a ref (commit SHA or tag), NOT `main`, for reproducible builds. +# Bump deliberately via PR when upstream ships updates: +# https://github.com/microsoft/power-platform-skills/tree/main/plugins/power-automate/server +ARG FLOWAGENT_REF=main +RUN mkdir -p /app/flowagent \ + && curl -fsSL "https://raw.githubusercontent.com/microsoft/power-platform-skills/${FLOWAGENT_REF}/plugins/power-automate/server/mcp.mjs" \ + -o /app/flowagent/mcp.mjs + +COPY entrypoint.sh /app/flowagent/entrypoint.sh +RUN chmod +x /app/flowagent/entrypoint.sh -- 2.54.0 From 2ca0643439787708d31b5ae4fa7cd89ef6118c70 Mon Sep 17 00:00:00 2001 From: admin Date: Sat, 29 Aug 2026 20:31:10 -0700 Subject: [PATCH 2/3] Add FlowAgent entrypoint: non-interactive az login via Pattern C secrets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reads the three _FILE-convention secrets (mounted by Swarm from Docker secrets provisioned by Woodpecker — see secrets/flowagent.secrets.example), performs `az login --service-principal`, then execs into whatever command mcpo invokes (node /app/flowagent/mcp.mjs). No secret value is ever written to disk outside the ephemeral Docker secret mount, logged, or baked into the image. --- mcpo/flowagent/entrypoint.sh | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 mcpo/flowagent/entrypoint.sh diff --git a/mcpo/flowagent/entrypoint.sh b/mcpo/flowagent/entrypoint.sh new file mode 100644 index 0000000..bea9d68 --- /dev/null +++ b/mcpo/flowagent/entrypoint.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# FlowAgent MCP entrypoint — non-interactive Azure service-principal login. +# +# Expects three env vars pointing at Docker secret files (Pattern C, +# _FILE convention, provisioned by Woodpecker — never hand-typed): +# FLOWAGENT_AZURE_CLIENT_ID_FILE +# FLOWAGENT_AZURE_TENANT_ID_FILE +# FLOWAGENT_AZURE_CLIENT_SECRET_FILE +# +# On success, execs into the real command (node /app/flowagent/mcp.mjs), +# replacing this shell so mcpo's stdio pipe talks directly to the MCP process. +set -eu + +: "${FLOWAGENT_AZURE_CLIENT_ID_FILE:?FLOWAGENT_AZURE_CLIENT_ID_FILE not set}" +: "${FLOWAGENT_AZURE_TENANT_ID_FILE:?FLOWAGENT_AZURE_TENANT_ID_FILE not set}" +: "${FLOWAGENT_AZURE_CLIENT_SECRET_FILE:?FLOWAGENT_AZURE_CLIENT_SECRET_FILE not set}" + +CLIENT_ID="$(cat "$FLOWAGENT_AZURE_CLIENT_ID_FILE")" +TENANT_ID="$(cat "$FLOWAGENT_AZURE_TENANT_ID_FILE")" +CLIENT_SECRET="$(cat "$FLOWAGENT_AZURE_CLIENT_SECRET_FILE")" + +az login --service-principal \ + -u "$CLIENT_ID" \ + -p "$CLIENT_SECRET" \ + --tenant "$TENANT_ID" \ + --output none + +unset CLIENT_SECRET + +exec "$@" -- 2.54.0 From f7c8ebc05ef02093014a3c8d331f0e3235f2f9c8 Mon Sep 17 00:00:00 2001 From: admin Date: Sat, 29 Aug 2026 20:31:11 -0700 Subject: [PATCH 3/3] Add flowagent secrets reference doc (placeholders only, no real values) Documents the Pattern C secrets needed once mcpo/config.json + ai.yaml are updated in a follow-up PR to actually wire FlowAgent into the mcpo service. --- secrets/flowagent.secrets.example | 53 +++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 secrets/flowagent.secrets.example diff --git a/secrets/flowagent.secrets.example b/secrets/flowagent.secrets.example new file mode 100644 index 0000000..171205b --- /dev/null +++ b/secrets/flowagent.secrets.example @@ -0,0 +1,53 @@ +# flowagent (Power Automate MCP, via mcpo service) — Secrets Reference +# Source: mcpo/flowagent — built into a custom image, consumed by the +# "mcpo" service in ai.yaml (NEVER mcpo-critical). +# +# Add SECRET values to Woodpecker at: +# https://woodpecker.bryanmail.net +# homelab/compose-files → Settings → Secrets +# +# Prerequisite (manual, outside GitOps — Azure Portal): +# 1. Entra ID → App registrations → New registration +# Name: flowagent-mcp-homelab, single tenant +# 2. API permissions → add Power Automate / Flow Service application +# permissions + Dynamics CRM user_impersonation (Dataverse access) +# 3. Grant admin consent +# 4. Certificates & secrets → new client secret → copy value immediately +# 5. Power Platform Admin Center → target environment → S2S apps → +# register the application user for this app ID (required for +# Dataverse/environment access by a service principal) +# +# NOTE: the OLD "powerautomate" mcpo/config.json entry (npm package +# powerautomate-mcp, client_id 84b431ed-..., tenant_id 0f6cf991-...) was +# never onboarded to this secrets pipeline and is being replaced by this. +# Do not reuse those IDs unless you've independently confirmed in Azure +# Portal that the old App Registration still exists, still has valid +# permissions/consent, and you intend to reuse it — otherwise register new. + +# ── SECRETS (add to Woodpecker) ────────────────────────────────────────── + +# Woodpecker secret name: flowagent_azure_client_id +# Used for: Azure AD App Registration client ID +# Env var in entrypoint: FLOWAGENT_AZURE_CLIENT_ID_FILE (Docker secret _FILE) +flowagent_azure_client_id= + +# Woodpecker secret name: flowagent_azure_tenant_id +# Used for: Azure AD tenant ID +# Env var in entrypoint: FLOWAGENT_AZURE_TENANT_ID_FILE (Docker secret _FILE) +flowagent_azure_tenant_id= + +# Woodpecker secret name: flowagent_azure_client_secret +# Used for: Azure AD App Registration client secret (rotate if leaked) +# Env var in entrypoint: FLOWAGENT_AZURE_CLIENT_SECRET_FILE (Docker secret _FILE) +flowagent_azure_client_secret= + +# ── Woodpecker provision-secrets case entry ────────────────────────────── +# Add this to the provision-secrets step in .woodpecker/deploy.yml +# (separate follow-up PR — this file only documents it): +# +# ai) +# ... existing ai-stack secret provisioning ... +# create_or_update_secret "flowagent_azure_client_id" "$FLOWAGENT_AZURE_CLIENT_ID" +# create_or_update_secret "flowagent_azure_tenant_id" "$FLOWAGENT_AZURE_TENANT_ID" +# create_or_update_secret "flowagent_azure_client_secret" "$FLOWAGENT_AZURE_CLIENT_SECRET" +# ;; -- 2.54.0