powerautomate-mcp 0.6.0 → 0.7.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 +283 -53
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -382,6 +382,20 @@ Create the file with your Microsoft Entra app client ID and Power Automate envir
|
|
|
382
382
|
);
|
|
383
383
|
}
|
|
384
384
|
parsed = interpolateEnvVars(parsed);
|
|
385
|
+
const envClientId = env["PA_MCP_CLIENT_ID"];
|
|
386
|
+
if (envClientId) {
|
|
387
|
+
const UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
388
|
+
if (!UUID_RE3.test(envClientId)) {
|
|
389
|
+
throw new ConfigurationError(
|
|
390
|
+
`PA_MCP_CLIENT_ID is not a valid UUID: ${envClientId.substring(0, 50)}`
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
parsed.auth = {
|
|
394
|
+
...parsed.auth ?? {},
|
|
395
|
+
clientId: envClientId
|
|
396
|
+
};
|
|
397
|
+
logger.info("Using client ID from PA_MCP_CLIENT_ID environment variable");
|
|
398
|
+
}
|
|
385
399
|
try {
|
|
386
400
|
const config = validateConfig(parsed);
|
|
387
401
|
logger.info(
|
|
@@ -5009,15 +5023,52 @@ var KNOWN_FUNCTIONS = /* @__PURE__ */ new Set([
|
|
|
5009
5023
|
"uriQuery",
|
|
5010
5024
|
"uriScheme"
|
|
5011
5025
|
]);
|
|
5012
|
-
|
|
5026
|
+
function extractWrappedExpressions(text) {
|
|
5027
|
+
const expressions = [];
|
|
5028
|
+
for (let i = 0; i < text.length - 1; i++) {
|
|
5029
|
+
if (text[i] !== "@") continue;
|
|
5030
|
+
if (text[i + 1] !== "{") continue;
|
|
5031
|
+
if (i > 0 && text[i - 1] === "@") continue;
|
|
5032
|
+
let depth = 0;
|
|
5033
|
+
let inString = false;
|
|
5034
|
+
let stringChar = "";
|
|
5035
|
+
let end = -1;
|
|
5036
|
+
for (let j = i + 2; j < text.length; j++) {
|
|
5037
|
+
const char = text[j];
|
|
5038
|
+
const prevChar = j > i + 2 ? text[j - 1] : "";
|
|
5039
|
+
if ((char === "'" || char === '"') && prevChar !== "\\") {
|
|
5040
|
+
if (!inString) {
|
|
5041
|
+
inString = true;
|
|
5042
|
+
stringChar = char;
|
|
5043
|
+
} else if (char === stringChar) {
|
|
5044
|
+
inString = false;
|
|
5045
|
+
}
|
|
5046
|
+
continue;
|
|
5047
|
+
}
|
|
5048
|
+
if (inString) continue;
|
|
5049
|
+
if (char === "{") {
|
|
5050
|
+
depth++;
|
|
5051
|
+
continue;
|
|
5052
|
+
}
|
|
5053
|
+
if (char === "}") {
|
|
5054
|
+
if (depth === 0) {
|
|
5055
|
+
end = j;
|
|
5056
|
+
break;
|
|
5057
|
+
}
|
|
5058
|
+
depth--;
|
|
5059
|
+
}
|
|
5060
|
+
}
|
|
5061
|
+
if (end !== -1) {
|
|
5062
|
+
expressions.push(text.slice(i + 2, end));
|
|
5063
|
+
i = end;
|
|
5064
|
+
}
|
|
5065
|
+
}
|
|
5066
|
+
return expressions;
|
|
5067
|
+
}
|
|
5013
5068
|
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;
|
|
5014
5069
|
function extractExpressions(text) {
|
|
5015
|
-
const expressions =
|
|
5070
|
+
const expressions = extractWrappedExpressions(text);
|
|
5016
5071
|
let match;
|
|
5017
|
-
while ((match = EXPRESSION_REGEX.exec(text)) !== null) {
|
|
5018
|
-
if (match[1]) expressions.push(match[1]);
|
|
5019
|
-
}
|
|
5020
|
-
EXPRESSION_REGEX.lastIndex = 0;
|
|
5021
5072
|
while ((match = BARE_EXPRESSION_REGEX.exec(text)) !== null) {
|
|
5022
5073
|
if (match[1]) expressions.push(match[1]);
|
|
5023
5074
|
}
|
|
@@ -5493,6 +5544,160 @@ function getAllValidationWarnings(result) {
|
|
|
5493
5544
|
return warnings;
|
|
5494
5545
|
}
|
|
5495
5546
|
|
|
5547
|
+
// src/utils/expression-escape.ts
|
|
5548
|
+
var logger3 = createChildLogger({ module: "expression-escape" });
|
|
5549
|
+
function containsExpressions(value) {
|
|
5550
|
+
if (typeof value === "string") {
|
|
5551
|
+
return value.includes("@{") || value.startsWith("@") && !value.startsWith("@@");
|
|
5552
|
+
}
|
|
5553
|
+
if (Array.isArray(value)) {
|
|
5554
|
+
return value.some(containsExpressions);
|
|
5555
|
+
}
|
|
5556
|
+
if (value && typeof value === "object") {
|
|
5557
|
+
return Object.values(value).some(containsExpressions);
|
|
5558
|
+
}
|
|
5559
|
+
return false;
|
|
5560
|
+
}
|
|
5561
|
+
function objectToStringExpression(obj) {
|
|
5562
|
+
const jsonStr = JSON.stringify(obj);
|
|
5563
|
+
const segments = [];
|
|
5564
|
+
let pos = 0;
|
|
5565
|
+
while (pos < jsonStr.length) {
|
|
5566
|
+
const exprStart = jsonStr.indexOf("@{", pos);
|
|
5567
|
+
if (exprStart === -1) {
|
|
5568
|
+
segments.push("'" + escapeForConcat(jsonStr.slice(pos)) + "'");
|
|
5569
|
+
break;
|
|
5570
|
+
}
|
|
5571
|
+
const isJsonStringValue = exprStart > 0 && jsonStr[exprStart - 1] === '"';
|
|
5572
|
+
if (exprStart > pos) {
|
|
5573
|
+
let literal = jsonStr.slice(pos, exprStart);
|
|
5574
|
+
if (isJsonStringValue) {
|
|
5575
|
+
literal = literal.slice(0, -1);
|
|
5576
|
+
}
|
|
5577
|
+
if (literal.length > 0) {
|
|
5578
|
+
segments.push("'" + escapeForConcat(literal) + "'");
|
|
5579
|
+
}
|
|
5580
|
+
}
|
|
5581
|
+
let depth = 0;
|
|
5582
|
+
let exprEnd = -1;
|
|
5583
|
+
for (let i = exprStart + 2; i < jsonStr.length; i++) {
|
|
5584
|
+
if (jsonStr[i] === "{") depth++;
|
|
5585
|
+
else if (jsonStr[i] === "}") {
|
|
5586
|
+
if (depth === 0) {
|
|
5587
|
+
exprEnd = i;
|
|
5588
|
+
break;
|
|
5589
|
+
}
|
|
5590
|
+
depth--;
|
|
5591
|
+
}
|
|
5592
|
+
}
|
|
5593
|
+
if (exprEnd === -1) {
|
|
5594
|
+
segments.push("'" + escapeForConcat(jsonStr.slice(exprStart)) + "'");
|
|
5595
|
+
break;
|
|
5596
|
+
}
|
|
5597
|
+
const expr = jsonStr.slice(exprStart + 2, exprEnd);
|
|
5598
|
+
if (isJsonStringValue) {
|
|
5599
|
+
segments.push(`'"'`);
|
|
5600
|
+
segments.push(expr);
|
|
5601
|
+
segments.push(`'"'`);
|
|
5602
|
+
} else {
|
|
5603
|
+
segments.push(expr);
|
|
5604
|
+
}
|
|
5605
|
+
pos = exprEnd + 1;
|
|
5606
|
+
if (isJsonStringValue && pos < jsonStr.length && jsonStr[pos] === '"') {
|
|
5607
|
+
pos++;
|
|
5608
|
+
}
|
|
5609
|
+
}
|
|
5610
|
+
const filtered = segments.filter((s) => s !== "''" && s !== "");
|
|
5611
|
+
if (filtered.length === 0) return jsonStr;
|
|
5612
|
+
if (filtered.length === 1 && !filtered[0].startsWith("'")) {
|
|
5613
|
+
return `@{${filtered[0]}}`;
|
|
5614
|
+
}
|
|
5615
|
+
return `@{json(concat(${filtered.join(",")}))}`;
|
|
5616
|
+
}
|
|
5617
|
+
function escapeForConcat(s) {
|
|
5618
|
+
return s.replace(/'/g, "''");
|
|
5619
|
+
}
|
|
5620
|
+
function preprocessActionInputs(inputs, actionName) {
|
|
5621
|
+
const processedInputs = { ...inputs };
|
|
5622
|
+
if (processedInputs.body && typeof processedInputs.body === "object") {
|
|
5623
|
+
const bodyStr = JSON.stringify(processedInputs.body);
|
|
5624
|
+
const hasAtKeys = /"@[a-zA-Z]/.test(bodyStr);
|
|
5625
|
+
if (hasAtKeys || containsExpressions(processedInputs.body)) {
|
|
5626
|
+
logger3.info({ action: actionName, field: "body", hasAtKeys }, "Converting action payload object to string expression");
|
|
5627
|
+
processedInputs.body = objectToStringExpression(processedInputs.body);
|
|
5628
|
+
}
|
|
5629
|
+
}
|
|
5630
|
+
if (processedInputs.parameters && typeof processedInputs.parameters === "object" && !Array.isArray(processedInputs.parameters)) {
|
|
5631
|
+
const parameters = processedInputs.parameters;
|
|
5632
|
+
let changed = false;
|
|
5633
|
+
const processedParameters = { ...parameters };
|
|
5634
|
+
for (const [key, value] of Object.entries(parameters)) {
|
|
5635
|
+
if (value && typeof value === "object" && containsExpressions(value)) {
|
|
5636
|
+
logger3.info({ action: actionName, field: `parameters.${key}` }, "Converting connector parameter object to string expression");
|
|
5637
|
+
processedParameters[key] = objectToStringExpression(value);
|
|
5638
|
+
changed = true;
|
|
5639
|
+
}
|
|
5640
|
+
}
|
|
5641
|
+
if (changed) {
|
|
5642
|
+
processedInputs.parameters = processedParameters;
|
|
5643
|
+
}
|
|
5644
|
+
}
|
|
5645
|
+
return processedInputs;
|
|
5646
|
+
}
|
|
5647
|
+
function preprocessFlowActions(actions) {
|
|
5648
|
+
const processed = {};
|
|
5649
|
+
for (const [name, action] of Object.entries(actions)) {
|
|
5650
|
+
if (!action || typeof action !== "object") {
|
|
5651
|
+
processed[name] = action;
|
|
5652
|
+
continue;
|
|
5653
|
+
}
|
|
5654
|
+
const actionObj = action;
|
|
5655
|
+
processed[name] = { ...actionObj };
|
|
5656
|
+
const processedAction = processed[name];
|
|
5657
|
+
if (actionObj.inputs && typeof actionObj.inputs === "object") {
|
|
5658
|
+
processedAction.inputs = preprocessActionInputs(
|
|
5659
|
+
actionObj.inputs,
|
|
5660
|
+
name
|
|
5661
|
+
);
|
|
5662
|
+
}
|
|
5663
|
+
if (actionObj.actions && typeof actionObj.actions === "object") {
|
|
5664
|
+
processedAction.actions = preprocessFlowActions(
|
|
5665
|
+
actionObj.actions
|
|
5666
|
+
);
|
|
5667
|
+
}
|
|
5668
|
+
if (actionObj.else && typeof actionObj.else === "object") {
|
|
5669
|
+
const elseBranch = actionObj.else;
|
|
5670
|
+
if (elseBranch.actions && typeof elseBranch.actions === "object") {
|
|
5671
|
+
processedAction.else = {
|
|
5672
|
+
...elseBranch,
|
|
5673
|
+
actions: preprocessFlowActions(elseBranch.actions)
|
|
5674
|
+
};
|
|
5675
|
+
}
|
|
5676
|
+
}
|
|
5677
|
+
if (actionObj.cases && typeof actionObj.cases === "object") {
|
|
5678
|
+
const cases = actionObj.cases;
|
|
5679
|
+
const processedCases = {};
|
|
5680
|
+
for (const [caseName, caseVal] of Object.entries(cases)) {
|
|
5681
|
+
if (caseVal && typeof caseVal === "object") {
|
|
5682
|
+
const cv = caseVal;
|
|
5683
|
+
if (cv.actions && typeof cv.actions === "object") {
|
|
5684
|
+
processedCases[caseName] = {
|
|
5685
|
+
...cv,
|
|
5686
|
+
actions: preprocessFlowActions(cv.actions)
|
|
5687
|
+
};
|
|
5688
|
+
} else {
|
|
5689
|
+
processedCases[caseName] = caseVal;
|
|
5690
|
+
}
|
|
5691
|
+
} else {
|
|
5692
|
+
processedCases[caseName] = caseVal;
|
|
5693
|
+
}
|
|
5694
|
+
}
|
|
5695
|
+
processedAction.cases = processedCases;
|
|
5696
|
+
}
|
|
5697
|
+
}
|
|
5698
|
+
return processed;
|
|
5699
|
+
}
|
|
5700
|
+
|
|
5496
5701
|
// src/tools/create-flow.ts
|
|
5497
5702
|
var triggerSchema = z.object({
|
|
5498
5703
|
type: z.string().describe("Trigger type (e.g., 'Request', 'Recurrence', 'OpenApiConnection')"),
|
|
@@ -5601,13 +5806,14 @@ var createFlowTool = {
|
|
|
5601
5806
|
async function handleCreateFlow(api, input) {
|
|
5602
5807
|
const parsed = createFlowInputSchema.parse(input);
|
|
5603
5808
|
logger.info({ displayName: parsed.displayName }, "Executing create_flow");
|
|
5809
|
+
const processedActions = preprocessFlowActions(parsed.actions);
|
|
5604
5810
|
const definition = {
|
|
5605
5811
|
$schema: "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
|
|
5606
5812
|
contentVersion: "1.0.0.0",
|
|
5607
5813
|
triggers: {
|
|
5608
5814
|
[parsed.triggerName ?? "manual"]: parsed.trigger
|
|
5609
5815
|
},
|
|
5610
|
-
actions:
|
|
5816
|
+
actions: processedActions
|
|
5611
5817
|
};
|
|
5612
5818
|
if (parsed.connectionReferences && Object.keys(parsed.connectionReferences).length > 0) {
|
|
5613
5819
|
definition.parameters = {
|
|
@@ -5782,11 +5988,12 @@ async function handleUpdateFlow(api, input) {
|
|
|
5782
5988
|
let newDefinition;
|
|
5783
5989
|
if (parsed.trigger || parsed.actions) {
|
|
5784
5990
|
const triggerName = parsed.triggerName ?? Object.keys(currentDef.triggers)[0] ?? "manual";
|
|
5991
|
+
const processedActions = parsed.actions ? preprocessFlowActions(parsed.actions) : currentDef.actions;
|
|
5785
5992
|
newDefinition = {
|
|
5786
5993
|
$schema: currentDef.$schema,
|
|
5787
5994
|
contentVersion: currentDef.contentVersion,
|
|
5788
5995
|
triggers: parsed.trigger ? { [triggerName]: parsed.trigger } : currentDef.triggers,
|
|
5789
|
-
actions:
|
|
5996
|
+
actions: processedActions
|
|
5790
5997
|
};
|
|
5791
5998
|
if (currentDef.parameters) {
|
|
5792
5999
|
newDefinition.parameters = currentDef.parameters;
|
|
@@ -14705,7 +14912,6 @@ function getDefaultEnvironment(environments) {
|
|
|
14705
14912
|
}
|
|
14706
14913
|
|
|
14707
14914
|
// src/setup/published-app.ts
|
|
14708
|
-
var PUBLISHED_APP_CLIENT_ID = "20ae33ee-6743-4786-9b00-8eb7bfebfd11";
|
|
14709
14915
|
var APP_DISPLAY_NAME = "Power Automate MCP";
|
|
14710
14916
|
var REDIRECT_URI = "https://login.microsoftonline.com/common/oauth2/nativeclient";
|
|
14711
14917
|
var REQUIRED_RESOURCE_ACCESS = [
|
|
@@ -14720,8 +14926,10 @@ var REQUIRED_RESOURCE_ACCESS = [
|
|
|
14720
14926
|
{
|
|
14721
14927
|
resourceAppId: "7df0a125-d3be-4c96-aa54-591f83ff541c",
|
|
14722
14928
|
resourceAccess: [
|
|
14723
|
-
{ id: "
|
|
14724
|
-
{ id: "
|
|
14929
|
+
{ id: "e45c5562-459d-4d1b-8148-83eb1b6dcf83", type: "Scope" },
|
|
14930
|
+
{ id: "30b2d850-00c3-4802-b7ae-ece9af9de5c6", type: "Scope" },
|
|
14931
|
+
{ id: "822a9cde-503a-472d-a530-d1dc9cd0d52b", type: "Scope" },
|
|
14932
|
+
{ id: "d05743e4-fb24-4dff-8a33-0f6c73c964bd", type: "Scope" }
|
|
14725
14933
|
]
|
|
14726
14934
|
},
|
|
14727
14935
|
{
|
|
@@ -14809,6 +15017,8 @@ async function createAppRegistration(displayName) {
|
|
|
14809
15017
|
"false",
|
|
14810
15018
|
"--enable-id-token-issuance",
|
|
14811
15019
|
"false",
|
|
15020
|
+
"--is-fallback-public-client",
|
|
15021
|
+
"true",
|
|
14812
15022
|
"--public-client-redirect-uris",
|
|
14813
15023
|
REDIRECT_URI,
|
|
14814
15024
|
"--required-resource-accesses",
|
|
@@ -14925,56 +15135,69 @@ function readExistingAuthConfig() {
|
|
|
14925
15135
|
function readExistingClientId() {
|
|
14926
15136
|
return readExistingAuthConfig().clientId;
|
|
14927
15137
|
}
|
|
14928
|
-
async function
|
|
15138
|
+
async function promptForClientId(askUser) {
|
|
15139
|
+
print("");
|
|
15140
|
+
print(` ${c.yellow}You need a Microsoft Entra app registration for your tenant.${c.reset}`);
|
|
15141
|
+
print(` ${c.dim}Create one in the Azure portal with these delegated permissions:${c.reset}`);
|
|
15142
|
+
print(` ${c.dim}\u2022 Microsoft Graph: User.Read, Sites.ReadWrite.All, Files.ReadWrite.All${c.reset}`);
|
|
15143
|
+
print(` ${c.dim}\u2022 Power Automate: Flows.Read.All, Flows.Manage.All, Activity.Read.All, Approvals.Manage.All${c.reset}`);
|
|
15144
|
+
print(` ${c.dim}\u2022 Dynamics CRM: user_impersonation${c.reset}`);
|
|
15145
|
+
print(` ${c.dim}Enable "Allow public client flows" for device code auth.${c.reset}`);
|
|
15146
|
+
print("");
|
|
15147
|
+
while (true) {
|
|
15148
|
+
const input = await askUser(` ${c.cyan}?${c.reset} Paste your app's ${c.bold}Client ID${c.reset}: `);
|
|
15149
|
+
if (input && UUID_RE2.test(input)) {
|
|
15150
|
+
return input;
|
|
15151
|
+
}
|
|
15152
|
+
print(` ${c.red}Invalid format \u2014 must be a UUID (e.g., 12345678-abcd-1234-abcd-123456789abc)${c.reset}`);
|
|
15153
|
+
}
|
|
15154
|
+
}
|
|
15155
|
+
async function resolveAppRegistration(askUser) {
|
|
15156
|
+
const envClientId = process.env["PA_MCP_CLIENT_ID"];
|
|
15157
|
+
if (envClientId && UUID_RE2.test(envClientId)) {
|
|
15158
|
+
print(` ${icons.check} Using client ID from PA_MCP_CLIENT_ID: ${c.dim}${envClientId}${c.reset}`);
|
|
15159
|
+
return { clientId: envClientId, created: false };
|
|
15160
|
+
}
|
|
14929
15161
|
const existingId = readExistingClientId();
|
|
14930
15162
|
if (existingId) {
|
|
14931
15163
|
print(` ${icons.check} Reusing app from existing config: ${c.dim}${existingId}${c.reset}`);
|
|
14932
15164
|
return { clientId: existingId, created: false };
|
|
14933
15165
|
}
|
|
14934
15166
|
const hasAzCli = await checkAzureCli();
|
|
14935
|
-
if (
|
|
14936
|
-
print(` ${c.dim}Azure CLI
|
|
14937
|
-
print(` ${icons.check} Client ID: ${c.dim}${PUBLISHED_APP_CLIENT_ID}${c.reset}`);
|
|
14938
|
-
return { clientId: PUBLISHED_APP_CLIENT_ID, created: false };
|
|
14939
|
-
}
|
|
14940
|
-
print(` ${c.dim}Azure CLI detected${c.reset}`);
|
|
14941
|
-
try {
|
|
14942
|
-
const azUser = await ensureAzureCliLogin();
|
|
14943
|
-
print(` ${icons.check} Azure CLI signed in as ${c.bold}${azUser}${c.reset}`);
|
|
14944
|
-
} catch (error) {
|
|
14945
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
14946
|
-
print(` ${c.yellow}Azure CLI login failed: ${msg}${c.reset}`);
|
|
14947
|
-
print(` ${c.dim}Falling back to shared app${c.reset}`);
|
|
14948
|
-
print(` ${icons.check} Client ID: ${c.dim}${PUBLISHED_APP_CLIENT_ID}${c.reset}`);
|
|
14949
|
-
return { clientId: PUBLISHED_APP_CLIENT_ID, created: false };
|
|
14950
|
-
}
|
|
14951
|
-
const existingAppId = await findExistingApp(APP_DISPLAY_NAME);
|
|
14952
|
-
if (existingAppId) {
|
|
14953
|
-
print(` ${icons.check} Found existing app: ${c.dim}${existingAppId}${c.reset}`);
|
|
14954
|
-
try {
|
|
14955
|
-
await addWamRedirectUri(existingAppId);
|
|
14956
|
-
} catch {
|
|
14957
|
-
}
|
|
14958
|
-
return { clientId: existingAppId, created: false };
|
|
14959
|
-
}
|
|
14960
|
-
print(` ${c.dim}Creating app registration...${c.reset}`);
|
|
14961
|
-
try {
|
|
14962
|
-
const newId = await createAppRegistration(APP_DISPLAY_NAME);
|
|
14963
|
-
print(` ${icons.check} App created: ${c.dim}${newId}${c.reset}`);
|
|
15167
|
+
if (hasAzCli) {
|
|
15168
|
+
print(` ${c.dim}Azure CLI detected${c.reset}`);
|
|
14964
15169
|
try {
|
|
14965
|
-
await
|
|
14966
|
-
print(` ${icons.check}
|
|
14967
|
-
|
|
14968
|
-
|
|
15170
|
+
const azUser = await ensureAzureCliLogin();
|
|
15171
|
+
print(` ${icons.check} Azure CLI signed in as ${c.bold}${azUser}${c.reset}`);
|
|
15172
|
+
const existingAppId = await findExistingApp(APP_DISPLAY_NAME);
|
|
15173
|
+
if (existingAppId) {
|
|
15174
|
+
print(` ${icons.check} Found existing app: ${c.dim}${existingAppId}${c.reset}`);
|
|
15175
|
+
try {
|
|
15176
|
+
await addWamRedirectUri(existingAppId);
|
|
15177
|
+
} catch {
|
|
15178
|
+
}
|
|
15179
|
+
return { clientId: existingAppId, created: false };
|
|
15180
|
+
}
|
|
15181
|
+
print(` ${c.dim}Creating app registration...${c.reset}`);
|
|
15182
|
+
const newId = await createAppRegistration(APP_DISPLAY_NAME);
|
|
15183
|
+
print(` ${icons.check} App created: ${c.dim}${newId}${c.reset}`);
|
|
15184
|
+
try {
|
|
15185
|
+
await addWamRedirectUri(newId);
|
|
15186
|
+
print(` ${icons.check} WAM redirect URI configured`);
|
|
15187
|
+
} catch {
|
|
15188
|
+
print(` ${c.dim}WAM redirect URI skipped (non-critical)${c.reset}`);
|
|
15189
|
+
}
|
|
15190
|
+
return { clientId: newId, created: true };
|
|
15191
|
+
} catch (error) {
|
|
15192
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
15193
|
+
print(` ${c.yellow}Azure CLI failed: ${msg}${c.reset}`);
|
|
14969
15194
|
}
|
|
14970
|
-
|
|
14971
|
-
}
|
|
14972
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
14973
|
-
print(` ${c.yellow}App creation failed: ${msg}${c.reset}`);
|
|
14974
|
-
print(` ${c.dim}Falling back to shared app${c.reset}`);
|
|
14975
|
-
print(` ${icons.check} Client ID: ${c.dim}${PUBLISHED_APP_CLIENT_ID}${c.reset}`);
|
|
14976
|
-
return { clientId: PUBLISHED_APP_CLIENT_ID, created: false };
|
|
15195
|
+
} else {
|
|
15196
|
+
print(` ${c.dim}Azure CLI not found \u2014 skipping automatic app creation${c.reset}`);
|
|
14977
15197
|
}
|
|
15198
|
+
const manualId = await promptForClientId(askUser);
|
|
15199
|
+
print(` ${icons.check} Client ID: ${c.dim}${manualId}${c.reset}`);
|
|
15200
|
+
return { clientId: manualId, created: false };
|
|
14978
15201
|
}
|
|
14979
15202
|
async function runSetupWizard() {
|
|
14980
15203
|
const rl = createInterface({
|
|
@@ -14992,7 +15215,7 @@ async function runSetupWizard() {
|
|
|
14992
15215
|
printHeader();
|
|
14993
15216
|
const totalSteps = 5;
|
|
14994
15217
|
printStep(1, totalSteps, "App Registration");
|
|
14995
|
-
const appResult = await resolveAppRegistration();
|
|
15218
|
+
const appResult = await resolveAppRegistration(prompt);
|
|
14996
15219
|
const clientId = appResult.clientId;
|
|
14997
15220
|
printStep(2, totalSteps, "Sign In");
|
|
14998
15221
|
const cacheResult = clearTokenCache();
|
|
@@ -15288,10 +15511,17 @@ Options:
|
|
|
15288
15511
|
--debug Enable debug-level logging
|
|
15289
15512
|
--help, -h Show this help message
|
|
15290
15513
|
|
|
15514
|
+
Environment Variables:
|
|
15515
|
+
PA_MCP_CLIENT_ID Microsoft Entra app client ID (overrides config file)
|
|
15516
|
+
PA_CONFIG_PATH Custom path to config.json
|
|
15517
|
+
|
|
15291
15518
|
First Run:
|
|
15292
15519
|
If no configuration exists, the setup wizard will run automatically.
|
|
15293
15520
|
You can also run it manually with --setup.
|
|
15294
15521
|
|
|
15522
|
+
Each tenant needs its own Microsoft Entra app registration.
|
|
15523
|
+
The wizard can create one via Azure CLI, or you can provide one manually.
|
|
15524
|
+
|
|
15295
15525
|
Configuration:
|
|
15296
15526
|
Config file: ${configPath}
|
|
15297
15527
|
|