powerautomate-mcp 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +416 -111
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { existsSync, mkdirSync, writeFileSync, lstatSync, statSync,
|
|
2
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync, lstatSync, statSync, unlinkSync, chmodSync, readdirSync } from 'fs';
|
|
3
3
|
import { dirname, join } from 'path';
|
|
4
4
|
import { platform, env } from 'process';
|
|
5
5
|
import { homedir } from 'os';
|
|
@@ -381,6 +381,7 @@ Create the file with your Microsoft Entra app client ID and Power Automate envir
|
|
|
381
381
|
err
|
|
382
382
|
);
|
|
383
383
|
}
|
|
384
|
+
parsed = interpolateEnvVars(parsed);
|
|
384
385
|
try {
|
|
385
386
|
const config = validateConfig(parsed);
|
|
386
387
|
logger.info(
|
|
@@ -409,12 +410,34 @@ function resolveEnvironment(config, envNameOrId) {
|
|
|
409
410
|
displayName: envConfig.displayName
|
|
410
411
|
};
|
|
411
412
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
413
|
+
{
|
|
414
|
+
throw new ConfigurationError(
|
|
415
|
+
`Environment "${envKey}" not found in configuration. Available environments: ${Object.keys(config.environments).filter((k) => k !== "default").join(", ") || "(none)"}`
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
function interpolateEnvVars(value) {
|
|
420
|
+
if (typeof value === "string") {
|
|
421
|
+
return value.replace(/\$\{([^}]+)\}/g, (_match, varName) => {
|
|
422
|
+
const envValue = env[varName];
|
|
423
|
+
if (envValue === void 0) {
|
|
424
|
+
logger.warn({ varName }, "Environment variable referenced in config is not set");
|
|
425
|
+
return "";
|
|
426
|
+
}
|
|
427
|
+
return envValue;
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
if (Array.isArray(value)) {
|
|
431
|
+
return value.map(interpolateEnvVars);
|
|
432
|
+
}
|
|
433
|
+
if (value !== null && typeof value === "object") {
|
|
434
|
+
const result = {};
|
|
435
|
+
for (const [key, val] of Object.entries(value)) {
|
|
436
|
+
result[key] = interpolateEnvVars(val);
|
|
437
|
+
}
|
|
438
|
+
return result;
|
|
439
|
+
}
|
|
440
|
+
return value;
|
|
418
441
|
}
|
|
419
442
|
|
|
420
443
|
// src/utils/security.ts
|
|
@@ -1112,12 +1135,12 @@ var FlowManagementApi = class {
|
|
|
1112
1135
|
throw new ApiError(`${context}: API error`, statusCode, errorDetails);
|
|
1113
1136
|
}
|
|
1114
1137
|
if (!responseText) {
|
|
1115
|
-
return {};
|
|
1138
|
+
return { value: [] };
|
|
1116
1139
|
}
|
|
1117
1140
|
return JSON.parse(responseText);
|
|
1118
1141
|
}
|
|
1119
1142
|
/**
|
|
1120
|
-
* List flows in an environment
|
|
1143
|
+
* List flows in an environment with optional pagination support
|
|
1121
1144
|
*/
|
|
1122
1145
|
async listFlows(options = {}) {
|
|
1123
1146
|
const envId = options.environment ?? this.defaultEnvironmentId;
|
|
@@ -1140,8 +1163,8 @@ var FlowManagementApi = class {
|
|
|
1140
1163
|
response,
|
|
1141
1164
|
"List flows"
|
|
1142
1165
|
);
|
|
1143
|
-
apiLogger.info({ count: data.value.length }, "Listed flows");
|
|
1144
|
-
return data.value;
|
|
1166
|
+
apiLogger.info({ count: data.value.length, hasMore: !!data.nextLink }, "Listed flows");
|
|
1167
|
+
return { flows: data.value, nextLink: data.nextLink };
|
|
1145
1168
|
}, "List flows");
|
|
1146
1169
|
}
|
|
1147
1170
|
/**
|
|
@@ -1434,9 +1457,13 @@ var FlowManagementApi = class {
|
|
|
1434
1457
|
const safeFlowId = validateRowId(flowId);
|
|
1435
1458
|
const safeRunId = validateRowId(runId);
|
|
1436
1459
|
apiLogger.info({ flowId: safeFlowId, runId: safeRunId, envId }, "Resubmitting flow run");
|
|
1460
|
+
const flow = await this.getFlow(safeFlowId, envId);
|
|
1461
|
+
const triggers = flow.properties.definition?.triggers ?? {};
|
|
1462
|
+
const triggerName = Object.keys(triggers)[0] ?? "manual";
|
|
1463
|
+
apiLogger.debug({ flowId: safeFlowId, triggerName }, "Using trigger name for resubmit");
|
|
1437
1464
|
const url = this.buildUrl(
|
|
1438
1465
|
envId,
|
|
1439
|
-
`/flows/${safeFlowId}/triggers/
|
|
1466
|
+
`/flows/${safeFlowId}/triggers/${triggerName}/histories/${safeRunId}/resubmit`
|
|
1440
1467
|
);
|
|
1441
1468
|
const headers = await this.getAuthHeaders();
|
|
1442
1469
|
return wrapApiCall(async () => {
|
|
@@ -1535,7 +1562,7 @@ var FlowManagementApi = class {
|
|
|
1535
1562
|
*/
|
|
1536
1563
|
async listApprovals(environmentId, top) {
|
|
1537
1564
|
const envId = environmentId ?? this.defaultEnvironmentId;
|
|
1538
|
-
const limit = top ?? 25;
|
|
1565
|
+
const limit = Math.min(top ?? 25, MAX_PAGE_SIZE);
|
|
1539
1566
|
apiLogger.debug({ envId, limit }, "Listing approvals");
|
|
1540
1567
|
const url = this.buildUrl(envId, "/approvals", { $top: limit });
|
|
1541
1568
|
const headers = await this.getAuthHeaders();
|
|
@@ -1617,6 +1644,12 @@ var ConnectorMetadataApi = class {
|
|
|
1617
1644
|
*/
|
|
1618
1645
|
async handleResponse(response, context) {
|
|
1619
1646
|
const { statusCode, body } = response;
|
|
1647
|
+
if (statusCode === 429) {
|
|
1648
|
+
await body.text();
|
|
1649
|
+
const retryAfter = response.headers["retry-after"];
|
|
1650
|
+
const retryMs = retryAfter ? parseInt(String(retryAfter), 10) * 1e3 : void 0;
|
|
1651
|
+
throw new RateLimitError(retryMs);
|
|
1652
|
+
}
|
|
1620
1653
|
const MAX_RESPONSE_SIZE = 50 * 1024 * 1024;
|
|
1621
1654
|
const chunks = [];
|
|
1622
1655
|
let totalSize = 0;
|
|
@@ -1951,6 +1984,12 @@ var GraphApi = class {
|
|
|
1951
1984
|
*/
|
|
1952
1985
|
async handleBinaryResponse(response, context) {
|
|
1953
1986
|
const { statusCode, body, headers } = response;
|
|
1987
|
+
if (statusCode === 429) {
|
|
1988
|
+
await body.text();
|
|
1989
|
+
const retryAfter = response.headers["retry-after"];
|
|
1990
|
+
const retryMs = retryAfter ? parseInt(String(retryAfter), 10) * 1e3 : void 0;
|
|
1991
|
+
throw new RateLimitError(retryMs);
|
|
1992
|
+
}
|
|
1954
1993
|
if (statusCode >= 400) {
|
|
1955
1994
|
const responseText = await body.text();
|
|
1956
1995
|
graphLogger.error({ statusCode, context }, "Graph API binary response error");
|
|
@@ -1979,6 +2018,12 @@ var GraphApi = class {
|
|
|
1979
2018
|
}
|
|
1980
2019
|
async handleResponse(response, context) {
|
|
1981
2020
|
const { statusCode, body } = response;
|
|
2021
|
+
if (statusCode === 429) {
|
|
2022
|
+
await body.text();
|
|
2023
|
+
const retryAfter = response.headers["retry-after"];
|
|
2024
|
+
const retryMs = retryAfter ? parseInt(String(retryAfter), 10) * 1e3 : void 0;
|
|
2025
|
+
throw new RateLimitError(retryMs);
|
|
2026
|
+
}
|
|
1982
2027
|
const MAX_RESPONSE_SIZE = 50 * 1024 * 1024;
|
|
1983
2028
|
const chunks = [];
|
|
1984
2029
|
let totalSize = 0;
|
|
@@ -2001,7 +2046,7 @@ var GraphApi = class {
|
|
|
2001
2046
|
throw new ApiError(`${context}: Graph API error`, statusCode, errorDetails);
|
|
2002
2047
|
}
|
|
2003
2048
|
if (!responseText) {
|
|
2004
|
-
return {};
|
|
2049
|
+
return { value: [] };
|
|
2005
2050
|
}
|
|
2006
2051
|
return JSON.parse(responseText);
|
|
2007
2052
|
}
|
|
@@ -3248,6 +3293,12 @@ var DataverseApi = class {
|
|
|
3248
3293
|
*/
|
|
3249
3294
|
async handleResponse(response, context) {
|
|
3250
3295
|
const { statusCode, body } = response;
|
|
3296
|
+
if (statusCode === 429) {
|
|
3297
|
+
await body.text();
|
|
3298
|
+
const retryAfter = response.headers["retry-after"];
|
|
3299
|
+
const retryMs = retryAfter ? parseInt(String(retryAfter), 10) * 1e3 : void 0;
|
|
3300
|
+
throw new RateLimitError(retryMs);
|
|
3301
|
+
}
|
|
3251
3302
|
const MAX_RESPONSE_SIZE = 50 * 1024 * 1024;
|
|
3252
3303
|
const chunks = [];
|
|
3253
3304
|
let totalSize = 0;
|
|
@@ -3273,7 +3324,7 @@ var DataverseApi = class {
|
|
|
3273
3324
|
throw new ApiError(`${context}: API error`, statusCode, errorDetails);
|
|
3274
3325
|
}
|
|
3275
3326
|
if (!responseText) {
|
|
3276
|
-
return {};
|
|
3327
|
+
return { value: [] };
|
|
3277
3328
|
}
|
|
3278
3329
|
return JSON.parse(responseText);
|
|
3279
3330
|
}
|
|
@@ -4066,6 +4117,7 @@ var SchemaCache = class {
|
|
|
4066
4117
|
};
|
|
4067
4118
|
var listFlowsInputSchema = z.object({
|
|
4068
4119
|
environment: z.string().optional().describe("Environment name or GUID. Uses default if omitted."),
|
|
4120
|
+
search: z.string().optional().describe("Search flows by display name (case-insensitive substring match). Applied client-side after fetching."),
|
|
4069
4121
|
filter: z.string().optional().describe(`OData filter expression (e.g., "properties/state eq 'Started'")`),
|
|
4070
4122
|
top: z.number().min(1).max(250).optional().describe("Maximum number of results to return (default 50, max 250)")
|
|
4071
4123
|
});
|
|
@@ -4079,6 +4131,10 @@ var listFlowsTool = {
|
|
|
4079
4131
|
type: "string",
|
|
4080
4132
|
description: "Environment name or GUID. Uses default if omitted."
|
|
4081
4133
|
},
|
|
4134
|
+
search: {
|
|
4135
|
+
type: "string",
|
|
4136
|
+
description: "Search flows by display name (case-insensitive substring match)."
|
|
4137
|
+
},
|
|
4082
4138
|
filter: {
|
|
4083
4139
|
type: "string",
|
|
4084
4140
|
description: `OData filter expression (e.g., "properties/state eq 'Started'")`
|
|
@@ -4103,11 +4159,16 @@ async function handleListFlows(api, input) {
|
|
|
4103
4159
|
return `Invalid filter: ${err instanceof Error ? err.message : "Filter contains disallowed patterns"}`;
|
|
4104
4160
|
}
|
|
4105
4161
|
}
|
|
4106
|
-
const
|
|
4162
|
+
const result = await api.listFlows({
|
|
4107
4163
|
environment: parsed.environment,
|
|
4108
4164
|
filter: safeFilter,
|
|
4109
4165
|
top: parsed.top ?? 50
|
|
4110
4166
|
});
|
|
4167
|
+
let flows = result.flows;
|
|
4168
|
+
if (parsed.search) {
|
|
4169
|
+
const needle = parsed.search.toLowerCase();
|
|
4170
|
+
flows = flows.filter((f) => f.properties.displayName.toLowerCase().includes(needle));
|
|
4171
|
+
}
|
|
4111
4172
|
if (flows.length === 0) {
|
|
4112
4173
|
return "No flows found";
|
|
4113
4174
|
}
|
|
@@ -4117,6 +4178,10 @@ async function handleListFlows(api, input) {
|
|
|
4117
4178
|
const modified = new Date(flow.properties.lastModifiedTime).toLocaleDateString();
|
|
4118
4179
|
lines.push(` ${state} ${flow.properties.displayName} (${flow.name}) - ${modified}`);
|
|
4119
4180
|
}
|
|
4181
|
+
if (result.nextLink) {
|
|
4182
|
+
lines.push(`
|
|
4183
|
+
(More flows available \u2014 use skipToken for next page)`);
|
|
4184
|
+
}
|
|
4120
4185
|
return lines.join("\n");
|
|
4121
4186
|
}
|
|
4122
4187
|
var getFlowInputSchema = z.object({
|
|
@@ -4645,37 +4710,7 @@ function validateActions(actions, result) {
|
|
|
4645
4710
|
for (const [name, action] of Object.entries(actions)) {
|
|
4646
4711
|
validateAction(action, `actions.${name}`, actionNames, result);
|
|
4647
4712
|
}
|
|
4648
|
-
|
|
4649
|
-
const visiting = /* @__PURE__ */ new Set();
|
|
4650
|
-
const detectCycle = (actionName, stack = []) => {
|
|
4651
|
-
if (visiting.has(actionName)) {
|
|
4652
|
-
return [...stack, actionName];
|
|
4653
|
-
}
|
|
4654
|
-
if (visited.has(actionName)) {
|
|
4655
|
-
return null;
|
|
4656
|
-
}
|
|
4657
|
-
visiting.add(actionName);
|
|
4658
|
-
stack.push(actionName);
|
|
4659
|
-
const action = actions[actionName];
|
|
4660
|
-
if (action?.runAfter) {
|
|
4661
|
-
for (const depName of Object.keys(action.runAfter)) {
|
|
4662
|
-
if (actionNames.has(depName)) {
|
|
4663
|
-
const cycle = detectCycle(depName, stack);
|
|
4664
|
-
if (cycle) return cycle;
|
|
4665
|
-
}
|
|
4666
|
-
}
|
|
4667
|
-
}
|
|
4668
|
-
visiting.delete(actionName);
|
|
4669
|
-
visited.add(actionName);
|
|
4670
|
-
return null;
|
|
4671
|
-
};
|
|
4672
|
-
for (const actionName of actionNames) {
|
|
4673
|
-
const cycle = detectCycle(actionName);
|
|
4674
|
-
if (cycle) {
|
|
4675
|
-
addError(result, "actions", `Circular dependency detected: ${cycle.join(" -> ")}`);
|
|
4676
|
-
break;
|
|
4677
|
-
}
|
|
4678
|
-
}
|
|
4713
|
+
detectCircularDependencies(actions, actionNames, "actions", result);
|
|
4679
4714
|
}
|
|
4680
4715
|
function validateAction(action, path, allActions, result) {
|
|
4681
4716
|
if (!action.type) {
|
|
@@ -4747,36 +4782,70 @@ function validateConnectorAction(action, path, result) {
|
|
|
4747
4782
|
addError(result, `${path}.inputs.host.operationId`, "Missing operation ID");
|
|
4748
4783
|
}
|
|
4749
4784
|
}
|
|
4750
|
-
function
|
|
4785
|
+
function validateNestedActions(actions, path, result) {
|
|
4786
|
+
const localScope = new Set(Object.keys(actions));
|
|
4787
|
+
for (const [name, subAction] of Object.entries(actions)) {
|
|
4788
|
+
validateAction(subAction, `${path}.${name}`, localScope, result);
|
|
4789
|
+
}
|
|
4790
|
+
detectCircularDependencies(actions, localScope, path, result);
|
|
4791
|
+
}
|
|
4792
|
+
function detectCircularDependencies(actions, actionNames, path, result) {
|
|
4793
|
+
const visited = /* @__PURE__ */ new Set();
|
|
4794
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
4795
|
+
const detectCycle = (actionName, stack = []) => {
|
|
4796
|
+
if (visiting.has(actionName)) {
|
|
4797
|
+
return [...stack, actionName];
|
|
4798
|
+
}
|
|
4799
|
+
if (visited.has(actionName)) {
|
|
4800
|
+
return null;
|
|
4801
|
+
}
|
|
4802
|
+
visiting.add(actionName);
|
|
4803
|
+
stack.push(actionName);
|
|
4804
|
+
const action = actions[actionName];
|
|
4805
|
+
if (action?.runAfter) {
|
|
4806
|
+
for (const depName of Object.keys(action.runAfter)) {
|
|
4807
|
+
if (actionNames.has(depName)) {
|
|
4808
|
+
const cycle = detectCycle(depName, stack);
|
|
4809
|
+
if (cycle) return cycle;
|
|
4810
|
+
}
|
|
4811
|
+
}
|
|
4812
|
+
}
|
|
4813
|
+
visiting.delete(actionName);
|
|
4814
|
+
visited.add(actionName);
|
|
4815
|
+
return null;
|
|
4816
|
+
};
|
|
4817
|
+
for (const actionName of actionNames) {
|
|
4818
|
+
const cycle = detectCycle(actionName);
|
|
4819
|
+
if (cycle) {
|
|
4820
|
+
addError(result, path, `Circular dependency detected: ${cycle.join(" -> ")}`);
|
|
4821
|
+
break;
|
|
4822
|
+
}
|
|
4823
|
+
}
|
|
4824
|
+
}
|
|
4825
|
+
function validateConditionAction(action, path, _allActions, result) {
|
|
4751
4826
|
if (!action.expression) {
|
|
4752
4827
|
addError(result, `${path}.expression`, "Condition action must have an expression");
|
|
4753
4828
|
}
|
|
4754
4829
|
if (!action.actions || Object.keys(action.actions).length === 0) {
|
|
4755
4830
|
addWarning(result, `${path}.actions`, "Condition 'if true' branch has no actions");
|
|
4756
4831
|
} else {
|
|
4757
|
-
|
|
4758
|
-
validateAction(subAction, `${path}.actions.${name}`, allActions, result);
|
|
4759
|
-
}
|
|
4832
|
+
validateNestedActions(action.actions, `${path}.actions`, result);
|
|
4760
4833
|
}
|
|
4761
4834
|
if (action.else?.actions) {
|
|
4762
|
-
|
|
4763
|
-
validateAction(subAction, `${path}.else.actions.${name}`, allActions, result);
|
|
4764
|
-
}
|
|
4835
|
+
validateNestedActions(action.else.actions, `${path}.else.actions`, result);
|
|
4765
4836
|
}
|
|
4766
4837
|
}
|
|
4767
|
-
function validateForeachAction(action, path,
|
|
4838
|
+
function validateForeachAction(action, path, _allActions, result) {
|
|
4768
4839
|
if (!action.foreach) {
|
|
4769
4840
|
addError(result, `${path}.foreach`, "Foreach action must have a foreach expression");
|
|
4770
4841
|
}
|
|
4771
4842
|
if (!action.actions || Object.keys(action.actions).length === 0) {
|
|
4772
4843
|
addWarning(result, `${path}.actions`, "Foreach loop has no actions");
|
|
4773
4844
|
} else {
|
|
4774
|
-
|
|
4775
|
-
validateAction(subAction, `${path}.actions.${name}`, allActions, result);
|
|
4776
|
-
}
|
|
4845
|
+
validateNestedActions(action.actions, `${path}.actions`, result);
|
|
4777
4846
|
}
|
|
4778
4847
|
}
|
|
4779
|
-
function validateSwitchAction(action, path,
|
|
4848
|
+
function validateSwitchAction(action, path, _allActions, result) {
|
|
4780
4849
|
if (!action.expression) {
|
|
4781
4850
|
addError(result, `${path}.expression`, "Switch action must have an expression");
|
|
4782
4851
|
}
|
|
@@ -4785,37 +4854,29 @@ function validateSwitchAction(action, path, allActions, result) {
|
|
|
4785
4854
|
} else {
|
|
4786
4855
|
for (const [caseName, caseData] of Object.entries(action.cases)) {
|
|
4787
4856
|
if (caseData.actions) {
|
|
4788
|
-
|
|
4789
|
-
validateAction(subAction, `${path}.cases.${caseName}.actions.${name}`, allActions, result);
|
|
4790
|
-
}
|
|
4857
|
+
validateNestedActions(caseData.actions, `${path}.cases.${caseName}.actions`, result);
|
|
4791
4858
|
}
|
|
4792
4859
|
}
|
|
4793
4860
|
}
|
|
4794
4861
|
if (action.default?.actions) {
|
|
4795
|
-
|
|
4796
|
-
validateAction(subAction, `${path}.default.actions.${name}`, allActions, result);
|
|
4797
|
-
}
|
|
4862
|
+
validateNestedActions(action.default.actions, `${path}.default.actions`, result);
|
|
4798
4863
|
}
|
|
4799
4864
|
}
|
|
4800
|
-
function validateScopeAction(action, path,
|
|
4865
|
+
function validateScopeAction(action, path, _allActions, result) {
|
|
4801
4866
|
if (!action.actions || Object.keys(action.actions).length === 0) {
|
|
4802
4867
|
addWarning(result, `${path}.actions`, "Scope has no actions");
|
|
4803
4868
|
} else {
|
|
4804
|
-
|
|
4805
|
-
validateAction(subAction, `${path}.actions.${name}`, allActions, result);
|
|
4806
|
-
}
|
|
4869
|
+
validateNestedActions(action.actions, `${path}.actions`, result);
|
|
4807
4870
|
}
|
|
4808
4871
|
}
|
|
4809
|
-
function validateUntilAction(action, path,
|
|
4872
|
+
function validateUntilAction(action, path, _allActions, result) {
|
|
4810
4873
|
if (!action.expression) {
|
|
4811
4874
|
addError(result, `${path}.expression`, "Until action must have an expression");
|
|
4812
4875
|
}
|
|
4813
4876
|
if (!action.actions || Object.keys(action.actions).length === 0) {
|
|
4814
4877
|
addWarning(result, `${path}.actions`, "Until loop has no actions");
|
|
4815
4878
|
} else {
|
|
4816
|
-
|
|
4817
|
-
validateAction(subAction, `${path}.actions.${name}`, allActions, result);
|
|
4818
|
-
}
|
|
4879
|
+
validateNestedActions(action.actions, `${path}.actions`, result);
|
|
4819
4880
|
}
|
|
4820
4881
|
}
|
|
4821
4882
|
|
|
@@ -4949,6 +5010,7 @@ var KNOWN_FUNCTIONS = /* @__PURE__ */ new Set([
|
|
|
4949
5010
|
"uriScheme"
|
|
4950
5011
|
]);
|
|
4951
5012
|
var EXPRESSION_REGEX = /@\{([^}]+)\}/g;
|
|
5013
|
+
var BARE_EXPRESSION_REGEX = /@((?:triggerBody|triggerOutputs|outputs|body|items|variables|parameters|workflow|result|actionOutputs|actionBody|trigger|actions|concat|toLower|toUpper|trim|substring|replace|split|length|contains|startsWith|endsWith|indexOf|lastIndexOf|first|last|take|skip|join|createArray|union|intersection|empty|if|and|or|not|equals|greater|greaterOrEquals|less|lessOrEquals|coalesce|int|float|string|bool|json|xml|array|add|sub|mul|div|mod|max|min|utcNow|addDays|addHours|addMinutes|addSeconds|formatDateTime|guid|base64|encodeUriComponent|decodeUriComponent)\s*\(.*\))/g;
|
|
4952
5014
|
function extractExpressions(text) {
|
|
4953
5015
|
const expressions = [];
|
|
4954
5016
|
let match;
|
|
@@ -4956,6 +5018,10 @@ function extractExpressions(text) {
|
|
|
4956
5018
|
if (match[1]) expressions.push(match[1]);
|
|
4957
5019
|
}
|
|
4958
5020
|
EXPRESSION_REGEX.lastIndex = 0;
|
|
5021
|
+
while ((match = BARE_EXPRESSION_REGEX.exec(text)) !== null) {
|
|
5022
|
+
if (match[1]) expressions.push(match[1]);
|
|
5023
|
+
}
|
|
5024
|
+
BARE_EXPRESSION_REGEX.lastIndex = 0;
|
|
4959
5025
|
return expressions;
|
|
4960
5026
|
}
|
|
4961
5027
|
function validateExpression(expression, path) {
|
|
@@ -5241,7 +5307,7 @@ function checkBestPractices(definition) {
|
|
|
5241
5307
|
const type = actionObj.type;
|
|
5242
5308
|
if (type === "Http" || type === "ApiConnection") {
|
|
5243
5309
|
const inputs = actionObj.inputs;
|
|
5244
|
-
const retryPolicy = actionObj.retryPolicy;
|
|
5310
|
+
const retryPolicy = inputs?.retryPolicy ?? actionObj.retryPolicy;
|
|
5245
5311
|
if (!retryPolicy || retryPolicy.type === "none") {
|
|
5246
5312
|
issues.push({
|
|
5247
5313
|
severity: "suggestion",
|
|
@@ -5438,12 +5504,12 @@ var triggerSchema = z.object({
|
|
|
5438
5504
|
startTime: z.string().optional(),
|
|
5439
5505
|
timeZone: z.string().optional()
|
|
5440
5506
|
}).optional().describe("Recurrence settings for scheduled triggers")
|
|
5441
|
-
});
|
|
5507
|
+
}).passthrough();
|
|
5442
5508
|
var actionSchema = z.object({
|
|
5443
5509
|
type: z.string().describe("Action type"),
|
|
5444
5510
|
inputs: z.unknown().optional().describe("Action inputs - can be object, string, array, or any value"),
|
|
5445
5511
|
runAfter: z.record(z.array(z.enum(["Succeeded", "Failed", "Skipped", "TimedOut"]))).optional().describe("Dependencies")
|
|
5446
|
-
});
|
|
5512
|
+
}).passthrough();
|
|
5447
5513
|
var connectionRefSchema = z.object({
|
|
5448
5514
|
connectionName: z.string().describe("Connection name in the environment"),
|
|
5449
5515
|
id: z.string().describe("Connection resource ID"),
|
|
@@ -5642,12 +5708,12 @@ var triggerSchema2 = z.object({
|
|
|
5642
5708
|
startTime: z.string().optional(),
|
|
5643
5709
|
timeZone: z.string().optional()
|
|
5644
5710
|
}).optional()
|
|
5645
|
-
});
|
|
5711
|
+
}).passthrough();
|
|
5646
5712
|
var actionSchema2 = z.object({
|
|
5647
5713
|
type: z.string(),
|
|
5648
5714
|
inputs: z.unknown().optional(),
|
|
5649
5715
|
runAfter: z.record(z.array(z.enum(["Succeeded", "Failed", "Skipped", "TimedOut"]))).optional()
|
|
5650
|
-
});
|
|
5716
|
+
}).passthrough();
|
|
5651
5717
|
var connectionRefSchema2 = z.object({
|
|
5652
5718
|
connectionName: z.string(),
|
|
5653
5719
|
id: z.string(),
|
|
@@ -13511,7 +13577,8 @@ function formatEnvironmentDetails(env2) {
|
|
|
13511
13577
|
};
|
|
13512
13578
|
}
|
|
13513
13579
|
async function getEnvironmentSummary(context, environmentId) {
|
|
13514
|
-
const
|
|
13580
|
+
const result = await context.api.listFlows({ environment: environmentId });
|
|
13581
|
+
const flows = result.flows;
|
|
13515
13582
|
const flowStats = {
|
|
13516
13583
|
total: flows.length,
|
|
13517
13584
|
started: flows.filter((f) => f.properties.state === "Started").length,
|
|
@@ -14083,6 +14150,122 @@ function getPrompt(name, args) {
|
|
|
14083
14150
|
return null;
|
|
14084
14151
|
}
|
|
14085
14152
|
}
|
|
14153
|
+
var PACKAGE_NAME = "powerautomate-mcp";
|
|
14154
|
+
var REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
|
|
14155
|
+
var CHECK_TIMEOUT_MS = 5e3;
|
|
14156
|
+
function getInstalledVersion() {
|
|
14157
|
+
try {
|
|
14158
|
+
let dir = dirname(fileURLToPath(import.meta.url));
|
|
14159
|
+
for (let i = 0; i < 5; i++) {
|
|
14160
|
+
const candidate = join(dir, "package.json");
|
|
14161
|
+
if (existsSync(candidate)) {
|
|
14162
|
+
const pkg = JSON.parse(readFileSync(candidate, "utf-8"));
|
|
14163
|
+
if (pkg.name === PACKAGE_NAME && pkg.version) {
|
|
14164
|
+
return pkg.version;
|
|
14165
|
+
}
|
|
14166
|
+
}
|
|
14167
|
+
const parent = dirname(dir);
|
|
14168
|
+
if (parent === dir) break;
|
|
14169
|
+
dir = parent;
|
|
14170
|
+
}
|
|
14171
|
+
return "0.0.0";
|
|
14172
|
+
} catch {
|
|
14173
|
+
return "0.0.0";
|
|
14174
|
+
}
|
|
14175
|
+
}
|
|
14176
|
+
async function checkForUpdate() {
|
|
14177
|
+
const currentVersion = getInstalledVersion();
|
|
14178
|
+
try {
|
|
14179
|
+
const { statusCode, body } = await request(REGISTRY_URL, {
|
|
14180
|
+
method: "GET",
|
|
14181
|
+
headers: { accept: "application/json" },
|
|
14182
|
+
signal: AbortSignal.timeout(CHECK_TIMEOUT_MS)
|
|
14183
|
+
});
|
|
14184
|
+
if (statusCode !== 200) {
|
|
14185
|
+
await body.text();
|
|
14186
|
+
return null;
|
|
14187
|
+
}
|
|
14188
|
+
const data = await body.json();
|
|
14189
|
+
const latestVersion = data.version;
|
|
14190
|
+
if (!latestVersion) return null;
|
|
14191
|
+
return {
|
|
14192
|
+
currentVersion,
|
|
14193
|
+
latestVersion,
|
|
14194
|
+
updateAvailable: compareVersions(latestVersion, currentVersion) > 0
|
|
14195
|
+
};
|
|
14196
|
+
} catch (err) {
|
|
14197
|
+
logger.debug({ err }, "Update check failed (non-fatal)");
|
|
14198
|
+
return null;
|
|
14199
|
+
}
|
|
14200
|
+
}
|
|
14201
|
+
function compareVersions(a, b) {
|
|
14202
|
+
const pa = a.split(".").map(Number);
|
|
14203
|
+
const pb = b.split(".").map(Number);
|
|
14204
|
+
for (let i = 0; i < 3; i++) {
|
|
14205
|
+
const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
14206
|
+
if (diff !== 0) return diff;
|
|
14207
|
+
}
|
|
14208
|
+
return 0;
|
|
14209
|
+
}
|
|
14210
|
+
function getUpdateCommand() {
|
|
14211
|
+
const npmExecPath = process.env["npm_execpath"] ?? "";
|
|
14212
|
+
const npmCommand = process.env["npm_command"] ?? "";
|
|
14213
|
+
if (npmExecPath.includes("npx") || npmCommand === "exec") {
|
|
14214
|
+
return { cmd: "npx", args: [`${PACKAGE_NAME}@latest`] };
|
|
14215
|
+
}
|
|
14216
|
+
if (npmExecPath.includes("yarn")) {
|
|
14217
|
+
return { cmd: "yarn", args: ["global", "add", PACKAGE_NAME] };
|
|
14218
|
+
}
|
|
14219
|
+
if (npmExecPath.includes("pnpm")) {
|
|
14220
|
+
return { cmd: "pnpm", args: ["add", "-g", PACKAGE_NAME] };
|
|
14221
|
+
}
|
|
14222
|
+
return { cmd: "npm", args: ["install", "-g", PACKAGE_NAME] };
|
|
14223
|
+
}
|
|
14224
|
+
async function runSelfUpdate() {
|
|
14225
|
+
const info = await checkForUpdate();
|
|
14226
|
+
if (info === null) {
|
|
14227
|
+
console.error("Could not reach npm registry. Check your internet connection.");
|
|
14228
|
+
process.exit(1);
|
|
14229
|
+
}
|
|
14230
|
+
if (!info.updateAvailable) {
|
|
14231
|
+
console.error(`Already up to date (v${info.currentVersion}).`);
|
|
14232
|
+
process.exit(0);
|
|
14233
|
+
}
|
|
14234
|
+
console.error(`Updating ${PACKAGE_NAME}: v${info.currentVersion} \u2192 v${info.latestVersion}`);
|
|
14235
|
+
const { cmd, args } = getUpdateCommand();
|
|
14236
|
+
console.error(`Running: ${cmd} ${args.join(" ")}`);
|
|
14237
|
+
return new Promise((_resolve) => {
|
|
14238
|
+
const child = execFile(cmd, args, { timeout: 12e4 }, (error, stdout, stderr) => {
|
|
14239
|
+
if (error) {
|
|
14240
|
+
console.error(`
|
|
14241
|
+
Update failed: ${error.message}`);
|
|
14242
|
+
if (stderr) console.error(stderr);
|
|
14243
|
+
console.error(`
|
|
14244
|
+
You can update manually: npm install -g ${PACKAGE_NAME}`);
|
|
14245
|
+
process.exit(1);
|
|
14246
|
+
}
|
|
14247
|
+
if (stdout) console.error(stdout.trim());
|
|
14248
|
+
console.error(`
|
|
14249
|
+
Updated to v${info.latestVersion} successfully.`);
|
|
14250
|
+
process.exit(0);
|
|
14251
|
+
});
|
|
14252
|
+
child.stdout?.pipe(process.stderr);
|
|
14253
|
+
child.stderr?.pipe(process.stderr);
|
|
14254
|
+
});
|
|
14255
|
+
}
|
|
14256
|
+
function backgroundUpdateCheck() {
|
|
14257
|
+
checkForUpdate().then((info) => {
|
|
14258
|
+
if (info?.updateAvailable) {
|
|
14259
|
+
console.error(
|
|
14260
|
+
`
|
|
14261
|
+
Update available: v${info.currentVersion} \u2192 v${info.latestVersion}
|
|
14262
|
+
Run: powerautomate-mcp --update
|
|
14263
|
+
`
|
|
14264
|
+
);
|
|
14265
|
+
}
|
|
14266
|
+
}).catch(() => {
|
|
14267
|
+
});
|
|
14268
|
+
}
|
|
14086
14269
|
|
|
14087
14270
|
// src/server.ts
|
|
14088
14271
|
async function createMcpServer(serverConfig) {
|
|
@@ -14162,7 +14345,7 @@ async function createMcpServer(serverConfig) {
|
|
|
14162
14345
|
const server = new Server(
|
|
14163
14346
|
{
|
|
14164
14347
|
name: "powerautomate-mcp",
|
|
14165
|
-
version:
|
|
14348
|
+
version: getInstalledVersion()
|
|
14166
14349
|
},
|
|
14167
14350
|
{
|
|
14168
14351
|
capabilities: {
|
|
@@ -14176,8 +14359,8 @@ async function createMcpServer(serverConfig) {
|
|
|
14176
14359
|
logger.debug("Listing tools");
|
|
14177
14360
|
return { tools };
|
|
14178
14361
|
});
|
|
14179
|
-
server.setRequestHandler(CallToolRequestSchema, async (
|
|
14180
|
-
const { name, arguments: args } =
|
|
14362
|
+
server.setRequestHandler(CallToolRequestSchema, async (request8) => {
|
|
14363
|
+
const { name, arguments: args } = request8.params;
|
|
14181
14364
|
logger.info({ tool: name }, "Tool called");
|
|
14182
14365
|
if (args && !checkObjectDepth(args, 20)) {
|
|
14183
14366
|
return {
|
|
@@ -14205,8 +14388,8 @@ async function createMcpServer(serverConfig) {
|
|
|
14205
14388
|
const resources = await listAllResources(resourceContext);
|
|
14206
14389
|
return { resources };
|
|
14207
14390
|
});
|
|
14208
|
-
server.setRequestHandler(ReadResourceRequestSchema, async (
|
|
14209
|
-
const { uri } =
|
|
14391
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request8) => {
|
|
14392
|
+
const { uri } = request8.params;
|
|
14210
14393
|
logger.info({ uri }, "Reading resource");
|
|
14211
14394
|
const result = await readResource(resourceContext, uri);
|
|
14212
14395
|
if (!result) {
|
|
@@ -14218,8 +14401,8 @@ async function createMcpServer(serverConfig) {
|
|
|
14218
14401
|
logger.debug("Listing prompts");
|
|
14219
14402
|
return { prompts };
|
|
14220
14403
|
});
|
|
14221
|
-
server.setRequestHandler(GetPromptRequestSchema, async (
|
|
14222
|
-
const { name, arguments: args } =
|
|
14404
|
+
server.setRequestHandler(GetPromptRequestSchema, async (request8) => {
|
|
14405
|
+
const { name, arguments: args } = request8.params;
|
|
14223
14406
|
logger.info({ prompt: name }, "Getting prompt");
|
|
14224
14407
|
const result = getPrompt(name, args ?? {});
|
|
14225
14408
|
if (!result) {
|
|
@@ -14321,8 +14504,9 @@ function checkObjectDepth(obj, maxDepth, current = 0) {
|
|
|
14321
14504
|
return true;
|
|
14322
14505
|
}
|
|
14323
14506
|
async function createDeviceCodeAuthProvider(config, silentOnly = false) {
|
|
14324
|
-
const { clientId, cachePath } = config;
|
|
14325
|
-
const
|
|
14507
|
+
const { clientId, tenantId, cachePath } = config;
|
|
14508
|
+
const validatedTenantId = tenantId ? validateTenantId(tenantId) : null;
|
|
14509
|
+
const authority = validatedTenantId ? `https://login.microsoftonline.com/${validatedTenantId}` : DEFAULT_AUTHORITY;
|
|
14326
14510
|
const cachePlugin = await createPersistentCachePlugin(cachePath);
|
|
14327
14511
|
const msalConfig = {
|
|
14328
14512
|
auth: {
|
|
@@ -14467,7 +14651,9 @@ async function createDeviceCodeAuthProvider(config, silentOnly = false) {
|
|
|
14467
14651
|
}
|
|
14468
14652
|
async function createAuthProviderFromConfig2(clientId, tenantId, cachePath, silentOnly = false) {
|
|
14469
14653
|
const config = {
|
|
14470
|
-
clientId
|
|
14654
|
+
clientId,
|
|
14655
|
+
tenantId: tenantId ?? null
|
|
14656
|
+
};
|
|
14471
14657
|
return createDeviceCodeAuthProvider(config, silentOnly);
|
|
14472
14658
|
}
|
|
14473
14659
|
|
|
@@ -14519,7 +14705,7 @@ function getDefaultEnvironment(environments) {
|
|
|
14519
14705
|
}
|
|
14520
14706
|
|
|
14521
14707
|
// src/setup/published-app.ts
|
|
14522
|
-
var PUBLISHED_APP_CLIENT_ID = "
|
|
14708
|
+
var PUBLISHED_APP_CLIENT_ID = "20ae33ee-6743-4786-9b00-8eb7bfebfd11";
|
|
14523
14709
|
var APP_DISPLAY_NAME = "Power Automate MCP";
|
|
14524
14710
|
var REDIRECT_URI = "https://login.microsoftonline.com/common/oauth2/nativeclient";
|
|
14525
14711
|
var REQUIRED_RESOURCE_ACCESS = [
|
|
@@ -14534,10 +14720,8 @@ var REQUIRED_RESOURCE_ACCESS = [
|
|
|
14534
14720
|
{
|
|
14535
14721
|
resourceAppId: "7df0a125-d3be-4c96-aa54-591f83ff541c",
|
|
14536
14722
|
resourceAccess: [
|
|
14537
|
-
{ id: "
|
|
14538
|
-
{ id: "
|
|
14539
|
-
{ id: "822a9cde-503a-472d-a530-d1dc9cd0d52b", type: "Scope" },
|
|
14540
|
-
{ id: "d05743e4-fb24-4dff-8a33-0f6c73c964bd", type: "Scope" }
|
|
14723
|
+
{ id: "e07c4438-06fe-4349-9077-b8ab4e888e21", type: "Scope" },
|
|
14724
|
+
{ id: "f3a53f5e-1975-4e99-8c6e-c6a0dfac61f6", type: "Scope" }
|
|
14541
14725
|
]
|
|
14542
14726
|
},
|
|
14543
14727
|
{
|
|
@@ -14625,8 +14809,6 @@ async function createAppRegistration(displayName) {
|
|
|
14625
14809
|
"false",
|
|
14626
14810
|
"--enable-id-token-issuance",
|
|
14627
14811
|
"false",
|
|
14628
|
-
"--is-fallback-public-client",
|
|
14629
|
-
"true",
|
|
14630
14812
|
"--public-client-redirect-uris",
|
|
14631
14813
|
REDIRECT_URI,
|
|
14632
14814
|
"--required-resource-accesses",
|
|
@@ -14724,19 +14906,25 @@ function clearTokenCache() {
|
|
|
14724
14906
|
return { cleared: files.length > 0, files };
|
|
14725
14907
|
}
|
|
14726
14908
|
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
14727
|
-
function
|
|
14909
|
+
function readExistingAuthConfig() {
|
|
14728
14910
|
try {
|
|
14729
14911
|
const configPath = getConfigPath();
|
|
14730
|
-
if (!existsSync(configPath)) return null;
|
|
14912
|
+
if (!existsSync(configPath)) return { clientId: null, tenantId: null };
|
|
14731
14913
|
const raw = readFileSync(configPath, "utf-8");
|
|
14732
14914
|
const parsed = JSON.parse(raw);
|
|
14733
|
-
const
|
|
14734
|
-
|
|
14735
|
-
return
|
|
14915
|
+
const clientId = parsed?.auth?.clientId;
|
|
14916
|
+
const tenantId = parsed?.auth?.tenantId;
|
|
14917
|
+
return {
|
|
14918
|
+
clientId: clientId && UUID_RE2.test(clientId) ? clientId : null,
|
|
14919
|
+
tenantId: tenantId && UUID_RE2.test(tenantId) ? tenantId : null
|
|
14920
|
+
};
|
|
14736
14921
|
} catch {
|
|
14737
|
-
return null;
|
|
14922
|
+
return { clientId: null, tenantId: null };
|
|
14738
14923
|
}
|
|
14739
14924
|
}
|
|
14925
|
+
function readExistingClientId() {
|
|
14926
|
+
return readExistingAuthConfig().clientId;
|
|
14927
|
+
}
|
|
14740
14928
|
async function resolveAppRegistration() {
|
|
14741
14929
|
const existingId = readExistingClientId();
|
|
14742
14930
|
if (existingId) {
|
|
@@ -14814,8 +15002,9 @@ async function runSetupWizard() {
|
|
|
14814
15002
|
print(` ${c.dim}Sign in with your Microsoft work account.${c.reset}`);
|
|
14815
15003
|
print(` ${c.dim}A device code will be shown \u2014 follow the instructions to authenticate.${c.reset}`);
|
|
14816
15004
|
print("");
|
|
14817
|
-
const
|
|
14818
|
-
let tenantId =
|
|
15005
|
+
const existingAuth = readExistingAuthConfig();
|
|
15006
|
+
let tenantId = existingAuth.tenantId;
|
|
15007
|
+
const authProvider = await createAuthProviderFromConfig2(clientId, tenantId);
|
|
14819
15008
|
try {
|
|
14820
15009
|
await authProvider.getToken();
|
|
14821
15010
|
const account = authProvider.getCurrentAccount();
|
|
@@ -14971,6 +15160,71 @@ function isSetupNeeded() {
|
|
|
14971
15160
|
return !existsSync(configPath);
|
|
14972
15161
|
}
|
|
14973
15162
|
|
|
15163
|
+
// src/cli/validate.ts
|
|
15164
|
+
async function runValidate() {
|
|
15165
|
+
console.error("Validating Power Automate MCP configuration...\n");
|
|
15166
|
+
let config;
|
|
15167
|
+
try {
|
|
15168
|
+
const configPath = getConfigPath();
|
|
15169
|
+
console.error(` [1/3] Config file: ${configPath}`);
|
|
15170
|
+
config = loadConfig();
|
|
15171
|
+
const envNames = Object.keys(config.environments).filter((k) => k !== "default");
|
|
15172
|
+
console.error(` Client ID: ${config.auth.clientId}`);
|
|
15173
|
+
console.error(` Tenant: ${config.auth.tenantId ?? "common"}`);
|
|
15174
|
+
console.error(` Environments: ${envNames.join(", ") || "(none)"}`);
|
|
15175
|
+
console.error(` Default: ${config.environments.default}`);
|
|
15176
|
+
console.error(" \u2713 Config valid\n");
|
|
15177
|
+
} catch (err) {
|
|
15178
|
+
const msg = err instanceof ConfigurationError ? err.message : String(err);
|
|
15179
|
+
console.error(` \u2717 Config error: ${msg}
|
|
15180
|
+
`);
|
|
15181
|
+
process.exit(1);
|
|
15182
|
+
}
|
|
15183
|
+
let authProvider;
|
|
15184
|
+
try {
|
|
15185
|
+
console.error(" [2/3] Authenticating...");
|
|
15186
|
+
authProvider = await createAuthProviderFromConfig(
|
|
15187
|
+
config.auth.clientId,
|
|
15188
|
+
config.auth.tenantId,
|
|
15189
|
+
void 0,
|
|
15190
|
+
true
|
|
15191
|
+
// silentOnly
|
|
15192
|
+
);
|
|
15193
|
+
const token = await authProvider.getToken();
|
|
15194
|
+
console.error(` Token acquired (${token.length} chars)`);
|
|
15195
|
+
const account = authProvider.getCurrentAccount();
|
|
15196
|
+
if (account) {
|
|
15197
|
+
console.error(` Account: ${account.username ?? account.name ?? "unknown"}`);
|
|
15198
|
+
}
|
|
15199
|
+
console.error(" \u2713 Auth valid\n");
|
|
15200
|
+
} catch (err) {
|
|
15201
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
15202
|
+
console.error(` \u2717 Auth error: ${msg}`);
|
|
15203
|
+
console.error(" Run: powerautomate-mcp --setup\n");
|
|
15204
|
+
process.exit(1);
|
|
15205
|
+
}
|
|
15206
|
+
try {
|
|
15207
|
+
console.error(" [3/3] Testing API connectivity...");
|
|
15208
|
+
const defaultEnv = resolveEnvironment(config);
|
|
15209
|
+
const flowApi = new FlowManagementApi({
|
|
15210
|
+
authProvider,
|
|
15211
|
+
defaultEnvironmentId: defaultEnv.id
|
|
15212
|
+
});
|
|
15213
|
+
const result = await flowApi.listFlows({ environment: defaultEnv.id, top: 1 });
|
|
15214
|
+
const count = result.flows.length;
|
|
15215
|
+
console.error(` Environment: ${defaultEnv.name} (${defaultEnv.id})`);
|
|
15216
|
+
console.error(` Flow API reachable (${count >= 1 ? "flows found" : "connected"})`);
|
|
15217
|
+
console.error(" \u2713 Connectivity valid\n");
|
|
15218
|
+
} catch (err) {
|
|
15219
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
15220
|
+
console.error(` \u2717 Connectivity error: ${msg}
|
|
15221
|
+
`);
|
|
15222
|
+
process.exit(1);
|
|
15223
|
+
}
|
|
15224
|
+
console.error("All checks passed. Server is ready to run.\n");
|
|
15225
|
+
process.exit(0);
|
|
15226
|
+
}
|
|
15227
|
+
|
|
14974
15228
|
// src/index.ts
|
|
14975
15229
|
function parseArgs() {
|
|
14976
15230
|
const args = process.argv.slice(2);
|
|
@@ -14982,11 +15236,27 @@ function parseArgs() {
|
|
|
14982
15236
|
port = parsed;
|
|
14983
15237
|
}
|
|
14984
15238
|
}
|
|
15239
|
+
let env2;
|
|
15240
|
+
const envIdx = args.indexOf("--env");
|
|
15241
|
+
if (envIdx !== -1 && args[envIdx + 1] && !args[envIdx + 1].startsWith("-")) {
|
|
15242
|
+
env2 = args[envIdx + 1];
|
|
15243
|
+
}
|
|
15244
|
+
let config;
|
|
15245
|
+
const configIdx = args.indexOf("--config");
|
|
15246
|
+
if (configIdx !== -1 && args[configIdx + 1] && !args[configIdx + 1].startsWith("-")) {
|
|
15247
|
+
config = args[configIdx + 1];
|
|
15248
|
+
}
|
|
14985
15249
|
return {
|
|
14986
15250
|
setup: args.includes("--setup") || args.includes("-s"),
|
|
14987
15251
|
help: args.includes("--help") || args.includes("-h"),
|
|
15252
|
+
version: args.includes("--version") || args.includes("-v"),
|
|
15253
|
+
validate: args.includes("--validate"),
|
|
15254
|
+
update: args.includes("--update"),
|
|
14988
15255
|
http: args.includes("--http"),
|
|
14989
|
-
port
|
|
15256
|
+
port,
|
|
15257
|
+
env: env2,
|
|
15258
|
+
config,
|
|
15259
|
+
debug: args.includes("--debug")
|
|
14990
15260
|
};
|
|
14991
15261
|
}
|
|
14992
15262
|
function getConfigPathHint() {
|
|
@@ -15000,16 +15270,23 @@ function getConfigPathHint() {
|
|
|
15000
15270
|
}
|
|
15001
15271
|
function printHelp() {
|
|
15002
15272
|
const configPath = getConfigPathHint();
|
|
15273
|
+
const version = getInstalledVersion();
|
|
15003
15274
|
console.log(`
|
|
15004
|
-
Power Automate MCP Server
|
|
15275
|
+
Power Automate MCP Server v${version}
|
|
15005
15276
|
|
|
15006
15277
|
Usage: powerautomate-mcp [options]
|
|
15007
15278
|
|
|
15008
15279
|
Options:
|
|
15009
|
-
--setup, -s
|
|
15010
|
-
--
|
|
15011
|
-
--
|
|
15012
|
-
--
|
|
15280
|
+
--setup, -s Run the interactive setup wizard
|
|
15281
|
+
--validate Verify config, auth, and API connectivity then exit
|
|
15282
|
+
--update Check for updates and install the latest version
|
|
15283
|
+
--version, -v Print version and exit
|
|
15284
|
+
--http Start with Streamable HTTP transport (for ChatGPT / remote clients)
|
|
15285
|
+
--port <N> Port for HTTP transport (default: 3000)
|
|
15286
|
+
--env <name> Override the default environment (alias or GUID)
|
|
15287
|
+
--config <path> Use an alternate config file
|
|
15288
|
+
--debug Enable debug-level logging
|
|
15289
|
+
--help, -h Show this help message
|
|
15013
15290
|
|
|
15014
15291
|
First Run:
|
|
15015
15292
|
If no configuration exists, the setup wizard will run automatically.
|
|
@@ -15023,10 +15300,30 @@ For more information, see the README.md file.
|
|
|
15023
15300
|
}
|
|
15024
15301
|
async function main() {
|
|
15025
15302
|
const args = parseArgs();
|
|
15303
|
+
if (args.version) {
|
|
15304
|
+
console.log(getInstalledVersion());
|
|
15305
|
+
process.exit(0);
|
|
15306
|
+
}
|
|
15026
15307
|
if (args.help) {
|
|
15027
15308
|
printHelp();
|
|
15028
15309
|
process.exit(0);
|
|
15029
15310
|
}
|
|
15311
|
+
if (args.update) {
|
|
15312
|
+
await runSelfUpdate();
|
|
15313
|
+
return;
|
|
15314
|
+
}
|
|
15315
|
+
if (args.debug) {
|
|
15316
|
+
logger.level = "debug";
|
|
15317
|
+
logger.debug("Debug logging enabled via --debug");
|
|
15318
|
+
}
|
|
15319
|
+
if (args.config) {
|
|
15320
|
+
process.env["PA_CONFIG_PATH"] = args.config;
|
|
15321
|
+
logger.debug({ configPath: args.config }, "Using custom config path");
|
|
15322
|
+
}
|
|
15323
|
+
if (args.validate) {
|
|
15324
|
+
await runValidate();
|
|
15325
|
+
return;
|
|
15326
|
+
}
|
|
15030
15327
|
if (args.setup || isSetupNeeded()) {
|
|
15031
15328
|
const result = await runSetupWizard();
|
|
15032
15329
|
if (!result.success) {
|
|
@@ -15039,7 +15336,11 @@ Setup failed: ${result.error}`);
|
|
|
15039
15336
|
process.exit(0);
|
|
15040
15337
|
}
|
|
15041
15338
|
}
|
|
15042
|
-
logger.info(
|
|
15339
|
+
logger.info(
|
|
15340
|
+
{ platform: process.platform, nodeVersion: process.version, version: getInstalledVersion() },
|
|
15341
|
+
"Starting Power Automate MCP"
|
|
15342
|
+
);
|
|
15343
|
+
backgroundUpdateCheck();
|
|
15043
15344
|
let config;
|
|
15044
15345
|
try {
|
|
15045
15346
|
config = loadConfig();
|
|
@@ -15056,6 +15357,10 @@ Configuration Error: ${error.message}
|
|
|
15056
15357
|
}
|
|
15057
15358
|
throw error;
|
|
15058
15359
|
}
|
|
15360
|
+
if (args.env) {
|
|
15361
|
+
config.environments.default = args.env;
|
|
15362
|
+
logger.info({ env: args.env }, "Default environment overridden via --env");
|
|
15363
|
+
}
|
|
15059
15364
|
try {
|
|
15060
15365
|
const { start } = await createMcpServer({
|
|
15061
15366
|
config,
|