@z_ai/mcp-server 0.1.0 → 0.1.1-beta.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.
@@ -0,0 +1,82 @@
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
+ image_source: z.string().describe('Local file path or remote URL to the image'),
46
+ prompt: z.string().describe('Instructions for text extraction. Specify what type of text to extract and any formatting requirements.'),
47
+ 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.')
48
+ }, async (params) => {
49
+ try {
50
+ const validationSchema = new ToolSchemaBuilder()
51
+ .required('image_source', CommonSchemas.nonEmptyString)
52
+ .required('prompt', CommonSchemas.nonEmptyString)
53
+ .optional('programming_language', z.string())
54
+ .build();
55
+ validationSchema.parse(params);
56
+ const result = await retryableExtract(params.image_source, params.prompt, params.programming_language);
57
+ return formatMcpResponse(createSuccessResponse(result));
58
+ }
59
+ catch (error) {
60
+ console.error('Text extraction tool execution failed', {
61
+ error: error instanceof Error ? error.message : String(error),
62
+ params
63
+ });
64
+ let errorResponse;
65
+ if (error instanceof z.ZodError) {
66
+ const validationErrors = error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', ');
67
+ errorResponse = createErrorResponse(`Validation failed: ${validationErrors}`);
68
+ }
69
+ else if (error instanceof FileNotFoundError) {
70
+ errorResponse = createErrorResponse(`Image file not found: ${error.message}`);
71
+ }
72
+ else if (error instanceof ApiError) {
73
+ errorResponse = createErrorResponse(`API error: ${error.message}`);
74
+ }
75
+ else {
76
+ errorResponse = createErrorResponse(`Unexpected error: ${error instanceof Error ? error.message : String(error)}`);
77
+ }
78
+ return formatMcpResponse(errorResponse);
79
+ }
80
+ });
81
+ console.info('Text Extraction tool registered successfully');
82
+ }
@@ -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 { 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
+ expected_image_source: z.string().describe('Local file path or remote URL to the image'),
51
+ actual_image_source: z.string().describe('Local file path or remote URL to the image'),
52
+ prompt: z.string().describe('Instructions for the comparison. Specify what aspects to focus on or what level of detail is needed.')
53
+ }, async (params) => {
54
+ try {
55
+ const validationSchema = new ToolSchemaBuilder()
56
+ .required('expected_image_source', CommonSchemas.nonEmptyString)
57
+ .required('actual_image_source', CommonSchemas.nonEmptyString)
58
+ .required('prompt', CommonSchemas.nonEmptyString)
59
+ .build();
60
+ validationSchema.parse(params);
61
+ const result = await retryableCompare(params.expected_image_source, params.actual_image_source, params.prompt);
62
+ return formatMcpResponse(createSuccessResponse(result));
63
+ }
64
+ catch (error) {
65
+ console.error('UI diff check 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('UI Diff Check tool registered successfully');
87
+ }
@@ -0,0 +1,83 @@
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
+ image_source: z.string().describe('Local file path or remote URL to the image'),
47
+ 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)."),
48
+ prompt: z.string().describe('Detailed instructions describing what to generate from this UI image. Should clearly state the desired output and any specific requirements.')
49
+ }, async (params) => {
50
+ try {
51
+ const validationSchema = new ToolSchemaBuilder()
52
+ .required('image_source', CommonSchemas.nonEmptyString)
53
+ .required('output_type', z.enum(['code', 'prompt', 'spec', 'description']))
54
+ .required('prompt', CommonSchemas.nonEmptyString)
55
+ .build();
56
+ validationSchema.parse(params);
57
+ const result = await retryableConvert(params.image_source, params.output_type, params.prompt);
58
+ return formatMcpResponse(createSuccessResponse(result));
59
+ }
60
+ catch (error) {
61
+ console.error('UI to artifact tool execution failed', {
62
+ error: error instanceof Error ? error.message : String(error),
63
+ params
64
+ });
65
+ let errorResponse;
66
+ if (error instanceof z.ZodError) {
67
+ const validationErrors = error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', ');
68
+ errorResponse = createErrorResponse(`Validation failed: ${validationErrors}`);
69
+ }
70
+ else if (error instanceof FileNotFoundError) {
71
+ errorResponse = createErrorResponse(`Image file not found: ${error.message}`);
72
+ }
73
+ else if (error instanceof ApiError) {
74
+ errorResponse = createErrorResponse(`API error: ${error.message}`);
75
+ }
76
+ else {
77
+ errorResponse = createErrorResponse(`Unexpected error: ${error instanceof Error ? error.message : String(error)}`);
78
+ }
79
+ return formatMcpResponse(errorResponse);
80
+ }
81
+ });
82
+ console.info('UI to Artifact tool registered successfully');
83
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@z_ai/mcp-server",
3
- "version": "0.1.0",
3
+ "version": "0.1.1-beta.0",
4
4
  "description": "MCP Server for Z.AI - A Model Context Protocol server that provides AI capabilities",
5
5
  "main": "build/index.js",
6
6
  "type": "module",
@@ -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
- }