Skip to content

fix: Use MCP JSON-RPC protocol for tool calls and outbound delivery - #26

Closed
madtank wants to merge 5 commits into
mainfrom
fix/mcp-jsonrpc-outbound
Closed

madtank wants to merge 5 commits into
mainfrom
fix/mcp-jsonrpc-outbound

Conversation

@madtank

@madtank madtank commented Feb 8, 2026

Copy link
Copy Markdown
Member

Problem

The plugin was calling ${mcpEndpoint}/tools/${toolName} (REST endpoint) which does not exist on the MCP server. The MCP server only speaks JSON-RPC at ${mcpEndpoint}/mcp.

This caused:

  1. All plugin tools (ax_messages, ax_tasks, ax_context, ax_agents) to fail
  2. Outbound delivery (heartbeat/cron routing) to fail silently
  3. Agents could not post to the channel programmatically

Fix

callAxTool() now sends proper MCP JSON-RPC tools/call requests. Outbound sendText/sendMedia match the Clawdbot ChannelOutboundContext interface and return proper OutboundDeliveryResult.

Files Changed

  • extension/lib/api.ts — JSON-RPC protocol, SSE handling, result extraction
  • extension/channel/ax-channel.ts — outbound interface alignment, callAxTool usage

clawdbot_cipher added 3 commits February 6, 2026 17:29
Adds proper outbound.sendText() implementation that uses the aX MCP
messages tool to send messages. This enables:

- Heartbeat delivery to ax-platform channel
- Cron job delivery with 'Deliver' checkbox
- Any agent reply routing to aX spaces

Configuration:
- outbound.tokenFile: Path to OAuth token JSON file
- outbound.mcpEndpoint: MCP server URL (default: https://mcp.paxai.app)
- outbound.defaultSpaceId: Default target space for delivery

The implementation reads the access token from the configured file
(or AX_ACCESS_TOKEN env var) and POSTs to the MCP messages tool.

Resolves: empty-heartbeat-file and 'Outbound not configured' errors
for cron jobs targeting ax-platform channel.
Implements the aX Platform visibility dashboard following the SEP-1865
MCP Apps Extension specification.

Components:
- ui/types.ts: DashboardContext schema with identity, space, tools, tasks, activity
- ui/dashboard.ts: Flowbite/Tailwind HTML builder for the three-layer dashboard
- ui/resource-handler.ts: MCP resources/read handler for ui://ax-platform/dashboard
- tools/ax-dashboard.ts: Tool that returns the interactive dashboard

Dashboard layers:
1. Header: Agent identity + space anchoring + permission badges
2. Content: Task Kanban board (Backlog → In Progress → Done)
3. Footer: Activity Pulse timeline (user actions + heartbeat work)

The dashboard provides full visibility into:
- Who: Agent identity via whoami
- Where: Current space context
- What: Available/restricted tools
- History: Recent activity breadcrumbs

Co-authored-by: @quantum_phoenix_307
The plugin was calling ${mcpEndpoint}/tools/${toolName} (REST) which doesn't
exist on the MCP server. The server only speaks JSON-RPC at ${mcpEndpoint}/mcp.

Changes:
- api.ts: callAxTool now sends proper JSON-RPC tools/call requests
  - Handles both JSON and SSE response formats
  - Extracts text content from MCP result envelopes
  - Better error messages with response body context
- ax-channel.ts: outbound sendText/sendMedia match ChannelOutboundContext signature
  - sendText(ctx: { cfg, to, text, ... }) -> OutboundDeliveryResult
  - Added sendMedia for media delivery (text + link fallback)
  - Added resolveTarget for proper target resolution
  - Uses callAxTool instead of raw fetch to wrong endpoint

This fixes: tools registered by the plugin (ax_messages, ax_tasks, etc.)
returning errors, and outbound delivery (heartbeat/cron) failing silently.
@claude

This comment has been minimized.

1. XSS: Replace inline onclick handlers with data-* attributes + event
   delegation. Task IDs now escaped via escapeHtml().

2. Missing space_id: Both sendText and sendMedia now pass space_id to
   callAxTool so outbound messages route to the correct space.

3. Dead code: Remove unused outboundConfig in createDispatchHandler
   (only needed in createAxChannel where it's actually used).

4. postMessage origin: Use window.location.origin instead of '*' to
   prevent data leakage to untrusted parent frames.
@madtank

madtank commented Feb 8, 2026 •

Copy link
Copy Markdown
Member Author

All 4 findings addressed in 43cd83d:

  1. XSS (onclick): Replaced inline onclick handlers with data-action/data-task-id attributes + event delegation listener. Task IDs now escaped via escapeHtml().
  2. Missing space_id: Both sendText and sendMedia now pass space_id: to to callAxTool.
  3. Dead outboundConfig: Removed unused line from createDispatchHandler.
  4. postMessage origin: Changed from "*" to window.location.origin.

Ready for re-review. @claude

@madtank

madtank commented Feb 8, 2026

Copy link
Copy Markdown
Member Author

All 4 findings addressed in 43cd83d:

  1. XSS (onclick): Replaced inline onclick handlers with data-action/data-task-id attributes + event delegation listener. Task IDs now escaped via escapeHtml().
  2. Missing space_id: Both sendText and sendMedia now pass space_id: to to callAxTool.
  3. Dead outboundConfig: Removed unused line from createDispatchHandler.
  4. postMessage origin: Changed from "*" to window.location.origin.

Ready for re-review. @claude

@claude review pr.

@claude

This comment has been minimized.

Must-fix:
1. Tool context access — use Record<string, unknown> and check both
   sessionKey and SessionKey for cross-compatibility
2. Dashboard marked as [Preview] with demo data disclaimer
5. Input validation in callAxTool (mcpEndpoint, authToken, toolName)

Should-fix:
3. Removed dead div from escapeHtml
4. Extracted resolveOutboundAuthToken() — eliminates 25 lines of
   duplication between sendText and sendMedia
2b. Added debug logging for SSE parse errors

Nice-to-have:
9. Enhanced JSDoc for extractToolResult with full format docs
7. Consistent context access across all 5 tool files
@madtank

madtank commented Feb 8, 2026

Copy link
Copy Markdown
Member Author

All 9 review findings addressed in f31c87c (9 files changed):

Must-fix:

  1. ✅ Tool context — Record<string, unknown>, checks both sessionKey and SessionKey
  2. ✅ Dashboard marked [Preview] with demo data disclaimer
  3. ✅ Input validation in callAxTool — validates all 3 required params

Should-fix:
3. ✅ Removed dead div from escapeHtml
4. ✅ Extracted resolveOutboundAuthToken() — eliminates 25 lines of duplication
2b. ✅ Debug logging for SSE parse errors

Nice-to-have:
7. ✅ Consistent context access across all 5 tool files
9. ✅ Enhanced JSDoc for extractToolResult

Only thing NOT changed: Issue 8 (type assertions with as any) — these are necessary due to incomplete SDK types and would require upstream changes to fix properly.

Ready for final review.

@madtank madtank closed this Feb 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant