diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a4a3905a51..a7721797709 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ Docs: https://docs.openclaw.ai - Control UI: point the Appearance tweakcn browse action and docs at the live tweakcn editor route instead of the removed `/themes` page. Fixes #77048. - Control UI: render Dream Diary prose through the sanitized markdown pipeline, so diary bold/italic/header markdown no longer appears as literal source text. Fixes #62413. - Control UI: render tool results whose output arrives as text-block arrays and give expanded tool output a scrollable block, so read/exec output remains visible in WebChat. Fixes #77054. +- MCP: include serialized conversation/message payloads in the primary text content for `conversations_list` and `messages_read`, while preserving `structuredContent` for capable clients. Fixes #77024. - Diagnostics: keep webhook/message OTEL attributes and Prometheus delivery labels low-cardinality and omit raw chat/message IDs from spans, so progress-draft and message-tool modes do not leak high-cardinality messaging identifiers. - Google Meet: stop advertising legacy `mode: "realtime"` to agents and config UIs, while keeping it as a hidden compatibility alias for `mode: "agent"`, so new joins use the STT -> OpenClaw agent -> TTS path instead of selecting the direct realtime voice fallback. - Google Meet: add `chrome.audioBufferBytes` for generated command-pair SoX audio commands and lower the default buffer from SoX's 8192 bytes to 4096 bytes to reduce Chrome talk-back latency. diff --git a/src/mcp/channel-server.test.ts b/src/mcp/channel-server.test.ts index 70c604ecaf8..f3a34aa4a3b 100644 --- a/src/mcp/channel-server.test.ts +++ b/src/mcp/channel-server.test.ts @@ -176,6 +176,55 @@ describe("openclaw channel mcp server", () => { ); }); + test("serializes conversation and message payloads into MCP primary content", async () => { + const mcp = await connectMcpWithoutGateway({ claudeChannelMode: "off" }); + try { + const gatewayRequest = vi.fn(async (method: string) => { + if (method === "sessions.list") { + return { + sessions: [ + { + key: "agent:main:telegram:direct:123", + channel: "telegram", + deliveryContext: { to: "123" }, + lastMessagePreview: "hello", + }, + ], + }; + } + if (method === "sessions.get") { + return { + messages: [ + { + id: "msg-1", + role: "assistant", + content: [{ type: "text", text: "full transcript text" }], + }, + ], + }; + } + throw new Error(`unexpected gateway method ${method}`); + }); + attachReadyGateway(mcp.bridge, gatewayRequest); + + const conversations = (await mcp.client.callTool({ + name: "conversations_list", + arguments: {}, + })) as { content?: Array<{ type: string; text?: string }> }; + expect(conversations.content?.[0]?.text).toContain('"sessionKey"'); + expect(conversations.content?.[0]?.text).toContain('"lastMessagePreview": "hello"'); + + const messages = (await mcp.client.callTool({ + name: "messages_read", + arguments: { session_key: "agent:main:telegram:direct:123" }, + })) as { content?: Array<{ type: string; text?: string }> }; + expect(messages.content?.[0]?.text).toContain('"id": "msg-1"'); + expect(messages.content?.[0]?.text).toContain("full transcript text"); + } finally { + await mcp.close(); + } + }); + test("emits Claude channel and permission notifications", async () => { const sessionKey = "agent:main:main"; let mcp: Awaited> | null = null; diff --git a/src/mcp/channel-shared.ts b/src/mcp/channel-shared.ts index 8a81ae78380..ff81b0cba8e 100644 --- a/src/mcp/channel-shared.ts +++ b/src/mcp/channel-shared.ts @@ -149,6 +149,16 @@ export function summarizeResult( }; } +export function summarizeStructuredResult( + label: string, + count: number, + payload: unknown, +): { content: Array<{ type: "text"; text: string }> } { + return { + content: [{ type: "text", text: `${label}: ${count}\n\n${JSON.stringify(payload, null, 2)}` }], + }; +} + function resolveConversationChannel(row: SessionRow): string | undefined { return normalizeMessageChannel( toText(row.deliveryContext?.channel) ?? diff --git a/src/mcp/channel-tools.ts b/src/mcp/channel-tools.ts index b19244fee83..21cf720ec94 100644 --- a/src/mcp/channel-tools.ts +++ b/src/mcp/channel-tools.ts @@ -5,6 +5,7 @@ import { extractAttachmentsFromMessage, resolveMessageId, summarizeResult, + summarizeStructuredResult, toText, } from "./channel-shared.js"; @@ -34,7 +35,7 @@ export function registerChannelMcpTools(server: McpServer, bridge: OpenClawChann async (args) => { const conversations = await bridge.listConversations(args); return { - ...summarizeResult("conversations", conversations.length), + ...summarizeStructuredResult("conversations", conversations.length, { conversations }), structuredContent: { conversations }, }; }, @@ -69,7 +70,7 @@ export function registerChannelMcpTools(server: McpServer, bridge: OpenClawChann async ({ session_key, limit }) => { const messages = await bridge.readMessages(session_key, limit ?? 20); return { - ...summarizeResult("messages", messages.length), + ...summarizeStructuredResult("messages", messages.length, { messages }), structuredContent: { messages }, }; },