midjourney-mcp
Version:
A Model Context Protocol server for Midjourney integration via MJ API
150 lines • 4.44 kB
JavaScript
/**
* MJ API client for Midjourney operations
*/
export class ApiError extends Error {
code;
description;
originalError;
constructor(code, description, originalError) {
super(`API Error ${code}: ${description}`);
this.code = code;
this.description = description;
this.originalError = originalError;
this.name = 'ApiError';
}
}
export class MJApiClient {
config;
constructor(config) {
this.config = config;
}
/**
* Make HTTP request with retry logic
*/
async makeRequest(endpoint, options = {}) {
const url = `${this.config.baseUrl}${endpoint}`;
const defaultHeaders = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.config.apiKey}`,
};
const requestOptions = {
...options,
headers: {
...defaultHeaders,
...options.headers,
},
};
let lastError = null;
for (let attempt = 1; attempt <= this.config.maxRetries; attempt++) {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
const response = await fetch(url, {
...requestOptions,
signal: controller.signal,
});
clearTimeout(timeoutId);
if (!response.ok) {
const errorText = await response.text();
throw new ApiError(response.status, `HTTP ${response.status}: ${errorText}`, { status: response.status, statusText: response.statusText });
}
const data = await response.json();
return data;
}
catch (error) {
lastError = error instanceof Error ? error : new Error(String(error));
if (attempt === this.config.maxRetries) {
break;
}
// Wait before retry (exponential backoff)
const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw lastError || new Error('Unknown error occurred');
}
/**
* Submit an imagine task
*/
async submitImagine(request) {
return this.makeRequest('/mj/submit/imagine', {
method: 'POST',
body: JSON.stringify(request),
});
}
/**
* Get task by ID
*/
async getTask(taskId) {
return this.makeRequest(`/mj/task/${taskId}/fetch`);
}
/**
* Submit upscale task
*/
async submitUpscale(taskId, index, state) {
const request = {
taskId,
action: 'UPSCALE',
index,
...(state && { state }),
};
return this.makeRequest('/mj/submit/change', {
method: 'POST',
body: JSON.stringify(request),
});
}
/**
* Submit variation task
*/
async submitVariation(taskId, index, state) {
const request = {
taskId,
action: 'VARIATION',
index,
...(state && { state }),
};
return this.makeRequest('/mj/submit/change', {
method: 'POST',
body: JSON.stringify(request),
});
}
/**
* Submit reroll task
*/
async submitReroll(taskId, state) {
const request = {
taskId,
action: 'REROLL',
...(state && { state }),
};
return this.makeRequest('/mj/submit/change', {
method: 'POST',
body: JSON.stringify(request),
});
}
/**
* Submit blend task
*/
async submitBlend(base64Array, state) {
return this.makeRequest('/mj/submit/blend', {
method: 'POST',
body: JSON.stringify({
base64Array,
state,
}),
});
}
/**
* Submit describe task
*/
async submitDescribe(base64, state) {
return this.makeRequest('/mj/submit/describe', {
method: 'POST',
body: JSON.stringify({
base64,
state,
}),
});
}
}
//# sourceMappingURL=api-client.js.map