Fix TypeScript errors and update Dockerfile for Alpine compatibility

This commit is contained in:
stabgan
2025-03-27 00:40:35 +05:30
parent a0d92730db
commit a9301b65eb
5 changed files with 30 additions and 23 deletions

View File

@@ -8,7 +8,8 @@ RUN apk add --no-cache \
make \ make \
python3 \ python3 \
curl \ curl \
ca-certificates ca-certificates \
vips-dev
# Configure npm for better reliability # Configure npm for better reliability
RUN npm config set strict-ssl false RUN npm config set strict-ssl false
@@ -16,18 +17,24 @@ RUN npm config set registry https://registry.npmjs.org/
RUN npm config set fetch-retry-mintimeout 20000 RUN npm config set fetch-retry-mintimeout 20000
RUN npm config set fetch-retry-maxtimeout 120000 RUN npm config set fetch-retry-maxtimeout 120000
# Copy package files # Install global packages needed for build
COPY package*.json ./ RUN npm install -g typescript shx
# Clean npm cache and install dependencies # Copy package files and modify to prevent prepare script from running
COPY package*.json ./
RUN node -e "const pkg = require('./package.json'); delete pkg.scripts.prepare; require('fs').writeFileSync('./package.json', JSON.stringify(pkg, null, 2));"
# Install dependencies without running the prepare script, including sharp with the correct platform
RUN npm cache clean --force && \ RUN npm cache clean --force && \
npm install --legacy-peer-deps --no-optional npm install --legacy-peer-deps --no-optional && \
npm install --platform=linuxmusl --arch=x64 sharp
# Copy source code # Copy source code
COPY . . COPY . .
# Build TypeScript code # Build TypeScript code manually
RUN npm run build RUN npx tsc && \
npx shx chmod +x dist/*.js
# Switch to production for runtime # Switch to production for runtime
ENV NODE_ENV=production ENV NODE_ENV=production

View File

@@ -1,5 +1,5 @@
import axios, { AxiosError, AxiosInstance } from 'axios'; import axios, { AxiosError, AxiosInstance } from 'axios';
import { McpError } from '@modelcontextprotocol/sdk/types.js'; import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
/** /**
* Client for interacting with the OpenRouter API * Client for interacting with the OpenRouter API
@@ -90,7 +90,7 @@ export class OpenRouterAPIClient {
if (axiosError.response) { if (axiosError.response) {
const responseData = axiosError.response.data as any; const responseData = axiosError.response.data as any;
const message = responseData?.error?.message || axiosError.message; const message = responseData?.error?.message || axiosError.message;
throw new McpError('RequestFailed', `OpenRouter API error: ${message}`); throw new McpError(ErrorCode.InternalError, `OpenRouter API error: ${message}`);
} }
} }
@@ -114,17 +114,17 @@ export class OpenRouterAPIClient {
const message = responseData?.error?.message || axiosError.message; const message = responseData?.error?.message || axiosError.message;
if (status === 401 || status === 403) { if (status === 401 || status === 403) {
throw new McpError('Unauthorized', `Authentication error: ${message}`); throw new McpError(ErrorCode.InvalidRequest, `Authentication error: ${message}`);
} else if (status === 429) { } else if (status === 429) {
throw new McpError('RateLimitExceeded', `Rate limit exceeded: ${message}`); throw new McpError(ErrorCode.InternalError, `Rate limit exceeded: ${message}`);
} else { } else {
throw new McpError('RequestFailed', `OpenRouter API error (${status}): ${message}`); throw new McpError(ErrorCode.InternalError, `OpenRouter API error (${status}): ${message}`);
} }
} else if (axiosError.request) { } else if (axiosError.request) {
throw new McpError('NetworkError', `Network error: ${axiosError.message}`); throw new McpError(ErrorCode.ConnectionClosed, `Network error: ${axiosError.message}`);
} }
} }
throw new McpError('UnknownError', `Unknown error: ${error.message || 'No error message'}`); throw new McpError(ErrorCode.InternalError, `Unknown error: ${error.message || 'No error message'}`);
} }
} }

View File

@@ -1,7 +1,7 @@
import path from 'path'; import path from 'path';
import { promises as fs } from 'fs'; import { promises as fs } from 'fs';
import sharp from 'sharp'; import sharp from 'sharp';
import { McpError } from '@modelcontextprotocol/sdk/types.js'; import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import OpenAI from 'openai'; import OpenAI from 'openai';
export interface AnalyzeImageToolRequest { export interface AnalyzeImageToolRequest {
@@ -21,7 +21,7 @@ export async function handleAnalyzeImage(
// Validate image path // Validate image path
const imagePath = args.image_path; const imagePath = args.image_path;
if (!path.isAbsolute(imagePath)) { if (!path.isAbsolute(imagePath)) {
throw new McpError('InvalidParams', 'Image path must be absolute'); throw new McpError(ErrorCode.InvalidParams, 'Image path must be absolute');
} }
// Read image file // Read image file
@@ -85,7 +85,7 @@ export async function handleAnalyzeImage(
// Call OpenRouter API // Call OpenRouter API
const completion = await openai.chat.completions.create({ const completion = await openai.chat.completions.create({
model, model,
messages, messages: messages as any,
}); });
return { return {

View File

@@ -1,4 +1,4 @@
import { McpError } from '@modelcontextprotocol/sdk/types.js'; import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import { ModelCache } from '../model-cache.js'; import { ModelCache } from '../model-cache.js';
export interface GetModelInfoToolRequest { export interface GetModelInfoToolRequest {
@@ -26,7 +26,7 @@ export async function handleGetModelInfo(
const model = modelCache.getModel(args.model); const model = modelCache.getModel(args.model);
if (!model) { if (!model) {
throw new McpError('NotFound', `Model '${args.model}' not found`); throw new McpError(ErrorCode.InvalidParams, `Model '${args.model}' not found`);
} }
return { return {

View File

@@ -1,6 +1,6 @@
import fetch from 'node-fetch'; import fetch from 'node-fetch';
import sharp from 'sharp'; import sharp from 'sharp';
import { McpError } from '@modelcontextprotocol/sdk/types.js'; import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import OpenAI from 'openai'; import OpenAI from 'openai';
export interface MultiImageAnalysisToolRequest { export interface MultiImageAnalysisToolRequest {
@@ -90,11 +90,11 @@ export async function handleMultiImageAnalysis(
try { try {
// Validate inputs // Validate inputs
if (!args.images || args.images.length === 0) { if (!args.images || args.images.length === 0) {
throw new McpError('InvalidParams', 'At least one image is required'); throw new McpError(ErrorCode.InvalidParams, 'At least one image is required');
} }
if (!args.prompt) { if (!args.prompt) {
throw new McpError('InvalidParams', 'A prompt is required'); throw new McpError(ErrorCode.InvalidParams, 'A prompt is required');
} }
// Prepare content array for the message // Prepare content array for the message
@@ -137,7 +137,7 @@ export async function handleMultiImageAnalysis(
messages: [{ messages: [{
role: 'user', role: 'user',
content content
}] }] as any
}); });
return { return {