@topolo/mcp 0.4.4 → 0.4.5
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/dispatch.js +4 -1
- package/dist/index.js +99 -12
- package/package.json +1 -1
package/dist/dispatch.js
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
auditAllApplicationRequirements,
|
|
11
11
|
applicationRequirementScopes,
|
|
12
12
|
requirementsForApplication,
|
|
13
|
+
resolveCatalogServiceUrl,
|
|
13
14
|
resolveServiceUrl
|
|
14
15
|
} from "@topolo/sdk";
|
|
15
16
|
|
|
@@ -87,7 +88,9 @@ var TOOLS = [
|
|
|
87
88
|
slug: entry.slug,
|
|
88
89
|
name: entry.name,
|
|
89
90
|
baseUrl: entry.baseUrl,
|
|
90
|
-
|
|
91
|
+
apiBaseUrl: entry.apiBaseUrl,
|
|
92
|
+
launchUrl: entry.launchUrl,
|
|
93
|
+
effectiveUrl: resolveCatalogServiceUrl(entry, { serviceKey: id }) || resolveServiceUrl(id),
|
|
91
94
|
surfaceKind: entry.surfaceKind,
|
|
92
95
|
launchable: entry.launchable,
|
|
93
96
|
permissions: [...entry.permissions]
|
package/dist/index.js
CHANGED
|
@@ -2040,15 +2040,88 @@ function statusRank(status) {
|
|
|
2040
2040
|
return 2;
|
|
2041
2041
|
}
|
|
2042
2042
|
var DEFAULT_SERVICE_URLS = SERVICES;
|
|
2043
|
+
function resolveCatalogServiceUrl(entry, options = {}) {
|
|
2044
|
+
const keys = catalogServiceKeyCandidates(entry, options.serviceKey);
|
|
2045
|
+
const override = resolveServiceUrlOverride(keys, options.overrides);
|
|
2046
|
+
if (override) return override;
|
|
2047
|
+
const apiBaseUrl = firstString(entry.apiBaseUrl, entry.api_base_url);
|
|
2048
|
+
if (apiBaseUrl) return apiBaseUrl;
|
|
2049
|
+
const bundledUrl = firstBundledServiceUrl(keys);
|
|
2050
|
+
const liveUrl = firstString(entry.baseUrl);
|
|
2051
|
+
if (bundledUrl && (!liveUrl || sameUrlEnvironment(bundledUrl, liveUrl))) return bundledUrl;
|
|
2052
|
+
return liveUrl ?? bundledUrl ?? null;
|
|
2053
|
+
}
|
|
2043
2054
|
function resolveServiceUrl(service, overrides) {
|
|
2044
|
-
const override =
|
|
2055
|
+
const override = resolveServiceUrlOverride([service], overrides);
|
|
2045
2056
|
if (override) return override;
|
|
2046
|
-
const envKey = `TOPOLO_SERVICE_URL_${service.replace(/\./g, "_").toUpperCase()}`;
|
|
2047
|
-
const envValue = typeof process !== "undefined" ? process.env?.[envKey] : void 0;
|
|
2048
|
-
if (envValue) return envValue;
|
|
2049
2057
|
return DEFAULT_SERVICE_URLS[service];
|
|
2050
2058
|
}
|
|
2059
|
+
function catalogServiceKeyCandidates(entry, preferred) {
|
|
2060
|
+
const values = [preferred, entry.slug, entry.name, entry.serviceId].filter(
|
|
2061
|
+
(value) => typeof value === "string" && value.trim().length > 0
|
|
2062
|
+
);
|
|
2063
|
+
const keys = /* @__PURE__ */ new Set();
|
|
2064
|
+
for (const value of values) {
|
|
2065
|
+
for (const candidate of serviceKeyCandidates(value)) keys.add(candidate);
|
|
2066
|
+
}
|
|
2067
|
+
return [...keys];
|
|
2068
|
+
}
|
|
2069
|
+
function serviceKeyCandidates(value) {
|
|
2070
|
+
const normalized = value.trim().toLowerCase().replace(/\s+/g, "-");
|
|
2071
|
+
const withoutTopolo = normalized.startsWith("topolo-") ? normalized.slice("topolo-".length) : normalized;
|
|
2072
|
+
return [.../* @__PURE__ */ new Set([
|
|
2073
|
+
normalized,
|
|
2074
|
+
normalized.replace(/-/g, "_"),
|
|
2075
|
+
withoutTopolo,
|
|
2076
|
+
withoutTopolo.replace(/-/g, "_")
|
|
2077
|
+
])].filter(Boolean);
|
|
2078
|
+
}
|
|
2079
|
+
function resolveServiceUrlOverride(keys, overrides) {
|
|
2080
|
+
for (const key of keys) {
|
|
2081
|
+
const direct = overrides?.[key];
|
|
2082
|
+
if (direct) return direct;
|
|
2083
|
+
const envStyleKey = key.replace(/\./g, "_");
|
|
2084
|
+
const envStyle = overrides?.[envStyleKey];
|
|
2085
|
+
if (envStyle) return envStyle;
|
|
2086
|
+
}
|
|
2087
|
+
for (const key of keys) {
|
|
2088
|
+
const envKey = `TOPOLO_SERVICE_URL_${key.replace(/\./g, "_").toUpperCase()}`;
|
|
2089
|
+
const envValue = typeof process !== "undefined" ? process.env?.[envKey] : void 0;
|
|
2090
|
+
if (envValue) return envValue;
|
|
2091
|
+
}
|
|
2092
|
+
return null;
|
|
2093
|
+
}
|
|
2094
|
+
function firstBundledServiceUrl(keys) {
|
|
2095
|
+
for (const key of keys) {
|
|
2096
|
+
const url = DEFAULT_SERVICE_URLS[key];
|
|
2097
|
+
if (url) return url;
|
|
2098
|
+
}
|
|
2099
|
+
return null;
|
|
2100
|
+
}
|
|
2101
|
+
function firstString(...values) {
|
|
2102
|
+
for (const value of values) {
|
|
2103
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
2104
|
+
}
|
|
2105
|
+
return null;
|
|
2106
|
+
}
|
|
2107
|
+
function sameUrlEnvironment(left, right) {
|
|
2108
|
+
return urlEnvironment(left) === urlEnvironment(right);
|
|
2109
|
+
}
|
|
2110
|
+
function urlEnvironment(value) {
|
|
2111
|
+
try {
|
|
2112
|
+
const url = new URL(value);
|
|
2113
|
+
const host = url.hostname.toLowerCase();
|
|
2114
|
+
if (host === "localhost" || host === "127.0.0.1") return "local";
|
|
2115
|
+
if (host.endsWith(".stg.topolo.us") || host.includes("topolo-staging")) return "staging";
|
|
2116
|
+
if (host.endsWith(".topolo.app") || host.endsWith(".topolo.us")) return "production";
|
|
2117
|
+
return "external";
|
|
2118
|
+
} catch {
|
|
2119
|
+
return "external";
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2051
2122
|
var WRITE_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
2123
|
+
var TOPOLO_ACTION_ID_HEADER = "X-Topolo-Action-Id";
|
|
2124
|
+
var TOPOLO_ACTION_NAME_HEADER = "X-Topolo-Action-Name";
|
|
2052
2125
|
var POSITIVE_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
2053
2126
|
var NEGATIVE_CACHE_TTL_MS = 60 * 1e3;
|
|
2054
2127
|
var CATALOG_CACHE_TTL_MS = 60 * 1e3;
|
|
@@ -2216,8 +2289,12 @@ var TopoloClient = class _TopoloClient {
|
|
|
2216
2289
|
async resolveLiveCallableService(serviceKey) {
|
|
2217
2290
|
const catalog = await this.listServices();
|
|
2218
2291
|
const match = catalog.find((entry) => catalogEntryMatches(entry, serviceKey));
|
|
2219
|
-
if (!match
|
|
2220
|
-
|
|
2292
|
+
if (!match || !isCallableCatalogEntry(match)) return null;
|
|
2293
|
+
const baseUrl = resolveCatalogServiceUrl(match, {
|
|
2294
|
+
serviceKey,
|
|
2295
|
+
overrides: this.serviceUrls
|
|
2296
|
+
});
|
|
2297
|
+
return baseUrl ? { serviceKey, baseUrl } : null;
|
|
2221
2298
|
}
|
|
2222
2299
|
/**
|
|
2223
2300
|
* Resolve a service-slug → opaque service-id via caller config or TopoloAuth.
|
|
@@ -2311,6 +2388,8 @@ var TopoloClient = class _TopoloClient {
|
|
|
2311
2388
|
name: typeof s.name === "string" ? s.name : null,
|
|
2312
2389
|
description: typeof s.description === "string" ? s.description : null,
|
|
2313
2390
|
baseUrl: typeof s.base_url === "string" ? s.base_url : null,
|
|
2391
|
+
apiBaseUrl: typeof s.api_base_url === "string" ? s.api_base_url : typeof s.apiBaseUrl === "string" ? s.apiBaseUrl : null,
|
|
2392
|
+
launchUrl: typeof s.launch_url === "string" ? s.launch_url : typeof s.launchUrl === "string" ? s.launchUrl : null,
|
|
2314
2393
|
status: typeof s.status === "string" ? s.status : null,
|
|
2315
2394
|
surfaceKind: typeof s.surface_kind === "string" ? s.surface_kind : null,
|
|
2316
2395
|
launchable: s.launchable === true,
|
|
@@ -2377,6 +2456,10 @@ var TopoloClient = class _TopoloClient {
|
|
|
2377
2456
|
path: mapped.path,
|
|
2378
2457
|
...mapped.query ? { query: mapped.query } : {},
|
|
2379
2458
|
...mapped.body !== void 0 ? { body: mapped.body } : {},
|
|
2459
|
+
headers: {
|
|
2460
|
+
[TOPOLO_ACTION_ID_HEADER]: entry.actionId,
|
|
2461
|
+
[TOPOLO_ACTION_NAME_HEADER]: entry.name
|
|
2462
|
+
},
|
|
2380
2463
|
confirm: options.confirm === true
|
|
2381
2464
|
});
|
|
2382
2465
|
}
|
|
@@ -2392,6 +2475,8 @@ var TopoloClient = class _TopoloClient {
|
|
|
2392
2475
|
name: app.name ?? app.id,
|
|
2393
2476
|
description: null,
|
|
2394
2477
|
baseUrl: app.productionUrl ?? null,
|
|
2478
|
+
apiBaseUrl: null,
|
|
2479
|
+
launchUrl: app.productionUrl ?? null,
|
|
2395
2480
|
status: "bundled",
|
|
2396
2481
|
surfaceKind: "application",
|
|
2397
2482
|
launchable: Boolean(app.productionUrl),
|
|
@@ -2435,7 +2520,7 @@ var TopoloClient = class _TopoloClient {
|
|
|
2435
2520
|
}
|
|
2436
2521
|
};
|
|
2437
2522
|
function resolveConfiguredServiceId(slug, serviceIds) {
|
|
2438
|
-
for (const serviceKey of
|
|
2523
|
+
for (const serviceKey of serviceKeyCandidates2(slug)) {
|
|
2439
2524
|
const configured = serviceIds?.[serviceKey];
|
|
2440
2525
|
if (typeof configured === "string" && configured.trim()) return configured.trim();
|
|
2441
2526
|
const envKey = `TOPOLO_SERVICE_ID_${serviceKey.replace(/\./g, "_").toUpperCase()}`;
|
|
@@ -2445,7 +2530,7 @@ function resolveConfiguredServiceId(slug, serviceIds) {
|
|
|
2445
2530
|
return null;
|
|
2446
2531
|
}
|
|
2447
2532
|
function resolveConfiguredServiceUrl(slug, serviceUrls) {
|
|
2448
|
-
for (const serviceKey of
|
|
2533
|
+
for (const serviceKey of serviceKeyCandidates2(slug)) {
|
|
2449
2534
|
const configured = serviceUrls?.[serviceKey];
|
|
2450
2535
|
if (typeof configured === "string" && configured.trim()) return configured.trim();
|
|
2451
2536
|
const envKey = `TOPOLO_SERVICE_URL_${serviceKey.replace(/\./g, "_").toUpperCase()}`;
|
|
@@ -2454,7 +2539,7 @@ function resolveConfiguredServiceUrl(slug, serviceUrls) {
|
|
|
2454
2539
|
}
|
|
2455
2540
|
return null;
|
|
2456
2541
|
}
|
|
2457
|
-
function
|
|
2542
|
+
function serviceKeyCandidates2(slug) {
|
|
2458
2543
|
const normalized = normalizeLookupKey(slug);
|
|
2459
2544
|
const withoutTopolo = normalized.startsWith("topolo-") ? normalized.slice("topolo-".length) : normalized;
|
|
2460
2545
|
return [.../* @__PURE__ */ new Set([
|
|
@@ -2476,7 +2561,7 @@ function catalogEntryLookupKeys(entry) {
|
|
|
2476
2561
|
for (const value of values) {
|
|
2477
2562
|
const normalized = normalizeLookupKey(value);
|
|
2478
2563
|
if (!normalized) continue;
|
|
2479
|
-
for (const candidate of
|
|
2564
|
+
for (const candidate of serviceKeyCandidates2(normalized)) {
|
|
2480
2565
|
keys.add(candidate);
|
|
2481
2566
|
}
|
|
2482
2567
|
}
|
|
@@ -2486,7 +2571,7 @@ function isCallableCatalogEntry(entry) {
|
|
|
2486
2571
|
const kind = normalizeLookupKey(entry.surfaceKind || "");
|
|
2487
2572
|
if (kind === "api" || kind === "technical_service" || kind === "service") return true;
|
|
2488
2573
|
return Boolean(
|
|
2489
|
-
entry.baseUrl && catalogEntryLookupKeys(entry).some((key) => Object.prototype.hasOwnProperty.call(DEFAULT_SERVICE_URLS, key))
|
|
2574
|
+
(entry.baseUrl || entry.apiBaseUrl) && catalogEntryLookupKeys(entry).some((key) => Object.prototype.hasOwnProperty.call(DEFAULT_SERVICE_URLS, key))
|
|
2490
2575
|
);
|
|
2491
2576
|
}
|
|
2492
2577
|
function normalizeActionCatalogEntry(item) {
|
|
@@ -2781,7 +2866,9 @@ var TOOLS = [
|
|
|
2781
2866
|
slug: entry.slug,
|
|
2782
2867
|
name: entry.name,
|
|
2783
2868
|
baseUrl: entry.baseUrl,
|
|
2784
|
-
|
|
2869
|
+
apiBaseUrl: entry.apiBaseUrl,
|
|
2870
|
+
launchUrl: entry.launchUrl,
|
|
2871
|
+
effectiveUrl: resolveCatalogServiceUrl(entry, { serviceKey: id }) || resolveServiceUrl(id),
|
|
2785
2872
|
surfaceKind: entry.surfaceKind,
|
|
2786
2873
|
launchable: entry.launchable,
|
|
2787
2874
|
permissions: [...entry.permissions]
|
package/package.json
CHANGED