@vue-skuilder/mcp 0.1.8-3
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/CLAUDE.md +113 -0
- package/dist/examples/local-dev.d.cts +1 -0
- package/dist/examples/local-dev.d.ts +1 -0
- package/dist/examples/local-dev.js +1555 -0
- package/dist/examples/local-dev.js.map +1 -0
- package/dist/examples/local-dev.mjs +1554 -0
- package/dist/examples/local-dev.mjs.map +1 -0
- package/dist/index.d.cts +334 -0
- package/dist/index.d.ts +334 -0
- package/dist/index.js +1630 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1578 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +33 -0
- package/src/examples/index.ts +2 -0
- package/src/examples/local-dev.ts +49 -0
- package/src/index.ts +14 -0
- package/src/prompts/elo-scoring-guidance.ts +116 -0
- package/src/prompts/fill-in-card-authoring.ts +99 -0
- package/src/prompts/index.ts +9 -0
- package/src/resources/cards.ts +313 -0
- package/src/resources/course.ts +32 -0
- package/src/resources/index.ts +23 -0
- package/src/resources/shapes.ts +121 -0
- package/src/resources/tags.ts +277 -0
- package/src/server.ts +595 -0
- package/src/tools/create-card.ts +58 -0
- package/src/tools/delete-card.ts +85 -0
- package/src/tools/index.ts +13 -0
- package/src/tools/tag-card.ts +83 -0
- package/src/tools/update-card.ts +115 -0
- package/src/types/index.ts +33 -0
- package/src/types/resources.ts +20 -0
- package/src/types/tools.ts +74 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/pouchdb.ts +41 -0
- package/src/utils/tools.ts +32 -0
- package/tsconfig.json +16 -0
- package/tsup.config.ts +17 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import type { CourseDBInterface } from '@vue-skuilder/db';
|
|
2
|
+
|
|
3
|
+
export interface TagResource {
|
|
4
|
+
name: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
cardCount: number;
|
|
7
|
+
created?: string;
|
|
8
|
+
author?: string;
|
|
9
|
+
metadata?: any;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface TagsCollection {
|
|
13
|
+
tags: TagResource[];
|
|
14
|
+
total: number;
|
|
15
|
+
stats?: {
|
|
16
|
+
totalTags: number;
|
|
17
|
+
totalTaggedCards: number;
|
|
18
|
+
averageTagsPerCard: number;
|
|
19
|
+
mostUsedTags: { name: string; count: number }[];
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface TagDistribution {
|
|
24
|
+
tagName: string;
|
|
25
|
+
frequency: number;
|
|
26
|
+
percentage: number;
|
|
27
|
+
cardIds: string[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Handle tags://all resource - List all available tags
|
|
32
|
+
*/
|
|
33
|
+
export async function handleTagsAllResource(
|
|
34
|
+
courseDB: CourseDBInterface
|
|
35
|
+
): Promise<TagsCollection> {
|
|
36
|
+
try {
|
|
37
|
+
// Get all tag stubs for the course
|
|
38
|
+
const tagStubsResponse = await courseDB.getCourseTagStubs();
|
|
39
|
+
const tagStubs = tagStubsResponse.rows || [];
|
|
40
|
+
|
|
41
|
+
// Transform to TagResource format
|
|
42
|
+
const tags: TagResource[] = [];
|
|
43
|
+
for (const stub of tagStubs) {
|
|
44
|
+
if (stub.doc) {
|
|
45
|
+
// For each tag, we'd need to count associated cards
|
|
46
|
+
// Note: Current CourseDBInterface doesn't have a direct method for this
|
|
47
|
+
// This is a limitation we'll need to address
|
|
48
|
+
tags.push({
|
|
49
|
+
name: (stub.doc as any).name || stub.id,
|
|
50
|
+
description: (stub.doc as any).snippet || `Tag: ${(stub.doc as any).name}`,
|
|
51
|
+
cardCount: (stub.doc as any).taggedCards?.length || 0,
|
|
52
|
+
created: (stub.doc as any).created,
|
|
53
|
+
author: (stub.doc as any).author,
|
|
54
|
+
metadata: (stub.doc as any).metadata
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
tags,
|
|
61
|
+
total: tags.length,
|
|
62
|
+
stats: {
|
|
63
|
+
totalTags: tags.length,
|
|
64
|
+
totalTaggedCards: 0, // Would need additional queries
|
|
65
|
+
averageTagsPerCard: 0, // Would need calculation
|
|
66
|
+
mostUsedTags: [] // Would need tag usage analysis
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.error('Error fetching all tags:', error);
|
|
72
|
+
throw new Error(`Failed to fetch tags: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Handle tags://stats resource - Tag usage statistics
|
|
78
|
+
*/
|
|
79
|
+
export async function handleTagsStatsResource(
|
|
80
|
+
courseDB: CourseDBInterface
|
|
81
|
+
): Promise<TagsCollection['stats']> {
|
|
82
|
+
try {
|
|
83
|
+
// Get all tags
|
|
84
|
+
const tagStubsResponse = await courseDB.getCourseTagStubs();
|
|
85
|
+
const totalTags = tagStubsResponse.rows?.length || 0;
|
|
86
|
+
|
|
87
|
+
// Get course info for context
|
|
88
|
+
const courseInfo = await courseDB.getCourseInfo();
|
|
89
|
+
console.log('Course info loaded for stats:', courseInfo.cardCount);
|
|
90
|
+
|
|
91
|
+
// Note: Comprehensive tag statistics would require additional methods
|
|
92
|
+
// in CourseDBInterface to efficiently query tag-card associations
|
|
93
|
+
return {
|
|
94
|
+
totalTags,
|
|
95
|
+
totalTaggedCards: 0, // Placeholder
|
|
96
|
+
averageTagsPerCard: 0, // Placeholder
|
|
97
|
+
mostUsedTags: [] // Placeholder
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error('Error fetching tag stats:', error);
|
|
102
|
+
throw new Error(`Failed to fetch tag statistics: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Handle tags://[tagName] resource - Specific tag details + card count
|
|
108
|
+
*/
|
|
109
|
+
export async function handleTagSpecificResource(
|
|
110
|
+
courseDB: CourseDBInterface,
|
|
111
|
+
tagName: string
|
|
112
|
+
): Promise<TagResource> {
|
|
113
|
+
try {
|
|
114
|
+
// Get the specific tag
|
|
115
|
+
const tag = await courseDB.getTag(tagName);
|
|
116
|
+
if (!tag) {
|
|
117
|
+
throw new Error(`Tag not found: ${tagName}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
name: (tag as any).name || tagName,
|
|
122
|
+
description: (tag as any).snippet || `Tag: ${tagName}`,
|
|
123
|
+
cardCount: (tag as any).taggedCards?.length || 0,
|
|
124
|
+
created: (tag as any).created,
|
|
125
|
+
author: (tag as any).author,
|
|
126
|
+
metadata: (tag as any).metadata
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error(`Error fetching tag ${tagName}:`, error);
|
|
131
|
+
throw new Error(`Failed to fetch tag ${tagName}: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Handle tags://union/[tag1]+[tag2] resource - Cards with ANY of these tags
|
|
137
|
+
*/
|
|
138
|
+
export async function handleTagsUnionResource(
|
|
139
|
+
courseDB: CourseDBInterface,
|
|
140
|
+
tagsParam: string
|
|
141
|
+
): Promise<{ cardIds: string[]; tags: string[]; operation: 'union' }> {
|
|
142
|
+
try {
|
|
143
|
+
const tags = tagsParam.split('+').map(tag => tag.trim());
|
|
144
|
+
|
|
145
|
+
if (tags.length === 0) {
|
|
146
|
+
throw new Error('No tags specified for union operation');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Validate all tags exist
|
|
150
|
+
for (const tagName of tags) {
|
|
151
|
+
try {
|
|
152
|
+
await courseDB.getTag(tagName);
|
|
153
|
+
} catch {
|
|
154
|
+
throw new Error(`Tag not found: ${tagName}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Note: Union operation would require specialized queries
|
|
159
|
+
// Current CourseDBInterface doesn't provide tag-based card filtering
|
|
160
|
+
return {
|
|
161
|
+
cardIds: [], // Placeholder
|
|
162
|
+
tags,
|
|
163
|
+
operation: 'union'
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
} catch (error) {
|
|
167
|
+
console.error(`Error performing tags union for ${tagsParam}:`, error);
|
|
168
|
+
throw new Error(`Failed to perform tags union: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Handle tags://intersect/[tag1]+[tag2] resource - Cards with ALL these tags
|
|
174
|
+
*/
|
|
175
|
+
export async function handleTagsIntersectResource(
|
|
176
|
+
courseDB: CourseDBInterface,
|
|
177
|
+
tagsParam: string
|
|
178
|
+
): Promise<{ cardIds: string[]; tags: string[]; operation: 'intersect' }> {
|
|
179
|
+
try {
|
|
180
|
+
const tags = tagsParam.split('+').map(tag => tag.trim());
|
|
181
|
+
|
|
182
|
+
if (tags.length === 0) {
|
|
183
|
+
throw new Error('No tags specified for intersect operation');
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Validate all tags exist
|
|
187
|
+
for (const tagName of tags) {
|
|
188
|
+
try {
|
|
189
|
+
await courseDB.getTag(tagName);
|
|
190
|
+
} catch {
|
|
191
|
+
throw new Error(`Tag not found: ${tagName}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Note: Intersect operation would require specialized queries
|
|
196
|
+
return {
|
|
197
|
+
cardIds: [], // Placeholder
|
|
198
|
+
tags,
|
|
199
|
+
operation: 'intersect'
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
} catch (error) {
|
|
203
|
+
console.error(`Error performing tags intersect for ${tagsParam}:`, error);
|
|
204
|
+
throw new Error(`Failed to perform tags intersect: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Handle tags://exclusive/[tag1]-[tag2] resource - Cards with tag1 but NOT tag2
|
|
210
|
+
*/
|
|
211
|
+
export async function handleTagsExclusiveResource(
|
|
212
|
+
courseDB: CourseDBInterface,
|
|
213
|
+
tagsParam: string
|
|
214
|
+
): Promise<{ cardIds: string[]; includeTag: string; excludeTag: string; operation: 'exclusive' }> {
|
|
215
|
+
try {
|
|
216
|
+
const [includeTag, excludeTag] = tagsParam.split('-').map(tag => tag.trim());
|
|
217
|
+
|
|
218
|
+
if (!includeTag || !excludeTag) {
|
|
219
|
+
throw new Error('Both include and exclude tags must be specified (format: tag1-tag2)');
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Validate both tags exist
|
|
223
|
+
try {
|
|
224
|
+
await courseDB.getTag(includeTag);
|
|
225
|
+
await courseDB.getTag(excludeTag);
|
|
226
|
+
} catch (error) {
|
|
227
|
+
throw new Error(`One or both tags not found: ${includeTag}, ${excludeTag}`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Note: Exclusive operation would require specialized queries
|
|
231
|
+
return {
|
|
232
|
+
cardIds: [], // Placeholder
|
|
233
|
+
includeTag,
|
|
234
|
+
excludeTag,
|
|
235
|
+
operation: 'exclusive'
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
} catch (error) {
|
|
239
|
+
console.error(`Error performing tags exclusive for ${tagsParam}:`, error);
|
|
240
|
+
throw new Error(`Failed to perform tags exclusive: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Handle tags://distribution resource - Tag frequency distribution
|
|
246
|
+
*/
|
|
247
|
+
export async function handleTagsDistributionResource(
|
|
248
|
+
courseDB: CourseDBInterface
|
|
249
|
+
): Promise<{ distribution: TagDistribution[]; totalTags: number; totalCards: number }> {
|
|
250
|
+
try {
|
|
251
|
+
// Get all tags
|
|
252
|
+
const tagStubsResponse = await courseDB.getCourseTagStubs();
|
|
253
|
+
const tags = tagStubsResponse.rows || [];
|
|
254
|
+
|
|
255
|
+
// Get course info
|
|
256
|
+
const courseInfo = await courseDB.getCourseInfo();
|
|
257
|
+
|
|
258
|
+
// Note: Full distribution analysis would require additional queries
|
|
259
|
+
// to map tags to cards and calculate frequencies
|
|
260
|
+
const distribution: TagDistribution[] = tags.map(stub => ({
|
|
261
|
+
tagName: stub.doc?.name || stub.id,
|
|
262
|
+
frequency: 0, // Placeholder
|
|
263
|
+
percentage: 0, // Placeholder
|
|
264
|
+
cardIds: [] // Placeholder
|
|
265
|
+
}));
|
|
266
|
+
|
|
267
|
+
return {
|
|
268
|
+
distribution,
|
|
269
|
+
totalTags: tags.length,
|
|
270
|
+
totalCards: courseInfo.cardCount
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.error('Error calculating tag distribution:', error);
|
|
275
|
+
throw new Error(`Failed to calculate tag distribution: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
276
|
+
}
|
|
277
|
+
}
|