Draw Things MCP

#!/usr/bin/env node /** * Draw Things API Connection Test * 測試不同方式連接到 Draw Things API */ import http from 'http'; import https from 'https'; import axios from 'axios'; import fs from 'fs'; // 記錄檔 const logFile = 'api-connection-test.log'; function log(message) { const timestamp = new Date().toISOString(); const logMessage = `${timestamp} - ${message}\n`; fs.appendFileSync(logFile, logMessage); console.log(message); } // 錯誤記錄 function logError(error, message = 'Error') { const timestamp = new Date().toISOString(); const errorDetails = error instanceof Error ? `${error.message}\n${error.stack}` : String(error); const logMessage = `${timestamp} - [ERROR] ${message}: ${errorDetails}\n`; fs.appendFileSync(logFile, logMessage); console.error(`${message}: ${error.message}`); } // 讀取參數 const apiPort = process.env.DRAW_THINGS_API_PORT || 7888; const apiProxyPort = process.env.PROXY_PORT || 7889; log('Draw Things API Connection Test'); log('==========================='); log(`Testing API on port ${apiPort}`); log(`Testing proxy on port ${apiProxyPort}`); log(''); // 測試 1: 直接使用 HTTP 模組連接 async function testHttpModule() { log('Test 1: 使用 Node.js HTTP 模組連接'); return new Promise((resolve) => { try { const urls = [ { name: '直接 API 連接 (127.0.0.1)', host: '127.0.0.1', port: apiPort }, { name: '直接 API 連接 (localhost)', host: 'localhost', port: apiPort }, { name: '代理伺服器連接 (127.0.0.1)', host: '127.0.0.1', port: apiProxyPort }, { name: '代理伺服器連接 (localhost)', host: 'localhost', port: apiProxyPort } ]; let completedTests = 0; const results = []; for (const url of urls) { log(`測試連接: ${url.name}`); const options = { hostname: url.host, port: url.port, path: '/sdapi/v1/options', method: 'GET', timeout: 5000, headers: { 'User-Agent': 'DrawThingsMCP/1.0', 'Accept': 'application/json' } }; const req = http.request(options, (res) => { log(`${url.name} 回應狀態碼: ${res.statusCode}`); let data = ''; res.on('data', chunk => { data += chunk; }); res.on('end', () => { const success = res.statusCode >= 200 && res.statusCode < 300; results.push({ name: url.name, success, statusCode: res.statusCode, hasData: !!data }); completedTests++; if (completedTests === urls.length) { resolve(results); } }); }); req.on('error', (e) => { log(`${url.name} 錯誤: ${e.message}`); results.push({ name: url.name, success: false, error: e.message }); completedTests++; if (completedTests === urls.length) { resolve(results); } }); req.on('timeout', () => { log(`${url.name} 連接逾時`); req.destroy(); results.push({ name: url.name, success: false, error: 'Timeout' }); completedTests++; if (completedTests === urls.length) { resolve(results); } }); req.end(); } } catch (error) { logError(error, 'HTTP 模組測試發生錯誤'); resolve([]); } }); } // 測試 2: 使用 Axios 連接 async function testAxios() { log('Test 2: 使用 Axios 連接'); try { const urls = [ { name: '直接 API 連接 (127.0.0.1)', url: `http://127.0.0.1:${apiPort}/sdapi/v1/options` }, { name: '直接 API 連接 (localhost)', url: `http://localhost:${apiPort}/sdapi/v1/options` }, { name: '代理伺服器連接 (127.0.0.1)', url: `http://127.0.0.1:${apiProxyPort}/sdapi/v1/options` }, { name: '代理伺服器連接 (localhost)', url: `http://localhost:${apiProxyPort}/sdapi/v1/options` }, ]; const results = []; for (const url of urls) { log(`測試連接: ${url.name}`); try { const response = await axios.get(url.url, { timeout: 5000, headers: { 'User-Agent': 'DrawThingsMCP/1.0', 'Accept': 'application/json' } }); log(`${url.name} 回應狀態碼: ${response.status}`); results.push({ name: url.name, success: response.status >= 200 && response.status < 300, statusCode: response.status, hasData: !!response.data }); } catch (error) { log(`${url.name} 錯誤: ${error.message}`); results.push({ name: url.name, success: false, error: error.message }); } } return results; } catch (error) { logError(error, 'Axios 測試發生錯誤'); return []; } } // 測試 3: 嘗試不同的端點 async function testDifferentEndpoints() { log('Test 3: 測試不同的 API 端點'); try { // 使用工作正常的連接方式 (localhost 或 127.0.0.1) const baseUrl = `http://127.0.0.1:${apiPort}`; const endpoints = [ '/sdapi/v1/options', '/sdapi/v1/samplers', '/sdapi/v1/sd-models', '/sdapi/v1/prompt-styles', '/' ]; const results = []; for (const endpoint of endpoints) { log(`測試端點: ${endpoint}`); try { const response = await axios.get(`${baseUrl}${endpoint}`, { timeout: 5000, headers: { 'User-Agent': 'DrawThingsMCP/1.0', 'Accept': 'application/json' } }); log(`端點 ${endpoint} 回應狀態碼: ${response.status}`); results.push({ endpoint, success: response.status >= 200 && response.status < 300, statusCode: response.status, hasData: !!response.data }); } catch (error) { log(`端點 ${endpoint} 錯誤: ${error.message}`); results.push({ endpoint, success: false, error: error.message }); } } return results; } catch (error) { logError(error, '端點測試發生錯誤'); return []; } } // 執行測試 async function runTests() { try { // 測試 1: HTTP 模組 log('\n執行 HTTP 模組測試...'); const httpResults = await testHttpModule(); log('\nHTTP 模組測試結果:'); httpResults.forEach(result => { log(`${result.name}: ${result.success ? '成功' : '失敗'} ${result.statusCode ? `(狀態碼: ${result.statusCode})` : ''} ${result.error ? `(錯誤: ${result.error})` : ''}`); }); // 測試 2: Axios log('\n執行 Axios 測試...'); const axiosResults = await testAxios(); log('\nAxios 測試結果:'); axiosResults.forEach(result => { log(`${result.name}: ${result.success ? '成功' : '失敗'} ${result.statusCode ? `(狀態碼: ${result.statusCode})` : ''} ${result.error ? `(錯誤: ${result.error})` : ''}`); }); // 測試 3: 不同端點 log('\n執行不同端點測試...'); const endpointResults = await testDifferentEndpoints(); log('\n不同端點測試結果:'); endpointResults.forEach(result => { log(`端點 ${result.endpoint}: ${result.success ? '成功' : '失敗'} ${result.statusCode ? `(狀態碼: ${result.statusCode})` : ''} ${result.error ? `(錯誤: ${result.error})` : ''}`); }); // 總結 const httpSuccess = httpResults.some(r => r.success); const axiosSuccess = axiosResults.some(r => r.success); const endpointSuccess = endpointResults.some(r => r.success); log('\n=== 測試總結 ==='); log(`HTTP 模組連接測試: ${httpSuccess ? '至少有一個成功' : '全部失敗'}`); log(`Axios 連接測試: ${axiosSuccess ? '至少有一個成功' : '全部失敗'}`); log(`端點測試: ${endpointSuccess ? '至少有一個成功' : '全部失敗'}`); if (httpSuccess || axiosSuccess) { log('\nAPI 連接測試成功! 您的 Draw Things API 似乎可以正常工作。'); // 建議最佳連接方式 const bestConnection = [...httpResults, ...axiosResults].find(r => r.success); if (bestConnection) { log(`建議使用連接方式: ${bestConnection.name}`); } } else { log('\nAPI 連接測試失敗! 請確認:'); log('1. Draw Things 應用程式正在運行'); log('2. Draw Things 已啟用 API 功能'); log('3. API 在設定的端口上運行 (默認 7888)'); log('4. 沒有防火牆阻擋連接'); } } catch (error) { logError(error, '測試執行過程中發生錯誤'); } } // 執行測試 runTests().catch(error => { logError(error, '測試主程序發生錯誤'); });