@gjermundgaraba/effect-actions 0.20.0 → 0.21.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 +19 -41
- package/dist/Action.d.mts +140 -46
- package/dist/Action.mjs +87 -42
- package/dist/ActionCli.d.mts +69 -33
- package/dist/ActionCli.mjs +51 -32
- package/dist/ActionHttp.d.mts +69 -35
- package/dist/ActionHttp.mjs +75 -23
- package/dist/ActionMcp.d.mts +56 -22
- package/dist/ActionMcp.mjs +94 -69
- package/dist/ActionRpc.d.mts +222 -55
- package/dist/ActionRpc.mjs +299 -46
- package/dist/ActionToolkit.d.mts +22 -5
- package/dist/ActionToolkit.mjs +36 -12
- package/dist/Authentication.d.mts +42 -10
- package/dist/Authentication.mjs +37 -30
- package/dist/Event.d.mts +370 -0
- package/dist/Event.mjs +103 -0
- package/dist/Testing.mjs +1 -1
- package/dist/Webhook.d.mts +146 -0
- package/dist/Webhook.mjs +72 -0
- package/dist/authentication/provider.d.mts +35 -10
- package/dist/authentication/provider.mjs +1 -1
- package/dist/authentication/refusal.mjs +2 -2
- package/dist/cli/commands.d.mts +9 -5
- package/dist/cli/commands.mjs +84 -33
- package/dist/contract/ast.mjs +4 -1
- package/dist/contract/authorizer.d.mts +8 -0
- package/dist/contract/authorizer.mjs +20 -0
- package/dist/contract/call.d.mts +9 -6
- package/dist/contract/call.mjs +48 -6
- package/dist/contract/callback.d.mts +7 -0
- package/dist/contract/callback.mjs +27 -0
- package/dist/contract/caller.d.mts +13 -2
- package/dist/contract/caller.mjs +22 -3
- package/dist/contract/canonical.mjs +10 -0
- package/dist/contract/codec.d.mts +9 -0
- package/dist/contract/codec.mjs +9 -0
- package/dist/contract/codes.mjs +81 -0
- package/dist/contract/declared.mjs +25 -9
- package/dist/contract/digest.mjs +6 -0
- package/dist/contract/errors.d.mts +9 -3
- package/dist/contract/errors.mjs +1 -1
- package/dist/contract/feed.d.mts +127 -0
- package/dist/contract/feed.mjs +249 -0
- package/dist/contract/hub.d.mts +94 -0
- package/dist/contract/hub.mjs +133 -0
- package/dist/contract/idempotency.d.mts +47 -0
- package/dist/contract/idempotency.mjs +99 -0
- package/dist/contract/implementation.d.mts +73 -47
- package/dist/contract/implementation.mjs +92 -58
- package/dist/contract/input-check.d.mts +15 -0
- package/dist/contract/input-check.mjs +16 -0
- package/dist/contract/lease.mjs +28 -0
- package/dist/contract/listed.d.mts +4 -0
- package/dist/contract/listed.mjs +22 -0
- package/dist/contract/log.d.mts +41 -0
- package/dist/contract/log.mjs +144 -0
- package/dist/contract/names.mjs +14 -4
- package/dist/contract/occurrence.d.mts +29 -0
- package/dist/contract/occurrence.mjs +45 -0
- package/dist/contract/pages.d.mts +13 -0
- package/dist/contract/pages.mjs +39 -0
- package/dist/contract/progress.d.mts +26 -0
- package/dist/contract/progress.mjs +72 -0
- package/dist/contract/push.d.mts +20 -0
- package/dist/contract/push.mjs +96 -0
- package/dist/contract/receiving.d.mts +29 -0
- package/dist/contract/receiving.mjs +42 -0
- package/dist/contract/recent.mjs +12 -0
- package/dist/contract/reported.mjs +16 -0
- package/dist/contract/serving.mjs +63 -0
- package/dist/contract/status.mjs +14 -5
- package/dist/contract/stream.d.mts +34 -0
- package/dist/contract/stream.mjs +31 -0
- package/dist/contract/subscribe.d.mts +45 -0
- package/dist/contract/subscribe.mjs +50 -0
- package/dist/contract/transient.mjs +28 -0
- package/dist/contract/watch.d.mts +18 -0
- package/dist/contract/watch.mjs +105 -0
- package/dist/contract/webhooks.d.mts +42 -0
- package/dist/contract/webhooks.mjs +53 -0
- package/dist/http/client.d.mts +37 -12
- package/dist/http/client.mjs +51 -12
- package/dist/http/events.d.mts +56 -0
- package/dist/http/events.mjs +102 -0
- package/dist/http/placed.d.mts +36 -0
- package/dist/http/placed.mjs +71 -0
- package/dist/http/schema-errors.mjs +1 -1
- package/dist/http/streamed.d.mts +21 -0
- package/dist/http/streamed.mjs +94 -0
- package/dist/http/watch.mjs +50 -0
- package/dist/mcp/bridge.mjs +283 -0
- package/dist/mcp/client.d.mts +30 -97
- package/dist/mcp/client.mjs +59 -132
- package/dist/mcp/events.mjs +142 -0
- package/dist/mcp/progress.mjs +34 -0
- package/dist/mcp/protocol.mjs +39 -13
- package/dist/mcp/reply.d.mts +79 -0
- package/dist/mcp/reply.mjs +99 -0
- package/dist/mcp/request.d.mts +40 -0
- package/dist/mcp/request.mjs +51 -0
- package/dist/mcp/watch.mjs +115 -0
- package/dist/rpc/watch.mjs +39 -0
- package/dist/stdio/console.mjs +13 -5
- package/dist/testing/memory.d.mts +1 -1
- package/dist/testing/memory.mjs +3 -3
- package/dist/webhook/address.mjs +47 -0
- package/dist/webhook/attempt.mjs +65 -0
- package/dist/webhook/receiver.mjs +67 -0
- package/dist/webhook/signing.mjs +28 -0
- package/dist/webhook/stored.mjs +57 -0
- package/dist/webhook/subscriptions.mjs +342 -0
- package/docs/Action-failures.md +2 -2
- package/docs/Action-streams.md +115 -0
- package/docs/Action.md +58 -124
- package/docs/ActionCli-failures.md +1 -2
- package/docs/ActionCli.md +83 -88
- package/docs/ActionHttp-failures.md +3 -3
- package/docs/ActionHttp.md +90 -70
- package/docs/ActionMcp-failures.md +2 -1
- package/docs/ActionMcp.md +120 -92
- package/docs/ActionRpc-events.md +126 -0
- package/docs/ActionRpc-failures.md +1 -2
- package/docs/ActionRpc.md +108 -79
- package/docs/ActionToolkit-failures.md +1 -2
- package/docs/ActionToolkit.md +33 -90
- package/docs/Authentication-advanced.md +52 -60
- package/docs/Authentication-failures.md +5 -4
- package/docs/Authentication.md +23 -58
- package/docs/Event-failures.md +15 -0
- package/docs/Event.md +281 -0
- package/docs/README.md +51 -82
- package/docs/Testing-failures.md +1 -5
- package/docs/Testing.md +126 -86
- package/docs/Webhook-failures.md +8 -0
- package/docs/Webhook.md +319 -0
- package/docs/setup-failures.md +2 -3
- package/docs/setup.md +32 -52
- package/examples/README.md +12 -37
- package/examples/assistant/README.md +21 -26
- package/examples/assistant/src/agent.ts +66 -24
- package/examples/assistant/src/cli.ts +7 -4
- package/examples/assistant/src/commands.ts +9 -4
- package/examples/assistant/src/identity/Identity.ts +5 -4
- package/examples/assistant/src/identity/authorize.ts +13 -5
- package/examples/assistant/src/identity/handlers.ts +3 -2
- package/examples/assistant/src/identity/permissions.ts +9 -3
- package/examples/assistant/src/platform/tasks-file.ts +15 -11
- package/examples/assistant/src/scripted.ts +7 -4
- package/examples/assistant/src/tasks/Tasks.ts +20 -6
- package/examples/assistant/src/tasks/handlers.ts +9 -5
- package/examples/assistant/src/tasks/store.ts +38 -11
- package/examples/assistant/src/toolkit.ts +11 -7
- package/examples/assistant/test/commands.test.ts +53 -27
- package/examples/assistant/test/identity/identity.test.ts +27 -11
- package/examples/assistant/test/platform/tasks-file.test.ts +39 -23
- package/examples/assistant/test/tasks/tasks.test.ts +62 -34
- package/examples/assistant/test/toolkit.test.ts +104 -75
- package/examples/build-events/README.md +83 -0
- package/examples/build-events/src/Api.ts +27 -0
- package/examples/build-events/src/Rpc.ts +26 -0
- package/examples/build-events/src/builds/Builds.ts +108 -0
- package/examples/build-events/src/builds/events.ts +54 -0
- package/examples/build-events/src/builds/handlers.ts +58 -0
- package/examples/build-events/src/builds/log.ts +30 -0
- package/examples/build-events/src/builds/status.ts +28 -0
- package/examples/build-events/src/builds/store.ts +130 -0
- package/examples/build-events/src/cli.ts +18 -0
- package/examples/build-events/src/commands.ts +32 -0
- package/examples/build-events/src/deploys/Deploys.ts +44 -0
- package/examples/build-events/src/deploys/approvers.ts +55 -0
- package/examples/build-events/src/deploys/events.ts +32 -0
- package/examples/build-events/src/deploys/handlers.ts +38 -0
- package/examples/build-events/src/identity/Identity.ts +29 -0
- package/examples/build-events/src/identity/members.ts +7 -0
- package/examples/build-events/src/identity/verifier.ts +22 -0
- package/examples/build-events/src/notifier/Notices.ts +26 -0
- package/examples/build-events/src/notifier/routes.ts +71 -0
- package/examples/build-events/src/notifier.ts +48 -0
- package/examples/build-events/src/routes.ts +71 -0
- package/examples/build-events/src/server.ts +62 -0
- package/examples/build-events/test/builds/events.test.ts +68 -0
- package/examples/build-events/test/builds/log.test.ts +71 -0
- package/examples/build-events/test/builds/progress.test.ts +57 -0
- package/examples/build-events/test/builds/status.test.ts +42 -0
- package/examples/build-events/test/commands.test.ts +103 -0
- package/examples/build-events/test/deploys/events.test.ts +52 -0
- package/examples/build-events/test/http.test.ts +95 -0
- package/examples/build-events/test/notifier.test.ts +80 -0
- package/examples/build-events/test/routes.test.ts +96 -0
- package/examples/build-events/test/rpc.test.ts +84 -0
- package/examples/build-events/test/support/as.ts +8 -0
- package/examples/build-events/test/support/memory.ts +43 -0
- package/examples/build-events/test/webhooks.test.ts +143 -0
- package/examples/kitchen-sink/README.md +178 -166
- package/examples/kitchen-sink/src/Actions.ts +11 -3
- package/examples/kitchen-sink/src/Api.ts +12 -6
- package/examples/kitchen-sink/src/Rpc.ts +7 -5
- package/examples/kitchen-sink/src/admin/Admin.ts +21 -10
- package/examples/kitchen-sink/src/admin/authenticate.ts +8 -4
- package/examples/kitchen-sink/src/admin/authorize.ts +13 -5
- package/examples/kitchen-sink/src/admin/grants.ts +5 -3
- package/examples/kitchen-sink/src/admin/handlers.ts +9 -5
- package/examples/kitchen-sink/src/agent.ts +14 -6
- package/examples/kitchen-sink/src/assistant/Assistant.ts +21 -15
- package/examples/kitchen-sink/src/assistant/conversations.ts +14 -9
- package/examples/kitchen-sink/src/assistant/demo-model.ts +2 -2
- package/examples/kitchen-sink/src/assistant/handlers.ts +42 -22
- package/examples/kitchen-sink/src/attachments/Attachments.ts +6 -6
- package/examples/kitchen-sink/src/attachments/download.ts +7 -6
- package/examples/kitchen-sink/src/attachments/handlers.ts +9 -4
- package/examples/kitchen-sink/src/attachments/store.ts +25 -18
- package/examples/kitchen-sink/src/browser.ts +10 -4
- package/examples/kitchen-sink/src/cli.ts +28 -12
- package/examples/kitchen-sink/src/config.ts +1 -1
- package/examples/kitchen-sink/src/identity/Identity.ts +24 -10
- package/examples/kitchen-sink/src/identity/authenticate.ts +19 -11
- package/examples/kitchen-sink/src/identity/authorize.ts +14 -4
- package/examples/kitchen-sink/src/identity/directory.ts +16 -7
- package/examples/kitchen-sink/src/identity/handlers.ts +1 -0
- package/examples/kitchen-sink/src/identity/members.ts +7 -2
- package/examples/kitchen-sink/src/identity/quota.ts +23 -20
- package/examples/kitchen-sink/src/issues/Issues.ts +91 -15
- package/examples/kitchen-sink/src/issues/assistant.ts +4 -2
- package/examples/kitchen-sink/src/issues/events.ts +46 -0
- package/examples/kitchen-sink/src/issues/export.ts +35 -0
- package/examples/kitchen-sink/src/issues/guide.ts +4 -3
- package/examples/kitchen-sink/src/issues/handlers.ts +20 -7
- package/examples/kitchen-sink/src/issues/store.ts +156 -67
- package/examples/kitchen-sink/src/issues/write-limit.ts +44 -18
- package/examples/kitchen-sink/src/memory.ts +11 -2
- package/examples/kitchen-sink/src/ops.ts +10 -5
- package/examples/kitchen-sink/src/request-policy.ts +21 -9
- package/examples/kitchen-sink/src/routes.ts +67 -27
- package/examples/kitchen-sink/src/sdk.ts +22 -12
- package/examples/kitchen-sink/src/seed.ts +15 -9
- package/examples/kitchen-sink/src/server.ts +24 -10
- package/examples/kitchen-sink/src/stdio.ts +9 -3
- package/examples/kitchen-sink/src/workspaces/Workspaces.ts +10 -7
- package/examples/kitchen-sink/src/workspaces/handlers.ts +3 -2
- package/examples/kitchen-sink/src/workspaces/registry.ts +16 -10
- package/examples/kitchen-sink/src/workspaces/tenant.ts +12 -5
- package/examples/kitchen-sink/test/admin/admin.test.ts +38 -23
- package/examples/kitchen-sink/test/assistant/assistant.test.ts +471 -299
- package/examples/kitchen-sink/test/attachments/attachments.test.ts +135 -94
- package/examples/kitchen-sink/test/identity/identity.test.ts +110 -82
- package/examples/kitchen-sink/test/identity/session.test.ts +65 -43
- package/examples/kitchen-sink/test/issues/assistant.test.ts +50 -31
- package/examples/kitchen-sink/test/issues/events.test.ts +273 -0
- package/examples/kitchen-sink/test/issues/export.test.ts +120 -0
- package/examples/kitchen-sink/test/issues/issues.test.ts +105 -75
- package/examples/kitchen-sink/test/request-policy.test.ts +108 -47
- package/examples/kitchen-sink/test/routes.test.ts +102 -57
- package/examples/kitchen-sink/test/support/as.ts +9 -0
- package/examples/kitchen-sink/test/support/scripted.ts +6 -5
- package/examples/kitchen-sink/test/support/services.ts +17 -0
- package/examples/live-rpc/README.md +33 -35
- package/examples/live-rpc/src/Rpc.ts +9 -5
- package/examples/live-rpc/src/browser.ts +39 -11
- package/examples/live-rpc/src/chat/Chat.ts +30 -16
- package/examples/live-rpc/src/chat/authorize.ts +2 -1
- package/examples/live-rpc/src/chat/events.ts +74 -0
- package/examples/live-rpc/src/chat/handlers.ts +13 -5
- package/examples/live-rpc/src/chat/room.ts +9 -5
- package/examples/live-rpc/src/chat/store.ts +51 -14
- package/examples/live-rpc/src/client.ts +22 -5
- package/examples/live-rpc/src/identity/Identity.ts +3 -3
- package/examples/live-rpc/src/identity/verifier.ts +8 -4
- package/examples/live-rpc/src/page.ts +58 -12
- package/examples/live-rpc/src/routes.ts +14 -10
- package/examples/live-rpc/src/server.ts +15 -5
- package/examples/live-rpc/test/browser.test.ts +127 -50
- package/examples/live-rpc/test/chat/chat.test.ts +215 -23
- package/examples/live-rpc/test/routes.test.ts +130 -46
- package/examples/live-rpc/test/server.test.ts +94 -33
- package/examples/mcp-tools/README.md +24 -38
- package/examples/mcp-tools/src/platform/fake-farm.ts +63 -24
- package/examples/mcp-tools/src/platform/print-farm.ts +59 -29
- package/examples/mcp-tools/src/printers/Printers.ts +18 -7
- package/examples/mcp-tools/src/printers/farm.ts +15 -5
- package/examples/mcp-tools/src/printers/handlers.ts +12 -6
- package/examples/mcp-tools/src/routes.ts +8 -6
- package/examples/mcp-tools/src/server.ts +12 -5
- package/examples/mcp-tools/src/stdio.ts +3 -2
- package/examples/mcp-tools/test/printers/printers.test.ts +132 -89
- package/examples/mcp-tools/test/routes.test.ts +140 -81
- package/examples/notes-service/README.md +30 -45
- package/examples/notes-service/src/Api.ts +1 -0
- package/examples/notes-service/src/browser.ts +15 -14
- package/examples/notes-service/src/cli.ts +8 -3
- package/examples/notes-service/src/commands.ts +46 -20
- package/examples/notes-service/src/identity/Identity.ts +2 -2
- package/examples/notes-service/src/identity/authorize.ts +6 -2
- package/examples/notes-service/src/identity/handlers.ts +3 -2
- package/examples/notes-service/src/identity/users.ts +2 -1
- package/examples/notes-service/src/identity/verifier.ts +12 -6
- package/examples/notes-service/src/notes/Notes.ts +46 -22
- package/examples/notes-service/src/notes/handlers.ts +18 -9
- package/examples/notes-service/src/notes/store.ts +70 -43
- package/examples/notes-service/src/routes.ts +7 -5
- package/examples/notes-service/src/server.ts +12 -5
- package/examples/notes-service/src/status/Status.ts +1 -1
- package/examples/notes-service/src/status/handlers.ts +5 -3
- package/examples/notes-service/src/stdio.ts +7 -3
- package/examples/notes-service/src/worker.ts +6 -3
- package/examples/notes-service/test/commands.test.ts +164 -91
- package/examples/notes-service/test/notes/as.ts +3 -1
- package/examples/notes-service/test/notes/idempotency.test.ts +97 -67
- package/examples/notes-service/test/notes/in-process.test.ts +26 -15
- package/examples/notes-service/test/notes/notes.test.ts +49 -31
- package/examples/notes-service/test/routes.test.ts +106 -71
- package/examples/notes-service/test/worker.test.ts +21 -13
- package/examples/quickstart/README.md +2 -6
- package/examples/quickstart/src/Api.ts +1 -0
- package/examples/quickstart/src/client.ts +6 -3
- package/examples/quickstart/src/greeting/Greeting.ts +1 -1
- package/examples/quickstart/src/greeting/handlers.ts +5 -2
- package/examples/quickstart/src/routes.ts +3 -2
- package/examples/quickstart/src/server.ts +6 -2
- package/examples/quickstart/test/routes.test.ts +3 -2
- package/package.json +10 -4
package/dist/ActionMcp.mjs
CHANGED
|
@@ -1,46 +1,28 @@
|
|
|
1
1
|
import { Anyone, assertAuthentication } from "./contract/caller.mjs";
|
|
2
|
-
import { assertOnce, heldOnce } from "./contract/names.mjs";
|
|
3
2
|
import { projectedErrors } from "./contract/declared.mjs";
|
|
3
|
+
import { assertOnce, heldOnce } from "./contract/names.mjs";
|
|
4
|
+
import { toolSuccessOf } from "./contract/stream.mjs";
|
|
5
|
+
import { acquire, answeringWhole } from "./contract/implementation.mjs";
|
|
6
|
+
import { inputParseOptions } from "./contract/call.mjs";
|
|
4
7
|
import { hintsOf } from "./contract/hints.mjs";
|
|
5
|
-
import { acquire, provideHandlers, select, toList } from "./contract/implementation.mjs";
|
|
6
8
|
import { promote, providerOf } from "./authentication/provider.mjs";
|
|
7
|
-
import {
|
|
8
|
-
import { defaultPath, fieldKey, httpProtocol, isMisplaced, liftOf, liftedFrom, protocols } from "./mcp/protocol.mjs";
|
|
9
|
+
import { provideServed, selectFrom } from "./contract/serving.mjs";
|
|
9
10
|
import { recordStepUp } from "./authentication/refusal.mjs";
|
|
10
11
|
import { withStderrConsole } from "./stdio/console.mjs";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
12
|
+
import { defaultPath, fieldKey, httpProtocol, isMisplaced, isObjectSchema, liftOf, liftedFrom, protocols, routingFormsOf, toolJsonSchema } from "./mcp/protocol.mjs";
|
|
13
|
+
import { eventSchemasOf, refuseUnservable, serveWebhooks, withEvents } from "./mcp/bridge.mjs";
|
|
14
|
+
import { progressNotifier } from "./mcp/progress.mjs";
|
|
15
|
+
import { McpCallError } from "./mcp/reply.mjs";
|
|
16
|
+
import { request } from "./mcp/request.mjs";
|
|
17
|
+
import { client } from "./mcp/client.mjs";
|
|
18
|
+
import { Cause, Context, Effect, ErrorReporter, Exit, Fiber, Layer, Option, Predicate, Schema, Stdio, Stream } from "effect";
|
|
14
19
|
import { HttpRouter, HttpServerRequest } from "effect/http";
|
|
15
|
-
import {
|
|
20
|
+
import { AiError, McpSchema, McpServer } from "effect/ai";
|
|
16
21
|
// src/mcp/ActionMcp.ts
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const definitionsReferenced = (value) => {
|
|
20
|
-
if (value === null || Predicate.isString(value) || Predicate.isNumber(value) || Predicate.isBoolean(value)) return [];
|
|
21
|
-
if (Array.isArray(value)) return value.flatMap(definitionsReferenced);
|
|
22
|
-
return Object.entries(value).flatMap(([field, nested]) => {
|
|
23
|
-
if (field !== "$ref") return definitionsReferenced(nested);
|
|
24
|
-
const [scope, key] = Predicate.isString(nested) ? JsonPointer.parseUriFragment(nested) ?? [] : [];
|
|
25
|
-
return scope === "$defs" && key !== void 0 ? [key] : [];
|
|
26
|
-
});
|
|
27
|
-
};
|
|
28
|
-
const toolJsonSchema = (schema, strict) => {
|
|
29
|
-
const document = Schema.toJsonSchemaDocument(schema, { onExcessProperty: strict ? "error" : "ignore" });
|
|
30
|
-
const [scope, key] = Predicate.isString(document.schema["$ref"]) ? JsonPointer.parseUriFragment(document.schema["$ref"]) ?? [] : [];
|
|
31
|
-
const inlined = scope === "$defs" && key !== void 0 ? key : void 0;
|
|
32
|
-
const root = inlined === void 0 ? document.schema : document.definitions[inlined];
|
|
33
|
-
if (root === void 0) return void 0;
|
|
34
|
-
const definitions = inlined !== void 0 && ![root, ...Object.values(document.definitions)].flatMap((schema) => isJson(schema) ? definitionsReferenced(schema) : []).includes(inlined) ? Object.fromEntries(Object.entries(document.definitions).filter(([name]) => name !== inlined)) : document.definitions;
|
|
35
|
-
return Object.keys(definitions).length === 0 ? root : {
|
|
36
|
-
...root,
|
|
37
|
-
$defs: definitions
|
|
38
|
-
};
|
|
39
|
-
};
|
|
40
|
-
const assertToolShapes = (lifted) => {
|
|
41
|
-
const inputs = lifted.map(([action]) => action).filter((action) => !isToolArgumentsSchema(toolJsonSchema(Schema.toCodecJson(action.input), true))).map(({ name }) => name);
|
|
22
|
+
const assertToolsServable = (lifted) => {
|
|
23
|
+
const inputs = lifted.map(([action]) => action).flatMap(({ input, name }) => isObjectSchema(toolJsonSchema(Schema.toCodecJson(input), true)) ? [] : [name]);
|
|
42
24
|
if (inputs.length > 0) throw new Error(`MCP tool input must be one object with keys, such as a struct: ${inputs.join(", ")} (wrap a union, an array or a scalar in a field, omit input for no arguments, or leave the action out of actions)`);
|
|
43
|
-
const misplaced = lifted.
|
|
25
|
+
const misplaced = lifted.flatMap(([action, lift]) => isMisplaced(action, lift) ? [action.name] : []);
|
|
44
26
|
if (misplaced.length > 0) throw new Error(`MCP media must be the success or an array of it, or a top-level field of a struct success, one, optional or a required array: ${misplaced.join(", ")} (make the image such a field, or give an optional array as a required one, empty when absent; an image in input or an error is not served over MCP, so leave that action out of actions)`);
|
|
45
27
|
};
|
|
46
28
|
const nativeInternalErrorText = "Tool execution failed due to an internal server error.";
|
|
@@ -72,26 +54,30 @@ const toolOf = (action, outputSchema) => Effect.map(Schema.decodeUnknownEffect(M
|
|
|
72
54
|
},
|
|
73
55
|
_meta: action.mcp._meta === void 0 ? void 0 : { ...action.mcp._meta }
|
|
74
56
|
}));
|
|
57
|
+
const internalError = (cause) => Effect.logError(cause).pipe(Effect.andThen(ErrorReporter.report(cause)), Effect.as(textErrorResult(nativeInternalErrorText)));
|
|
58
|
+
const internalErrorOnDefect = (cause) => Cause.hasDies(cause) ? internalError(cause) : Effect.failCause(cause);
|
|
59
|
+
const encoder = (schema) => {
|
|
60
|
+
const encode = Schema.encodeUnknownEffect(Schema.toCodecJson(schema));
|
|
61
|
+
return (value) => Effect.orDie(encode(value));
|
|
62
|
+
};
|
|
75
63
|
const registerTools = Effect.fnUntraced(function* (apps, authentication) {
|
|
76
64
|
const registry = yield* McpServer.McpServer;
|
|
77
|
-
const bound = yield* acquire(apps);
|
|
65
|
+
const bound = yield* acquire(apps, authentication);
|
|
78
66
|
const built = yield* Effect.context();
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const lift = liftOf(
|
|
67
|
+
for (const [action, handler] of bound) {
|
|
68
|
+
const toolSuccess = toolSuccessOf(action.success);
|
|
69
|
+
const run = answeringWhole(action, handler);
|
|
70
|
+
const lift = liftOf(toolSuccess);
|
|
83
71
|
const media = lift.fields.length === 0 ? void 0 : lift;
|
|
84
|
-
const
|
|
72
|
+
const structuredSuccess = media === void 0 ? toolSuccess : media.rest;
|
|
73
|
+
const structured = structuredSuccess === void 0 ? void 0 : Schema.toCodecJson(structuredSuccess);
|
|
85
74
|
const outputSchema = structured === void 0 ? void 0 : yield* Schema.decodeUnknownEffect(McpSchema.ToolOutputJson)(toolJsonSchema(structured, false)).pipe(Effect.orDie);
|
|
86
75
|
const tool = yield* toolOf(action, outputSchema).pipe(Effect.orDie);
|
|
87
76
|
const decode = Schema.decodeUnknownEffect(Schema.toCodecJson(action.input), inputParseOptions);
|
|
88
|
-
const
|
|
89
|
-
const encode = Schema.encodeUnknownEffect(Schema.toCodecJson(schema));
|
|
90
|
-
return (value) => Effect.orDie(encode(value));
|
|
91
|
-
};
|
|
92
|
-
const encodeSuccess = encoder(action.success);
|
|
77
|
+
const encodeSuccess = encoder(toolSuccess);
|
|
93
78
|
const encodeFailure = encoder(Schema.Union(projectedErrors(action)));
|
|
94
|
-
const
|
|
79
|
+
const reported = (input) => action.progress === void 0 ? run(input) : Effect.flatMap(progressNotifier(registry.notifications, action.progress), (sink) => run(input, sink));
|
|
80
|
+
const call = authentication === void 0 || action.caller === Anyone ? reported : (input) => recordStepUp(promote(authentication, reported(input)));
|
|
95
81
|
const liftedFieldNames = new Set(media?.fields.map(({ name }) => name));
|
|
96
82
|
const resultOf = (encoded, success) => {
|
|
97
83
|
if (media === void 0) return new McpSchema.CallToolResult({
|
|
@@ -114,10 +100,7 @@ const registerTools = Effect.fnUntraced(function* (apps, authentication) {
|
|
|
114
100
|
yield* registry.addTool({
|
|
115
101
|
tool,
|
|
116
102
|
annotations: Context.empty(),
|
|
117
|
-
handle: (payload) => Effect.annotateCurrentSpan({
|
|
118
|
-
tool: action.name,
|
|
119
|
-
parameters: payload ?? {}
|
|
120
|
-
}).pipe(Effect.andThen(() => decode(payload ?? {})), Effect.mapError(({ message }) => new McpSchema.InvalidParams({ message: new AiError.ToolParameterValidationError({
|
|
103
|
+
handle: (payload) => Effect.annotateCurrentSpan({ tool: action.name }).pipe(Effect.andThen(() => decode(payload ?? {})), Effect.mapError(({ message }) => new McpSchema.InvalidParams({ message: new AiError.ToolParameterValidationError({
|
|
121
104
|
toolName: action.name,
|
|
122
105
|
description: message
|
|
123
106
|
}).message })), Effect.flatMap((input) => call(input).pipe(Effect.matchEffect({
|
|
@@ -130,34 +113,63 @@ const registerTools = Effect.fnUntraced(function* (apps, authentication) {
|
|
|
130
113
|
});
|
|
131
114
|
}
|
|
132
115
|
});
|
|
133
|
-
|
|
116
|
+
/**
|
|
117
|
+
* Refuses event types an endpoint cannot serve as MCP events: one named twice, one named as MCP's
|
|
118
|
+
* own, or one whose input or payload is no object.
|
|
119
|
+
*/
|
|
120
|
+
const assertEventsServable = (events) => {
|
|
121
|
+
assertOnce("MCP event", events);
|
|
122
|
+
const reserved = events.find(({ name }) => name.startsWith("mcp."));
|
|
123
|
+
if (reserved !== void 0) throw new Error(`MCP event name starts with "mcp.", which MCP keeps for its own events: ${reserved.name} (rename it, or serve it on another surface)`);
|
|
124
|
+
for (const event of events) eventSchemasOf(event);
|
|
125
|
+
};
|
|
126
|
+
/** The revisions an endpoint speaks, the 2026-07-28 one serving `serving`'s events if any. */
|
|
127
|
+
const servingEvents = ([stateless, ...rest], serving) => serving.events.length === 0 ? [stateless, ...rest] : [withEvents(stateless, serving), ...rest];
|
|
128
|
+
const server = (apps, serving, transport, features = Layer.empty) => {
|
|
129
|
+
const { events, authentication } = serving;
|
|
134
130
|
assertOnce("MCP tool", apps.flatMap((app) => app.actions), heldOnce);
|
|
135
|
-
const lifted = apps.flatMap((app) => app.actions.map((action) => [action, liftOf(action.success)]));
|
|
136
|
-
|
|
131
|
+
const lifted = apps.flatMap((app) => app.actions.map((action) => [action, liftOf(toolSuccessOf(action.success))]));
|
|
132
|
+
assertToolsServable(lifted);
|
|
137
133
|
const names = new Set(lifted.map(([{ name }]) => name));
|
|
138
134
|
const register = Effect.gen(function* () {
|
|
139
135
|
const namesClaimedByFeatures = (yield* McpServer.McpServer).tools.flatMap(({ tool }) => names.has(tool.name) ? [tool.name] : []);
|
|
140
136
|
if (namesClaimedByFeatures.length > 0) return yield* Effect.die(/* @__PURE__ */ new Error(`Duplicate MCP tool: ${namesClaimedByFeatures.join(", ")}, claimed by an action and a native feature (rename the native tool, or leave the action out of actions)`));
|
|
137
|
+
yield* refuseUnservable(serving);
|
|
138
|
+
yield* serveWebhooks(serving);
|
|
141
139
|
yield* registerTools(apps, authentication);
|
|
142
140
|
});
|
|
143
|
-
return Layer.effectDiscard(register).pipe(Layer.provide(features), Layer.provide(transport), Layer.fresh,
|
|
141
|
+
return Layer.effectDiscard(register).pipe(Layer.provide(features), Layer.provide(transport), Layer.fresh, provideServed({
|
|
142
|
+
apps,
|
|
143
|
+
events
|
|
144
|
+
}));
|
|
144
145
|
};
|
|
145
146
|
const anonymousMethods = /* @__PURE__ */ new Set([
|
|
146
147
|
"server/discover",
|
|
147
148
|
"tools/list",
|
|
149
|
+
"events/list",
|
|
148
150
|
"notifications/cancelled"
|
|
149
151
|
]);
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
+
const namedMethods = /* @__PURE__ */ new Map([
|
|
153
|
+
["tools/call", "tool"],
|
|
154
|
+
["events/poll", "event"],
|
|
155
|
+
["events/stream", "event"]
|
|
156
|
+
]);
|
|
157
|
+
const openOf = (contracts) => new Set(contracts.filter(({ caller }) => caller === Anyone).flatMap(({ name }) => routingFormsOf(name)));
|
|
158
|
+
const requiresAuthentication = (actions, events) => {
|
|
159
|
+
const open = {
|
|
160
|
+
tool: openOf(actions),
|
|
161
|
+
event: openOf(events)
|
|
162
|
+
};
|
|
152
163
|
return (headers) => {
|
|
153
|
-
if (open.size === 0) return true;
|
|
164
|
+
if (open.tool.size === 0 && open.event.size === 0) return true;
|
|
154
165
|
if (headers["mcp-protocol-version"] !== httpProtocol.protocolVersion) return true;
|
|
155
166
|
const method = headers["mcp-method"];
|
|
156
167
|
if (method === void 0) return true;
|
|
157
168
|
if (anonymousMethods.has(method)) return false;
|
|
158
|
-
|
|
169
|
+
const named = namedMethods.get(method);
|
|
170
|
+
if (named === void 0) return true;
|
|
159
171
|
const name = headers["mcp-name"];
|
|
160
|
-
return name === void 0 || !open.has(name);
|
|
172
|
+
return name === void 0 || !open[named].has(name);
|
|
161
173
|
};
|
|
162
174
|
};
|
|
163
175
|
const namesItsMethod = (request) => Effect.match(request.json, {
|
|
@@ -165,23 +177,30 @@ const namesItsMethod = (request) => Effect.match(request.json, {
|
|
|
165
177
|
onSuccess: (body) => !Predicate.hasProperty(body, "method") || body.method === request.headers["mcp-method"]
|
|
166
178
|
});
|
|
167
179
|
const readsItsBody = (route) => Effect.flatMap(HttpServerRequest.HttpServerRequest, (request) => request.method === "POST" ? Effect.andThen(request.text, route) : route);
|
|
168
|
-
function layerHttp(apps, { actions, features, path = defaultPath, authentication, requestScoped, allowSubscriptions
|
|
169
|
-
const selected =
|
|
180
|
+
function layerHttp(apps, { actions, features, path = defaultPath, authentication, requestScoped, allowSubscriptions, ...options }) {
|
|
181
|
+
const { apps: selected, events } = selectFrom(apps, actions);
|
|
170
182
|
const served = selected.flatMap((app) => app.actions);
|
|
183
|
+
const listed = events.flatMap((app) => app.events);
|
|
171
184
|
assertAuthentication(served, authentication);
|
|
172
|
-
|
|
185
|
+
assertAuthentication(listed, authentication, "event");
|
|
186
|
+
assertEventsServable(listed);
|
|
187
|
+
const serving = {
|
|
188
|
+
events,
|
|
189
|
+
authentication
|
|
190
|
+
};
|
|
191
|
+
const transport = server(selected, serving, requestScoped === true ? McpServer.layerHttpRequestScoped({
|
|
173
192
|
...options,
|
|
174
193
|
path,
|
|
175
|
-
protocols: [httpProtocol]
|
|
194
|
+
protocols: servingEvents([httpProtocol], serving)
|
|
176
195
|
}) : McpServer.layerHttp({
|
|
177
196
|
...options,
|
|
178
197
|
path,
|
|
179
|
-
protocols,
|
|
198
|
+
protocols: servingEvents(protocols, serving),
|
|
180
199
|
allowSessionTermination: true,
|
|
181
|
-
allowSubscriptions
|
|
182
|
-
}), features
|
|
200
|
+
allowSubscriptions: allowSubscriptions ?? (features !== void 0 || events.length > 0)
|
|
201
|
+
}), features);
|
|
183
202
|
if (authentication === void 0) return transport.pipe(Layer.provide(HttpRouter.middleware(readsItsBody).layer));
|
|
184
|
-
const required = requiresAuthentication(served);
|
|
203
|
+
const required = requiresAuthentication(served, listed);
|
|
185
204
|
const middleware = HttpRouter.middleware(Effect.map(providerOf(authentication), (runtime) => (route) => Effect.flatMap(HttpServerRequest.HttpServerRequest, (request) => request.method !== "POST" || required(request.headers) ? runtime.http(readsItsBody(route), false) : Effect.flatMap(namesItsMethod(request), (named) => runtime.http(readsItsBody(route), named)))));
|
|
186
205
|
return transport.pipe(Layer.provide(middleware.layer));
|
|
187
206
|
}
|
|
@@ -191,9 +210,15 @@ const jsonLinesOnly = Layer.effect(Stdio.Stdio, Effect.map(Stdio.Stdio, (stdio)
|
|
|
191
210
|
stdin: stdio.stdin.pipe(Stream.decodeText, Stream.splitLines, Stream.filter(isJsonLine), Stream.map((line) => `${line}\n`), Stream.encodeText)
|
|
192
211
|
})));
|
|
193
212
|
function runStdio(apps, { actions, features, ...options }) {
|
|
194
|
-
const
|
|
213
|
+
const { apps: selected, events } = selectFrom(apps, actions);
|
|
214
|
+
assertEventsServable(events.flatMap((app) => app.events));
|
|
215
|
+
const serving = {
|
|
216
|
+
events,
|
|
217
|
+
authentication: void 0
|
|
218
|
+
};
|
|
219
|
+
const transport = server(selected, serving, McpServer.layerStdio({
|
|
195
220
|
...options,
|
|
196
|
-
protocols
|
|
221
|
+
protocols: servingEvents(protocols, serving)
|
|
197
222
|
}).pipe(Layer.provide(jsonLinesOnly)), features);
|
|
198
223
|
return Layer.launch(transport).pipe(withStderrConsole, Effect.forkChild, Effect.flatMap(Fiber.await), Effect.flatMap((exit) => Exit.isFailure(exit) && !Cause.hasInterruptsOnly(exit.cause) ? Effect.failCause(exit.cause) : Effect.void));
|
|
199
224
|
}
|