@magek/mcp-server 0.0.8
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 +42 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +25 -0
- package/dist/prompts/cqrs-flow.d.ts +15 -0
- package/dist/prompts/cqrs-flow.js +252 -0
- package/dist/prompts/troubleshooting.d.ts +15 -0
- package/dist/prompts/troubleshooting.js +239 -0
- package/dist/resources/cli-reference.d.ts +13 -0
- package/dist/resources/cli-reference.js +193 -0
- package/dist/resources/documentation.d.ts +18 -0
- package/dist/resources/documentation.js +62 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.js +127 -0
- package/dist/utils/docs-loader.d.ts +19 -0
- package/dist/utils/docs-loader.js +111 -0
- package/docs/advanced/custom-templates.md +96 -0
- package/docs/advanced/data-migrations.md +181 -0
- package/docs/advanced/environment-configuration.md +74 -0
- package/docs/advanced/framework-packages.md +17 -0
- package/docs/advanced/health/sensor-health.md +389 -0
- package/docs/advanced/instrumentation.md +135 -0
- package/docs/advanced/register.md +119 -0
- package/docs/advanced/sensor.md +10 -0
- package/docs/advanced/testing.md +96 -0
- package/docs/advanced/touch-entities.md +45 -0
- package/docs/architecture/command.md +367 -0
- package/docs/architecture/entity.md +214 -0
- package/docs/architecture/event-driven.md +30 -0
- package/docs/architecture/event-handler.md +108 -0
- package/docs/architecture/event.md +145 -0
- package/docs/architecture/notifications.md +54 -0
- package/docs/architecture/queries.md +207 -0
- package/docs/architecture/read-model.md +507 -0
- package/docs/contributing.md +349 -0
- package/docs/docs-index.json +200 -0
- package/docs/features/error-handling.md +204 -0
- package/docs/features/event-stream.md +35 -0
- package/docs/features/logging.md +81 -0
- package/docs/features/schedule-actions.md +44 -0
- package/docs/getting-started/ai-coding-assistants.md +181 -0
- package/docs/getting-started/coding.md +543 -0
- package/docs/getting-started/installation.md +143 -0
- package/docs/graphql.md +1213 -0
- package/docs/index.md +62 -0
- package/docs/introduction.md +58 -0
- package/docs/magek-arch.png +0 -0
- package/docs/magek-cli.md +67 -0
- package/docs/magek-logo.svg +1 -0
- package/docs/security/authentication.md +189 -0
- package/docs/security/authorization.md +242 -0
- package/docs/security/security.md +16 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# @magek/mcp-server
|
|
2
|
+
|
|
3
|
+
MCP server that enables AI coding assistants to build Magek applications. Provides documentation, CLI commands, and CQRS patterns to Claude Code, Codex CLI, and other MCP-compatible tools.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
**Claude Code:**
|
|
8
|
+
```bash
|
|
9
|
+
claude mcp add magek -- npx -y @magek/mcp-server
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
**Codex CLI** — add to `.codex/config.json`:
|
|
13
|
+
```json
|
|
14
|
+
{ "mcpServers": { "magek": { "command": "npx", "args": ["-y", "@magek/mcp-server"] } } }
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Other MCP tools** — add to your MCP configuration:
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"mcpServers": {
|
|
21
|
+
"magek": {
|
|
22
|
+
"command": "npx",
|
|
23
|
+
"args": ["-y", "@magek/mcp-server"]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## What It Provides
|
|
30
|
+
|
|
31
|
+
- **Documentation** — All Magek docs available as MCP resources (`magek://docs/*`)
|
|
32
|
+
- **CLI Reference** — Complete scaffolding command reference (`magek://cli/reference`)
|
|
33
|
+
- **CQRS Flow Prompt** — Step-by-step guide for implementing features
|
|
34
|
+
- **Troubleshooting Prompt** — Common issues and solutions
|
|
35
|
+
|
|
36
|
+
## Documentation
|
|
37
|
+
|
|
38
|
+
Full documentation: [magek.ai/docs/getting-started/ai-coding-assistants](https://magek.ai/docs/getting-started/ai-coding-assistants)
|
|
39
|
+
|
|
40
|
+
## License
|
|
41
|
+
|
|
42
|
+
Apache-2.0
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
5
|
+
import { createMagekServer } from './server.js';
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
// Resolve docs path - first check env var, then use bundled docs
|
|
8
|
+
function resolveDocsPath() {
|
|
9
|
+
if (process.env.MAGEK_DOCS_PATH) {
|
|
10
|
+
return process.env.MAGEK_DOCS_PATH;
|
|
11
|
+
}
|
|
12
|
+
// When installed as a package, docs are in dist/../docs
|
|
13
|
+
const bundledDocsPath = join(__dirname, '..', 'docs');
|
|
14
|
+
return bundledDocsPath;
|
|
15
|
+
}
|
|
16
|
+
async function main() {
|
|
17
|
+
const docsPath = resolveDocsPath();
|
|
18
|
+
const server = createMagekServer({ docsPath });
|
|
19
|
+
const transport = new StdioServerTransport();
|
|
20
|
+
await server.connect(transport);
|
|
21
|
+
}
|
|
22
|
+
main().catch((error) => {
|
|
23
|
+
console.error('Failed to start Magek MCP server:', error);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const CQRS_FLOW_PROMPT_NAME = "magek_cqrs_flow";
|
|
2
|
+
export declare const CQRS_FLOW_PROMPT_DESCRIPTION = "Complete guide for implementing a CQRS feature end-to-end in Magek";
|
|
3
|
+
export interface CqrsFlowArguments {
|
|
4
|
+
feature: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function getCqrsFlowPrompt(args: CqrsFlowArguments): string;
|
|
7
|
+
export declare function getCqrsFlowPromptDefinition(): {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
arguments: {
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
required: boolean;
|
|
14
|
+
}[];
|
|
15
|
+
};
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
export const CQRS_FLOW_PROMPT_NAME = 'magek_cqrs_flow';
|
|
2
|
+
export const CQRS_FLOW_PROMPT_DESCRIPTION = 'Complete guide for implementing a CQRS feature end-to-end in Magek';
|
|
3
|
+
export function getCqrsFlowPrompt(args) {
|
|
4
|
+
const { feature } = args;
|
|
5
|
+
return `# Implementing "${feature}" in Magek
|
|
6
|
+
|
|
7
|
+
Follow this guide to implement the "${feature}" feature using Magek's CQRS pattern.
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
Magek follows the CQRS (Command Query Responsibility Segregation) pattern with Event Sourcing:
|
|
12
|
+
|
|
13
|
+
\`\`\`
|
|
14
|
+
Command → Event → Entity → Read Model
|
|
15
|
+
↓ ↓ ↓ ↓
|
|
16
|
+
User Immutable State Query
|
|
17
|
+
Intent Facts Reducer Access
|
|
18
|
+
\`\`\`
|
|
19
|
+
|
|
20
|
+
## Step 1: Define the Command
|
|
21
|
+
|
|
22
|
+
Commands represent user intent. Create a command that captures what the user wants to do.
|
|
23
|
+
|
|
24
|
+
\`\`\`bash
|
|
25
|
+
npx magek new:command <CommandName> --fields <field1:type1> <field2:type2>
|
|
26
|
+
\`\`\`
|
|
27
|
+
|
|
28
|
+
**Best Practices:**
|
|
29
|
+
- Use imperative naming (Create, Update, Delete, Archive)
|
|
30
|
+
- Include only the fields needed to perform the action
|
|
31
|
+
- Commands should be named after what the user wants to do, not technical operations
|
|
32
|
+
|
|
33
|
+
**Example for "${feature}":**
|
|
34
|
+
\`\`\`typescript
|
|
35
|
+
@Command({ authorize: 'all' })
|
|
36
|
+
export class <CommandName> {
|
|
37
|
+
public constructor(
|
|
38
|
+
// Add fields that represent the command parameters
|
|
39
|
+
readonly field1: string,
|
|
40
|
+
readonly field2: number,
|
|
41
|
+
) {}
|
|
42
|
+
|
|
43
|
+
public static async handle(
|
|
44
|
+
command: <CommandName>,
|
|
45
|
+
register: Register
|
|
46
|
+
): Promise<void> {
|
|
47
|
+
// Validate the command
|
|
48
|
+
// Generate a unique ID for the entity
|
|
49
|
+
const entityId = UUID.generate()
|
|
50
|
+
|
|
51
|
+
// Register the event
|
|
52
|
+
register.events(new <EventName>(entityId, command.field1, command.field2))
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
\`\`\`
|
|
56
|
+
|
|
57
|
+
## Step 2: Define the Event
|
|
58
|
+
|
|
59
|
+
Events are immutable facts. They record what happened as a result of the command.
|
|
60
|
+
|
|
61
|
+
\`\`\`bash
|
|
62
|
+
npx magek new:event <EventName> --fields <field1:type1> <field2:type2>
|
|
63
|
+
\`\`\`
|
|
64
|
+
|
|
65
|
+
**Best Practices:**
|
|
66
|
+
- Use past tense naming (Created, Updated, Deleted, Archived)
|
|
67
|
+
- Include the entity ID and all data needed to reconstruct state
|
|
68
|
+
- Events should be self-contained and meaningful
|
|
69
|
+
|
|
70
|
+
**Example:**
|
|
71
|
+
\`\`\`typescript
|
|
72
|
+
@Event
|
|
73
|
+
export class <EventName> {
|
|
74
|
+
public constructor(
|
|
75
|
+
readonly entityId: UUID,
|
|
76
|
+
readonly field1: string,
|
|
77
|
+
readonly field2: number,
|
|
78
|
+
) {}
|
|
79
|
+
|
|
80
|
+
public entityID(): UUID {
|
|
81
|
+
return this.entityId
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
\`\`\`
|
|
85
|
+
|
|
86
|
+
## Step 3: Define the Entity
|
|
87
|
+
|
|
88
|
+
Entities maintain state by reducing events. They are the aggregate roots.
|
|
89
|
+
|
|
90
|
+
\`\`\`bash
|
|
91
|
+
npx magek new:entity <EntityName> --fields <field1:type1> <field2:type2> --reduces <EventName>
|
|
92
|
+
\`\`\`
|
|
93
|
+
|
|
94
|
+
**Best Practices:**
|
|
95
|
+
- One entity per aggregate root
|
|
96
|
+
- Entities should only contain state derived from events
|
|
97
|
+
- Use the \`@Reduces\` decorator to specify which events affect this entity
|
|
98
|
+
|
|
99
|
+
**Example:**
|
|
100
|
+
\`\`\`typescript
|
|
101
|
+
@Entity
|
|
102
|
+
export class <EntityName> {
|
|
103
|
+
public constructor(
|
|
104
|
+
readonly id: UUID,
|
|
105
|
+
readonly field1: string,
|
|
106
|
+
readonly field2: number,
|
|
107
|
+
) {}
|
|
108
|
+
|
|
109
|
+
@Reduces(<EventName>)
|
|
110
|
+
public static reduce<EventName>(
|
|
111
|
+
event: <EventName>,
|
|
112
|
+
currentEntity?: <EntityName>
|
|
113
|
+
): <EntityName> {
|
|
114
|
+
return new <EntityName>(
|
|
115
|
+
event.entityId,
|
|
116
|
+
event.field1,
|
|
117
|
+
event.field2,
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
\`\`\`
|
|
122
|
+
|
|
123
|
+
## Step 4: Define the Read Model
|
|
124
|
+
|
|
125
|
+
Read models provide optimized query access to your data.
|
|
126
|
+
|
|
127
|
+
\`\`\`bash
|
|
128
|
+
npx magek new:read-model <ReadModelName> --fields <field1:type1> <field2:type2> --projects <EntityName>:id
|
|
129
|
+
\`\`\`
|
|
130
|
+
|
|
131
|
+
**Best Practices:**
|
|
132
|
+
- Design read models for specific query use cases
|
|
133
|
+
- Include only the fields needed for queries
|
|
134
|
+
- You can have multiple read models projecting the same entity
|
|
135
|
+
|
|
136
|
+
**Example:**
|
|
137
|
+
\`\`\`typescript
|
|
138
|
+
@ReadModel({
|
|
139
|
+
authorize: 'all'
|
|
140
|
+
})
|
|
141
|
+
export class <ReadModelName> {
|
|
142
|
+
public constructor(
|
|
143
|
+
readonly id: UUID,
|
|
144
|
+
readonly field1: string,
|
|
145
|
+
readonly field2: number,
|
|
146
|
+
) {}
|
|
147
|
+
|
|
148
|
+
@Projects(<EntityName>, 'id')
|
|
149
|
+
public static project<EntityName>(
|
|
150
|
+
entity: <EntityName>,
|
|
151
|
+
currentReadModel?: <ReadModelName>
|
|
152
|
+
): ProjectionResult<<ReadModelName>> {
|
|
153
|
+
return new <ReadModelName>(
|
|
154
|
+
entity.id,
|
|
155
|
+
entity.field1,
|
|
156
|
+
entity.field2,
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
\`\`\`
|
|
161
|
+
|
|
162
|
+
## Step 5: (Optional) Add Event Handlers
|
|
163
|
+
|
|
164
|
+
If your feature needs side effects (send emails, call APIs), add an event handler.
|
|
165
|
+
|
|
166
|
+
\`\`\`bash
|
|
167
|
+
npx magek new:event-handler <HandlerName> --event <EventName>
|
|
168
|
+
\`\`\`
|
|
169
|
+
|
|
170
|
+
**Example:**
|
|
171
|
+
\`\`\`typescript
|
|
172
|
+
@EventHandler(<EventName>)
|
|
173
|
+
export class <HandlerName> {
|
|
174
|
+
public static async handle(event: <EventName>): Promise<void> {
|
|
175
|
+
// Perform side effects here
|
|
176
|
+
// e.g., send email, call external API, etc.
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
\`\`\`
|
|
180
|
+
|
|
181
|
+
## Verification Checklist
|
|
182
|
+
|
|
183
|
+
After implementing all components:
|
|
184
|
+
|
|
185
|
+
1. ✅ Command validates input and registers events
|
|
186
|
+
2. ✅ Event contains all data needed to reconstruct state
|
|
187
|
+
3. ✅ Entity correctly reduces events to state
|
|
188
|
+
4. ✅ Read model projects entity state for queries
|
|
189
|
+
5. ✅ All files are registered in your application
|
|
190
|
+
|
|
191
|
+
## Testing
|
|
192
|
+
|
|
193
|
+
Run your Magek server and test via GraphQL:
|
|
194
|
+
|
|
195
|
+
\`\`\`bash
|
|
196
|
+
npx magek start
|
|
197
|
+
\`\`\`
|
|
198
|
+
|
|
199
|
+
Then test your mutation:
|
|
200
|
+
\`\`\`graphql
|
|
201
|
+
mutation {
|
|
202
|
+
<CommandName>(input: { field1: "value", field2: 123 })
|
|
203
|
+
}
|
|
204
|
+
\`\`\`
|
|
205
|
+
|
|
206
|
+
And query:
|
|
207
|
+
\`\`\`graphql
|
|
208
|
+
query {
|
|
209
|
+
<ReadModelName>s {
|
|
210
|
+
id
|
|
211
|
+
field1
|
|
212
|
+
field2
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
\`\`\`
|
|
216
|
+
|
|
217
|
+
## Common Patterns
|
|
218
|
+
|
|
219
|
+
### Authorization
|
|
220
|
+
Use the \`authorize\` option to control access:
|
|
221
|
+
- \`'all'\` - Anyone can access
|
|
222
|
+
- \`'authenticated'\` - Must be logged in
|
|
223
|
+
- \`['admin']\` - Specific roles only
|
|
224
|
+
|
|
225
|
+
### Validation
|
|
226
|
+
Validate in the command handler before registering events:
|
|
227
|
+
\`\`\`typescript
|
|
228
|
+
if (!command.field1) {
|
|
229
|
+
throw new InvalidParameterError('field1 is required')
|
|
230
|
+
}
|
|
231
|
+
\`\`\`
|
|
232
|
+
|
|
233
|
+
### Entity References
|
|
234
|
+
Reference other entities using their UUID:
|
|
235
|
+
\`\`\`typescript
|
|
236
|
+
readonly relatedEntityId: UUID
|
|
237
|
+
\`\`\`
|
|
238
|
+
`;
|
|
239
|
+
}
|
|
240
|
+
export function getCqrsFlowPromptDefinition() {
|
|
241
|
+
return {
|
|
242
|
+
name: CQRS_FLOW_PROMPT_NAME,
|
|
243
|
+
description: CQRS_FLOW_PROMPT_DESCRIPTION,
|
|
244
|
+
arguments: [
|
|
245
|
+
{
|
|
246
|
+
name: 'feature',
|
|
247
|
+
description: 'The feature to implement (e.g., "Create Product", "User Registration")',
|
|
248
|
+
required: true,
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
};
|
|
252
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const TROUBLESHOOTING_PROMPT_NAME = "magek_troubleshoot";
|
|
2
|
+
export declare const TROUBLESHOOTING_PROMPT_DESCRIPTION = "Common Magek issues and solutions";
|
|
3
|
+
export interface TroubleshootingArguments {
|
|
4
|
+
issue?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function getTroubleshootingPrompt(args: TroubleshootingArguments): string;
|
|
7
|
+
export declare function getTroubleshootingPromptDefinition(): {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
arguments: {
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
required: boolean;
|
|
14
|
+
}[];
|
|
15
|
+
};
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
export const TROUBLESHOOTING_PROMPT_NAME = 'magek_troubleshoot';
|
|
2
|
+
export const TROUBLESHOOTING_PROMPT_DESCRIPTION = 'Common Magek issues and solutions';
|
|
3
|
+
export function getTroubleshootingPrompt(args) {
|
|
4
|
+
const { issue } = args;
|
|
5
|
+
const intro = issue
|
|
6
|
+
? `# Troubleshooting: ${issue}\n\nHere are solutions for issues related to "${issue}":\n\n`
|
|
7
|
+
: '# Magek Troubleshooting Guide\n\nCommon issues and their solutions:\n\n';
|
|
8
|
+
return `${intro}## GraphQL Schema Issues
|
|
9
|
+
|
|
10
|
+
### Schema not updating after adding new components
|
|
11
|
+
|
|
12
|
+
**Symptoms:**
|
|
13
|
+
- New commands/queries don't appear in GraphQL playground
|
|
14
|
+
- Types are missing from schema
|
|
15
|
+
|
|
16
|
+
**Solutions:**
|
|
17
|
+
1. Make sure all components are exported from your main index file
|
|
18
|
+
2. Restart the development server (\`npx magek start\`)
|
|
19
|
+
3. Check that decorators are correctly applied (\`@Command\`, \`@Event\`, \`@Entity\`, \`@ReadModel\`)
|
|
20
|
+
4. Verify imports are correct (no circular dependencies)
|
|
21
|
+
|
|
22
|
+
\`\`\`typescript
|
|
23
|
+
// src/index.ts - ensure all components are exported
|
|
24
|
+
export * from './commands/CreateProduct'
|
|
25
|
+
export * from './events/ProductCreated'
|
|
26
|
+
export * from './entities/Product'
|
|
27
|
+
export * from './read-models/ProductReadModel'
|
|
28
|
+
\`\`\`
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Event Issues
|
|
33
|
+
|
|
34
|
+
### Events not being reduced by Entity
|
|
35
|
+
|
|
36
|
+
**Symptoms:**
|
|
37
|
+
- Entity state doesn't update after command executes
|
|
38
|
+
- Read model stays empty
|
|
39
|
+
|
|
40
|
+
**Solutions:**
|
|
41
|
+
1. Verify the \`@Reduces\` decorator references the correct event class
|
|
42
|
+
2. Check that the event's \`entityID()\` method returns the correct ID
|
|
43
|
+
3. Ensure the reduce method returns a new entity instance (not mutating)
|
|
44
|
+
|
|
45
|
+
\`\`\`typescript
|
|
46
|
+
@Entity
|
|
47
|
+
export class Product {
|
|
48
|
+
// Make sure decorator references the actual event class
|
|
49
|
+
@Reduces(ProductCreated) // ✅ Correct
|
|
50
|
+
@Reduces('ProductCreated') // ❌ Won't work
|
|
51
|
+
public static reduceProductCreated(event: ProductCreated): Product {
|
|
52
|
+
return new Product(event.entityId, event.name)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
\`\`\`
|
|
56
|
+
|
|
57
|
+
### Events registered but command returns error
|
|
58
|
+
|
|
59
|
+
**Symptoms:**
|
|
60
|
+
- Command throws error even though events were registered
|
|
61
|
+
|
|
62
|
+
**Solutions:**
|
|
63
|
+
1. Check for validation errors before registering events
|
|
64
|
+
2. Ensure all event constructor parameters are provided
|
|
65
|
+
3. Verify UUID generation is working
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Authorization Issues
|
|
70
|
+
|
|
71
|
+
### "Unauthorized" error on commands/queries
|
|
72
|
+
|
|
73
|
+
**Symptoms:**
|
|
74
|
+
- 401 or 403 errors when executing mutations/queries
|
|
75
|
+
- Works in playground but fails in app
|
|
76
|
+
|
|
77
|
+
**Solutions:**
|
|
78
|
+
1. Check the \`authorize\` option in decorators:
|
|
79
|
+
\`\`\`typescript
|
|
80
|
+
@Command({ authorize: 'all' }) // Public access
|
|
81
|
+
@Command({ authorize: 'authenticated' }) // Requires login
|
|
82
|
+
@Command({ authorize: ['admin'] }) // Requires admin role
|
|
83
|
+
\`\`\`
|
|
84
|
+
|
|
85
|
+
2. If using authentication, ensure JWT token is valid
|
|
86
|
+
3. Verify token is passed in Authorization header:
|
|
87
|
+
\`\`\`
|
|
88
|
+
Authorization: Bearer <token>
|
|
89
|
+
\`\`\`
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Read Model Issues
|
|
94
|
+
|
|
95
|
+
### Read model not updating
|
|
96
|
+
|
|
97
|
+
**Symptoms:**
|
|
98
|
+
- Queries return stale data
|
|
99
|
+
- Entity exists but read model is empty
|
|
100
|
+
|
|
101
|
+
**Solutions:**
|
|
102
|
+
1. Verify \`@Projects\` decorator is correct:
|
|
103
|
+
\`\`\`typescript
|
|
104
|
+
@Projects(Product, 'id') // Must match entity and join key
|
|
105
|
+
public static projectProduct(entity: Product): ProductReadModel {
|
|
106
|
+
return new ProductReadModel(entity.id, entity.name)
|
|
107
|
+
}
|
|
108
|
+
\`\`\`
|
|
109
|
+
|
|
110
|
+
2. Check the projection method returns the correct type
|
|
111
|
+
3. Ensure the join key exists on the entity
|
|
112
|
+
|
|
113
|
+
### Read model returns null for existing entity
|
|
114
|
+
|
|
115
|
+
**Solutions:**
|
|
116
|
+
1. Check if the entity ID matches what's used in the projection
|
|
117
|
+
2. Verify the projection method handles all entity states
|
|
118
|
+
3. Look for errors in the server logs
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Entity Issues
|
|
123
|
+
|
|
124
|
+
### "Entity not found" errors
|
|
125
|
+
|
|
126
|
+
**Symptoms:**
|
|
127
|
+
- Commands that update existing entities fail
|
|
128
|
+
- Entity lookup returns undefined
|
|
129
|
+
|
|
130
|
+
**Solutions:**
|
|
131
|
+
1. Verify the entity ID is correct (UUID format)
|
|
132
|
+
2. Check that the entity has been created (initial event was processed)
|
|
133
|
+
3. Use \`fetchEntityByID\` or \`fetchEntityByKey\` correctly:
|
|
134
|
+
\`\`\`typescript
|
|
135
|
+
const entity = await entityProvider.fetchEntityByID(Product, entityId)
|
|
136
|
+
if (!entity) {
|
|
137
|
+
throw new InvalidParameterError('Product not found')
|
|
138
|
+
}
|
|
139
|
+
\`\`\`
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Development Server Issues
|
|
144
|
+
|
|
145
|
+
### Server won't start
|
|
146
|
+
|
|
147
|
+
**Symptoms:**
|
|
148
|
+
- Error on \`npx magek start\`
|
|
149
|
+
- Port already in use
|
|
150
|
+
|
|
151
|
+
**Solutions:**
|
|
152
|
+
1. Check if another process is using port 3000:
|
|
153
|
+
\`\`\`bash
|
|
154
|
+
lsof -i :3000
|
|
155
|
+
kill -9 <PID>
|
|
156
|
+
\`\`\`
|
|
157
|
+
|
|
158
|
+
2. Verify all dependencies are installed:
|
|
159
|
+
\`\`\`bash
|
|
160
|
+
npm install
|
|
161
|
+
\`\`\`
|
|
162
|
+
|
|
163
|
+
3. Check for TypeScript compilation errors:
|
|
164
|
+
\`\`\`bash
|
|
165
|
+
npx tsc --noEmit
|
|
166
|
+
\`\`\`
|
|
167
|
+
|
|
168
|
+
### Hot reload not working
|
|
169
|
+
|
|
170
|
+
**Solutions:**
|
|
171
|
+
1. Check file watcher limits (Linux):
|
|
172
|
+
\`\`\`bash
|
|
173
|
+
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
|
|
174
|
+
sudo sysctl -p
|
|
175
|
+
\`\`\`
|
|
176
|
+
|
|
177
|
+
2. Restart the development server
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Type Errors
|
|
182
|
+
|
|
183
|
+
### TypeScript errors with decorators
|
|
184
|
+
|
|
185
|
+
**Symptoms:**
|
|
186
|
+
- "Unable to resolve signature" errors
|
|
187
|
+
- "Experimental decorator" warnings
|
|
188
|
+
|
|
189
|
+
**Solutions:**
|
|
190
|
+
1. Ensure \`tsconfig.json\` has decorator support:
|
|
191
|
+
\`\`\`json
|
|
192
|
+
{
|
|
193
|
+
"compilerOptions": {
|
|
194
|
+
"experimentalDecorators": true,
|
|
195
|
+
"emitDecoratorMetadata": true
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
\`\`\`
|
|
199
|
+
|
|
200
|
+
2. Make sure reflect-metadata is imported at the entry point
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Database/Persistence Issues
|
|
205
|
+
|
|
206
|
+
### Data not persisting across restarts
|
|
207
|
+
|
|
208
|
+
**Symptoms:**
|
|
209
|
+
- All data lost when server restarts
|
|
210
|
+
- Events not saved
|
|
211
|
+
|
|
212
|
+
**Solutions:**
|
|
213
|
+
1. Check database configuration in your environment
|
|
214
|
+
2. Verify the event store adapter is correctly configured
|
|
215
|
+
3. For development, NeDB stores data in \`.magek/\` directory
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Getting More Help
|
|
220
|
+
|
|
221
|
+
1. **Read the documentation**: \`magek://docs/index\`
|
|
222
|
+
2. **Check CLI reference**: \`magek://cli/reference\`
|
|
223
|
+
3. **Enable debug logging**: Set \`MAGEK_LOG_LEVEL=debug\`
|
|
224
|
+
4. **GitHub Issues**: https://github.com/theam/magek/issues
|
|
225
|
+
`;
|
|
226
|
+
}
|
|
227
|
+
export function getTroubleshootingPromptDefinition() {
|
|
228
|
+
return {
|
|
229
|
+
name: TROUBLESHOOTING_PROMPT_NAME,
|
|
230
|
+
description: TROUBLESHOOTING_PROMPT_DESCRIPTION,
|
|
231
|
+
arguments: [
|
|
232
|
+
{
|
|
233
|
+
name: 'issue',
|
|
234
|
+
description: 'Specific issue description (optional, e.g., "GraphQL schema not updating")',
|
|
235
|
+
required: false,
|
|
236
|
+
},
|
|
237
|
+
],
|
|
238
|
+
};
|
|
239
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const CLI_REFERENCE_URI = "magek://cli/reference";
|
|
2
|
+
export declare const CLI_REFERENCE_CONTENT = "# Magek CLI Commands\n\nComprehensive reference for all Magek CLI scaffolding commands. These commands generate TypeScript files following Magek conventions.\n\n## Scaffolding Commands\n\n### Create a Command\n\nCommands represent user intent that triggers events. They are the entry point for all write operations.\n\n```bash\nnpx magek new:command <Name> --fields field1:type1 field2:type2\n```\n\n**Example:**\n```bash\nnpx magek new:command CreateProduct --fields sku:string price:number description:string\n```\n\n**Available field types:** string, number, boolean, UUID, Date\n\n---\n\n### Create an Event\n\nEvents are immutable facts that happened in the system. They are the source of truth.\n\n```bash\nnpx magek new:event <Name> --fields field1:type1 field2:type2\n```\n\n**Example:**\n```bash\nnpx magek new:event ProductCreated --fields productId:UUID sku:string price:number\n```\n\n---\n\n### Create an Entity\n\nEntities (aggregate roots) maintain state from events. Use --reduces to specify which events the entity handles.\n\n```bash\nnpx magek new:entity <Name> --fields field1:type1 field2:type2 --reduces EventName\n```\n\n**Example:**\n```bash\nnpx magek new:entity Product --fields sku:string price:number inStock:boolean --reduces ProductCreated\n```\n\n---\n\n### Create a Read Model\n\nRead models are query-optimized projections. Use --projects to specify which entity to project.\n\n```bash\nnpx magek new:read-model <Name> --fields field1:type1 field2:type2 --projects Entity:joinKey\n```\n\n**Example:**\n```bash\nnpx magek new:read-model ProductReadModel --fields sku:string price:number name:string --projects Product:id\n```\n\n---\n\n### Create an Event Handler\n\nEvent handlers react to events and perform side effects (send emails, call external APIs, etc.).\n\n```bash\nnpx magek new:event-handler <Name> --event EventName\n```\n\n**Example:**\n```bash\nnpx magek new:event-handler SendWelcomeEmail --event UserRegistered\n```\n\n---\n\n### Create a Scheduled Command\n\nScheduled commands run on a cron schedule for recurring tasks.\n\n```bash\nnpx magek new:scheduled-command <Name>\n```\n\n**Example:**\n```bash\nnpx magek new:scheduled-command CleanupExpiredSessions\n```\n\n---\n\n### Create a Query\n\nQueries retrieve data from read models without side effects.\n\n```bash\nnpx magek new:query <Name> --fields field1:type1\n```\n\n**Example:**\n```bash\nnpx magek new:query GetProductBySku --fields sku:string\n```\n\n---\n\n### Create a Type\n\nCustom types for domain modeling.\n\n```bash\nnpx magek new:type <Name> --fields field1:type1 field2:type2\n```\n\n**Example:**\n```bash\nnpx magek new:type Money --fields amount:number currency:string\n```\n\n---\n\n## Project Initialization\n\n### Create a New Magek Project\n\n```bash\nnpx create-magek my-app\n```\n\nOr with pnpm:\n```bash\npnpm create magek my-app\n```\n\n---\n\n## Development Server\n\n### Start the Development Server\n\n```bash\nnpx magek start\n```\n\nThis starts:\n- GraphQL API at http://localhost:3000/graphql\n- GraphQL Playground for testing queries\n\n---\n\n## Field Type Reference\n\n| Type | Description | Example |\n|------|-------------|---------|\n| `string` | Text values | `name:string` |\n| `number` | Numeric values | `price:number` |\n| `boolean` | True/false values | `isActive:boolean` |\n| `UUID` | Unique identifiers | `productId:UUID` |\n| `Date` | Date/time values | `createdAt:Date` |\n\n## Tips for Claude Code\n\nWhen helping users scaffold Magek components:\n\n1. **Start with the Command** - This defines the user action\n2. **Create the Event** - This records what happened\n3. **Create the Entity** - This maintains the state\n4. **Create the Read Model** - This provides query access\n\nAlways use descriptive names that reflect the domain (e.g., `CreateOrder` not `Create`).\n";
|
|
3
|
+
export interface CliReferenceResource {
|
|
4
|
+
uri: string;
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
mimeType: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function getCliReferenceResource(): CliReferenceResource;
|
|
10
|
+
export declare function readCliReference(): {
|
|
11
|
+
content: string;
|
|
12
|
+
mimeType: string;
|
|
13
|
+
};
|