@numa-tech/numa 1.16.1 → 1.17.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/README.md +17 -8
- package/dist/ai-registry/commands.js +41 -5
- package/dist/ai-registry/commands.js.map +1 -1
- package/dist/ai-registry/mcp-installer.d.ts +1 -0
- package/dist/ai-registry/mcp-installer.js +20 -1
- package/dist/ai-registry/mcp-installer.js.map +1 -1
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/command-catalog.js +14 -4
- package/dist/command-catalog.js.map +1 -1
- package/dist/mcp/commands.d.ts +1 -0
- package/dist/mcp/commands.js +18 -4
- package/dist/mcp/commands.js.map +1 -1
- package/dist/mcp-gateway/commands.d.ts +24 -0
- package/dist/mcp-gateway/commands.js +125 -0
- package/dist/mcp-gateway/commands.js.map +1 -0
- package/dist/mcp-gateway/install.d.ts +22 -0
- package/dist/mcp-gateway/install.js +36 -0
- package/dist/mcp-gateway/install.js.map +1 -0
- package/dist/mcp-gateway/profile.d.ts +61 -0
- package/dist/mcp-gateway/profile.js +155 -0
- package/dist/mcp-gateway/profile.js.map +1 -0
- package/dist/mcp-gateway/runtime.d.ts +141 -0
- package/dist/mcp-gateway/runtime.js +148 -0
- package/dist/mcp-gateway/runtime.js.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type McpInstallOptions, type McpInstallerDependencies } from "../ai-registry/mcp-installer.js";
|
|
2
|
+
import { type GatewayBinding, type GatewayOptions } from "./profile.js";
|
|
3
|
+
export interface GatewayInstallOptions extends GatewayOptions {
|
|
4
|
+
agent: string;
|
|
5
|
+
scope?: string;
|
|
6
|
+
transport?: string;
|
|
7
|
+
customConfig?: string;
|
|
8
|
+
force?: boolean;
|
|
9
|
+
name?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function gatewayInstallPlan(binding: GatewayBinding, service: string, options: GatewayInstallOptions): {
|
|
12
|
+
name: string;
|
|
13
|
+
endpoint: string;
|
|
14
|
+
profileRevision: number;
|
|
15
|
+
definition: {
|
|
16
|
+
command: string;
|
|
17
|
+
args: string[];
|
|
18
|
+
env: Record<string, string>;
|
|
19
|
+
};
|
|
20
|
+
options: McpInstallOptions;
|
|
21
|
+
};
|
|
22
|
+
export declare function installGatewayPlan(plan: ReturnType<typeof gatewayInstallPlan>, dependencies?: McpInstallerDependencies): Promise<import("../ai-registry/mcp-installer.js").McpInstallResult>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { installMcpClientDefinition } from "../ai-registry/mcp-installer.js";
|
|
3
|
+
import { gatewayError } from "./profile.js";
|
|
4
|
+
import { serviceEndpoint } from "./runtime.js";
|
|
5
|
+
export function gatewayInstallPlan(binding, service, options) {
|
|
6
|
+
serviceEndpoint(binding, service);
|
|
7
|
+
if (binding.metadata.publishedEndpoints?.find(e => e.serviceId === service)?.transport === "sse")
|
|
8
|
+
throw gatewayError("Direct SSE providers require a Streamable HTTP Router endpoint before installation.");
|
|
9
|
+
const agent = options.agent;
|
|
10
|
+
if (!["chatgpt", "codex", "claude", "cursor", "workbuddy", "openclaw", "custom"].includes(agent))
|
|
11
|
+
throw gatewayError("Unsupported Agent adapter.");
|
|
12
|
+
if (agent === "chatgpt" || options.transport === "remote")
|
|
13
|
+
throw gatewayError("This gateway profile uses a stdio authentication bridge. Remote OAuth installation is not available for this MCP gateway.", "mcp_gateway_remote_oauth_unavailable");
|
|
14
|
+
if (options.transport && !["auto", "bridge"].includes(options.transport))
|
|
15
|
+
throw gatewayError("Transport must be auto or bridge.");
|
|
16
|
+
const scope = options.scope ?? (["codex", "openclaw"].includes(agent) ? "user" : "project");
|
|
17
|
+
if (scope !== "user" && scope !== "project")
|
|
18
|
+
throw gatewayError("Scope must be project or user.");
|
|
19
|
+
if (["codex", "openclaw"].includes(agent) && scope !== "user")
|
|
20
|
+
throw gatewayError(`${agent} MCP registration requires user scope.`);
|
|
21
|
+
const name = options.name ?? `${binding.metadata.namespaceKey}-${service}`;
|
|
22
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,119}$/u.test(name))
|
|
23
|
+
throw gatewayError("Choose a valid Agent registration alias with --name (maximum 120 characters).");
|
|
24
|
+
const env = { NUMA_PROFILE_URL: binding.profileUrl };
|
|
25
|
+
const credentialFile = options.credentialFile || process.env.NUMA_MCP_CREDENTIAL_FILE;
|
|
26
|
+
if (credentialFile)
|
|
27
|
+
env.NUMA_MCP_CREDENTIAL_FILE = resolve(credentialFile);
|
|
28
|
+
return { name, endpoint: serviceEndpoint(binding, service), profileRevision: binding.profileRevision,
|
|
29
|
+
definition: { command: "numa", args: ["mcp", "bridge", service, "--namespace", binding.metadata.namespaceKey,
|
|
30
|
+
"--instance", binding.metadata.instanceCode, "--gateway", binding.serviceKey, "--profile-id", binding.profileId, "--env-id", binding.metadata.envId, "--gateway-id", binding.metadata.gatewayId, "--endpoint", serviceEndpoint(binding, service)], env },
|
|
31
|
+
options: { agent, scope, workspace: options.workspace, customConfig: options.customConfig, force: options.force } };
|
|
32
|
+
}
|
|
33
|
+
export async function installGatewayPlan(plan, dependencies = {}) {
|
|
34
|
+
return installMcpClientDefinition(plan.name, plan.definition, plan.options, dependencies);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/mcp-gateway/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type AuthConfig } from "../config.js";
|
|
3
|
+
import { type ResolvedPlatformProfile } from "../platform-profile.js";
|
|
4
|
+
import { AiRegistryError } from "../ai-registry/errors.js";
|
|
5
|
+
declare const Metadata: z.ZodObject<{
|
|
6
|
+
namespaceKey: z.ZodString;
|
|
7
|
+
instanceCode: z.ZodString;
|
|
8
|
+
nacosNamespaceId: z.ZodString;
|
|
9
|
+
envId: z.ZodString;
|
|
10
|
+
clusterId: z.ZodString;
|
|
11
|
+
gatewayId: z.ZodString;
|
|
12
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
13
|
+
publishedEndpoints: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
14
|
+
serviceId: z.ZodString;
|
|
15
|
+
url: z.ZodString;
|
|
16
|
+
transport: z.ZodEnum<{
|
|
17
|
+
sse: "sse";
|
|
18
|
+
"streamable-http": "streamable-http";
|
|
19
|
+
}>;
|
|
20
|
+
applicationId: z.ZodString;
|
|
21
|
+
gatewayBindingId: z.ZodString;
|
|
22
|
+
bindingVersion: z.ZodNumber;
|
|
23
|
+
roleClientId: z.ZodString;
|
|
24
|
+
}, z.core.$strict>>>;
|
|
25
|
+
}, z.core.$strict>;
|
|
26
|
+
export interface GatewayOptions {
|
|
27
|
+
namespace?: string;
|
|
28
|
+
instance?: string;
|
|
29
|
+
gateway?: string;
|
|
30
|
+
workspace?: string;
|
|
31
|
+
credentialFile?: string;
|
|
32
|
+
profileId?: string;
|
|
33
|
+
endpoint?: string;
|
|
34
|
+
envId?: string;
|
|
35
|
+
gatewayId?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface GatewayBinding {
|
|
38
|
+
serviceKey: string;
|
|
39
|
+
profileId: string;
|
|
40
|
+
profileUrl: string;
|
|
41
|
+
profileRevision: number;
|
|
42
|
+
tenantId: string;
|
|
43
|
+
baseUrl: string;
|
|
44
|
+
resource: string;
|
|
45
|
+
audience: string;
|
|
46
|
+
roleClientId: string;
|
|
47
|
+
authority: {
|
|
48
|
+
issuer: string;
|
|
49
|
+
discoveryUrl: string;
|
|
50
|
+
clientId: string;
|
|
51
|
+
scopes: string[];
|
|
52
|
+
};
|
|
53
|
+
metadata: z.infer<typeof Metadata>;
|
|
54
|
+
}
|
|
55
|
+
export declare function gatewayError(message: string, code?: string): AiRegistryError;
|
|
56
|
+
export declare function hasGatewayProfiles(): boolean;
|
|
57
|
+
export declare function publicUrl(value: string): URL;
|
|
58
|
+
export declare function gatewayProfiles(profile?: ResolvedPlatformProfile | undefined): GatewayBinding[];
|
|
59
|
+
export declare function resolveMcpGateway(options: GatewayOptions): Promise<GatewayBinding>;
|
|
60
|
+
export declare function gatewayAuthConfig(binding: GatewayBinding, options: GatewayOptions): Promise<AuthConfig>;
|
|
61
|
+
export {};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { lstat, readFile } from "node:fs/promises";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { appConfigDirectory, loadAppConfig } from "../app-config.js";
|
|
6
|
+
import { DEFAULT_REDIRECT_HOST, DEFAULT_REDIRECT_PORT } from "../config.js";
|
|
7
|
+
import { currentPlatformProfile } from "../platform-profile.js";
|
|
8
|
+
import { readRegistryManifest } from "../ai-registry/workspace.js";
|
|
9
|
+
import { AiRegistryError } from "../ai-registry/errors.js";
|
|
10
|
+
const Identifier = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,159}$/u);
|
|
11
|
+
const PublishedEndpoint = z.object({
|
|
12
|
+
serviceId: z.string().regex(/^[a-z0-9][a-z0-9-]{0,62}$/u), url: z.string(),
|
|
13
|
+
transport: z.enum(["streamable-http", "sse"]), applicationId: Identifier, gatewayBindingId: Identifier,
|
|
14
|
+
bindingVersion: z.number().int().positive(), roleClientId: Identifier
|
|
15
|
+
}).strict();
|
|
16
|
+
const Metadata = z.object({
|
|
17
|
+
namespaceKey: Identifier, instanceCode: Identifier, nacosNamespaceId: Identifier,
|
|
18
|
+
envId: Identifier, clusterId: Identifier, gatewayId: Identifier, default: z.boolean().optional(), publishedEndpoints: z.array(PublishedEndpoint).max(256).optional()
|
|
19
|
+
}).strict();
|
|
20
|
+
export function gatewayError(message, code = "mcp_gateway_invalid") {
|
|
21
|
+
return new AiRegistryError(message, code);
|
|
22
|
+
}
|
|
23
|
+
export function hasGatewayProfiles() {
|
|
24
|
+
return Object.values(currentPlatformProfile()?.services ?? {}).some(service => {
|
|
25
|
+
const configuration = service.configuration;
|
|
26
|
+
return configuration && Object.hasOwn(configuration, "mcpGateway");
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export function publicUrl(value) {
|
|
30
|
+
try {
|
|
31
|
+
const url = new URL(value);
|
|
32
|
+
const local = ["localhost", "127.0.0.1", "::1", "[::1]"].includes(url.hostname) || url.hostname.endsWith(".localhost");
|
|
33
|
+
if (url.username || url.password || url.search || url.hash || (url.protocol !== "https:" && !(url.protocol === "http:" && local)))
|
|
34
|
+
throw new Error();
|
|
35
|
+
return url;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
throw gatewayError("MCP gateway metadata requires HTTPS URLs without credentials, query or fragment (loopback development excepted).");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export function gatewayProfiles(profile = currentPlatformProfile()) {
|
|
42
|
+
if (!profile)
|
|
43
|
+
throw gatewayError("A platform config profile is required for MCP gateways.", "mcp_gateway_profile_required");
|
|
44
|
+
if (profile.stale)
|
|
45
|
+
throw gatewayError("The platform profile is stale; refresh it before gateway invocation or installation.", "mcp_gateway_profile_stale");
|
|
46
|
+
const result = [];
|
|
47
|
+
for (const [serviceKey, raw] of Object.entries(profile.services)) {
|
|
48
|
+
const service = raw;
|
|
49
|
+
if (!service.configuration || !Object.hasOwn(service.configuration, "mcpGateway"))
|
|
50
|
+
continue;
|
|
51
|
+
const metadata = Metadata.safeParse(service.configuration.mcpGateway);
|
|
52
|
+
if (!metadata.success)
|
|
53
|
+
throw gatewayError("Invalid MCP gateway namespace metadata in platform profile.");
|
|
54
|
+
const authority = profile.authorities[service.authority];
|
|
55
|
+
if (!authority || !authority.clientId || !authority.scopes.includes("openid"))
|
|
56
|
+
throw gatewayError("MCP gateway has no valid authority.");
|
|
57
|
+
const base = publicUrl(service.baseUrl).toString().replace(/\/+$/u, "");
|
|
58
|
+
if (!base.endsWith("/mcp-gw") || !service.audience || !service.roleClientId)
|
|
59
|
+
throw gatewayError("MCP gateway baseUrl must identify the /mcp-gw application and its audience.");
|
|
60
|
+
publicUrl(service.resource);
|
|
61
|
+
const seenEndpoints = new Set();
|
|
62
|
+
for (const endpoint of metadata.data.publishedEndpoints ?? []) {
|
|
63
|
+
const u = publicUrl(endpoint.url), b = new URL(base);
|
|
64
|
+
const gatewayPrefix = b.pathname.slice(0, -"/mcp-gw".length);
|
|
65
|
+
if (u.toString() !== endpoint.url || u.origin !== b.origin || !u.pathname.startsWith(gatewayPrefix + "/") || /[%\\]/u.test(endpoint.url) || seenEndpoints.has(endpoint.serviceId))
|
|
66
|
+
throw gatewayError("Invalid or duplicate published MCP endpoint in selected gateway.");
|
|
67
|
+
seenEndpoints.add(endpoint.serviceId);
|
|
68
|
+
}
|
|
69
|
+
const issuer = publicUrl(authority.issuer).toString().replace(/\/+$/u, "");
|
|
70
|
+
if (publicUrl(authority.discoveryUrl).toString() !== `${issuer}/.well-known/openid-configuration`)
|
|
71
|
+
throw gatewayError("MCP gateway discovery must belong to its issuer.");
|
|
72
|
+
result.push({ serviceKey, profileId: profile.profileId, profileUrl: profile.sourceUrl, profileRevision: profile.revision,
|
|
73
|
+
tenantId: profile.tenant.id, baseUrl: base, resource: service.resource, audience: service.audience,
|
|
74
|
+
roleClientId: service.roleClientId, authority: { ...authority, issuer }, metadata: metadata.data });
|
|
75
|
+
}
|
|
76
|
+
const environments = new Map();
|
|
77
|
+
const defaults = new Set();
|
|
78
|
+
for (const binding of result) {
|
|
79
|
+
const m = binding.metadata;
|
|
80
|
+
const signature = JSON.stringify([m.clusterId, m.namespaceKey, m.instanceCode, m.nacosNamespaceId, binding.authority.issuer]);
|
|
81
|
+
if (environments.has(m.envId) && environments.get(m.envId) !== signature)
|
|
82
|
+
throw gatewayError("MCP gateways disagree on the environment namespace or issuer.");
|
|
83
|
+
environments.set(m.envId, signature);
|
|
84
|
+
if (m.default) {
|
|
85
|
+
const key = `${m.namespaceKey}\0${m.instanceCode}`;
|
|
86
|
+
if (defaults.has(key))
|
|
87
|
+
throw gatewayError("Multiple default MCP gateways are configured for one namespace instance.");
|
|
88
|
+
defaults.add(key);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
export async function resolveMcpGateway(options) {
|
|
94
|
+
const bindings = gatewayProfiles();
|
|
95
|
+
const profile = currentPlatformProfile();
|
|
96
|
+
if (options.profileId && options.profileId !== profile.profileId)
|
|
97
|
+
throw gatewayError("Installed MCP profile identity changed; reinstall after reviewing the new profile.");
|
|
98
|
+
const explicit = options.namespace?.trim();
|
|
99
|
+
const project = explicit ? undefined : await readRegistryManifest(options.workspace, false);
|
|
100
|
+
const user = await loadAppConfig();
|
|
101
|
+
const profileDefault = profile.services.aiRegistry?.configuration?.defaultNamespaceKey;
|
|
102
|
+
const namespace = explicit || project?.manifest.namespaceKey || user.aiRegistryDefaultNamespaceKey || profileDefault;
|
|
103
|
+
if (!namespace)
|
|
104
|
+
throw gatewayError("Select a namespace with --namespace, project manifest, user default or profile default.", "mcp_gateway_namespace_required");
|
|
105
|
+
const instance = options.instance || (!explicit ? project?.manifest.instanceCode : undefined);
|
|
106
|
+
let candidates = bindings.filter(b => b.metadata.namespaceKey === namespace && (!instance || b.metadata.instanceCode === instance)
|
|
107
|
+
&& (!options.gateway || b.serviceKey === options.gateway));
|
|
108
|
+
if (!candidates.length)
|
|
109
|
+
throw gatewayError("The requested namespace/gateway is not configured in this platform profile.", "mcp_gateway_not_configured");
|
|
110
|
+
if (new Set(candidates.map(b => b.metadata.instanceCode)).size > 1)
|
|
111
|
+
throw gatewayError("Namespace is ambiguous; select --instance.", "mcp_gateway_ambiguous");
|
|
112
|
+
if (candidates.length > 1) {
|
|
113
|
+
const defaults = candidates.filter(b => b.metadata.default);
|
|
114
|
+
if (defaults.length === 1)
|
|
115
|
+
candidates = defaults;
|
|
116
|
+
}
|
|
117
|
+
if (candidates.length !== 1)
|
|
118
|
+
throw gatewayError("Namespace gateway is ambiguous; select --gateway <profile-service-key>.", "mcp_gateway_ambiguous");
|
|
119
|
+
const selected = candidates[0];
|
|
120
|
+
if ((options.envId && selected.metadata.envId !== options.envId) || (options.gatewayId && selected.metadata.gatewayId !== options.gatewayId))
|
|
121
|
+
throw gatewayError("Installed MCP environment or gateway identity changed; reinstall after review.");
|
|
122
|
+
return selected;
|
|
123
|
+
}
|
|
124
|
+
export async function gatewayAuthConfig(binding, options) {
|
|
125
|
+
let clientId = binding.authority.clientId;
|
|
126
|
+
let clientSecret;
|
|
127
|
+
const file = options.credentialFile || process.env.NUMA_MCP_CREDENTIAL_FILE;
|
|
128
|
+
if (file) {
|
|
129
|
+
try {
|
|
130
|
+
const info = await lstat(resolve(file));
|
|
131
|
+
if (!info.isFile() || info.isSymbolicLink() || info.size > 65536 || (process.platform !== "win32" && (info.mode & 0o077)))
|
|
132
|
+
throw new Error();
|
|
133
|
+
const value = JSON.parse(await readFile(resolve(file), "utf8"));
|
|
134
|
+
if (value.issuer !== binding.authority.issuer)
|
|
135
|
+
throw gatewayError("Machine credential issuer does not match the selected gateway.");
|
|
136
|
+
if (typeof value.client_id !== "string" || !value.client_id || typeof value.client_secret !== "string" || !value.client_secret)
|
|
137
|
+
throw new Error();
|
|
138
|
+
clientId = value.client_id;
|
|
139
|
+
clientSecret = value.client_secret;
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
if (error instanceof AiRegistryError)
|
|
143
|
+
throw error;
|
|
144
|
+
throw gatewayError("Cannot load the private MCP machine credential file; use a regular 0600 platform-delivered file.", "mcp_gateway_credential_invalid");
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const key = createHash("sha256").update(JSON.stringify([binding.profileId, binding.tenantId, binding.authority.issuer, clientId, binding.audience])).digest("hex").slice(0, 24);
|
|
148
|
+
return { authenticationMode: clientSecret ? "client_credentials" : "browser", discoveryUrl: binding.authority.discoveryUrl,
|
|
149
|
+
issuerUrl: binding.authority.issuer, clientId, clientSecret, resourceAudience: binding.audience,
|
|
150
|
+
profileTenantId: binding.tenantId, scope: clientSecret ? "openid" : binding.authority.scopes.join(" "),
|
|
151
|
+
tokenFile: join(appConfigDirectory(), `mcp-token-${key}.json`), redirectHost: DEFAULT_REDIRECT_HOST,
|
|
152
|
+
redirectPort: DEFAULT_REDIRECT_PORT, redirectPath: "/callback", openBrowser: process.env.NUMA_AUTH_OPEN_BROWSER !== "false",
|
|
153
|
+
backendBaseUrl: binding.baseUrl, allowAbsoluteBackendUrls: false };
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/mcp-gateway/profile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
2
|
+
import type { AuthConfig } from "../config.js";
|
|
3
|
+
import { type KeycloakFetchDependencies } from "../oauth.js";
|
|
4
|
+
import { type GatewayBinding } from "./profile.js";
|
|
5
|
+
export type RuntimeDependencies = KeycloakFetchDependencies & {
|
|
6
|
+
timeoutMs?: number;
|
|
7
|
+
};
|
|
8
|
+
export declare function serviceEndpoint(binding: GatewayBinding, service: string): string;
|
|
9
|
+
export declare function gatewayFetch(binding: GatewayBinding, auth: AuthConfig, dependencies?: RuntimeDependencies, exactEndpoint?: string): typeof fetch;
|
|
10
|
+
export declare function gatewayTransport(binding: GatewayBinding, auth: AuthConfig, service: string, dependencies?: RuntimeDependencies): StreamableHTTPClientTransport;
|
|
11
|
+
export declare function listGatewayTools(binding: GatewayBinding, auth: AuthConfig, service: string, dependencies?: RuntimeDependencies): Promise<{
|
|
12
|
+
tools: {
|
|
13
|
+
inputSchema: {
|
|
14
|
+
[x: string]: unknown;
|
|
15
|
+
type: "object";
|
|
16
|
+
properties?: Record<string, object> | undefined;
|
|
17
|
+
required?: string[] | undefined;
|
|
18
|
+
};
|
|
19
|
+
name: string;
|
|
20
|
+
description?: string | undefined;
|
|
21
|
+
outputSchema?: {
|
|
22
|
+
[x: string]: unknown;
|
|
23
|
+
type: "object";
|
|
24
|
+
properties?: Record<string, object> | undefined;
|
|
25
|
+
required?: string[] | undefined;
|
|
26
|
+
} | undefined;
|
|
27
|
+
annotations?: {
|
|
28
|
+
title?: string | undefined;
|
|
29
|
+
readOnlyHint?: boolean | undefined;
|
|
30
|
+
destructiveHint?: boolean | undefined;
|
|
31
|
+
idempotentHint?: boolean | undefined;
|
|
32
|
+
openWorldHint?: boolean | undefined;
|
|
33
|
+
} | undefined;
|
|
34
|
+
execution?: {
|
|
35
|
+
taskSupport?: "optional" | "required" | "forbidden" | undefined;
|
|
36
|
+
} | undefined;
|
|
37
|
+
_meta?: Record<string, unknown> | undefined;
|
|
38
|
+
icons?: {
|
|
39
|
+
src: string;
|
|
40
|
+
mimeType?: string | undefined;
|
|
41
|
+
sizes?: string[] | undefined;
|
|
42
|
+
theme?: "light" | "dark" | undefined;
|
|
43
|
+
}[] | undefined;
|
|
44
|
+
title?: string | undefined;
|
|
45
|
+
}[];
|
|
46
|
+
}>;
|
|
47
|
+
export declare function callGatewayTool(binding: GatewayBinding, auth: AuthConfig, service: string, tool: string, argumentsValue: Record<string, unknown>, dependencies?: RuntimeDependencies): Promise<{
|
|
48
|
+
[x: string]: unknown;
|
|
49
|
+
content: ({
|
|
50
|
+
type: "text";
|
|
51
|
+
text: string;
|
|
52
|
+
annotations?: {
|
|
53
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
54
|
+
priority?: number | undefined;
|
|
55
|
+
lastModified?: string | undefined;
|
|
56
|
+
} | undefined;
|
|
57
|
+
_meta?: Record<string, unknown> | undefined;
|
|
58
|
+
} | {
|
|
59
|
+
type: "image";
|
|
60
|
+
data: string;
|
|
61
|
+
mimeType: string;
|
|
62
|
+
annotations?: {
|
|
63
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
64
|
+
priority?: number | undefined;
|
|
65
|
+
lastModified?: string | undefined;
|
|
66
|
+
} | undefined;
|
|
67
|
+
_meta?: Record<string, unknown> | undefined;
|
|
68
|
+
} | {
|
|
69
|
+
type: "audio";
|
|
70
|
+
data: string;
|
|
71
|
+
mimeType: string;
|
|
72
|
+
annotations?: {
|
|
73
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
74
|
+
priority?: number | undefined;
|
|
75
|
+
lastModified?: string | undefined;
|
|
76
|
+
} | undefined;
|
|
77
|
+
_meta?: Record<string, unknown> | undefined;
|
|
78
|
+
} | {
|
|
79
|
+
type: "resource";
|
|
80
|
+
resource: {
|
|
81
|
+
uri: string;
|
|
82
|
+
text: string;
|
|
83
|
+
mimeType?: string | undefined;
|
|
84
|
+
_meta?: Record<string, unknown> | undefined;
|
|
85
|
+
} | {
|
|
86
|
+
uri: string;
|
|
87
|
+
blob: string;
|
|
88
|
+
mimeType?: string | undefined;
|
|
89
|
+
_meta?: Record<string, unknown> | undefined;
|
|
90
|
+
};
|
|
91
|
+
annotations?: {
|
|
92
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
93
|
+
priority?: number | undefined;
|
|
94
|
+
lastModified?: string | undefined;
|
|
95
|
+
} | undefined;
|
|
96
|
+
_meta?: Record<string, unknown> | undefined;
|
|
97
|
+
} | {
|
|
98
|
+
uri: string;
|
|
99
|
+
name: string;
|
|
100
|
+
type: "resource_link";
|
|
101
|
+
description?: string | undefined;
|
|
102
|
+
mimeType?: string | undefined;
|
|
103
|
+
size?: number | undefined;
|
|
104
|
+
annotations?: {
|
|
105
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
106
|
+
priority?: number | undefined;
|
|
107
|
+
lastModified?: string | undefined;
|
|
108
|
+
} | undefined;
|
|
109
|
+
_meta?: {
|
|
110
|
+
[x: string]: unknown;
|
|
111
|
+
} | undefined;
|
|
112
|
+
icons?: {
|
|
113
|
+
src: string;
|
|
114
|
+
mimeType?: string | undefined;
|
|
115
|
+
sizes?: string[] | undefined;
|
|
116
|
+
theme?: "light" | "dark" | undefined;
|
|
117
|
+
}[] | undefined;
|
|
118
|
+
title?: string | undefined;
|
|
119
|
+
})[];
|
|
120
|
+
_meta?: {
|
|
121
|
+
[x: string]: unknown;
|
|
122
|
+
progressToken?: string | number | undefined;
|
|
123
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
124
|
+
taskId: string;
|
|
125
|
+
} | undefined;
|
|
126
|
+
} | undefined;
|
|
127
|
+
structuredContent?: Record<string, unknown> | undefined;
|
|
128
|
+
isError?: boolean | undefined;
|
|
129
|
+
} | {
|
|
130
|
+
[x: string]: unknown;
|
|
131
|
+
toolResult: unknown;
|
|
132
|
+
_meta?: {
|
|
133
|
+
[x: string]: unknown;
|
|
134
|
+
progressToken?: string | number | undefined;
|
|
135
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
136
|
+
taskId: string;
|
|
137
|
+
} | undefined;
|
|
138
|
+
} | undefined;
|
|
139
|
+
}>;
|
|
140
|
+
export declare function gatewayCatalog(binding: GatewayBinding, auth: AuthConfig, service?: string, dependencies?: RuntimeDependencies): Promise<Record<string, any>>;
|
|
141
|
+
export declare function runGatewayBridge(binding: GatewayBinding, auth: AuthConfig, service: string): Promise<void>;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { PACKAGE_VERSION } from "../branding.js";
|
|
5
|
+
import { fetchWithKeycloakIdentity } from "../oauth.js";
|
|
6
|
+
import { bridgeMcpTransports } from "../ai-registry/bridge.js";
|
|
7
|
+
import { AiRegistryError } from "../ai-registry/errors.js";
|
|
8
|
+
import { gatewayError } from "./profile.js";
|
|
9
|
+
const MAX_BYTES = 4 * 1024 * 1024;
|
|
10
|
+
export function serviceEndpoint(binding, service) {
|
|
11
|
+
if (service === "@catalog")
|
|
12
|
+
return binding.baseUrl + "/catalog/mcp" + (binding.metadata.publishedEndpoints !== undefined ? `?gatewayId=${encodeURIComponent(binding.metadata.gatewayId)}` : "");
|
|
13
|
+
if (!/^[a-z0-9][a-z0-9-]{0,62}$/u.test(service))
|
|
14
|
+
throw gatewayError("Invalid MCP service name.");
|
|
15
|
+
if (binding.metadata.publishedEndpoints !== undefined) {
|
|
16
|
+
const endpoint = binding.metadata.publishedEndpoints.find(e => e.serviceId === service);
|
|
17
|
+
if (!endpoint)
|
|
18
|
+
throw gatewayError("MCP service has no published endpoint in this gateway profile.");
|
|
19
|
+
return endpoint.url;
|
|
20
|
+
}
|
|
21
|
+
return `${binding.baseUrl}/services/${service}/mcp`;
|
|
22
|
+
}
|
|
23
|
+
export function gatewayFetch(binding, auth, dependencies = {}, exactEndpoint) {
|
|
24
|
+
return async (input, init = {}) => {
|
|
25
|
+
const url = new URL(typeof input === "string" || input instanceof URL ? input : input.url);
|
|
26
|
+
const base = new URL(binding.baseUrl);
|
|
27
|
+
const catalogPath = base.pathname + "/api/v1/catalog";
|
|
28
|
+
const catalogRequest = url.pathname === catalogPath || /^\/[a-z0-9][a-z0-9-]{0,62}$/u.test(url.pathname.slice(catalogPath.length)) && url.pathname.startsWith(catalogPath + "/");
|
|
29
|
+
const validQuery = !url.search || (catalogRequest || url.pathname === base.pathname + "/catalog/mcp") && [...url.searchParams.keys()].every(k => k === "gatewayId") && url.searchParams.getAll("gatewayId").length === 1 && url.searchParams.get("gatewayId") === binding.metadata.gatewayId;
|
|
30
|
+
const allowedPath = exactEndpoint ? url.origin + url.pathname === new URL(exactEndpoint).origin + new URL(exactEndpoint).pathname && url.search === new URL(exactEndpoint).search : catalogRequest || url.pathname.startsWith(base.pathname + "/");
|
|
31
|
+
if (url.origin !== base.origin || !allowedPath || url.username || url.password || !validQuery || url.hash) {
|
|
32
|
+
throw gatewayError("MCP request escaped the selected gateway application.");
|
|
33
|
+
}
|
|
34
|
+
const timeout = AbortSignal.timeout(dependencies.timeoutMs ?? 60_000);
|
|
35
|
+
const signal = init.signal ? AbortSignal.any([init.signal, timeout]) : timeout;
|
|
36
|
+
const response = await fetchWithKeycloakIdentity(auth, url.toString(), () => ({ ...init, signal, redirect: "manual", headers: new Headers(init.headers) }), {
|
|
37
|
+
...dependencies, retryUnauthorized: false
|
|
38
|
+
});
|
|
39
|
+
if (response.status >= 300 && response.status < 400) {
|
|
40
|
+
await response.body?.cancel();
|
|
41
|
+
throw gatewayError("MCP gateway redirects are refused.");
|
|
42
|
+
}
|
|
43
|
+
if (Number(response.headers.get("content-length")) > MAX_BYTES) {
|
|
44
|
+
await response.body?.cancel();
|
|
45
|
+
throw gatewayError("MCP gateway response exceeds the size limit.");
|
|
46
|
+
}
|
|
47
|
+
if (!response.body)
|
|
48
|
+
return response;
|
|
49
|
+
let size = 0;
|
|
50
|
+
const bounded = response.body.pipeThrough(new TransformStream({
|
|
51
|
+
transform(chunk, controller) {
|
|
52
|
+
size += chunk.byteLength;
|
|
53
|
+
if (size > MAX_BYTES)
|
|
54
|
+
throw gatewayError("MCP gateway response exceeds the size limit.");
|
|
55
|
+
controller.enqueue(chunk);
|
|
56
|
+
}
|
|
57
|
+
}));
|
|
58
|
+
return new Response(bounded, { status: response.status, statusText: response.statusText, headers: response.headers });
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export function gatewayTransport(binding, auth, service, dependencies = {}) {
|
|
62
|
+
if (binding.metadata.publishedEndpoints?.find(e => e.serviceId === service)?.transport === "sse")
|
|
63
|
+
throw gatewayError("Direct SSE providers are not supported by this bridge; publish a Streamable HTTP Router endpoint.");
|
|
64
|
+
return new StreamableHTTPClientTransport(new URL(serviceEndpoint(binding, service)), { fetch: gatewayFetch(binding, auth, dependencies, serviceEndpoint(binding, service)) });
|
|
65
|
+
}
|
|
66
|
+
function safeError(error) {
|
|
67
|
+
if (error instanceof AiRegistryError)
|
|
68
|
+
return error;
|
|
69
|
+
const code = error?.code;
|
|
70
|
+
const status = error?.status ?? (typeof code === "number" && code >= 400 && code <= 599 ? code : undefined);
|
|
71
|
+
if (status === 401 || status === 403)
|
|
72
|
+
return new AiRegistryError(`MCP gateway access denied (HTTP ${status}).`, "mcp_gateway_forbidden", status);
|
|
73
|
+
if (typeof code === "string" && /login|auth|token/iu.test(code))
|
|
74
|
+
return gatewayError("MCP identity is unavailable; run numa mcp login for the selected namespace or supply its machine credential file.", "mcp_gateway_login_required");
|
|
75
|
+
return gatewayError("MCP gateway request failed; check namespace identity, connectivity and service state.", "mcp_gateway_request_failed");
|
|
76
|
+
}
|
|
77
|
+
async function withClient(binding, auth, service, dependencies, operation) {
|
|
78
|
+
const client = new Client({ name: "numa-mcp-gateway", version: PACKAGE_VERSION });
|
|
79
|
+
let timer;
|
|
80
|
+
try {
|
|
81
|
+
return await Promise.race([
|
|
82
|
+
(async () => { await client.connect(gatewayTransport(binding, auth, service, dependencies)); return operation(client); })(),
|
|
83
|
+
new Promise((_resolve, reject) => { timer = setTimeout(() => reject(gatewayError("MCP operation timed out.", "mcp_gateway_timeout")), dependencies.timeoutMs ?? 60_000); })
|
|
84
|
+
]);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
throw safeError(error);
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
clearTimeout(timer);
|
|
91
|
+
await client.close().catch(() => undefined);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export async function listGatewayTools(binding, auth, service, dependencies = {}) {
|
|
95
|
+
return withClient(binding, auth, service, dependencies, async (client) => {
|
|
96
|
+
const tools = [];
|
|
97
|
+
let cursor;
|
|
98
|
+
const seen = new Set();
|
|
99
|
+
for (let page = 0; page < 32; page++) {
|
|
100
|
+
const result = await client.listTools(cursor ? { cursor } : undefined);
|
|
101
|
+
tools.push(...result.tools);
|
|
102
|
+
if (tools.length > 4096)
|
|
103
|
+
throw gatewayError("Too many MCP tools.");
|
|
104
|
+
cursor = result.nextCursor;
|
|
105
|
+
if (!cursor)
|
|
106
|
+
return { tools };
|
|
107
|
+
if (seen.has(cursor))
|
|
108
|
+
throw gatewayError("MCP tools pagination repeated a cursor.");
|
|
109
|
+
seen.add(cursor);
|
|
110
|
+
}
|
|
111
|
+
throw gatewayError("MCP tools pagination exceeded its limit.");
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
export async function callGatewayTool(binding, auth, service, tool, argumentsValue, dependencies = {}) {
|
|
115
|
+
return withClient(binding, auth, service, dependencies, client => client.callTool({ name: tool, arguments: argumentsValue }, undefined, { timeout: dependencies.timeoutMs ?? 60_000 }));
|
|
116
|
+
}
|
|
117
|
+
export async function gatewayCatalog(binding, auth, service, dependencies = {}) {
|
|
118
|
+
if (service)
|
|
119
|
+
serviceEndpoint(binding, service);
|
|
120
|
+
try {
|
|
121
|
+
const response = await gatewayFetch(binding, auth, dependencies)(binding.baseUrl + "/api/v1/catalog" + (service ? `/${service}` : "") + (binding.metadata.publishedEndpoints !== undefined ? `?gatewayId=${encodeURIComponent(binding.metadata.gatewayId)}` : ""));
|
|
122
|
+
if (!response.ok)
|
|
123
|
+
throw new AiRegistryError(`MCP directory request failed (HTTP ${response.status}).`, "mcp_gateway_catalog_failed", response.status);
|
|
124
|
+
const value = await response.json();
|
|
125
|
+
const rows = service ? [value] : value.services;
|
|
126
|
+
if (!Array.isArray(rows) || rows.length > 256)
|
|
127
|
+
throw gatewayError("Invalid MCP directory response.");
|
|
128
|
+
for (const row of rows) {
|
|
129
|
+
if (typeof row.serviceId !== "string" || row.url !== serviceEndpoint(binding, row.serviceId) || row.transport !== (binding.metadata.publishedEndpoints?.find(e => e.serviceId === row.serviceId)?.transport ?? "streamable-http") || (row.gatewayId !== undefined && row.gatewayId !== binding.metadata.gatewayId) || !Array.isArray(row.tools))
|
|
130
|
+
throw gatewayError("MCP directory returned an endpoint outside the selected gateway binding.");
|
|
131
|
+
}
|
|
132
|
+
if (service && value.serviceId !== service)
|
|
133
|
+
throw gatewayError("MCP directory service identity mismatch.");
|
|
134
|
+
return value;
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
throw safeError(error);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
export async function runGatewayBridge(binding, auth, service) {
|
|
141
|
+
try {
|
|
142
|
+
await bridgeMcpTransports(new StdioServerTransport(), gatewayTransport(binding, auth, service));
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
throw safeError(error);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/mcp-gateway/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,EAAE,yBAAyB,EAAkC,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAuB,MAAM,cAAc,CAAC;AAEjE,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAGlC,MAAM,UAAU,eAAe,CAAC,OAAuB,EAAE,OAAe;IACtE,IAAI,OAAO,KAAK,UAAU;QAAE,OAAO,OAAO,CAAC,OAAO,GAAG,cAAc,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAChM,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,MAAM,YAAY,CAAC,2BAA2B,CAAC,CAAC;IACjG,IAAI,OAAO,CAAC,QAAQ,CAAC,kBAAkB,KAAK,SAAS,EAAE,CAAC;QACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,OAAO,CAAC,CAAC;QACxF,IAAI,CAAC,QAAQ;YAAE,MAAM,YAAY,CAAC,gEAAgE,CAAC,CAAC;QACpG,OAAO,QAAQ,CAAC,GAAG,CAAC;IACtB,CAAC;IACD,OAAO,GAAG,OAAO,CAAC,OAAO,aAAa,OAAO,MAAM,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAuB,EAAE,IAAgB,EAAE,YAAY,GAAwB,EAAE,EAAE,aAAsB;IACpI,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,EAAE;QAChC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,YAAY,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3F,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,GAAG,iBAAiB,CAAC;QACtD,MAAM,cAAc,GAAG,GAAG,CAAC,QAAQ,KAAK,WAAW,IAAI,8BAA8B,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC;QACjL,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,cAAc,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,WAAW,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC7R,MAAM,WAAW,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,QAAQ,KAAK,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC;QACnP,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YAC1G,MAAM,YAAY,CAAC,uDAAuD,CAAC,CAAC;QAC9E,CAAC;QACD,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,SAAS,IAAI,MAAM,CAAC,CAAC;QACtE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAC/E,MAAM,QAAQ,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;YAC1J,GAAG,YAAY,EAAE,iBAAiB,EAAE,KAAK;SAC1C,CAAC,CAAC;QACH,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YACpD,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;YAAC,MAAM,YAAY,CAAC,oCAAoC,CAAC,CAAC;QAC1F,CAAC;QACD,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,GAAG,SAAS,EAAE,CAAC;YAC/D,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;YAAC,MAAM,YAAY,CAAC,8CAA8C,CAAC,CAAC;QACpG,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,IAAI;YAAE,OAAO,QAAQ,CAAC;QACpC,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,eAAe,CAAyB;YACpF,SAAS,CAAC,KAAK,EAAE,UAAU;gBACzB,IAAI,IAAI,KAAK,CAAC,UAAU,CAAC;gBACzB,IAAI,IAAI,GAAG,SAAS;oBAAE,MAAM,YAAY,CAAC,8CAA8C,CAAC,CAAC;gBACzF,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC5B,CAAC;SACF,CAAC,CAAC,CAAC;QACJ,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACxH,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAuB,EAAE,IAAgB,EAAE,OAAe,EAAE,YAAY,GAAwB,EAAE;IACjI,IAAI,OAAO,CAAC,QAAQ,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,OAAO,CAAC,EAAE,SAAS,KAAK,KAAK;QAAE,MAAM,YAAY,CAAC,mGAAmG,CAAC,CAAC;IAC1N,OAAO,IAAI,6BAA6B,CAAC,IAAI,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;AAChL,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,KAAK,YAAY,eAAe;QAAE,OAAO,KAAK,CAAC;IACnD,MAAM,IAAI,GAAI,KAA4B,EAAE,IAAI,CAAC;IACjD,MAAM,MAAM,GAAI,KAA8C,EAAE,MAAM,IAAI,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACtJ,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,eAAe,CAAC,mCAAmC,MAAM,IAAI,EAAE,uBAAuB,EAAE,MAAM,CAAC,CAAC;IACjJ,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,YAAY,CAAC,mHAAmH,EAAE,4BAA4B,CAAC,CAAC;IACxO,OAAO,YAAY,CAAC,uFAAuF,EAAE,4BAA4B,CAAC,CAAC;AAC7I,CAAC;AAED,KAAK,UAAU,UAAU,CAAI,OAAuB,EAAE,IAAgB,EAAE,OAAe,EAAE,YAAiC,EAAE,SAAyC;IACnK,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC;IAClF,IAAI,KAAiC,CAAC;IACtC,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC;YACxB,CAAC,KAAK,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;YAC3H,IAAI,OAAO,CAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,GAAG,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,0BAA0B,EAAE,qBAAqB,CAAC,CAAC,EAAE,YAAY,CAAC,SAAS,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;SACnL,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAAC,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC;IAAC,CAAC;YACnC,CAAC;QAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAAC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAAC,CAAC;AAC/E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAuB,EAAE,IAAgB,EAAE,OAAe,EAAE,YAAY,GAAwB,EAAE;IACvI,OAAO,UAAU,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;QACrE,MAAM,KAAK,GAAsD,EAAE,CAAC;QACpE,IAAI,MAA0B,CAAC;QAC/B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACvE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5B,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI;gBAAE,MAAM,YAAY,CAAC,qBAAqB,CAAC,CAAC;YACnE,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC;YAC3B,IAAI,CAAC,MAAM;gBAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAC9B,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,MAAM,YAAY,CAAC,yCAAyC,CAAC,CAAC;YACpF,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC;QACD,MAAM,YAAY,CAAC,0CAA0C,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAuB,EAAE,IAAgB,EAAE,OAAe,EAAE,IAAY,EAAE,cAAuC,EAAE,YAAY,GAAwB,EAAE;IAC7L,OAAO,UAAU,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,YAAY,CAAC,SAAS,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC;AAC1L,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAuB,EAAE,IAAgB,EAAE,OAAgB,EAAE,YAAY,GAAwB,EAAE;IACtI,IAAI,OAAO;QAAE,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/C,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,OAAO,CAAC,OAAO,GAAG,iBAAiB,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACnQ,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,MAAM,IAAI,eAAe,CAAC,sCAAsC,QAAQ,CAAC,MAAM,IAAI,EAAE,4BAA4B,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACtJ,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;QAChD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG;YAAE,MAAM,YAAY,CAAC,iCAAiC,CAAC,CAAC;QACrG,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,IAAI,GAAG,CAAC,GAAG,KAAK,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,SAAS,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,GAAG,CAAC,SAAS,CAAC,EAAE,SAAS,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,GAAG,CAAC,SAAS,KAAK,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,MAAM,YAAY,CAAC,0EAA0E,CAAC,CAAC;QAClb,CAAC;QACD,IAAI,OAAO,IAAI,KAAK,CAAC,SAAS,KAAK,OAAO;YAAE,MAAM,YAAY,CAAC,0CAA0C,CAAC,CAAC;QAC3G,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAAC,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC;IAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAuB,EAAE,IAAgB,EAAE,OAAe;IAC/F,IAAI,CAAC;QAAC,MAAM,mBAAmB,CAAC,IAAI,oBAAoB,EAAE,EAAE,gBAAgB,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAAC,CAAC;IACxG,OAAO,KAAK,EAAE,CAAC;QAAC,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC;IAAC,CAAC;AAC3C,CAAC"}
|