@emseepea/create-tool-server 0.0.2 → 0.0.4

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
@@ -1,22 +1,70 @@
1
1
  # `@emseepea/create-tool-server`
2
2
 
3
- Create a private, standalone Em See Pea project with one public, read-only
4
- tool. The package builds its starter from the maintained
5
- [first public tool example](https://github.com/emseepea/emseepea/tree/main/examples/basic-no-ui).
3
+ This directory is both the maintained example and its public npm initializer.
6
4
 
7
- ## Create the Project
5
+ ## Use This Template
8
6
 
9
- This initializer is queued for the next pre-alpha release and is not yet
10
- available from npm.
7
+ Use this template for the smallest server with one public, read-only tool and
8
+ no external service, sign-in, web page, progress stream, or shared storage.
9
+ Choose the [API-backed server](../api-backed-server/README.md) when the tool
10
+ must call a public web service. [Compare all eight templates](https://emseepea.github.io/emseepea/examples/).
11
+
12
+ ## Create a Project
11
13
 
12
14
  ```sh
13
- npm init @emseepea/tool-server@next -- my-server
15
+ npm init @emseepea/tool-server -- my-server
14
16
  ```
15
17
 
18
+ <!-- generated-project-readme -->
19
+
20
+ ## Your First Public Tool
21
+
22
+ Choose this example when you want the smallest working server with one public,
23
+ read-only tool and no web page.
24
+
25
+ The `get-pea-variety` tool returns useful details about one sample pea variety. Em
26
+ See Pea checks the input and result before returning them through the public
27
+ `@emseepea/server` API.
28
+
29
+ ## What This Example Includes
30
+
31
+ - Model Context Protocol (MCP) `2026-07-28` over `POST /mcp`
32
+ - one public, read-only tool with sample data
33
+ - checks for tool input and output
34
+ - local use on your computer only
35
+
36
+ It does not include sign-in, saved sessions, live progress, changes to data, or
37
+ production network setup.
38
+
39
+ ## Run
40
+
41
+ From this directory:
42
+
16
43
  ```sh
17
- cd my-server
18
44
  npm install
19
- npm test
20
- npm run lint
45
+ npm run build
21
46
  npm start
22
47
  ```
48
+
49
+ The endpoint is `http://127.0.0.1:3000/mcp` and the health check is
50
+ `http://127.0.0.1:3000/healthz`.
51
+
52
+ ## Check This Example
53
+
54
+ [Ordinary tests](test/) live in `test/`.
55
+ The [AI tool-choice and understanding test](eval/meaning.test.mjs) lives separately in `eval/`.
56
+ The commands below run each suite independently.
57
+
58
+ Run its build and MCP checks:
59
+
60
+ ```sh
61
+ npm test
62
+ ```
63
+
64
+ Check that Claude chooses the variety tool and understands its result:
65
+
66
+ ```sh
67
+ npm run test:llm
68
+ ```
69
+
70
+ If Claude is not already signed in, run `claude auth login` first.
@@ -3,8 +3,8 @@
3
3
  Choose this example when you want the smallest working server with one public,
4
4
  read-only tool and no web page.
5
5
 
6
- The `get-bean-details` tool returns useful details about one sample coffee. Em
7
- See Pea checks the question and result before returning them through the public
6
+ The `get-pea-variety` tool returns useful details about one sample pea variety. Em
7
+ See Pea checks the input and result before returning them through the public
8
8
  `@emseepea/server` API.
9
9
 
10
10
  ## What This Example Includes
@@ -42,7 +42,7 @@ Run its build and MCP checks:
42
42
  npm test
43
43
  ```
44
44
 
45
- Check that Claude chooses the details tool and understands its result:
45
+ Check that Claude chooses the variety tool and understands its result:
46
46
 
47
47
  ```sh
48
48
  npm run test:llm
@@ -0,0 +1,20 @@
1
+ import { toolSelectionTest } from "@emseepea/testing/semantic";
2
+
3
+ toolSelectionTest("Pea variety details keep each concept distinct", {
4
+ server: new URL("../dist/server.js", import.meta.url),
5
+ question:
6
+ "For Highland Snap, give me its pea type, growth habit, days to maturity, and " +
7
+ "traits. Keep those concepts distinct.",
8
+ criticalFacts: [
9
+ "snap",
10
+ "climbing",
11
+ "70",
12
+ "edible pods",
13
+ "needs support"
14
+ ],
15
+ criteria:
16
+ "The answer says Highland Snap is a snap pea with a climbing growth habit, " +
17
+ "matures in 70 days, has edible pods, and needs support. It does not confuse " +
18
+ "pea type, growth habit, maturity time, or traits.",
19
+ expectedTools: ["get-pea-variety"],
20
+ });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "emseepea-starter",
3
3
  "version": "0.0.0",
4
- "private": true,
4
+ "description": "Create an Em See Pea server with one public tool.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "scripts": {
@@ -13,17 +13,18 @@
13
13
  "test:llm:built": "emseepea-test eval",
14
14
  "lint": "oxlint src test eval"
15
15
  },
16
- "dependencies": {
17
- "@emseepea/server": "0.1.0",
18
- "zod": "4.4.3"
19
- },
20
16
  "devDependencies": {
21
- "@emseepea/testing": "0.2.1",
17
+ "@emseepea/testing": "0.2.2",
22
18
  "@types/node": "24.13.3",
23
19
  "typescript": "6.0.3",
24
20
  "oxlint": "1.80.0"
25
21
  },
26
22
  "engines": {
27
23
  "node": ">=22"
24
+ },
25
+ "private": true,
26
+ "dependencies": {
27
+ "@emseepea/server": "0.2.2",
28
+ "zod": "4.4.3"
28
29
  }
29
30
  }
@@ -0,0 +1,44 @@
1
+ import { defineTool, type CapabilityModuleFactory } from "@emseepea/server";
2
+ import { z } from "zod";
3
+
4
+ const varietyNames = ["Harbour Gem", "Highland Snap"] as const;
5
+ const peaVarietySchema = z.object({
6
+ name: z.enum(varietyNames),
7
+ peaType: z.enum(["shelling", "snap"]),
8
+ growthHabit: z.enum(["bush", "climbing"]),
9
+ daysToMaturity: z.number().int().positive(),
10
+ traits: z.array(z.string()),
11
+ });
12
+ const varieties: Record<(typeof varietyNames)[number], z.input<typeof peaVarietySchema>> = {
13
+ "Harbour Gem": {
14
+ name: "Harbour Gem",
15
+ peaType: "shelling",
16
+ growthHabit: "bush",
17
+ daysToMaturity: 62,
18
+ traits: ["compact", "sweet peas"],
19
+ },
20
+ "Highland Snap": {
21
+ name: "Highland Snap",
22
+ peaType: "snap",
23
+ growthHabit: "climbing",
24
+ daysToMaturity: 70,
25
+ traits: ["edible pods", "needs support"],
26
+ },
27
+ };
28
+
29
+ export default (() => defineTool({
30
+ name: "get-pea-variety",
31
+ access: "public",
32
+ title: "Pea Variety Details",
33
+ description: "Get the type, growth habit, maturity time, and traits of a sample pea variety.",
34
+ inputSchema: z.object({ name: z.enum(varietyNames) }),
35
+ outputSchema: peaVarietySchema,
36
+ handler: ({ name }) => {
37
+ const data = varieties[name];
38
+ return {
39
+ text: `${data.name} is a ${data.peaType} pea with a ${data.growthHabit} habit. ` +
40
+ `It matures in ${data.daysToMaturity} days and is known for ${data.traits.join(" and ")}.`,
41
+ data,
42
+ };
43
+ },
44
+ })) satisfies CapabilityModuleFactory;
@@ -1,9 +1,9 @@
1
1
  import { createEmseepea, discoverCapabilities, serveEmseepea } from "@emseepea/server";
2
2
 
3
3
  const handler = createEmseepea({
4
- name: "emseepea-basic-no-ui",
4
+ name: "emseepea-tool-server",
5
5
  version: "0.0.0",
6
- instructions: "Use get-bean-details for information about a sample coffee bean.",
6
+ instructions: "Use get-pea-variety for information about a sample pea variety.",
7
7
  ...await discoverCapabilities(new URL("./capabilities/", import.meta.url)),
8
8
  });
9
9
 
@@ -3,24 +3,23 @@ import test from "node:test";
3
3
 
4
4
  import { startMcpServer } from "@emseepea/testing";
5
5
 
6
- test("advertises and returns understandable bean details", async (t) => {
6
+ test("advertises and returns understandable pea variety details", async (t) => {
7
7
  const running = await startMcpServer(t, new URL("../dist/server.js", import.meta.url));
8
8
  const client = await running.connect();
9
9
 
10
10
  const listed = await client.listTools();
11
- assert.deepEqual(listed.tools.map(({ name }) => name), ["get-bean-details"]);
11
+ assert.deepEqual(listed.tools.map(({ name }) => name), ["get-pea-variety"]);
12
12
 
13
13
  const result = await client.callTool({
14
- name: "get-bean-details",
15
- arguments: { name: "Highland Bloom" },
14
+ name: "get-pea-variety",
15
+ arguments: { name: "Highland Snap" },
16
16
  });
17
17
  assert.equal(result.isError, false);
18
18
  assert.deepEqual(result.structuredContent, {
19
- name: "Highland Bloom",
20
- origin: "Sample Highlands",
21
- variety: "Bourbon",
22
- process: "natural",
23
- roast: "medium",
24
- tastingNotes: ["berry", "cocoa"],
19
+ name: "Highland Snap",
20
+ peaType: "snap",
21
+ growthHabit: "climbing",
22
+ daysToMaturity: 70,
23
+ traits: ["edible pods", "needs support"],
25
24
  });
26
25
  });
package/package.json CHANGED
@@ -1,22 +1,37 @@
1
1
  {
2
2
  "name": "@emseepea/create-tool-server",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Create an Em See Pea server with one public tool.",
5
5
  "license": "MIT",
6
- "repository": {
7
- "type": "git",
8
- "url": "git+https://github.com/emseepea/emseepea.git",
9
- "directory": "packages/create-tool-server"
10
- },
11
- "homepage": "https://emseepea.github.io/emseepea/examples/",
12
- "bugs": "https://github.com/emseepea/emseepea/issues",
13
- "publishConfig": { "access": "public", "provenance": true, "tag": "next" },
14
6
  "type": "module",
15
- "bin": { "create-tool-server": "./dist/create.mjs" },
16
- "files": ["dist"],
7
+ "starterDependencies": ["@emseepea/server", "zod"],
17
8
  "scripts": {
18
- "build": "node ../../scripts/build-initializer.mjs",
19
- "prepack": "npm run build"
9
+ "build": "npm run build:example && npm run build:initializer",
10
+ "build:example": "tsc -p tsconfig.json",
11
+ "build:initializer": "node ../../scripts/build-initializer.mjs",
12
+ "start": "node dist/server.js",
13
+ "test": "npm run build && npm run test:built",
14
+ "test:built": "node --test test/*.test.mjs",
15
+ "test:llm": "npm run build && npm run test:llm:built",
16
+ "test:llm:built": "emseepea-test eval",
17
+ "lint": "oxlint src test eval",
18
+ "prepack": "npm run build:initializer"
19
+ },
20
+ "devDependencies": {
21
+ "@emseepea/server": "0.2.2",
22
+ "zod": "4.4.3",
23
+ "@emseepea/testing": "0.2.2",
24
+ "@types/node": "24.13.3",
25
+ "typescript": "6.0.3",
26
+ "oxlint": "1.80.0"
20
27
  },
21
- "engines": { "node": ">=22" }
28
+ "engines": {
29
+ "node": ">=22"
30
+ },
31
+ "repository": { "type": "git", "url": "git+https://github.com/emseepea/emseepea.git", "directory": "examples/tool-server" },
32
+ "homepage": "https://emseepea.github.io/emseepea/examples/",
33
+ "bugs": "https://github.com/emseepea/emseepea/issues",
34
+ "publishConfig": { "access": "public", "provenance": true },
35
+ "bin": { "create-tool-server": "./initializer-dist/create.mjs" },
36
+ "files": ["initializer-dist"]
22
37
  }
@@ -1,21 +0,0 @@
1
- import { toolSelectionTest } from "@emseepea/testing/semantic";
2
-
3
- toolSelectionTest("Basic bean details keep each concept distinct", {
4
- server: new URL("../dist/server.js", import.meta.url),
5
- question:
6
- "For Highland Bloom, give me its origin, variety, processing method, roast, and " +
7
- "tasting notes. Keep those concepts distinct.",
8
- criticalFacts: [
9
- "Sample Highlands",
10
- "Bourbon",
11
- "natural",
12
- "medium",
13
- "berry",
14
- "cocoa"
15
- ],
16
- criteria:
17
- "The answer says Highland Bloom is a medium-roast, naturally processed Bourbon " +
18
- "from Sample Highlands with berry and cocoa tasting notes. It does not confuse " +
19
- "origin, variety, process, roast, or tasting notes.",
20
- expectedTools: ["get-bean-details"],
21
- });
@@ -1,47 +0,0 @@
1
- import { defineTool, type CapabilityModuleFactory } from "@emseepea/server";
2
- import { z } from "zod";
3
-
4
- const beanNames = ["Harbour Dawn", "Highland Bloom"] as const;
5
- const beanDetailsSchema = z.object({
6
- name: z.enum(beanNames),
7
- origin: z.string(),
8
- variety: z.string(),
9
- process: z.string(),
10
- roast: z.enum(["light", "medium", "dark"]),
11
- tastingNotes: z.array(z.string()),
12
- });
13
- const beans: Record<(typeof beanNames)[number], z.input<typeof beanDetailsSchema>> = {
14
- "Harbour Dawn": {
15
- name: "Harbour Dawn",
16
- origin: "Sample Coast",
17
- variety: "Caturra",
18
- process: "washed",
19
- roast: "light",
20
- tastingNotes: ["citrus", "honey"],
21
- },
22
- "Highland Bloom": {
23
- name: "Highland Bloom",
24
- origin: "Sample Highlands",
25
- variety: "Bourbon",
26
- process: "natural",
27
- roast: "medium",
28
- tastingNotes: ["berry", "cocoa"],
29
- },
30
- };
31
-
32
- export default (() => defineTool({
33
- name: "get-bean-details",
34
- access: "public",
35
- title: "Coffee Bean Details",
36
- description: "Get origin, processing, roast, and tasting details for a sample coffee bean.",
37
- inputSchema: z.object({ name: z.enum(beanNames) }),
38
- outputSchema: beanDetailsSchema,
39
- handler: ({ name }) => {
40
- const data = beans[name];
41
- return {
42
- text: `${data.name} is a ${data.roast} ${data.process} ${data.variety} from ` +
43
- `${data.origin}, with notes of ${data.tastingNotes.join(" and ")}.`,
44
- data,
45
- };
46
- },
47
- })) satisfies CapabilityModuleFactory;
File without changes
File without changes