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.
- package/README.md +19 -5
- package/dist/bin/run-dmcp.js +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +7 -1
- package/dist/mcp-server.d.ts +5 -1
- package/dist/mcp-server.js +5 -1
- package/dist/register/batch.js +11 -10
- package/dist/register/character.js +16 -16
- package/dist/register/core.js +128 -111
- package/dist/register/display.js +42 -41
- package/dist/register/resolve.js +4 -1
- package/dist/register/world.js +13 -13
- package/dist/rpg/index.d.ts +0 -16
- package/dist/rpg/index.js +4 -22
- package/dist/rpg/register/batch.js +3 -3
- package/dist/rpg/server.d.ts +16 -0
- package/dist/rpg/server.js +22 -0
- package/dist/schemas/index.d.ts +62 -62
- package/dist/schemas/index.js +91 -72
- package/dist/server.d.ts +1 -0
- package/dist/server.js +20 -0
- package/dist/utils/output-schemas.d.ts +58 -58
- package/dist/utils/validation.d.ts +31 -2
- package/dist/utils/validation.js +67 -10
- package/package.json +9 -1
- package/dist/register/abilities.d.ts +0 -2
- package/dist/register/abilities.js +0 -165
- package/dist/register/combat.d.ts +0 -2
- package/dist/register/combat.js +0 -207
- package/dist/register/mcp-prompts.d.ts +0 -2
- package/dist/register/mcp-prompts.js +0 -684
- package/dist/register/quests.d.ts +0 -2
- package/dist/register/quests.js +0 -118
- package/dist/register/status.d.ts +0 -2
- package/dist/register/status.js +0 -130
- package/dist/register/tables.d.ts +0 -2
- package/dist/register/tables.js +0 -146
- package/dist/tools/ability.d.ts +0 -48
- package/dist/tools/ability.js +0 -238
- package/dist/tools/combat.d.ts +0 -13
- package/dist/tools/combat.js +0 -195
- package/dist/tools/dice.d.ts +0 -23
- package/dist/tools/dice.js +0 -111
- package/dist/tools/quest.d.ts +0 -34
- package/dist/tools/quest.js +0 -164
- package/dist/tools/status.d.ts +0 -36
- package/dist/tools/status.js +0 -218
- package/dist/tools/tables.d.ts +0 -33
- package/dist/tools/tables.js +0 -209
package/README.md
CHANGED
|
@@ -59,14 +59,28 @@ schema comes up, where the database lives, and whether anything listens.
|
|
|
59
59
|
|
|
60
60
|
**The package root is the core, and the tabletop surface is a layer above it.** Dice, combat,
|
|
61
61
|
abilities, status effects, random tables and quests are genuinely game-shaped — an optional
|
|
62
|
-
dependency, not part of the engine (see [docs/DESIGN.md](docs/DESIGN.md) §8).
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
dependency, not part of the engine (see [docs/DESIGN.md](docs/DESIGN.md) §8).
|
|
63
|
+
|
|
64
|
+
**Mechanism and assembly are separate entries, and importing one never loads the other** (since
|
|
65
|
+
0.4.0). Four specifiers, two layers by two kinds:
|
|
66
|
+
|
|
67
|
+
| | mechanism — functions, constants, types | assembly — builds a server |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| **core** | `run-dmcp` | `run-dmcp/server` → `createCoreMcpServer` |
|
|
70
|
+
| **+ tabletop** | `run-dmcp/rpg` | `run-dmcp/rpg/server` → `createMcpServer` |
|
|
71
|
+
|
|
72
|
+
Assembling a server means loading the MCP SDK, twenty-one register modules and (for the full
|
|
73
|
+
assembly) the web UI. Wanting `createGame` or `LIMITS` does not, and until 0.4.0 both entries
|
|
74
|
+
charged for it anyway: the core entry cost 97.4ms per process cold and costs 47.0ms now, which is
|
|
75
|
+
below the MCP SDK's own 55.0ms, because without the assembly it no longer loads the SDK at all.
|
|
76
|
+
|
|
77
|
+
A consumer that *does* build a server loads the SDK regardless, so it saves less than that
|
|
78
|
+
difference suggests — measured with the SDK warm, importing both entries, 67.4ms → 38.0ms, about
|
|
79
|
+
29ms per process. The functions did not change; their specifiers did.
|
|
66
80
|
|
|
67
81
|
```ts
|
|
68
82
|
import { initializeSchema, type SchemaMigration } from "run-dmcp";
|
|
69
|
-
import { createMcpServer } from "run-dmcp/rpg";
|
|
83
|
+
import { createMcpServer } from "run-dmcp/rpg/server";
|
|
70
84
|
|
|
71
85
|
const migrations: SchemaMigration[] = [
|
|
72
86
|
{
|
package/dist/bin/run-dmcp.js
CHANGED
|
@@ -18,7 +18,7 @@ import { startHttpServer } from "../http/server.js";
|
|
|
18
18
|
// (design §8, issue #17). The application always served the full surface,
|
|
19
19
|
// so it reaches for it here rather than the core-only `createCoreMcpServer`
|
|
20
20
|
// in ../mcp-server.js.
|
|
21
|
-
import { createMcpServer } from "../rpg/
|
|
21
|
+
import { createMcpServer } from "../rpg/server.js";
|
|
22
22
|
import { httpPortFromEnv, setHttpPort, webUiEnabled } from "../utils/webui.js";
|
|
23
23
|
import { createLogger } from "../utils/logger.js";
|
|
24
24
|
const log = createLogger("bin");
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export { createCoreMcpServer, SERVER_NAME, SERVER_VERSION } from "./mcp-server.js";
|
|
2
1
|
export { getDatabase, closeDatabase, withTransaction, getDatabasePath, getDataDir, resolveDataPathFrom, } from "./db/connection.js";
|
|
3
2
|
export type { DataPathInputs } from "./db/connection.js";
|
|
4
3
|
export { initializeSchema } from "./db/schema.js";
|
package/dist/index.js
CHANGED
|
@@ -26,7 +26,13 @@
|
|
|
26
26
|
// depending up into it. `src/__tests__/layerBoundary.test.ts` walks the
|
|
27
27
|
// static import graph from this file and fails if anything under `src/rpg/`
|
|
28
28
|
// is reachable from it.
|
|
29
|
-
|
|
29
|
+
// The assembled core server is NOT here. It moved to "run-dmcp/server"
|
|
30
|
+
// (src/server.ts) so that importing mechanism stops loading it: building a
|
|
31
|
+
// server costs the MCP SDK and twenty-one register modules, and a consumer
|
|
32
|
+
// reaching for `LIMITS` or `createGame` was paying for both -- 97.4ms per
|
|
33
|
+
// process against 46.8ms without it, cold, at 0.3.0. Enforced by
|
|
34
|
+
// src/__tests__/assemblyBoundary.test.ts, which walks this file's runtime
|
|
35
|
+
// import graph and fails if the assembly is reachable from it again.
|
|
30
36
|
// The database, and where it lives. The path resolves against the consuming
|
|
31
37
|
// application (DMCP_DB_PATH, else an existing XDG data directory, else the
|
|
32
38
|
// working directory) and never against this package's install location.
|
package/dist/mcp-server.d.ts
CHANGED
|
@@ -2,7 +2,11 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
2
2
|
import { type Mechanic } from "./timeline/resolve.js";
|
|
3
3
|
import { type RenderVocabulary } from "./timeline/render.js";
|
|
4
4
|
export declare const SERVER_NAME = "dmcp";
|
|
5
|
-
|
|
5
|
+
/** What the server tells a client it is, in the MCP handshake. Kept equal to
|
|
6
|
+
* the published package version by src/__tests__/serverVersion.test.ts --
|
|
7
|
+
* this said "0.3.0" for the whole of 0.4.0, because a release bumps
|
|
8
|
+
* package.json and nothing was watching this. */
|
|
9
|
+
export declare const SERVER_VERSION = "0.5.0";
|
|
6
10
|
/**
|
|
7
11
|
* Build an MCP server with every CORE tool, resource and prompt this engine
|
|
8
12
|
* serves -- entities, facts, events, the timeline, and the entity/property
|
package/dist/mcp-server.js
CHANGED
|
@@ -41,7 +41,11 @@ import { registerRenderTools } from "./register/render.js";
|
|
|
41
41
|
import { createResolver } from "./timeline/resolve.js";
|
|
42
42
|
import { createStateRenderer } from "./timeline/render.js";
|
|
43
43
|
export const SERVER_NAME = "dmcp";
|
|
44
|
-
|
|
44
|
+
/** What the server tells a client it is, in the MCP handshake. Kept equal to
|
|
45
|
+
* the published package version by src/__tests__/serverVersion.test.ts --
|
|
46
|
+
* this said "0.3.0" for the whole of 0.4.0, because a release bumps
|
|
47
|
+
* package.json and nothing was watching this. */
|
|
48
|
+
export const SERVER_VERSION = "0.5.0";
|
|
45
49
|
/**
|
|
46
50
|
* Build an MCP server with every CORE tool, resource and prompt this engine
|
|
47
51
|
* serves -- entities, facts, events, the timeline, and the entity/property
|
package/dist/register/batch.js
CHANGED
|
@@ -3,7 +3,7 @@ import * as characterTools from "../tools/character.js";
|
|
|
3
3
|
import * as worldTools from "../tools/world.js";
|
|
4
4
|
import * as inventoryTools from "../tools/inventory.js";
|
|
5
5
|
import * as narrativeTools from "../tools/narrative.js";
|
|
6
|
-
import { LIMITS } from "../utils/validation.js";
|
|
6
|
+
import { LIMITS, validatedSchemas } from "../utils/validation.js";
|
|
7
7
|
import { ANNOTATIONS } from "../utils/tool-annotations.js";
|
|
8
8
|
import { imageGenSchema, voiceSchema } from "../schemas/index.js";
|
|
9
9
|
// Multi-entity workflow tools over entity/property concepts -- characters,
|
|
@@ -18,7 +18,7 @@ export function registerBatchTools(server) {
|
|
|
18
18
|
server.registerTool("batch_create_npcs", {
|
|
19
19
|
description: "Create multiple NPCs at once. Use this when populating a location with several characters. Returns all created characters.",
|
|
20
20
|
inputSchema: {
|
|
21
|
-
gameId:
|
|
21
|
+
gameId: validatedSchemas.id.describe("The game ID"),
|
|
22
22
|
npcs: z
|
|
23
23
|
.array(z.object({
|
|
24
24
|
name: z.string().min(1).max(LIMITS.NAME_MAX).describe("NPC name"),
|
|
@@ -28,10 +28,10 @@ export function registerBatchTools(server) {
|
|
|
28
28
|
.object({
|
|
29
29
|
health: z.number().optional(),
|
|
30
30
|
maxHealth: z.number().optional(),
|
|
31
|
-
conditions:
|
|
31
|
+
conditions: validatedSchemas.stringArray.optional(),
|
|
32
32
|
})
|
|
33
33
|
.optional(),
|
|
34
|
-
locationId:
|
|
34
|
+
locationId: validatedSchemas.id.optional().describe("Starting location"),
|
|
35
35
|
notes: z.string().max(LIMITS.CONTENT_MAX).optional(),
|
|
36
36
|
voice: voiceSchema.optional(),
|
|
37
37
|
imageGen: imageGenSchema.optional(),
|
|
@@ -105,12 +105,13 @@ export function registerBatchTools(server) {
|
|
|
105
105
|
server.registerTool("scene_transition", {
|
|
106
106
|
description: "Complete scene transition in one call: moves specified characters to a new location and logs a narrative event. Perfect for moving between scenes.",
|
|
107
107
|
inputSchema: {
|
|
108
|
-
gameId:
|
|
108
|
+
gameId: validatedSchemas.id.describe("The game ID"),
|
|
109
109
|
characterIds: z
|
|
110
|
-
.array(
|
|
110
|
+
.array(validatedSchemas.id)
|
|
111
111
|
.min(1)
|
|
112
|
+
.max(LIMITS.ARRAY_MAX)
|
|
112
113
|
.describe("Characters to move to the new scene"),
|
|
113
|
-
destinationId:
|
|
114
|
+
destinationId: validatedSchemas.id.describe("Destination location ID"),
|
|
114
115
|
narrativeDescription: z
|
|
115
116
|
.string()
|
|
116
117
|
.max(LIMITS.DESCRIPTION_MAX)
|
|
@@ -165,7 +166,7 @@ export function registerBatchTools(server) {
|
|
|
165
166
|
server.registerTool("get_character_context", {
|
|
166
167
|
description: "Get comprehensive character context in one call: character details, inventory, and current location info. Reduces multiple tool calls to one.",
|
|
167
168
|
inputSchema: {
|
|
168
|
-
characterId:
|
|
169
|
+
characterId: validatedSchemas.id.describe("The character ID"),
|
|
169
170
|
},
|
|
170
171
|
annotations: ANNOTATIONS.READ_ONLY,
|
|
171
172
|
}, async ({ characterId }) => {
|
|
@@ -219,8 +220,8 @@ export function registerBatchTools(server) {
|
|
|
219
220
|
server.registerTool("get_location_context", {
|
|
220
221
|
description: "Get comprehensive location context in one call: location details, present characters, and items here. Reduces multiple tool calls to one.",
|
|
221
222
|
inputSchema: {
|
|
222
|
-
locationId:
|
|
223
|
-
gameId:
|
|
223
|
+
locationId: validatedSchemas.id.describe("The location ID"),
|
|
224
|
+
gameId: validatedSchemas.id.describe("The game ID (needed for character lookup)"),
|
|
224
225
|
},
|
|
225
226
|
annotations: ANNOTATIONS.READ_ONLY,
|
|
226
227
|
}, async ({ locationId, gameId }) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import * as characterTools from "../tools/character.js";
|
|
3
3
|
import { imageGenSchema, voiceSchema } 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
|
import { characterOutputSchema, characterStatusSchema, conditionModifyOutputSchema, } from "../utils/output-schemas.js";
|
|
7
7
|
import { verbositySchema, applyVerbosity } from "../utils/verbosity.js";
|
|
@@ -44,7 +44,7 @@ export function registerCharacterTools(server) {
|
|
|
44
44
|
server.registerTool("get_character", {
|
|
45
45
|
description: "Get character details",
|
|
46
46
|
inputSchema: {
|
|
47
|
-
characterId:
|
|
47
|
+
characterId: validatedSchemas.id.describe("The character ID"),
|
|
48
48
|
},
|
|
49
49
|
outputSchema: characterOutputSchema,
|
|
50
50
|
annotations: ANNOTATIONS.READ_ONLY,
|
|
@@ -67,13 +67,13 @@ export function registerCharacterTools(server) {
|
|
|
67
67
|
server.registerTool("update_character", {
|
|
68
68
|
description: "Update character attributes, skills, status, or voice",
|
|
69
69
|
inputSchema: {
|
|
70
|
-
characterId:
|
|
71
|
-
name:
|
|
70
|
+
characterId: validatedSchemas.id.describe("The character ID"),
|
|
71
|
+
name: validatedSchemas.token.optional().describe("New name"),
|
|
72
72
|
attributes: z.record(z.string(), z.number()).optional().describe("Attribute updates"),
|
|
73
73
|
skills: z.record(z.string(), z.number()).optional().describe("Skill updates"),
|
|
74
74
|
status: z.record(z.string(), z.unknown()).optional().describe("Status updates"),
|
|
75
|
-
locationId:
|
|
76
|
-
notes:
|
|
75
|
+
locationId: validatedSchemas.id.optional().describe("New location"),
|
|
76
|
+
notes: validatedSchemas.content.optional().describe("Notes update"),
|
|
77
77
|
voice: voiceSchema.nullable().optional().describe("Voice characteristics (null to remove)"),
|
|
78
78
|
imageGen: imageGenSchema.nullable().optional().describe("Image generation metadata (null to remove)"),
|
|
79
79
|
},
|
|
@@ -98,9 +98,9 @@ export function registerCharacterTools(server) {
|
|
|
98
98
|
server.registerTool("list_characters", {
|
|
99
99
|
description: "List characters in a game. Use verbosity to control response size: 'minimal' for quick lookups (id/name only), 'standard' for common fields, 'full' for all details.",
|
|
100
100
|
inputSchema: {
|
|
101
|
-
gameId:
|
|
101
|
+
gameId: validatedSchemas.id.describe("The game ID"),
|
|
102
102
|
isPlayer: z.boolean().optional().describe("Filter by player/NPC"),
|
|
103
|
-
locationId:
|
|
103
|
+
locationId: validatedSchemas.id.optional().describe("Filter by location"),
|
|
104
104
|
verbosity: verbositySchema,
|
|
105
105
|
},
|
|
106
106
|
outputSchema: {
|
|
@@ -128,8 +128,8 @@ export function registerCharacterTools(server) {
|
|
|
128
128
|
server.registerTool("move_character", {
|
|
129
129
|
description: "Move a character to a different location",
|
|
130
130
|
inputSchema: {
|
|
131
|
-
characterId:
|
|
132
|
-
locationId:
|
|
131
|
+
characterId: validatedSchemas.id.describe("The character ID"),
|
|
132
|
+
locationId: validatedSchemas.id.describe("The destination location ID"),
|
|
133
133
|
},
|
|
134
134
|
outputSchema: {
|
|
135
135
|
success: z.boolean(),
|
|
@@ -163,7 +163,7 @@ export function registerCharacterTools(server) {
|
|
|
163
163
|
server.registerTool("modify_health", {
|
|
164
164
|
description: "Modify a character's health. Use mode 'damage' to reduce health, or 'heal' to restore health.",
|
|
165
165
|
inputSchema: {
|
|
166
|
-
characterId:
|
|
166
|
+
characterId: validatedSchemas.id.describe("The character ID"),
|
|
167
167
|
mode: z.enum(["damage", "heal"]).describe("'damage' to reduce health, 'heal' to restore health"),
|
|
168
168
|
amount: z.number().describe("Amount of damage or healing"),
|
|
169
169
|
},
|
|
@@ -201,7 +201,7 @@ export function registerCharacterTools(server) {
|
|
|
201
201
|
server.registerTool("modify_conditions", {
|
|
202
202
|
description: "Add and/or remove conditions from a character in a single call. More efficient than separate add/remove calls.",
|
|
203
203
|
inputSchema: {
|
|
204
|
-
characterId:
|
|
204
|
+
characterId: validatedSchemas.id.describe("The character ID"),
|
|
205
205
|
add: z.array(z.string().max(100)).max(LIMITS.ARRAY_MAX).optional().describe("Conditions to add"),
|
|
206
206
|
remove: z.array(z.string().max(100)).max(LIMITS.ARRAY_MAX).optional().describe("Conditions to remove"),
|
|
207
207
|
},
|
|
@@ -244,8 +244,8 @@ export function registerCharacterTools(server) {
|
|
|
244
244
|
server.registerTool("get_character_by_name", {
|
|
245
245
|
description: "Look up a character by name within a game. Supports exact, partial, and fuzzy matching. Returns the best match or an error if no reasonable match found.",
|
|
246
246
|
inputSchema: {
|
|
247
|
-
gameId:
|
|
248
|
-
name:
|
|
247
|
+
gameId: validatedSchemas.id.describe("The game ID to search within"),
|
|
248
|
+
name: validatedSchemas.token.describe("Character name to search for (case-insensitive)"),
|
|
249
249
|
},
|
|
250
250
|
outputSchema: characterOutputSchema,
|
|
251
251
|
annotations: ANNOTATIONS.READ_ONLY,
|
|
@@ -268,7 +268,7 @@ export function registerCharacterTools(server) {
|
|
|
268
268
|
server.registerTool("list_character_summaries", {
|
|
269
269
|
description: "List characters with quick-identification summaries. Use this to help identify characters by appearance before looking up their full details. More efficient than loading full character data when you just need to identify who's who.",
|
|
270
270
|
inputSchema: {
|
|
271
|
-
gameId:
|
|
271
|
+
gameId: validatedSchemas.id.describe("The game ID"),
|
|
272
272
|
},
|
|
273
273
|
outputSchema: {
|
|
274
274
|
summaries: z.array(z.object({
|
|
@@ -297,7 +297,7 @@ export function registerCharacterTools(server) {
|
|
|
297
297
|
server.registerTool("delete_character", {
|
|
298
298
|
description: "Delete a character permanently. This is IRREVERSIBLE and will remove the character and all associated data.",
|
|
299
299
|
inputSchema: {
|
|
300
|
-
characterId:
|
|
300
|
+
characterId: validatedSchemas.id.describe("The character ID to delete"),
|
|
301
301
|
},
|
|
302
302
|
outputSchema: {
|
|
303
303
|
success: z.boolean(),
|