@fredrika/mcp-mochi 1.0.0 → 1.0.2
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 +3 -3
- package/dist/common/version.d.ts +1 -0
- package/dist/common/version.js +3 -0
- package/dist/index.d.ts +186 -75
- package/dist/index.js +308 -112
- package/package.json +2 -2
- package/dist/mochi-client.d.ts +0 -74
- package/dist/mochi-client.js +0 -67
- package/dist/test-mochi-api.d.ts +0 -1
- package/dist/test-mochi-api.js +0 -69
package/README.md
CHANGED
|
@@ -114,7 +114,7 @@ To use this with Claude Desktop, add the following to your `claude_desktop_confi
|
|
|
114
114
|
```json
|
|
115
115
|
{
|
|
116
116
|
"mcpServers": {
|
|
117
|
-
"
|
|
117
|
+
"mochi": {
|
|
118
118
|
"command": "docker",
|
|
119
119
|
"args": [
|
|
120
120
|
"run",
|
|
@@ -137,11 +137,11 @@ To use this with Claude Desktop, add the following to your `claude_desktop_confi
|
|
|
137
137
|
```json
|
|
138
138
|
{
|
|
139
139
|
"mcpServers": {
|
|
140
|
-
"
|
|
140
|
+
"mochi": {
|
|
141
141
|
"command": "npx",
|
|
142
142
|
"args": [
|
|
143
143
|
"-y",
|
|
144
|
-
"@
|
|
144
|
+
"@fredrika/mcp-mochi"
|
|
145
145
|
],
|
|
146
146
|
"env": {
|
|
147
147
|
"MOCHI_API_KEY": "<YOUR_TOKEN>"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const VERSION = "1.0.2";
|
package/dist/index.d.ts
CHANGED
|
@@ -4,11 +4,8 @@ declare const CreateCardRequestSchema: z.ZodObject<{
|
|
|
4
4
|
content: z.ZodString;
|
|
5
5
|
"deck-id": z.ZodString;
|
|
6
6
|
"template-id": z.ZodOptional<z.ZodString>;
|
|
7
|
-
archived: z.ZodOptional<z.ZodBoolean>;
|
|
8
|
-
"review-reverse": z.ZodOptional<z.ZodBoolean>;
|
|
9
|
-
pos: z.ZodOptional<z.ZodString>;
|
|
10
7
|
"manual-tags": z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
11
|
-
fields: z.
|
|
8
|
+
fields: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
12
9
|
id: z.ZodString;
|
|
13
10
|
value: z.ZodString;
|
|
14
11
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -17,31 +14,62 @@ declare const CreateCardRequestSchema: z.ZodObject<{
|
|
|
17
14
|
}, {
|
|
18
15
|
id: string;
|
|
19
16
|
value: string;
|
|
20
|
-
}
|
|
17
|
+
}>>;
|
|
21
18
|
}, "strip", z.ZodTypeAny, {
|
|
22
19
|
content: string;
|
|
23
20
|
"deck-id": string;
|
|
21
|
+
fields: Record<string, {
|
|
22
|
+
id: string;
|
|
23
|
+
value: string;
|
|
24
|
+
}>;
|
|
25
|
+
"template-id"?: string | undefined;
|
|
26
|
+
"manual-tags"?: string[] | undefined;
|
|
27
|
+
}, {
|
|
28
|
+
content: string;
|
|
29
|
+
"deck-id": string;
|
|
30
|
+
fields: Record<string, {
|
|
31
|
+
id: string;
|
|
32
|
+
value: string;
|
|
33
|
+
}>;
|
|
24
34
|
"template-id"?: string | undefined;
|
|
25
|
-
archived?: boolean | undefined;
|
|
26
|
-
"review-reverse"?: boolean | undefined;
|
|
27
|
-
pos?: string | undefined;
|
|
28
35
|
"manual-tags"?: string[] | undefined;
|
|
36
|
+
}>;
|
|
37
|
+
declare const UpdateCardRequestSchema: z.ZodObject<{
|
|
38
|
+
content: z.ZodOptional<z.ZodString>;
|
|
39
|
+
"deck-id": z.ZodOptional<z.ZodString>;
|
|
40
|
+
"template-id": z.ZodOptional<z.ZodString>;
|
|
41
|
+
"archived?": z.ZodOptional<z.ZodBoolean>;
|
|
42
|
+
"trashed?": z.ZodOptional<z.ZodString>;
|
|
43
|
+
fields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
44
|
+
id: z.ZodString;
|
|
45
|
+
value: z.ZodString;
|
|
46
|
+
}, "strip", z.ZodTypeAny, {
|
|
47
|
+
id: string;
|
|
48
|
+
value: string;
|
|
49
|
+
}, {
|
|
50
|
+
id: string;
|
|
51
|
+
value: string;
|
|
52
|
+
}>>>;
|
|
53
|
+
}, "strip", z.ZodTypeAny, {
|
|
54
|
+
content?: string | undefined;
|
|
55
|
+
"deck-id"?: string | undefined;
|
|
56
|
+
"template-id"?: string | undefined;
|
|
29
57
|
fields?: Record<string, {
|
|
30
58
|
id: string;
|
|
31
59
|
value: string;
|
|
32
60
|
}> | undefined;
|
|
61
|
+
"archived?"?: boolean | undefined;
|
|
62
|
+
"trashed?"?: string | undefined;
|
|
33
63
|
}, {
|
|
34
|
-
content
|
|
35
|
-
"deck-id"
|
|
64
|
+
content?: string | undefined;
|
|
65
|
+
"deck-id"?: string | undefined;
|
|
36
66
|
"template-id"?: string | undefined;
|
|
37
|
-
archived?: boolean | undefined;
|
|
38
|
-
"review-reverse"?: boolean | undefined;
|
|
39
|
-
pos?: string | undefined;
|
|
40
|
-
"manual-tags"?: string[] | undefined;
|
|
41
67
|
fields?: Record<string, {
|
|
42
68
|
id: string;
|
|
43
69
|
value: string;
|
|
44
70
|
}> | undefined;
|
|
71
|
+
"archived?"?: boolean | undefined;
|
|
72
|
+
"trashed?"?: string | undefined;
|
|
45
73
|
}>;
|
|
46
74
|
declare const ListDecksParamsSchema: z.ZodObject<{
|
|
47
75
|
bookmark: z.ZodOptional<z.ZodString>;
|
|
@@ -63,54 +91,134 @@ declare const ListCardsParamsSchema: z.ZodObject<{
|
|
|
63
91
|
bookmark?: string | undefined;
|
|
64
92
|
limit?: number | undefined;
|
|
65
93
|
}>;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
type CreateCardRequest = z.infer<typeof CreateCardRequestSchema>;
|
|
69
|
-
declare const CreateCardResponseSchema: z.ZodObject<{
|
|
70
|
-
status: z.ZodString;
|
|
71
|
-
error_message: z.ZodOptional<z.ZodString>;
|
|
94
|
+
declare const ListTemplatesParamsSchema: z.ZodObject<{
|
|
95
|
+
bookmark: z.ZodOptional<z.ZodString>;
|
|
72
96
|
}, "strip", z.ZodTypeAny, {
|
|
73
|
-
|
|
74
|
-
error_message?: string | undefined;
|
|
97
|
+
bookmark?: string | undefined;
|
|
75
98
|
}, {
|
|
76
|
-
|
|
77
|
-
error_message?: string | undefined;
|
|
99
|
+
bookmark?: string | undefined;
|
|
78
100
|
}>;
|
|
79
|
-
declare const
|
|
101
|
+
declare const ListTemplatesResponseSchema: z.ZodObject<{
|
|
80
102
|
bookmark: z.ZodString;
|
|
81
103
|
docs: z.ZodArray<z.ZodObject<{
|
|
82
104
|
id: z.ZodString;
|
|
83
|
-
sort: z.ZodNumber;
|
|
84
105
|
name: z.ZodString;
|
|
85
|
-
|
|
106
|
+
content: z.ZodString;
|
|
107
|
+
pos: z.ZodString;
|
|
108
|
+
fields: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
109
|
+
id: z.ZodString;
|
|
110
|
+
name: z.ZodString;
|
|
111
|
+
pos: z.ZodString;
|
|
112
|
+
options: z.ZodOptional<z.ZodObject<{
|
|
113
|
+
"multi-line?": z.ZodOptional<z.ZodBoolean>;
|
|
114
|
+
}, "strip", z.ZodTypeAny, {
|
|
115
|
+
"multi-line?"?: boolean | undefined;
|
|
116
|
+
}, {
|
|
117
|
+
"multi-line?"?: boolean | undefined;
|
|
118
|
+
}>>;
|
|
119
|
+
}, "strip", z.ZodTypeAny, {
|
|
120
|
+
name: string;
|
|
121
|
+
id: string;
|
|
122
|
+
pos: string;
|
|
123
|
+
options?: {
|
|
124
|
+
"multi-line?"?: boolean | undefined;
|
|
125
|
+
} | undefined;
|
|
126
|
+
}, {
|
|
127
|
+
name: string;
|
|
128
|
+
id: string;
|
|
129
|
+
pos: string;
|
|
130
|
+
options?: {
|
|
131
|
+
"multi-line?"?: boolean | undefined;
|
|
132
|
+
} | undefined;
|
|
133
|
+
}>>;
|
|
86
134
|
}, "strip", z.ZodTypeAny, {
|
|
87
|
-
sort: number;
|
|
88
135
|
name: string;
|
|
89
136
|
id: string;
|
|
90
|
-
|
|
137
|
+
content: string;
|
|
138
|
+
fields: Record<string, {
|
|
139
|
+
name: string;
|
|
140
|
+
id: string;
|
|
141
|
+
pos: string;
|
|
142
|
+
options?: {
|
|
143
|
+
"multi-line?"?: boolean | undefined;
|
|
144
|
+
} | undefined;
|
|
145
|
+
}>;
|
|
146
|
+
pos: string;
|
|
91
147
|
}, {
|
|
92
|
-
sort: number;
|
|
93
148
|
name: string;
|
|
94
149
|
id: string;
|
|
95
|
-
|
|
150
|
+
content: string;
|
|
151
|
+
fields: Record<string, {
|
|
152
|
+
name: string;
|
|
153
|
+
id: string;
|
|
154
|
+
pos: string;
|
|
155
|
+
options?: {
|
|
156
|
+
"multi-line?"?: boolean | undefined;
|
|
157
|
+
} | undefined;
|
|
158
|
+
}>;
|
|
159
|
+
pos: string;
|
|
96
160
|
}>, "many">;
|
|
97
161
|
}, "strip", z.ZodTypeAny, {
|
|
98
162
|
bookmark: string;
|
|
99
163
|
docs: {
|
|
100
|
-
sort: number;
|
|
101
164
|
name: string;
|
|
102
165
|
id: string;
|
|
103
|
-
|
|
166
|
+
content: string;
|
|
167
|
+
fields: Record<string, {
|
|
168
|
+
name: string;
|
|
169
|
+
id: string;
|
|
170
|
+
pos: string;
|
|
171
|
+
options?: {
|
|
172
|
+
"multi-line?"?: boolean | undefined;
|
|
173
|
+
} | undefined;
|
|
174
|
+
}>;
|
|
175
|
+
pos: string;
|
|
104
176
|
}[];
|
|
105
177
|
}, {
|
|
106
178
|
bookmark: string;
|
|
107
179
|
docs: {
|
|
108
|
-
sort: number;
|
|
109
180
|
name: string;
|
|
110
181
|
id: string;
|
|
111
|
-
|
|
182
|
+
content: string;
|
|
183
|
+
fields: Record<string, {
|
|
184
|
+
name: string;
|
|
185
|
+
id: string;
|
|
186
|
+
pos: string;
|
|
187
|
+
options?: {
|
|
188
|
+
"multi-line?"?: boolean | undefined;
|
|
189
|
+
} | undefined;
|
|
190
|
+
}>;
|
|
191
|
+
pos: string;
|
|
112
192
|
}[];
|
|
113
193
|
}>;
|
|
194
|
+
type ListTemplatesParams = z.infer<typeof ListTemplatesParamsSchema>;
|
|
195
|
+
type ListTemplatesResponse = z.infer<typeof ListTemplatesResponseSchema>;
|
|
196
|
+
type ListCardsParams = z.infer<typeof ListCardsParamsSchema>;
|
|
197
|
+
type ListDecksParams = z.infer<typeof ListDecksParamsSchema>;
|
|
198
|
+
type CreateCardRequest = z.infer<typeof CreateCardRequestSchema>;
|
|
199
|
+
type UpdateCardRequest = z.infer<typeof UpdateCardRequestSchema>;
|
|
200
|
+
declare const CreateCardResponseSchema: z.ZodObject<{
|
|
201
|
+
id: z.ZodString;
|
|
202
|
+
tags: z.ZodArray<z.ZodString, "many">;
|
|
203
|
+
content: z.ZodString;
|
|
204
|
+
name: z.ZodString;
|
|
205
|
+
"deck-id": z.ZodString;
|
|
206
|
+
fields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
207
|
+
}, "strip", z.ZodTypeAny, {
|
|
208
|
+
name: string;
|
|
209
|
+
id: string;
|
|
210
|
+
content: string;
|
|
211
|
+
"deck-id": string;
|
|
212
|
+
tags: string[];
|
|
213
|
+
fields?: Record<string, unknown> | undefined;
|
|
214
|
+
}, {
|
|
215
|
+
name: string;
|
|
216
|
+
id: string;
|
|
217
|
+
content: string;
|
|
218
|
+
"deck-id": string;
|
|
219
|
+
tags: string[];
|
|
220
|
+
fields?: Record<string, unknown> | undefined;
|
|
221
|
+
}>;
|
|
114
222
|
declare const ListCardsResponseSchema: z.ZodObject<{
|
|
115
223
|
bookmark: z.ZodString;
|
|
116
224
|
docs: z.ZodArray<z.ZodObject<{
|
|
@@ -119,43 +227,21 @@ declare const ListCardsResponseSchema: z.ZodObject<{
|
|
|
119
227
|
content: z.ZodString;
|
|
120
228
|
name: z.ZodString;
|
|
121
229
|
"deck-id": z.ZodString;
|
|
122
|
-
fields: z.ZodRecord<z.ZodString, z.ZodUnknown
|
|
123
|
-
pos: z.ZodString;
|
|
124
|
-
references: z.ZodArray<z.ZodUnknown, "many">;
|
|
125
|
-
reviews: z.ZodArray<z.ZodUnknown, "many">;
|
|
126
|
-
"created-at": z.ZodObject<{
|
|
127
|
-
date: z.ZodString;
|
|
128
|
-
}, "strip", z.ZodTypeAny, {
|
|
129
|
-
date: string;
|
|
130
|
-
}, {
|
|
131
|
-
date: string;
|
|
132
|
-
}>;
|
|
230
|
+
fields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
133
231
|
}, "strip", z.ZodTypeAny, {
|
|
134
232
|
name: string;
|
|
135
233
|
id: string;
|
|
136
234
|
content: string;
|
|
137
235
|
"deck-id": string;
|
|
138
|
-
pos: string;
|
|
139
|
-
fields: Record<string, unknown>;
|
|
140
236
|
tags: string[];
|
|
141
|
-
|
|
142
|
-
reviews: unknown[];
|
|
143
|
-
"created-at": {
|
|
144
|
-
date: string;
|
|
145
|
-
};
|
|
237
|
+
fields?: Record<string, unknown> | undefined;
|
|
146
238
|
}, {
|
|
147
239
|
name: string;
|
|
148
240
|
id: string;
|
|
149
241
|
content: string;
|
|
150
242
|
"deck-id": string;
|
|
151
|
-
pos: string;
|
|
152
|
-
fields: Record<string, unknown>;
|
|
153
243
|
tags: string[];
|
|
154
|
-
|
|
155
|
-
reviews: unknown[];
|
|
156
|
-
"created-at": {
|
|
157
|
-
date: string;
|
|
158
|
-
};
|
|
244
|
+
fields?: Record<string, unknown> | undefined;
|
|
159
245
|
}>, "many">;
|
|
160
246
|
}, "strip", z.ZodTypeAny, {
|
|
161
247
|
bookmark: string;
|
|
@@ -164,14 +250,8 @@ declare const ListCardsResponseSchema: z.ZodObject<{
|
|
|
164
250
|
id: string;
|
|
165
251
|
content: string;
|
|
166
252
|
"deck-id": string;
|
|
167
|
-
pos: string;
|
|
168
|
-
fields: Record<string, unknown>;
|
|
169
253
|
tags: string[];
|
|
170
|
-
|
|
171
|
-
reviews: unknown[];
|
|
172
|
-
"created-at": {
|
|
173
|
-
date: string;
|
|
174
|
-
};
|
|
254
|
+
fields?: Record<string, unknown> | undefined;
|
|
175
255
|
}[];
|
|
176
256
|
}, {
|
|
177
257
|
bookmark: string;
|
|
@@ -180,25 +260,56 @@ declare const ListCardsResponseSchema: z.ZodObject<{
|
|
|
180
260
|
id: string;
|
|
181
261
|
content: string;
|
|
182
262
|
"deck-id": string;
|
|
183
|
-
pos: string;
|
|
184
|
-
fields: Record<string, unknown>;
|
|
185
263
|
tags: string[];
|
|
186
|
-
|
|
187
|
-
reviews: unknown[];
|
|
188
|
-
"created-at": {
|
|
189
|
-
date: string;
|
|
190
|
-
};
|
|
264
|
+
fields?: Record<string, unknown> | undefined;
|
|
191
265
|
}[];
|
|
192
266
|
}>;
|
|
193
267
|
type CreateCardResponse = z.infer<typeof CreateCardResponseSchema>;
|
|
194
|
-
type ListDecksResponse = z.infer<typeof ListDecksResponseSchema
|
|
268
|
+
type ListDecksResponse = z.infer<typeof ListDecksResponseSchema>["docs"];
|
|
195
269
|
type ListCardsResponse = z.infer<typeof ListCardsResponseSchema>;
|
|
270
|
+
declare const ListDecksResponseSchema: z.ZodObject<{
|
|
271
|
+
bookmark: z.ZodString;
|
|
272
|
+
docs: z.ZodArray<z.ZodObject<{
|
|
273
|
+
id: z.ZodString;
|
|
274
|
+
sort: z.ZodNumber;
|
|
275
|
+
name: z.ZodString;
|
|
276
|
+
archived: z.ZodOptional<z.ZodBoolean>;
|
|
277
|
+
}, "strip", z.ZodTypeAny, {
|
|
278
|
+
sort: number;
|
|
279
|
+
name: string;
|
|
280
|
+
id: string;
|
|
281
|
+
archived?: boolean | undefined;
|
|
282
|
+
}, {
|
|
283
|
+
sort: number;
|
|
284
|
+
name: string;
|
|
285
|
+
id: string;
|
|
286
|
+
archived?: boolean | undefined;
|
|
287
|
+
}>, "many">;
|
|
288
|
+
}, "strip", z.ZodTypeAny, {
|
|
289
|
+
bookmark: string;
|
|
290
|
+
docs: {
|
|
291
|
+
sort: number;
|
|
292
|
+
name: string;
|
|
293
|
+
id: string;
|
|
294
|
+
archived?: boolean | undefined;
|
|
295
|
+
}[];
|
|
296
|
+
}, {
|
|
297
|
+
bookmark: string;
|
|
298
|
+
docs: {
|
|
299
|
+
sort: number;
|
|
300
|
+
name: string;
|
|
301
|
+
id: string;
|
|
302
|
+
archived?: boolean | undefined;
|
|
303
|
+
}[];
|
|
304
|
+
}>;
|
|
196
305
|
export declare class MochiClient {
|
|
197
306
|
private api;
|
|
198
307
|
private token;
|
|
199
308
|
constructor(token: string);
|
|
200
309
|
createCard(request: CreateCardRequest): Promise<CreateCardResponse>;
|
|
310
|
+
updateCard(cardId: string, request: UpdateCardRequest): Promise<CreateCardResponse>;
|
|
201
311
|
listDecks(params?: ListDecksParams): Promise<ListDecksResponse>;
|
|
202
312
|
listCards(params?: ListCardsParams): Promise<ListCardsResponse>;
|
|
313
|
+
listTemplates(params?: ListTemplatesParams): Promise<ListTemplatesResponse>;
|
|
203
314
|
}
|
|
204
315
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
5
5
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
6
|
import dotenv from "dotenv";
|
|
7
7
|
import { z } from "zod";
|
|
8
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
8
9
|
dotenv.config();
|
|
9
10
|
/**
|
|
10
11
|
* Custom error class for Mochi API errors
|
|
@@ -34,10 +35,15 @@ const CreateCardRequestSchema = z.object({
|
|
|
34
35
|
content: z.string().min(1),
|
|
35
36
|
"deck-id": z.string().min(1),
|
|
36
37
|
"template-id": z.string().optional(),
|
|
37
|
-
archived: z.boolean().optional(),
|
|
38
|
-
"review-reverse": z.boolean().optional(),
|
|
39
|
-
pos: z.string().optional(),
|
|
40
38
|
"manual-tags": z.array(z.string()).optional(),
|
|
39
|
+
fields: z.record(z.string(), CreateCardFieldSchema),
|
|
40
|
+
});
|
|
41
|
+
const UpdateCardRequestSchema = z.object({
|
|
42
|
+
content: z.string().optional(),
|
|
43
|
+
"deck-id": z.string().optional(),
|
|
44
|
+
"template-id": z.string().optional(),
|
|
45
|
+
"archived?": z.boolean().optional(),
|
|
46
|
+
"trashed?": z.string().optional(),
|
|
41
47
|
fields: z.record(z.string(), CreateCardFieldSchema).optional(),
|
|
42
48
|
});
|
|
43
49
|
const ListDecksParamsSchema = z.object({
|
|
@@ -48,27 +54,35 @@ const ListCardsParamsSchema = z.object({
|
|
|
48
54
|
limit: z.number().min(1).max(100).optional(),
|
|
49
55
|
bookmark: z.string().optional(),
|
|
50
56
|
});
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
.
|
|
58
|
-
|
|
57
|
+
const ListTemplatesParamsSchema = z.object({
|
|
58
|
+
bookmark: z.string().optional(),
|
|
59
|
+
});
|
|
60
|
+
const TemplateFieldSchema = z.object({
|
|
61
|
+
id: z.string(),
|
|
62
|
+
name: z.string(),
|
|
63
|
+
pos: z.string(),
|
|
64
|
+
options: z
|
|
65
|
+
.object({
|
|
66
|
+
"multi-line?": z.boolean().optional(),
|
|
67
|
+
})
|
|
68
|
+
.optional(),
|
|
69
|
+
});
|
|
70
|
+
const TemplateSchema = z
|
|
59
71
|
.object({
|
|
60
72
|
id: z.string(),
|
|
61
|
-
sort: z.number(),
|
|
62
73
|
name: z.string(),
|
|
63
|
-
|
|
74
|
+
content: z.string(),
|
|
75
|
+
pos: z.string(),
|
|
76
|
+
fields: z.record(z.string(), TemplateFieldSchema),
|
|
64
77
|
})
|
|
65
78
|
.strip();
|
|
66
|
-
const
|
|
79
|
+
const ListTemplatesResponseSchema = z
|
|
67
80
|
.object({
|
|
68
81
|
bookmark: z.string(),
|
|
69
|
-
docs: z.array(
|
|
82
|
+
docs: z.array(TemplateSchema),
|
|
70
83
|
})
|
|
71
84
|
.strip();
|
|
85
|
+
// Response Zod schemas
|
|
72
86
|
const CardSchema = z
|
|
73
87
|
.object({
|
|
74
88
|
id: z.string(),
|
|
@@ -76,21 +90,30 @@ const CardSchema = z
|
|
|
76
90
|
content: z.string(),
|
|
77
91
|
name: z.string(),
|
|
78
92
|
"deck-id": z.string(),
|
|
79
|
-
fields: z.record(z.unknown()),
|
|
80
|
-
pos: z.string(),
|
|
81
|
-
references: z.array(z.unknown()),
|
|
82
|
-
reviews: z.array(z.unknown()),
|
|
83
|
-
"created-at": z.object({
|
|
84
|
-
date: z.string(),
|
|
85
|
-
}),
|
|
93
|
+
fields: z.record(z.unknown()).optional(),
|
|
86
94
|
})
|
|
87
95
|
.strip();
|
|
96
|
+
const CreateCardResponseSchema = CardSchema.strip();
|
|
88
97
|
const ListCardsResponseSchema = z
|
|
89
98
|
.object({
|
|
90
99
|
bookmark: z.string(),
|
|
91
100
|
docs: z.array(CardSchema),
|
|
92
101
|
})
|
|
93
102
|
.strip();
|
|
103
|
+
const DeckSchema = z
|
|
104
|
+
.object({
|
|
105
|
+
id: z.string(),
|
|
106
|
+
sort: z.number(),
|
|
107
|
+
name: z.string(),
|
|
108
|
+
archived: z.boolean().optional(),
|
|
109
|
+
})
|
|
110
|
+
.strip();
|
|
111
|
+
const ListDecksResponseSchema = z
|
|
112
|
+
.object({
|
|
113
|
+
bookmark: z.string(),
|
|
114
|
+
docs: z.array(DeckSchema),
|
|
115
|
+
})
|
|
116
|
+
.strip();
|
|
94
117
|
function getApiKey() {
|
|
95
118
|
const apiKey = process.env.MOCHI_API_KEY;
|
|
96
119
|
if (!apiKey) {
|
|
@@ -100,59 +123,6 @@ function getApiKey() {
|
|
|
100
123
|
return apiKey;
|
|
101
124
|
}
|
|
102
125
|
const MOCHI_API_KEY = getApiKey();
|
|
103
|
-
// Tool definitions
|
|
104
|
-
const CREATE_CARD_TOOL = {
|
|
105
|
-
name: "mochi_create_card",
|
|
106
|
-
description: "Create a new flashcard",
|
|
107
|
-
inputSchema: {
|
|
108
|
-
type: "object",
|
|
109
|
-
properties: {
|
|
110
|
-
content: {
|
|
111
|
-
type: "string",
|
|
112
|
-
description: "The markdown content of the card. Separate front from back with `\n---\n`",
|
|
113
|
-
},
|
|
114
|
-
"deck-id": {
|
|
115
|
-
type: "string",
|
|
116
|
-
description: "The deck ID that the card belongs too.",
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
required: ["content", "deck-id"],
|
|
120
|
-
},
|
|
121
|
-
};
|
|
122
|
-
const LIST_CARDS_TOOL = {
|
|
123
|
-
name: "mochi_list_cards",
|
|
124
|
-
description: "List cards in pages of 10 cards per page",
|
|
125
|
-
inputSchema: {
|
|
126
|
-
type: "object",
|
|
127
|
-
properties: {
|
|
128
|
-
"deck-id": {
|
|
129
|
-
type: "string",
|
|
130
|
-
description: "Only return cards for the specified deck ID",
|
|
131
|
-
},
|
|
132
|
-
limit: {
|
|
133
|
-
type: "number",
|
|
134
|
-
description: "Number of cards to return per page (1-100, default 10)",
|
|
135
|
-
},
|
|
136
|
-
bookmark: {
|
|
137
|
-
type: "string",
|
|
138
|
-
description: "Cursor for pagination from a previous list request",
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
},
|
|
142
|
-
};
|
|
143
|
-
const LIST_DECKS_TOOL = {
|
|
144
|
-
name: "mochi_list_decks",
|
|
145
|
-
description: "List all decks",
|
|
146
|
-
inputSchema: {
|
|
147
|
-
type: "object",
|
|
148
|
-
properties: {},
|
|
149
|
-
},
|
|
150
|
-
};
|
|
151
|
-
const MOCHI_TOOLS = [
|
|
152
|
-
CREATE_CARD_TOOL,
|
|
153
|
-
LIST_CARDS_TOOL,
|
|
154
|
-
LIST_DECKS_TOOL,
|
|
155
|
-
];
|
|
156
126
|
export class MochiClient {
|
|
157
127
|
api;
|
|
158
128
|
token;
|
|
@@ -170,12 +140,16 @@ export class MochiClient {
|
|
|
170
140
|
const response = await this.api.post("/cards", request);
|
|
171
141
|
return CreateCardResponseSchema.parse(response.data);
|
|
172
142
|
}
|
|
143
|
+
async updateCard(cardId, request) {
|
|
144
|
+
const response = await this.api.post(`/cards/${cardId}`, request);
|
|
145
|
+
return CreateCardResponseSchema.parse(response.data);
|
|
146
|
+
}
|
|
173
147
|
async listDecks(params) {
|
|
174
148
|
const validatedParams = params
|
|
175
149
|
? ListDecksParamsSchema.parse(params)
|
|
176
150
|
: undefined;
|
|
177
151
|
const response = await this.api.get("/decks", { params: validatedParams });
|
|
178
|
-
return ListDecksResponseSchema.parse(response.data);
|
|
152
|
+
return ListDecksResponseSchema.parse(response.data).docs.filter((deck) => !deck.archived);
|
|
179
153
|
}
|
|
180
154
|
async listCards(params) {
|
|
181
155
|
const validatedParams = params
|
|
@@ -184,11 +158,20 @@ export class MochiClient {
|
|
|
184
158
|
const response = await this.api.get("/cards", { params: validatedParams });
|
|
185
159
|
return ListCardsResponseSchema.parse(response.data);
|
|
186
160
|
}
|
|
161
|
+
async listTemplates(params) {
|
|
162
|
+
const validatedParams = params
|
|
163
|
+
? ListTemplatesParamsSchema.parse(params)
|
|
164
|
+
: undefined;
|
|
165
|
+
const response = await this.api.get("/templates", {
|
|
166
|
+
params: validatedParams,
|
|
167
|
+
});
|
|
168
|
+
return ListTemplatesResponseSchema.parse(response.data);
|
|
169
|
+
}
|
|
187
170
|
}
|
|
188
171
|
// Server setup
|
|
189
172
|
const server = new Server({
|
|
190
173
|
name: "mcp-server/mochi",
|
|
191
|
-
version: "
|
|
174
|
+
version: "1.0.2",
|
|
192
175
|
}, {
|
|
193
176
|
capabilities: {
|
|
194
177
|
tools: {},
|
|
@@ -197,59 +180,267 @@ const server = new Server({
|
|
|
197
180
|
});
|
|
198
181
|
// Set up request handlers
|
|
199
182
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
200
|
-
tools:
|
|
183
|
+
tools: [
|
|
184
|
+
{
|
|
185
|
+
name: "mochi_create_card",
|
|
186
|
+
description: `Create a new flashcard in Mochi. Use this whenever I ask questions about something that is interesting to remember. E.g. if I ask "What is the capital of France?", you should create a new flashcard with the content "What is the capital of France?\n---\nParis".
|
|
187
|
+
|
|
188
|
+
## Parameters
|
|
189
|
+
|
|
190
|
+
### deck-id (required)
|
|
191
|
+
ALWAYS look up deck-id with the mochi_list_decks tool.
|
|
192
|
+
|
|
193
|
+
### content (required)
|
|
194
|
+
The markdown content of the card. Separate front and back using a horizontal rule (---).
|
|
195
|
+
|
|
196
|
+
### fields (optional)
|
|
197
|
+
A map of field IDs (keyword) to field values. The field IDs should correspond to the fields defined on the template used by the card.
|
|
198
|
+
|
|
199
|
+
## Example
|
|
200
|
+
{
|
|
201
|
+
"content": "New card from API. ",
|
|
202
|
+
"deck-id": "btmZUXWM",
|
|
203
|
+
"template-id": "8BtaEAXe",
|
|
204
|
+
"fields": {
|
|
205
|
+
"name": {
|
|
206
|
+
"id": "name",
|
|
207
|
+
"value": "Hello,"
|
|
208
|
+
},
|
|
209
|
+
"JNEnw1e7": {
|
|
210
|
+
"id": "JNEnw1e7",
|
|
211
|
+
"value": "World!"
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
## Good cards:
|
|
217
|
+
- **concise**: as short question and answer as possible.
|
|
218
|
+
- **focused:** A question or answer involving too much detail will dull your concentration and stimulate incomplete retrievals, leaving some bulbs unlit.
|
|
219
|
+
- **precise** about what they're asking for. Vague questions will elicit vague answers, which won't reliably light the bulbs you're targeting.
|
|
220
|
+
- **consistent** answers, lighting the same bulbs each time you perform the task.
|
|
221
|
+
- **tractable**: Write prompts which you can almost always answer correctly. This often means breaking the task down, or adding cues
|
|
222
|
+
- **effortful**: You shouldn't be able to trivially infer the answer.
|
|
223
|
+
`,
|
|
224
|
+
inputSchema: zodToJsonSchema(CreateCardRequestSchema),
|
|
225
|
+
annotations: {
|
|
226
|
+
title: "Create flashcard on Mochi",
|
|
227
|
+
readOnlyHint: false,
|
|
228
|
+
destructiveHint: false,
|
|
229
|
+
idempotentHint: false,
|
|
230
|
+
openWorldHint: true,
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
name: "mochi_update_card",
|
|
235
|
+
description: `Update an existing flashcard in Mochi.`,
|
|
236
|
+
inputSchema: zodToJsonSchema(z.object({
|
|
237
|
+
"card-id": z.string(),
|
|
238
|
+
...UpdateCardRequestSchema.shape,
|
|
239
|
+
})),
|
|
240
|
+
annotations: {
|
|
241
|
+
title: "Update flashcard on Mochi",
|
|
242
|
+
readOnlyHint: false,
|
|
243
|
+
destructiveHint: false,
|
|
244
|
+
idempotentHint: false,
|
|
245
|
+
openWorldHint: true,
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
name: "mochi_list_cards",
|
|
250
|
+
description: "List cards in pages of 10 cards per page",
|
|
251
|
+
inputSchema: zodToJsonSchema(ListCardsParamsSchema),
|
|
252
|
+
annotations: {
|
|
253
|
+
title: "List flashcards on Mochi",
|
|
254
|
+
readOnlyHint: true,
|
|
255
|
+
destructiveHint: false,
|
|
256
|
+
idempotentHint: true,
|
|
257
|
+
openWorldHint: false,
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
name: "mochi_list_decks",
|
|
262
|
+
description: "List all decks",
|
|
263
|
+
inputSchema: zodToJsonSchema(ListDecksParamsSchema),
|
|
264
|
+
annotations: {
|
|
265
|
+
title: "List decks on Mochi",
|
|
266
|
+
readOnlyHint: true,
|
|
267
|
+
destructiveHint: false,
|
|
268
|
+
idempotentHint: true,
|
|
269
|
+
openWorldHint: false,
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
name: "mochi_list_templates",
|
|
274
|
+
description: `Templates can be used to create cards with pre-defined fields using the template_id field.
|
|
275
|
+
|
|
276
|
+
Example response:
|
|
277
|
+
{
|
|
278
|
+
"bookmark": "g1AAAABAeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYpzVBn4JgaaVZiC5Dlg8igyWQAxwRHd",
|
|
279
|
+
"docs": [
|
|
280
|
+
{
|
|
281
|
+
"id": "YDELNZSu",
|
|
282
|
+
"name": "Simple flashcard",
|
|
283
|
+
"content": "# << Front >>\n---\n<< Back >>",
|
|
284
|
+
"pos": "s",
|
|
285
|
+
"fields": {
|
|
286
|
+
"name": {
|
|
287
|
+
"id": "name",
|
|
288
|
+
"name": "Front",
|
|
289
|
+
"pos": "a"
|
|
290
|
+
},
|
|
291
|
+
"Ysrde7Lj": {
|
|
292
|
+
"id": "Ysrde7Lj",
|
|
293
|
+
"name": "Back",
|
|
294
|
+
"pos": "m",
|
|
295
|
+
"options": {
|
|
296
|
+
"multi-line?": true
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
...
|
|
302
|
+
]
|
|
303
|
+
}`,
|
|
304
|
+
inputSchema: zodToJsonSchema(ListTemplatesParamsSchema),
|
|
305
|
+
annotations: {
|
|
306
|
+
title: "List templates on Mochi",
|
|
307
|
+
readOnlyHint: true,
|
|
308
|
+
destructiveHint: false,
|
|
309
|
+
idempotentHint: true,
|
|
310
|
+
openWorldHint: false,
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
],
|
|
201
314
|
}));
|
|
315
|
+
// Create Mochi client
|
|
316
|
+
const mochiClient = new MochiClient(MOCHI_API_KEY);
|
|
202
317
|
// Add resource handlers
|
|
203
318
|
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
204
|
-
const decks = await mochiClient.listDecks();
|
|
205
|
-
return {
|
|
206
|
-
resources: decks.docs.map((deck) => ({
|
|
207
|
-
uri: `mochi://decks/${deck.id}`,
|
|
208
|
-
name: deck.name + ` (Deck ID: ${deck.id})`,
|
|
209
|
-
description: `Deck ID: ${deck.id}`,
|
|
210
|
-
mimeType: "application/json",
|
|
211
|
-
})),
|
|
212
|
-
};
|
|
213
|
-
});
|
|
214
|
-
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
215
|
-
const uri = request.params.uri;
|
|
216
|
-
const match = uri.match(/^mochi:\/\/decks\/(.+)$/);
|
|
217
|
-
if (!match) {
|
|
218
|
-
throw new Error("Invalid resource URI");
|
|
219
|
-
}
|
|
220
|
-
const deckId = match[1];
|
|
221
|
-
const deck = await mochiClient.listCards({ "deck-id": deckId });
|
|
222
319
|
return {
|
|
223
|
-
|
|
320
|
+
resources: [
|
|
224
321
|
{
|
|
225
|
-
uri
|
|
322
|
+
uri: `mochi://decks`,
|
|
323
|
+
name: "All Mochi Decks",
|
|
324
|
+
description: `List of all decks in Mochi.`,
|
|
325
|
+
mimeType: "application/json",
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
uri: `mochi://templates`,
|
|
329
|
+
name: "All Mochi Templates",
|
|
330
|
+
description: `List of all templates in Mochi.`,
|
|
226
331
|
mimeType: "application/json",
|
|
227
|
-
text: JSON.stringify(deck.docs.map((card) => ({
|
|
228
|
-
id: card.id,
|
|
229
|
-
name: card.name,
|
|
230
|
-
content: card.content,
|
|
231
|
-
fields: card.fields,
|
|
232
|
-
})), null, 2),
|
|
233
332
|
},
|
|
234
333
|
],
|
|
235
334
|
};
|
|
236
335
|
});
|
|
237
|
-
|
|
238
|
-
const
|
|
336
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
337
|
+
const uri = request.params.uri;
|
|
338
|
+
switch (uri) {
|
|
339
|
+
case "mochi://decks": {
|
|
340
|
+
const decks = await mochiClient.listDecks();
|
|
341
|
+
return {
|
|
342
|
+
contents: [
|
|
343
|
+
{
|
|
344
|
+
uri,
|
|
345
|
+
mimeType: "application/json",
|
|
346
|
+
text: JSON.stringify(decks.map((deck) => ({
|
|
347
|
+
id: deck.id,
|
|
348
|
+
name: deck.name,
|
|
349
|
+
archived: deck.archived,
|
|
350
|
+
})), null, 2),
|
|
351
|
+
},
|
|
352
|
+
],
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
case "mochi://templates": {
|
|
356
|
+
const templates = await mochiClient.listTemplates();
|
|
357
|
+
return {
|
|
358
|
+
contents: [
|
|
359
|
+
{
|
|
360
|
+
uri,
|
|
361
|
+
mimeType: "application/json",
|
|
362
|
+
text: JSON.stringify(templates, null, 2),
|
|
363
|
+
},
|
|
364
|
+
],
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
default: {
|
|
368
|
+
throw new Error("Invalid resource URI");
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
});
|
|
239
372
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
240
373
|
try {
|
|
241
374
|
switch (request.params.name) {
|
|
242
375
|
case "mochi_create_card": {
|
|
243
376
|
const validatedArgs = CreateCardRequestSchema.parse(request.params.arguments);
|
|
244
|
-
|
|
377
|
+
const response = await mochiClient.createCard(validatedArgs);
|
|
378
|
+
return {
|
|
379
|
+
content: [
|
|
380
|
+
{
|
|
381
|
+
type: "text",
|
|
382
|
+
text: JSON.stringify(response, null, 2),
|
|
383
|
+
},
|
|
384
|
+
],
|
|
385
|
+
isError: false,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
case "mochi_update_card": {
|
|
389
|
+
const { "card-id": cardId, ...updateArgs } = z
|
|
390
|
+
.object({
|
|
391
|
+
"card-id": z.string(),
|
|
392
|
+
...UpdateCardRequestSchema.shape,
|
|
393
|
+
})
|
|
394
|
+
.parse(request.params.arguments);
|
|
395
|
+
const response = await mochiClient.updateCard(cardId, updateArgs);
|
|
396
|
+
return {
|
|
397
|
+
content: [
|
|
398
|
+
{
|
|
399
|
+
type: "text",
|
|
400
|
+
text: JSON.stringify(response, null, 2),
|
|
401
|
+
},
|
|
402
|
+
],
|
|
403
|
+
isError: false,
|
|
404
|
+
};
|
|
245
405
|
}
|
|
246
406
|
case "mochi_list_decks": {
|
|
247
407
|
const validatedArgs = ListDecksParamsSchema.parse(request.params.arguments);
|
|
248
|
-
|
|
408
|
+
const response = await mochiClient.listDecks(validatedArgs);
|
|
409
|
+
return {
|
|
410
|
+
content: [
|
|
411
|
+
{
|
|
412
|
+
type: "text",
|
|
413
|
+
text: JSON.stringify(response, null, 2),
|
|
414
|
+
},
|
|
415
|
+
],
|
|
416
|
+
isError: false,
|
|
417
|
+
};
|
|
249
418
|
}
|
|
250
419
|
case "mochi_list_cards": {
|
|
251
420
|
const validatedArgs = ListCardsParamsSchema.parse(request.params.arguments);
|
|
252
|
-
|
|
421
|
+
const response = await mochiClient.listCards(validatedArgs);
|
|
422
|
+
return {
|
|
423
|
+
content: [
|
|
424
|
+
{
|
|
425
|
+
type: "text",
|
|
426
|
+
text: JSON.stringify(response, null, 2),
|
|
427
|
+
},
|
|
428
|
+
],
|
|
429
|
+
isError: false,
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
case "mochi_list_templates": {
|
|
433
|
+
const validatedArgs = ListTemplatesParamsSchema.parse(request.params.arguments);
|
|
434
|
+
const response = await mochiClient.listTemplates(validatedArgs);
|
|
435
|
+
return {
|
|
436
|
+
content: [
|
|
437
|
+
{
|
|
438
|
+
type: "text",
|
|
439
|
+
text: JSON.stringify(response, null, 2),
|
|
440
|
+
},
|
|
441
|
+
],
|
|
442
|
+
isError: false,
|
|
443
|
+
};
|
|
253
444
|
}
|
|
254
445
|
default:
|
|
255
446
|
return {
|
|
@@ -265,13 +456,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
265
456
|
}
|
|
266
457
|
catch (error) {
|
|
267
458
|
if (error instanceof z.ZodError) {
|
|
459
|
+
const formattedErrors = error.errors.map((err) => {
|
|
460
|
+
const path = err.path.join(".");
|
|
461
|
+
const message = err.code === "invalid_type" && err.message.includes("Required")
|
|
462
|
+
? `Required field '${path}' is missing`
|
|
463
|
+
: err.message;
|
|
464
|
+
return `${path ? `${path}: ` : ""}${message}`;
|
|
465
|
+
});
|
|
268
466
|
return {
|
|
269
467
|
content: [
|
|
270
468
|
{
|
|
271
469
|
type: "text",
|
|
272
|
-
text: `Validation error
|
|
273
|
-
.map((e) => e.message)
|
|
274
|
-
.join(", ")}`,
|
|
470
|
+
text: `Validation error:\n${formattedErrors.join("\n")}`,
|
|
275
471
|
},
|
|
276
472
|
],
|
|
277
473
|
isError: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fredrika/mcp-mochi",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "MCP server for Mochi flashcard integration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"build": "tsc",
|
|
16
16
|
"start": "node dist/index.js",
|
|
17
17
|
"dev": "ts-node-esm src/index.ts",
|
|
18
|
-
"dev:inspect": "npx @modelcontextprotocol/inspector ts-node-esm src/
|
|
18
|
+
"dev:inspect": "npx @modelcontextprotocol/inspector ts-node-esm src/index.ts",
|
|
19
19
|
"test": "jest",
|
|
20
20
|
"prepublishOnly": "npm run build"
|
|
21
21
|
},
|
package/dist/mochi-client.d.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
export interface Flashcard {
|
|
2
|
-
id: string;
|
|
3
|
-
name: string;
|
|
4
|
-
content: string;
|
|
5
|
-
tags: string[];
|
|
6
|
-
'deck-id': string;
|
|
7
|
-
fields: Record<string, unknown>;
|
|
8
|
-
pos: string;
|
|
9
|
-
references: unknown[];
|
|
10
|
-
reviews: unknown[];
|
|
11
|
-
'created-at': {
|
|
12
|
-
date: string;
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
export interface FlashcardInput {
|
|
16
|
-
front: string;
|
|
17
|
-
back: string;
|
|
18
|
-
tags?: string[];
|
|
19
|
-
}
|
|
20
|
-
export interface ReviewResult {
|
|
21
|
-
success: boolean;
|
|
22
|
-
timeSpentMs: number;
|
|
23
|
-
}
|
|
24
|
-
export interface ListFlashcardsParams {
|
|
25
|
-
'deck-id'?: string;
|
|
26
|
-
limit?: number;
|
|
27
|
-
bookmark?: string;
|
|
28
|
-
}
|
|
29
|
-
export interface ListFlashcardsResponse {
|
|
30
|
-
bookmark: string;
|
|
31
|
-
docs: Flashcard[];
|
|
32
|
-
}
|
|
33
|
-
export interface TemplateField {
|
|
34
|
-
id: string;
|
|
35
|
-
name: string;
|
|
36
|
-
pos: string;
|
|
37
|
-
options?: {
|
|
38
|
-
'multi-line?'?: boolean;
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
export interface Template {
|
|
42
|
-
id: string;
|
|
43
|
-
name: string;
|
|
44
|
-
content: string;
|
|
45
|
-
pos: string;
|
|
46
|
-
fields: Record<string, TemplateField>;
|
|
47
|
-
}
|
|
48
|
-
export interface ListTemplatesResponse {
|
|
49
|
-
bookmark: string;
|
|
50
|
-
docs: Template[];
|
|
51
|
-
}
|
|
52
|
-
export interface ListTemplatesParams {
|
|
53
|
-
bookmark?: string;
|
|
54
|
-
}
|
|
55
|
-
export declare class MochiClient {
|
|
56
|
-
private api;
|
|
57
|
-
private token;
|
|
58
|
-
constructor(token: string);
|
|
59
|
-
getFlashcards(params?: ListFlashcardsParams): Promise<ListFlashcardsResponse>;
|
|
60
|
-
getFlashcard(id: string): Promise<Flashcard>;
|
|
61
|
-
createFlashcard(input: FlashcardInput): Promise<Flashcard>;
|
|
62
|
-
updateFlashcard(id: string, input: Partial<FlashcardInput>): Promise<Flashcard>;
|
|
63
|
-
deleteFlashcard(id: string): Promise<void>;
|
|
64
|
-
getDueFlashcards(): Promise<Flashcard[]>;
|
|
65
|
-
reviewFlashcard(id: string, result: ReviewResult): Promise<Flashcard>;
|
|
66
|
-
getStats(): Promise<{
|
|
67
|
-
totalCards: number;
|
|
68
|
-
dueCards: number;
|
|
69
|
-
averageSuccessRate: number;
|
|
70
|
-
cardsReviewedToday: number;
|
|
71
|
-
}>;
|
|
72
|
-
getTemplate(id: string): Promise<Template>;
|
|
73
|
-
listTemplates(params?: ListTemplatesParams): Promise<ListTemplatesResponse>;
|
|
74
|
-
}
|
package/dist/mochi-client.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
2
|
-
export class MochiClient {
|
|
3
|
-
api;
|
|
4
|
-
token;
|
|
5
|
-
constructor(token) {
|
|
6
|
-
this.token = '228b69396efc60896d3033e3';
|
|
7
|
-
this.api = axios.create({
|
|
8
|
-
baseURL: 'https://app.mochi.cards/api/',
|
|
9
|
-
headers: {
|
|
10
|
-
'Authorization': `Basic ${Buffer.from(`${this.token}:`).toString('base64')}`,
|
|
11
|
-
'Content-Type': 'application/json'
|
|
12
|
-
}
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
async getFlashcards(params) {
|
|
16
|
-
try {
|
|
17
|
-
const response = await this.api.get('/cards', { params });
|
|
18
|
-
console.log(response.data);
|
|
19
|
-
return response.data;
|
|
20
|
-
}
|
|
21
|
-
catch (error) {
|
|
22
|
-
console.error('Error fetching flashcards:', error);
|
|
23
|
-
throw error;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
async getFlashcard(id) {
|
|
27
|
-
const response = await this.api.get(`/cards/${id}`);
|
|
28
|
-
return response.data;
|
|
29
|
-
}
|
|
30
|
-
async createFlashcard(input) {
|
|
31
|
-
const response = await this.api.post('/cards', input);
|
|
32
|
-
return response.data;
|
|
33
|
-
}
|
|
34
|
-
async updateFlashcard(id, input) {
|
|
35
|
-
const response = await this.api.patch(`/cards/${id}`, input);
|
|
36
|
-
return response.data;
|
|
37
|
-
}
|
|
38
|
-
async deleteFlashcard(id) {
|
|
39
|
-
await this.api.delete(`/cards/${id}`);
|
|
40
|
-
}
|
|
41
|
-
async getDueFlashcards() {
|
|
42
|
-
const response = await this.api.get('/cards');
|
|
43
|
-
return response.data;
|
|
44
|
-
}
|
|
45
|
-
async reviewFlashcard(id, result) {
|
|
46
|
-
const response = await this.api.post(`/cards/${id}/review`, result);
|
|
47
|
-
return response.data;
|
|
48
|
-
}
|
|
49
|
-
async getStats() {
|
|
50
|
-
const response = await this.api.get('/v1/stats');
|
|
51
|
-
return response.data;
|
|
52
|
-
}
|
|
53
|
-
async getTemplate(id) {
|
|
54
|
-
const response = await this.api.get(`/templates/${id}`);
|
|
55
|
-
return response.data;
|
|
56
|
-
}
|
|
57
|
-
async listTemplates(params) {
|
|
58
|
-
try {
|
|
59
|
-
const response = await this.api.get('/templates', { params });
|
|
60
|
-
return response.data;
|
|
61
|
-
}
|
|
62
|
-
catch (error) {
|
|
63
|
-
console.error('Error fetching templates:', error);
|
|
64
|
-
throw error;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
package/dist/test-mochi-api.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/test-mochi-api.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
2
|
-
import { MochiClient } from './mochi-client.js';
|
|
3
|
-
import { config } from 'dotenv';
|
|
4
|
-
// Load environment variables
|
|
5
|
-
config();
|
|
6
|
-
const MOCHI_TOKEN = process.env.MOCHI_TOKEN;
|
|
7
|
-
if (!MOCHI_TOKEN) {
|
|
8
|
-
throw new Error("MOCHI_TOKEN environment variable is required");
|
|
9
|
-
}
|
|
10
|
-
// After the check above, TypeScript knows MOCHI_TOKEN is defined
|
|
11
|
-
const token = MOCHI_TOKEN;
|
|
12
|
-
async function testMochiApi() {
|
|
13
|
-
console.log("Testing Mochi API connection...");
|
|
14
|
-
console.log("Using token:", token.slice(0, 5) + "..." + token.slice(-5));
|
|
15
|
-
const client = new MochiClient(token);
|
|
16
|
-
try {
|
|
17
|
-
// Test getting stats (simplest operation)
|
|
18
|
-
console.log("\nTesting getStats...");
|
|
19
|
-
const stats = await client.getStats();
|
|
20
|
-
console.log("Stats response:", stats);
|
|
21
|
-
// Test getting flashcards
|
|
22
|
-
console.log("\nTesting getFlashcards...");
|
|
23
|
-
const cards = await client.getFlashcards();
|
|
24
|
-
console.log("Flashcards response:", cards);
|
|
25
|
-
// Test creating a flashcard
|
|
26
|
-
console.log("\nTesting createFlashcard...");
|
|
27
|
-
const newCard = await client.createFlashcard({
|
|
28
|
-
front: "Test Front",
|
|
29
|
-
back: "Test Back",
|
|
30
|
-
tags: ["test"]
|
|
31
|
-
});
|
|
32
|
-
console.log("Created card:", newCard);
|
|
33
|
-
// Test getting a specific flashcard
|
|
34
|
-
console.log("\nTesting getFlashcard...");
|
|
35
|
-
const card = await client.getFlashcard(newCard.id);
|
|
36
|
-
console.log("Retrieved card:", card);
|
|
37
|
-
// Test updating the flashcard
|
|
38
|
-
console.log("\nTesting updateFlashcard...");
|
|
39
|
-
const updatedCard = await client.updateFlashcard(newCard.id, {
|
|
40
|
-
front: "Updated Front"
|
|
41
|
-
});
|
|
42
|
-
console.log("Updated card:", updatedCard);
|
|
43
|
-
// Test deleting the flashcard
|
|
44
|
-
console.log("\nTesting deleteFlashcard...");
|
|
45
|
-
await client.deleteFlashcard(newCard.id);
|
|
46
|
-
console.log("Card deleted successfully");
|
|
47
|
-
}
|
|
48
|
-
catch (error) {
|
|
49
|
-
console.error("Error testing Mochi API:", error);
|
|
50
|
-
if (axios.isAxiosError(error)) {
|
|
51
|
-
const axiosError = error;
|
|
52
|
-
if (axiosError.response) {
|
|
53
|
-
console.error("Response status:", axiosError.response.status);
|
|
54
|
-
console.error("Response data:", axiosError.response.data);
|
|
55
|
-
console.error("Response headers:", axiosError.response.headers);
|
|
56
|
-
console.error("Request URL:", axiosError.config?.url);
|
|
57
|
-
console.error("Request method:", axiosError.config?.method);
|
|
58
|
-
}
|
|
59
|
-
else if (axiosError.request) {
|
|
60
|
-
console.error("No response received. Request details:", axiosError.request);
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
console.error("Error setting up request:", axiosError.message);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
// Run the test
|
|
69
|
-
testMochiApi().catch(console.error);
|