@gjermundgaraba/effect-actions 0.18.1 → 0.18.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/dist/ActionCli.d.mts +1 -1
- package/dist/ActionCli.mjs +1 -1
- package/dist/ActionHttp.d.mts +7 -6
- package/dist/Authentication.d.mts +5 -5
- package/dist/Authentication.mjs +3 -3
- package/docs/Action-failures.md +1 -1
- package/docs/Action-in-process.md +1 -1
- package/docs/Action.md +1 -1
- package/docs/ActionMcp-failures.md +1 -1
- package/docs/ActionMcp.md +3 -3
- package/docs/README.md +4 -3
- package/docs/guarantees.md +4 -4
- package/docs/setup.md +6 -6
- package/examples/kitchen-sink/README.md +13 -13
- package/examples/kitchen-sink/src/stdio.ts +2 -1
- package/examples/notes-service/README.md +1 -1
- package/examples/notes-service/src/stdio.ts +2 -1
- package/package.json +5 -5
package/dist/ActionCli.d.mts
CHANGED
|
@@ -97,7 +97,7 @@ type CallServices<C, A extends Any> = C extends Effect.Effect<infer M, unknown,
|
|
|
97
97
|
* `Command.withSubcommands` on the result would put in the derived ones' place. `remote` calls a
|
|
98
98
|
* server instead. A test runs it in memory, with no process:
|
|
99
99
|
* `Command.runWith(command, { version })(args)`.
|
|
100
|
-
* Guide: `docs/ActionCli.md` in this package; in an application: `examples/
|
|
100
|
+
* Guide: `docs/ActionCli.md` in this package; in an application: `examples/assistant/src/commands.ts`.
|
|
101
101
|
*/
|
|
102
102
|
export declare function make<const Apps extends Served, const O extends Selection<ActionOf<Member<Apps>>> = {}, const Own extends Subcommands = []>(implementations: Apps, options: O & NoInfer<Options$1<ActionOf<Member<Apps>>>> & NoInfer<KnownOptions<O, Options$1, ActionOf<Member<Apps>>>> & {
|
|
103
103
|
readonly subcommands?: Own | undefined;
|
package/dist/ActionCli.mjs
CHANGED
|
@@ -86,7 +86,7 @@ function remoteCommand(binding, action, options) {
|
|
|
86
86
|
* `Command.withSubcommands` on the result would put in the derived ones' place. `remote` calls a
|
|
87
87
|
* server instead. A test runs it in memory, with no process:
|
|
88
88
|
* `Command.runWith(command, { version })(args)`.
|
|
89
|
-
* Guide: `docs/ActionCli.md` in this package; in an application: `examples/
|
|
89
|
+
* Guide: `docs/ActionCli.md` in this package; in an application: `examples/assistant/src/commands.ts`.
|
|
90
90
|
*/
|
|
91
91
|
function make(implementations, options) {
|
|
92
92
|
const apps = toList(implementations);
|
package/dist/ActionHttp.d.mts
CHANGED
|
@@ -112,12 +112,13 @@ export declare function layer<const H extends AnyHttp, const Apps extends Served
|
|
|
112
112
|
* `transformClient: HttpClient.mapRequest(HttpClientRequest.bearerToken(token))`. The native
|
|
113
113
|
* client itself stays available: `HttpApiClient.make(Http.api)`.
|
|
114
114
|
*
|
|
115
|
-
* A call fails with a declared error value (the action's own,
|
|
116
|
-
* `InvalidInput`, `Unauthenticated` or `Forbidden
|
|
117
|
-
* server could not be reached or answered with a status or
|
|
118
|
-
* declare, or a `SchemaError` when the success does not decode. An
|
|
119
|
-
* fails with `InvalidInput`, and nothing is sent. A call also fails
|
|
120
|
-
* `transformClient` returns fails with, as it is, and requires what that
|
|
115
|
+
* A call fails with a declared error value (the action's own, the binding's, a built-in
|
|
116
|
+
* `InvalidInput`, `Unauthenticated` or `Forbidden`, or on a protected action its descriptor's),
|
|
117
|
+
* a native `HttpClientError` when the server could not be reached or answered with a status or
|
|
118
|
+
* body the contract does not declare, or a `SchemaError` when the success does not decode. An
|
|
119
|
+
* input that does not encode fails with `InvalidInput`, and nothing is sent. A call also fails
|
|
120
|
+
* with what the client `transformClient` returns fails with, as it is, and requires what that
|
|
121
|
+
* client requires.
|
|
121
122
|
*/
|
|
122
123
|
export declare function client<const H extends AnyHttp>(binding: H, options?: Options): Effect.Effect<Client<H>, never, HttpClient.HttpClient>;
|
|
123
124
|
export declare function client<const H extends AnyHttp, E, R>(binding: H, options: Options<E, R>): Effect.Effect<Client<H, E, R>, never, HttpClient.HttpClient>;
|
|
@@ -41,8 +41,8 @@ export interface ProtectedResource {
|
|
|
41
41
|
export interface RefusalResponseOptions<D extends Any = Any> {
|
|
42
42
|
/**
|
|
43
43
|
* The descriptor refusing, whose scheme decides the challenge: Bearer's, below, when left
|
|
44
|
-
* out; another scheme's 401 names that scheme,
|
|
45
|
-
* declares is sent as its endpoints declare it.
|
|
44
|
+
* out; another HTTP scheme's or Basic's 401 names that scheme, an API key's none, and nothing
|
|
45
|
+
* steps up under it. An error it declares is sent as its endpoints declare it.
|
|
46
46
|
*/
|
|
47
47
|
readonly authentication?: D | undefined;
|
|
48
48
|
/** The OAuth protected resource refusing: the one given to `layer`. */
|
|
@@ -63,9 +63,9 @@ type DeclaredOf<D> = D extends {
|
|
|
63
63
|
* `authorization` presented a bearer token, or the `insufficient_scope` of a `Forbidden`
|
|
64
64
|
* naming scopes. Given the protected resource `layer` was, every challenge names its metadata
|
|
65
65
|
* URL and a 401's its `scopesRequired`. Under a descriptor of another scheme, it is the JSON
|
|
66
|
-
* and status alone, a 401 naming that scheme
|
|
67
|
-
* its endpoints declare it, its JSON with its status.
|
|
68
|
-
* web `Response`.
|
|
66
|
+
* and status alone, a 401 naming that scheme, or none for an API key. An error
|
|
67
|
+
* `authentication` declares is sent as its endpoints declare it, its JSON with its status.
|
|
68
|
+
* `HttpServerResponse.toWeb` gives it as a web `Response`.
|
|
69
69
|
*/
|
|
70
70
|
export declare const refusalResponse: <D extends Any = never>(error: Refusal | DeclaredOf<D>, options?: RefusalResponseOptions<D>) => HttpServerResponse.HttpServerResponse;
|
|
71
71
|
/** What `make` takes besides the name and the identity. */
|
package/dist/Authentication.mjs
CHANGED
|
@@ -52,9 +52,9 @@ const withNoStoreAndChallenge = (response, challenge) => HttpServerResponse.setH
|
|
|
52
52
|
* `authorization` presented a bearer token, or the `insufficient_scope` of a `Forbidden`
|
|
53
53
|
* naming scopes. Given the protected resource `layer` was, every challenge names its metadata
|
|
54
54
|
* URL and a 401's its `scopesRequired`. Under a descriptor of another scheme, it is the JSON
|
|
55
|
-
* and status alone, a 401 naming that scheme
|
|
56
|
-
* its endpoints declare it, its JSON with its status.
|
|
57
|
-
* web `Response`.
|
|
55
|
+
* and status alone, a 401 naming that scheme, or none for an API key. An error
|
|
56
|
+
* `authentication` declares is sent as its endpoints declare it, its JSON with its status.
|
|
57
|
+
* `HttpServerResponse.toWeb` gives it as a web `Response`.
|
|
58
58
|
*/
|
|
59
59
|
const refusalResponse = (error, options) => {
|
|
60
60
|
const authentication = options?.authentication;
|
package/docs/Action-failures.md
CHANGED
|
@@ -43,5 +43,5 @@ The tasks are in [Action.md](Action.md).
|
|
|
43
43
|
- `Type 'CurrentUser' is not assignable to type 'never'` where a program calling an `Action.client` runs, or `Type 'CurrentUser' is missing the following properties from type 'Scope'` at `it.effect`: a call to a protected action reads the caller from its own context, never from the one the client was acquired in. Provide the caller around the call.
|
|
44
44
|
- `Type 'Scope' is not assignable to type 'never'` where a program runs, or `Service not found: effect/Scope` in plain JavaScript: acquiring an `Action.client` builds, as a layer does. Acquire it in a builder or a layer, or run the program in `Effect.scoped`.
|
|
45
45
|
- A builder runs on every request, or a route owes `HttpRouter.Request<"Requires", X>` for `X`, a service its builder yields: acquiring an `Action.client` runs the builders, and a handler acquires one on every request. Acquire the client in the builder, and call it in the handler.
|
|
46
|
-
- An `Action.client` call dies with a `SchemaError`: the handler's success, or what it fails with, does not pass through its codec.
|
|
46
|
+
- An `Action.client` call dies with a `SchemaError`: the handler's success, or what it fails with, does not pass through its codec. The cause holds the failure beside the `SchemaError`, as `Cause.pretty` shows: before it for a failure the action's errors reject, undeclared or breaking a check, after it for one they accept that does not encode. Return what the success schema accepts, and fail with an error the action declares.
|
|
47
47
|
- `InvalidInput` with `Expected <Class>` from an `Action.client` call given a plain object: an input that is a class encodes only its instances. Pass `new Class({ ... })`.
|
|
@@ -70,7 +70,7 @@ export const builders = Action.layer([status, identity, issues, attachments, adm
|
|
|
70
70
|
|
|
71
71
|
// kitchen-sink/src/server.ts
|
|
72
72
|
Layer.mergeAll(
|
|
73
|
-
HttpRouter.serve(publicRoutes).pipe(Layer.provide(listen(publicPort))),
|
|
73
|
+
HttpRouter.serve(Layer.merge(publicRoutes, socket)).pipe(Layer.provide(listen(publicPort))),
|
|
74
74
|
HttpRouter.serve(adminRoutes).pipe(Layer.provide(listen(adminPort))),
|
|
75
75
|
).pipe(Layer.provide(builders), Layer.provide(memory));
|
|
76
76
|
```
|
package/docs/Action.md
CHANGED
|
@@ -68,7 +68,7 @@ uses every option, sharing some by spreading a constant (`IssueWriteErrors`, `ch
|
|
|
68
68
|
import it ([setup.md](setup.md#bundle-for-a-browser)).
|
|
69
69
|
- **The name** matches `[A-Za-z0-9_-]{1,128}`, is not `then`, and is unique within each binding,
|
|
70
70
|
MCP endpoint, Toolkit, CLI and client holding it.
|
|
71
|
-
- **For no arguments, omit `input`.** A `Schema.Struct({})` accepts any value but `null`, and MCP
|
|
71
|
+
- **For no arguments, omit `input`.** A `Schema.Struct({})` accepts any value but `null` and `undefined`, and MCP
|
|
72
72
|
refuses it as a tool's input ([ActionMcp.md](ActionMcp.md#describe-tools-to-a-model)).
|
|
73
73
|
- **A field callers may omit is `Schema.optional`.** On the wire it also takes `null`, read as
|
|
74
74
|
left out, as a tool's schema lists; a typed client refuses `null`. `Schema.optionalKey` takes
|
|
@@ -24,7 +24,7 @@ Search for a fragment of the message. The tasks are in [ActionMcp.md](ActionMcp.
|
|
|
24
24
|
- A hand-written HTTP request answers 400 with JSON-RPC error `-32602`, `Required request metadata is missing` or `io.modelcontextprotocol/clientCapabilities request metadata is required`: it names 2026-07-28 in `MCP-Protocol-Version` and its `params._meta` lacks `io.modelcontextprotocol/protocolVersion`, for the first message, or `io.modelcontextprotocol/clientCapabilities`, for the second. Build it with `ActionMcp.request`, or copy the `curl` of [mcp-tools](../examples/mcp-tools/README.md#connect-a-client).
|
|
25
25
|
- A hand-written HTTP request answers 400 with JSON-RPC error `-32020`, `MCP-Protocol-Version header is required`, `Mcp-Method header does not match request method` or `Mcp-Name header does not match request parameters`: those headers repeat a 2026-07-28 request's revision, method and `tools/call` name, and one is absent or differs from its body. Build it with `ActionMcp.request`.
|
|
26
26
|
- A hand-written HTTP request answers an empty 406: its `Accept` header does not list both `application/json` and `text/event-stream`, as `*/*` does not. Send both.
|
|
27
|
-
- A client asking for 2025-03-26 or 2024-11-05 is offered 2025-11-25, and disconnects if it cannot speak it: HTTP and stdio serve 2026-07-28, 2025-11-25 and 2025-06-18. Update the client.
|
|
27
|
+
- A client asking for 2025-03-26 or 2024-11-05 is offered 2025-11-25, and disconnects if it cannot speak it: HTTP and stdio serve 2026-07-28, 2025-11-25 and 2025-06-18, a `requestScoped` endpoint 2026-07-28 alone. Update the client.
|
|
28
28
|
- A request written by hand to a stdio server answers JSON-RPC error `-32602`, `Invalid request metadata`: it is neither preceded by `initialize` nor carries the 2026-07-28 metadata. Open with `initialize` and `notifications/initialized`, or give the request's `_meta` its `io.modelcontextprotocol/protocolVersion` and `io.modelcontextprotocol/clientCapabilities`.
|
|
29
29
|
- A client reports a broken transport from a stdio subprocess: something wrote to stdout. The global `console.log` did, or a layer provided around `runStdio` did, through the default logger, or through `Console` or a logger such as `Logger.consoleJson`, which `logToStderr` does not move. Remove the write, apply `ActionCli.logToStderr` last, or log JSON with `Logger.withConsoleError(Logger.formatJson)`.
|
|
30
30
|
- A request carrying an `Origin` gets an empty 403: the origin is not in `allowedOrigins`. Add the exact origin, if the deployment trusts it.
|
package/docs/ActionMcp.md
CHANGED
|
@@ -130,9 +130,9 @@ tool's read-only hint, and the contract's `mcp` option holds its `title`, its ot
|
|
|
130
130
|
- MCP takes a write as destructive unless it states `destructiveHint: false`: one that only adds.
|
|
131
131
|
- A tool's input is one object with keys. Omit `input` for a tool without arguments, and wrap a
|
|
132
132
|
union, an array or a scalar in a field.
|
|
133
|
-
- An argument the schema refuses, an undeclared one included,
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
- An argument the schema refuses, an undeclared one included, never reaches the handler: it
|
|
134
|
+
is an `isError` result, text `Invalid parameters for tool '<name>': …`, not `InvalidInput`,
|
|
135
|
+
and to 2025-06-18 a JSON-RPC error. So constrain in the schema
|
|
136
136
|
what a model may send: an id written into an upstream URL is not made safe by
|
|
137
137
|
`encodeURIComponent`, which leaves `..` alone.
|
|
138
138
|
- A `Schema.makeFilter` check adds nothing to the tool's listed input schema, and
|
package/docs/README.md
CHANGED
|
@@ -15,9 +15,10 @@ first (step 5), before the examples and the pages.
|
|
|
15
15
|
limit, with no mark or with one that understates what is lost. If an output says it was
|
|
16
16
|
truncated, read that page again alone.
|
|
17
17
|
2. **Start from the example closest to what you are building** ([Examples](#examples)). Its
|
|
18
|
-
README has a layout tree and a "Where to look" table naming the file
|
|
19
|
-
layout and idioms: the examples are the reference for how code is
|
|
20
|
-
one way, not the rules, the alternatives or the traps: read steps
|
|
18
|
+
README has a layout tree, and all but quickstart's a "Where to look" table naming the file
|
|
19
|
+
for each thing. Copy its layout and idioms: the examples are the reference for how code is
|
|
20
|
+
written. An example shows one way, not the rules, the alternatives or the traps: read steps
|
|
21
|
+
3 and 4 even when it fits.
|
|
21
22
|
3. **Read [Action.md](Action.md) completely.** Every surface builds on it.
|
|
22
23
|
4. **Read the page of each surface you serve** ([Pages](#pages)), and the example files its task
|
|
23
24
|
sections link.
|
package/docs/guarantees.md
CHANGED
|
@@ -22,9 +22,9 @@ One call, on each surface. An HTTP route is `POST <prefix>/<action>` with a JSON
|
|
|
22
22
|
- **An action without input** takes `{}` and nothing else, on every surface. Over HTTP, send the body `{}` typed as JSON: no body is a **400**, and no `Content-Type` a **415**.
|
|
23
23
|
- **A media field**, `Action.Image`, is `{ "data": "<base64>", "mimeType": "image/png" }` inside the JSON on every surface but MCP, which lifts it out of `structuredContent` into a block of its own: [Return images and other media](ActionMcp.md#return-images-and-other-media).
|
|
24
24
|
- **A failure the action's errors reject**, undeclared or breaking a check, is its call's defect on every surface, beside the `SchemaError` saying why. A class error's checks are not rerun: one built with `disableChecks` is accepted, and fails to encode instead.
|
|
25
|
-
- **Internal failures are never sent.**
|
|
25
|
+
- **Internal failures are never sent.** Over HTTP, MCP and RPC, the cause of a defect goes to the log and to the call's `ErrorReporter`s: those the server runs with, as provided around `HttpRouter.serve` or `Testing.layer`, win over those provided to one surface's layer, which only fill in what a request lacks.
|
|
26
26
|
- **Messages for invalid input.** A message for input that does not decode names paths and what the schema expects, never a field's value. A path names every key it passes through, a record's keys and an undeclared key included, so never key a record by a secret such as an email or a token. A schema's own `message` annotation, or a filter's message, is sent as written, so never put the input in one.
|
|
27
|
-
- **Earlier MCP revisions.** The MCP column is
|
|
27
|
+
- **Earlier MCP revisions.** The MCP column is 2026-07-28. A 2025-11-25 or 2025-06-18 client, over HTTP or stdio, gets `structuredContent` only for a success that is an object, and any other success as its text block alone, a string unquoted; a 2025-06-18 client gets invalid arguments as a JSON-RPC error instead of a result. Over HTTP such a client opens a session, which on an endpoint serving a protected tool only a signed-in caller does: it signs in for every request there, a public tool's call and `tools/list` included. A `requestScoped` endpoint serves only 2026-07-28, and only `POST`. Stdio authenticates nothing: the host provides the identity around `runStdio` ([Serve tools over stdio](ActionMcp.md#serve-tools-over-stdio)).
|
|
28
28
|
- **Request bodies have no size limit** unless the host sets one, on every route of the server, MCP endpoints included ([Serve the routes](ActionHttp.md#serve-the-routes)).
|
|
29
29
|
|
|
30
30
|
[kitchen-sink/test/identity/identity.test.ts](../examples/kitchen-sink/test/identity/identity.test.ts) asserts the 401 and the 403 as sent, and [assistant/test/toolkit.test.ts](../examples/assistant/test/toolkit.test.ts) a refusal as a Toolkit result.
|
|
@@ -38,7 +38,7 @@ What the library does not do, where a reader might expect it to:
|
|
|
38
38
|
- **Filter tool discovery by caller.** `tools/list` names every tool its endpoint serves, protected ones included, to anyone who may list them. Serve public tools on an endpoint of their own if signed-out callers must not see the protected ones.
|
|
39
39
|
- **Limit requests.** A rate limit is the handler's, failing with an error its action declares, or middleware's.
|
|
40
40
|
- **Allow browsers across origins.** CORS for JSON routes is the host's, with `HttpRouter.cors`; an MCP endpoint refuses a browser `Origin` it does not list ([Allow browser clients](ActionMcp.md#allow-browser-clients)).
|
|
41
|
-
- **Stream, upload or retry.** Actions are unary JSON calls
|
|
42
|
-
- **Expire MCP sessions, or serve MCP features other than tools.** A session a client of a 2025 revision opens over HTTP lasts until that client ends it or the process stops
|
|
41
|
+
- **Stream, upload or retry.** Actions are unary JSON calls: one input, one success or one declared error. Every HTTP route is a `POST`, a read-only action's included; RPC needs a protocol speaking JSON.
|
|
42
|
+
- **Expire MCP sessions, or serve MCP features other than tools.** A session a client of a 2025 revision opens over HTTP lasts until that client ends it or the process stops ([Serve tools over HTTP](ActionMcp.md#serve-tools-over-http)). Prompts and resources are Effect's native ones, given as `features` ([Add native prompts and resources](ActionMcp.md#add-native-prompts-and-resources)).
|
|
43
43
|
- **Mix identities.** An action names one identity service, and a remote surface one authentication descriptor.
|
|
44
44
|
- **Harden a deployment.** Real token validation, request limits and error reporting are the application's. The examples mark each shortcut they take `DEMO ONLY`: [examples](../examples/README.md).
|
package/docs/setup.md
CHANGED
|
@@ -13,12 +13,12 @@ When something fails, search [setup-failures.md](setup-failures.md). Reading ord
|
|
|
13
13
|
pnpm add @gjermundgaraba/effect-actions effect@~4.0.4
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
| Need | Add
|
|
17
|
-
| ----------------------------------- |
|
|
18
|
-
| Node HTTP server, stdio host or CLI | `@effect/platform-node@~4.0.4`
|
|
19
|
-
| Tests | `vitest@^5
|
|
20
|
-
| Type checking | `typescript@^7.0.2`, as a dev dependency
|
|
21
|
-
| Running a TypeScript entrypoint | `tsx`, as a dev dependency: `node --import tsx <entrypoint>.ts`
|
|
16
|
+
| Need | Add |
|
|
17
|
+
| ----------------------------------- | --------------------------------------------------------------- |
|
|
18
|
+
| Node HTTP server, stdio host or CLI | `@effect/platform-node@~4.0.4` |
|
|
19
|
+
| Tests | `vitest@^5` and `@effect/vitest@~4.0.4`, as dev dependencies |
|
|
20
|
+
| Type checking | `typescript@^7.0.2`, as a dev dependency |
|
|
21
|
+
| Running a TypeScript entrypoint | `tsx`, as a dev dependency: `node --import tsx <entrypoint>.ts` |
|
|
22
22
|
|
|
23
23
|
The `effect` peer admits the 4.0.x patches from the oldest whose APIs the package uses, and no
|
|
24
24
|
minor release: a minor release may change the unstable Effect modules the surfaces build on.
|
|
@@ -253,21 +253,21 @@ search for in the file.
|
|
|
253
253
|
|
|
254
254
|
### ActionToolkit
|
|
255
255
|
|
|
256
|
-
| Export or option
|
|
257
|
-
|
|
|
258
|
-
| `make`: `actions`, `needsApproval` (a boolean rule)
|
|
259
|
-
| `toolkit` given to `LanguageModel`
|
|
260
|
-
| `layer`, and the caller per turn
|
|
261
|
-
| `toolkit` and the model yielded in a builder
|
|
262
|
-
| `layer` provided to the routes
|
|
263
|
-
| An approval answered in a later request
|
|
264
|
-
| `tools.handle`, a call made by hand
|
|
256
|
+
| Export or option | File |
|
|
257
|
+
| --------------------------------------------------------- | ------------------------------------ |
|
|
258
|
+
| `make`: `actions`, `needsApproval` (a boolean rule) | `src/issues/assistant.ts` |
|
|
259
|
+
| `toolkit` given to `LanguageModel` | `src/issues/assistant.ts` (`triage`) |
|
|
260
|
+
| `layer`, and the caller per turn | `src/agent.ts` |
|
|
261
|
+
| `toolkit` and the model yielded in a builder | `src/assistant/handlers.ts` |
|
|
262
|
+
| `layer` provided to the routes | `src/routes.ts` (`assistantTools`) |
|
|
263
|
+
| An approval answered in a later request (`openApprovals`) | `src/assistant/handlers.ts` |
|
|
264
|
+
| `tools.handle`, a call made by hand | `test/issues/assistant.test.ts` |
|
|
265
265
|
|
|
266
266
|
### ActionCli
|
|
267
267
|
|
|
268
268
|
| Export or option | File |
|
|
269
269
|
| -------------------------------------------------------------- | ------------------------------------------ |
|
|
270
|
-
| `remote`: `name`, `commands`
|
|
270
|
+
| `remote`: `name`, `commands`, `client` | `src/cli.ts` |
|
|
271
271
|
| `commands`: `stdin`, `positional`, `aliases`, `render`, `name` | `src/cli.ts` |
|
|
272
272
|
| A client from `Config`, its credentials optional | `src/cli.ts` |
|
|
273
273
|
| `make`, with a trusted identity the host supplies | `src/ops.ts` |
|
|
@@ -299,9 +299,9 @@ Left out because this application has no honest place for them:
|
|
|
299
299
|
- `Action.implement` with a plain record of handlers: every implementation of several actions
|
|
300
300
|
here has a builder. `implementation.actions`. `mcp._meta`.
|
|
301
301
|
- `ActionCli.command` and `remoteCommand`, one action as one command; `make`'s and `remote`'s
|
|
302
|
-
`actions
|
|
303
|
-
|
|
304
|
-
|
|
302
|
+
`actions`. Both CLIs here are aggregates of every action, and the remote one reads its client
|
|
303
|
+
from `Config`. `subcommands` and `toUserError`, a command written by hand:
|
|
304
|
+
[notes-service](../notes-service/) has two.
|
|
305
305
|
- `ActionRpc.layer`'s `actions`, `Rpc.group`, and `ActionRpc.client`'s options.
|
|
306
306
|
- A binding's other fields, `Http.actions`, `Http.error` and `Http.authentication`.
|
|
307
307
|
- `ActionMcp`'s `path`, `description`, `websiteUrl`, `icons` and `extensions`; `fetchClient`'s
|
|
@@ -14,7 +14,8 @@ import { status } from "./workspaces/handlers.js";
|
|
|
14
14
|
import { WorkspaceRegistry } from "./workspaces/registry.js";
|
|
15
15
|
|
|
16
16
|
// Entrypoint: an MCP server a local agent starts as a subprocess, such as
|
|
17
|
-
// `claude mcp add tracker --
|
|
17
|
+
// `claude mcp add tracker -- "$PWD/node_modules/.bin/tsx" "$PWD/examples/kitchen-sink/src/stdio.ts"`
|
|
18
|
+
// from the repository root: mcp-tools' README says why the paths are full.
|
|
18
19
|
// It lists the implementations it serves itself, and imports nothing of the HTTP router. They
|
|
19
20
|
// are those of the `/mcp` endpoint, with its tools and features and the same `authorize`.
|
|
20
21
|
// stdio is a local surface: it takes no `authentication`, since no token arrives.
|
|
@@ -103,7 +103,7 @@ src/
|
|
|
103
103
|
├── server.ts entrypoint: the HTTP server
|
|
104
104
|
├── worker.ts entrypoint: a fetch handler for a serverless host
|
|
105
105
|
├── stdio.ts entrypoint: MCP for a local agent
|
|
106
|
-
├── commands.ts the commands calling the server,
|
|
106
|
+
├── commands.ts the commands calling the server, two written by hand, and their connection
|
|
107
107
|
├── cli.ts entrypoint: the commands
|
|
108
108
|
└── browser.ts client module: promises for a web page
|
|
109
109
|
test/
|
|
@@ -10,7 +10,8 @@ import { NoteStore } from "./notes/store.js";
|
|
|
10
10
|
import { status } from "./status/handlers.js";
|
|
11
11
|
|
|
12
12
|
// Entrypoint: an MCP server a local agent starts as a subprocess, such as
|
|
13
|
-
// `claude mcp add notes --
|
|
13
|
+
// `claude mcp add notes -- "$PWD/node_modules/.bin/tsx" "$PWD/examples/notes-service/src/stdio.ts"`
|
|
14
|
+
// from the repository root: mcp-tools' README says why the paths are full.
|
|
14
15
|
// The same implementations as the HTTP server, and the same `authorize`. No token arrives
|
|
15
16
|
// over stdio, so this host names the caller itself. It is a process of its own with services
|
|
16
17
|
// of its own: this in-memory store holds its notes, not the running server's. To share them,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjermundgaraba/effect-actions",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.2",
|
|
4
4
|
"description": "Define Effect action contracts once and project them onto HTTP, MCP, Effect RPC, native Toolkits, and CLIs.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-agents",
|
|
@@ -56,9 +56,9 @@
|
|
|
56
56
|
"effect": "4.0.5",
|
|
57
57
|
"tsx": "4.23.15",
|
|
58
58
|
"typescript": "7.0.2",
|
|
59
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@1.
|
|
60
|
-
"vite-plus": "1.
|
|
61
|
-
"vitest": "5.0.
|
|
59
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.3.0",
|
|
60
|
+
"vite-plus": "1.3.0",
|
|
61
|
+
"vitest": "5.0.5"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
64
|
"effect": "~4.0.4"
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"devEngines": {
|
|
67
67
|
"packageManager": {
|
|
68
68
|
"name": "pnpm",
|
|
69
|
-
"version": "12.
|
|
69
|
+
"version": "12.14.0",
|
|
70
70
|
"onFail": "download"
|
|
71
71
|
},
|
|
72
72
|
"runtime": {
|