@z_ai/mcp-server 0.1.0 → 0.1.1-beta.1
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 +54 -0
- package/README.zh-CN.md +53 -6
- package/build/core/base-image-service.js +91 -0
- package/build/core/chat-service.js +15 -1
- package/build/index.js +16 -3
- package/build/prompts/data-viz.js +97 -0
- package/build/prompts/diagram-analysis.js +101 -0
- package/build/prompts/error-diagnosis.js +68 -0
- package/build/prompts/general-image.js +44 -0
- package/build/prompts/index.js +11 -0
- package/build/prompts/text-extraction.js +44 -0
- package/build/prompts/ui-diff.js +189 -0
- package/build/prompts/ui-to-artifact.js +88 -0
- package/build/tools/data-viz.js +87 -0
- package/build/tools/diagram-analysis.js +87 -0
- package/build/tools/error-diagnosis.js +87 -0
- package/build/tools/general-image.js +78 -0
- package/build/tools/text-extraction.js +87 -0
- package/build/tools/ui-diff.js +92 -0
- package/build/tools/ui-to-artifact.js +91 -0
- package/build/tools/video-analysis.js +10 -1
- package/package.json +1 -1
- package/build/tools/image-analysis.js +0 -125
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { FileNotFoundError, ApiError } from '../types/index.js';
|
|
3
|
+
import { CommonSchemas, ToolSchemaBuilder } from '../utils/validation.js';
|
|
4
|
+
import { formatMcpResponse, createSuccessResponse, createErrorResponse, withRetry } from '../core/api-common.js';
|
|
5
|
+
import { BaseImageAnalysisService } from '../core/base-image-service.js';
|
|
6
|
+
import { GENERAL_IMAGE_ANALYSIS_PROMPT } from '../prompts/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* General Image Analysis service - Fallback for any image analysis
|
|
9
|
+
*/
|
|
10
|
+
class GeneralImageAnalysisService extends BaseImageAnalysisService {
|
|
11
|
+
/**
|
|
12
|
+
* Analyze image with general purpose prompt
|
|
13
|
+
* @param imageSource Image file path or URL
|
|
14
|
+
* @param userPrompt User's analysis request
|
|
15
|
+
* @returns Analysis result
|
|
16
|
+
*/
|
|
17
|
+
async analyzeImage(imageSource, userPrompt) {
|
|
18
|
+
console.info('Starting general image analysis', {
|
|
19
|
+
imageSource,
|
|
20
|
+
prompt: userPrompt
|
|
21
|
+
});
|
|
22
|
+
// Validate prompt
|
|
23
|
+
this.validatePrompt(userPrompt, 'analyze-image');
|
|
24
|
+
// Process image
|
|
25
|
+
const imageContent = await this.processImageSource(imageSource);
|
|
26
|
+
// Execute analysis
|
|
27
|
+
return await this.executeVisionAnalysis(GENERAL_IMAGE_ANALYSIS_PROMPT, userPrompt, [imageContent], 'analyze-image');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Register General Image Analysis tool with MCP server
|
|
32
|
+
* @param server MCP server instance
|
|
33
|
+
*/
|
|
34
|
+
export function registerGeneralImageAnalysisTool(server) {
|
|
35
|
+
const service = new GeneralImageAnalysisService();
|
|
36
|
+
const retryableAnalyze = withRetry(service.analyzeImage.bind(service), 2, 1000);
|
|
37
|
+
server.tool('analyze_image', `General-purpose image analysis for scenarios not covered by specialized tools.
|
|
38
|
+
|
|
39
|
+
Use this tool as a FALLBACK when none of the other specialized tools (ui_to_artifact, extract_text_from_screenshot,
|
|
40
|
+
diagnose_error_screenshot, understand_technical_diagram, analyze_data_visualization, ui_diff_check) fit the user's need.
|
|
41
|
+
|
|
42
|
+
This tool provides flexible image understanding for any visual content.`, {
|
|
43
|
+
image_source: z.string().describe('Local file path or remote URL to the image'),
|
|
44
|
+
prompt: z.string().describe('Detailed description of what you want to analyze, extract, or understand from the image. Be specific about your requirements.')
|
|
45
|
+
}, async (params) => {
|
|
46
|
+
try {
|
|
47
|
+
const validationSchema = new ToolSchemaBuilder()
|
|
48
|
+
.required('image_source', CommonSchemas.nonEmptyString)
|
|
49
|
+
.required('prompt', CommonSchemas.nonEmptyString)
|
|
50
|
+
.build();
|
|
51
|
+
validationSchema.parse(params);
|
|
52
|
+
const result = await retryableAnalyze(params.image_source, params.prompt);
|
|
53
|
+
return formatMcpResponse(createSuccessResponse(result));
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.error('General image analysis tool execution failed', {
|
|
57
|
+
error: error instanceof Error ? error.message : String(error),
|
|
58
|
+
params
|
|
59
|
+
});
|
|
60
|
+
let errorResponse;
|
|
61
|
+
if (error instanceof z.ZodError) {
|
|
62
|
+
const validationErrors = error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', ');
|
|
63
|
+
errorResponse = createErrorResponse(`Validation failed: ${validationErrors}`);
|
|
64
|
+
}
|
|
65
|
+
else if (error instanceof FileNotFoundError) {
|
|
66
|
+
errorResponse = createErrorResponse(`Image file not found: ${error.message}`);
|
|
67
|
+
}
|
|
68
|
+
else if (error instanceof ApiError) {
|
|
69
|
+
errorResponse = createErrorResponse(`API error: ${error.message}`);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
errorResponse = createErrorResponse(`Unexpected error: ${error instanceof Error ? error.message : String(error)}`);
|
|
73
|
+
}
|
|
74
|
+
return formatMcpResponse(errorResponse);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
console.info('General Image Analysis tool registered successfully');
|
|
78
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { FileNotFoundError, ApiError } from '../types/index.js';
|
|
3
|
+
import { CommonSchemas, ToolSchemaBuilder } from '../utils/validation.js';
|
|
4
|
+
import { formatMcpResponse, createSuccessResponse, createErrorResponse, withRetry } from '../core/api-common.js';
|
|
5
|
+
import { BaseImageAnalysisService } from '../core/base-image-service.js';
|
|
6
|
+
import { TEXT_EXTRACTION_PROMPT } from '../prompts/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Text Extraction service - OCR and text extraction from screenshots
|
|
9
|
+
*/
|
|
10
|
+
class TextExtractionService extends BaseImageAnalysisService {
|
|
11
|
+
/**
|
|
12
|
+
* Extract text from screenshot
|
|
13
|
+
* @param imageSource Image file path or URL
|
|
14
|
+
* @param userPrompt User's extraction requirements
|
|
15
|
+
* @param programmingLanguage Optional programming language hint
|
|
16
|
+
* @returns Extracted text
|
|
17
|
+
*/
|
|
18
|
+
async extractText(imageSource, userPrompt, programmingLanguage) {
|
|
19
|
+
console.info('Starting text extraction', {
|
|
20
|
+
imageSource,
|
|
21
|
+
prompt: userPrompt,
|
|
22
|
+
language: programmingLanguage
|
|
23
|
+
});
|
|
24
|
+
// Validate prompt
|
|
25
|
+
this.validatePrompt(userPrompt, 'text-extraction');
|
|
26
|
+
// Enhance prompt with language hint if provided
|
|
27
|
+
let enhancedPrompt = userPrompt;
|
|
28
|
+
if (programmingLanguage && programmingLanguage.trim()) {
|
|
29
|
+
enhancedPrompt = `${userPrompt}\n\n<language_hint>The code is in ${programmingLanguage}.</language_hint>`;
|
|
30
|
+
}
|
|
31
|
+
// Process image
|
|
32
|
+
const imageContent = await this.processImageSource(imageSource);
|
|
33
|
+
// Execute analysis
|
|
34
|
+
return await this.executeVisionAnalysis(TEXT_EXTRACTION_PROMPT, enhancedPrompt, [imageContent], 'text-extraction');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Register Text Extraction tool with MCP server
|
|
39
|
+
* @param server MCP server instance
|
|
40
|
+
*/
|
|
41
|
+
export function registerTextExtractionTool(server) {
|
|
42
|
+
const service = new TextExtractionService();
|
|
43
|
+
const retryableExtract = withRetry(service.extractText.bind(service), 2, 1000);
|
|
44
|
+
server.tool('extract_text_from_screenshot', `Extract and recognize text from screenshots using advanced OCR capabilities.
|
|
45
|
+
|
|
46
|
+
Use this tool ONLY when the user has a screenshot containing text and wants to extract it.
|
|
47
|
+
This tool specializes in OCR for code, terminal output, documentation, and general text extraction.
|
|
48
|
+
|
|
49
|
+
Do NOT use for: UI design conversion, error diagnosis, or diagram understanding.`, {
|
|
50
|
+
image_source: z.string().describe('Local file path or remote URL to the image'),
|
|
51
|
+
prompt: z.string().describe('Instructions for text extraction. Specify what type of text to extract and any formatting requirements.'),
|
|
52
|
+
programming_language: z.string().optional().describe('Optional: specify the programming language if the screenshot contains code (e.g., \'python\', \'javascript\', \'java\'). Leave empty for auto-detection or non-code text.')
|
|
53
|
+
}, async (params) => {
|
|
54
|
+
try {
|
|
55
|
+
const validationSchema = new ToolSchemaBuilder()
|
|
56
|
+
.required('image_source', CommonSchemas.nonEmptyString)
|
|
57
|
+
.required('prompt', CommonSchemas.nonEmptyString)
|
|
58
|
+
.optional('programming_language', z.string())
|
|
59
|
+
.build();
|
|
60
|
+
validationSchema.parse(params);
|
|
61
|
+
const result = await retryableExtract(params.image_source, params.prompt, params.programming_language);
|
|
62
|
+
return formatMcpResponse(createSuccessResponse(result));
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
console.error('Text extraction tool execution failed', {
|
|
66
|
+
error: error instanceof Error ? error.message : String(error),
|
|
67
|
+
params
|
|
68
|
+
});
|
|
69
|
+
let errorResponse;
|
|
70
|
+
if (error instanceof z.ZodError) {
|
|
71
|
+
const validationErrors = error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', ');
|
|
72
|
+
errorResponse = createErrorResponse(`Validation failed: ${validationErrors}`);
|
|
73
|
+
}
|
|
74
|
+
else if (error instanceof FileNotFoundError) {
|
|
75
|
+
errorResponse = createErrorResponse(`Image file not found: ${error.message}`);
|
|
76
|
+
}
|
|
77
|
+
else if (error instanceof ApiError) {
|
|
78
|
+
errorResponse = createErrorResponse(`API error: ${error.message}`);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
errorResponse = createErrorResponse(`Unexpected error: ${error instanceof Error ? error.message : String(error)}`);
|
|
82
|
+
}
|
|
83
|
+
return formatMcpResponse(errorResponse);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
console.info('Text Extraction tool registered successfully');
|
|
87
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { FileNotFoundError, ApiError } from '../types/index.js';
|
|
3
|
+
import { CommonSchemas, ToolSchemaBuilder } from '../utils/validation.js';
|
|
4
|
+
import { formatMcpResponse, createSuccessResponse, createErrorResponse, withRetry } from '../core/api-common.js';
|
|
5
|
+
import { BaseImageAnalysisService } from '../core/base-image-service.js';
|
|
6
|
+
import { UI_DIFF_CHECK_PROMPT } from '../prompts/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* UI Diff Check service - Compare two UI screenshots
|
|
9
|
+
*/
|
|
10
|
+
class UiDiffCheckService extends BaseImageAnalysisService {
|
|
11
|
+
/**
|
|
12
|
+
* Compare two UI screenshots
|
|
13
|
+
* @param expectedImageSource Expected/reference design image
|
|
14
|
+
* @param actualImageSource Actual implementation image
|
|
15
|
+
* @param userPrompt User's comparison requirements
|
|
16
|
+
* @returns Comparison analysis with differences
|
|
17
|
+
*/
|
|
18
|
+
async compareUiScreenshots(expectedImageSource, actualImageSource, userPrompt) {
|
|
19
|
+
console.info('Starting UI diff comparison', {
|
|
20
|
+
expectedImage: expectedImageSource,
|
|
21
|
+
actualImage: actualImageSource,
|
|
22
|
+
prompt: userPrompt
|
|
23
|
+
});
|
|
24
|
+
// Validate prompt
|
|
25
|
+
this.validatePrompt(userPrompt, 'ui-diff-check');
|
|
26
|
+
// Enhance prompt to clarify which image is which
|
|
27
|
+
const enhancedPrompt = `<images>
|
|
28
|
+
The first image is the EXPECTED/REFERENCE design (the target).
|
|
29
|
+
The second image is the ACTUAL/CURRENT implementation (what needs to be checked).
|
|
30
|
+
</images>
|
|
31
|
+
|
|
32
|
+
${userPrompt}`;
|
|
33
|
+
// Process both images
|
|
34
|
+
const imageContents = await this.processMultipleImageSources([
|
|
35
|
+
expectedImageSource,
|
|
36
|
+
actualImageSource
|
|
37
|
+
]);
|
|
38
|
+
// Execute analysis
|
|
39
|
+
return await this.executeVisionAnalysis(UI_DIFF_CHECK_PROMPT, enhancedPrompt, imageContents, 'ui-diff-check');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Register UI Diff Check tool with MCP server
|
|
44
|
+
* @param server MCP server instance
|
|
45
|
+
*/
|
|
46
|
+
export function registerUiDiffCheckTool(server) {
|
|
47
|
+
const service = new UiDiffCheckService();
|
|
48
|
+
const retryableCompare = withRetry(service.compareUiScreenshots.bind(service), 2, 1000);
|
|
49
|
+
server.tool('ui_diff_check', `Compare two UI screenshots to identify visual differences and implementation discrepancies.
|
|
50
|
+
|
|
51
|
+
Use this tool ONLY when the user wants to compare an expected/reference UI with an actual implementation.
|
|
52
|
+
This tool is specialized for UI quality assurance and design-to-implementation verification.
|
|
53
|
+
|
|
54
|
+
Do NOT use for: general image comparison, error diagnosis, or analyzing single UIs.`, {
|
|
55
|
+
expected_image_source: z.string().describe('Local file path or remote URL to the image'),
|
|
56
|
+
actual_image_source: z.string().describe('Local file path or remote URL to the image'),
|
|
57
|
+
prompt: z.string().describe('Instructions for the comparison. Specify what aspects to focus on or what level of detail is needed.')
|
|
58
|
+
}, async (params) => {
|
|
59
|
+
try {
|
|
60
|
+
const validationSchema = new ToolSchemaBuilder()
|
|
61
|
+
.required('expected_image_source', CommonSchemas.nonEmptyString)
|
|
62
|
+
.required('actual_image_source', CommonSchemas.nonEmptyString)
|
|
63
|
+
.required('prompt', CommonSchemas.nonEmptyString)
|
|
64
|
+
.build();
|
|
65
|
+
validationSchema.parse(params);
|
|
66
|
+
const result = await retryableCompare(params.expected_image_source, params.actual_image_source, params.prompt);
|
|
67
|
+
return formatMcpResponse(createSuccessResponse(result));
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
console.error('UI diff check tool execution failed', {
|
|
71
|
+
error: error instanceof Error ? error.message : String(error),
|
|
72
|
+
params
|
|
73
|
+
});
|
|
74
|
+
let errorResponse;
|
|
75
|
+
if (error instanceof z.ZodError) {
|
|
76
|
+
const validationErrors = error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', ');
|
|
77
|
+
errorResponse = createErrorResponse(`Validation failed: ${validationErrors}`);
|
|
78
|
+
}
|
|
79
|
+
else if (error instanceof FileNotFoundError) {
|
|
80
|
+
errorResponse = createErrorResponse(`Image file not found: ${error.message}`);
|
|
81
|
+
}
|
|
82
|
+
else if (error instanceof ApiError) {
|
|
83
|
+
errorResponse = createErrorResponse(`API error: ${error.message}`);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
errorResponse = createErrorResponse(`Unexpected error: ${error instanceof Error ? error.message : String(error)}`);
|
|
87
|
+
}
|
|
88
|
+
return formatMcpResponse(errorResponse);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
console.info('UI Diff Check tool registered successfully');
|
|
92
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { FileNotFoundError, ApiError } from '../types/index.js';
|
|
3
|
+
import { CommonSchemas, ToolSchemaBuilder } from '../utils/validation.js';
|
|
4
|
+
import { formatMcpResponse, createSuccessResponse, createErrorResponse, withRetry } from '../core/api-common.js';
|
|
5
|
+
import { BaseImageAnalysisService } from '../core/base-image-service.js';
|
|
6
|
+
import { UI_TO_ARTIFACT_PROMPTS } from '../prompts/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* UI to Artifact service - Convert UI screenshots to code/prompts/specs/descriptions
|
|
9
|
+
*/
|
|
10
|
+
class UiToArtifactService extends BaseImageAnalysisService {
|
|
11
|
+
/**
|
|
12
|
+
* Convert UI screenshot to specified artifact type
|
|
13
|
+
* @param imageSource Image file path or URL
|
|
14
|
+
* @param outputType Type of output (code, prompt, spec, description)
|
|
15
|
+
* @param userPrompt User's specific requirements
|
|
16
|
+
* @returns Generated artifact
|
|
17
|
+
*/
|
|
18
|
+
async convertUiToArtifact(imageSource, outputType, userPrompt) {
|
|
19
|
+
console.info('Starting UI to artifact conversion', {
|
|
20
|
+
imageSource,
|
|
21
|
+
outputType,
|
|
22
|
+
prompt: userPrompt
|
|
23
|
+
});
|
|
24
|
+
// Validate output type
|
|
25
|
+
const normalizedType = outputType.toLowerCase();
|
|
26
|
+
const systemPrompt = UI_TO_ARTIFACT_PROMPTS[normalizedType];
|
|
27
|
+
if (!systemPrompt) {
|
|
28
|
+
throw new Error(`Invalid output_type '${outputType}'. Must be one of: code, prompt, spec, description`);
|
|
29
|
+
}
|
|
30
|
+
// Validate prompt
|
|
31
|
+
this.validatePrompt(userPrompt, 'ui-to-artifact');
|
|
32
|
+
// Process image
|
|
33
|
+
const imageContent = await this.processImageSource(imageSource);
|
|
34
|
+
// Execute analysis
|
|
35
|
+
return await this.executeVisionAnalysis(systemPrompt, userPrompt, [imageContent], 'ui-to-artifact');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Register UI to Artifact tool with MCP server
|
|
40
|
+
* @param server MCP server instance
|
|
41
|
+
*/
|
|
42
|
+
export function registerUiToArtifactTool(server) {
|
|
43
|
+
const service = new UiToArtifactService();
|
|
44
|
+
const retryableConvert = withRetry(service.convertUiToArtifact.bind(service), 2, 1000);
|
|
45
|
+
server.tool('ui_to_artifact', `Convert UI screenshots into various artifacts: code, prompts, design specifications, or descriptions.
|
|
46
|
+
|
|
47
|
+
Use this tool ONLY when the user wants to:
|
|
48
|
+
- Generate frontend code from UI design (output_type='code')
|
|
49
|
+
- Create AI prompts for UI generation (output_type='prompt')
|
|
50
|
+
- Extract design specifications (output_type='spec')
|
|
51
|
+
- Get natural language description of the UI (output_type='description')
|
|
52
|
+
|
|
53
|
+
Do NOT use for: screenshots containing text/code to extract, error messages, diagrams, or data visualizations.`, {
|
|
54
|
+
image_source: z.string().describe('Local file path or remote URL to the image'),
|
|
55
|
+
output_type: z.enum(['code', 'prompt', 'spec', 'description']).describe("Type of output to generate. Options: 'code' (generate frontend code), 'prompt' (generate AI prompt for recreating this UI), 'spec' (generate design specification document), 'description' (natural language description of the UI)."),
|
|
56
|
+
prompt: z.string().describe('Detailed instructions describing what to generate from this UI image. Should clearly state the desired output and any specific requirements.')
|
|
57
|
+
}, async (params) => {
|
|
58
|
+
try {
|
|
59
|
+
const validationSchema = new ToolSchemaBuilder()
|
|
60
|
+
.required('image_source', CommonSchemas.nonEmptyString)
|
|
61
|
+
.required('output_type', z.enum(['code', 'prompt', 'spec', 'description']))
|
|
62
|
+
.required('prompt', CommonSchemas.nonEmptyString)
|
|
63
|
+
.build();
|
|
64
|
+
validationSchema.parse(params);
|
|
65
|
+
const result = await retryableConvert(params.image_source, params.output_type, params.prompt);
|
|
66
|
+
return formatMcpResponse(createSuccessResponse(result));
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
console.error('UI to artifact tool execution failed', {
|
|
70
|
+
error: error instanceof Error ? error.message : String(error),
|
|
71
|
+
params
|
|
72
|
+
});
|
|
73
|
+
let errorResponse;
|
|
74
|
+
if (error instanceof z.ZodError) {
|
|
75
|
+
const validationErrors = error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', ');
|
|
76
|
+
errorResponse = createErrorResponse(`Validation failed: ${validationErrors}`);
|
|
77
|
+
}
|
|
78
|
+
else if (error instanceof FileNotFoundError) {
|
|
79
|
+
errorResponse = createErrorResponse(`Image file not found: ${error.message}`);
|
|
80
|
+
}
|
|
81
|
+
else if (error instanceof ApiError) {
|
|
82
|
+
errorResponse = createErrorResponse(`API error: ${error.message}`);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
errorResponse = createErrorResponse(`Unexpected error: ${error instanceof Error ? error.message : String(error)}`);
|
|
86
|
+
}
|
|
87
|
+
return formatMcpResponse(errorResponse);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
console.info('UI to Artifact tool registered successfully');
|
|
91
|
+
}
|
|
@@ -78,7 +78,16 @@ export function registerVideoAnalysisTool(server) {
|
|
|
78
78
|
const retryableAnalyze = withRetry(analysisService.analyzeVideo.bind(analysisService), 2, // Maximum 2 retries
|
|
79
79
|
1000 // 1 second delay
|
|
80
80
|
);
|
|
81
|
-
server.tool('analyze_video',
|
|
81
|
+
server.tool('analyze_video', `Analyze video content using advanced AI vision models.
|
|
82
|
+
|
|
83
|
+
Use this tool when the user wants to:
|
|
84
|
+
- Understand what happens in a video
|
|
85
|
+
- Extract key moments or actions from video
|
|
86
|
+
- Analyze video content, scenes, or sequences
|
|
87
|
+
- Get descriptions of video footage
|
|
88
|
+
- Identify objects, people, or activities in video
|
|
89
|
+
|
|
90
|
+
Supports both local files and remote URL. Maximum file size: 8MB. Supports MP4, MOV, M4V formats.`, {
|
|
82
91
|
video_source: z.string().describe('Local file path or remote URL to the video (supports MP4, MOV, M4V)'),
|
|
83
92
|
prompt: z.string().describe('Detailed text prompt describing what to analyze, extract, or understand from the video')
|
|
84
93
|
}, async (params) => {
|
package/package.json
CHANGED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { FileNotFoundError, ApiError } from '../types/index.js';
|
|
3
|
-
import { ToolExecutionError } from '../core/error-handler.js';
|
|
4
|
-
import { CommonSchemas, ToolSchemaBuilder } from '../utils/validation.js';
|
|
5
|
-
import { createMultiModalMessage, createImageContent, formatMcpResponse, createSuccessResponse, createErrorResponse, withRetry } from '../core/api-common.js';
|
|
6
|
-
import { fileService } from '../core/file-service.js';
|
|
7
|
-
import { chatService } from '../core/chat-service.js';
|
|
8
|
-
/**
|
|
9
|
-
* Image analysis service class
|
|
10
|
-
*/
|
|
11
|
-
export class ImageAnalysisService {
|
|
12
|
-
chatService = chatService;
|
|
13
|
-
fileService = fileService;
|
|
14
|
-
MAX_IMAGE_SIZE_MB = 5;
|
|
15
|
-
/**
|
|
16
|
-
* Execute image analysis
|
|
17
|
-
* @param request Image analysis request
|
|
18
|
-
* @returns Analysis result
|
|
19
|
-
*/
|
|
20
|
-
async analyzeImage(request) {
|
|
21
|
-
console.info('Starting image analysis', {
|
|
22
|
-
imageSource: request.imageSource,
|
|
23
|
-
prompt: request.prompt
|
|
24
|
-
});
|
|
25
|
-
try {
|
|
26
|
-
// Validate image source (file or URL) and size
|
|
27
|
-
await this.fileService.validateImageSource(request.imageSource, this.MAX_IMAGE_SIZE_MB);
|
|
28
|
-
// Validate prompt
|
|
29
|
-
if (!request.prompt || request.prompt.trim().length === 0) {
|
|
30
|
-
throw new ToolExecutionError('Prompt is required for image analysis', 'image-analysis', 'VALIDATION_ERROR', {
|
|
31
|
-
toolName: 'image-analysis',
|
|
32
|
-
operation: 'analyzeImage',
|
|
33
|
-
metadata: { imageSource: request.imageSource }
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
// Handle image source (URL or local file)
|
|
37
|
-
let imageContent;
|
|
38
|
-
if (this.fileService.isUrl(request.imageSource)) {
|
|
39
|
-
// For URLs, pass directly without base64 encoding
|
|
40
|
-
imageContent = createImageContent(request.imageSource);
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
// For local files, encode to base64
|
|
44
|
-
const imageData = await this.fileService.encodeImageToBase64(request.imageSource);
|
|
45
|
-
imageContent = createImageContent(imageData);
|
|
46
|
-
}
|
|
47
|
-
// Create multimodal message
|
|
48
|
-
const messages = createMultiModalMessage([imageContent], request.prompt);
|
|
49
|
-
const result = await this.chatService.visionCompletions(messages);
|
|
50
|
-
console.info('Image analysis completed', {
|
|
51
|
-
imageSource: request.imageSource
|
|
52
|
-
});
|
|
53
|
-
return result;
|
|
54
|
-
}
|
|
55
|
-
catch (error) {
|
|
56
|
-
console.error('Image analysis failed', {
|
|
57
|
-
error: error instanceof Error ? error.message : String(error),
|
|
58
|
-
imageSource: request.imageSource
|
|
59
|
-
});
|
|
60
|
-
if (error instanceof ToolExecutionError) {
|
|
61
|
-
throw error;
|
|
62
|
-
}
|
|
63
|
-
// Wrap unknown errors
|
|
64
|
-
throw new ToolExecutionError(`Image analysis failed: ${error.message}`, 'image-analysis', 'EXECUTION_ERROR', {
|
|
65
|
-
toolName: 'image-analysis',
|
|
66
|
-
operation: 'analyzeImage',
|
|
67
|
-
metadata: { imageSource: request.imageSource, originalError: error }
|
|
68
|
-
}, error);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Register image analysis tool with MCP server
|
|
74
|
-
* @param server MCP server instance
|
|
75
|
-
*/
|
|
76
|
-
export function registerImageAnalysisTool(server) {
|
|
77
|
-
const analysisService = new ImageAnalysisService();
|
|
78
|
-
const retryableAnalyze = withRetry(analysisService.analyzeImage.bind(analysisService), 2, // Maximum 2 retries
|
|
79
|
-
1000 // 1 second delay
|
|
80
|
-
);
|
|
81
|
-
server.tool('analyze_image', 'Analyze an image using advanced AI vision models with comprehensive understanding capabilities. Supports both local files and remote URL. Maximum file size: 5MB', {
|
|
82
|
-
image_source: z.string().describe('Local file path or remote URL to the image (supports PNG, JPG, JPEG)'),
|
|
83
|
-
prompt: z.string().describe('Detailed text prompt. If the task is **front-end code replication**, the prompt you provide must be: "Describe in detail the layout structure, color style, main components, and interactive elements of the website in this image to facilitate subsequent code generation by the model." + your additional requirements. \ For **other tasks**, the prompt you provide must clearly describe what to analyze, extract, or understand from the image.')
|
|
84
|
-
}, async (params) => {
|
|
85
|
-
try {
|
|
86
|
-
// Validate parameters
|
|
87
|
-
const validationSchema = new ToolSchemaBuilder()
|
|
88
|
-
.required('image_source', CommonSchemas.nonEmptyString)
|
|
89
|
-
.required('prompt', CommonSchemas.nonEmptyString)
|
|
90
|
-
.build();
|
|
91
|
-
validationSchema.parse(params);
|
|
92
|
-
// Build request object
|
|
93
|
-
const request = {
|
|
94
|
-
imageSource: params.image_source,
|
|
95
|
-
prompt: params.prompt
|
|
96
|
-
};
|
|
97
|
-
// Execute analysis
|
|
98
|
-
const result = await retryableAnalyze(request);
|
|
99
|
-
const response = createSuccessResponse(result);
|
|
100
|
-
return formatMcpResponse(response);
|
|
101
|
-
}
|
|
102
|
-
catch (error) {
|
|
103
|
-
console.error('Tool execution failed', {
|
|
104
|
-
error: error instanceof Error ? error.message : String(error),
|
|
105
|
-
params
|
|
106
|
-
});
|
|
107
|
-
let errorResponse;
|
|
108
|
-
if (error instanceof z.ZodError) {
|
|
109
|
-
const validationErrors = error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', ');
|
|
110
|
-
errorResponse = createErrorResponse(`Validation failed: ${validationErrors}`);
|
|
111
|
-
}
|
|
112
|
-
else if (error instanceof FileNotFoundError) {
|
|
113
|
-
errorResponse = createErrorResponse(`Image file not found: ${error.message}`);
|
|
114
|
-
}
|
|
115
|
-
else if (error instanceof ApiError) {
|
|
116
|
-
errorResponse = createErrorResponse(`API error: ${error.message}`);
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
errorResponse = createErrorResponse(`Unexpected error: ${error instanceof Error ? error.message : String(error)}`);
|
|
120
|
-
}
|
|
121
|
-
return formatMcpResponse(errorResponse);
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
console.info('Image analysis tool registered successfully');
|
|
125
|
-
}
|