@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
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Error Handling"
|
|
3
|
+
group: "Features"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Error handling
|
|
7
|
+
|
|
8
|
+
## Error handling in Magek
|
|
9
|
+
|
|
10
|
+
Magek provides a default error handling mechanism that will try to catch all the errors that are thrown in the application and will log them. This is useful for debugging purposes, but you may want to customize the error handling in your application. For example, you may want to email the administrator when an error occurs.
|
|
11
|
+
|
|
12
|
+
### Custom error handling
|
|
13
|
+
|
|
14
|
+
To customize the error handling, you need to create a class decorated with the `@GlobalErrorHandler` decorator. This class will contain the methods that will be called when an error is thrown. There is one method for each component in the application where an error can be thrown. All these functions receive the error that was thrown and the information about the component that was being executed when the error occurred.
|
|
15
|
+
|
|
16
|
+
They must return a promise that resolves to an `Error` object or `undefined`. If the promise resolves to `undefined`, the error will be ignored and **Magek** will continue working. If the promise resolves to an `Error` object, the error will be thrown and **Magek** will handle it on a case-by-case basis in the default way.
|
|
17
|
+
|
|
18
|
+
### Command handle errors
|
|
19
|
+
|
|
20
|
+
These are the errors that are thrown in the `handle` method of the `@Command`. You can catch and return new errors in this method annotating a class with `@GlobalErrorHandler` and implementing the following method:
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
@GlobalErrorHandler()
|
|
24
|
+
export class MyErrorHandler {
|
|
25
|
+
public static async onCommandHandlerError(
|
|
26
|
+
error: Error,
|
|
27
|
+
commandEnvelope: CommandEnvelope,
|
|
28
|
+
commandMetadata: CommandMetadata
|
|
29
|
+
): Promise<Error | undefined> {
|
|
30
|
+
// Do something with the error
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
This method receives the error that was thrown and the command that was being handled when the error occurred.
|
|
36
|
+
|
|
37
|
+
### Scheduled command handle errors
|
|
38
|
+
|
|
39
|
+
These are the errors that are thrown in the `handle` method of the `@ScheduledCommand`. You can catch and return new errors in this function annotating a class with `@GlobalErrorHandler` and implementing the following method:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
@GlobalErrorHandler()
|
|
43
|
+
export class MyErrorHandler {
|
|
44
|
+
public static async onScheduledCommandHandlerError(
|
|
45
|
+
error: Error,
|
|
46
|
+
scheduledCommandEnvelope: ScheduledCommandEnvelope,
|
|
47
|
+
scheduledCommandMetadata: ScheduledCommandMetadata
|
|
48
|
+
): Promise<Error | undefined> {
|
|
49
|
+
// Do something with the error
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Note that if an error is thrown on a ScheduleCommand, **Magek** will stop working.
|
|
55
|
+
|
|
56
|
+
### Event handler errors
|
|
57
|
+
|
|
58
|
+
These are the errors that are thrown in the `handle` method of the `@Event`. You can catch and return new errors in this function annotating a class with `@GlobalErrorHandler` and implementing the following method:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
@GlobalErrorHandler()
|
|
62
|
+
export class MyErrorHandler {
|
|
63
|
+
public static async onDispatchEventHandlerError(
|
|
64
|
+
error: Error,
|
|
65
|
+
eventEnvelope: EventEnvelope | NotificationInterface,
|
|
66
|
+
eventHandlerMetadata: unknown,
|
|
67
|
+
eventInstance: EventInterface
|
|
68
|
+
): Promise<Error | undefined> {
|
|
69
|
+
// Do something with the error
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Reducer errors
|
|
75
|
+
|
|
76
|
+
These are the errors that are thrown in the `@reduces` method of the `@Entity`. You can catch and return new errors in this function annotating a class with `@GlobalErrorHandler` and implementing the following method:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
@GlobalErrorHandler()
|
|
80
|
+
export class MyErrorHandler {
|
|
81
|
+
public static async onReducerError(
|
|
82
|
+
error: Error,
|
|
83
|
+
eventEnvelope: EventEnvelope,
|
|
84
|
+
reducerMetadata: ReducerMetadata,
|
|
85
|
+
eventInstance: EventInterface,
|
|
86
|
+
snapshotInstance: EntityInterface | null
|
|
87
|
+
): Promise<Error> {
|
|
88
|
+
// Do something with the error
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Note you can not ignore a Reducer error as the new entity could not be created
|
|
94
|
+
|
|
95
|
+
### Event errors
|
|
96
|
+
|
|
97
|
+
These are the errors that are thrown if the event doesn't exist. You can catch and return new errors in this function annotating a class with `@GlobalErrorHandler` and implementing the following method:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
@GlobalErrorHandler()
|
|
101
|
+
export class MyErrorHandler {
|
|
102
|
+
public static async onEventError(error: Error, eventEnvelope: EventEnvelope): Promise<Error | undefined> {
|
|
103
|
+
// Do something with the error
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
This method receives the error that was thrown and the event received.
|
|
109
|
+
|
|
110
|
+
### Projection errors
|
|
111
|
+
|
|
112
|
+
These are the errors that are thrown in the `@projects` method of the `@ReadModel`. You can catch and return new errors in this function annotating a class with `@GlobalErrorHandler` and implementing the following method:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
@GlobalErrorHandler()
|
|
116
|
+
export class MyErrorHandler {
|
|
117
|
+
public static async onProjectionError(
|
|
118
|
+
error: Error,
|
|
119
|
+
entityEnvelope: EntitySnapshotEnvelope,
|
|
120
|
+
projectionMetadata: ProjectionMetadata<EntityInterface>,
|
|
121
|
+
entity: EntityInterface,
|
|
122
|
+
readModel: ReadModelInterface | undefined
|
|
123
|
+
): Promise<Error | undefined> {
|
|
124
|
+
// Do something with the error
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### All errors
|
|
130
|
+
|
|
131
|
+
These are the errors that are thrown in any of the previous methods. You can catch and return new errors in this function annotating a class with `@GlobalErrorHandler` and implementing the following method:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
@GlobalErrorHandler()
|
|
135
|
+
export class MyErrorHandler {
|
|
136
|
+
public onError(error: Error | undefined): Promise<Error | undefined> {
|
|
137
|
+
// Do something with the error
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
This method receives the error that was thrown.
|
|
143
|
+
|
|
144
|
+
## Global error handler example
|
|
145
|
+
|
|
146
|
+
You can implement all error handling functions in the same class. Here is an example of a global error handler that will handle all the errors mentioned above:
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
@GlobalErrorHandler()
|
|
150
|
+
export class AppErrorHandler {
|
|
151
|
+
public static async onCommandHandlerError(
|
|
152
|
+
error: Error,
|
|
153
|
+
commandEnvelope: CommandEnvelope,
|
|
154
|
+
commandMetadata: CommandMetadata
|
|
155
|
+
): Promise<Error | undefined> {
|
|
156
|
+
return error
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
public static async onScheduledCommandHandlerError(
|
|
160
|
+
error: Error,
|
|
161
|
+
scheduledCommandEnvelope: ScheduledCommandEnvelope,
|
|
162
|
+
scheduledCommandMetadata: ScheduledCommandMetadata
|
|
163
|
+
): Promise<Error | undefined> {
|
|
164
|
+
return error
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public static async onDispatchEventHandlerError(
|
|
168
|
+
error: Error,
|
|
169
|
+
eventEnvelope: EventEnvelope | NotificationInterface,
|
|
170
|
+
eventHandlerMetadata: unknown,
|
|
171
|
+
eventInstance: EventInterface
|
|
172
|
+
): Promise<Error | undefined> {
|
|
173
|
+
return error
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
public static async onReducerError(
|
|
177
|
+
error: Error,
|
|
178
|
+
eventEnvelope: EventEnvelope,
|
|
179
|
+
reducerMetadata: ReducerMetadata,
|
|
180
|
+
eventInstance: EventInterface,
|
|
181
|
+
snapshotInstance: EntityInterface | null
|
|
182
|
+
): Promise<Error | undefined> {
|
|
183
|
+
return error
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
public static async onProjectionError(
|
|
187
|
+
error: Error,
|
|
188
|
+
entityEnvelope: EntitySnapshotEnvelope,
|
|
189
|
+
projectionMetadata: ProjectionMetadata<EntityInterface>,
|
|
190
|
+
entity: EntityInterface,
|
|
191
|
+
readModel: ReadModelInterface | undefined
|
|
192
|
+
): Promise<Error | undefined> {
|
|
193
|
+
return error
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
public static async onEventError(error: Error, eventEnvelope: EventEnvelope): Promise<Error | undefined> {
|
|
197
|
+
return error
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
public static async onError(error: Error | undefined): Promise<Error | undefined> {
|
|
201
|
+
return error
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Event Stream API"
|
|
3
|
+
group: "Features"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# The event stream
|
|
7
|
+
|
|
8
|
+
The event stream API is a read-only API that allows you to fetch the events that have been generated by your application. It's useful for debugging purposes, but also for building your own analytics tools. The access to this API is disabled by default, but you can enable it by configuring the `authorizeReadEvents` policy in your entities. You can also use the `authorizeReadEvents` policy to restrict access to the events of certain entities.
|
|
9
|
+
|
|
10
|
+
## Accessing the event streams API
|
|
11
|
+
|
|
12
|
+
The `authorizeReadEvents` policy can be configured with any of the supported authorization mechanisms:
|
|
13
|
+
|
|
14
|
+
- `'all'` to make them public.
|
|
15
|
+
- an array of roles.
|
|
16
|
+
- An [authorizer function](/security/authorization#event-stream-authorizers) that matches the `EventStreamAuthorizer` type signature. For example
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
@Entity({
|
|
20
|
+
authorizeReadEvents: 'all', // Anyone can read any Cart's event
|
|
21
|
+
})
|
|
22
|
+
export class Cart {
|
|
23
|
+
public constructor(
|
|
24
|
+
readonly id: UUID,
|
|
25
|
+
readonly cartItems: Array<CartItem>,
|
|
26
|
+
public shippingAddress?: Address,
|
|
27
|
+
public checks = 0
|
|
28
|
+
) {}
|
|
29
|
+
// <reducers...>
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
> **Note:** Be careful when exposing events data, as this data is likely to hold internal system state. Pay special attention when authorizing public access with the `'all'` option, it's always recommended to look for alternate solutions that limit access.
|
|
34
|
+
|
|
35
|
+
To read more about how to restrict the access to the event stream API, check out the [authorization guide](/security/authorization).
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Logging"
|
|
3
|
+
group: "Features"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Logging in Magek
|
|
7
|
+
|
|
8
|
+
If no configuration is provided, Magek uses the default JavaScript logging capabilities. Depending on the log level, it will call different logging methods:
|
|
9
|
+
|
|
10
|
+
- `console.debug` for `Level.debug`
|
|
11
|
+
- `console.info` for `Level.info`
|
|
12
|
+
- `console.warn` for `Level.warn`
|
|
13
|
+
- `console.error` for `Level.error`
|
|
14
|
+
|
|
15
|
+
In this regard, there's no distinction from any other node process and you'll find the logs in your standard output.
|
|
16
|
+
|
|
17
|
+
## Advanced logging
|
|
18
|
+
|
|
19
|
+
You may need some advanced logging capabilities, such as redirecting your logs to a log aggregator. Magek also supports overriding the default behavior by providing custom loggers. The only thing you need to do is to provide an object that implements the `Logger` interface at config time:
|
|
20
|
+
|
|
21
|
+
```typescript title="@magek/common/lib/logger.ts"
|
|
22
|
+
interface Logger {
|
|
23
|
+
debug(message?: any, ...optionalParams: any[]): void
|
|
24
|
+
info(message?: any, ...optionalParams: any[]): void
|
|
25
|
+
warn(message?: any, ...optionalParams: any[]): void
|
|
26
|
+
error(message?: any, ...optionalParams: any[]): void
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```typescript title="src/config/config.ts"
|
|
31
|
+
|
|
32
|
+
Magek.configure('development', (config: MagekConfig): void => {
|
|
33
|
+
config.appName = 'my-store'
|
|
34
|
+
config.runtime = ServerRuntime
|
|
35
|
+
config.eventStoreAdapter = eventStore
|
|
36
|
+
// highlight-start
|
|
37
|
+
config.logger = new MyCustomLogger() // Overrides the default logger object
|
|
38
|
+
config.logLevel = Level.debug // Sets the log level at 'debug'
|
|
39
|
+
config.logPrefix = 'my-store-dev' // Sets the default prefix
|
|
40
|
+
// highlight-end
|
|
41
|
+
})
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Using the Magek's logger
|
|
45
|
+
|
|
46
|
+
All framework's components will use this logger by default and will generate logs that match the following pattern:
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
[<logPrefix>]|moduleName: <message>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
You can get a custom logger instance that extends the configured logger by adding your moduleName and optionally overriding the configured prefix with the `getLogger` helper function. It's a good practice to build and use a separate logger instance built with this method for each context, as this will make it easier to filter your logs when you need to investigate a problem.
|
|
53
|
+
|
|
54
|
+
_Example: Obtaining a logger for your command:_
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
@Command({
|
|
58
|
+
authorize: [User],
|
|
59
|
+
})
|
|
60
|
+
export class UpdateShippingAddress {
|
|
61
|
+
@field()
|
|
62
|
+
readonly cartId!: UUID
|
|
63
|
+
|
|
64
|
+
@field()
|
|
65
|
+
readonly address!: Address
|
|
66
|
+
|
|
67
|
+
public static async handle(command: UpdateShippingAddress, register: Register): Promise<void> {
|
|
68
|
+
const logger = getLogger(Magek.config, 'UpdateShippingCommand#handler', 'MyApp')
|
|
69
|
+
logger.debug(`User ${register.currentUser?.username} changed shipping address for cart ${command.cartId}: ${JSON.stringify(command.address}`)
|
|
70
|
+
register.events(new ShippingAddressUpdated(command.cartId, command.address))
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
When a `UpdateShippingAddress` command is handled, it wil log messages that look like the following:
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
[MyApp]|UpdateShippingCommand#handler: User buyer42 changed shipping address for cart 314: { street: '13th rue del percebe', number: 6, ... }
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Using the configured Magek logger is not mandatory for your application, but it might be convenient to centralize your logs and this is a standard way to do it.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Scheduled Actions"
|
|
3
|
+
group: "Features"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Schedule actions
|
|
7
|
+
|
|
8
|
+
There are many cases in which you want to trigger some action periodically. For example, you may want to send a reminder email to a user every day at 10:00 AM. For this, you can use scheduled commands.
|
|
9
|
+
|
|
10
|
+
## Scheduled command
|
|
11
|
+
|
|
12
|
+
Commands represent an action. Therefore, the way to trigger an action periodically is by scheduling a command. Scheduled commands are the way to add automated tasks to your application, like cron jobs in other frameworks. Magek scheduled commands are TypeScript classes decorated with `@ScheduledCommand`. Unlike conventional commands, **the handle function doesn't have any parameters**.
|
|
13
|
+
|
|
14
|
+
In Magek, a scheduled command looks like this:
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
@ScheduledCommand({
|
|
18
|
+
minute: '0/5', // runs every 5 minutes
|
|
19
|
+
})
|
|
20
|
+
export class CheckCartCount {
|
|
21
|
+
public static async handle(): Promise<void> {
|
|
22
|
+
/* YOUR CODE HERE */
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
You can pass the following parameters to the `@ScheduledCommand` decorator:
|
|
28
|
+
|
|
29
|
+
* `minute`: A cron expression to specify the minute(s) in which the command will be triggered. For example, `0/5` means "every 5 minutes". You can also use a comma-separated list of values, like `1,5,10,15,20,25,30,35,40,45,50,55` to specify a list of minutes.
|
|
30
|
+
* `hour`: A cron expression to specify the hour(s) in which the command will be triggered. For example, `0/2` means "every 2 hours". You can also use a comma-separated list of values, like `1,3,5,7,9,11,13,15,17,19,21,23` to specify a list of hours.
|
|
31
|
+
* `day`: A cron expression to specify the day(s) in which the command will be triggered. For example, `1/2` means "every 2 days". You can also use a comma-separated list of values, like `1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31` to specify a list of days.
|
|
32
|
+
* `month`: A cron expression to specify the month(s) in which the command will be triggered. For example, `1/2` means "every 2 months". You can also use a comma-separated list of values, like `1,3,5,7,9,11` to specify a list of months.
|
|
33
|
+
* `weekDay`: A cron expression to specify the day(s) of the week in which the command will be triggered. For example, `1/2` means "every 2 days of the week". You can also use a comma-separated list of values, like `1,3,5` to specify a list of days of the week.
|
|
34
|
+
* `year`: A cron expression to specify the year(s) in which the command will be triggered. For example, `2020/2` means "every 2 years". You can also use a comma-separated list of values, like `2020,2022,2024,2026,2028,2030` to specify a list of years.
|
|
35
|
+
|
|
36
|
+
By default, if no paramaters are passed, the scheduled command will not be triggered.
|
|
37
|
+
|
|
38
|
+
## Creating a scheduled command
|
|
39
|
+
|
|
40
|
+
The preferred way to create a scheduled command is by using the generator, e.g.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx magek new:scheduled-command CheckCartCount
|
|
44
|
+
```
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "AI Coding Assistants"
|
|
3
|
+
group: "Getting Started"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# AI Coding Assistants
|
|
7
|
+
|
|
8
|
+
Magek provides an MCP (Model Context Protocol) server that enables AI coding assistants like **Claude Code** and **Codex CLI** to understand and work with Magek projects. This gives your AI assistant access to Magek documentation, CLI commands, and best practices — so it can help you build event-sourced applications faster.
|
|
9
|
+
|
|
10
|
+
## Quick Start
|
|
11
|
+
|
|
12
|
+
### Claude Code
|
|
13
|
+
|
|
14
|
+
Add Magek to Claude Code with a single command:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
claude mcp add magek -- npx -y @magek/mcp-server
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
That's it! Claude Code now has access to Magek documentation and can help you scaffold commands, events, entities, and read models.
|
|
21
|
+
|
|
22
|
+
### Codex CLI
|
|
23
|
+
|
|
24
|
+
Add to your project's `.codex/config.json`:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"mcpServers": {
|
|
29
|
+
"magek": {
|
|
30
|
+
"command": "npx",
|
|
31
|
+
"args": ["-y", "@magek/mcp-server"]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Manual Configuration
|
|
38
|
+
|
|
39
|
+
For other MCP-compatible tools, add to your configuration:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"mcpServers": {
|
|
44
|
+
"magek": {
|
|
45
|
+
"command": "npx",
|
|
46
|
+
"args": ["-y", "@magek/mcp-server"]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## What Your AI Assistant Can Do
|
|
53
|
+
|
|
54
|
+
Once configured, your AI coding assistant can:
|
|
55
|
+
|
|
56
|
+
### Access Documentation
|
|
57
|
+
|
|
58
|
+
The MCP server provides all Magek documentation as resources. Your assistant can read about:
|
|
59
|
+
|
|
60
|
+
- Commands, Events, Entities, and Read Models
|
|
61
|
+
- Authentication and Authorization
|
|
62
|
+
- Event Handlers and Scheduled Commands
|
|
63
|
+
- Advanced topics like Data Migrations and Testing
|
|
64
|
+
|
|
65
|
+
### Use CLI Commands
|
|
66
|
+
|
|
67
|
+
Your assistant knows all Magek CLI scaffolding commands and can execute them for you:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Create a command
|
|
71
|
+
npx magek new:command CreateProduct --fields sku:string price:number
|
|
72
|
+
|
|
73
|
+
# Create an event
|
|
74
|
+
npx magek new:event ProductCreated --fields productId:UUID sku:string price:number
|
|
75
|
+
|
|
76
|
+
# Create an entity
|
|
77
|
+
npx magek new:entity Product --fields sku:string price:number --reduces ProductCreated
|
|
78
|
+
|
|
79
|
+
# Create a read model
|
|
80
|
+
npx magek new:read-model ProductReadModel --fields sku:string price:number --projects Product:id
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Follow CQRS Patterns
|
|
84
|
+
|
|
85
|
+
The MCP server includes a CQRS flow prompt that guides your assistant through implementing complete features:
|
|
86
|
+
|
|
87
|
+
1. **Command** → User intent (e.g., `CreateProduct`)
|
|
88
|
+
2. **Event** → Immutable fact (e.g., `ProductCreated`)
|
|
89
|
+
3. **Entity** → State reducer (e.g., `Product`)
|
|
90
|
+
4. **Read Model** → Query access (e.g., `ProductReadModel`)
|
|
91
|
+
|
|
92
|
+
### Troubleshoot Issues
|
|
93
|
+
|
|
94
|
+
The troubleshooting prompt helps your assistant diagnose common issues:
|
|
95
|
+
|
|
96
|
+
- GraphQL schema not updating
|
|
97
|
+
- Events not being reduced
|
|
98
|
+
- Authorization errors
|
|
99
|
+
- Entity not found errors
|
|
100
|
+
|
|
101
|
+
## Available Resources
|
|
102
|
+
|
|
103
|
+
| Resource | Description |
|
|
104
|
+
|----------|-------------|
|
|
105
|
+
| `magek://docs/index` | Index of all documentation topics |
|
|
106
|
+
| `magek://docs/introduction` | Introduction to Magek |
|
|
107
|
+
| `magek://docs/getting-started/*` | Installation and coding guides |
|
|
108
|
+
| `magek://docs/architecture/*` | Commands, Events, Entities, Read Models |
|
|
109
|
+
| `magek://docs/security/*` | Authentication and Authorization |
|
|
110
|
+
| `magek://docs/features/*` | Error handling, Logging, Scheduling |
|
|
111
|
+
| `magek://docs/advanced/*` | Testing, Migrations, Configuration |
|
|
112
|
+
| `magek://cli/reference` | Complete CLI command reference |
|
|
113
|
+
|
|
114
|
+
## Available Prompts
|
|
115
|
+
|
|
116
|
+
| Prompt | Description |
|
|
117
|
+
|--------|-------------|
|
|
118
|
+
| `magek_cqrs_flow` | Step-by-step guide for implementing a feature |
|
|
119
|
+
| `magek_troubleshoot` | Common issues and solutions |
|
|
120
|
+
|
|
121
|
+
## Example Conversation
|
|
122
|
+
|
|
123
|
+
Here's how you might interact with your AI assistant:
|
|
124
|
+
|
|
125
|
+
> **You:** Create a user registration feature for my Magek app
|
|
126
|
+
>
|
|
127
|
+
> **Assistant:** I'll help you implement user registration using Magek's CQRS pattern. Let me create the command, event, entity, and read model...
|
|
128
|
+
>
|
|
129
|
+
> ```bash
|
|
130
|
+
> npx magek new:command RegisterUser --fields email:string password:string name:string
|
|
131
|
+
> npx magek new:event UserRegistered --fields userId:UUID email:string name:string
|
|
132
|
+
> npx magek new:entity User --fields email:string name:string --reduces UserRegistered
|
|
133
|
+
> npx magek new:read-model UserReadModel --fields email:string name:string --projects User:id
|
|
134
|
+
> ```
|
|
135
|
+
|
|
136
|
+
## Custom Documentation Path
|
|
137
|
+
|
|
138
|
+
If you're developing Magek itself or want to use local documentation:
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"mcpServers": {
|
|
143
|
+
"magek": {
|
|
144
|
+
"command": "npx",
|
|
145
|
+
"args": ["-y", "@magek/mcp-server"],
|
|
146
|
+
"env": {
|
|
147
|
+
"MAGEK_DOCS_PATH": "./docs/content"
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Troubleshooting
|
|
155
|
+
|
|
156
|
+
### MCP Server Not Found
|
|
157
|
+
|
|
158
|
+
Make sure you have Node.js 22+ installed:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
node -v
|
|
162
|
+
# Should output v22.x.x or higher
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Documentation Not Loading
|
|
166
|
+
|
|
167
|
+
The MCP server bundles documentation from the published package. If you need the latest docs, update the package:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
npx -y @magek/mcp-server@latest
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Claude Code Can't Find Magek
|
|
174
|
+
|
|
175
|
+
Verify the MCP server is configured:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
claude mcp list
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
You should see `magek` in the list of configured servers.
|