wxMaxima
Loading...
Searching...
No Matches
Data Structures | Public Member Functions
McpServer Class Reference

A minimal, opt-in MCP (Model Context Protocol) server exposing the current worksheet as read-only context an external AI tool can query (GH request: "a de facto standard [for] an AI sidebar that ... gives it access to a worksheet"). More...

#include <McpServer.h>

Inheritance diagram for McpServer:
[legend]
Collaboration diagram for McpServer:
[legend]

Public Member Functions

 McpServer (Worksheet *worksheet, Variablespane *variablesPane)
 
void ReconcileWithConfig (const Configuration &config)
 Starts/stops listening to match the current configuration. Call this once after construction and again whenever the option or port could have changed (the Options dialog closing).
 

Detailed Description

A minimal, opt-in MCP (Model Context Protocol) server exposing the current worksheet as read-only context an external AI tool can query (GH request: "a de facto standard [for] an AI sidebar that ... gives it access to a worksheet").

Off by default – see Configuration::McpServerEnabled().

Transport: MCP's "Streamable HTTP", the subset of it a purely request/response (no server-initiated push) server needs – a single HTTP endpoint that accepts a POST'd JSON-RPC 2.0 request and answers with one JSON-RPC response, closing the connection afterwards (no keep-alive, no chunked transfer, no SSE stream: a GET on the endpoint gets a plain 405, which the spec allows for a server with nothing to push). No Mcp-Session-Id bookkeeping either – the spec marks that optional for the server to assign, and every tool call here is independently answerable from the live worksheet state with no cross-call session to track.

Implemented directly on wxSocketServer/wxSocketBase (the same primitive Maxima.cpp already uses for the Maxima<->wxMaxima protocol, just event-driven here instead of on a worker thread) rather than pulling in an HTTP library: the request shape this needs to parse is deliberately tiny (one method, one path, a couple of headers, a Content-Length-delimited body), and every request is handled synchronously by McpTools before the response is written, so there is no benefit to a general-purpose HTTP server for a case this narrow.

Runs entirely on the GUI thread's own event loop (the wxSocketServer/ wxSocketBase objects are event-driven, Notify()-based, not blocking calls on a worker thread) so it can call directly into Worksheet/GroupCell/ Variablespane – none of which are thread-safe – with no marshaling. Keep it that way: never make this transport threaded without adding the CallAfter()-based marshaling every cross-thread touch of a worksheet cell needs elsewhere in this codebase (see AGENTS.md's CellPtr / "Asynchronous Sidebars & Safety" notes).

Safety: binds to 127.0.0.1 only (refuses to listen on any other address), double-checks each accepted connection's peer address is loopback too, and validates the Origin header (when a client sends one – browsers always do, most non-browser MCP clients don't) against localhost/127.0.0.1 to block the DNS-rebinding attack the MCP spec calls out: a malicious web page resolving an attacker-controlled hostname to 127.0.0.1 so a victim's browser fetch reaches this server as if it were same-origin. None of this can ever let a request write to the worksheet – see McpTools.h for the exact, deliberately narrow read (plus watch/unwatch) surface this offers.


The documentation for this class was generated from the following files: