diag(mcp): Client-Capabilities beim Binden festhalten

Der Push-Test mit den echten CLIs war NEGATIV: codex meldete "durch
agenthub_work erfahren", kimi ausdruecklich "kein MCP-Push". Der Kanal
funktioniert (mit eigenem Testclient verifiziert), die Hosts reichen ihn
aber offenbar nicht ans Modell durch.

Naheliegender Verdacht, statt zu spekulieren gemessen: `sendLoggingMessage`
nuetzt nichts, wenn der CLIENT `logging` nicht deklariert — dann verwirft
seine SDK-Seite die Notification, bevor das Modell sie je sieht. Mein
Testclient deklarierte sie ausdruecklich und empfing deshalb.

Die Bridge schreibt die deklarierten Client-Capabilities jetzt nach
~/.cache/agenthub/client-capabilities-<agent>.json.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
chahinebrini 2026-07-29 21:21:28 +02:00
parent dbaf29a6c6
commit 55606eddc8

View File

@ -1,4 +1,7 @@
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { writeFileSync, mkdirSync } from 'node:fs';
import { join } from 'node:path';
import { homedir } from 'node:os';
import { parseSSEBuffer } from '../cli/commands/watch.js'; import { parseSSEBuffer } from '../cli/commands/watch.js';
import { remoteClient } from '../cli/remoteClient.js'; import { remoteClient } from '../cli/remoteClient.js';
@ -79,6 +82,21 @@ export function bindPushChannel(server: McpServer, serverUrl: string, agent: str
const state: PushState = { agent: name, names: new Set([name]), stop: () => { stopped = true; } }; const state: PushState = { agent: name, names: new Set([name]), stop: () => { stopped = true; } };
active = state; active = state;
// DIAGNOSE: Was deklariert der CLI-Host ueberhaupt? `sendLoggingMessage`
// nuetzt nichts, wenn der Client `logging` nicht deklariert — dann verwirft
// seine SDK-Seite die Notification, bevor das Modell sie je sieht. Genau das
// ist der Verdacht, nachdem codex und kimi den Push nicht wahrgenommen haben.
// Wir schreiben es weg, statt zu spekulieren.
try {
const caps = server.server.getClientCapabilities();
const dir = join(homedir(), '.cache', 'agenthub');
mkdirSync(dir, { recursive: true });
writeFileSync(
join(dir, `client-capabilities-${name}.json`),
JSON.stringify({ agent: name, at: new Date().toISOString(), capabilities: caps ?? null }, null, 2),
);
} catch { /* Diagnose darf den Kanal nie blockieren */ }
void (async () => { void (async () => {
// Aliase mitnehmen, damit ein umbenannter Agent seine Events weiter bekommt. // Aliase mitnehmen, damit ein umbenannter Agent seine Events weiter bekommt.
try { try {