@emseepea/create-progress-streaming-server 0.0.12 → 0.0.14

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 CHANGED
@@ -7,7 +7,7 @@ This directory is both the maintained example and its public npm initializer.
7
7
  Use this template for a tool that reports bounded progress while its HTTP call
8
8
  remains open. Choose the [tool server](../tool-server/README.md) when the result
9
9
  can return promptly. This template does not add replay, reconnectable sessions,
10
- or subscriptions. [Compare all eight templates](https://emseepea.github.io/emseepea/examples/).
10
+ or subscriptions. [Compare all templates](https://emseepea.github.io/emseepea/examples/).
11
11
 
12
12
  ## Create a Project
13
13
 
@@ -17,6 +17,30 @@ npm init @emseepea/progress-streaming-server -- my-server
17
17
 
18
18
  <!-- generated-project-readme -->
19
19
 
20
+ ## Choose Open or Protected Access
21
+
22
+ Start open when the catalogue and operations are public.
23
+
24
+ To protect this template, pass both options to the app factory:
25
+
26
+ - `access: { access: "protected", requiredScopes: ["peas:read"] }`
27
+ - an `authentication` adapter
28
+
29
+ Keep `authentication.discovery` as `"public"` unless capability names or
30
+ schemas are sensitive. Use `"protected"` only when each principal should see a
31
+ permission-filtered catalogue. OAuth metadata remains public in both modes.
32
+
33
+ ## Add Observability
34
+
35
+ The same factory accepts `observability`.
36
+
37
+ - Use `structuredLogging` for safe structured events.
38
+ - Use `openTelemetry` for traces and metrics.
39
+
40
+ Adapters receive only redacted framework events. They never receive request
41
+ bodies, arguments, results, tokens, provider claims, or raw errors. See the
42
+ [server API](https://github.com/emseepea/emseepea/tree/main/packages/framework#authentication-and-observability) for the complete configuration.
43
+
20
44
  ## Streaming Progress Example
21
45
 
22
46
  Choose this example when a tool takes long enough that people benefit from
@@ -1,4 +1,28 @@
1
- # Streaming Progress Example
1
+ # Choose Open or Protected Access
2
+
3
+ Start open when the catalogue and operations are public.
4
+
5
+ To protect this template, pass both options to the app factory:
6
+
7
+ - `access: { access: "protected", requiredScopes: ["peas:read"] }`
8
+ - an `authentication` adapter
9
+
10
+ Keep `authentication.discovery` as `"public"` unless capability names or
11
+ schemas are sensitive. Use `"protected"` only when each principal should see a
12
+ permission-filtered catalogue. OAuth metadata remains public in both modes.
13
+
14
+ ## Add Observability
15
+
16
+ The same factory accepts `observability`.
17
+
18
+ - Use `structuredLogging` for safe structured events.
19
+ - Use `openTelemetry` for traces and metrics.
20
+
21
+ Adapters receive only redacted framework events. They never receive request
22
+ bodies, arguments, results, tokens, provider claims, or raw errors. See the
23
+ [server API](https://github.com/emseepea/emseepea/tree/main/packages/framework#authentication-and-observability) for the complete configuration.
24
+
25
+ ## Streaming Progress Example
2
26
 
3
27
  Choose this example when a tool takes long enough that people benefit from
4
28
  seeing progress before the final answer.
@@ -14,7 +14,7 @@
14
14
  "lint": "oxlint src test eval"
15
15
  },
16
16
  "devDependencies": {
17
- "@emseepea/testing": "0.5.2",
17
+ "@emseepea/testing": "0.6.1",
18
18
  "@types/node": "24.13.3",
19
19
  "typescript": "6.0.3",
20
20
  "oxlint": "1.80.0"
@@ -24,7 +24,7 @@
24
24
  },
25
25
  "private": true,
26
26
  "dependencies": {
27
- "@emseepea/server": "0.3.3",
27
+ "@emseepea/server": "0.4.0",
28
28
  "zod": "4.4.3"
29
29
  }
30
30
  }
@@ -0,0 +1,21 @@
1
+ import {
2
+ createEmseepea,
3
+ discoverCapabilities,
4
+ type AccessPolicy,
5
+ type EmseepeaExtensions,
6
+ } from "@emseepea/server";
7
+
8
+ export interface ProgressStreamingServerOptions extends EmseepeaExtensions {
9
+ readonly access?: AccessPolicy;
10
+ }
11
+
12
+ export async function createProgressStreamingServer(options: ProgressStreamingServerOptions = {}) {
13
+ const { access = { access: "public" }, ...extensions } = options;
14
+ return createEmseepea({
15
+ name: "emseepea-progress-streaming-server",
16
+ version: "0.0.0",
17
+ instructions: "Use run-germination-trial for the sample pea germination trial.",
18
+ ...await discoverCapabilities(new URL("./capabilities/", import.meta.url), access),
19
+ ...extensions,
20
+ });
21
+ }
@@ -1,10 +1,15 @@
1
1
  import { setTimeout as delay } from "node:timers/promises";
2
- import { defineStreamingTool, type CapabilityModuleFactory } from "@emseepea/server";
2
+ import {
3
+ defineStreamingTool,
4
+ type AccessPolicy,
5
+ type CapabilityModuleFactory,
6
+ type StreamingToolContext,
7
+ } from "@emseepea/server";
3
8
  import { z } from "zod";
4
9
 
5
- export default (() => defineStreamingTool({
10
+ export default ((access) => defineStreamingTool({
6
11
  name: "run-germination-trial",
7
- access: "public",
12
+ ...access,
8
13
  description: "Run a sample pea germination trial with bounded progress.",
9
14
  inputSchema: z.object({
10
15
  tray: z.literal("sample-tray").describe("Sample germination tray to test."),
@@ -17,7 +22,7 @@ export default (() => defineStreamingTool({
17
22
  stages: z.tuple([z.literal("soak"), z.literal("sow"), z.literal("sprout")])
18
23
  .describe("Trial stages completed in order."),
19
24
  }),
20
- async handler({ tray }, { reportProgress, signal }) {
25
+ async handler({ tray }, { reportProgress, signal }: StreamingToolContext) {
21
26
  const stages: ["soak", "sow", "sprout"] = ["soak", "sow", "sprout"];
22
27
  for (const [index, stage] of stages.entries()) {
23
28
  await reportProgress({ progress: index + 1, total: stages.length, message: stage });
@@ -26,4 +31,4 @@ export default (() => defineStreamingTool({
26
31
  const data = { tray, status: "complete" as const, germinatedSeeds: 8 as const, totalSeeds: 10 as const, stages };
27
32
  return { data };
28
33
  },
29
- })) satisfies CapabilityModuleFactory;
34
+ })) satisfies CapabilityModuleFactory<AccessPolicy>;
@@ -1,11 +1,9 @@
1
- import { createEmseepea, discoverCapabilities, serveEmseepea } from "@emseepea/server";
1
+ import { serveEmseepea } from "@emseepea/server";
2
+ import { createProgressStreamingServer } from "./app.js";
2
3
 
3
- const running = await serveEmseepea(createEmseepea({
4
- name: "emseepea-progress-streaming-server",
5
- version: "0.0.0",
6
- instructions: "Use run-germination-trial for the sample pea germination trial.",
7
- ...await discoverCapabilities(new URL("./capabilities/", import.meta.url)),
8
- }), { port: Number.parseInt(process.env.PORT ?? "3000", 10) });
4
+ const running = await serveEmseepea(await createProgressStreamingServer(), {
5
+ port: Number.parseInt(process.env.PORT ?? "3000", 10),
6
+ });
9
7
 
10
8
  console.log(`Em See Pea progress-streaming-server example listening at ${running.url}`);
11
9
 
@@ -1,7 +1,12 @@
1
1
  import assert from "node:assert/strict";
2
2
  import test from "node:test";
3
3
 
4
- import { startMcpServer } from "@emseepea/testing";
4
+ import {
5
+ insecureTestAuthentication,
6
+ startEmseepea,
7
+ startMcpServer,
8
+ } from "@emseepea/testing";
9
+ import { createProgressStreamingServer } from "../dist/app.js";
5
10
 
6
11
  test("reports bounded progress before returning the final germination result", async (t) => {
7
12
  const running = await startMcpServer(t, new URL("../dist/server.js", import.meta.url));
@@ -29,3 +34,20 @@ test("reports bounded progress before returning the final germination result", a
29
34
  });
30
35
  assert.equal(result.content[0].text, JSON.stringify(result.structuredContent));
31
36
  });
37
+
38
+ test("the same template composes protected access and observability", async (t) => {
39
+ const events = [];
40
+ const permissions = ["trials:run"];
41
+ const running = await startEmseepea(t, await createProgressStreamingServer({
42
+ access: { access: "protected", requiredScopes: permissions },
43
+ authentication: insecureTestAuthentication(permissions),
44
+ observability: [{ id: "test-log", emit: (event) => events.push(event) }],
45
+ }));
46
+ const client = await running.connect("test-token");
47
+ const result = await client.callTool({
48
+ name: "run-germination-trial",
49
+ arguments: { tray: "sample-tray" },
50
+ });
51
+ assert.equal(result.structuredContent.status, "complete");
52
+ assert.ok(events.some(({ capability }) => capability === "run-germination-trial"));
53
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emseepea/create-progress-streaming-server",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "description": "Create an Em See Pea server that streams tool progress.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -18,9 +18,9 @@
18
18
  "prepack": "npm run build:initializer"
19
19
  },
20
20
  "devDependencies": {
21
- "@emseepea/server": "0.3.3",
21
+ "@emseepea/server": "0.4.0",
22
22
  "zod": "4.4.3",
23
- "@emseepea/testing": "0.5.2",
23
+ "@emseepea/testing": "0.6.1",
24
24
  "@types/node": "24.13.3",
25
25
  "typescript": "6.0.3",
26
26
  "oxlint": "1.80.0"