@mythxengine/mcp-server 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.
- package/LICENSE +21 -0
- package/dist/__tests__/assemble.test.d.ts +2 -0
- package/dist/__tests__/assemble.test.d.ts.map +1 -0
- package/dist/__tests__/assemble.test.js +81 -0
- package/dist/__tests__/assemble.test.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/index.d.ts +9 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +202 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/server.d.ts +41 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +91 -0
- package/dist/server.js.map +1 -0
- package/dist/state/manager.d.ts +88 -0
- package/dist/state/manager.d.ts.map +1 -0
- package/dist/state/manager.js +308 -0
- package/dist/state/manager.js.map +1 -0
- package/dist/state/rules.d.ts +30 -0
- package/dist/state/rules.d.ts.map +1 -0
- package/dist/state/rules.js +61 -0
- package/dist/state/rules.js.map +1 -0
- package/dist/state/worldpacks.d.ts +43 -0
- package/dist/state/worldpacks.d.ts.map +1 -0
- package/dist/state/worldpacks.js +125 -0
- package/dist/state/worldpacks.js.map +1 -0
- package/dist/tools/augmentation/augment.d.ts +15 -0
- package/dist/tools/augmentation/augment.d.ts.map +1 -0
- package/dist/tools/augmentation/augment.js +512 -0
- package/dist/tools/augmentation/augment.js.map +1 -0
- package/dist/tools/augmentation/index.d.ts +6 -0
- package/dist/tools/augmentation/index.d.ts.map +1 -0
- package/dist/tools/augmentation/index.js +7 -0
- package/dist/tools/augmentation/index.js.map +1 -0
- package/dist/tools/characters.d.ts +26 -0
- package/dist/tools/characters.d.ts.map +1 -0
- package/dist/tools/characters.js +362 -0
- package/dist/tools/characters.js.map +1 -0
- package/dist/tools/clocks.d.ts +33 -0
- package/dist/tools/clocks.d.ts.map +1 -0
- package/dist/tools/clocks.js +438 -0
- package/dist/tools/clocks.js.map +1 -0
- package/dist/tools/combat.d.ts +38 -0
- package/dist/tools/combat.d.ts.map +1 -0
- package/dist/tools/combat.js +574 -0
- package/dist/tools/combat.js.map +1 -0
- package/dist/tools/dice.d.ts +9 -0
- package/dist/tools/dice.d.ts.map +1 -0
- package/dist/tools/dice.js +287 -0
- package/dist/tools/dice.js.map +1 -0
- package/dist/tools/encounters.d.ts +21 -0
- package/dist/tools/encounters.d.ts.map +1 -0
- package/dist/tools/encounters.js +521 -0
- package/dist/tools/encounters.js.map +1 -0
- package/dist/tools/engagement.d.ts +25 -0
- package/dist/tools/engagement.d.ts.map +1 -0
- package/dist/tools/engagement.js +491 -0
- package/dist/tools/engagement.js.map +1 -0
- package/dist/tools/expansion/archetype.d.ts +12 -0
- package/dist/tools/expansion/archetype.d.ts.map +1 -0
- package/dist/tools/expansion/archetype.js +157 -0
- package/dist/tools/expansion/archetype.js.map +1 -0
- package/dist/tools/expansion/index.d.ts +12 -0
- package/dist/tools/expansion/index.d.ts.map +1 -0
- package/dist/tools/expansion/index.js +21 -0
- package/dist/tools/expansion/index.js.map +1 -0
- package/dist/tools/expansion/location.d.ts +12 -0
- package/dist/tools/expansion/location.d.ts.map +1 -0
- package/dist/tools/expansion/location.js +149 -0
- package/dist/tools/expansion/location.js.map +1 -0
- package/dist/tools/expansion/monster.d.ts +12 -0
- package/dist/tools/expansion/monster.d.ts.map +1 -0
- package/dist/tools/expansion/monster.js +157 -0
- package/dist/tools/expansion/monster.js.map +1 -0
- package/dist/tools/expansion/npc.d.ts +12 -0
- package/dist/tools/expansion/npc.d.ts.map +1 -0
- package/dist/tools/expansion/npc.js +153 -0
- package/dist/tools/expansion/npc.js.map +1 -0
- package/dist/tools/generation/archetypes.d.ts +12 -0
- package/dist/tools/generation/archetypes.d.ts.map +1 -0
- package/dist/tools/generation/archetypes.js +129 -0
- package/dist/tools/generation/archetypes.js.map +1 -0
- package/dist/tools/generation/arcs.d.ts +13 -0
- package/dist/tools/generation/arcs.d.ts.map +1 -0
- package/dist/tools/generation/arcs.js +186 -0
- package/dist/tools/generation/arcs.js.map +1 -0
- package/dist/tools/generation/encounters.d.ts +12 -0
- package/dist/tools/generation/encounters.d.ts.map +1 -0
- package/dist/tools/generation/encounters.js +169 -0
- package/dist/tools/generation/encounters.js.map +1 -0
- package/dist/tools/generation/index.d.ts +19 -0
- package/dist/tools/generation/index.d.ts.map +1 -0
- package/dist/tools/generation/index.js +42 -0
- package/dist/tools/generation/index.js.map +1 -0
- package/dist/tools/generation/items.d.ts +12 -0
- package/dist/tools/generation/items.d.ts.map +1 -0
- package/dist/tools/generation/items.js +149 -0
- package/dist/tools/generation/items.js.map +1 -0
- package/dist/tools/generation/locations.d.ts +12 -0
- package/dist/tools/generation/locations.d.ts.map +1 -0
- package/dist/tools/generation/locations.js +131 -0
- package/dist/tools/generation/locations.js.map +1 -0
- package/dist/tools/generation/monsters.d.ts +12 -0
- package/dist/tools/generation/monsters.d.ts.map +1 -0
- package/dist/tools/generation/monsters.js +154 -0
- package/dist/tools/generation/monsters.js.map +1 -0
- package/dist/tools/generation/narrative.d.ts +12 -0
- package/dist/tools/generation/narrative.d.ts.map +1 -0
- package/dist/tools/generation/narrative.js +129 -0
- package/dist/tools/generation/narrative.js.map +1 -0
- package/dist/tools/generation/npcs.d.ts +12 -0
- package/dist/tools/generation/npcs.d.ts.map +1 -0
- package/dist/tools/generation/npcs.js +136 -0
- package/dist/tools/generation/npcs.js.map +1 -0
- package/dist/tools/generation/resume.d.ts +12 -0
- package/dist/tools/generation/resume.d.ts.map +1 -0
- package/dist/tools/generation/resume.js +288 -0
- package/dist/tools/generation/resume.js.map +1 -0
- package/dist/tools/generation/rules-prompt.d.ts +23 -0
- package/dist/tools/generation/rules-prompt.d.ts.map +1 -0
- package/dist/tools/generation/rules-prompt.js +209 -0
- package/dist/tools/generation/rules-prompt.js.map +1 -0
- package/dist/tools/generation/seed.d.ts +12 -0
- package/dist/tools/generation/seed.d.ts.map +1 -0
- package/dist/tools/generation/seed.js +171 -0
- package/dist/tools/generation/seed.js.map +1 -0
- package/dist/tools/generation/situations.d.ts +13 -0
- package/dist/tools/generation/situations.d.ts.map +1 -0
- package/dist/tools/generation/situations.js +247 -0
- package/dist/tools/generation/situations.js.map +1 -0
- package/dist/tools/gm-guidance.d.ts +13 -0
- package/dist/tools/gm-guidance.d.ts.map +1 -0
- package/dist/tools/gm-guidance.js +395 -0
- package/dist/tools/gm-guidance.js.map +1 -0
- package/dist/tools/index.d.ts +33 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +80 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/investigation.d.ts +41 -0
- package/dist/tools/investigation.d.ts.map +1 -0
- package/dist/tools/investigation.js +586 -0
- package/dist/tools/investigation.js.map +1 -0
- package/dist/tools/leads.d.ts +29 -0
- package/dist/tools/leads.d.ts.map +1 -0
- package/dist/tools/leads.js +460 -0
- package/dist/tools/leads.js.map +1 -0
- package/dist/tools/players.d.ts +30 -0
- package/dist/tools/players.d.ts.map +1 -0
- package/dist/tools/players.js +448 -0
- package/dist/tools/players.js.map +1 -0
- package/dist/tools/portable-clues.d.ts +29 -0
- package/dist/tools/portable-clues.d.ts.map +1 -0
- package/dist/tools/portable-clues.js +490 -0
- package/dist/tools/portable-clues.js.map +1 -0
- package/dist/tools/relationships.d.ts +29 -0
- package/dist/tools/relationships.d.ts.map +1 -0
- package/dist/tools/relationships.js +471 -0
- package/dist/tools/relationships.js.map +1 -0
- package/dist/tools/scene-framing.d.ts +21 -0
- package/dist/tools/scene-framing.d.ts.map +1 -0
- package/dist/tools/scene-framing.js +380 -0
- package/dist/tools/scene-framing.js.map +1 -0
- package/dist/tools/sessions.d.ts +30 -0
- package/dist/tools/sessions.d.ts.map +1 -0
- package/dist/tools/sessions.js +253 -0
- package/dist/tools/sessions.js.map +1 -0
- package/dist/tools/time.d.ts +26 -0
- package/dist/tools/time.d.ts.map +1 -0
- package/dist/tools/time.js +438 -0
- package/dist/tools/time.js.map +1 -0
- package/dist/tools/turns.d.ts +38 -0
- package/dist/tools/turns.d.ts.map +1 -0
- package/dist/tools/turns.js +560 -0
- package/dist/tools/turns.js.map +1 -0
- package/dist/tools/worldpack/assemble.d.ts +20 -0
- package/dist/tools/worldpack/assemble.d.ts.map +1 -0
- package/dist/tools/worldpack/assemble.js +237 -0
- package/dist/tools/worldpack/assemble.js.map +1 -0
- package/dist/tools/worldpack/docs-generator.d.ts +18 -0
- package/dist/tools/worldpack/docs-generator.d.ts.map +1 -0
- package/dist/tools/worldpack/docs-generator.js +264 -0
- package/dist/tools/worldpack/docs-generator.js.map +1 -0
- package/dist/tools/worldpack/export.d.ts +12 -0
- package/dist/tools/worldpack/export.d.ts.map +1 -0
- package/dist/tools/worldpack/export.js +209 -0
- package/dist/tools/worldpack/export.js.map +1 -0
- package/dist/tools/worldpack/index.d.ts +15 -0
- package/dist/tools/worldpack/index.d.ts.map +1 -0
- package/dist/tools/worldpack/index.js +30 -0
- package/dist/tools/worldpack/index.js.map +1 -0
- package/dist/tools/worldpack/lookup.d.ts +19 -0
- package/dist/tools/worldpack/lookup.d.ts.map +1 -0
- package/dist/tools/worldpack/lookup.js +320 -0
- package/dist/tools/worldpack/lookup.js.map +1 -0
- package/dist/tools/worldpack/manage.d.ts +20 -0
- package/dist/tools/worldpack/manage.d.ts.map +1 -0
- package/dist/tools/worldpack/manage.js +101 -0
- package/dist/tools/worldpack/manage.js.map +1 -0
- package/dist/tools/worldpack/save-result.d.ts +12 -0
- package/dist/tools/worldpack/save-result.d.ts.map +1 -0
- package/dist/tools/worldpack/save-result.js +222 -0
- package/dist/tools/worldpack/save-result.js.map +1 -0
- package/dist/tools/worldpack/summary.d.ts +13 -0
- package/dist/tools/worldpack/summary.d.ts.map +1 -0
- package/dist/tools/worldpack/summary.js +180 -0
- package/dist/tools/worldpack/summary.js.map +1 -0
- package/dist/tools/worldpack/validate.d.ts +12 -0
- package/dist/tools/worldpack/validate.d.ts.map +1 -0
- package/dist/tools/worldpack/validate.js +388 -0
- package/dist/tools/worldpack/validate.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Monster Generation Tool
|
|
3
|
+
*
|
|
4
|
+
* Generates monsters based on the world seed.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { randomUUID } from "crypto";
|
|
8
|
+
import { sessionManager, readManifest, writeManifest, addManifestStep, } from "../../state/manager.js";
|
|
9
|
+
import { buildRulesPromptSection, buildMonsterHPGuidelines } from "./rules-prompt.js";
|
|
10
|
+
const GenerateMonstersInput = z.object({
|
|
11
|
+
sessionId: z.string(),
|
|
12
|
+
count: z.number().min(1).max(20).optional().describe("Number of monsters to generate"),
|
|
13
|
+
threatTiers: z.array(z.enum(["minion", "standard", "elite", "boss"])).optional().describe("Filter by threat tiers"),
|
|
14
|
+
focusOn: z.array(z.string()).optional().describe("Specific monster seeds to focus on (by name)"),
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* generate_monsters tool
|
|
18
|
+
*/
|
|
19
|
+
export const generateMonstersTool = {
|
|
20
|
+
name: "generate_monsters",
|
|
21
|
+
description: "Generate monsters based on the world seed. Returns a prompt for LLM execution.",
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: "object",
|
|
24
|
+
properties: {
|
|
25
|
+
sessionId: { type: "string", description: "Session ID" },
|
|
26
|
+
count: { type: "number", description: "Number of monsters to generate" },
|
|
27
|
+
threatTiers: {
|
|
28
|
+
type: "array",
|
|
29
|
+
items: { type: "string", enum: ["minion", "standard", "elite", "boss"] },
|
|
30
|
+
description: "Filter by threat tiers"
|
|
31
|
+
},
|
|
32
|
+
focusOn: { type: "array", items: { type: "string" }, description: "Specific monster seeds to focus on" },
|
|
33
|
+
},
|
|
34
|
+
required: ["sessionId"],
|
|
35
|
+
},
|
|
36
|
+
handler: async (args) => {
|
|
37
|
+
const input = GenerateMonstersInput.parse(args);
|
|
38
|
+
const session = await sessionManager.get(input.sessionId);
|
|
39
|
+
if (!session) {
|
|
40
|
+
throw new Error(`Session not found: ${input.sessionId}`);
|
|
41
|
+
}
|
|
42
|
+
if (!session.generation?.worldSeed) {
|
|
43
|
+
throw new Error("World seed not found. Call generate_world_seed first.");
|
|
44
|
+
}
|
|
45
|
+
const worldSeed = session.generation.worldSeed;
|
|
46
|
+
const stepId = randomUUID();
|
|
47
|
+
// Filter monster seeds
|
|
48
|
+
let monsterSeeds = worldSeed.monsterSeeds;
|
|
49
|
+
if (input.focusOn) {
|
|
50
|
+
monsterSeeds = monsterSeeds.filter(m => input.focusOn.includes(m.name));
|
|
51
|
+
}
|
|
52
|
+
if (input.threatTiers) {
|
|
53
|
+
monsterSeeds = monsterSeeds.filter(m => input.threatTiers.includes(m.threat));
|
|
54
|
+
}
|
|
55
|
+
const count = input.count || monsterSeeds.length;
|
|
56
|
+
// Record the generation step
|
|
57
|
+
session.generation.history.push({
|
|
58
|
+
id: stepId,
|
|
59
|
+
type: "monsters",
|
|
60
|
+
startedAt: new Date().toISOString(),
|
|
61
|
+
completedAt: null,
|
|
62
|
+
status: "in_progress",
|
|
63
|
+
generatedIds: [],
|
|
64
|
+
});
|
|
65
|
+
session.generation.status = "generating";
|
|
66
|
+
await sessionManager.save(session);
|
|
67
|
+
// Update manifest
|
|
68
|
+
const manifest = await readManifest(input.sessionId);
|
|
69
|
+
if (manifest) {
|
|
70
|
+
addManifestStep(manifest, "monsters", "monsters.json");
|
|
71
|
+
manifest.status = "generating";
|
|
72
|
+
await writeManifest(input.sessionId, manifest);
|
|
73
|
+
}
|
|
74
|
+
// Build rules section from seed (uses defaults if no custom rules)
|
|
75
|
+
const rulesSection = buildRulesPromptSection(worldSeed.rules);
|
|
76
|
+
const monsterHPGuidelines = buildMonsterHPGuidelines(worldSeed.rules);
|
|
77
|
+
const systemPrompt = `You are a monster designer for tabletop RPGs. Create dangerous, memorable creatures that challenge players and fit the world's tone.
|
|
78
|
+
|
|
79
|
+
${rulesSection}
|
|
80
|
+
|
|
81
|
+
${monsterHPGuidelines}
|
|
82
|
+
|
|
83
|
+
Design Guidelines:
|
|
84
|
+
- Armor: 0-1 for most, 2-3 for heavily armored
|
|
85
|
+
- Each monster needs 1-3 attacks with damage dice (d4, d6, d8, d10, d12)
|
|
86
|
+
- Include morale, tactics, lore, and narrative text
|
|
87
|
+
- Special abilities should be interesting but not overwhelming
|
|
88
|
+
|
|
89
|
+
Output valid JSON only.`;
|
|
90
|
+
const userPrompt = `Generate ${count} monsters for this world:
|
|
91
|
+
|
|
92
|
+
World: ${worldSeed.name}
|
|
93
|
+
Tone: ${worldSeed.aesthetic.tone}
|
|
94
|
+
Themes: ${worldSeed.aesthetic.themes.join(", ")}
|
|
95
|
+
Visual Style: ${worldSeed.aesthetic.visualStyle}
|
|
96
|
+
Core Conflict: ${worldSeed.coreConflict}
|
|
97
|
+
Lethality: ${worldSeed.settings.lethality}
|
|
98
|
+
Supernatural Presence: ${worldSeed.settings.supernaturalPresence}
|
|
99
|
+
|
|
100
|
+
Monster seeds to develop:
|
|
101
|
+
${monsterSeeds.slice(0, count).map((m, i) => `${i + 1}. ${m.name} (${m.threat}): ${m.concept}`).join("\n")}
|
|
102
|
+
|
|
103
|
+
Output a JSON object:
|
|
104
|
+
{
|
|
105
|
+
"monsters": [
|
|
106
|
+
{
|
|
107
|
+
"id": "monster:slug-name",
|
|
108
|
+
"name": "Monster Name",
|
|
109
|
+
"description": "Physical description",
|
|
110
|
+
"hp": 10,
|
|
111
|
+
"armor": 0,
|
|
112
|
+
"abilities": { "STR": 0, "AGI": 0, "WIT": -2, "CON": 0 },
|
|
113
|
+
"threat": "minion|standard|elite|boss",
|
|
114
|
+
"attacks": [
|
|
115
|
+
{
|
|
116
|
+
"name": "Attack Name",
|
|
117
|
+
"ability": "STR|AGI|WIT|CON",
|
|
118
|
+
"damage": "d6",
|
|
119
|
+
"properties": ["optional", "tags"],
|
|
120
|
+
"flavor": "Narrative description of the attack"
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
"specialAbilities": ["Description of special ability"],
|
|
124
|
+
"morale": {
|
|
125
|
+
"threshold": 5,
|
|
126
|
+
"checkWhen": "belowHalfHP|allyDies|firstHit|never",
|
|
127
|
+
"fleesBelowHP": 3
|
|
128
|
+
},
|
|
129
|
+
"tactics": {
|
|
130
|
+
"preferredRange": "melee|ranged|any",
|
|
131
|
+
"targetPriority": "weakest|strongest|nearest|random",
|
|
132
|
+
"specialBehavior": "Optional tactical notes"
|
|
133
|
+
},
|
|
134
|
+
"lore": "World lore about this creature",
|
|
135
|
+
"encounterText": "Narrative text when first encountered",
|
|
136
|
+
"deathText": "Narrative text when defeated"
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
Return ONLY the JSON object, no markdown formatting.`;
|
|
142
|
+
return {
|
|
143
|
+
prompt: {
|
|
144
|
+
system: systemPrompt,
|
|
145
|
+
user: userPrompt,
|
|
146
|
+
outputSchemaName: "WorldMonster[]",
|
|
147
|
+
},
|
|
148
|
+
stepId,
|
|
149
|
+
message: `Monster generation initiated for ${count} monsters. Execute the prompt and call save_generation_result.`,
|
|
150
|
+
};
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
export const monsterTools = [generateMonstersTool];
|
|
154
|
+
//# sourceMappingURL=monsters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monsters.js","sourceRoot":"","sources":["../../../src/tools/generation/monsters.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Narrative Generation Tool
|
|
3
|
+
*
|
|
4
|
+
* Generates narrative guidance based on the world seed.
|
|
5
|
+
*/
|
|
6
|
+
import type { MCPToolEntry } from "@mythxengine/types";
|
|
7
|
+
/**
|
|
8
|
+
* generate_narrative tool
|
|
9
|
+
*/
|
|
10
|
+
export declare const generateNarrativeTool: MCPToolEntry;
|
|
11
|
+
export declare const narrativeTools: MCPToolEntry[];
|
|
12
|
+
//# sourceMappingURL=narrative.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"narrative.d.ts","sourceRoot":"","sources":["../../../src/tools/generation/narrative.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAYvD;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,YAiInC,CAAC;AAEF,eAAO,MAAM,cAAc,gBAA0B,CAAC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Narrative Generation Tool
|
|
3
|
+
*
|
|
4
|
+
* Generates narrative guidance based on the world seed.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { randomUUID } from "crypto";
|
|
8
|
+
import { sessionManager, readManifest, writeManifest, addManifestStep, } from "../../state/manager.js";
|
|
9
|
+
const GenerateNarrativeInput = z.object({
|
|
10
|
+
sessionId: z.string(),
|
|
11
|
+
});
|
|
12
|
+
/**
|
|
13
|
+
* generate_narrative tool
|
|
14
|
+
*/
|
|
15
|
+
export const generateNarrativeTool = {
|
|
16
|
+
name: "generate_narrative",
|
|
17
|
+
description: "Generate narrative guidance (opening scenes, plot hooks, conflicts) based on the world seed. Returns a prompt for LLM execution.",
|
|
18
|
+
inputSchema: {
|
|
19
|
+
type: "object",
|
|
20
|
+
properties: {
|
|
21
|
+
sessionId: { type: "string", description: "Session ID" },
|
|
22
|
+
},
|
|
23
|
+
required: ["sessionId"],
|
|
24
|
+
},
|
|
25
|
+
handler: async (args) => {
|
|
26
|
+
const input = GenerateNarrativeInput.parse(args);
|
|
27
|
+
const session = await sessionManager.get(input.sessionId);
|
|
28
|
+
if (!session) {
|
|
29
|
+
throw new Error(`Session not found: ${input.sessionId}`);
|
|
30
|
+
}
|
|
31
|
+
if (!session.generation?.worldSeed) {
|
|
32
|
+
throw new Error("World seed not found. Call generate_world_seed first.");
|
|
33
|
+
}
|
|
34
|
+
const worldSeed = session.generation.worldSeed;
|
|
35
|
+
const stepId = randomUUID();
|
|
36
|
+
// Record the generation step
|
|
37
|
+
session.generation.history.push({
|
|
38
|
+
id: stepId,
|
|
39
|
+
type: "narrative",
|
|
40
|
+
startedAt: new Date().toISOString(),
|
|
41
|
+
completedAt: null,
|
|
42
|
+
status: "in_progress",
|
|
43
|
+
generatedIds: [],
|
|
44
|
+
});
|
|
45
|
+
session.generation.status = "generating";
|
|
46
|
+
await sessionManager.save(session);
|
|
47
|
+
// Update manifest
|
|
48
|
+
const manifest = await readManifest(input.sessionId);
|
|
49
|
+
if (manifest) {
|
|
50
|
+
addManifestStep(manifest, "narrative", "narrative.json");
|
|
51
|
+
manifest.status = "generating";
|
|
52
|
+
await writeManifest(input.sessionId, manifest);
|
|
53
|
+
}
|
|
54
|
+
const systemPrompt = `You are a narrative designer for tabletop RPGs. Create guidance that helps GMs and AI run compelling sessions in this world.
|
|
55
|
+
|
|
56
|
+
Focus on:
|
|
57
|
+
- Opening scenes that immediately establish tone and hook players
|
|
58
|
+
- Plot hooks that connect to the core conflict
|
|
59
|
+
- Common conflicts that arise naturally from the world
|
|
60
|
+
- Resolution patterns that fit the world's tone
|
|
61
|
+
|
|
62
|
+
Output valid JSON only.`;
|
|
63
|
+
const userPrompt = `Generate narrative guidance for this world:
|
|
64
|
+
|
|
65
|
+
World: ${worldSeed.name}
|
|
66
|
+
Tagline: ${worldSeed.tagline}
|
|
67
|
+
Tone: ${worldSeed.aesthetic.tone}
|
|
68
|
+
Themes: ${worldSeed.aesthetic.themes.join(", ")}
|
|
69
|
+
Core Conflict: ${worldSeed.coreConflict}
|
|
70
|
+
|
|
71
|
+
Archetypes:
|
|
72
|
+
${worldSeed.archetypeSeeds.map(a => `- ${a.name}: ${a.concept}`).join("\n")}
|
|
73
|
+
|
|
74
|
+
Key Locations:
|
|
75
|
+
${worldSeed.locationSeeds.map(l => `- ${l.name}: ${l.concept}`).join("\n")}
|
|
76
|
+
|
|
77
|
+
Important NPCs:
|
|
78
|
+
${worldSeed.npcSeeds.map(n => `- ${n.name}: ${n.concept}`).join("\n")}
|
|
79
|
+
|
|
80
|
+
Output a JSON object:
|
|
81
|
+
{
|
|
82
|
+
"narrative": {
|
|
83
|
+
"openingScenes": [
|
|
84
|
+
"A vivid opening scene description that establishes tone",
|
|
85
|
+
"Another possible opening with different focus",
|
|
86
|
+
"A third option for variety"
|
|
87
|
+
],
|
|
88
|
+
"plotHooks": [
|
|
89
|
+
"A hook that connects to the core conflict",
|
|
90
|
+
"A hook involving key NPCs",
|
|
91
|
+
"A hook tied to a specific location",
|
|
92
|
+
"A personal hook for player characters",
|
|
93
|
+
"A mysterious hook with unanswered questions"
|
|
94
|
+
],
|
|
95
|
+
"commonConflicts": [
|
|
96
|
+
"A type of conflict that arises naturally",
|
|
97
|
+
"Another common source of tension",
|
|
98
|
+
"A recurring challenge players will face",
|
|
99
|
+
"An internal conflict characters might struggle with"
|
|
100
|
+
],
|
|
101
|
+
"resolutionPatterns": [
|
|
102
|
+
"How victories typically look in this world",
|
|
103
|
+
"What partial successes might mean",
|
|
104
|
+
"How failures manifest and their consequences",
|
|
105
|
+
"Bittersweet outcomes that fit the tone"
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
Notes:
|
|
111
|
+
- Opening scenes should be read-aloud quality
|
|
112
|
+
- Plot hooks should be immediately actionable
|
|
113
|
+
- Conflicts should feel organic to the world
|
|
114
|
+
- Resolution patterns should guide GM expectations
|
|
115
|
+
|
|
116
|
+
Return ONLY the JSON object, no markdown formatting.`;
|
|
117
|
+
return {
|
|
118
|
+
prompt: {
|
|
119
|
+
system: systemPrompt,
|
|
120
|
+
user: userPrompt,
|
|
121
|
+
outputSchemaName: "NarrativeGuidance",
|
|
122
|
+
},
|
|
123
|
+
stepId,
|
|
124
|
+
message: `Narrative guidance generation initiated. Execute the prompt and call save_generation_result.`,
|
|
125
|
+
};
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
export const narrativeTools = [generateNarrativeTool];
|
|
129
|
+
//# sourceMappingURL=narrative.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"narrative.js","sourceRoot":"","sources":["../../../src/tools/generation/narrative.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NPC Generation Tool
|
|
3
|
+
*
|
|
4
|
+
* Generates NPCs based on the world seed.
|
|
5
|
+
*/
|
|
6
|
+
import type { MCPToolEntry } from "@mythxengine/types";
|
|
7
|
+
/**
|
|
8
|
+
* generate_npcs tool
|
|
9
|
+
*/
|
|
10
|
+
export declare const generateNPCsTool: MCPToolEntry;
|
|
11
|
+
export declare const npcTools: MCPToolEntry[];
|
|
12
|
+
//# sourceMappingURL=npcs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npcs.d.ts","sourceRoot":"","sources":["../../../src/tools/generation/npcs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,oBAAoB,CAAC;AAezE;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,YAsI9B,CAAC;AAEF,eAAO,MAAM,QAAQ,gBAAqB,CAAC"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NPC Generation Tool
|
|
3
|
+
*
|
|
4
|
+
* Generates NPCs based on the world seed.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { randomUUID } from "crypto";
|
|
8
|
+
import { sessionManager, readManifest, writeManifest, addManifestStep, } from "../../state/manager.js";
|
|
9
|
+
import { buildRulesPromptSection } from "./rules-prompt.js";
|
|
10
|
+
const GenerateNPCsInput = z.object({
|
|
11
|
+
sessionId: z.string(),
|
|
12
|
+
count: z.number().min(1).max(20).optional().describe("Number of NPCs to generate (default: from world seed)"),
|
|
13
|
+
focusOn: z.array(z.string()).optional().describe("Specific NPC seeds to focus on (by name)"),
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* generate_npcs tool
|
|
17
|
+
*/
|
|
18
|
+
export const generateNPCsTool = {
|
|
19
|
+
name: "generate_npcs",
|
|
20
|
+
description: "Generate NPCs based on the world seed. Returns a prompt for LLM execution.",
|
|
21
|
+
inputSchema: {
|
|
22
|
+
type: "object",
|
|
23
|
+
properties: {
|
|
24
|
+
sessionId: { type: "string", description: "Session ID" },
|
|
25
|
+
count: { type: "number", description: "Number of NPCs to generate" },
|
|
26
|
+
focusOn: { type: "array", items: { type: "string" }, description: "Specific NPC seeds to focus on" },
|
|
27
|
+
},
|
|
28
|
+
required: ["sessionId"],
|
|
29
|
+
},
|
|
30
|
+
handler: async (args) => {
|
|
31
|
+
const input = GenerateNPCsInput.parse(args);
|
|
32
|
+
const session = await sessionManager.get(input.sessionId);
|
|
33
|
+
if (!session) {
|
|
34
|
+
throw new Error(`Session not found: ${input.sessionId}`);
|
|
35
|
+
}
|
|
36
|
+
if (!session.generation?.worldSeed) {
|
|
37
|
+
throw new Error("World seed not found. Call generate_world_seed first.");
|
|
38
|
+
}
|
|
39
|
+
const worldSeed = session.generation.worldSeed;
|
|
40
|
+
const stepId = randomUUID();
|
|
41
|
+
const npcSeeds = input.focusOn
|
|
42
|
+
? worldSeed.npcSeeds.filter(n => input.focusOn.includes(n.name))
|
|
43
|
+
: worldSeed.npcSeeds;
|
|
44
|
+
const count = input.count || npcSeeds.length;
|
|
45
|
+
// Record the generation step
|
|
46
|
+
session.generation.history.push({
|
|
47
|
+
id: stepId,
|
|
48
|
+
type: "npcs",
|
|
49
|
+
startedAt: new Date().toISOString(),
|
|
50
|
+
completedAt: null,
|
|
51
|
+
status: "in_progress",
|
|
52
|
+
generatedIds: [],
|
|
53
|
+
});
|
|
54
|
+
session.generation.status = "generating";
|
|
55
|
+
await sessionManager.save(session);
|
|
56
|
+
// Update manifest
|
|
57
|
+
const manifest = await readManifest(input.sessionId);
|
|
58
|
+
if (manifest) {
|
|
59
|
+
addManifestStep(manifest, "npcs", "npcs.json");
|
|
60
|
+
manifest.status = "generating";
|
|
61
|
+
await writeManifest(input.sessionId, manifest);
|
|
62
|
+
}
|
|
63
|
+
// Build rules section from seed (uses defaults if no custom rules)
|
|
64
|
+
const rulesSection = buildRulesPromptSection(worldSeed.rules);
|
|
65
|
+
const systemPrompt = `You are an NPC designer for tabletop RPGs. Create memorable characters with clear motivations that drive interesting interactions.
|
|
66
|
+
|
|
67
|
+
${rulesSection}
|
|
68
|
+
|
|
69
|
+
### NPC Design Guidelines
|
|
70
|
+
- Each NPC needs a clear narrative role (quest_giver, ally, obstacle, information, antagonist, merchant, background)
|
|
71
|
+
- Personality should be distinct and easy to roleplay
|
|
72
|
+
- Motivation drives their actions and creates hooks
|
|
73
|
+
- Dialogue hints help GMs voice the character
|
|
74
|
+
- Include where they can be found (location IDs)
|
|
75
|
+
- Relationships create webs of intrigue
|
|
76
|
+
- Secrets add depth and discovery opportunities
|
|
77
|
+
|
|
78
|
+
Output valid JSON only.`;
|
|
79
|
+
const userPrompt = `Generate ${count} NPCs for this world:
|
|
80
|
+
|
|
81
|
+
World: ${worldSeed.name}
|
|
82
|
+
Tone: ${worldSeed.aesthetic.tone}
|
|
83
|
+
Themes: ${worldSeed.aesthetic.themes.join(", ")}
|
|
84
|
+
Core Conflict: ${worldSeed.coreConflict}
|
|
85
|
+
|
|
86
|
+
NPC seeds to develop:
|
|
87
|
+
${npcSeeds.slice(0, count).map((n, i) => `${i + 1}. ${n.name}: ${n.concept}`).join("\n")}
|
|
88
|
+
|
|
89
|
+
Locations where NPCs might be found:
|
|
90
|
+
${worldSeed.locationSeeds.map(l => `- ${l.name}: ${l.concept}`).join("\n")}
|
|
91
|
+
|
|
92
|
+
Output a JSON object:
|
|
93
|
+
{
|
|
94
|
+
"npcs": [
|
|
95
|
+
{
|
|
96
|
+
"id": "npc:slug-name",
|
|
97
|
+
"name": "NPC Name",
|
|
98
|
+
"description": "Physical description and role",
|
|
99
|
+
"personality": "Key personality traits and quirks",
|
|
100
|
+
"motivation": "What drives this NPC's actions",
|
|
101
|
+
"attitude": "friendly|neutral|hostile|unknown",
|
|
102
|
+
"dialogueHints": [
|
|
103
|
+
"Example speech pattern or catchphrase",
|
|
104
|
+
"Topic they like to discuss",
|
|
105
|
+
"How they react to strangers"
|
|
106
|
+
],
|
|
107
|
+
"narrativeRole": "quest_giver|ally|obstacle|information|antagonist|merchant|background",
|
|
108
|
+
"locations": ["location:where-they-can-be-found"],
|
|
109
|
+
"relationships": {
|
|
110
|
+
"npc:other-npc-id": "Description of relationship"
|
|
111
|
+
},
|
|
112
|
+
"secrets": ["Something hidden about this NPC"]
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
Notes:
|
|
118
|
+
- Mix narrative roles for variety
|
|
119
|
+
- Create relationship connections between NPCs
|
|
120
|
+
- Secrets are optional but add depth
|
|
121
|
+
- Dialogue hints should make the NPC easy to voice
|
|
122
|
+
|
|
123
|
+
Return ONLY the JSON object, no markdown formatting.`;
|
|
124
|
+
return {
|
|
125
|
+
prompt: {
|
|
126
|
+
system: systemPrompt,
|
|
127
|
+
user: userPrompt,
|
|
128
|
+
outputSchemaName: "WorldNPC[]",
|
|
129
|
+
},
|
|
130
|
+
stepId,
|
|
131
|
+
message: `NPC generation initiated for ${count} NPCs. Execute the prompt and call save_generation_result.`,
|
|
132
|
+
};
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
export const npcTools = [generateNPCsTool];
|
|
136
|
+
//# sourceMappingURL=npcs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npcs.js","sourceRoot":"","sources":["../../../src/tools/generation/npcs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resume Generation Tool
|
|
3
|
+
*
|
|
4
|
+
* Resumes an interrupted world generation session from file-based state.
|
|
5
|
+
*/
|
|
6
|
+
import type { MCPToolEntry } from "@mythxengine/types";
|
|
7
|
+
/**
|
|
8
|
+
* resume_generation tool
|
|
9
|
+
*/
|
|
10
|
+
export declare const resumeGenerationTool: MCPToolEntry;
|
|
11
|
+
export declare const resumeTools: MCPToolEntry[];
|
|
12
|
+
//# sourceMappingURL=resume.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../../src/tools/generation/resume.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAsB,MAAM,oBAAoB,CAAC;AAoO3E;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,YA0GlC,CAAC;AAEF,eAAO,MAAM,WAAW,gBAAyB,CAAC"}
|