@husar.ai/cli 0.4.0 → 0.4.2
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/AGENTS.md +835 -0
- package/MCP_SERVER.md +92 -0
- package/dist/auth/api.d.ts +15 -0
- package/dist/auth/api.js +86 -0
- package/dist/auth/api.js.map +1 -0
- package/dist/auth/config.d.ts +32 -0
- package/dist/auth/config.js +95 -0
- package/dist/auth/config.js.map +1 -0
- package/dist/auth/login.d.ts +30 -0
- package/dist/auth/login.js +450 -0
- package/dist/auth/login.js.map +1 -0
- package/dist/cli.js +83 -3
- package/dist/cli.js.map +1 -1
- package/dist/functions/create.d.ts +6 -0
- package/dist/functions/create.js +311 -0
- package/dist/functions/create.js.map +1 -0
- package/dist/mcp.js +20 -14
- package/dist/mcp.js.map +1 -1
- package/dist/types/config.d.ts +3 -1
- package/dist/types/config.js +12 -1
- package/dist/types/config.js.map +1 -1
- package/dist/zeus/const.js +1410 -218
- package/dist/zeus/const.js.map +1 -1
- package/dist/zeus/index.d.ts +6889 -1508
- package/dist/zeus/index.js +197 -11
- package/dist/zeus/index.js.map +1 -1
- package/package.json +3 -3
- package/src/auth/api.ts +133 -0
- package/src/auth/config.ts +198 -0
- package/src/auth/login.ts +631 -0
- package/src/cli.ts +96 -4
- package/src/functions/create.ts +489 -0
- package/src/mcp.ts +47 -27
- package/src/types/config.ts +32 -1
- package/src/zeus/const.ts +1418 -218
- package/src/zeus/index.ts +6969 -1611
package/src/mcp.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { ConfigMaker } from 'config-maker';
|
|
|
7
7
|
import { parser } from './functions/parser.js';
|
|
8
8
|
import { generateCms } from './functions/generate.js';
|
|
9
9
|
import path from 'path';
|
|
10
|
-
import { HusarConfigType } from '@/types/config.js';
|
|
10
|
+
import { HusarConfigType, getAdminToken } from '@/types/config.js';
|
|
11
11
|
import {
|
|
12
12
|
buildClientSchema,
|
|
13
13
|
printSchema,
|
|
@@ -227,8 +227,9 @@ const createCmsParseFileHandler = ({ timeoutMs = 300_000 }: { timeoutMs?: number
|
|
|
227
227
|
if (!raw.host) {
|
|
228
228
|
throw new Error('Please implement host in husar.json');
|
|
229
229
|
}
|
|
230
|
-
|
|
231
|
-
|
|
230
|
+
const adminToken = getAdminToken(raw);
|
|
231
|
+
if (!adminToken) {
|
|
232
|
+
throw new Error('Admin token not configured. Set HUSAR_ADMIN_TOKEN env var, or adminTokenEnv in husar.json');
|
|
232
233
|
}
|
|
233
234
|
const result = await withTimeout(
|
|
234
235
|
parser({
|
|
@@ -237,7 +238,7 @@ const createCmsParseFileHandler = ({ timeoutMs = 300_000 }: { timeoutMs?: number
|
|
|
237
238
|
opts: { type: (type ?? 'shape') as 'model' | 'shape', name },
|
|
238
239
|
authentication: {
|
|
239
240
|
HUSAR_MCP_HOST: raw.host,
|
|
240
|
-
HUSAR_MCP_ADMIN_TOKEN:
|
|
241
|
+
HUSAR_MCP_ADMIN_TOKEN: adminToken,
|
|
241
242
|
},
|
|
242
243
|
}),
|
|
243
244
|
timeoutMs,
|
|
@@ -333,9 +334,10 @@ export const startMcpServer = async () => {
|
|
|
333
334
|
const cfg = await getConfig(workspaceRoot);
|
|
334
335
|
const raw = cfg.get();
|
|
335
336
|
const host = raw.host;
|
|
336
|
-
const token = raw
|
|
337
|
+
const token = getAdminToken(raw);
|
|
337
338
|
if (!host) throw new Error('Missing host in husar.json');
|
|
338
|
-
if (!token)
|
|
339
|
+
if (!token)
|
|
340
|
+
throw new Error('Admin token not configured. Set HUSAR_ADMIN_TOKEN env var, or adminTokenEnv in husar.json');
|
|
339
341
|
const url = new URL(endpointPath || 'api/graphql', host).toString();
|
|
340
342
|
const vars =
|
|
341
343
|
typeof variables === 'string' && variables.trim().length ? JSON.parse(variables) : (variables ?? {});
|
|
@@ -375,9 +377,10 @@ export const startMcpServer = async () => {
|
|
|
375
377
|
const cfg = await getConfig(workspaceRoot);
|
|
376
378
|
const raw = cfg.get();
|
|
377
379
|
const host = raw.host;
|
|
378
|
-
const token = raw
|
|
380
|
+
const token = getAdminToken(raw);
|
|
379
381
|
if (!host) throw new Error('Missing host in husar.json');
|
|
380
|
-
if (!token)
|
|
382
|
+
if (!token)
|
|
383
|
+
throw new Error('Admin token not configured. Set HUSAR_ADMIN_TOKEN env var, or adminTokenEnv in husar.json');
|
|
381
384
|
const url = new URL(endpointPath || 'api/graphql', host).toString();
|
|
382
385
|
const res = await fetch(url, {
|
|
383
386
|
method: 'POST',
|
|
@@ -403,9 +406,10 @@ export const startMcpServer = async () => {
|
|
|
403
406
|
const cfg = await getConfig(workspaceRoot);
|
|
404
407
|
const raw = cfg.get();
|
|
405
408
|
const host = raw.host;
|
|
406
|
-
const token = raw
|
|
409
|
+
const token = getAdminToken(raw);
|
|
407
410
|
if (!host) throw new Error('Missing host in husar.json');
|
|
408
|
-
if (!token)
|
|
411
|
+
if (!token)
|
|
412
|
+
throw new Error('Admin token not configured. Set HUSAR_ADMIN_TOKEN env var, or adminTokenEnv in husar.json');
|
|
409
413
|
const url = new URL(endpointPath || 'api/graphql', host).toString();
|
|
410
414
|
const res = await fetch(url, {
|
|
411
415
|
method: 'POST',
|
|
@@ -603,9 +607,10 @@ export const startMcpServer = async () => {
|
|
|
603
607
|
const cfg = await getConfig(workspaceRoot);
|
|
604
608
|
const raw = cfg.get();
|
|
605
609
|
const host = raw.host;
|
|
606
|
-
const token = raw
|
|
610
|
+
const token = getAdminToken(raw);
|
|
607
611
|
if (!host) throw new Error('Missing host in husar.json');
|
|
608
|
-
if (!token)
|
|
612
|
+
if (!token)
|
|
613
|
+
throw new Error('Admin token not configured. Set HUSAR_ADMIN_TOKEN env var, or adminTokenEnv in husar.json');
|
|
609
614
|
const { query, variables: tmpl } = suggestQueryFromSDL({ sdl, task, rootType: 'Query' });
|
|
610
615
|
const overrides =
|
|
611
616
|
typeof variables === 'string' && variables.trim().length ? JSON.parse(variables) : (variables ?? {});
|
|
@@ -689,9 +694,10 @@ export const startMcpServer = async () => {
|
|
|
689
694
|
const cfg = await getConfig(undefined);
|
|
690
695
|
const raw = cfg.get();
|
|
691
696
|
const host = raw.host;
|
|
692
|
-
const token = raw
|
|
697
|
+
const token = getAdminToken(raw);
|
|
693
698
|
if (!host) throw new Error('Missing host in husar.json');
|
|
694
|
-
if (!token)
|
|
699
|
+
if (!token)
|
|
700
|
+
throw new Error('Admin token not configured. Set HUSAR_ADMIN_TOKEN env var, or adminTokenEnv in husar.json');
|
|
695
701
|
const url = new URL('api/graphql', host).toString();
|
|
696
702
|
const input = { name, args };
|
|
697
703
|
const res = await fetch(url, {
|
|
@@ -718,20 +724,34 @@ export const startMcpServer = async () => {
|
|
|
718
724
|
},
|
|
719
725
|
});
|
|
720
726
|
|
|
727
|
+
// Create a passthrough Zod schema that accepts any object properties.
|
|
728
|
+
// This allows the MCP SDK to properly pass arguments to handlers while
|
|
729
|
+
// letting the backend handle actual validation. We use z.object({}).passthrough()
|
|
730
|
+
// which accepts and preserves all properties.
|
|
731
|
+
const passthroughZodSchema = z.object({}).passthrough();
|
|
732
|
+
|
|
721
733
|
for (const toolDef of ormTools) {
|
|
722
|
-
//
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
734
|
+
// Register ORM tools with the passthrough schema.
|
|
735
|
+
// The description includes the actual JSON Schema for AI context.
|
|
736
|
+
server.registerTool(
|
|
737
|
+
toolDef.name,
|
|
738
|
+
{
|
|
739
|
+
description: `${toolDef.description}\n\nExpected parameters: ${JSON.stringify(toolDef.parameters, null, 2)}`,
|
|
740
|
+
inputSchema: passthroughZodSchema,
|
|
741
|
+
},
|
|
742
|
+
(async (args: unknown, _extra: unknown) => {
|
|
743
|
+
try {
|
|
744
|
+
const outcome = await toolDef.run(args);
|
|
745
|
+
const payload =
|
|
746
|
+
typeof outcome.result !== 'undefined' ? outcome.result : { ok: outcome.ok, error: outcome.error };
|
|
747
|
+
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
|
|
748
|
+
} catch (err) {
|
|
749
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
750
|
+
const stack = err instanceof Error && err.stack ? `\nStack: ${err.stack}` : '';
|
|
751
|
+
return { isError: true, content: [{ type: 'text', text: `Error: ${message}${stack}` }] };
|
|
752
|
+
}
|
|
753
|
+
}) as any,
|
|
754
|
+
);
|
|
735
755
|
}
|
|
736
756
|
} catch (e) {
|
|
737
757
|
// In case tool spec import fails, keep MCP operational for other tools
|
package/src/types/config.ts
CHANGED
|
@@ -3,5 +3,36 @@ export type HusarConfigType = {
|
|
|
3
3
|
hostEnvironmentVariable: string;
|
|
4
4
|
authenticationEnvironmentVariable: string;
|
|
5
5
|
overrideHost: boolean;
|
|
6
|
-
|
|
6
|
+
/** @deprecated Use adminTokenEnv instead for security. This field is kept for backward compatibility. */
|
|
7
|
+
adminToken?: string;
|
|
8
|
+
/** Environment variable name containing the admin token (recommended) */
|
|
9
|
+
adminTokenEnv?: string;
|
|
7
10
|
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get the admin token from config, checking env vars first
|
|
14
|
+
* Priority:
|
|
15
|
+
* 1. HUSAR_MCP_ADMIN_TOKEN env var (for MCP override)
|
|
16
|
+
* 2. ENV var specified by adminTokenEnv in config
|
|
17
|
+
* 3. HUSAR_ADMIN_TOKEN env var (default)
|
|
18
|
+
* 4. adminToken field in config (deprecated, for backward compatibility)
|
|
19
|
+
*/
|
|
20
|
+
export function getAdminToken(config: Partial<HusarConfigType>): string | undefined {
|
|
21
|
+
// 1. MCP-specific override
|
|
22
|
+
if (process.env.HUSAR_MCP_ADMIN_TOKEN) {
|
|
23
|
+
return process.env.HUSAR_MCP_ADMIN_TOKEN;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 2. Config-specified env var
|
|
27
|
+
if (config.adminTokenEnv && process.env[config.adminTokenEnv]) {
|
|
28
|
+
return process.env[config.adminTokenEnv];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 3. Default env var
|
|
32
|
+
if (process.env.HUSAR_ADMIN_TOKEN) {
|
|
33
|
+
return process.env.HUSAR_ADMIN_TOKEN;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 4. Deprecated: direct token in config (backward compatibility)
|
|
37
|
+
return config.adminToken;
|
|
38
|
+
}
|