run-dmcp 0.1.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 (167) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +79 -0
  3. package/dist/__tests__/engineVocabulary.test.d.ts +1 -0
  4. package/dist/__tests__/engineVocabulary.test.js +147 -0
  5. package/dist/db/__tests__/connection.test.d.ts +1 -0
  6. package/dist/db/__tests__/connection.test.js +72 -0
  7. package/dist/db/__tests__/testDb.d.ts +33 -0
  8. package/dist/db/__tests__/testDb.js +41 -0
  9. package/dist/db/connection.d.ts +22 -0
  10. package/dist/db/connection.js +107 -0
  11. package/dist/db/schema.d.ts +1 -0
  12. package/dist/db/schema.js +725 -0
  13. package/dist/events/emitter.d.ts +22 -0
  14. package/dist/events/emitter.js +71 -0
  15. package/dist/http/server.d.ts +3 -0
  16. package/dist/http/server.js +649 -0
  17. package/dist/index.d.ts +2 -0
  18. package/dist/index.js +92 -0
  19. package/dist/register/abilities.d.ts +2 -0
  20. package/dist/register/abilities.js +165 -0
  21. package/dist/register/audio.d.ts +2 -0
  22. package/dist/register/audio.js +326 -0
  23. package/dist/register/batch.d.ts +2 -0
  24. package/dist/register/batch.js +343 -0
  25. package/dist/register/character.d.ts +2 -0
  26. package/dist/register/character.js +324 -0
  27. package/dist/register/combat.d.ts +2 -0
  28. package/dist/register/combat.js +207 -0
  29. package/dist/register/core.d.ts +2 -0
  30. package/dist/register/core.js +1040 -0
  31. package/dist/register/display.d.ts +2 -0
  32. package/dist/register/display.js +263 -0
  33. package/dist/register/factions.d.ts +2 -0
  34. package/dist/register/factions.js +186 -0
  35. package/dist/register/images.d.ts +2 -0
  36. package/dist/register/images.js +400 -0
  37. package/dist/register/inventory.d.ts +2 -0
  38. package/dist/register/inventory.js +115 -0
  39. package/dist/register/mcp-prompts.d.ts +2 -0
  40. package/dist/register/mcp-prompts.js +684 -0
  41. package/dist/register/mcp-resources.d.ts +2 -0
  42. package/dist/register/mcp-resources.js +335 -0
  43. package/dist/register/narrative.d.ts +2 -0
  44. package/dist/register/narrative.js +242 -0
  45. package/dist/register/notes.d.ts +2 -0
  46. package/dist/register/notes.js +170 -0
  47. package/dist/register/pause.d.ts +2 -0
  48. package/dist/register/pause.js +580 -0
  49. package/dist/register/quests.d.ts +2 -0
  50. package/dist/register/quests.js +118 -0
  51. package/dist/register/relationships.d.ts +2 -0
  52. package/dist/register/relationships.js +147 -0
  53. package/dist/register/resources.d.ts +2 -0
  54. package/dist/register/resources.js +277 -0
  55. package/dist/register/secrets.d.ts +2 -0
  56. package/dist/register/secrets.js +192 -0
  57. package/dist/register/status.d.ts +2 -0
  58. package/dist/register/status.js +130 -0
  59. package/dist/register/tables.d.ts +2 -0
  60. package/dist/register/tables.js +146 -0
  61. package/dist/register/tags.d.ts +2 -0
  62. package/dist/register/tags.js +114 -0
  63. package/dist/register/time.d.ts +2 -0
  64. package/dist/register/time.js +281 -0
  65. package/dist/register/world.d.ts +2 -0
  66. package/dist/register/world.js +127 -0
  67. package/dist/schemas/index.d.ts +921 -0
  68. package/dist/schemas/index.js +121 -0
  69. package/dist/test-setup.d.ts +1 -0
  70. package/dist/test-setup.js +13 -0
  71. package/dist/tools/__tests__/audio.test.d.ts +1 -0
  72. package/dist/tools/__tests__/audio.test.js +59 -0
  73. package/dist/tools/__tests__/conserved.test.d.ts +1 -0
  74. package/dist/tools/__tests__/conserved.test.js +488 -0
  75. package/dist/tools/__tests__/constraint.test.d.ts +1 -0
  76. package/dist/tools/__tests__/constraint.test.js +212 -0
  77. package/dist/tools/__tests__/expiry-consequences.test.d.ts +1 -0
  78. package/dist/tools/__tests__/expiry-consequences.test.js +110 -0
  79. package/dist/tools/__tests__/images.test.d.ts +1 -0
  80. package/dist/tools/__tests__/images.test.js +59 -0
  81. package/dist/tools/__tests__/relationship.test.d.ts +1 -0
  82. package/dist/tools/__tests__/relationship.test.js +132 -0
  83. package/dist/tools/__tests__/resource-constraints.test.d.ts +1 -0
  84. package/dist/tools/__tests__/resource-constraints.test.js +131 -0
  85. package/dist/tools/__tests__/resource.test.d.ts +1 -0
  86. package/dist/tools/__tests__/resource.test.js +190 -0
  87. package/dist/tools/__tests__/time.test.d.ts +1 -0
  88. package/dist/tools/__tests__/time.test.js +404 -0
  89. package/dist/tools/__tests__/timers.test.d.ts +1 -0
  90. package/dist/tools/__tests__/timers.test.js +426 -0
  91. package/dist/tools/__tests__/world.test.d.ts +1 -0
  92. package/dist/tools/__tests__/world.test.js +70 -0
  93. package/dist/tools/ability.d.ts +48 -0
  94. package/dist/tools/ability.js +238 -0
  95. package/dist/tools/audio.d.ts +24 -0
  96. package/dist/tools/audio.js +365 -0
  97. package/dist/tools/character.d.ts +70 -0
  98. package/dist/tools/character.js +309 -0
  99. package/dist/tools/combat.d.ts +13 -0
  100. package/dist/tools/combat.js +195 -0
  101. package/dist/tools/constraint.d.ts +132 -0
  102. package/dist/tools/constraint.js +269 -0
  103. package/dist/tools/dice.d.ts +23 -0
  104. package/dist/tools/dice.js +111 -0
  105. package/dist/tools/display.d.ts +120 -0
  106. package/dist/tools/display.js +528 -0
  107. package/dist/tools/faction.d.ts +61 -0
  108. package/dist/tools/faction.js +269 -0
  109. package/dist/tools/game.d.ts +96 -0
  110. package/dist/tools/game.js +526 -0
  111. package/dist/tools/image-prompt.d.ts +49 -0
  112. package/dist/tools/image-prompt.js +479 -0
  113. package/dist/tools/images.d.ts +47 -0
  114. package/dist/tools/images.js +449 -0
  115. package/dist/tools/inventory.d.ts +20 -0
  116. package/dist/tools/inventory.js +145 -0
  117. package/dist/tools/narrative.d.ts +58 -0
  118. package/dist/tools/narrative.js +237 -0
  119. package/dist/tools/notes.d.ts +41 -0
  120. package/dist/tools/notes.js +220 -0
  121. package/dist/tools/pause.d.ts +110 -0
  122. package/dist/tools/pause.js +1254 -0
  123. package/dist/tools/quest.d.ts +34 -0
  124. package/dist/tools/quest.js +164 -0
  125. package/dist/tools/relationship.d.ts +74 -0
  126. package/dist/tools/relationship.js +324 -0
  127. package/dist/tools/resource.d.ts +93 -0
  128. package/dist/tools/resource.js +374 -0
  129. package/dist/tools/rules.d.ts +4 -0
  130. package/dist/tools/rules.js +30 -0
  131. package/dist/tools/secrets.d.ts +49 -0
  132. package/dist/tools/secrets.js +195 -0
  133. package/dist/tools/status.d.ts +36 -0
  134. package/dist/tools/status.js +218 -0
  135. package/dist/tools/tables.d.ts +33 -0
  136. package/dist/tools/tables.js +209 -0
  137. package/dist/tools/tags.d.ts +52 -0
  138. package/dist/tools/tags.js +176 -0
  139. package/dist/tools/time.d.ts +33 -0
  140. package/dist/tools/time.js +276 -0
  141. package/dist/tools/timers.d.ts +41 -0
  142. package/dist/tools/timers.js +215 -0
  143. package/dist/tools/world.d.ts +78 -0
  144. package/dist/tools/world.js +331 -0
  145. package/dist/types/index.d.ts +969 -0
  146. package/dist/types/index.js +1 -0
  147. package/dist/utils/__tests__/json.test.d.ts +1 -0
  148. package/dist/utils/__tests__/json.test.js +55 -0
  149. package/dist/utils/__tests__/validation.test.d.ts +1 -0
  150. package/dist/utils/__tests__/validation.test.js +90 -0
  151. package/dist/utils/errors.d.ts +44 -0
  152. package/dist/utils/errors.js +121 -0
  153. package/dist/utils/json.d.ts +9 -0
  154. package/dist/utils/json.js +23 -0
  155. package/dist/utils/logger.d.ts +7 -0
  156. package/dist/utils/logger.js +50 -0
  157. package/dist/utils/output-schemas.d.ts +594 -0
  158. package/dist/utils/output-schemas.js +331 -0
  159. package/dist/utils/tool-annotations.d.ts +147 -0
  160. package/dist/utils/tool-annotations.js +98 -0
  161. package/dist/utils/validation.d.ts +34 -0
  162. package/dist/utils/validation.js +52 -0
  163. package/dist/utils/verbosity.d.ts +57 -0
  164. package/dist/utils/verbosity.js +67 -0
  165. package/dist/utils/webui.d.ts +20 -0
  166. package/dist/utils/webui.js +35 -0
  167. package/package.json +75 -0
@@ -0,0 +1,331 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Shared output schemas for MCP tools.
4
+ * These enable clients to validate structured outputs from tools.
5
+ */
6
+ // ============================================================================
7
+ // COMMON RESPONSE PATTERNS
8
+ // ============================================================================
9
+ /** Simple success/failure response */
10
+ export const successResponseSchema = {
11
+ success: z.boolean(),
12
+ message: z.string().optional(),
13
+ };
14
+ /** Simple text result */
15
+ export const textResultSchema = {
16
+ result: z.string(),
17
+ };
18
+ /** Entity deleted response */
19
+ export const deletedResponseSchema = {
20
+ deleted: z.boolean(),
21
+ id: z.string().optional(),
22
+ };
23
+ /** List response with count */
24
+ export const listResponseSchema = (itemSchema) => ({
25
+ items: z.array(itemSchema),
26
+ count: z.number(),
27
+ });
28
+ // ============================================================================
29
+ // GAME SCHEMAS
30
+ // ============================================================================
31
+ export const gameOutputSchema = {
32
+ id: z.string(),
33
+ name: z.string(),
34
+ setting: z.string(),
35
+ style: z.string(),
36
+ createdAt: z.string(),
37
+ updatedAt: z.string(),
38
+ webUi: z.object({
39
+ url: z.string(),
40
+ message: z.string(),
41
+ }).optional(),
42
+ };
43
+ export const gameStateOutputSchema = {
44
+ game: z.object({
45
+ id: z.string(),
46
+ name: z.string(),
47
+ setting: z.string(),
48
+ style: z.string(),
49
+ }),
50
+ characterCount: z.number(),
51
+ locationCount: z.number(),
52
+ activeQuests: z.number(),
53
+ activeCombat: z.boolean(),
54
+ };
55
+ export const gameMenuOutputSchema = {
56
+ hasExistingGames: z.boolean(),
57
+ games: z.array(z.object({
58
+ id: z.string(),
59
+ name: z.string(),
60
+ setting: z.string(),
61
+ style: z.string(),
62
+ createdAt: z.string(),
63
+ updatedAt: z.string(),
64
+ webUiUrl: z.string().optional(),
65
+ })),
66
+ instruction: z.string(),
67
+ webUi: z.object({
68
+ baseUrl: z.string(),
69
+ message: z.string(),
70
+ }).optional(),
71
+ };
72
+ // ============================================================================
73
+ // CHARACTER SCHEMAS
74
+ // ============================================================================
75
+ export const characterStatusSchema = z.object({
76
+ health: z.number(),
77
+ maxHealth: z.number(),
78
+ conditions: z.array(z.string()),
79
+ experience: z.number(),
80
+ level: z.number(),
81
+ });
82
+ export const characterOutputSchema = {
83
+ id: z.string(),
84
+ gameId: z.string(),
85
+ name: z.string(),
86
+ isPlayer: z.boolean(),
87
+ attributes: z.record(z.string(), z.number()),
88
+ skills: z.record(z.string(), z.number()),
89
+ status: characterStatusSchema,
90
+ locationId: z.string().nullable(),
91
+ notes: z.string(),
92
+ createdAt: z.string(),
93
+ };
94
+ export const characterListOutputSchema = {
95
+ characters: z.array(z.object({
96
+ id: z.string(),
97
+ name: z.string(),
98
+ isPlayer: z.boolean(),
99
+ status: characterStatusSchema,
100
+ locationId: z.string().nullable(),
101
+ })),
102
+ count: z.number(),
103
+ };
104
+ // ============================================================================
105
+ // LOCATION SCHEMAS
106
+ // ============================================================================
107
+ export const exitSchema = z.object({
108
+ direction: z.string(),
109
+ destinationId: z.string(),
110
+ description: z.string().optional(),
111
+ locked: z.boolean().optional(),
112
+ hidden: z.boolean().optional(),
113
+ });
114
+ export const locationOutputSchema = {
115
+ id: z.string(),
116
+ gameId: z.string(),
117
+ name: z.string(),
118
+ description: z.string(),
119
+ properties: z.object({
120
+ exits: z.array(exitSchema),
121
+ features: z.array(z.string()),
122
+ atmosphere: z.string(),
123
+ }),
124
+ };
125
+ export const locationListOutputSchema = {
126
+ locations: z.array(z.object({
127
+ id: z.string(),
128
+ name: z.string(),
129
+ description: z.string(),
130
+ })),
131
+ count: z.number(),
132
+ };
133
+ // ============================================================================
134
+ // QUEST SCHEMAS
135
+ // ============================================================================
136
+ export const questObjectiveSchema = z.object({
137
+ id: z.string(),
138
+ description: z.string(),
139
+ completed: z.boolean(),
140
+ optional: z.boolean().optional(),
141
+ });
142
+ export const questOutputSchema = {
143
+ id: z.string(),
144
+ gameId: z.string(),
145
+ name: z.string(),
146
+ description: z.string(),
147
+ objectives: z.array(questObjectiveSchema),
148
+ status: z.enum(["active", "completed", "failed", "abandoned"]),
149
+ rewards: z.string().optional(),
150
+ };
151
+ // ============================================================================
152
+ // COMBAT SCHEMAS
153
+ // ============================================================================
154
+ export const combatParticipantSchema = z.object({
155
+ characterId: z.string(),
156
+ initiative: z.number(),
157
+ isActive: z.boolean(),
158
+ });
159
+ export const combatOutputSchema = {
160
+ id: z.string(),
161
+ gameId: z.string(),
162
+ locationId: z.string(),
163
+ participants: z.array(combatParticipantSchema),
164
+ currentTurn: z.number(),
165
+ round: z.number(),
166
+ status: z.enum(["active", "resolved"]),
167
+ log: z.array(z.string()),
168
+ };
169
+ // ============================================================================
170
+ // DICE SCHEMAS
171
+ // ============================================================================
172
+ export const diceRollOutputSchema = {
173
+ expression: z.string(),
174
+ rolls: z.array(z.number()),
175
+ modifier: z.number(),
176
+ total: z.number(),
177
+ };
178
+ export const checkResultOutputSchema = {
179
+ roll: z.object({
180
+ expression: z.string(),
181
+ rolls: z.array(z.number()),
182
+ modifier: z.number(),
183
+ total: z.number(),
184
+ }),
185
+ modifier: z.number(),
186
+ total: z.number(),
187
+ difficulty: z.number(),
188
+ success: z.boolean(),
189
+ criticalSuccess: z.boolean(),
190
+ criticalFailure: z.boolean(),
191
+ margin: z.number(),
192
+ };
193
+ // ============================================================================
194
+ // ITEM SCHEMAS
195
+ // ============================================================================
196
+ export const itemOutputSchema = {
197
+ id: z.string(),
198
+ gameId: z.string(),
199
+ ownerId: z.string(),
200
+ ownerType: z.enum(["character", "location"]),
201
+ name: z.string(),
202
+ properties: z.object({
203
+ description: z.string(),
204
+ type: z.string(),
205
+ weight: z.number().optional(),
206
+ value: z.number().optional(),
207
+ effects: z.array(z.string()).optional(),
208
+ }),
209
+ };
210
+ export const inventoryOutputSchema = {
211
+ ownerId: z.string(),
212
+ ownerType: z.enum(["character", "location"]),
213
+ items: z.array(z.object({
214
+ id: z.string(),
215
+ name: z.string(),
216
+ properties: z.object({
217
+ description: z.string(),
218
+ type: z.string(),
219
+ }),
220
+ })),
221
+ count: z.number(),
222
+ };
223
+ // ============================================================================
224
+ // NARRATIVE SCHEMAS
225
+ // ============================================================================
226
+ export const narrativeEventOutputSchema = {
227
+ id: z.string(),
228
+ gameId: z.string(),
229
+ eventType: z.string(),
230
+ content: z.string(),
231
+ timestamp: z.string(),
232
+ };
233
+ export const narrativeSummaryOutputSchema = {
234
+ totalEvents: z.number(),
235
+ firstEvent: z.string().nullable(),
236
+ lastEvent: z.string().nullable(),
237
+ eventTypes: z.record(z.string(), z.number()),
238
+ recentEvents: z.array(z.object({
239
+ id: z.string(),
240
+ eventType: z.string(),
241
+ content: z.string(),
242
+ timestamp: z.string(),
243
+ })),
244
+ };
245
+ // ============================================================================
246
+ // MAP SCHEMAS
247
+ // ============================================================================
248
+ export const mapOutputSchema = {
249
+ nodes: z.array(z.object({
250
+ id: z.string(),
251
+ name: z.string(),
252
+ hasPlayer: z.boolean(),
253
+ exits: z.array(z.object({
254
+ direction: z.string(),
255
+ destinationId: z.string(),
256
+ })),
257
+ })),
258
+ connections: z.array(z.object({
259
+ from: z.string(),
260
+ to: z.string(),
261
+ direction: z.string(),
262
+ })),
263
+ bounds: z.object({
264
+ minX: z.number(),
265
+ maxX: z.number(),
266
+ minY: z.number(),
267
+ maxY: z.number(),
268
+ }),
269
+ playerLocation: z.string().optional(),
270
+ };
271
+ // ============================================================================
272
+ // RESOURCE SCHEMAS
273
+ // ============================================================================
274
+ export const resourceOutputSchema = {
275
+ id: z.string(),
276
+ gameId: z.string(),
277
+ ownerId: z.string().nullable(),
278
+ ownerType: z.enum(["game", "character"]),
279
+ name: z.string(),
280
+ description: z.string(),
281
+ category: z.string().nullable(),
282
+ value: z.number(),
283
+ minValue: z.number().nullable(),
284
+ maxValue: z.number().nullable(),
285
+ };
286
+ // ============================================================================
287
+ // CONDITION/STATUS EFFECT SCHEMAS
288
+ // ============================================================================
289
+ export const conditionModifyOutputSchema = {
290
+ characterId: z.string(),
291
+ characterName: z.string(),
292
+ conditions: z.array(z.string()),
293
+ action: z.enum(["added", "removed", "modified"]),
294
+ added: z.array(z.string()),
295
+ removed: z.array(z.string()),
296
+ };
297
+ export const statusEffectOutputSchema = {
298
+ id: z.string(),
299
+ targetId: z.string(),
300
+ name: z.string(),
301
+ description: z.string(),
302
+ effectType: z.enum(["buff", "debuff", "neutral"]).nullable(),
303
+ duration: z.number().nullable(),
304
+ stacks: z.number(),
305
+ };
306
+ // ============================================================================
307
+ // TAG SCHEMAS
308
+ // ============================================================================
309
+ export const tagModifyOutputSchema = {
310
+ entityId: z.string(),
311
+ entityType: z.string(),
312
+ tags: z.array(z.string()),
313
+ action: z.enum(["added", "removed"]),
314
+ tag: z.string(),
315
+ };
316
+ // ============================================================================
317
+ // IMAGE SCHEMAS
318
+ // ============================================================================
319
+ export const storedImageOutputSchema = {
320
+ id: z.string(),
321
+ gameId: z.string(),
322
+ entityId: z.string(),
323
+ entityType: z.string(), // Flexible: character, location, item, scene, faction, quest, ability, etc.
324
+ fileSize: z.number(),
325
+ mimeType: z.string(),
326
+ width: z.number().nullable(),
327
+ height: z.number().nullable(),
328
+ label: z.string().nullable(),
329
+ isPrimary: z.boolean(),
330
+ createdAt: z.string(),
331
+ };
@@ -0,0 +1,147 @@
1
+ import type { ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
2
+ /**
3
+ * Pre-defined tool annotation sets for common patterns.
4
+ * These follow MCP best practices for describing tool behavior.
5
+ *
6
+ * Per the MCP spec:
7
+ * - readOnlyHint: If true, the tool does not modify its environment (default: false)
8
+ * - destructiveHint: If true, the tool may perform destructive updates (default: true when readOnlyHint is false)
9
+ * - idempotentHint: If true, calling the tool multiple times with same args has same effect as calling once
10
+ * - openWorldHint: If true, the tool may interact with an "open world" of external entities
11
+ */
12
+ /**
13
+ * Read-only operations that don't modify state.
14
+ * Examples: get_character, list_locations, render_map
15
+ */
16
+ export declare const READ_ONLY: ToolAnnotations;
17
+ /**
18
+ * Operations that create new entities.
19
+ * Examples: create_game, create_character, create_location
20
+ */
21
+ export declare const CREATE: ToolAnnotations;
22
+ /**
23
+ * Operations that update existing entities.
24
+ * Examples: update_character, move_character, apply_damage
25
+ */
26
+ export declare const UPDATE: ToolAnnotations;
27
+ /**
28
+ * Idempotent update operations where repeated calls have the same effect.
29
+ * Examples: set_rules, set_time (setting to same value)
30
+ */
31
+ export declare const IDEMPOTENT_UPDATE: ToolAnnotations;
32
+ /**
33
+ * Operations that delete or remove entities permanently.
34
+ * These should trigger human-in-the-loop confirmation in MCP clients.
35
+ * Examples: delete_game, delete_character, remove_combatant
36
+ */
37
+ export declare const DESTRUCTIVE: ToolAnnotations;
38
+ /**
39
+ * Operations that connect to external systems.
40
+ * Examples: store_image with URL fetching
41
+ */
42
+ export declare const EXTERNAL: ToolAnnotations;
43
+ /**
44
+ * Read-only operations that connect to external systems.
45
+ * Examples: fetching external images for display
46
+ */
47
+ export declare const EXTERNAL_READ: ToolAnnotations;
48
+ /**
49
+ * Helper to merge annotation sets with custom overrides.
50
+ */
51
+ export declare function withAnnotations(base: ToolAnnotations, overrides: Partial<ToolAnnotations>): ToolAnnotations;
52
+ /**
53
+ * Annotation sets organized by tool category for easy reference.
54
+ */
55
+ export declare const ANNOTATIONS: {
56
+ readonly READ_ONLY: {
57
+ title?: string | undefined;
58
+ readOnlyHint?: boolean | undefined;
59
+ destructiveHint?: boolean | undefined;
60
+ idempotentHint?: boolean | undefined;
61
+ openWorldHint?: boolean | undefined;
62
+ };
63
+ readonly CREATE: {
64
+ title?: string | undefined;
65
+ readOnlyHint?: boolean | undefined;
66
+ destructiveHint?: boolean | undefined;
67
+ idempotentHint?: boolean | undefined;
68
+ openWorldHint?: boolean | undefined;
69
+ };
70
+ readonly UPDATE: {
71
+ title?: string | undefined;
72
+ readOnlyHint?: boolean | undefined;
73
+ destructiveHint?: boolean | undefined;
74
+ idempotentHint?: boolean | undefined;
75
+ openWorldHint?: boolean | undefined;
76
+ };
77
+ readonly IDEMPOTENT_UPDATE: {
78
+ title?: string | undefined;
79
+ readOnlyHint?: boolean | undefined;
80
+ destructiveHint?: boolean | undefined;
81
+ idempotentHint?: boolean | undefined;
82
+ openWorldHint?: boolean | undefined;
83
+ };
84
+ readonly DESTRUCTIVE: {
85
+ title?: string | undefined;
86
+ readOnlyHint?: boolean | undefined;
87
+ destructiveHint?: boolean | undefined;
88
+ idempotentHint?: boolean | undefined;
89
+ openWorldHint?: boolean | undefined;
90
+ };
91
+ readonly EXTERNAL: {
92
+ title?: string | undefined;
93
+ readOnlyHint?: boolean | undefined;
94
+ destructiveHint?: boolean | undefined;
95
+ idempotentHint?: boolean | undefined;
96
+ openWorldHint?: boolean | undefined;
97
+ };
98
+ readonly EXTERNAL_READ: {
99
+ title?: string | undefined;
100
+ readOnlyHint?: boolean | undefined;
101
+ destructiveHint?: boolean | undefined;
102
+ idempotentHint?: boolean | undefined;
103
+ openWorldHint?: boolean | undefined;
104
+ };
105
+ readonly GET: {
106
+ title?: string | undefined;
107
+ readOnlyHint?: boolean | undefined;
108
+ destructiveHint?: boolean | undefined;
109
+ idempotentHint?: boolean | undefined;
110
+ openWorldHint?: boolean | undefined;
111
+ };
112
+ readonly LIST: {
113
+ title?: string | undefined;
114
+ readOnlyHint?: boolean | undefined;
115
+ destructiveHint?: boolean | undefined;
116
+ idempotentHint?: boolean | undefined;
117
+ openWorldHint?: boolean | undefined;
118
+ };
119
+ readonly RENDER: {
120
+ title?: string | undefined;
121
+ readOnlyHint?: boolean | undefined;
122
+ destructiveHint?: boolean | undefined;
123
+ idempotentHint?: boolean | undefined;
124
+ openWorldHint?: boolean | undefined;
125
+ };
126
+ readonly DELETE: {
127
+ title?: string | undefined;
128
+ readOnlyHint?: boolean | undefined;
129
+ destructiveHint?: boolean | undefined;
130
+ idempotentHint?: boolean | undefined;
131
+ openWorldHint?: boolean | undefined;
132
+ };
133
+ readonly REMOVE: {
134
+ title?: string | undefined;
135
+ readOnlyHint?: boolean | undefined;
136
+ destructiveHint?: boolean | undefined;
137
+ idempotentHint?: boolean | undefined;
138
+ openWorldHint?: boolean | undefined;
139
+ };
140
+ readonly SET: {
141
+ title?: string | undefined;
142
+ readOnlyHint?: boolean | undefined;
143
+ destructiveHint?: boolean | undefined;
144
+ idempotentHint?: boolean | undefined;
145
+ openWorldHint?: boolean | undefined;
146
+ };
147
+ };
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Pre-defined tool annotation sets for common patterns.
3
+ * These follow MCP best practices for describing tool behavior.
4
+ *
5
+ * Per the MCP spec:
6
+ * - readOnlyHint: If true, the tool does not modify its environment (default: false)
7
+ * - destructiveHint: If true, the tool may perform destructive updates (default: true when readOnlyHint is false)
8
+ * - idempotentHint: If true, calling the tool multiple times with same args has same effect as calling once
9
+ * - openWorldHint: If true, the tool may interact with an "open world" of external entities
10
+ */
11
+ /**
12
+ * Read-only operations that don't modify state.
13
+ * Examples: get_character, list_locations, render_map
14
+ */
15
+ export const READ_ONLY = {
16
+ readOnlyHint: true,
17
+ };
18
+ /**
19
+ * Operations that create new entities.
20
+ * Examples: create_game, create_character, create_location
21
+ */
22
+ export const CREATE = {
23
+ readOnlyHint: false,
24
+ destructiveHint: false, // Additive, not destructive
25
+ idempotentHint: false, // Creates new entity each time
26
+ };
27
+ /**
28
+ * Operations that update existing entities.
29
+ * Examples: update_character, move_character, apply_damage
30
+ */
31
+ export const UPDATE = {
32
+ readOnlyHint: false,
33
+ destructiveHint: false, // Updates, not deletes
34
+ idempotentHint: false, // State changes with each call
35
+ };
36
+ /**
37
+ * Idempotent update operations where repeated calls have the same effect.
38
+ * Examples: set_rules, set_time (setting to same value)
39
+ */
40
+ export const IDEMPOTENT_UPDATE = {
41
+ readOnlyHint: false,
42
+ destructiveHint: false,
43
+ idempotentHint: true,
44
+ };
45
+ /**
46
+ * Operations that delete or remove entities permanently.
47
+ * These should trigger human-in-the-loop confirmation in MCP clients.
48
+ * Examples: delete_game, delete_character, remove_combatant
49
+ */
50
+ export const DESTRUCTIVE = {
51
+ readOnlyHint: false,
52
+ destructiveHint: true,
53
+ idempotentHint: true, // Deleting twice has same effect as deleting once
54
+ };
55
+ /**
56
+ * Operations that connect to external systems.
57
+ * Examples: store_image with URL fetching
58
+ */
59
+ export const EXTERNAL = {
60
+ readOnlyHint: false,
61
+ openWorldHint: true,
62
+ };
63
+ /**
64
+ * Read-only operations that connect to external systems.
65
+ * Examples: fetching external images for display
66
+ */
67
+ export const EXTERNAL_READ = {
68
+ readOnlyHint: true,
69
+ openWorldHint: true,
70
+ };
71
+ /**
72
+ * Helper to merge annotation sets with custom overrides.
73
+ */
74
+ export function withAnnotations(base, overrides) {
75
+ return { ...base, ...overrides };
76
+ }
77
+ /**
78
+ * Annotation sets organized by tool category for easy reference.
79
+ */
80
+ export const ANNOTATIONS = {
81
+ // Read operations
82
+ READ_ONLY,
83
+ // Write operations
84
+ CREATE,
85
+ UPDATE,
86
+ IDEMPOTENT_UPDATE,
87
+ DESTRUCTIVE,
88
+ // External operations
89
+ EXTERNAL,
90
+ EXTERNAL_READ,
91
+ // Convenience aliases
92
+ GET: READ_ONLY,
93
+ LIST: READ_ONLY,
94
+ RENDER: READ_ONLY,
95
+ DELETE: DESTRUCTIVE,
96
+ REMOVE: DESTRUCTIVE,
97
+ SET: IDEMPOTENT_UPDATE,
98
+ };
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Common input length limits for security and performance.
4
+ * These prevent DoS attacks via extremely large inputs.
5
+ */
6
+ export declare const LIMITS: {
7
+ readonly NAME_MAX: 200;
8
+ readonly DESCRIPTION_MAX: 5000;
9
+ readonly CONTENT_MAX: 50000;
10
+ readonly NARRATIVE_MAX: 200000;
11
+ readonly ARRAY_MAX: 100;
12
+ readonly MAX_DEPTH: 10;
13
+ };
14
+ /**
15
+ * Pre-built Zod schemas with length limits
16
+ */
17
+ export declare const validatedSchemas: {
18
+ readonly name: z.ZodString;
19
+ readonly description: z.ZodString;
20
+ readonly content: z.ZodString;
21
+ readonly narrative: z.ZodString;
22
+ readonly id: z.ZodString;
23
+ readonly tag: z.ZodString;
24
+ readonly stringArray: z.ZodArray<z.ZodString, "many">;
25
+ readonly tagArray: z.ZodArray<z.ZodString, "many">;
26
+ };
27
+ /**
28
+ * Helper to create a bounded string schema
29
+ */
30
+ export declare function boundedString(maxLength?: number): z.ZodString;
31
+ /**
32
+ * Helper to create a bounded array schema
33
+ */
34
+ export declare function boundedArray<T extends z.ZodType>(schema: T, maxItems?: number): z.ZodArray<T, "many">;
@@ -0,0 +1,52 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Common input length limits for security and performance.
4
+ * These prevent DoS attacks via extremely large inputs.
5
+ */
6
+ export const LIMITS = {
7
+ // Short text fields (names, titles)
8
+ NAME_MAX: 200,
9
+ // Medium text fields (descriptions)
10
+ DESCRIPTION_MAX: 5000,
11
+ // Long text fields (notes, content)
12
+ CONTENT_MAX: 50000,
13
+ // Very long text fields (story exports, narrative)
14
+ NARRATIVE_MAX: 200000,
15
+ // Array limits
16
+ ARRAY_MAX: 100,
17
+ // JSON object depth limit (for nested structures)
18
+ MAX_DEPTH: 10,
19
+ };
20
+ /**
21
+ * Pre-built Zod schemas with length limits
22
+ */
23
+ export const validatedSchemas = {
24
+ // Name fields (character names, location names, etc.)
25
+ name: z.string().min(1).max(LIMITS.NAME_MAX),
26
+ // Description fields
27
+ description: z.string().max(LIMITS.DESCRIPTION_MAX),
28
+ // Content fields (notes, large text)
29
+ content: z.string().max(LIMITS.CONTENT_MAX),
30
+ // Narrative content (very large text allowed)
31
+ narrative: z.string().max(LIMITS.NARRATIVE_MAX),
32
+ // ID fields (UUIDs are 36 characters)
33
+ id: z.string().max(100),
34
+ // Tag/category strings
35
+ tag: z.string().min(1).max(100),
36
+ // Array of strings with limits
37
+ stringArray: z.array(z.string().max(LIMITS.NAME_MAX)).max(LIMITS.ARRAY_MAX),
38
+ // Array of tags
39
+ tagArray: z.array(z.string().min(1).max(100)).max(LIMITS.ARRAY_MAX),
40
+ };
41
+ /**
42
+ * Helper to create a bounded string schema
43
+ */
44
+ export function boundedString(maxLength = LIMITS.NAME_MAX) {
45
+ return z.string().max(maxLength);
46
+ }
47
+ /**
48
+ * Helper to create a bounded array schema
49
+ */
50
+ export function boundedArray(schema, maxItems = LIMITS.ARRAY_MAX) {
51
+ return z.array(schema).max(maxItems);
52
+ }