UNPKG

@tomisakae/accessibility-service-mcp

Version:

MCP server for Android Accessibility Service API automation

199 lines (198 loc) 7.38 kB
/** * Android Accessibility Service API Client */ import axios from "axios"; import { API_CONFIG } from "../config/config.js"; export class AccessibilityApiClient { client; constructor() { this.client = axios.create({ baseURL: API_CONFIG.BASE_URL, timeout: API_CONFIG.TIMEOUT, headers: API_CONFIG.DEFAULT_HEADERS, }); // Request interceptor để log requests this.client.interceptors.request.use((config) => { console.error(`[API] ${config.method?.toUpperCase()} ${config.url}`); return config; }); // Response interceptor để handle errors this.client.interceptors.response.use((response) => response, (error) => { console.error(`[API Error] ${error.message}`); if (error.code === "ECONNREFUSED") { throw new Error(`Không thể kết nối đến API server tại ${API_CONFIG.BASE_URL}. Vui lòng kiểm tra:\n` + `1. Thiết bị Android đã bật API server\n` + `2. IP address trong .env file đúng (hiện tại: ${API_CONFIG.HOST}:${API_CONFIG.PORT})\n` + `3. Thiết bị và máy tính trong cùng mạng`); } throw error; }); } // Health check async health() { const response = await this.client.get("/health"); if (!response.data.success) { throw new Error(response.data.error || "Health check failed"); } return response.data; } // UI Operations async getUiTree() { const response = await this.client.get("/ui-tree"); if (!response.data.success) { throw new Error(response.data.error || "Failed to get UI tree"); } return response.data; } async findElements(request) { const response = await this.client.post("/find-elements", request); if (!response.data.success) { throw new Error(response.data.error || "Failed to find elements"); } return response.data; } // Interaction Operations async click(request) { const response = await this.client.post("/click", request); if (!response.data.success) { throw new Error(response.data.error || "Click failed"); } return response.data; } async longClick(request) { const response = await this.client.post("/long-click", request); if (!response.data.success) { throw new Error(response.data.error || "Long click failed"); } return response.data; } async doubleClick(request) { const response = await this.client.post("/double-click", request); if (!response.data.success) { throw new Error(response.data.error || "Double click failed"); } return response.data; } async inputText(request) { // Ensure UTF-8 encoding for Vietnamese text const encodedRequest = { ...request, text: Buffer.from(request.text, "utf8").toString("utf8"), }; const response = await this.client.post("/input-text", encodedRequest); if (!response.data.success) { throw new Error(response.data.error || "Input text failed"); } return response.data; } async keyboardAction(request) { const response = await this.client.post("/keyboard-action", request); if (!response.data.success) { throw new Error(response.data.error || "Keyboard action failed"); } return response.data; } async scroll(request) { const response = await this.client.post("/scroll", request); if (!response.data.success) { throw new Error(response.data.error || "Scroll failed"); } return response.data; } async swipe(request) { const response = await this.client.post("/swipe", request); if (!response.data.success) { throw new Error(response.data.error || "Swipe failed"); } return response.data; } // Navigation Operations async home() { const response = await this.client.post("/home"); if (!response.data.success) { throw new Error(response.data.error || "Home navigation failed"); } return response.data; } async back() { const response = await this.client.post("/back"); if (!response.data.success) { throw new Error(response.data.error || "Back navigation failed"); } return response.data; } async recent() { const response = await this.client.post("/recent"); if (!response.data.success) { throw new Error(response.data.error || "Recent apps navigation failed"); } return response.data; } // App Management Operations async clickApp(request) { const response = await this.client.post("/click-app", request); if (!response.data.success) { throw new Error(response.data.error || "Click app failed"); } return response.data; } async launchApp(request) { const response = await this.client.post("/launch-app", request); if (!response.data.success) { throw new Error(response.data.error || "Launch app failed"); } return response.data; } async closeApp(request) { const response = await this.client.post("/close-app", request); if (!response.data.success) { throw new Error(response.data.error || "Close app failed"); } return response.data; } async getRecentApps() { const response = await this.client.get("/recent-apps"); if (!response.data.success) { throw new Error(response.data.error || "Failed to get recent apps"); } return response.data; } // System Operations async getDeviceInfo() { const response = await this.client.get("/device-info"); if (!response.data.success) { throw new Error(response.data.error || "Failed to get device info"); } return response.data; } async getScreenshot() { const response = await this.client.get("/screenshot"); if (!response.data.success) { throw new Error(response.data.error || "Failed to get screenshot"); } return response.data; } async setVolume(request) { const response = await this.client.post("/volume", request); if (!response.data.success) { throw new Error(response.data.error || "Volume control failed"); } return response.data; } async openNotifications() { const response = await this.client.post("/open-notifications"); if (!response.data.success) { throw new Error(response.data.error || "Open notifications failed"); } return response.data; } async openQuickSettings() { const response = await this.client.post("/open-quick-settings"); if (!response.data.success) { throw new Error(response.data.error || "Open quick settings failed"); } return response.data; } } // Singleton instance export const apiClient = new AccessibilityApiClient();