Qwen Code Companion Plugin: Schnittstellenspezifikation
Zuletzt aktualisiert: 15. September 2025
Dieses Dokument definiert den Vertrag für die Entwicklung eines Companion-Plugins, um den IDE-Modus von Qwen Code zu aktivieren. Für VS Code werden diese Funktionen (natives Diffing, Kontextbewusstsein) von der offiziellen Extension bereitgestellt (marketplace ). Diese Spezifikation richtet sich an Contributoren, die ähnliche Funktionen in andere Editoren wie JetBrains IDEs, Sublime Text usw. integrieren möchten.
I. Die Kommunikationsschnittstelle
Qwen Code und das IDE-Plugin kommunizieren über einen lokalen Kommunikationskanal.
1. Transportschicht: MCP über HTTP
Das Plugin MUSS einen lokalen HTTP-Server ausführen, der das Model Context Protocol (MCP) implementiert.
- Protokoll: Der Server muss ein valider MCP-Server sein. Wir empfehlen die Verwendung eines bestehenden MCP SDK für deine bevorzugte Programmiersprache, falls verfügbar.
- Endpoint: Der Server sollte einen einzigen Endpoint (z. B.
/mcp) für die gesamte MCP-Kommunikation bereitstellen. - Port: Der Server MUSS auf einem dynamisch zugewiesenen Port lauschen (d. h. Port
0verwenden).
2. Discovery-Mechanismus: Die Lock-Datei
Damit sich Qwen Code verbinden kann, muss es den Port deines Servers ermitteln. Das Plugin MUSS dies ermöglichen, indem es eine „Lock-Datei“ erstellt und die Port-Umgebungsvariable setzt.
-
Wie die CLI die Datei findet: Die CLI liest den Port aus
QWEN_CODE_IDE_SERVER_PORTund anschließend~/.qwen/ide/<PORT>.lock. (Es gibt Legacy-Fallbacks für ältere Extensions; siehe Hinweis unten.) -
Dateipfad: Die Datei muss in einem bestimmten Verzeichnis erstellt werden:
~/.qwen/ide/. Dein Plugin muss dieses Verzeichnis erstellen, falls es noch nicht existiert. -
Namenskonvention: Der Dateiname ist entscheidend und MUSS folgendem Muster entsprechen:
<PORT>.lock<PORT>: Der Port, auf dem dein MCP-Server lauscht.
-
Dateiinhalt & Workspace-Validierung: Die Datei MUSS ein JSON-Objekt mit folgender Struktur enthalten:
{ "port": 12345, "workspacePath": "/path/to/project1:/path/to/project2", "authToken": "a-very-secret-token", "ppid": 1234, "ideName": "VS Code" }port(number, required): Der Port des MCP-Servers.workspacePath(string, required): Eine Liste aller offenen Workspace-Root-Pfade, getrennt durch das betriebssystemspezifische Pfadtrennzeichen (:für Linux/macOS,;für Windows). Die CLI verwendet diesen Pfad, um sicherzustellen, dass sie im selben Projektordner ausgeführt wird, der in der IDE geöffnet ist. Wenn das aktuelle Arbeitsverzeichnis der CLI kein Unterverzeichnis vonworkspacePathist, wird die Verbindung abgelehnt. Dein Plugin MUSS den korrekten absoluten Pfad (oder die Pfade) zum Root des offenen Workspaces bereitstellen.authToken(string, required): Ein geheimer Token zur Absicherung der Verbindung. Die CLI fügt diesen Token bei allen Anfragen in einenAuthorization: Bearer <token>-Header ein.ppid(number, required): Die Parent-Process-ID des IDE-Prozesses.ideName(string, required): Ein benutzerfreundlicher Name für die IDE (z. B.VS Code,JetBrains IDE).
-
Authentifizierung: Um die Verbindung abzusichern, MUSS das Plugin einen einzigartigen, geheimen Token generieren und in die Discovery-Datei aufnehmen. Die CLI fügt diesen Token anschließend in den
Authorization-Header aller Anfragen an den MCP-Server ein (z. B.Authorization: Bearer a-very-secret-token). Dein Server MUSS diesen Token bei jeder Anfrage validieren und nicht autorisierte Anfragen ablehnen. -
Umgebungsvariablen (Required): Dein Plugin MUSS
QWEN_CODE_IDE_SERVER_PORTim integrierten Terminal setzen, damit die CLI die korrekte<PORT>.lock-Datei finden kann.
Legacy-Hinweis: Bei Extensions älter als v0.5.1 kann Qwen Code auf das Lesen von JSON-Dateien im System-Temp-Verzeichnis mit den Namen qwen-code-ide-server-<PID>.json oder qwen-code-ide-server-<PORT>.json zurückgreifen. Neue Integrationen sollten sich nicht auf diese Legacy-Dateien verlassen.
II. Die Kontextschnittstelle
Um Kontextbewusstsein zu ermöglichen, KANN das Plugin der CLI Echtzeitinformationen über die Aktivitäten des Nutzers in der IDE bereitstellen.
ide/contextUpdate Notification
Das Plugin KANN eine ide/contextUpdate Notification an die CLI senden, sobald sich der Kontext des Nutzers ändert.
-
Auslösende Ereignisse: Diese Notification sollte gesendet werden (empfohlenes Debouncing von 50 ms), wenn:
- eine Datei geöffnet, geschlossen oder fokussiert wird.
- sich die Cursorposition oder die Textauswahl des Nutzers in der aktiven Datei ändert.
-
Payload (
IdeContext): Die Parameter der Notification MÜSSEN einIdeContext-Objekt sein:interface IdeContext { workspaceState?: { openFiles?: File[]; isTrusted?: boolean; }; } interface File { // Absolute path to the file path: string; // Last focused Unix timestamp (for ordering) timestamp: number; // True if this is the currently focused file isActive?: boolean; cursor?: { // 1-based line number line: number; // 1-based character number character: number; }; // The text currently selected by the user selectedText?: string; }Hinweis: Die
openFiles-Liste sollte nur Dateien enthalten, die tatsächlich auf der Festplatte existieren. Virtuelle Dateien (z. B. ungespeicherte Dateien ohne Pfad, Editor-Einstellungsseiten) MÜSSEN ausgeschlossen werden.
Wie die CLI diesen Kontext verwendet
Nach dem Empfang des IdeContext-Objekts führt die CLI mehrere Normalisierungs- und Kürzungsschritte durch, bevor sie die Informationen an das Modell sendet.
- Dateisortierung: Die CLI verwendet das
timestamp-Feld, um die zuletzt verwendeten Dateien zu ermitteln. Sie sortiert dieopenFiles-Liste basierend auf diesem Wert. Daher MUSS dein Plugin einen genauen Unix-Timestamp für den Zeitpunkt des letzten Fokus einer Datei bereitstellen. - Aktive Datei: Die CLI betrachtet nur die neueste Datei (nach der Sortierung) als „aktive“ Datei. Sie ignoriert das
isActive-Flag bei allen anderen Dateien und leert derencursor- undselectedText-Felder. Dein Plugin sollte sich darauf konzentrieren,isActive: truezu setzen und Cursor-/Auswahldetails nur für die aktuell fokussierte Datei bereitzustellen. - Kürzung (Truncation): Um Token-Limits einzuhalten, kürzt die CLI sowohl die Dateiliste (auf 10 Dateien) als auch den
selectedText(auf 16 KB).
Obwohl die CLI die finale Kürzung übernimmt, wird dringend empfohlen, dass auch dein Plugin die Menge des gesendeten Kontexts begrenzt.
III. Die Diffing-Schnittstelle
Um interaktive Code-Änderungen zu ermöglichen, KANN das Plugin eine Diffing-Schnittstelle bereitstellen. Dies erlaubt der CLI, die IDE aufzufordern, eine Diff-Ansicht zu öffnen, die vorgeschlagene Änderungen an einer Datei anzeigt. Der Nutzer kann diese Änderungen dann direkt in der IDE prüfen, bearbeiten und schließlich akzeptieren oder ablehnen.
openDiff Tool
Das Plugin MUSS ein openDiff-Tool auf seinem MCP-Server registrieren.
-
Beschreibung: Dieses Tool weist die IDE an, eine bearbeitbare Diff-Ansicht für eine bestimmte Datei zu öffnen.
-
Request (
OpenDiffRequest): Das Tool wird über einentools/call-Request aufgerufen. Dasarguments-Feld innerhalb derparamsdes Requests MUSS einOpenDiffRequest-Objekt sein.interface OpenDiffRequest { // The absolute path to the file to be diffed. filePath: string; // The proposed new content for the file. newContent: string; } -
Response (
CallToolResult): Das Tool MUSS sofort einCallToolResultzurückgeben, um den Request zu bestätigen und zu melden, ob die Diff-Ansicht erfolgreich geöffnet wurde.- Bei Erfolg: Wenn die Diff-Ansicht erfolgreich geöffnet wurde, MUSS die Response einen leeren Inhalt enthalten (d. h.
content: []). - Bei Fehler: Wenn ein Fehler das Öffnen der Diff-Ansicht verhindert hat, MUSS die Response
isError: trueenthalten und einenTextContent-Block imcontent-Array beinhalten, der den Fehler beschreibt.
Das tatsächliche Ergebnis des Diffs (Akzeptanz oder Ablehnung) wird asynchron über Notifications kommuniziert.
- Bei Erfolg: Wenn die Diff-Ansicht erfolgreich geöffnet wurde, MUSS die Response einen leeren Inhalt enthalten (d. h.
closeDiff Tool
Das Plugin MUSS ein closeDiff-Tool auf seinem MCP-Server registrieren.
-
Beschreibung: Dieses Tool weist die IDE an, eine geöffnete Diff-Ansicht für eine bestimmte Datei zu schließen.
-
Request (
CloseDiffRequest): Das Tool wird über einentools/call-Request aufgerufen. Dasarguments-Feld innerhalb derparamsdes Requests MUSS einCloseDiffRequest-Objekt sein.interface CloseDiffRequest { // The absolute path to the file whose diff view should be closed. filePath: string; } -
Response (
CallToolResult): Das Tool MUSS einCallToolResultzurückgeben.- Bei Erfolg: Wenn die Diff-Ansicht erfolgreich geschlossen wurde, MUSS die Response einen einzelnen TextContent-Block im Content-Array enthalten, der den finalen Inhalt der Datei vor dem Schließen beinhaltet.
- Bei Fehler: Wenn ein Fehler das Schließen der Diff-Ansicht verhindert hat, MUSS die Response
isError: trueenthalten und einenTextContent-Block imcontent-Array beinhalten, der den Fehler beschreibt.
ide/diffAccepted Notification
Wenn der Nutzer die Änderungen in einer Diff-Ansicht akzeptiert (z. B. durch Klicken auf „Apply“ oder „Save“), MUSS das Plugin eine ide/diffAccepted-Notification an die CLI senden.
-
Payload: Die Parameter der Notification MÜSSEN den Dateipfad und den finalen Inhalt der Datei enthalten. Der Inhalt kann vom ursprünglichen
newContentabweichen, wenn der Nutzer manuelle Änderungen in der Diff-Ansicht vorgenommen hat.{ // The absolute path to the file that was diffed. filePath: string; // The full content of the file after acceptance. content: string; }
ide/diffRejected Notification
Wenn der Nutzer die Änderungen ablehnt (z. B. durch Schließen der Diff-Ansicht ohne Akzeptieren), MUSS das Plugin eine ide/diffRejected-Notification an die CLI senden.
-
Payload: Die Parameter der Notification MÜSSEN den Dateipfad des abgelehnten Diffs enthalten.
{ // The absolute path to the file that was diffed. filePath: string; }
IV. Die Lifecycle-Schnittstelle
Das Plugin MUSS seine Ressourcen und die Discovery-Datei korrekt basierend auf dem Lifecycle der IDE verwalten.
- Bei Aktivierung (IDE-Start/Plugin aktiviert):
- Starte den MCP-Server.
- Erstelle die Discovery-Datei.
- Bei Deaktivierung (IDE-Shutdown/Plugin deaktiviert):
- Stoppe den MCP-Server.
- Lösche die Discovery-Datei.