run-dmcp 0.3.0 → 0.5.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.
Files changed (49) hide show
  1. package/README.md +19 -5
  2. package/dist/bin/run-dmcp.js +1 -1
  3. package/dist/index.d.ts +0 -1
  4. package/dist/index.js +7 -1
  5. package/dist/mcp-server.d.ts +5 -1
  6. package/dist/mcp-server.js +5 -1
  7. package/dist/register/batch.js +11 -10
  8. package/dist/register/character.js +16 -16
  9. package/dist/register/core.js +128 -111
  10. package/dist/register/display.js +42 -41
  11. package/dist/register/resolve.js +4 -1
  12. package/dist/register/world.js +13 -13
  13. package/dist/rpg/index.d.ts +0 -16
  14. package/dist/rpg/index.js +4 -22
  15. package/dist/rpg/register/batch.js +3 -3
  16. package/dist/rpg/server.d.ts +16 -0
  17. package/dist/rpg/server.js +22 -0
  18. package/dist/schemas/index.d.ts +62 -62
  19. package/dist/schemas/index.js +91 -72
  20. package/dist/server.d.ts +1 -0
  21. package/dist/server.js +20 -0
  22. package/dist/utils/output-schemas.d.ts +58 -58
  23. package/dist/utils/validation.d.ts +31 -2
  24. package/dist/utils/validation.js +67 -10
  25. package/package.json +9 -1
  26. package/dist/register/abilities.d.ts +0 -2
  27. package/dist/register/abilities.js +0 -165
  28. package/dist/register/combat.d.ts +0 -2
  29. package/dist/register/combat.js +0 -207
  30. package/dist/register/mcp-prompts.d.ts +0 -2
  31. package/dist/register/mcp-prompts.js +0 -684
  32. package/dist/register/quests.d.ts +0 -2
  33. package/dist/register/quests.js +0 -118
  34. package/dist/register/status.d.ts +0 -2
  35. package/dist/register/status.js +0 -130
  36. package/dist/register/tables.d.ts +0 -2
  37. package/dist/register/tables.js +0 -146
  38. package/dist/tools/ability.d.ts +0 -48
  39. package/dist/tools/ability.js +0 -238
  40. package/dist/tools/combat.d.ts +0 -13
  41. package/dist/tools/combat.js +0 -195
  42. package/dist/tools/dice.d.ts +0 -23
  43. package/dist/tools/dice.js +0 -111
  44. package/dist/tools/quest.d.ts +0 -34
  45. package/dist/tools/quest.js +0 -164
  46. package/dist/tools/status.d.ts +0 -36
  47. package/dist/tools/status.js +0 -218
  48. package/dist/tools/tables.d.ts +0 -33
  49. package/dist/tools/tables.js +0 -209
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import * as worldTools from "../tools/world.js";
3
3
  import { imageGenSchema } from "../schemas/index.js";
4
- import { LIMITS } from "../utils/validation.js";
4
+ import { LIMITS, validatedSchemas } from "../utils/validation.js";
5
5
  import { ANNOTATIONS } from "../utils/tool-annotations.js";
6
6
  export function registerWorldTools(server) {
7
7
  server.registerTool("create_location", {
@@ -26,7 +26,7 @@ export function registerWorldTools(server) {
26
26
  server.registerTool("get_location", {
27
27
  description: "Get location details",
28
28
  inputSchema: {
29
- locationId: z.string().describe("The location ID"),
29
+ locationId: validatedSchemas.id.describe("The location ID"),
30
30
  },
31
31
  annotations: ANNOTATIONS.READ_ONLY,
32
32
  }, async ({ locationId }) => {
@@ -44,9 +44,9 @@ export function registerWorldTools(server) {
44
44
  server.registerTool("update_location", {
45
45
  description: "Update a location",
46
46
  inputSchema: {
47
- locationId: z.string().describe("The location ID"),
48
- name: z.string().optional().describe("New name"),
49
- description: z.string().optional().describe("New description"),
47
+ locationId: validatedSchemas.id.describe("The location ID"),
48
+ name: validatedSchemas.token.optional().describe("New name"),
49
+ description: validatedSchemas.description.optional().describe("New description"),
50
50
  properties: z.record(z.string(), z.unknown()).optional().describe("Property updates"),
51
51
  imageGen: imageGenSchema.nullable().optional().describe("Image generation metadata (null to remove)"),
52
52
  },
@@ -66,7 +66,7 @@ export function registerWorldTools(server) {
66
66
  server.registerTool("list_locations", {
67
67
  description: "List all locations in a game",
68
68
  inputSchema: {
69
- gameId: z.string().describe("The game ID"),
69
+ gameId: validatedSchemas.id.describe("The game ID"),
70
70
  },
71
71
  annotations: ANNOTATIONS.READ_ONLY,
72
72
  }, async ({ gameId }) => {
@@ -78,11 +78,11 @@ export function registerWorldTools(server) {
78
78
  server.registerTool("connect_locations", {
79
79
  description: "Create exits/paths between two locations. Call this whenever you describe how locations connect to each other - the player should be able to navigate based on database connections.",
80
80
  inputSchema: {
81
- fromLocationId: z.string().describe("First location ID"),
82
- toLocationId: z.string().describe("Second location ID"),
83
- fromDirection: z.string().describe("Direction from first location (e.g., 'north', 'up', 'through the door')"),
84
- toDirection: z.string().describe("Direction from second location back (e.g., 'south', 'down')"),
85
- description: z.string().optional().describe("Description of the path"),
81
+ fromLocationId: validatedSchemas.id.describe("First location ID"),
82
+ toLocationId: validatedSchemas.id.describe("Second location ID"),
83
+ fromDirection: validatedSchemas.token.describe("Direction from first location (e.g., 'north', 'up', 'through the door')"),
84
+ toDirection: validatedSchemas.token.describe("Direction from second location back (e.g., 'south', 'down')"),
85
+ description: validatedSchemas.description.optional().describe("Description of the path"),
86
86
  bidirectional: z.boolean().optional().describe("Create exit in both directions (default: true)"),
87
87
  },
88
88
  annotations: ANNOTATIONS.CREATE,
@@ -108,8 +108,8 @@ export function registerWorldTools(server) {
108
108
  server.registerTool("get_location_by_name", {
109
109
  description: "Look up a location by name within a game. Supports exact, partial, and fuzzy matching. Returns the best match or an error if no reasonable match found.",
110
110
  inputSchema: {
111
- gameId: z.string().describe("The game ID to search within"),
112
- name: z.string().describe("Location name to search for (case-insensitive)"),
111
+ gameId: validatedSchemas.id.describe("The game ID to search within"),
112
+ name: validatedSchemas.token.describe("Location name to search for (case-insensitive)"),
113
113
  },
114
114
  annotations: ANNOTATIONS.READ_ONLY,
115
115
  }, async ({ gameId, name }) => {
@@ -1,26 +1,10 @@
1
1
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import type { Mechanic } from "../timeline/resolve.js";
3
- import type { RenderVocabulary } from "../timeline/render.js";
4
2
  /**
5
3
  * Register every RPG-layer tool, resource and prompt onto an existing
6
4
  * server. Combat brings dice with it (registerCombatTools registers both,
7
5
  * matching how the pre-split assembly registered them as one domain).
8
6
  */
9
7
  export declare function registerRpgTools(server: McpServer): void;
10
- /**
11
- * Build the FULL assembly: every core tool plus every RPG tool, resource and
12
- * prompt this engine has always served. Same name, same `{ mechanics?,
13
- * vocabulary? }` options as the pre-split `createMcpServer` in
14
- * src/mcp-server.ts -- this is that function, now composed from two layers
15
- * instead of one, so src/bin/run-dmcp.ts's zero-argument call site keeps
16
- * working unchanged and the registered tool/resource/prompt set is
17
- * unchanged too (src/__tests__/layerBoundary.test.ts asserts this exactly).
18
- */
19
- export declare function createMcpServer(options?: {
20
- mechanics?: readonly Mechanic[];
21
- vocabulary?: RenderVocabulary;
22
- }): McpServer;
23
- export { createHttpServer, startHttpServer } from "../http/server.js";
24
8
  export * from "./tools/dice.js";
25
9
  export * from "./tools/combat.js";
26
10
  export * from "./tools/ability.js";
package/dist/rpg/index.js CHANGED
@@ -1,4 +1,3 @@
1
- import { createCoreMcpServer } from "../mcp-server.js";
2
1
  import { registerCombatTools } from "./register/combat.js";
3
2
  import { registerAbilityTools } from "./register/abilities.js";
4
3
  import { registerStatusTools } from "./register/status.js";
@@ -22,27 +21,10 @@ export function registerRpgTools(server) {
22
21
  registerRpgMcpResources(server); // game-quests, quest
23
22
  registerMcpPrompts(server); // Reusable prompt templates (game-master session library)
24
23
  }
25
- /**
26
- * Build the FULL assembly: every core tool plus every RPG tool, resource and
27
- * prompt this engine has always served. Same name, same `{ mechanics?,
28
- * vocabulary? }` options as the pre-split `createMcpServer` in
29
- * src/mcp-server.ts -- this is that function, now composed from two layers
30
- * instead of one, so src/bin/run-dmcp.ts's zero-argument call site keeps
31
- * working unchanged and the registered tool/resource/prompt set is
32
- * unchanged too (src/__tests__/layerBoundary.test.ts asserts this exactly).
33
- */
34
- export function createMcpServer(options) {
35
- const server = createCoreMcpServer(options);
36
- registerRpgTools(server);
37
- return server;
38
- }
39
- // The web UI. An application opts into serving it; importing this never
40
- // does. It lives on disk at src/http/server.ts, not under src/rpg/ -- it
41
- // imports RPG tools (quest/ability/combat), which is why it cannot be
42
- // reachable from the core entry point, but its CLIENT_DIST path resolution
43
- // is depth-sensitive in both src/ and compiled dist/, so it stays put and
44
- // only its EXPORT moves up to this layer.
45
- export { createHttpServer, startHttpServer } from "../http/server.js";
24
+ // `createMcpServer` and the web UI are NOT here. Both are assembly, and both
25
+ // moved to "run-dmcp/rpg/server" (src/rpg/server.ts) so that importing the
26
+ // layer's tool functions stops loading a server and an HTTP framework with
27
+ // them.
46
28
  // The RPG tool modules, exported as library functions -- the same shape
47
29
  // core's index.ts uses for the timeline (replay, changesWithin, and so on):
48
30
  // a consumer that wants to call combat/quest/table/status/ability/dice logic
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  import * as characterTools from "../../tools/character.js";
3
3
  import * as narrativeTools from "../../tools/narrative.js";
4
4
  import * as combatTools from "../tools/combat.js";
5
- import { LIMITS } from "../../utils/validation.js";
5
+ import { LIMITS, validatedSchemas } from "../../utils/validation.js";
6
6
  import { ANNOTATIONS } from "../../utils/tool-annotations.js";
7
7
  // The one multi-entity workflow tool that reaches into combat, split out of
8
8
  // src/register/batch.ts (design §8, issue #17): everything else there --
@@ -17,8 +17,8 @@ export function registerRpgBatchTools(server) {
17
17
  server.registerTool("setup_combat_encounter", {
18
18
  description: "Complete combat setup in one call: creates enemy NPCs and starts combat with all participants (enemies + players at location). Returns the ready-to-play combat state.",
19
19
  inputSchema: {
20
- gameId: z.string().describe("The game ID"),
21
- locationId: z.string().describe("Location where combat takes place"),
20
+ gameId: validatedSchemas.id.describe("The game ID"),
21
+ locationId: validatedSchemas.id.describe("Location where combat takes place"),
22
22
  enemies: z
23
23
  .array(z.object({
24
24
  name: z.string().min(1).max(LIMITS.NAME_MAX).describe("Enemy name"),
@@ -0,0 +1,16 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { Mechanic } from "../timeline/resolve.js";
3
+ import type { RenderVocabulary } from "../timeline/render.js";
4
+ /**
5
+ * Build the FULL assembly: every core tool plus every RPG tool, resource and
6
+ * prompt this engine has always served. Same name and same `{ mechanics?,
7
+ * vocabulary? }` options as the pre-split `createMcpServer` in
8
+ * src/mcp-server.ts, so src/bin/run-dmcp.ts's zero-argument call site keeps
9
+ * working unchanged and the registered tool/resource/prompt set is unchanged
10
+ * too (src/__tests__/layerBoundary.test.ts asserts this exactly).
11
+ */
12
+ export declare function createMcpServer(options?: {
13
+ mechanics?: readonly Mechanic[];
14
+ vocabulary?: RenderVocabulary;
15
+ }): McpServer;
16
+ export { createHttpServer, startHttpServer } from "../http/server.js";
@@ -0,0 +1,22 @@
1
+ import { createCoreMcpServer } from "../mcp-server.js";
2
+ import { registerRpgTools } from "./index.js";
3
+ /**
4
+ * Build the FULL assembly: every core tool plus every RPG tool, resource and
5
+ * prompt this engine has always served. Same name and same `{ mechanics?,
6
+ * vocabulary? }` options as the pre-split `createMcpServer` in
7
+ * src/mcp-server.ts, so src/bin/run-dmcp.ts's zero-argument call site keeps
8
+ * working unchanged and the registered tool/resource/prompt set is unchanged
9
+ * too (src/__tests__/layerBoundary.test.ts asserts this exactly).
10
+ */
11
+ export function createMcpServer(options) {
12
+ const server = createCoreMcpServer(options);
13
+ registerRpgTools(server);
14
+ return server;
15
+ }
16
+ // The web UI. An application opts into serving it; importing this never
17
+ // does. It lives on disk at src/http/server.ts, not under src/rpg/ -- it
18
+ // imports RPG tools (quest/ability/combat), which is why it cannot be
19
+ // reachable from the core entry point, but its CLIENT_DIST path resolution
20
+ // is depth-sensitive in both src/ and compiled dist/, so it stays put and
21
+ // only its EXPORT moves up to this layer.
22
+ export { createHttpServer, startHttpServer } from "../http/server.js";