Help us improve
Share bugs, ideas, or general feedback.
Manages Azure Connector Gateways, connections, and event-driven triggers to connect Microsoft 365 services (Teams, Forms, SharePoint, OneDrive) and external APIs to sandbox apps.
npx claudepluginhub azure/connectorsHow this skill is triggered — by the user, by Claude, or both
Slash command
/azure-connectorgateway:azure-connectorgatewayThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Manage connector gateways, connections, and triggers — connect external services
references/consent.mdreferences/direct-api.mdreferences/dynamic-values.mdreferences/gateway-connections.mdreferences/gotchas.mdreferences/handler-guide.mdreferences/prerequisites.mdreferences/quickstart.mdreferences/runtime-url-examples.mdreferences/trigger-flow.mdreferences/trigger-setup.mdreferences/tutorial-welcome-emailer.mdscripts/trigger-getting-started.pyversion.jsonBuilds, scaffolds, deploys, and tests Power Automate cloud flows via FlowStudio MCP server without the portal. Useful for creating flow definitions, wiring connections, updating actions, or generating workflows from scratch.
Routes Azure tasks to the right specialist agent from a catalog. Classifies tasks into domains (architecture, containers, database, etc.) and dispatches single agents or parallel teams. Does not answer Azure questions itself.
Routes to specialized skills for adding Power Apps data sources like Dataverse (business data), SharePoint lists, Teams messages, Excel, OneDrive, and Office 365 based on user goals.
Share bugs, ideas, or general feedback.
Manage connector gateways, connections, and triggers — connect external services to sandbox apps via direct API calls or event-driven triggers.
| User request | Pattern | Connectors involved |
|---|---|---|
| "Send a Teams message when a form is submitted" | Trigger (Forms) + Direct API (Teams) | microsoftforms, teams |
| "Notify a channel when a file is uploaded" | Trigger (OneDrive/Blob) + Direct API (Teams) | onedriveforbusiness/azureblob, teams |
| "Send an email when a SharePoint list item changes" | Trigger (SharePoint) + Direct API (Office 365) | sharepointonline, office365 |
| "Post to Teams when a new email arrives" | Trigger (Office 365) + Direct API (Teams) | office365, teams |
| "Save form responses to SharePoint" | Trigger (Forms) + Direct API (SharePoint) | microsoftforms, sharepointonline |
| Rule | Details |
|---|---|
| No hallucination | Check references/ for details. Use az rest --help for syntax. |
| No generated notebooks/scripts | Do NOT generate a notebook or standalone script for the user. Walk through interactively. (Reference scripts in scripts/ and labs/ exist for learning.) |
| No MCP configs | Sandbox apps call runtime URL directly via HTTP. If you reach mcp-config create, STOP. |
| No guessing dynamic values | x-ms-dynamic-* → call API, present results, STOP. Never assume a team/channel/folder/site. |
| Execute, don't ask | Gather inputs → execute immediately → report. Never say "Can I run this?" |
| No az extensions | Gateway = az rest. Sandbox = aca CLI. Do NOT use az connectorgateway/sandbox/sandboxgroup. |
Always @$tmpFile | For az rest --body in PowerShell — inline JSON breaks. Bash examples in references/ use inline for brevity (shell quoting works in bash). See gotchas.md. |
| Trigger body schema | Uses metadata + notificationDetails (callbackUrl/body/auth). operationName+parameters at properties root. callbackTarget does NOT exist. See Step 5B template. |
| Handler deploy | Write to local file → aca sandbox fs write. Never inline Python in PowerShell. |
| SSL/stderr | REQUESTS_CA_BUNDLE preferred. verify=False needs disable_warnings(). stderr = trigger failure. See handler-guide.md. |
| Parallel execution | Run independent ops (connections, ACLs, gatewayConnections wiring, dynamic values) as parallel tool calls. |
| Sandbox ↔ connection wiring | Use the declarative gatewayConnections pattern (SG-level PATCH + per-sandbox PUT body). See gateway-connections.md. |
When to STOP and ask the user: Any parameter with dynamic values (teams, channels, folders, sites, lists), choosing integration pattern, OAuth consent. You must NEVER skip this — always fetch the list and present it.
When to EXECUTE immediately: creating gateways/connections/triggers/policies, wiring gatewayConnections, deploying handlers, installing deps.
Check az account show and aca --version. If missing, see prerequisites.md.
Select subscription — list available subscriptions, ask the user to pick:
az account list --query "[].{name:name, id:id, isDefault:isDefault}" -o table
Present the list and ask: "Which subscription do you want to use?" If the user picks a non-default subscription, set it:
az account set --subscription "{selected_subscription_id}"
Store the subscription ID for all subsequent commands.
Select resource group — ask: "Do you have an existing resource group, or should I create one?"
az group list --query "[].{name:name, location:location}" -o table
az group create --name {rg} --location {location}
Stop and wait for the user's answers before continuing.
Ask the user:
| User says | Connector name | Common triggers |
|---|---|---|
| Email, Outlook | office365 | OnNewEmailV3, OnFlaggedEmail |
| SharePoint, list | sharepointonline | OnNewItem, OnUpdatedItem |
| OneDrive, files | onedriveforbusiness | OnNewFile, OnUpdatedFile |
| Teams | teams | OnNewChannelMessage |
| Forms, survey, quiz | microsoftforms | OnFormResponse, OnNewResponse |
| Azure Blob | azureblob | OnNewBlob, OnUpdatedBlob |
Stop and wait for the user's answer before continuing.
⚡ Parallel batch: Once you know the gateway name, run ALL of these in one parallel call:
- Get gateway info (principalId, tenantId, location)
- List existing connections (names, statuses, runtime URLs)
- Get sandbox group identity (if sandbox already exists)
This avoids sequential round-trips and saves ~2 minutes.
ARM base URL:
https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/connectorGatewaysAPI version:api-version=2026-05-01-previewUse the subscription and resource group selected in Step 0.
Ask the user:
az rest --method GET \
--url "https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/connectorGateways/{gw}?api-version=2026-05-01-preview" \
--query "{name:name, principalId:identity.principalId, tenantId:identity.tenantId}"
$gwBody = @{ location = "{location}"; identity = @{ type = "SystemAssigned" } } | ConvertTo-Json -Compress
$tmp = New-TemporaryFile; Set-Content $tmp $gwBody
az rest --method PUT `
--url "https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/connectorGateways/{gw}?api-version=2026-05-01-preview" `
--body "@$tmp" `
--query "{name:name, principalId:identity.principalId, tenantId:identity.tenantId}"
Remove-Item $tmp
principalId and tenantId — they are needed later for
access policies and InvokePort auth.az rest --method GET \
--url "https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/connectorGateways/{gw}/connections?api-version=2026-05-01-preview" \
--query "value[].{name:name, status:properties.statuses[0].status, connector:properties.connectorName}"
Once you have the gateway info, proceed immediately to Step 3.
Create ALL needed connections in parallel, then consent all at once:
# Create connections (parallel tool calls if multiple):
$connBody = @{ properties = @{ connectorName = "office365" }; location = "{location}" } | ConvertTo-Json -Compress
$tmp = New-TemporaryFile; Set-Content $tmp $connBody
az rest --method PUT `
--url "https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/connectorGateways/{gw}/connections/o365-conn?api-version=2026-05-01-preview" `
--body "@$tmp"
Remove-Item $tmp
# Repeat for additional connections (onedriveforbusiness, sharepointonline, etc.)
Generate consent links and open in browser. → Exact format: See consent.md
⚠️ Use
Start-Processto open links. Body MUST useparametersarray withobjectId/tenantIdfrom the connection. Do NOT try other formats or print the URL.
Ask user to authenticate (use ask_user), then verify:
az rest --method GET \
--url ".../{gw}/connections?api-version=2026-05-01-preview" \
--query "value[].{name:name, status:properties.statuses[0].status}"
# All should show: Connected. If not, re-consent.
Ask the user:
dynamicInvoke
(send email, read list, create file). If deploying to sandbox, also wires the connection to the sandbox group + sandbox via gatewayConnections[].Stop and wait for the user's answer.
→ Full details: direct-api.md | Dynamic values: dynamic-values.md
managedApis/{connector}?export=true) → extract operationId-to-path tabledynamicInvoke on the connection with the resolved method + pathx-ms-dynamic-* → resolve via dynamicInvoke, show display names to user, store valuesIf deploying to sandbox: Wire the connection declaratively (sandbox-group gatewayConnections[] PATCH + per-sandbox PUT body referencing the same connection) → gateway-connections.md. The platform proxy injects Bearer auth on every runtime-URL call automatically; the handler makes plain requests.get(...) calls with no auth header.
→ Skip to Final verification checklist.
→ Full trigger setup (Steps 5B–9B): trigger-setup.md | Dynamic values: dynamic-values.md
GET .../managedApis/{connector}/apiOperations?api-version=2016-06-01 → filter for properties.triggerbatch (polling): inform user it polls every ~3 minutes by default. Ask if they want a different interval.x-ms-dynamic-* via Swagger + dynamicInvoke)Enabled⚠️ Do NOT use
callbackTarget— that field does not exist. Correct schema:metadata+notificationDetails. See trigger-setup.md.
| Target | Callback URL | Notes |
|---|---|---|
| ShellCommand | .../executeShellCommand | Auto-resumes sandbox; needs RBAC c24cf47c-... on sandbox group |
| ExecuteCommand | .../executeCommand | Same as above, no shell interpretation |
| InvokePort | https://{id}--{port}.proxy.azuredevcompute.io/... | Sandbox must be running; needs port auth |
After trigger creation → deploy handler. See handler-guide.md.
For Direct API calls (path A):
Connected, connectionRuntimeUrl availablegateway-acl (gateway MI) AND sandbox-acl (sandbox-group MI)aca sandboxgroup identity assign --name {sg} --system-assigned if principalId is null)properties.gatewayConnections[] includes an entry with this connection's {resourceId, connectionRuntimeUrl, authentication.type=SystemAssignedManagedIdentity} (PATCH; merge-don't-clobber)gatewayConnections: [{resourceId}] in its data-plane PUT body (the aca CLI doesn't expose --gateway-connection; use az rest data-plane PUT)For Event-driven triggers (path B):
ConnectedEnabled, gateway-acl exists (gateway MI → connection)sandbox-acl + sandbox-group gatewayConnections[] entry + per-sandbox gatewayConnections[{resourceId}] (same as path A)After setup → deploy the handler app. See handler-guide.md.
# ARM base: https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/connectorGateways
# API version: api-version=2026-05-01-preview
# Gateway
az rest --method GET --url ".../connectorGateways/{gw}?api-version=2026-05-01-preview"
# Connections
az rest --method GET --url ".../connectorGateways/{gw}/connections?api-version=2026-05-01-preview"
# List operations (summaries + trigger types)
az rest --method GET --url ".../providers/Microsoft.Web/locations/{location}/managedApis/{connector}/apiOperations?api-version=2016-06-01"
# Get Swagger (full paths, parameters, x-ms-dynamic-* extensions)
az rest --method GET --url ".../providers/Microsoft.Web/locations/{location}/managedApis/{connector}" --url-parameters "api-version=2016-06-01" "export=true"
# Dynamic invoke
az rest --method POST --url ".../connectorGateways/{gw}/connections/{conn}/dynamicInvoke?api-version=2026-05-01-preview" --body '{"request":{"method":"GET","path":"/..."}}'
# Trigger configs
az rest --method GET --url ".../connectorGateways/{gw}/triggerConfigs?api-version=2026-05-01-preview"
az rest --method GET --url ".../connectorGateways/{gw}/triggerConfigs/{name}?api-version=2026-05-01-preview" --query "properties.state"