@topolo/mcp 0.11.9 → 0.11.11
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 +87 -46
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1540,7 +1540,9 @@ var TopoloClient = class _TopoloClient {
|
|
|
1540
1540
|
};
|
|
1541
1541
|
}
|
|
1542
1542
|
planResolvedAction(entry, input, options) {
|
|
1543
|
-
const
|
|
1543
|
+
const inputValidation = validateTopoloActionInput(entry.inputSchema, input);
|
|
1544
|
+
const resourceIssue = validateActionResource(entry, options.resource);
|
|
1545
|
+
const validation = resourceIssue ? { valid: false, errors: [...inputValidation.errors, resourceIssue] } : inputValidation;
|
|
1544
1546
|
const agentAccess = entry.agentAccess ?? (entry.destructive ? "off" : entry.readOnly && !entry.requiresConfirmation ? "auto" : "confirm");
|
|
1545
1547
|
const confirmationRequired = agentAccess === "confirm" || entry.requiresConfirmation || entry.destructive;
|
|
1546
1548
|
let request = null;
|
|
@@ -1599,6 +1601,13 @@ var TopoloClient = class _TopoloClient {
|
|
|
1599
1601
|
`Topolo action "${entry.actionId}" input is invalid: ${validation.errors.map((issue) => `${issue.path} ${issue.message}`).join("; ")}`
|
|
1600
1602
|
);
|
|
1601
1603
|
}
|
|
1604
|
+
const resourceIssue = validateActionResource(entry, options.resource);
|
|
1605
|
+
if (resourceIssue) {
|
|
1606
|
+
throw new TopoloSdkError(
|
|
1607
|
+
"invalid_action_resource",
|
|
1608
|
+
`Topolo action "${entry.actionId}" resource context is invalid: ${resourceIssue.message}`
|
|
1609
|
+
);
|
|
1610
|
+
}
|
|
1602
1611
|
const mapped = mapActionInput(entry, input);
|
|
1603
1612
|
const service = entry.appSlug || entry.appId;
|
|
1604
1613
|
const result = await this.request({
|
|
@@ -1661,6 +1670,32 @@ var TopoloClient = class _TopoloClient {
|
|
|
1661
1670
|
};
|
|
1662
1671
|
}
|
|
1663
1672
|
};
|
|
1673
|
+
function validateActionResource(entry, resource) {
|
|
1674
|
+
const permissionName = entry.permissionName || entry.requiredPermission.split(".").at(-1) || "";
|
|
1675
|
+
if (!permissionName.startsWith("workspace:")) return null;
|
|
1676
|
+
if (!resource) {
|
|
1677
|
+
return {
|
|
1678
|
+
path: "$.resource",
|
|
1679
|
+
code: "required",
|
|
1680
|
+
message: "Select a workspace with the application resource catalog before planning or calling this action."
|
|
1681
|
+
};
|
|
1682
|
+
}
|
|
1683
|
+
if (resource.resourceType !== "workspace") {
|
|
1684
|
+
return {
|
|
1685
|
+
path: "$.resource.resourceType",
|
|
1686
|
+
code: "const",
|
|
1687
|
+
message: 'This action requires resourceType "workspace".'
|
|
1688
|
+
};
|
|
1689
|
+
}
|
|
1690
|
+
if (!resource.resourceId.trim()) {
|
|
1691
|
+
return {
|
|
1692
|
+
path: "$.resource.resourceId",
|
|
1693
|
+
code: "required",
|
|
1694
|
+
message: "This action requires a workspace resourceId."
|
|
1695
|
+
};
|
|
1696
|
+
}
|
|
1697
|
+
return null;
|
|
1698
|
+
}
|
|
1664
1699
|
function resolveConfiguredAppId(slug, appIds) {
|
|
1665
1700
|
for (const serviceKey of serviceKeyCandidates2(slug)) {
|
|
1666
1701
|
const configured = appIds?.[serviceKey];
|
|
@@ -2818,52 +2853,58 @@ async function refreshCredentialIfNeeded(environment = selectedEnvironment(), op
|
|
|
2818
2853
|
if (process.env[`${prefix}_API_KEY`] || process.env[`${prefix}_ACCESS_TOKEN`] || environment === "production" && process.env.TOPOLO_API_KEY || environment === "production" && process.env.TOPOLO_ACCESS_TOKEN) {
|
|
2819
2854
|
return resolveCredential(environment);
|
|
2820
2855
|
}
|
|
2821
|
-
const
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
);
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2856
|
+
const observed = profileForEnvironment(await readConfig(), environment).credential;
|
|
2857
|
+
return withConfigWriteLock(async () => {
|
|
2858
|
+
const config = await readConfig();
|
|
2859
|
+
const profile = profileForEnvironment(config, environment);
|
|
2860
|
+
const cred = profile.credential;
|
|
2861
|
+
if (!cred || cred.kind !== "access_token") return cred ?? null;
|
|
2862
|
+
if (!cred.refreshToken || !profile.oauthClientId) return cred;
|
|
2863
|
+
if (options.force && observed?.kind === "access_token" && observed.accessToken !== cred.accessToken) {
|
|
2864
|
+
return cred;
|
|
2865
|
+
}
|
|
2866
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
2867
|
+
if (!options.force && cred.expiresAt && cred.expiresAt - REFRESH_SKEW_SECONDS > now) return cred;
|
|
2868
|
+
const serviceUrls = resolveServiceUrls(profile.serviceUrls, environment);
|
|
2869
|
+
if (environment === "local" && !serviceUrls?.auth) {
|
|
2870
|
+
throw new TopoloSdkError2(
|
|
2871
|
+
"environment_service_url_required",
|
|
2872
|
+
"Local Topolo credential refresh requires an explicit local Auth service origin."
|
|
2873
|
+
);
|
|
2874
|
+
}
|
|
2875
|
+
try {
|
|
2876
|
+
const oauth = new TopoloOAuth({
|
|
2877
|
+
serviceUrls
|
|
2878
|
+
});
|
|
2879
|
+
const tokens = await oauth.refreshToken({
|
|
2880
|
+
clientId: profile.oauthClientId,
|
|
2881
|
+
refreshToken: cred.refreshToken
|
|
2882
|
+
});
|
|
2883
|
+
const refreshed = {
|
|
2884
|
+
kind: "access_token",
|
|
2885
|
+
accessToken: tokens.access_token,
|
|
2886
|
+
...tokens.refresh_token ? { refreshToken: tokens.refresh_token } : { refreshToken: cred.refreshToken },
|
|
2887
|
+
expiresAt: Math.floor(Date.now() / 1e3) + tokens.expires_in
|
|
2888
|
+
};
|
|
2889
|
+
const activeContext = profile.activeContext;
|
|
2890
|
+
const activeEntry = activeContext ? profile.contexts?.[activeContext] : void 0;
|
|
2891
|
+
const updated = activeContext && activeEntry ? writeProfileConfig(config, environment, {
|
|
2892
|
+
credential: refreshed,
|
|
2893
|
+
contexts: {
|
|
2894
|
+
...profile.contexts ?? {},
|
|
2895
|
+
[activeContext]: {
|
|
2896
|
+
...activeEntry,
|
|
2897
|
+
credential: refreshed,
|
|
2898
|
+
oauthClientId: activeEntry.oauthClientId ?? profile.oauthClientId
|
|
2899
|
+
}
|
|
2859
2900
|
}
|
|
2860
|
-
}
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
}
|
|
2901
|
+
}) : environment === "production" && !config.profiles?.production ? { ...config, credential: refreshed } : writeProfileConfig(config, environment, { credential: refreshed });
|
|
2902
|
+
await writeConfig(updated);
|
|
2903
|
+
return refreshed;
|
|
2904
|
+
} catch {
|
|
2905
|
+
return cred;
|
|
2906
|
+
}
|
|
2907
|
+
});
|
|
2867
2908
|
}
|
|
2868
2909
|
async function refreshContextCredentialIfNeeded(environment, key, options = {}) {
|
|
2869
2910
|
return withConfigWriteLock(async () => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topolo/mcp",
|
|
3
|
-
"version": "0.11.
|
|
4
|
-
"topoloPublishedVersion": "0.11.
|
|
3
|
+
"version": "0.11.11",
|
|
4
|
+
"topoloPublishedVersion": "0.11.11",
|
|
5
5
|
"description": "Model Context Protocol server for the Topolo platform. Exposes scope-gated tools that third-party agents (Claude, Codex, etc.) can call natively.",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"author": "Topolo",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
38
|
-
"@topolo/sdk": "0.11.
|
|
38
|
+
"@topolo/sdk": "0.11.11"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^20.12.0",
|