@numa-tech/numa 1.11.10

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.
Files changed (99) hide show
  1. package/README.md +602 -0
  2. package/THIRD_PARTY_NOTICES.md +13 -0
  3. package/assets/codex-shortcut-icon.icns +0 -0
  4. package/assets/codex-shortcut-icon.ico +0 -0
  5. package/dist/app-config.d.ts +26 -0
  6. package/dist/app-config.js +135 -0
  7. package/dist/app-config.js.map +1 -0
  8. package/dist/backend.d.ts +16 -0
  9. package/dist/backend.js +106 -0
  10. package/dist/backend.js.map +1 -0
  11. package/dist/branding.d.ts +7 -0
  12. package/dist/branding.js +13 -0
  13. package/dist/branding.js.map +1 -0
  14. package/dist/chatgpt-console.d.ts +53 -0
  15. package/dist/chatgpt-console.js +105 -0
  16. package/dist/chatgpt-console.js.map +1 -0
  17. package/dist/cli.d.ts +2 -0
  18. package/dist/cli.js +451 -0
  19. package/dist/cli.js.map +1 -0
  20. package/dist/codex-auth-agent.d.ts +60 -0
  21. package/dist/codex-auth-agent.js +331 -0
  22. package/dist/codex-auth-agent.js.map +1 -0
  23. package/dist/codex-commands.d.ts +2 -0
  24. package/dist/codex-commands.js +528 -0
  25. package/dist/codex-commands.js.map +1 -0
  26. package/dist/codex-legacy-cleanup.d.ts +5 -0
  27. package/dist/codex-legacy-cleanup.js +77 -0
  28. package/dist/codex-legacy-cleanup.js.map +1 -0
  29. package/dist/codex-process.d.ts +13 -0
  30. package/dist/codex-process.js +193 -0
  31. package/dist/codex-process.js.map +1 -0
  32. package/dist/codex-protocol.d.ts +352 -0
  33. package/dist/codex-protocol.js +116 -0
  34. package/dist/codex-protocol.js.map +1 -0
  35. package/dist/codex-quota-cache.d.ts +20 -0
  36. package/dist/codex-quota-cache.js +82 -0
  37. package/dist/codex-quota-cache.js.map +1 -0
  38. package/dist/codex-selection.d.ts +18 -0
  39. package/dist/codex-selection.js +47 -0
  40. package/dist/codex-selection.js.map +1 -0
  41. package/dist/codex-service-client.d.ts +11 -0
  42. package/dist/codex-service-client.js +91 -0
  43. package/dist/codex-service-client.js.map +1 -0
  44. package/dist/codex-shortcuts.d.ts +43 -0
  45. package/dist/codex-shortcuts.js +429 -0
  46. package/dist/codex-shortcuts.js.map +1 -0
  47. package/dist/codex-tui.d.ts +15 -0
  48. package/dist/codex-tui.js +235 -0
  49. package/dist/codex-tui.js.map +1 -0
  50. package/dist/command-catalog.d.ts +9 -0
  51. package/dist/command-catalog.js +206 -0
  52. package/dist/command-catalog.js.map +1 -0
  53. package/dist/config-page.d.ts +2 -0
  54. package/dist/config-page.js +51 -0
  55. package/dist/config-page.js.map +1 -0
  56. package/dist/config.d.ts +22 -0
  57. package/dist/config.js +99 -0
  58. package/dist/config.js.map +1 -0
  59. package/dist/identity.d.ts +23 -0
  60. package/dist/identity.js +78 -0
  61. package/dist/identity.js.map +1 -0
  62. package/dist/media/client.d.ts +79 -0
  63. package/dist/media/client.js +175 -0
  64. package/dist/media/client.js.map +1 -0
  65. package/dist/media/commands.d.ts +2 -0
  66. package/dist/media/commands.js +193 -0
  67. package/dist/media/commands.js.map +1 -0
  68. package/dist/media/errors.d.ts +8 -0
  69. package/dist/media/errors.js +37 -0
  70. package/dist/media/errors.js.map +1 -0
  71. package/dist/media/schemas.d.ts +62 -0
  72. package/dist/media/schemas.js +71 -0
  73. package/dist/media/schemas.js.map +1 -0
  74. package/dist/media/transfers.d.ts +38 -0
  75. package/dist/media/transfers.js +169 -0
  76. package/dist/media/transfers.js.map +1 -0
  77. package/dist/oauth.d.ts +30 -0
  78. package/dist/oauth.js +295 -0
  79. package/dist/oauth.js.map +1 -0
  80. package/dist/private-file.d.ts +3 -0
  81. package/dist/private-file.js +51 -0
  82. package/dist/private-file.js.map +1 -0
  83. package/dist/server.d.ts +2 -0
  84. package/dist/server.js +197 -0
  85. package/dist/server.js.map +1 -0
  86. package/dist/types.d.ts +40 -0
  87. package/dist/types.js +2 -0
  88. package/dist/types.js.map +1 -0
  89. package/dist/web-console-page.d.ts +3 -0
  90. package/dist/web-console-page.js +59 -0
  91. package/dist/web-console-page.js.map +1 -0
  92. package/dist/web-console.d.ts +22 -0
  93. package/dist/web-console.js +335 -0
  94. package/dist/web-console.js.map +1 -0
  95. package/examples/claude-desktop-installed-binary.json +11 -0
  96. package/examples/claude-desktop-npx.json +12 -0
  97. package/examples/codex-installed-binary.json +11 -0
  98. package/examples/codex-npx.json +12 -0
  99. package/package.json +67 -0
@@ -0,0 +1,30 @@
1
+ import type { AuthConfig } from "./config.js";
2
+ import type { LoginSession, OidcDiscovery, TokenCache } from "./types.js";
3
+ export declare class AuthError extends Error {
4
+ readonly code: string;
5
+ constructor(message: string, code?: string);
6
+ }
7
+ export declare class LoginRequiredError extends AuthError {
8
+ constructor(message?: string);
9
+ }
10
+ export declare function nowSeconds(): number;
11
+ export declare function loadDiscovery(config: AuthConfig): Promise<OidcDiscovery>;
12
+ export declare function readTokenCache(config: AuthConfig): Promise<TokenCache | undefined>;
13
+ export declare function deleteTokenCache(config: AuthConfig): Promise<void>;
14
+ export declare function getUserinfo(config: AuthConfig, discovery: OidcDiscovery, accessToken: string): Promise<Record<string, unknown>>;
15
+ export declare function refreshAccessToken(config: AuthConfig, cache: TokenCache): Promise<TokenCache>;
16
+ export declare function ensureAccessToken(config: AuthConfig, forceRefresh?: boolean): Promise<string>;
17
+ export type KeycloakTokenProvider = (config: AuthConfig, forceRefresh?: boolean) => Promise<string>;
18
+ export interface KeycloakFetchDependencies {
19
+ fetch?: typeof fetch;
20
+ tokenProvider?: KeycloakTokenProvider;
21
+ }
22
+ export declare function fetchWithKeycloakIdentity(config: AuthConfig, url: string, requestFactory: () => RequestInit, dependencies?: KeycloakFetchDependencies): Promise<Response>;
23
+ export declare function whoami(config: AuthConfig, forceRefresh?: boolean): Promise<Record<string, unknown>>;
24
+ export interface BrowserLoginOptions {
25
+ successRedirectUrl?: string;
26
+ failureRedirectUrl?: string;
27
+ }
28
+ export declare function startBrowserLogin(config: AuthConfig, options?: BrowserLoginOptions): Promise<LoginSession>;
29
+ export declare function completeBrowserLogin(config: AuthConfig, session: LoginSession): Promise<Record<string, unknown>>;
30
+ export declare function blockingBrowserLogin(config: AuthConfig, options?: BrowserLoginOptions): Promise<Record<string, unknown>>;
package/dist/oauth.js ADDED
@@ -0,0 +1,295 @@
1
+ import { createHash, randomBytes, randomUUID } from "node:crypto";
2
+ import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
3
+ import { createServer } from "node:http";
4
+ import { dirname } from "node:path";
5
+ import open from "open";
6
+ import { redirectUri } from "./config.js";
7
+ const REFRESH_LEEWAY_SECONDS = 60;
8
+ const LOGIN_SESSION_TTL_SECONDS = 300;
9
+ export class AuthError extends Error {
10
+ code;
11
+ constructor(message, code = "auth_error") {
12
+ super(message);
13
+ this.code = code;
14
+ }
15
+ }
16
+ export class LoginRequiredError extends AuthError {
17
+ constructor(message = "No usable Keycloak login is available.") {
18
+ super(message, "login_required");
19
+ }
20
+ }
21
+ export function nowSeconds() {
22
+ return Math.floor(Date.now() / 1000);
23
+ }
24
+ async function parseJsonResponse(response, url) {
25
+ const text = await response.text();
26
+ let parsed = {};
27
+ if (text) {
28
+ try {
29
+ parsed = JSON.parse(text);
30
+ }
31
+ catch {
32
+ parsed = { raw: text };
33
+ }
34
+ }
35
+ if (!response.ok) {
36
+ const body = parsed;
37
+ const detail = body.error_description ?? body.error ?? body.raw ?? response.statusText;
38
+ throw new AuthError(`HTTP ${response.status} from ${url}: ${String(detail)}`, "http_error");
39
+ }
40
+ return parsed;
41
+ }
42
+ async function requestJson(url, init) {
43
+ const response = await fetch(url, {
44
+ ...init,
45
+ headers: {
46
+ Accept: "application/json",
47
+ ...(init?.body ? { "Content-Type": "application/x-www-form-urlencoded" } : {}),
48
+ ...(init?.headers ?? {})
49
+ }
50
+ });
51
+ return parseJsonResponse(response, url);
52
+ }
53
+ function formBody(values) {
54
+ const body = new URLSearchParams();
55
+ for (const [key, value] of Object.entries(values)) {
56
+ if (value != null && value !== "")
57
+ body.set(key, value);
58
+ }
59
+ return body;
60
+ }
61
+ function addClientAuth(config, values) {
62
+ return formBody({
63
+ ...values,
64
+ client_id: config.clientId,
65
+ client_secret: config.clientSecret
66
+ });
67
+ }
68
+ export async function loadDiscovery(config) {
69
+ return requestJson(config.discoveryUrl);
70
+ }
71
+ function pkcePair() {
72
+ const verifier = randomBytes(32).toString("base64url");
73
+ const challenge = createHash("sha256").update(verifier).digest("base64url");
74
+ return { verifier, challenge };
75
+ }
76
+ async function writeTokenCache(path, cache) {
77
+ await mkdir(dirname(path), { recursive: true });
78
+ const tmp = `${path}.tmp`;
79
+ await writeFile(tmp, `${JSON.stringify(cache, null, 2)}\n`, { mode: 0o600 });
80
+ await rename(tmp, path);
81
+ }
82
+ export async function readTokenCache(config) {
83
+ try {
84
+ const raw = await readFile(config.tokenFile, "utf8");
85
+ return JSON.parse(raw);
86
+ }
87
+ catch (error) {
88
+ if (error.code === "ENOENT")
89
+ return undefined;
90
+ throw error;
91
+ }
92
+ }
93
+ export async function deleteTokenCache(config) {
94
+ await rm(config.tokenFile, { force: true });
95
+ }
96
+ async function saveToken(config, discovery, token, userinfo, existingRefreshExpiresAt) {
97
+ const obtainedAt = nowSeconds();
98
+ const expiresAt = obtainedAt + (token.expires_in ?? 0);
99
+ const refreshExpiresAt = token.refresh_expires_in && token.refresh_expires_in > 0
100
+ ? obtainedAt + token.refresh_expires_in
101
+ : existingRefreshExpiresAt;
102
+ const cache = {
103
+ issuer: discovery.issuer,
104
+ discoveryUrl: config.discoveryUrl,
105
+ clientId: config.clientId,
106
+ scope: token.scope ?? config.scope,
107
+ obtainedAt,
108
+ expiresAt,
109
+ refreshExpiresAt,
110
+ token,
111
+ userinfo
112
+ };
113
+ await writeTokenCache(config.tokenFile, cache);
114
+ return cache;
115
+ }
116
+ export async function getUserinfo(config, discovery, accessToken) {
117
+ return requestJson(discovery.userinfo_endpoint, {
118
+ headers: { Authorization: `Bearer ${accessToken}` }
119
+ });
120
+ }
121
+ export async function refreshAccessToken(config, cache) {
122
+ if (!cache.token.refresh_token) {
123
+ throw new LoginRequiredError("Saved token has no refresh token. Start login again.");
124
+ }
125
+ const discovery = await loadDiscovery(config);
126
+ const refreshed = await requestJson(discovery.token_endpoint, {
127
+ method: "POST",
128
+ body: addClientAuth(config, {
129
+ grant_type: "refresh_token",
130
+ refresh_token: cache.token.refresh_token
131
+ })
132
+ });
133
+ const token = {
134
+ ...refreshed,
135
+ // Some OIDC servers reuse the existing refresh token instead of returning
136
+ // it again. Keep it until the server explicitly rejects the refresh grant.
137
+ refresh_token: refreshed.refresh_token ?? cache.token.refresh_token
138
+ };
139
+ const userinfo = await getUserinfo(config, discovery, token.access_token);
140
+ return saveToken(config, discovery, token, userinfo, cache.refreshExpiresAt);
141
+ }
142
+ export async function ensureAccessToken(config, forceRefresh = false) {
143
+ let cache = await readTokenCache(config);
144
+ if (!cache)
145
+ throw new LoginRequiredError("No token cache exists. Start login first.");
146
+ if (cache.discoveryUrl !== config.discoveryUrl || cache.clientId !== config.clientId) {
147
+ throw new LoginRequiredError("Token cache was created for a different Keycloak discovery URL or client.");
148
+ }
149
+ if (forceRefresh || cache.expiresAt <= nowSeconds() + REFRESH_LEEWAY_SECONDS) {
150
+ cache = await refreshAccessToken(config, cache);
151
+ }
152
+ return cache.token.access_token;
153
+ }
154
+ export async function fetchWithKeycloakIdentity(config, url, requestFactory, dependencies = {}) {
155
+ const fetchImpl = dependencies.fetch ?? fetch;
156
+ const tokenProvider = dependencies.tokenProvider ?? ensureAccessToken;
157
+ const send = async (forceRefresh) => {
158
+ const token = await tokenProvider(config, forceRefresh);
159
+ const init = requestFactory();
160
+ const headers = new Headers(init.headers);
161
+ headers.set("Authorization", `Bearer ${token}`);
162
+ return fetchImpl(url, { ...init, headers });
163
+ };
164
+ let response = await send(false);
165
+ if (response.status === 401) {
166
+ await response.body?.cancel().catch(() => undefined);
167
+ response = await send(true);
168
+ }
169
+ return response;
170
+ }
171
+ export async function whoami(config, forceRefresh = false) {
172
+ const discovery = await loadDiscovery(config);
173
+ if (forceRefresh)
174
+ await ensureAccessToken(config, true);
175
+ const response = await fetchWithKeycloakIdentity(config, discovery.userinfo_endpoint, () => ({ headers: { Accept: "application/json" } }));
176
+ const info = await parseJsonResponse(response, discovery.userinfo_endpoint);
177
+ const cache = await readTokenCache(config);
178
+ if (cache)
179
+ await writeTokenCache(config.tokenFile, { ...cache, userinfo: info });
180
+ return info;
181
+ }
182
+ export async function startBrowserLogin(config, options = {}) {
183
+ const discovery = await loadDiscovery(config);
184
+ const { verifier, challenge } = pkcePair();
185
+ const state = randomBytes(24).toString("base64url");
186
+ const callback = redirectUri(config);
187
+ const id = randomUUID();
188
+ let server;
189
+ const session = {
190
+ id,
191
+ authorizationUrl: "",
192
+ redirectUri: callback,
193
+ codeVerifier: verifier,
194
+ state,
195
+ createdAt: nowSeconds(),
196
+ expiresAt: nowSeconds() + LOGIN_SESSION_TTL_SECONDS,
197
+ close: async () => {
198
+ if (!server)
199
+ return;
200
+ await new Promise((resolve, reject) => {
201
+ server?.close((error) => (error ? reject(error) : resolve()));
202
+ });
203
+ server = undefined;
204
+ }
205
+ };
206
+ const authUrl = new URL(discovery.authorization_endpoint);
207
+ authUrl.searchParams.set("client_id", config.clientId);
208
+ authUrl.searchParams.set("redirect_uri", callback);
209
+ authUrl.searchParams.set("response_type", "code");
210
+ authUrl.searchParams.set("scope", config.scope);
211
+ authUrl.searchParams.set("state", state);
212
+ authUrl.searchParams.set("code_challenge", challenge);
213
+ authUrl.searchParams.set("code_challenge_method", "S256");
214
+ session.authorizationUrl = authUrl.toString();
215
+ server = createServer((request, response) => {
216
+ const requestUrl = new URL(request.url ?? "/", callback);
217
+ if (requestUrl.pathname !== config.redirectPath) {
218
+ response.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
219
+ response.end("Not found\n");
220
+ return;
221
+ }
222
+ const returnedState = requestUrl.searchParams.get("state");
223
+ if (returnedState !== state) {
224
+ session.error = "State mismatch";
225
+ }
226
+ else if (requestUrl.searchParams.get("error")) {
227
+ session.error = requestUrl.searchParams.get("error_description") ?? requestUrl.searchParams.get("error") ?? "Login failed";
228
+ }
229
+ else {
230
+ session.code = requestUrl.searchParams.get("code") ?? undefined;
231
+ }
232
+ const redirect = session.code ? options.successRedirectUrl : options.failureRedirectUrl;
233
+ if (redirect) {
234
+ response.writeHead(303, {
235
+ Location: redirect,
236
+ "Cache-Control": "no-store",
237
+ "Referrer-Policy": "no-referrer"
238
+ });
239
+ response.end();
240
+ return;
241
+ }
242
+ response.writeHead(session.code ? 200 : 400, {
243
+ "Content-Type": "text/plain; charset=utf-8",
244
+ "Cache-Control": "no-store"
245
+ });
246
+ response.end(session.code ? "Login complete. You may close this tab.\n" : `Login failed: ${session.error}\n`);
247
+ });
248
+ await new Promise((resolve, reject) => {
249
+ server?.once("error", reject);
250
+ server?.listen(config.redirectPort, config.redirectHost, () => resolve());
251
+ });
252
+ if (config.openBrowser) {
253
+ await open(session.authorizationUrl).catch(() => undefined);
254
+ }
255
+ return session;
256
+ }
257
+ export async function completeBrowserLogin(config, session) {
258
+ if (session.error)
259
+ throw new AuthError(session.error, "login_failed");
260
+ if (!session.code) {
261
+ if (session.expiresAt <= nowSeconds()) {
262
+ await session.close();
263
+ throw new AuthError("Login session expired before callback was received.", "login_expired");
264
+ }
265
+ throw new AuthError("Login callback has not been received yet.", "login_pending");
266
+ }
267
+ const discovery = await loadDiscovery(config);
268
+ const token = await requestJson(discovery.token_endpoint, {
269
+ method: "POST",
270
+ body: addClientAuth(config, {
271
+ grant_type: "authorization_code",
272
+ code: session.code,
273
+ redirect_uri: session.redirectUri,
274
+ code_verifier: session.codeVerifier
275
+ })
276
+ });
277
+ const info = await getUserinfo(config, discovery, token.access_token);
278
+ await saveToken(config, discovery, token, info);
279
+ await session.close();
280
+ return info;
281
+ }
282
+ export async function blockingBrowserLogin(config, options = {}) {
283
+ const session = await startBrowserLogin(config, options);
284
+ process.stderr.write(`Open this URL to log in:\n${session.authorizationUrl}\n`);
285
+ try {
286
+ while (!session.code && !session.error && session.expiresAt > nowSeconds()) {
287
+ await new Promise((resolve) => setTimeout(resolve, 500));
288
+ }
289
+ return await completeBrowserLogin(config, session);
290
+ }
291
+ finally {
292
+ await session.close().catch(() => undefined);
293
+ }
294
+ }
295
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function writePrivateText(path: string, content: string): Promise<void>;
2
+ export declare function writePrivateJson(path: string, value: unknown): Promise<void>;
3
+ export declare function readJsonIfExists(path: string): Promise<unknown | undefined>;
@@ -0,0 +1,51 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { chmod, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
3
+ import { dirname } from "node:path";
4
+ const RETRYABLE_CODES = new Set(["EACCES", "EBUSY", "EAGAIN", "EPERM"]);
5
+ function isRetryable(error) {
6
+ const code = error?.code;
7
+ return typeof code === "string" && RETRYABLE_CODES.has(code);
8
+ }
9
+ async function renameWithRetry(source, destination) {
10
+ let lastError;
11
+ for (let attempt = 0; attempt < 5; attempt += 1) {
12
+ try {
13
+ await rename(source, destination);
14
+ return;
15
+ }
16
+ catch (error) {
17
+ lastError = error;
18
+ if (!isRetryable(error) || attempt === 4)
19
+ throw error;
20
+ await new Promise((resolve) => setTimeout(resolve, 10 * 2 ** attempt));
21
+ }
22
+ }
23
+ throw lastError;
24
+ }
25
+ export async function writePrivateText(path, content) {
26
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
27
+ const temporaryPath = `${path}.${process.pid}.${randomBytes(8).toString("hex")}.tmp`;
28
+ try {
29
+ await writeFile(temporaryPath, content, { encoding: "utf8", mode: 0o600 });
30
+ await renameWithRetry(temporaryPath, path);
31
+ if (process.platform !== "win32")
32
+ await chmod(path, 0o600);
33
+ }
34
+ finally {
35
+ await rm(temporaryPath, { force: true }).catch(() => undefined);
36
+ }
37
+ }
38
+ export async function writePrivateJson(path, value) {
39
+ await writePrivateText(path, `${JSON.stringify(value, null, 2)}\n`);
40
+ }
41
+ export async function readJsonIfExists(path) {
42
+ try {
43
+ return JSON.parse(await readFile(path, "utf8"));
44
+ }
45
+ catch (error) {
46
+ if (error.code === "ENOENT")
47
+ return undefined;
48
+ throw error;
49
+ }
50
+ }
51
+ //# sourceMappingURL=private-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"private-file.js","sourceRoot":"","sources":["../src/private-file.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function createServer(): McpServer;
package/dist/server.js ADDED
@@ -0,0 +1,197 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { z } from "zod";
3
+ import { authenticatedBackendRequest } from "./backend.js";
4
+ import { CLI_NAME, PACKAGE_VERSION, PRODUCT_NAME } from "./branding.js";
5
+ import { COMMAND_CATALOG } from "./command-catalog.js";
6
+ import { loadConfig } from "./config.js";
7
+ import { currentIdentity, requireAnyRole, RoleRequiredError } from "./identity.js";
8
+ import { AuthError, completeBrowserLogin, deleteTokenCache, readTokenCache, startBrowserLogin } from "./oauth.js";
9
+ const sessions = new Map();
10
+ function textResult(text, structuredContent, isError = false) {
11
+ return {
12
+ isError,
13
+ content: [{ type: "text", text }],
14
+ ...(structuredContent ? { structuredContent } : {})
15
+ };
16
+ }
17
+ function jsonResult(value) {
18
+ return textResult(JSON.stringify(value, null, 2), value);
19
+ }
20
+ function errorResult(error) {
21
+ const message = error instanceof Error ? error.message : String(error);
22
+ const code = error instanceof AuthError || error instanceof RoleRequiredError ? error.code : "error";
23
+ return textResult(`Error: ${message}`, { ok: false, code, message }, true);
24
+ }
25
+ export function createServer() {
26
+ const server = new McpServer({
27
+ name: `${CLI_NAME}-platform-cli`,
28
+ version: PACKAGE_VERSION
29
+ });
30
+ server.registerTool("numa_command_catalog", {
31
+ title: `Get ${PRODUCT_NAME} CLI Command Catalog`,
32
+ description: "List CLI commands, authentication requirements, required roles, and examples for AI clients.",
33
+ inputSchema: {},
34
+ annotations: {
35
+ readOnlyHint: true,
36
+ destructiveHint: false,
37
+ idempotentHint: true,
38
+ openWorldHint: false
39
+ }
40
+ }, async () => jsonResult({ schema_version: 1, commands: COMMAND_CATALOG }));
41
+ server.registerTool("numa_auth_status", {
42
+ title: `Get ${PRODUCT_NAME} Auth Status`,
43
+ description: "Inspect local Keycloak authentication cache status without exposing tokens.",
44
+ inputSchema: {},
45
+ annotations: {
46
+ readOnlyHint: true,
47
+ destructiveHint: false,
48
+ idempotentHint: true,
49
+ openWorldHint: false
50
+ }
51
+ }, async () => {
52
+ try {
53
+ const config = loadConfig();
54
+ const cache = await readTokenCache(config);
55
+ return jsonResult({
56
+ logged_in: Boolean(cache),
57
+ token_file: config.tokenFile,
58
+ discovery_url: config.discoveryUrl,
59
+ client_id: config.clientId,
60
+ expires_at: cache?.expiresAt,
61
+ refresh_expires_at: cache?.refreshExpiresAt,
62
+ cached_user: cache?.userinfo
63
+ });
64
+ }
65
+ catch (error) {
66
+ return errorResult(error);
67
+ }
68
+ });
69
+ server.registerTool("numa_auth_start_login", {
70
+ title: `Start ${PRODUCT_NAME} Keycloak Login`,
71
+ description: "Start local browser-based Keycloak PKCE login. Returns an authorization URL and login_session_id; never returns tokens.",
72
+ inputSchema: {},
73
+ annotations: {
74
+ readOnlyHint: false,
75
+ destructiveHint: false,
76
+ idempotentHint: false,
77
+ openWorldHint: true
78
+ }
79
+ }, async () => {
80
+ try {
81
+ const session = await startBrowserLogin(loadConfig());
82
+ sessions.set(session.id, session);
83
+ return jsonResult({
84
+ login_session_id: session.id,
85
+ authorization_url: session.authorizationUrl,
86
+ redirect_uri: session.redirectUri,
87
+ expires_at: session.expiresAt,
88
+ instruction: "Open authorization_url in a browser, complete login, then call numa_auth_complete_login."
89
+ });
90
+ }
91
+ catch (error) {
92
+ return errorResult(error);
93
+ }
94
+ });
95
+ server.registerTool("numa_auth_complete_login", {
96
+ title: `Complete ${PRODUCT_NAME} Keycloak Login`,
97
+ description: "Complete a browser login after the local callback is received and save the token cache. Returns user identity, not tokens.",
98
+ inputSchema: {
99
+ login_session_id: z.string().min(1).describe("Session ID returned by numa_auth_start_login")
100
+ },
101
+ annotations: {
102
+ readOnlyHint: false,
103
+ destructiveHint: false,
104
+ idempotentHint: true,
105
+ openWorldHint: true
106
+ }
107
+ }, async ({ login_session_id }) => {
108
+ try {
109
+ const session = sessions.get(login_session_id);
110
+ if (!session)
111
+ throw new AuthError("Unknown login_session_id.", "unknown_login_session");
112
+ const info = await completeBrowserLogin(loadConfig(), session);
113
+ sessions.delete(login_session_id);
114
+ return jsonResult({ ok: true, user: info });
115
+ }
116
+ catch (error) {
117
+ return errorResult(error);
118
+ }
119
+ });
120
+ server.registerTool("numa_auth_whoami", {
121
+ title: `Get Current ${PRODUCT_NAME} User`,
122
+ description: "Return the current Keycloak user identity from the userinfo endpoint. Refreshes saved access token if needed; never returns tokens.",
123
+ inputSchema: {
124
+ force_refresh: z.boolean().default(false).describe("Force refresh before reading userinfo")
125
+ },
126
+ annotations: {
127
+ readOnlyHint: true,
128
+ destructiveHint: false,
129
+ idempotentHint: true,
130
+ openWorldHint: true
131
+ }
132
+ }, async ({ force_refresh }) => {
133
+ try {
134
+ const identity = await currentIdentity(loadConfig(), force_refresh);
135
+ const { raw: _raw, ...safeIdentity } = identity;
136
+ return jsonResult({ user: safeIdentity });
137
+ }
138
+ catch (error) {
139
+ return errorResult(error);
140
+ }
141
+ });
142
+ server.registerTool("numa_auth_logout", {
143
+ title: `Clear Local ${PRODUCT_NAME} Login`,
144
+ description: "Delete the local Keycloak token cache. This does not revoke server-side Keycloak sessions.",
145
+ inputSchema: {},
146
+ annotations: {
147
+ readOnlyHint: false,
148
+ destructiveHint: true,
149
+ idempotentHint: true,
150
+ openWorldHint: false
151
+ }
152
+ }, async () => {
153
+ try {
154
+ const config = loadConfig();
155
+ await deleteTokenCache(config);
156
+ return jsonResult({ ok: true, token_file: config.tokenFile });
157
+ }
158
+ catch (error) {
159
+ return errorResult(error);
160
+ }
161
+ });
162
+ server.registerTool("numa_backend_request", {
163
+ title: `Call ${PRODUCT_NAME} Backend With Keycloak Auth`,
164
+ description: "Proxy an HTTP request to a configured Numa backend and inject the saved Keycloak bearer token internally. Does not expose tokens.",
165
+ inputSchema: {
166
+ method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).default("GET"),
167
+ path: z.string().optional().describe("Backend path resolved against NUMA_BACKEND_BASE_URL"),
168
+ url: z.string().url().optional().describe("Absolute URL; disabled unless NUMA_BACKEND_ALLOW_ABSOLUTE_URLS=true"),
169
+ headers: z.record(z.string(), z.string()).optional().describe("Extra headers except Authorization"),
170
+ body: z.unknown().optional().describe("JSON-serializable request body or string"),
171
+ required_roles: z
172
+ .array(z.string().min(1))
173
+ .optional()
174
+ .describe("Require at least one Keycloak realm/client role before the request")
175
+ },
176
+ annotations: {
177
+ readOnlyHint: false,
178
+ destructiveHint: true,
179
+ idempotentHint: false,
180
+ openWorldHint: true
181
+ }
182
+ }, async (input) => {
183
+ try {
184
+ const { headers, required_roles, ...rest } = input;
185
+ if (required_roles?.length)
186
+ await requireAnyRole(loadConfig(), required_roles);
187
+ const safeHeaders = Object.fromEntries(Object.entries(headers ?? {}).filter(([key]) => key.toLowerCase() !== "authorization"));
188
+ const response = await authenticatedBackendRequest(loadConfig(), { ...rest, headers: safeHeaders });
189
+ return jsonResult({ ok: response.status >= 200 && response.status < 300, response });
190
+ }
191
+ catch (error) {
192
+ return errorResult(error);
193
+ }
194
+ });
195
+ return server;
196
+ }
197
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACnF,OAAO,EACL,SAAS,EACT,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAGpB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;AAEjD,SAAS,UAAU,CAAC,IAAY,EAAE,iBAA2C,EAAE,OAAO,GAAG,KAAK;IAC5F,OAAO;QACL,OAAO;QACP,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;QAC1C,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpD,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,KAA8B;IAChD,OAAO,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,KAAK,YAAY,SAAS,IAAI,KAAK,YAAY,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;IACrG,OAAO,UAAU,CAAC,UAAU,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,GAAG,QAAQ,eAAe;QAChC,OAAO,EAAE,eAAe;KACzB,CAAC,CAAC;IAEH,MAAM,CAAC,YAAY,CACjB,sBAAsB,EACtB;QACE,KAAK,EAAE,OAAO,YAAY,sBAAsB;QAChD,WAAW,EAAE,8FAA8F;QAC3G,WAAW,EAAE,EAAE;QACf,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,KAAK;SACrB;KACF,EACD,KAAK,IAAI,EAAE,CAAC,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC,CACzE,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,kBAAkB,EAClB;QACE,KAAK,EAAE,OAAO,YAAY,cAAc;QACxC,WAAW,EAAE,6EAA6E;QAC1F,WAAW,EAAE,EAAE;QACf,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,KAAK;SACrB;KACF,EACD,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;YAC3C,OAAO,UAAU,CAAC;gBAChB,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC;gBACzB,UAAU,EAAE,MAAM,CAAC,SAAS;gBAC5B,aAAa,EAAE,MAAM,CAAC,YAAY;gBAClC,SAAS,EAAE,MAAM,CAAC,QAAQ;gBAC1B,UAAU,EAAE,KAAK,EAAE,SAAS;gBAC5B,kBAAkB,EAAE,KAAK,EAAE,gBAAgB;gBAC3C,WAAW,EAAE,KAAK,EAAE,QAAQ;aAC7B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,uBAAuB,EACvB;QACE,KAAK,EAAE,SAAS,YAAY,iBAAiB;QAC7C,WAAW,EACT,yHAAyH;QAC3H,WAAW,EAAE,EAAE;QACf,WAAW,EAAE;YACX,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,KAAK;YACrB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,UAAU,EAAE,CAAC,CAAC;YACtD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YAClC,OAAO,UAAU,CAAC;gBAChB,gBAAgB,EAAE,OAAO,CAAC,EAAE;gBAC5B,iBAAiB,EAAE,OAAO,CAAC,gBAAgB;gBAC3C,YAAY,EAAE,OAAO,CAAC,WAAW;gBACjC,UAAU,EAAE,OAAO,CAAC,SAAS;gBAC7B,WAAW,EAAE,0FAA0F;aACxG,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,0BAA0B,EAC1B;QACE,KAAK,EAAE,YAAY,YAAY,iBAAiB;QAChD,WAAW,EACT,4HAA4H;QAC9H,WAAW,EAAE;YACX,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,8CAA8C,CAAC;SAC7F;QACD,WAAW,EAAE;YACX,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAC/C,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,SAAS,CAAC,2BAA2B,EAAE,uBAAuB,CAAC,CAAC;YACxF,MAAM,IAAI,GAAG,MAAM,oBAAoB,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,CAAC;YAC/D,QAAQ,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;YAClC,OAAO,UAAU,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,kBAAkB,EAClB;QACE,KAAK,EAAE,eAAe,YAAY,OAAO;QACzC,WAAW,EACT,qIAAqI;QACvI,WAAW,EAAE;YACX,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,uCAAuC,CAAC;SAC5F;QACD,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE;QAC1B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,UAAU,EAAE,EAAE,aAAa,CAAC,CAAC;YACpE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,YAAY,EAAE,GAAG,QAAQ,CAAC;YAChD,OAAO,UAAU,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,kBAAkB,EAClB;QACE,KAAK,EAAE,eAAe,YAAY,QAAQ;QAC1C,WAAW,EAAE,4FAA4F;QACzG,WAAW,EAAE,EAAE;QACf,WAAW,EAAE;YACX,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,IAAI;YACrB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,KAAK;SACrB;KACF,EACD,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;YAC5B,MAAM,gBAAgB,CAAC,MAAM,CAAC,CAAC;YAC/B,OAAO,UAAU,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,sBAAsB,EACtB;QACE,KAAK,EAAE,QAAQ,YAAY,6BAA6B;QACxD,WAAW,EACT,mIAAmI;QACrI,WAAW,EAAE;YACX,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;YACxE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;YAC3F,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qEAAqE,CAAC;YAChH,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;YACnG,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;YACjF,cAAc,EAAE,CAAC;iBACd,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;iBACxB,QAAQ,EAAE;iBACV,QAAQ,CAAC,oEAAoE,CAAC;SAClF;QACD,WAAW,EAAE;YACX,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,IAAI;YACrB,cAAc,EAAE,KAAK;YACrB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;YACnD,IAAI,cAAc,EAAE,MAAM;gBAAE,MAAM,cAAc,CAAC,UAAU,EAAE,EAAE,cAAc,CAAC,CAAC;YAC/E,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CACpC,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,eAAe,CAAC,CACvF,CAAC;YACF,MAAM,QAAQ,GAAG,MAAM,2BAA2B,CAAC,UAAU,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;YACpG,OAAO,UAAU,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QACvF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CACF,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,40 @@
1
+ export interface OidcDiscovery {
2
+ issuer: string;
3
+ authorization_endpoint: string;
4
+ token_endpoint: string;
5
+ userinfo_endpoint: string;
6
+ device_authorization_endpoint?: string;
7
+ end_session_endpoint?: string;
8
+ }
9
+ export interface TokenResponse {
10
+ access_token: string;
11
+ token_type?: string;
12
+ expires_in?: number;
13
+ refresh_token?: string;
14
+ refresh_expires_in?: number;
15
+ id_token?: string;
16
+ scope?: string;
17
+ }
18
+ export interface TokenCache {
19
+ issuer: string;
20
+ discoveryUrl: string;
21
+ clientId: string;
22
+ scope: string;
23
+ obtainedAt: number;
24
+ expiresAt: number;
25
+ refreshExpiresAt?: number;
26
+ token: TokenResponse;
27
+ userinfo?: Record<string, unknown>;
28
+ }
29
+ export interface LoginSession {
30
+ id: string;
31
+ authorizationUrl: string;
32
+ redirectUri: string;
33
+ codeVerifier: string;
34
+ state: string;
35
+ createdAt: number;
36
+ expiresAt: number;
37
+ code?: string;
38
+ error?: string;
39
+ close: () => Promise<void>;
40
+ }