@directus/api 35.2.0 → 36.0.0-rc.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/dist/ai/chat/models/chat-request.js +48 -48
- package/dist/ai/chat/models/object-request.js +6 -6
- package/dist/ai/chat/models/providers.js +14 -14
- package/dist/ai/chat/utils/parse-json-schema-7.js +22 -22
- package/dist/ai/mcp/server.js +44 -6
- package/dist/ai/mcp/utils.js +31 -0
- package/dist/ai/tools/assets/index.js +3 -3
- package/dist/ai/tools/collections/index.js +18 -18
- package/dist/ai/tools/fields/index.js +18 -18
- package/dist/ai/tools/files/index.js +18 -18
- package/dist/ai/tools/flows/index.js +16 -16
- package/dist/ai/tools/folders/index.js +18 -18
- package/dist/ai/tools/items/index.js +17 -17
- package/dist/ai/tools/operations/index.js +16 -16
- package/dist/ai/tools/relations/index.js +22 -22
- package/dist/ai/tools/schema/index.js +3 -3
- package/dist/ai/tools/schema.js +159 -159
- package/dist/ai/tools/system/index.js +3 -3
- package/dist/ai/tools/trigger-flow/index.js +3 -3
- package/dist/app.js +33 -9
- package/dist/auth/drivers/ldap.js +3 -1
- package/dist/auth/drivers/local.js +2 -0
- package/dist/auth/drivers/oauth2.js +3 -1
- package/dist/auth/drivers/openid.js +3 -1
- package/dist/auth/drivers/saml.js +2 -0
- package/dist/auth/utils/check-local-disabled.js +16 -0
- package/dist/auth/utils/check-sso-enabled.js +14 -0
- package/dist/auth.js +8 -5
- package/dist/cli/commands/bootstrap/index.js +3 -0
- package/dist/cli/commands/cache/clear.js +6 -1
- package/dist/cli/commands/roles/create.js +4 -1
- package/dist/cli/commands/users/create.js +3 -0
- package/dist/constants.js +8 -1
- package/dist/controllers/access.js +1 -1
- package/dist/controllers/activity.js +2 -1
- package/dist/controllers/assets.js +2 -0
- package/dist/controllers/auth.js +13 -5
- package/dist/controllers/collections.js +1 -1
- package/dist/controllers/comments.js +1 -1
- package/dist/controllers/dashboards.js +1 -1
- package/dist/controllers/fields.js +1 -1
- package/dist/controllers/files.js +3 -1
- package/dist/controllers/flows.js +6 -5
- package/dist/controllers/folders.js +1 -1
- package/dist/controllers/graphql.js +2 -0
- package/dist/controllers/items.js +3 -1
- package/dist/controllers/license.js +119 -0
- package/dist/controllers/mcp/index.js +38 -0
- package/dist/controllers/mcp/oauth-clients.js +68 -0
- package/dist/controllers/mcp/oauth-consent-page.js +316 -0
- package/dist/controllers/mcp/oauth.js +381 -0
- package/dist/controllers/mcp/templates/oauth-consent.liquid +62 -0
- package/dist/controllers/mcp/templates/oauth-error.liquid +28 -0
- package/dist/controllers/notifications.js +1 -1
- package/dist/controllers/operations.js +1 -1
- package/dist/controllers/panels.js +1 -1
- package/dist/controllers/permissions.js +1 -1
- package/dist/controllers/policies.js +1 -1
- package/dist/controllers/presets.js +1 -1
- package/dist/controllers/revisions.js +3 -2
- package/dist/controllers/roles.js +1 -1
- package/dist/controllers/server.js +38 -9
- package/dist/controllers/shares.js +1 -1
- package/dist/controllers/translations.js +1 -1
- package/dist/controllers/users.js +1 -1
- package/dist/controllers/utils.js +2 -2
- package/dist/controllers/versions.js +12 -5
- package/dist/database/get-ast-from-query/lib/convert-wildcards.js +10 -1
- package/dist/database/get-ast-from-query/lib/parse-fields.js +2 -1
- package/dist/database/helpers/fn/dialects/mysql.js +7 -12
- package/dist/database/helpers/fn/dialects/oracle.js +3 -4
- package/dist/database/helpers/fn/dialects/postgres.js +4 -26
- package/dist/database/helpers/fn/json/mysql-json-path.js +22 -0
- package/dist/database/helpers/fn/json/parse-function.js +14 -6
- package/dist/database/helpers/fn/json/postgres-json-path.js +54 -0
- package/dist/database/migrations/20260110A-add-ai-provider-settings.js +4 -4
- package/dist/database/migrations/20260217A-null-item-versions.js +14 -0
- package/dist/database/migrations/20260312A-add-ai-translation-settings.js +18 -0
- package/dist/database/migrations/20260507A-add-licensing.js +22 -0
- package/dist/database/migrations/20260512A-add-autosave-revision-interval.js +14 -0
- package/dist/database/migrations/20260512B-add-mcp-oauth.js +87 -0
- package/dist/database/run-ast/lib/apply-query/filter/operator.js +116 -33
- package/dist/database/run-ast/lib/apply-query/index.js +4 -1
- package/dist/database/run-ast/lib/apply-query/sort.js +17 -7
- package/dist/database/run-ast/lib/get-db-query.js +21 -9
- package/dist/database/run-ast/lib/parse-current-level.js +2 -1
- package/dist/database/run-ast/run-ast.js +2 -1
- package/dist/database/run-ast/utils/get-column.js +2 -1
- package/dist/extensions/lib/installation/manager.js +1 -1
- package/dist/extensions/lib/sandbox/register/operation.js +1 -1
- package/dist/extensions/lib/sync/sync.js +1 -1
- package/dist/extensions/manager.js +3 -3
- package/dist/flows.js +5 -5
- package/dist/license/entitlements/lib/collections.js +37 -0
- package/dist/license/entitlements/lib/custom-llms-enabled.js +18 -0
- package/dist/license/entitlements/lib/custom-permission-rules-enabled.js +41 -0
- package/dist/license/entitlements/lib/flows.js +29 -0
- package/dist/license/entitlements/lib/seats.js +103 -0
- package/dist/license/entitlements/lib/sso-enabled.js +45 -0
- package/dist/license/entitlements/manager.js +256 -0
- package/dist/license/index.js +4 -0
- package/dist/license/manager.js +505 -0
- package/dist/license/utils/compute-license-status.js +27 -0
- package/dist/license/utils/get-core-grace-expires-at.js +38 -0
- package/dist/license/utils/get-license-key.js +23 -0
- package/dist/license/utils/get-license-token.js +23 -0
- package/dist/license/utils/handle-license-error.js +41 -0
- package/dist/license/utils/is-in-core-grace-period.js +11 -0
- package/dist/license/utils/is-sso-bypass-allowed.js +21 -0
- package/dist/license/utils/use-rpc.js +33 -0
- package/dist/middleware/cache.js +4 -1
- package/dist/middleware/error-handler.js +11 -0
- package/dist/middleware/extract-token.js +11 -2
- package/dist/middleware/is-admin.js +16 -0
- package/dist/middleware/is-locked.js +16 -0
- package/dist/middleware/mcp-oauth-guard.js +23 -0
- package/dist/middleware/request-counter.js +5 -2
- package/dist/packages/types/dist/index.js +117 -122
- package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.js +10 -1
- package/dist/permissions/utils/get-unaliased-field-key.js +2 -1
- package/dist/request/is-denied-ip.js +2 -0
- package/dist/schedules/license.js +31 -0
- package/dist/schedules/oauth-cleanup.js +26 -0
- package/dist/schedules/retention.js +1 -1
- package/dist/schedules/telemetry.js +4 -1
- package/dist/schedules/tus.js +1 -1
- package/dist/schedules/utils/duration-to-cron.js +36 -0
- package/dist/services/activity.js +15 -0
- package/dist/services/authentication.js +12 -5
- package/dist/services/collections.js +40 -10
- package/dist/services/fields.js +6 -6
- package/dist/services/flows.js +12 -0
- package/dist/services/graphql/resolvers/system-admin.js +2 -2
- package/dist/services/graphql/resolvers/system-global.js +1 -1
- package/dist/services/graphql/resolvers/system.js +34 -18
- package/dist/services/graphql/schema/get-types.js +23 -2
- package/dist/services/graphql/schema/parse-query.js +8 -0
- package/dist/services/graphql/schema/read.js +12 -0
- package/dist/services/graphql/types/json-filter.js +30 -0
- package/dist/services/index.js +6 -6
- package/dist/services/items.js +32 -14
- package/dist/services/mcp-oauth/cimd.js +307 -0
- package/dist/services/mcp-oauth/index.js +1185 -0
- package/dist/services/mcp-oauth/types/error.js +22 -0
- package/dist/services/mcp-oauth/utils/cimd-egress.js +182 -0
- package/dist/services/mcp-oauth/utils/domain.js +21 -0
- package/dist/services/mcp-oauth/utils/loopback.js +11 -0
- package/dist/services/mcp-oauth/utils/redirect.js +84 -0
- package/dist/services/mcp-oauth/utils/registration-debug.js +131 -0
- package/dist/services/payload.js +2 -1
- package/dist/services/permissions.js +31 -9
- package/dist/services/revisions.js +15 -0
- package/dist/services/server.js +21 -4
- package/dist/services/settings.js +37 -3
- package/dist/services/users.js +13 -6
- package/dist/services/utils.js +6 -1
- package/dist/services/versions.js +137 -69
- package/dist/utils/calculate-field-depth.js +1 -0
- package/dist/utils/deep-freeze.js +24 -0
- package/dist/utils/extract-function-name.js +13 -0
- package/dist/utils/generate-translations.js +5 -5
- package/dist/utils/get-accountability-for-token.js +13 -1
- package/dist/utils/get-cache-key.js +1 -1
- package/dist/utils/get-history-filter-query.js +22 -0
- package/dist/utils/get-schema.js +2 -2
- package/dist/utils/get-service.js +3 -3
- package/dist/utils/is-admin.js +9 -0
- package/dist/utils/parse-oauth-scope.js +12 -0
- package/dist/utils/sanitize-query.js +1 -1
- package/dist/utils/split-field-path.js +29 -0
- package/dist/utils/transaction.js +2 -2
- package/dist/utils/translations-validation.js +2 -2
- package/dist/utils/validate-query.js +35 -4
- package/dist/utils/validate-user-count-integrity.js +28 -5
- package/dist/utils/verify-session-jwt.js +5 -2
- package/dist/utils/versioning/handle-version.js +130 -48
- package/dist/utils/versioning/remove-circular.js +17 -0
- package/dist/websocket/authenticate.js +2 -1
- package/dist/websocket/collab/collab.js +1 -1
- package/dist/websocket/collab/room.js +1 -1
- package/dist/websocket/controllers/base.js +12 -0
- package/dist/websocket/controllers/graphql.js +1 -1
- package/dist/websocket/handlers/subscribe.js +1 -1
- package/dist/websocket/messages.js +64 -64
- package/dist/websocket/utils/items.js +2 -2
- package/license +90 -80
- package/package.json +33 -32
- package/dist/controllers/mcp.js +0 -31
|
@@ -1,79 +1,79 @@
|
|
|
1
1
|
import { zodJsonSchema7Parser } from "../utils/zod-jsonschema7-parser.js";
|
|
2
2
|
import { ProviderAnthropic, ProviderGoogle, ProviderOpenAi, ProviderOpenAiCompatible } from "./providers.js";
|
|
3
3
|
import "ai";
|
|
4
|
-
import { z } from "zod";
|
|
4
|
+
import { z as z$1 } from "zod";
|
|
5
5
|
|
|
6
6
|
//#region src/ai/chat/models/chat-request.ts
|
|
7
|
-
const ChatRequestTool = z.union([z.string(), z.object({
|
|
8
|
-
name: z.string(),
|
|
9
|
-
description: z.string(),
|
|
10
|
-
inputSchema: z.custom(zodJsonSchema7Parser, { message: "Invalid JSON schema" })
|
|
7
|
+
const ChatRequestTool = z$1.union([z$1.string(), z$1.object({
|
|
8
|
+
name: z$1.string(),
|
|
9
|
+
description: z$1.string(),
|
|
10
|
+
inputSchema: z$1.custom(zodJsonSchema7Parser, { message: "Invalid JSON schema" })
|
|
11
11
|
})]);
|
|
12
|
-
const ToolApprovalMode = z.enum([
|
|
12
|
+
const ToolApprovalMode = z$1.enum([
|
|
13
13
|
"always",
|
|
14
14
|
"ask",
|
|
15
15
|
"disabled"
|
|
16
16
|
]);
|
|
17
|
-
const ItemContextData = z.object({
|
|
18
|
-
collection: z.string(),
|
|
19
|
-
key: z.union([z.string(), z.number()])
|
|
17
|
+
const ItemContextData = z$1.object({
|
|
18
|
+
collection: z$1.string(),
|
|
19
|
+
key: z$1.union([z$1.string(), z$1.number()])
|
|
20
20
|
});
|
|
21
|
-
const VisualElementContextData = z.object({
|
|
22
|
-
key: z.string(),
|
|
23
|
-
collection: z.string(),
|
|
24
|
-
item: z.union([z.string(), z.number()]),
|
|
25
|
-
fields: z.array(z.string()).optional(),
|
|
26
|
-
rect: z.object({
|
|
27
|
-
top: z.number(),
|
|
28
|
-
left: z.number(),
|
|
29
|
-
width: z.number(),
|
|
30
|
-
height: z.number()
|
|
21
|
+
const VisualElementContextData = z$1.object({
|
|
22
|
+
key: z$1.string(),
|
|
23
|
+
collection: z$1.string(),
|
|
24
|
+
item: z$1.union([z$1.string(), z$1.number()]),
|
|
25
|
+
fields: z$1.array(z$1.string()).optional(),
|
|
26
|
+
rect: z$1.object({
|
|
27
|
+
top: z$1.number(),
|
|
28
|
+
left: z$1.number(),
|
|
29
|
+
width: z$1.number(),
|
|
30
|
+
height: z$1.number()
|
|
31
31
|
}).optional()
|
|
32
32
|
});
|
|
33
|
-
const PromptContextData = z.object({
|
|
34
|
-
text: z.string(),
|
|
35
|
-
prompt: z.record(z.string(), z.unknown()),
|
|
36
|
-
values: z.record(z.string(), z.string())
|
|
33
|
+
const PromptContextData = z$1.object({
|
|
34
|
+
text: z$1.string(),
|
|
35
|
+
prompt: z$1.record(z$1.string(), z$1.unknown()),
|
|
36
|
+
values: z$1.record(z$1.string(), z$1.string())
|
|
37
37
|
});
|
|
38
|
-
const ContextAttachment = z.discriminatedUnion("type", [
|
|
39
|
-
z.object({
|
|
40
|
-
type: z.literal("item"),
|
|
41
|
-
display: z.string(),
|
|
38
|
+
const ContextAttachment = z$1.discriminatedUnion("type", [
|
|
39
|
+
z$1.object({
|
|
40
|
+
type: z$1.literal("item"),
|
|
41
|
+
display: z$1.string(),
|
|
42
42
|
data: ItemContextData,
|
|
43
|
-
snapshot: z.record(z.string(), z.unknown())
|
|
43
|
+
snapshot: z$1.record(z$1.string(), z$1.unknown())
|
|
44
44
|
}),
|
|
45
|
-
z.object({
|
|
46
|
-
type: z.literal("visual-element"),
|
|
47
|
-
display: z.string(),
|
|
45
|
+
z$1.object({
|
|
46
|
+
type: z$1.literal("visual-element"),
|
|
47
|
+
display: z$1.string(),
|
|
48
48
|
data: VisualElementContextData,
|
|
49
|
-
snapshot: z.record(z.string(), z.unknown())
|
|
49
|
+
snapshot: z$1.record(z$1.string(), z$1.unknown())
|
|
50
50
|
}),
|
|
51
|
-
z.object({
|
|
52
|
-
type: z.literal("prompt"),
|
|
53
|
-
display: z.string(),
|
|
51
|
+
z$1.object({
|
|
52
|
+
type: z$1.literal("prompt"),
|
|
53
|
+
display: z$1.string(),
|
|
54
54
|
data: PromptContextData,
|
|
55
|
-
snapshot: z.record(z.string(), z.unknown())
|
|
55
|
+
snapshot: z$1.record(z$1.string(), z$1.unknown())
|
|
56
56
|
})
|
|
57
57
|
]);
|
|
58
|
-
const PageContext = z.object({
|
|
59
|
-
path: z.string(),
|
|
60
|
-
collection: z.string().optional(),
|
|
61
|
-
item: z.union([z.string(), z.number()]).optional(),
|
|
62
|
-
module: z.string().optional()
|
|
58
|
+
const PageContext = z$1.object({
|
|
59
|
+
path: z$1.string(),
|
|
60
|
+
collection: z$1.string().optional(),
|
|
61
|
+
item: z$1.union([z$1.string(), z$1.number()]).optional(),
|
|
62
|
+
module: z$1.string().optional()
|
|
63
63
|
});
|
|
64
|
-
const ChatContext = z.object({
|
|
65
|
-
attachments: z.array(ContextAttachment).max(10).optional(),
|
|
64
|
+
const ChatContext = z$1.object({
|
|
65
|
+
attachments: z$1.array(ContextAttachment).max(10).optional(),
|
|
66
66
|
page: PageContext.optional()
|
|
67
67
|
});
|
|
68
|
-
const ChatRequest = z.intersection(z.discriminatedUnion("provider", [
|
|
68
|
+
const ChatRequest = z$1.intersection(z$1.discriminatedUnion("provider", [
|
|
69
69
|
ProviderOpenAi,
|
|
70
70
|
ProviderAnthropic,
|
|
71
71
|
ProviderGoogle,
|
|
72
72
|
ProviderOpenAiCompatible
|
|
73
|
-
]), z.object({
|
|
74
|
-
tools: z.array(ChatRequestTool),
|
|
75
|
-
messages: z.array(z.looseObject({})),
|
|
76
|
-
toolApprovals: z.record(z.string(), ToolApprovalMode).optional(),
|
|
73
|
+
]), z$1.object({
|
|
74
|
+
tools: z$1.array(ChatRequestTool),
|
|
75
|
+
messages: z$1.array(z$1.looseObject({})),
|
|
76
|
+
toolApprovals: z$1.record(z$1.string(), ToolApprovalMode).optional(),
|
|
77
77
|
context: ChatContext.optional()
|
|
78
78
|
}));
|
|
79
79
|
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { zodJsonSchema7Parser } from "../utils/zod-jsonschema7-parser.js";
|
|
2
2
|
import { ProviderAnthropic, ProviderGoogle, ProviderOpenAi, ProviderOpenAiCompatible } from "./providers.js";
|
|
3
3
|
import "ai";
|
|
4
|
-
import { z } from "zod";
|
|
4
|
+
import { z as z$1 } from "zod";
|
|
5
5
|
|
|
6
6
|
//#region src/ai/chat/models/object-request.ts
|
|
7
|
-
const ObjectRequest = z.intersection(z.discriminatedUnion("provider", [
|
|
7
|
+
const ObjectRequest = z$1.intersection(z$1.discriminatedUnion("provider", [
|
|
8
8
|
ProviderOpenAi,
|
|
9
9
|
ProviderAnthropic,
|
|
10
10
|
ProviderGoogle,
|
|
11
11
|
ProviderOpenAiCompatible
|
|
12
|
-
]), z.object({
|
|
13
|
-
prompt: z.string(),
|
|
14
|
-
outputSchema: z.custom(zodJsonSchema7Parser, { message: "Invalid JSON schema" }),
|
|
15
|
-
maxOutputTokens: z.number().int().min(256).optional()
|
|
12
|
+
]), z$1.object({
|
|
13
|
+
prompt: z$1.string(),
|
|
14
|
+
outputSchema: z$1.custom(zodJsonSchema7Parser, { message: "Invalid JSON schema" }),
|
|
15
|
+
maxOutputTokens: z$1.number().int().min(256).optional()
|
|
16
16
|
}));
|
|
17
17
|
|
|
18
18
|
//#endregion
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
1
|
+
import { z as z$1 } from "zod";
|
|
2
2
|
|
|
3
3
|
//#region src/ai/chat/models/providers.ts
|
|
4
|
-
const ProviderTypeSchema = z.enum([
|
|
4
|
+
const ProviderTypeSchema = z$1.enum([
|
|
5
5
|
"openai",
|
|
6
6
|
"anthropic",
|
|
7
7
|
"google",
|
|
8
8
|
"openai-compatible"
|
|
9
9
|
]);
|
|
10
|
-
const ProviderOpenAi = z.object({
|
|
11
|
-
provider: z.literal("openai"),
|
|
12
|
-
model: z.string()
|
|
10
|
+
const ProviderOpenAi = z$1.object({
|
|
11
|
+
provider: z$1.literal("openai"),
|
|
12
|
+
model: z$1.string()
|
|
13
13
|
});
|
|
14
|
-
const ProviderAnthropic = z.object({
|
|
15
|
-
provider: z.literal("anthropic"),
|
|
16
|
-
model: z.string()
|
|
14
|
+
const ProviderAnthropic = z$1.object({
|
|
15
|
+
provider: z$1.literal("anthropic"),
|
|
16
|
+
model: z$1.string()
|
|
17
17
|
});
|
|
18
|
-
const ProviderGoogle = z.object({
|
|
19
|
-
provider: z.literal("google"),
|
|
20
|
-
model: z.string()
|
|
18
|
+
const ProviderGoogle = z$1.object({
|
|
19
|
+
provider: z$1.literal("google"),
|
|
20
|
+
model: z$1.string()
|
|
21
21
|
});
|
|
22
|
-
const ProviderOpenAiCompatible = z.object({
|
|
23
|
-
provider: z.literal("openai-compatible"),
|
|
24
|
-
model: z.string()
|
|
22
|
+
const ProviderOpenAiCompatible = z$1.object({
|
|
23
|
+
provider: z$1.literal("openai-compatible"),
|
|
24
|
+
model: z$1.string()
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
//#endregion
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { fromZodError } from "zod-validation-error";
|
|
2
|
-
import { z } from "zod";
|
|
2
|
+
import { z as z$1 } from "zod";
|
|
3
3
|
|
|
4
4
|
//#region src/ai/chat/utils/parse-json-schema-7.ts
|
|
5
|
-
const jsonType = z.enum([
|
|
5
|
+
const jsonType = z$1.enum([
|
|
6
6
|
"null",
|
|
7
7
|
"boolean",
|
|
8
8
|
"object",
|
|
@@ -11,7 +11,7 @@ const jsonType = z.enum([
|
|
|
11
11
|
"integer",
|
|
12
12
|
"string"
|
|
13
13
|
]);
|
|
14
|
-
const maybeDraft7Url = z.url({
|
|
14
|
+
const maybeDraft7Url = z$1.url({
|
|
15
15
|
protocol: /^https?$/,
|
|
16
16
|
hostname: /^json-schema\.org$/
|
|
17
17
|
}).refine((val) => {
|
|
@@ -22,26 +22,26 @@ const maybeDraft7Url = z.url({
|
|
|
22
22
|
return false;
|
|
23
23
|
}
|
|
24
24
|
}, { message: "Must be the JSON Schema Draft-07 meta-schema URL" });
|
|
25
|
-
const JsonSchema7 = z.object({
|
|
25
|
+
const JsonSchema7 = z$1.object({
|
|
26
26
|
$schema: maybeDraft7Url.optional(),
|
|
27
|
-
$id: z.string().optional(),
|
|
28
|
-
$ref: z.string().optional(),
|
|
29
|
-
title: z.string().optional(),
|
|
30
|
-
description: z.string().optional(),
|
|
31
|
-
type: z.union([jsonType, z.array(jsonType).nonempty()]).optional(),
|
|
32
|
-
properties: z.record(z.string(), z.any()).optional(),
|
|
33
|
-
required: z.array(z.string()).optional(),
|
|
34
|
-
items: z.union([z.any(), z.array(z.any()).nonempty()]).optional(),
|
|
35
|
-
additionalProperties: z.union([z.boolean(), z.any()]).optional(),
|
|
36
|
-
patternProperties: z.record(z.string(), z.any()).optional(),
|
|
37
|
-
enum: z.array(z.any()).optional(),
|
|
38
|
-
const: z.any().optional(),
|
|
39
|
-
anyOf: z.array(z.any()).optional(),
|
|
40
|
-
allOf: z.array(z.any()).optional(),
|
|
41
|
-
oneOf: z.array(z.any()).optional(),
|
|
42
|
-
not: z.any().optional(),
|
|
43
|
-
definitions: z.record(z.string(), z.any()).optional(),
|
|
44
|
-
$defs: z.record(z.string(), z.any()).optional()
|
|
27
|
+
$id: z$1.string().optional(),
|
|
28
|
+
$ref: z$1.string().optional(),
|
|
29
|
+
title: z$1.string().optional(),
|
|
30
|
+
description: z$1.string().optional(),
|
|
31
|
+
type: z$1.union([jsonType, z$1.array(jsonType).nonempty()]).optional(),
|
|
32
|
+
properties: z$1.record(z$1.string(), z$1.any()).optional(),
|
|
33
|
+
required: z$1.array(z$1.string()).optional(),
|
|
34
|
+
items: z$1.union([z$1.any(), z$1.array(z$1.any()).nonempty()]).optional(),
|
|
35
|
+
additionalProperties: z$1.union([z$1.boolean(), z$1.any()]).optional(),
|
|
36
|
+
patternProperties: z$1.record(z$1.string(), z$1.any()).optional(),
|
|
37
|
+
enum: z$1.array(z$1.any()).optional(),
|
|
38
|
+
const: z$1.any().optional(),
|
|
39
|
+
anyOf: z$1.array(z$1.any()).optional(),
|
|
40
|
+
allOf: z$1.array(z$1.any()).optional(),
|
|
41
|
+
oneOf: z$1.array(z$1.any()).optional(),
|
|
42
|
+
not: z$1.any().optional(),
|
|
43
|
+
definitions: z$1.record(z$1.string(), z$1.any()).optional(),
|
|
44
|
+
$defs: z$1.record(z$1.string(), z$1.any()).optional()
|
|
45
45
|
}).refine((obj) => {
|
|
46
46
|
const keys = new Set(Object.keys(obj));
|
|
47
47
|
return [
|
package/dist/ai/mcp/server.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { ItemsService } from "../../services/items.js";
|
|
2
|
-
import { coerceJsonFields } from "../tools/utils.js";
|
|
3
2
|
import { Url } from "../../utils/url.js";
|
|
4
3
|
import "../../services/index.js";
|
|
4
|
+
import { coerceJsonFields } from "../tools/utils.js";
|
|
5
5
|
import { findMcpTool, getAllMcpTools } from "../tools/index.js";
|
|
6
6
|
import { DirectusTransport } from "./transport.js";
|
|
7
|
+
import { MCP_ACCESS_SCOPE, buildMcpWWWAuthenticateHeader, getMcpUrls } from "./utils.js";
|
|
7
8
|
import { useEnv } from "@directus/env";
|
|
8
9
|
import { ForbiddenError, InvalidPayloadError, isDirectusError } from "@directus/errors";
|
|
9
10
|
import { isObject, toArray } from "@directus/utils";
|
|
10
11
|
import { fromZodError } from "zod-validation-error";
|
|
11
|
-
import { z } from "zod";
|
|
12
|
+
import { z as z$1 } from "zod";
|
|
12
13
|
import { render, tokenize } from "micromustache";
|
|
13
14
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
14
15
|
import { CallToolRequestSchema, ErrorCode as ErrorCode$1, GetPromptRequestSchema, InitializedNotificationSchema, JSONRPCMessageSchema, ListPromptsRequestSchema, ListToolsRequestSchema, McpError } from "@modelcontextprotocol/sdk/types.js";
|
|
@@ -34,11 +35,48 @@ var DirectusMCP = class {
|
|
|
34
35
|
} });
|
|
35
36
|
}
|
|
36
37
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
38
|
+
* Send a 401 with WWW-Authenticate per RFC 6750 / RFC 9728.
|
|
39
|
+
* Includes `resource_metadata` pointing to `/.well-known/oauth-protected-resource/mcp`
|
|
40
|
+
* so clients can discover the authorization server from a 401 response.
|
|
41
|
+
*/
|
|
42
|
+
sendUnauthorized(res, error, status = 401) {
|
|
43
|
+
const { metadataUrl } = getMcpUrls();
|
|
44
|
+
res.set("WWW-Authenticate", buildMcpWWWAuthenticateHeader(metadataUrl, error)).set("Access-Control-Expose-Headers", "WWW-Authenticate").status(status).send();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Handle an incoming MCP JSON-RPC request.
|
|
48
|
+
*
|
|
49
|
+
* OAuth-specific checks (when `accountability.oauth` is set):
|
|
50
|
+
* - Transport restriction: token must be in Authorization header (RFC 6750), not cookie/query
|
|
51
|
+
* - Scope check: must include mcp:access
|
|
52
|
+
* - Audience check: must match the canonical MCP resource URL (PUBLIC_URL/mcp)
|
|
53
|
+
*
|
|
54
|
+
* Note: this function does not await lower-level logic; the actual response is an
|
|
55
|
+
* asynchronous side effect happening after the function returns.
|
|
56
|
+
*
|
|
57
|
+
* @see sendUnauthorized for WWW-Authenticate format (RFC 9728 `resource_metadata` attribute)
|
|
39
58
|
*/
|
|
40
59
|
handleRequest(req, res) {
|
|
41
|
-
|
|
60
|
+
const oauth = req.accountability?.oauth;
|
|
61
|
+
if (!req.accountability?.user && !req.accountability?.role && req.accountability?.admin !== true) {
|
|
62
|
+
this.sendUnauthorized(res);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (oauth) {
|
|
66
|
+
if (req.tokenSource !== "header") {
|
|
67
|
+
this.sendUnauthorized(res, "invalid_request");
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (!oauth.scopes.includes(MCP_ACCESS_SCOPE)) {
|
|
71
|
+
this.sendUnauthorized(res, "insufficient_scope", 403);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const { resourceUrl } = getMcpUrls();
|
|
75
|
+
if (!oauth.aud.includes(resourceUrl)) {
|
|
76
|
+
this.sendUnauthorized(res, "invalid_token");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
42
80
|
if (!req.accepts("application/json")) {
|
|
43
81
|
res.status(405).send();
|
|
44
82
|
return;
|
|
@@ -130,7 +168,7 @@ var DirectusMCP = class {
|
|
|
130
168
|
tools.push({
|
|
131
169
|
name: tool.name,
|
|
132
170
|
description: tool.description,
|
|
133
|
-
inputSchema: z.toJSONSchema(tool.inputSchema),
|
|
171
|
+
inputSchema: z$1.toJSONSchema(tool.inputSchema),
|
|
134
172
|
annotations: tool.annotations
|
|
135
173
|
});
|
|
136
174
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useEnv } from "@directus/env";
|
|
2
|
+
|
|
3
|
+
//#region src/ai/mcp/utils.ts
|
|
4
|
+
/** The only OAuth scope for MCP access. Used in JWT claims, discovery metadata, and scope validation. */
|
|
5
|
+
const MCP_ACCESS_SCOPE = "mcp:access";
|
|
6
|
+
/**
|
|
7
|
+
* Canonical MCP resource and discovery URLs derived from PUBLIC_URL.
|
|
8
|
+
*/
|
|
9
|
+
function getMcpUrls() {
|
|
10
|
+
const base = useEnv()["PUBLIC_URL"].replace(/\/+$/, "");
|
|
11
|
+
return {
|
|
12
|
+
issuerUrl: base || "/",
|
|
13
|
+
resourceUrl: `${base}/mcp`,
|
|
14
|
+
metadataUrl: `${base}/.well-known/oauth-protected-resource/mcp`
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** Check if a request path targets the concrete MCP endpoint. */
|
|
18
|
+
function isMcpPath(path) {
|
|
19
|
+
return path === "/mcp" || path === "/mcp/";
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* RFC 6750 / RFC 9728 WWW-Authenticate header for MCP OAuth responses.
|
|
23
|
+
*/
|
|
24
|
+
function buildMcpWWWAuthenticateHeader(metadataUrl, error) {
|
|
25
|
+
let header = `Bearer resource_metadata="${metadataUrl}", scope="${MCP_ACCESS_SCOPE}"`;
|
|
26
|
+
if (error) header += `, error="${error}"`;
|
|
27
|
+
return header;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
31
|
+
export { MCP_ACCESS_SCOPE, buildMcpWWWAuthenticateHeader, getMcpUrls, isMcpPath };
|
|
@@ -4,13 +4,13 @@ import { requireText } from "../../../utils/require-text.js";
|
|
|
4
4
|
import { defineTool } from "../define-tool.js";
|
|
5
5
|
import { UnsupportedMediaTypeError } from "@directus/errors";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import { z } from "zod";
|
|
7
|
+
import { z as z$1 } from "zod";
|
|
8
8
|
import { dirname, resolve } from "node:path";
|
|
9
9
|
|
|
10
10
|
//#region src/ai/tools/assets/index.ts
|
|
11
11
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
-
const AssetsValidateSchema = z.strictObject({ id: z.string() });
|
|
13
|
-
const AssetsInputSchema = z.object({ id: z.string() });
|
|
12
|
+
const AssetsValidateSchema = z$1.strictObject({ id: z$1.string() });
|
|
13
|
+
const AssetsInputSchema = z$1.object({ id: z$1.string() });
|
|
14
14
|
const assets = defineTool({
|
|
15
15
|
name: "assets",
|
|
16
16
|
description: requireText(resolve(__dirname, "./prompt.md")),
|
|
@@ -5,38 +5,38 @@ import { CollectionItemInputSchema, CollectionItemValidateCreateSchema, Collecti
|
|
|
5
5
|
import { InvalidPayloadError } from "@directus/errors";
|
|
6
6
|
import { isObject, toArray } from "@directus/utils";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
|
-
import { z } from "zod";
|
|
8
|
+
import { z as z$1 } from "zod";
|
|
9
9
|
import { dirname, resolve } from "node:path";
|
|
10
10
|
|
|
11
11
|
//#region src/ai/tools/collections/index.ts
|
|
12
12
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
-
const CollectionsValidateSchema = z.discriminatedUnion("action", [
|
|
14
|
-
z.strictObject({
|
|
15
|
-
action: z.literal("create"),
|
|
16
|
-
data: z.array(CollectionItemValidateCreateSchema)
|
|
13
|
+
const CollectionsValidateSchema = z$1.discriminatedUnion("action", [
|
|
14
|
+
z$1.strictObject({
|
|
15
|
+
action: z$1.literal("create"),
|
|
16
|
+
data: z$1.array(CollectionItemValidateCreateSchema)
|
|
17
17
|
}),
|
|
18
|
-
z.strictObject({
|
|
19
|
-
action: z.literal("read"),
|
|
20
|
-
keys: z.array(z.string()).optional()
|
|
18
|
+
z$1.strictObject({
|
|
19
|
+
action: z$1.literal("read"),
|
|
20
|
+
keys: z$1.array(z$1.string()).optional()
|
|
21
21
|
}),
|
|
22
|
-
z.strictObject({
|
|
23
|
-
action: z.literal("update"),
|
|
24
|
-
data: z.array(CollectionItemValidateUpdateSchema)
|
|
22
|
+
z$1.strictObject({
|
|
23
|
+
action: z$1.literal("update"),
|
|
24
|
+
data: z$1.array(CollectionItemValidateUpdateSchema)
|
|
25
25
|
}),
|
|
26
|
-
z.strictObject({
|
|
27
|
-
action: z.literal("delete"),
|
|
28
|
-
keys: z.array(z.string())
|
|
26
|
+
z$1.strictObject({
|
|
27
|
+
action: z$1.literal("delete"),
|
|
28
|
+
keys: z$1.array(z$1.string())
|
|
29
29
|
})
|
|
30
30
|
]);
|
|
31
|
-
const CollectionsInputSchema = z.object({
|
|
32
|
-
action: z.enum([
|
|
31
|
+
const CollectionsInputSchema = z$1.object({
|
|
32
|
+
action: z$1.enum([
|
|
33
33
|
"create",
|
|
34
34
|
"read",
|
|
35
35
|
"update",
|
|
36
36
|
"delete"
|
|
37
37
|
]).describe("The operation to perform"),
|
|
38
|
-
keys: z.array(z.string()).optional(),
|
|
39
|
-
data: z.array(CollectionItemInputSchema).optional()
|
|
38
|
+
keys: z$1.array(z$1.string()).optional(),
|
|
39
|
+
data: z$1.array(CollectionItemInputSchema).optional()
|
|
40
40
|
});
|
|
41
41
|
const collections = defineTool({
|
|
42
42
|
name: "collections",
|
|
@@ -10,41 +10,41 @@ import { FieldItemInputSchema, FieldItemValidateSchema, RawFieldItemInputSchema,
|
|
|
10
10
|
import { InvalidPayloadError } from "@directus/errors";
|
|
11
11
|
import { toArray } from "@directus/utils";
|
|
12
12
|
import { fileURLToPath } from "node:url";
|
|
13
|
-
import { z } from "zod";
|
|
13
|
+
import { z as z$1 } from "zod";
|
|
14
14
|
import { dirname, resolve } from "node:path";
|
|
15
15
|
|
|
16
16
|
//#region src/ai/tools/fields/index.ts
|
|
17
17
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
18
|
-
const FieldsBaseValidateSchema = z.strictObject({ collection: z.string() });
|
|
19
|
-
const FieldsValidateSchema = z.discriminatedUnion("action", [
|
|
18
|
+
const FieldsBaseValidateSchema = z$1.strictObject({ collection: z$1.string() });
|
|
19
|
+
const FieldsValidateSchema = z$1.discriminatedUnion("action", [
|
|
20
20
|
FieldsBaseValidateSchema.extend({
|
|
21
|
-
action: z.literal("create"),
|
|
22
|
-
data: z.union([z.array(FieldItemValidateSchema), FieldItemValidateSchema])
|
|
21
|
+
action: z$1.literal("create"),
|
|
22
|
+
data: z$1.union([z$1.array(FieldItemValidateSchema), FieldItemValidateSchema])
|
|
23
23
|
}),
|
|
24
|
-
z.object({
|
|
25
|
-
action: z.literal("read"),
|
|
26
|
-
collection: z.string().optional(),
|
|
27
|
-
field: z.string().optional()
|
|
24
|
+
z$1.object({
|
|
25
|
+
action: z$1.literal("read"),
|
|
26
|
+
collection: z$1.string().optional(),
|
|
27
|
+
field: z$1.string().optional()
|
|
28
28
|
}),
|
|
29
29
|
FieldsBaseValidateSchema.extend({
|
|
30
|
-
action: z.literal("update"),
|
|
31
|
-
data: z.array(RawFieldItemValidateSchema.partial({ type: true }))
|
|
30
|
+
action: z$1.literal("update"),
|
|
31
|
+
data: z$1.array(RawFieldItemValidateSchema.partial({ type: true }))
|
|
32
32
|
}),
|
|
33
33
|
FieldsBaseValidateSchema.extend({
|
|
34
|
-
action: z.literal("delete"),
|
|
35
|
-
field: z.string()
|
|
34
|
+
action: z$1.literal("delete"),
|
|
35
|
+
field: z$1.string()
|
|
36
36
|
})
|
|
37
37
|
]);
|
|
38
|
-
const FieldsInputSchema = z.object({
|
|
39
|
-
action: z.enum([
|
|
38
|
+
const FieldsInputSchema = z$1.object({
|
|
39
|
+
action: z$1.enum([
|
|
40
40
|
"read",
|
|
41
41
|
"create",
|
|
42
42
|
"update",
|
|
43
43
|
"delete"
|
|
44
44
|
]).describe("The operation to perform"),
|
|
45
|
-
collection: z.string().describe("The name of the collection").optional(),
|
|
46
|
-
field: z.string().describe("The name of the field. Required for delete. Optional for read (omit to read all fields). Do not use for create or update.").optional(),
|
|
47
|
-
data: z.array(FieldItemInputSchema.extend({ children: RawFieldItemInputSchema.shape.children }).partial().required({ field: true })).describe("Array of field objects for create/update actions. Each object must include \"field\" (the field name).").optional()
|
|
45
|
+
collection: z$1.string().describe("The name of the collection").optional(),
|
|
46
|
+
field: z$1.string().describe("The name of the field. Required for delete. Optional for read (omit to read all fields). Do not use for create or update.").optional(),
|
|
47
|
+
data: z$1.array(FieldItemInputSchema.extend({ children: RawFieldItemInputSchema.shape.children }).partial().required({ field: true })).describe("Array of field objects for create/update actions. Each object must include \"field\" (the field name).").optional()
|
|
48
48
|
});
|
|
49
49
|
const fields = defineTool({
|
|
50
50
|
name: "fields",
|
|
@@ -5,42 +5,42 @@ import { FileImportItemInputSchema, FileImportItemValidateSchema, FileItemInputS
|
|
|
5
5
|
import { buildSanitizedQueryFromArgs } from "../utils.js";
|
|
6
6
|
import { isObject } from "@directus/utils";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
|
-
import { z } from "zod";
|
|
8
|
+
import { z as z$1 } from "zod";
|
|
9
9
|
import { dirname, resolve } from "node:path";
|
|
10
10
|
|
|
11
11
|
//#region src/ai/tools/files/index.ts
|
|
12
12
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
-
const FilesValidateSchema = z.discriminatedUnion("action", [
|
|
14
|
-
z.strictObject({
|
|
15
|
-
action: z.literal("read"),
|
|
16
|
-
keys: z.array(PrimaryKeyValidateSchema).optional(),
|
|
13
|
+
const FilesValidateSchema = z$1.discriminatedUnion("action", [
|
|
14
|
+
z$1.strictObject({
|
|
15
|
+
action: z$1.literal("read"),
|
|
16
|
+
keys: z$1.array(PrimaryKeyValidateSchema).optional(),
|
|
17
17
|
query: QueryValidateSchema.optional()
|
|
18
18
|
}),
|
|
19
|
-
z.strictObject({
|
|
20
|
-
action: z.literal("update"),
|
|
19
|
+
z$1.strictObject({
|
|
20
|
+
action: z$1.literal("update"),
|
|
21
21
|
data: FileItemValidateSchema,
|
|
22
|
-
keys: z.array(PrimaryKeyValidateSchema).optional(),
|
|
22
|
+
keys: z$1.array(PrimaryKeyValidateSchema).optional(),
|
|
23
23
|
query: QueryValidateSchema.optional()
|
|
24
24
|
}),
|
|
25
|
-
z.strictObject({
|
|
26
|
-
action: z.literal("delete"),
|
|
27
|
-
keys: z.array(PrimaryKeyValidateSchema)
|
|
25
|
+
z$1.strictObject({
|
|
26
|
+
action: z$1.literal("delete"),
|
|
27
|
+
keys: z$1.array(PrimaryKeyValidateSchema)
|
|
28
28
|
}),
|
|
29
|
-
z.strictObject({
|
|
30
|
-
action: z.literal("import"),
|
|
31
|
-
data: z.array(FileImportItemValidateSchema)
|
|
29
|
+
z$1.strictObject({
|
|
30
|
+
action: z$1.literal("import"),
|
|
31
|
+
data: z$1.array(FileImportItemValidateSchema)
|
|
32
32
|
})
|
|
33
33
|
]);
|
|
34
|
-
const FilesInputSchema = z.object({
|
|
35
|
-
action: z.enum([
|
|
34
|
+
const FilesInputSchema = z$1.object({
|
|
35
|
+
action: z$1.enum([
|
|
36
36
|
"read",
|
|
37
37
|
"update",
|
|
38
38
|
"delete",
|
|
39
39
|
"import"
|
|
40
40
|
]).describe("The operation to perform"),
|
|
41
41
|
query: QueryInputSchema.optional(),
|
|
42
|
-
keys: z.array(PrimaryKeyInputSchema).optional(),
|
|
43
|
-
data: z.array(FileItemInputSchema.extend({ ...FileImportItemInputSchema.shape }).partial()).optional()
|
|
42
|
+
keys: z$1.array(PrimaryKeyInputSchema).optional(),
|
|
43
|
+
data: z$1.array(FileItemInputSchema.extend({ ...FileImportItemInputSchema.shape }).partial()).optional()
|
|
44
44
|
});
|
|
45
45
|
const files = defineTool({
|
|
46
46
|
name: "files",
|
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
import { requireText } from "../../../utils/require-text.js";
|
|
2
2
|
import { defineTool } from "../define-tool.js";
|
|
3
|
+
import { FlowsService } from "../../../services/flows.js";
|
|
3
4
|
import { FlowItemInputSchema, FlowItemValidateSchema, QueryInputSchema, QueryValidateSchema } from "../schema.js";
|
|
4
5
|
import { buildSanitizedQueryFromArgs } from "../utils.js";
|
|
5
|
-
import { FlowsService } from "../../../services/flows.js";
|
|
6
6
|
import { isObject } from "@directus/utils";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
|
-
import { z } from "zod";
|
|
8
|
+
import { z as z$1 } from "zod";
|
|
9
9
|
import { dirname, resolve } from "node:path";
|
|
10
10
|
|
|
11
11
|
//#region src/ai/tools/flows/index.ts
|
|
12
12
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
-
const FlowsValidateSchema = z.discriminatedUnion("action", [
|
|
14
|
-
z.strictObject({
|
|
15
|
-
action: z.literal("create"),
|
|
13
|
+
const FlowsValidateSchema = z$1.discriminatedUnion("action", [
|
|
14
|
+
z$1.strictObject({
|
|
15
|
+
action: z$1.literal("create"),
|
|
16
16
|
data: FlowItemValidateSchema
|
|
17
17
|
}),
|
|
18
|
-
z.strictObject({
|
|
19
|
-
action: z.literal("read"),
|
|
18
|
+
z$1.strictObject({
|
|
19
|
+
action: z$1.literal("read"),
|
|
20
20
|
query: QueryValidateSchema.optional()
|
|
21
21
|
}),
|
|
22
|
-
z.strictObject({
|
|
23
|
-
action: z.literal("update"),
|
|
24
|
-
key: z.string(),
|
|
22
|
+
z$1.strictObject({
|
|
23
|
+
action: z$1.literal("update"),
|
|
24
|
+
key: z$1.string(),
|
|
25
25
|
data: FlowItemValidateSchema,
|
|
26
26
|
query: QueryValidateSchema.optional()
|
|
27
27
|
}),
|
|
28
|
-
z.strictObject({
|
|
29
|
-
action: z.literal("delete"),
|
|
30
|
-
key: z.string()
|
|
28
|
+
z$1.strictObject({
|
|
29
|
+
action: z$1.literal("delete"),
|
|
30
|
+
key: z$1.string()
|
|
31
31
|
})
|
|
32
32
|
]);
|
|
33
|
-
const FlowsInputSchema = z.object({
|
|
34
|
-
action: z.enum([
|
|
33
|
+
const FlowsInputSchema = z$1.object({
|
|
34
|
+
action: z$1.enum([
|
|
35
35
|
"create",
|
|
36
36
|
"read",
|
|
37
37
|
"update",
|
|
@@ -39,7 +39,7 @@ const FlowsInputSchema = z.object({
|
|
|
39
39
|
]).describe("The operation to perform"),
|
|
40
40
|
query: QueryInputSchema.optional(),
|
|
41
41
|
data: FlowItemInputSchema.optional(),
|
|
42
|
-
key: z.string().optional()
|
|
42
|
+
key: z$1.string().optional()
|
|
43
43
|
});
|
|
44
44
|
const flows = defineTool({
|
|
45
45
|
name: "flows",
|