Skip to main content
Glama
antonpinchuk

mobile-mcp-opengl

by antonpinchuk

MCP für OpenGL-Android-Entwicklung und -Automatisierung

Ein MCP-Server für KI-Codierungsagenten (Claude Code, Cursor usw.) zum Testen von Android-Apps, deren gesamte Benutzeroberfläche in einer einzigen opaken OpenGL/Vulkan/Metal-Oberfläche gezeichnet wird – Cocos2d-x, Unity, Unreal, rohes OpenGL, libGDX und ähnliche Engines.

Das Problem, das dies löst

adb shell uiautomator dump und jedes auf dem Accessibility-Baum basierende Automatisierungstool (einschließlich der meisten MCP-Mobilautomatisierungsserver) funktionieren, indem sie die native Android-View-Hierarchie untersuchen – Schaltflächen, Beschriftungen, deren Text und Koordinaten. Das funktioniert hervorragend für eine normale Android-Benutzeroberfläche, die aus nativen Views aufgebaut ist.

Es funktioniert nicht für ein Spiel oder eine App, die ihre gesamte Benutzeroberfläche als Texturen in einer einzigen GLSurfaceView rendert. Aus Sicht des Accessibility-Baums gibt es genau eine opake View auf dem Bildschirm ohne Kinder, ohne Beschriftungen, ohne Koordinaten für irgendetwas darin. Es gibt nichts zu untersuchen – der Bildschirm ist eine Blackbox, egal wie viel UI tatsächlich darauf ist.

Der einzige verbleibende echte Beobachtungskanal sind Screenshots. Dieser Server ist um diese Tatsache herum aufgebaut, als Normalfall, nicht als gelegentlicher Fallback.

Wie sich dies von mobile-mcp unterscheidet

mobile-next/mobile-mcp ist der Allzweck-MCP-Mobilautomatisierungsserver und eine gute Standardwahl für normale native Apps: zuerst Accessibility-Baum (schnell, günstig, kein Vision-Modell, keine Bild-Tokens), nur wenn der Baum nicht liefert, was benötigt wird, wird auf Screenshots + Koordinaten zurückgegriffen.

Für eine OpenGL-Canvas-App ist dieser Fallback nicht gelegentlich – es ist der einzige Weg, der jemals funktioniert, jedes Mal. mobile-mcp-opengl ist speziell für diesen Fall gebaut und trifft dadurch zwei unterschiedliche Designentscheidungen:

  1. Überhaupt kein Versuch des Accessibility-Baums. Es gibt nichts zu gewinnen, wenn man es versucht – er kommt für diese Apps immer leer zurück –, daher geht jedes Tool hier direkt zu Screenshot + Vision.

  2. Die Vision-Analyse läuft über einen pluggable, separaten Provider (siehe unten), nicht über das Modell, das den aufrufenden Agenten ausführt. Eine funktionale QA-Schleife über ein Spiel kann leicht Hunderte von Screenshot-Prüfungen pro Sitzung erreichen; das alles über die eigene Vision des Haupt-Codierungsagenten zu leiten kostet echtes Geld und Tokens/Kontext, die du lieber für die eigentliche Codierungsarbeit ausgeben würdest. Hier gelangen die Screenshot-Bytes nie in den Kontext des aufrufenden Agenten – nur die kurze Textantwort des Providers.

Related MCP server: Android-MCP

Warum kombinierte Aktions- und Beobachtungswerkzeuge, nicht separate Primitive

Ein naives Design stellt tap, screenshot und ask als drei separate Werkzeuge bereit. Das zwingt den aufrufenden Agenten, für jede einzelne Interaktion eine mehrstufige Schleife zu orchestrieren: Tippen → Screenshot machen → an einen Vision-Schritt übergeben → Ergebnis lesen → entscheiden, was als Nächstes zu tun ist. Jeder dieser Schritte ist ein separater Tool-Aufruf und eine separate Runde – Tokens werden für Koordination verbrannt statt für die eigentliche Testlogik, und es gibt mehr Angriffsfläche für den Agenten, einen Schritt auszulassen, sie falsch zu ordnen oder über veralteten Zustand zwischen Aufrufen nachzudenken.

Stattdessen stellt dieser Server kombinierte Werkzeuge bereit – tap_and_ask, swipe_and_ask, long_press_and_ask – die die Aktion ausführen, kurz warten, den Screenshot machen, den Vision-Provider fragen und eine kurze Antwort zurückgeben, alles als ein einziger Tool-Aufruf. Ein mehrstufiges Testszenario kostet am Ende ungefähr eine Agentenrunde pro sinnvoller Prüfung, nicht drei oder vier.

Einfache screenshot_ask (nur beobachten, keine Aktion) und günstige Nicht-Vision-Werkzeuge (type_text, press_key, logcat_grep) sind ebenfalls für die Teile eines Testablaufs verfügbar, die dieses Muster nicht benötigen.

Werkzeuge

Tool

Was es tut

Vision-Aufruf?

screenshot_ask

Screenshot, dann eine kurze Frage dazu stellen

Ja

tap_and_ask

Tippen (x, y), warten, Screenshot, fragen

Ja

swipe_and_ask

Wischen/Ziehen (x1,y1)→(x2,y2), warten, Screenshot, fragen

Ja

long_press_and_ask

Langes Drücken (x, y) für eine Dauer, warten, Screenshot, fragen

Ja

record_and_ask

Optionale Aktion, dann N Screenshots mit zeitlichem Abstand, dieselbe Frage zu jedem Frame stellen

Ja (N Aufrufe)

type_text

In das aktuell fokussierte Feld tippen

Nein

press_key

Ein Android-KEYCODE_*-Ereignis senden (Zurück, Eingabe, ...)

Nein

logcat_grep

Aktuelles logcat lesen, optional nach Regex gefiltert

Nein

vision_spend_report

Heutige kumulative Vision-Ausgaben und Schwellenwerte melden

Nein

Bevorzuge logcat_grep gegenüber einem Vision-Aufruf, wenn das, was du brauchst, bereits in einer Log-Zeile steht (Abstürze, eigene Debug-Ausgaben, Netzwerkfehler) – es ist kostenlos und exakt, ein Vision-Aufruf ist beides nicht.

Animationen prüfen: record_and_ask

Einzelbild-Werkzeuge können dir nicht sagen, ob etwas animiert korrekt funktioniert (pulsiert der Stärkeindikator sanft, fliegt ein Label hoch und blendet aus, springt ein Sprite zurück zu seiner Startposition). record_and_ask führt eine optionale Aktion aus (Tippen oder Wischen, oder keines), wartet waitMs (gleiche Bedeutung wie waitMs in tap_and_ask/swipe_and_ask – Zeit für die UI, um zu reagieren, bevor das erste Bild aufgenommen wird), erfasst dann frameCount Screenshots im Abstand von intervalMs und gibt eine kurze Antwort pro Frame zurück – der aufrufende Agent erhält eine Zeitleiste in einem Tool-Aufruf, anstatt selbst N separate Screenshot+Ask-Roundtrips zu orchestrieren.

Warum ein Vision-Aufruf pro Frame, nicht ein Aufruf mit allen Frames gebündelt. Runwares imageCaption akzeptiert offenbar ein undokumentiertes inputImages-Array (Plural) neben dem dokumentierten einzelnen inputImage – direkt gegen die API getestet. Es funktioniert sauber für genau 2 Bilder (ein Vorher/Nachher-Vergleich in derselben Anfrage kam korrekt und kohärent zurück). Bei 3+ Bildern in einer Anfrage erzeugten sowohl dieses Array-Parameter als auch ein manuell zusammengesetztes Side-by-Side-„Filmstreifen“-Bild in Tests abgeschnittene oder fehlerhafte Antworten – das kleine 7B-Vision-Modell verliert offenbar die Kohärenz, wenn die kombinierte visuelle+Anweisungslast in einem Aufruf zu hoch wird. Sequentielle Einzelbild-Aufrufe (der Ansatz dieses Tools) waren bei jeder getesteten Frame-Anzahl zuverlässig und sind nicht wesentlich teurer: Die Kosten werden von der Antwortlänge (siehe unten) dominiert, nicht von der Anzahl der Aufrufe, daher kosten N kurze sequentielle Antworten ungefähr so viel wie oder weniger als eine lange Multi-Bild-Antwort. Wenn dein eigener Provider Multi-Bild-Anfragen zuverlässiger verarbeitet, ist dies ein offensichtlicher Ort zum Optimieren – siehe „Bring dein eigenes Modell“.

Einrichtung

git clone <this repo>
cd mobile-mcp-opengl
npm install
cp .env.example .env
# edit .env: at minimum set RUNWARE_API_KEY (or switch VISION_PROVIDER, see below)

Erfordert adb im PATH (oder ADB_PATH in .env gesetzt) und ein laufendes/verbundenes Gerät oder einen Emulator. Wenn mehr als eines angeschlossen ist, setze ADB_DEVICE_SERIAL (siehe adb devices).

Bei Claude Code registrieren

Füge eine .mcp.json in deinem Projektstamm hinzu (diese Datei ist normalerweise projektspezifisch und git-ignoriert, da sie normalerweise auf einen maschinenspezifischen Pfad zeigt oder maschinenspezifische Env-Überschreibungen enthält):

{
  "mcpServers": {
    "mobile-opengl": {
      "command": "node",
      "args": ["/absolute/path/to/mobile-mcp-opengl/src/server.js"]
    }
  }
}

Claude Code übernimmt dies automatisch für das Projekt. Der Server liest seine eigene .env (neben package.json in diesem Repo) für die gesamte Konfiguration – der aufrufende Agent muss selbst nie einen API-Schlüssel kennen oder übergeben.

Kostenmodell – lies dies, bevor du eine lange QA-Sitzung ausführst

Die Antwortlänge treibt die Kosten, nicht die Bildgröße. Dies wurde empirisch gegen den Standard-Provider Runware/Qwen2.5-VL-7B-Instruct gemessen: Dieselbe Frage mit einer erzwungenen Ein-Wort-Antwort kostete gleich viel ($0.0006) über Bildgrößen von 360×360 bis 1600×2400 (Retina-Klasse). Dasselbe 1024×1024-Bild mit einer offenen „Beschreibe dies“-Aufforderung kostete $0.0013–0.0019 – 2-3x mehr – rein weil das Modell eine längere Antwort schrieb, nicht weil das Bild größer war.

Praktische Auswirkungen:

  • Vergiss das Herunterskalieren von Screenshots, bevor du sie sendest – es reduziert die Kosten für diesen Provider nicht wesentlich und du verlierst Details, die du vielleicht brauchst.

  • Formuliere Fragen immer so, dass kurze Antworten erzwungen werden: ja/nein, eine Zahl, ein kurzes Label, ein winziges JSON-Objekt mit ein paar Feldern. Jedes Tool in diesem Server fügt automatisch eine Kurzantwort-Anweisung hinzu, aber eine vage offene Frage („Was siehst du?“) kann das Modell dennoch zu einer längeren Antwort drängen als eine spezifische („Ist der Fehlerdialog sichtbar? ja/nein“).

Bei ~$0.0006/Aufruf für gut formulierte kurze Fragen kostet eine 500-Aufruf-QA-Sitzung ungefähr $0.30. Das gleiche Volumen an offenen „Beschreibe den Bildschirm“-Fragen kann das 2-3x kosten.

Integrierte Ausgaben-Schutzmechanismen

Jeder Vision-Aufruf wird in .vision-log.jsonl protokolliert (JSONL, ein Eintrag pro Aufruf: Zeitstempel, Frage, Antwort, Kosten). Zwei unabhängige Schutzmechanismen sitzen auf diesem Log, beide provider-agnostisch (sie arbeiten mit dem, was ein Provider als costUsd meldet):

  • Pro-Aufruf-Warnung (VISION_ALERT_USD, Standard $0.0015): Wenn ein einzelner Aufruf darüber zurückkommt, enthält die Antwort des Tools einen [COST ALERT]-Hinweis, der dir sagt, dass das Modell wahrscheinlich die Kurzantwort-Anweisung ignoriert hat – ein Signal, die Frage umzuformulieren, nicht etwas, das man stillschweigend hinnehmen sollte.

  • Tageslimit (VISION_SESSION_CAP_USD, Standard $2.00): Sobald die heutigen kumulierten protokollierten Ausgaben diesen Wert erreichen, wird jeder weitere Vision-Aufruf komplett abgelehnt (bevor er den Provider erreicht), bis das Limit erhöht wird oder der Tag umschlägt. Dies ist ein harter Stopp gegen eine außer Kontrolle geratene Schleife, nicht nur eine Warnung.

Rufe vision_spend_report jederzeit auf, um die heutige Summe zu prüfen, ohne einen Geräte- oder Vision-Aufruf zu machen.

Wenn ein Provider keine Kosten melden kann (siehe openai-compatible unten), werden Aufrufe von ihm mit costUsd: null protokolliert und lösen nie die Warnung aus oder zählen zum Limit – die Schutzmechanismen können einfach keine Ausgaben schützen, die sie nicht sehen können.

Bring dein eigenes Modell

Die Vision-Analyse läuft über src/providers/visionProvider.js, das einen Provider anhand des Namens aus VISION_PROVIDER in .env auswählt. Zwei sind integriert:

  • runware (Standard) – spricht direkt mit der imageCaption-Aufgabe von Runware.ai und verwendet standardmäßig Qwen2.5-VL-7B-Instruct (AIR-ID runware:152@2). Runware und OpenRouter sind zwei separate Dienste mit separaten API-Schlüsseln und Modellkatalogen – dies spricht direkt mit Runware, nicht über OpenRouter.

  • openai-compatible – ein generischer Provider für alles, was das OpenAI-Chat-Completions-Vision-Format spricht (image_url-Inhaltsteile). Funktioniert mit OpenRouter, einem lokalen Ollama/LM-Studio-Server mit einem Vision-Modell, Groq, Together.ai oder jedem anderen kompatiblen Endpunkt. Konfiguriere OPENAI_COMPATIBLE_BASE_URL, OPENAI_COMPATIBLE_API_KEY, OPENAI_COMPATIBLE_MODEL in .env. Die meisten OpenAI-kompatiblen APIs melden Token-Nutzung statt eines festen Dollar-Betrags; setze OPENAI_COMPATIBLE_PRICE_PER_1M_INPUT/_OUTPUT, wenn du möchtest, dass dieser Provider costUsd daraus schätzt (andernfalls sind Kostenverfolgung/Schutzmechanismen für diesen Provider wirkungslos, wie oben erwähnt).

Um einen vollständig benutzerdefinierten Provider hinzuzufügen (ein selbst gehostetes Modell, eine völlig andere API-Form), kopiere src/providers/openaiCompatibleProvider.js als Ausgangspunkt und implementiere:

async function ask(imageBuffer, mimeType, question) {
  // return { text: string, costUsd: number | null }
}
module.exports = { ask };

und registriere ihn mit einem Namen in loadProvider() von src/providers/visionProvider.js.

Lizenz

MIT


Entwickelt von Kinect.PRO

Install Server
F
license - not found
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    C
    quality
    B
    maintenance
    A lightweight bridge enabling AI agents to perform real-world tasks on Android devices such as app navigation, UI interaction, and automated QA testing without requiring computer-vision pipelines or preprogrammed scripts.
    14
    807
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to control Android devices and emulators through direct UI interaction, allowing app navigation, automated testing, and real-world task execution via ADB without computer vision or scripts.
    1
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI agents to fully control Android devices through over 30 tools for app management, UI automation, and vision-based analysis via ADB. It supports multi-device management, action recording, and smart execution strategies ranging from UI hierarchy parsing to coordinate-based interaction.
    37
    137
    1
    MIT

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/antonpinchuk/mobile-mcp-opengl'

If you have feedback or need assistance with the MCP directory API, please join our Discord server