@reverso/mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -0
- package/dist/bin.d.ts +10 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +87 -0
- package/dist/bin.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +51 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +193 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/content.d.ts +177 -0
- package/dist/tools/content.d.ts.map +1 -0
- package/dist/tools/content.js +143 -0
- package/dist/tools/content.js.map +1 -0
- package/dist/tools/forms.d.ts +197 -0
- package/dist/tools/forms.d.ts.map +1 -0
- package/dist/tools/forms.js +132 -0
- package/dist/tools/forms.js.map +1 -0
- package/dist/tools/generation.d.ts +98 -0
- package/dist/tools/generation.d.ts.map +1 -0
- package/dist/tools/generation.js +213 -0
- package/dist/tools/generation.js.map +1 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +9 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/media.d.ts +160 -0
- package/dist/tools/media.d.ts.map +1 -0
- package/dist/tools/media.js +143 -0
- package/dist/tools/media.js.map +1 -0
- package/dist/tools/schema.d.ts +86 -0
- package/dist/tools/schema.d.ts.map +1 -0
- package/dist/tools/schema.js +263 -0
- package/dist/tools/schema.js.map +1 -0
- package/dist/types.d.ts +39 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content generation and analysis tools for the MCP server.
|
|
3
|
+
*
|
|
4
|
+
* These tools provide AI-powered content suggestions and analysis.
|
|
5
|
+
* They are designed to be helpful for content creation workflows.
|
|
6
|
+
*/
|
|
7
|
+
import type { DrizzleDatabase } from '@reverso/db';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import type { ContentAnalysis } from '../types.js';
|
|
10
|
+
export declare const generationTools: {
|
|
11
|
+
analyze_content: {
|
|
12
|
+
description: string;
|
|
13
|
+
inputSchema: z.ZodObject<{
|
|
14
|
+
content: z.ZodString;
|
|
15
|
+
type: z.ZodOptional<z.ZodEnum<{
|
|
16
|
+
text: "text";
|
|
17
|
+
markdown: "markdown";
|
|
18
|
+
html: "html";
|
|
19
|
+
}>>;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
handler: (_db: DrizzleDatabase, input: {
|
|
22
|
+
content: string;
|
|
23
|
+
type?: string;
|
|
24
|
+
}) => Promise<ContentAnalysis>;
|
|
25
|
+
};
|
|
26
|
+
suggest_content_improvements: {
|
|
27
|
+
description: string;
|
|
28
|
+
inputSchema: z.ZodObject<{
|
|
29
|
+
content: z.ZodString;
|
|
30
|
+
fieldType: z.ZodString;
|
|
31
|
+
fieldName: z.ZodOptional<z.ZodString>;
|
|
32
|
+
maxLength: z.ZodOptional<z.ZodNumber>;
|
|
33
|
+
}, z.core.$strip>;
|
|
34
|
+
handler: (_db: DrizzleDatabase, input: {
|
|
35
|
+
content: string;
|
|
36
|
+
fieldType: string;
|
|
37
|
+
fieldName?: string;
|
|
38
|
+
maxLength?: number;
|
|
39
|
+
}) => Promise<{
|
|
40
|
+
original: string;
|
|
41
|
+
suggestions: string[];
|
|
42
|
+
charCount: number;
|
|
43
|
+
withinLimit: boolean;
|
|
44
|
+
}>;
|
|
45
|
+
};
|
|
46
|
+
generate_slug: {
|
|
47
|
+
description: string;
|
|
48
|
+
inputSchema: z.ZodObject<{
|
|
49
|
+
text: z.ZodString;
|
|
50
|
+
maxLength: z.ZodOptional<z.ZodNumber>;
|
|
51
|
+
}, z.core.$strip>;
|
|
52
|
+
handler: (_db: DrizzleDatabase, input: {
|
|
53
|
+
text: string;
|
|
54
|
+
maxLength?: number;
|
|
55
|
+
}) => Promise<{
|
|
56
|
+
slug: string;
|
|
57
|
+
original: string;
|
|
58
|
+
}>;
|
|
59
|
+
};
|
|
60
|
+
generate_excerpt: {
|
|
61
|
+
description: string;
|
|
62
|
+
inputSchema: z.ZodObject<{
|
|
63
|
+
content: z.ZodString;
|
|
64
|
+
maxLength: z.ZodOptional<z.ZodNumber>;
|
|
65
|
+
preserveWords: z.ZodOptional<z.ZodBoolean>;
|
|
66
|
+
}, z.core.$strip>;
|
|
67
|
+
handler: (_db: DrizzleDatabase, input: {
|
|
68
|
+
content: string;
|
|
69
|
+
maxLength?: number;
|
|
70
|
+
preserveWords?: boolean;
|
|
71
|
+
}) => Promise<{
|
|
72
|
+
excerpt: string;
|
|
73
|
+
truncated: boolean;
|
|
74
|
+
originalLength?: undefined;
|
|
75
|
+
} | {
|
|
76
|
+
excerpt: string;
|
|
77
|
+
truncated: boolean;
|
|
78
|
+
originalLength: number;
|
|
79
|
+
}>;
|
|
80
|
+
};
|
|
81
|
+
count_words: {
|
|
82
|
+
description: string;
|
|
83
|
+
inputSchema: z.ZodObject<{
|
|
84
|
+
content: z.ZodString;
|
|
85
|
+
}, z.core.$strip>;
|
|
86
|
+
handler: (_db: DrizzleDatabase, input: {
|
|
87
|
+
content: string;
|
|
88
|
+
}) => Promise<{
|
|
89
|
+
words: number;
|
|
90
|
+
characters: number;
|
|
91
|
+
charactersNoSpaces: number;
|
|
92
|
+
sentences: number;
|
|
93
|
+
paragraphs: number;
|
|
94
|
+
avgWordsPerSentence: number;
|
|
95
|
+
}>;
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
//# sourceMappingURL=generation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generation.d.ts","sourceRoot":"","sources":["../../src/tools/generation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,eAAO,MAAM,eAAe;;;;;;;;;;;uBAOH,eAAe,SAAS;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,KAAG,OAAO,CAAC,eAAe,CAAC;;;;;;;;;;uBA2EnG,eAAe,SACb;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAA;SAAE;;;;;;;;;;;;;uBAqElE,eAAe,SAAS;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAA;SAAE;;;;;;;;;;;;uBA0B1E,eAAe,SACb;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAC;YAAC,aAAa,CAAC,EAAE,OAAO,CAAA;SAAE;;;;;;;;;;;;;;;uBA8BpD,eAAe,SAAS;YAAE,OAAO,EAAE,MAAM,CAAA;SAAE;;;;;;;;;CAgBnE,CAAC"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content generation and analysis tools for the MCP server.
|
|
3
|
+
*
|
|
4
|
+
* These tools provide AI-powered content suggestions and analysis.
|
|
5
|
+
* They are designed to be helpful for content creation workflows.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
export const generationTools = {
|
|
9
|
+
analyze_content: {
|
|
10
|
+
description: 'Analyze content for quality, readability, and SEO',
|
|
11
|
+
inputSchema: z.object({
|
|
12
|
+
content: z.string().describe('Content to analyze'),
|
|
13
|
+
type: z.enum(['text', 'html', 'markdown']).optional().describe('Content type'),
|
|
14
|
+
}),
|
|
15
|
+
handler: async (_db, input) => {
|
|
16
|
+
const text = stripHtml(input.content);
|
|
17
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
18
|
+
const sentences = text.split(/[.!?]+/).filter(Boolean);
|
|
19
|
+
const wordCount = words.length;
|
|
20
|
+
// Calculate readability (simplified Flesch-Kincaid)
|
|
21
|
+
const avgWordsPerSentence = sentences.length > 0 ? wordCount / sentences.length : 0;
|
|
22
|
+
let readability = 'medium';
|
|
23
|
+
if (avgWordsPerSentence < 12)
|
|
24
|
+
readability = 'easy';
|
|
25
|
+
else if (avgWordsPerSentence > 20)
|
|
26
|
+
readability = 'hard';
|
|
27
|
+
// Generate suggestions
|
|
28
|
+
const suggestions = [];
|
|
29
|
+
if (wordCount < 50) {
|
|
30
|
+
suggestions.push('Content is quite short. Consider adding more detail.');
|
|
31
|
+
}
|
|
32
|
+
if (avgWordsPerSentence > 25) {
|
|
33
|
+
suggestions.push('Sentences are long. Consider breaking them up for readability.');
|
|
34
|
+
}
|
|
35
|
+
if (!text.includes('.') && wordCount > 20) {
|
|
36
|
+
suggestions.push('Add proper punctuation for better readability.');
|
|
37
|
+
}
|
|
38
|
+
// Check for common issues
|
|
39
|
+
const consecutiveSpaces = /\s{2,}/.test(text);
|
|
40
|
+
if (consecutiveSpaces) {
|
|
41
|
+
suggestions.push('Remove extra whitespace between words.');
|
|
42
|
+
}
|
|
43
|
+
// SEO suggestions for longer content
|
|
44
|
+
let seoScore;
|
|
45
|
+
if (wordCount > 100) {
|
|
46
|
+
seoScore = 50;
|
|
47
|
+
// Check for headings (if HTML/markdown)
|
|
48
|
+
if (input.type === 'html' || input.type === 'markdown') {
|
|
49
|
+
const hasHeadings = /<h[1-6]|^#{1,6}\s/m.test(input.content);
|
|
50
|
+
if (hasHeadings) {
|
|
51
|
+
seoScore += 15;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
suggestions.push('Consider adding headings to structure your content.');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Length bonus
|
|
58
|
+
if (wordCount > 300)
|
|
59
|
+
seoScore += 10;
|
|
60
|
+
if (wordCount > 600)
|
|
61
|
+
seoScore += 10;
|
|
62
|
+
if (wordCount > 1000)
|
|
63
|
+
seoScore += 10;
|
|
64
|
+
// Readability bonus
|
|
65
|
+
if (readability === 'easy')
|
|
66
|
+
seoScore += 5;
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
wordCount,
|
|
70
|
+
readability,
|
|
71
|
+
suggestions,
|
|
72
|
+
seoScore,
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
suggest_content_improvements: {
|
|
77
|
+
description: 'Suggest improvements for content based on field type and context',
|
|
78
|
+
inputSchema: z.object({
|
|
79
|
+
content: z.string().describe('Current content'),
|
|
80
|
+
fieldType: z.string().describe('Field type (e.g., "text", "textarea", "wysiwyg")'),
|
|
81
|
+
fieldName: z.string().optional().describe('Field name for context'),
|
|
82
|
+
maxLength: z.number().optional().describe('Maximum length constraint'),
|
|
83
|
+
}),
|
|
84
|
+
handler: async (_db, input) => {
|
|
85
|
+
const suggestions = [];
|
|
86
|
+
const content = input.content.trim();
|
|
87
|
+
// Field-specific suggestions
|
|
88
|
+
switch (input.fieldType) {
|
|
89
|
+
case 'text':
|
|
90
|
+
if (content.length > 60 && input.fieldName?.toLowerCase().includes('title')) {
|
|
91
|
+
suggestions.push('Title is long. Consider shortening to under 60 characters for SEO.');
|
|
92
|
+
}
|
|
93
|
+
if (content.length < 3) {
|
|
94
|
+
suggestions.push('Content seems very short. Add more descriptive text.');
|
|
95
|
+
}
|
|
96
|
+
break;
|
|
97
|
+
case 'textarea':
|
|
98
|
+
case 'wysiwyg':
|
|
99
|
+
case 'markdown':
|
|
100
|
+
if (content.length < 100) {
|
|
101
|
+
suggestions.push('Consider expanding the content with more detail.');
|
|
102
|
+
}
|
|
103
|
+
if (content.length > 5000) {
|
|
104
|
+
suggestions.push('Content is quite long. Consider breaking into sections.');
|
|
105
|
+
}
|
|
106
|
+
break;
|
|
107
|
+
case 'email':
|
|
108
|
+
if (!content.includes('@') || !content.includes('.')) {
|
|
109
|
+
suggestions.push('This doesn\'t appear to be a valid email format.');
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
|
+
case 'url':
|
|
113
|
+
if (!content.startsWith('http://') && !content.startsWith('https://')) {
|
|
114
|
+
suggestions.push('URL should start with http:// or https://');
|
|
115
|
+
}
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
// Max length check
|
|
119
|
+
if (input.maxLength && content.length > input.maxLength) {
|
|
120
|
+
suggestions.push(`Content exceeds maximum length of ${input.maxLength} characters.`);
|
|
121
|
+
}
|
|
122
|
+
// Common improvements
|
|
123
|
+
if (content !== content.trim()) {
|
|
124
|
+
suggestions.push('Remove leading/trailing whitespace.');
|
|
125
|
+
}
|
|
126
|
+
if (/\s{2,}/.test(content)) {
|
|
127
|
+
suggestions.push('Remove extra spaces between words.');
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
original: content,
|
|
131
|
+
suggestions,
|
|
132
|
+
charCount: content.length,
|
|
133
|
+
withinLimit: input.maxLength ? content.length <= input.maxLength : true,
|
|
134
|
+
};
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
generate_slug: {
|
|
138
|
+
description: 'Generate a URL-friendly slug from text',
|
|
139
|
+
inputSchema: z.object({
|
|
140
|
+
text: z.string().describe('Text to convert to slug'),
|
|
141
|
+
maxLength: z.number().optional().describe('Maximum slug length'),
|
|
142
|
+
}),
|
|
143
|
+
handler: async (_db, input) => {
|
|
144
|
+
let slug = input.text
|
|
145
|
+
.toLowerCase()
|
|
146
|
+
.normalize('NFD')
|
|
147
|
+
.replace(/[\u0300-\u036f]/g, '') // Remove diacritics
|
|
148
|
+
.replace(/[^a-z0-9\s-]/g, '') // Remove special characters
|
|
149
|
+
.replace(/\s+/g, '-') // Replace spaces with hyphens
|
|
150
|
+
.replace(/-+/g, '-') // Replace multiple hyphens
|
|
151
|
+
.replace(/^-|-$/g, ''); // Remove leading/trailing hyphens
|
|
152
|
+
if (input.maxLength && slug.length > input.maxLength) {
|
|
153
|
+
slug = slug.substring(0, input.maxLength).replace(/-$/, '');
|
|
154
|
+
}
|
|
155
|
+
return { slug, original: input.text };
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
generate_excerpt: {
|
|
159
|
+
description: 'Generate an excerpt from longer content',
|
|
160
|
+
inputSchema: z.object({
|
|
161
|
+
content: z.string().describe('Full content'),
|
|
162
|
+
maxLength: z.number().optional().describe('Maximum excerpt length (default: 160)'),
|
|
163
|
+
preserveWords: z.boolean().optional().describe('Preserve whole words (default: true)'),
|
|
164
|
+
}),
|
|
165
|
+
handler: async (_db, input) => {
|
|
166
|
+
const text = stripHtml(input.content).trim();
|
|
167
|
+
const maxLength = input.maxLength ?? 160;
|
|
168
|
+
const preserveWords = input.preserveWords ?? true;
|
|
169
|
+
if (text.length <= maxLength) {
|
|
170
|
+
return { excerpt: text, truncated: false };
|
|
171
|
+
}
|
|
172
|
+
let excerpt = text.substring(0, maxLength);
|
|
173
|
+
if (preserveWords) {
|
|
174
|
+
const lastSpace = excerpt.lastIndexOf(' ');
|
|
175
|
+
if (lastSpace > maxLength * 0.7) {
|
|
176
|
+
excerpt = excerpt.substring(0, lastSpace);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
excerpt = excerpt.trim() + '...';
|
|
180
|
+
return { excerpt, truncated: true, originalLength: text.length };
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
count_words: {
|
|
184
|
+
description: 'Count words in content',
|
|
185
|
+
inputSchema: z.object({
|
|
186
|
+
content: z.string().describe('Content to count'),
|
|
187
|
+
}),
|
|
188
|
+
handler: async (_db, input) => {
|
|
189
|
+
const text = stripHtml(input.content);
|
|
190
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
191
|
+
const sentences = text.split(/[.!?]+/).filter(Boolean);
|
|
192
|
+
const paragraphs = text.split(/\n\n+/).filter(Boolean);
|
|
193
|
+
return {
|
|
194
|
+
words: words.length,
|
|
195
|
+
characters: text.length,
|
|
196
|
+
charactersNoSpaces: text.replace(/\s/g, '').length,
|
|
197
|
+
sentences: sentences.length,
|
|
198
|
+
paragraphs: paragraphs.length,
|
|
199
|
+
avgWordsPerSentence: sentences.length > 0 ? Math.round(words.length / sentences.length) : 0,
|
|
200
|
+
};
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
/**
|
|
205
|
+
* Strip HTML tags from content.
|
|
206
|
+
*/
|
|
207
|
+
function stripHtml(html) {
|
|
208
|
+
return html
|
|
209
|
+
.replace(/<[^>]*>/g, ' ')
|
|
210
|
+
.replace(/\s+/g, ' ')
|
|
211
|
+
.trim();
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=generation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generation.js","sourceRoot":"","sources":["../../src/tools/generation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool exports for the MCP server.
|
|
3
|
+
*/
|
|
4
|
+
export { contentTools } from './content.js';
|
|
5
|
+
export { schemaTools } from './schema.js';
|
|
6
|
+
export { mediaTools } from './media.js';
|
|
7
|
+
export { formsTools } from './forms.js';
|
|
8
|
+
export { generationTools } from './generation.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool exports for the MCP server.
|
|
3
|
+
*/
|
|
4
|
+
export { contentTools } from './content.js';
|
|
5
|
+
export { schemaTools } from './schema.js';
|
|
6
|
+
export { mediaTools } from './media.js';
|
|
7
|
+
export { formsTools } from './forms.js';
|
|
8
|
+
export { generationTools } from './generation.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Media tools for the MCP server.
|
|
3
|
+
*/
|
|
4
|
+
import type { DrizzleDatabase } from '@reverso/db';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
export declare const mediaTools: {
|
|
7
|
+
list_media: {
|
|
8
|
+
description: string;
|
|
9
|
+
inputSchema: z.ZodObject<{
|
|
10
|
+
type: z.ZodOptional<z.ZodEnum<{
|
|
11
|
+
image: "image";
|
|
12
|
+
video: "video";
|
|
13
|
+
audio: "audio";
|
|
14
|
+
document: "document";
|
|
15
|
+
other: "other";
|
|
16
|
+
}>>;
|
|
17
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
18
|
+
offset: z.ZodOptional<z.ZodNumber>;
|
|
19
|
+
}, z.core.$strip>;
|
|
20
|
+
handler: (db: DrizzleDatabase, input: {
|
|
21
|
+
type?: string;
|
|
22
|
+
limit?: number;
|
|
23
|
+
offset?: number;
|
|
24
|
+
}) => Promise<{
|
|
25
|
+
media: {
|
|
26
|
+
id: string;
|
|
27
|
+
createdAt: Date;
|
|
28
|
+
updatedAt: Date;
|
|
29
|
+
filename: string;
|
|
30
|
+
originalName: string;
|
|
31
|
+
mimeType: string;
|
|
32
|
+
size: number;
|
|
33
|
+
width: number | null;
|
|
34
|
+
height: number | null;
|
|
35
|
+
alt: string | null;
|
|
36
|
+
caption: string | null;
|
|
37
|
+
storagePath: string;
|
|
38
|
+
storageProvider: string | null;
|
|
39
|
+
metadata: string | null;
|
|
40
|
+
}[];
|
|
41
|
+
total: number;
|
|
42
|
+
offset: number;
|
|
43
|
+
limit: number;
|
|
44
|
+
}>;
|
|
45
|
+
};
|
|
46
|
+
get_media: {
|
|
47
|
+
description: string;
|
|
48
|
+
inputSchema: z.ZodObject<{
|
|
49
|
+
id: z.ZodOptional<z.ZodString>;
|
|
50
|
+
filename: z.ZodOptional<z.ZodString>;
|
|
51
|
+
}, z.core.$strip>;
|
|
52
|
+
handler: (db: DrizzleDatabase, input: {
|
|
53
|
+
id?: string;
|
|
54
|
+
filename?: string;
|
|
55
|
+
}) => Promise<{
|
|
56
|
+
id: string;
|
|
57
|
+
createdAt: Date;
|
|
58
|
+
updatedAt: Date;
|
|
59
|
+
filename: string;
|
|
60
|
+
originalName: string;
|
|
61
|
+
mimeType: string;
|
|
62
|
+
size: number;
|
|
63
|
+
width: number | null;
|
|
64
|
+
height: number | null;
|
|
65
|
+
alt: string | null;
|
|
66
|
+
caption: string | null;
|
|
67
|
+
storagePath: string;
|
|
68
|
+
storageProvider: string | null;
|
|
69
|
+
metadata: string | null;
|
|
70
|
+
}>;
|
|
71
|
+
};
|
|
72
|
+
delete_media: {
|
|
73
|
+
description: string;
|
|
74
|
+
inputSchema: z.ZodObject<{
|
|
75
|
+
id: z.ZodString;
|
|
76
|
+
}, z.core.$strip>;
|
|
77
|
+
handler: (db: DrizzleDatabase, input: {
|
|
78
|
+
id: string;
|
|
79
|
+
}) => Promise<{
|
|
80
|
+
deleted: {
|
|
81
|
+
id: string;
|
|
82
|
+
createdAt: Date;
|
|
83
|
+
updatedAt: Date;
|
|
84
|
+
filename: string;
|
|
85
|
+
originalName: string;
|
|
86
|
+
mimeType: string;
|
|
87
|
+
size: number;
|
|
88
|
+
width: number | null;
|
|
89
|
+
height: number | null;
|
|
90
|
+
alt: string | null;
|
|
91
|
+
caption: string | null;
|
|
92
|
+
storagePath: string;
|
|
93
|
+
storageProvider: string | null;
|
|
94
|
+
metadata: string | null;
|
|
95
|
+
} | undefined;
|
|
96
|
+
media: {
|
|
97
|
+
id: string;
|
|
98
|
+
createdAt: Date;
|
|
99
|
+
updatedAt: Date;
|
|
100
|
+
filename: string;
|
|
101
|
+
originalName: string;
|
|
102
|
+
mimeType: string;
|
|
103
|
+
size: number;
|
|
104
|
+
width: number | null;
|
|
105
|
+
height: number | null;
|
|
106
|
+
alt: string | null;
|
|
107
|
+
caption: string | null;
|
|
108
|
+
storagePath: string;
|
|
109
|
+
storageProvider: string | null;
|
|
110
|
+
metadata: string | null;
|
|
111
|
+
};
|
|
112
|
+
}>;
|
|
113
|
+
};
|
|
114
|
+
get_media_stats: {
|
|
115
|
+
description: string;
|
|
116
|
+
inputSchema: z.ZodObject<{}, z.core.$strip>;
|
|
117
|
+
handler: (db: DrizzleDatabase) => Promise<{
|
|
118
|
+
total: number;
|
|
119
|
+
byType: Record<string, number>;
|
|
120
|
+
totalSizeBytes: number;
|
|
121
|
+
totalSizeMB: number;
|
|
122
|
+
}>;
|
|
123
|
+
};
|
|
124
|
+
search_media: {
|
|
125
|
+
description: string;
|
|
126
|
+
inputSchema: z.ZodObject<{
|
|
127
|
+
query: z.ZodString;
|
|
128
|
+
type: z.ZodOptional<z.ZodEnum<{
|
|
129
|
+
image: "image";
|
|
130
|
+
video: "video";
|
|
131
|
+
audio: "audio";
|
|
132
|
+
document: "document";
|
|
133
|
+
other: "other";
|
|
134
|
+
}>>;
|
|
135
|
+
}, z.core.$strip>;
|
|
136
|
+
handler: (db: DrizzleDatabase, input: {
|
|
137
|
+
query: string;
|
|
138
|
+
type?: string;
|
|
139
|
+
}) => Promise<{
|
|
140
|
+
results: {
|
|
141
|
+
id: string;
|
|
142
|
+
createdAt: Date;
|
|
143
|
+
updatedAt: Date;
|
|
144
|
+
filename: string;
|
|
145
|
+
originalName: string;
|
|
146
|
+
mimeType: string;
|
|
147
|
+
size: number;
|
|
148
|
+
width: number | null;
|
|
149
|
+
height: number | null;
|
|
150
|
+
alt: string | null;
|
|
151
|
+
caption: string | null;
|
|
152
|
+
storagePath: string;
|
|
153
|
+
storageProvider: string | null;
|
|
154
|
+
metadata: string | null;
|
|
155
|
+
}[];
|
|
156
|
+
count: number;
|
|
157
|
+
}>;
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
//# sourceMappingURL=media.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../src/tools/media.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,UAAU;;;;;;;;;;;;;;sBASb,eAAe,SACZ;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBA0CvC,eAAe,SAAS;YAAE,EAAE,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE;;;;;;;;;;;;;;;;;;;;;;sBAyB1D,eAAe,SAAS;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBActC,eAAe;;;;;;;;;;;;;;;;;;;sBAoCf,eAAe,SAAS;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE;;;;;;;;;;;;;;;;;;;;CA+B/E,CAAC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Media tools for the MCP server.
|
|
3
|
+
*/
|
|
4
|
+
import { getMediaList, getMediaById, getMediaByFilename, deleteMedia, getMediaCount } from '@reverso/db';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
export const mediaTools = {
|
|
7
|
+
list_media: {
|
|
8
|
+
description: 'List all media files in the CMS',
|
|
9
|
+
inputSchema: z.object({
|
|
10
|
+
type: z.enum(['image', 'video', 'audio', 'document', 'other']).optional().describe('Filter by media type'),
|
|
11
|
+
limit: z.number().optional().describe('Maximum number of results (default: 50)'),
|
|
12
|
+
offset: z.number().optional().describe('Offset for pagination'),
|
|
13
|
+
}),
|
|
14
|
+
handler: async (db, input) => {
|
|
15
|
+
let media = await getMediaList(db, { limit: 1000 });
|
|
16
|
+
if (input.type) {
|
|
17
|
+
media = media.filter((m) => {
|
|
18
|
+
const mimeType = m.mimeType?.toLowerCase() ?? '';
|
|
19
|
+
switch (input.type) {
|
|
20
|
+
case 'image':
|
|
21
|
+
return mimeType.startsWith('image/');
|
|
22
|
+
case 'video':
|
|
23
|
+
return mimeType.startsWith('video/');
|
|
24
|
+
case 'audio':
|
|
25
|
+
return mimeType.startsWith('audio/');
|
|
26
|
+
case 'document':
|
|
27
|
+
return (mimeType.includes('pdf') ||
|
|
28
|
+
mimeType.includes('document') ||
|
|
29
|
+
mimeType.includes('text/'));
|
|
30
|
+
default:
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
const total = media.length;
|
|
36
|
+
const offset = input.offset ?? 0;
|
|
37
|
+
const limit = input.limit ?? 50;
|
|
38
|
+
media = media.slice(offset, offset + limit);
|
|
39
|
+
return { media, total, offset, limit };
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
get_media: {
|
|
43
|
+
description: 'Get details of a specific media file',
|
|
44
|
+
inputSchema: z.object({
|
|
45
|
+
id: z.string().optional().describe('Media ID'),
|
|
46
|
+
filename: z.string().optional().describe('Media filename'),
|
|
47
|
+
}),
|
|
48
|
+
handler: async (db, input) => {
|
|
49
|
+
if (!input.id && !input.filename) {
|
|
50
|
+
throw new Error('Either id or filename must be provided');
|
|
51
|
+
}
|
|
52
|
+
let media = null;
|
|
53
|
+
if (input.id) {
|
|
54
|
+
media = await getMediaById(db, input.id);
|
|
55
|
+
}
|
|
56
|
+
else if (input.filename) {
|
|
57
|
+
media = await getMediaByFilename(db, input.filename);
|
|
58
|
+
}
|
|
59
|
+
if (!media) {
|
|
60
|
+
throw new Error(`Media not found: ${input.id ?? input.filename}`);
|
|
61
|
+
}
|
|
62
|
+
return media;
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
delete_media: {
|
|
66
|
+
description: 'Delete a media file from the CMS',
|
|
67
|
+
inputSchema: z.object({
|
|
68
|
+
id: z.string().describe('Media ID to delete'),
|
|
69
|
+
}),
|
|
70
|
+
handler: async (db, input) => {
|
|
71
|
+
const media = await getMediaById(db, input.id);
|
|
72
|
+
if (!media) {
|
|
73
|
+
throw new Error(`Media not found: ${input.id}`);
|
|
74
|
+
}
|
|
75
|
+
const deleted = await deleteMedia(db, input.id);
|
|
76
|
+
return { deleted, media };
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
get_media_stats: {
|
|
80
|
+
description: 'Get statistics about media files in the CMS',
|
|
81
|
+
inputSchema: z.object({}),
|
|
82
|
+
handler: async (db) => {
|
|
83
|
+
const media = await getMediaList(db, { limit: 10000 });
|
|
84
|
+
const total = await getMediaCount(db);
|
|
85
|
+
const byType = media.reduce((acc, m) => {
|
|
86
|
+
const mimeType = m.mimeType?.toLowerCase() ?? 'unknown';
|
|
87
|
+
let type = 'other';
|
|
88
|
+
if (mimeType.startsWith('image/'))
|
|
89
|
+
type = 'image';
|
|
90
|
+
else if (mimeType.startsWith('video/'))
|
|
91
|
+
type = 'video';
|
|
92
|
+
else if (mimeType.startsWith('audio/'))
|
|
93
|
+
type = 'audio';
|
|
94
|
+
else if (mimeType.includes('pdf') || mimeType.includes('document'))
|
|
95
|
+
type = 'document';
|
|
96
|
+
acc[type] = (acc[type] ?? 0) + 1;
|
|
97
|
+
return acc;
|
|
98
|
+
}, {});
|
|
99
|
+
const totalSize = media.reduce((sum, m) => sum + (m.size ?? 0), 0);
|
|
100
|
+
return {
|
|
101
|
+
total,
|
|
102
|
+
byType,
|
|
103
|
+
totalSizeBytes: totalSize,
|
|
104
|
+
totalSizeMB: Math.round((totalSize / 1024 / 1024) * 100) / 100,
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
search_media: {
|
|
109
|
+
description: 'Search media files by filename or alt text',
|
|
110
|
+
inputSchema: z.object({
|
|
111
|
+
query: z.string().describe('Search query'),
|
|
112
|
+
type: z.enum(['image', 'video', 'audio', 'document', 'other']).optional().describe('Filter by media type'),
|
|
113
|
+
}),
|
|
114
|
+
handler: async (db, input) => {
|
|
115
|
+
let media = await getMediaList(db, { limit: 10000 });
|
|
116
|
+
const query = input.query.toLowerCase();
|
|
117
|
+
media = media.filter((m) => {
|
|
118
|
+
const filename = m.filename?.toLowerCase() ?? '';
|
|
119
|
+
const alt = m.alt?.toLowerCase() ?? '';
|
|
120
|
+
return filename.includes(query) || alt.includes(query);
|
|
121
|
+
});
|
|
122
|
+
if (input.type) {
|
|
123
|
+
media = media.filter((m) => {
|
|
124
|
+
const mimeType = m.mimeType?.toLowerCase() ?? '';
|
|
125
|
+
switch (input.type) {
|
|
126
|
+
case 'image':
|
|
127
|
+
return mimeType.startsWith('image/');
|
|
128
|
+
case 'video':
|
|
129
|
+
return mimeType.startsWith('video/');
|
|
130
|
+
case 'audio':
|
|
131
|
+
return mimeType.startsWith('audio/');
|
|
132
|
+
case 'document':
|
|
133
|
+
return mimeType.includes('pdf') || mimeType.includes('document');
|
|
134
|
+
default:
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return { results: media, count: media.length };
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
//# sourceMappingURL=media.js.map
|