Repository navigation
Conversation
StartMCPSocketServer[server, opts] serves an MCPServerObject over MCP's Streamable HTTP transport inside the current kernel (SocketListen on 127.0.0.1), including a front end's kernel, and returns an MCPSocketServerObject at once; DeleteObject stops it. Chatbook's ACP window uses it to give a coding agent tools that run in the user's kernel. - HTTP (Kernel/Server/HTTP.wl, Socket.wl): one JSON-RPC message per POST, answered as JSON or as an event stream with keep-alive comments; 202 for notifications, 405 for GET and DELETE; stateless (no Mcp-Session-Id); Host and Origin checks against DNS rebinding; bearer-token or function authentication; framing limits, and a timeout for stalled requests that doesn't count kernel stalls. - "EvaluationFunction": the handler (a preemptive evaluation) can hand tools/call and prompts/get to the caller as run and info, and run[] evaluates the call later (e.g. on the main link) and writes its answer. Every call is answered once, also on aborts, cancels and internal failures. - Options "Port", "Path", "Authentication", "EvaluationFunction", "KeepAliveInterval" and "ToolOptions"; properties such as "URL", "Port", "Token", "JSONConfiguration" and "PendingRequests". - Internal failures redact secrets: the values of secret keys, Authorization headers, Bearer tokens, and secrets registered with withFailureSecrets (the servers' tokens and each request's token) never reach messages, bug reports or log files, and the stack is not searched. The InternalFailures directory is private (0700). - handleMethod["initialize"] no longer switches messages off in the whole kernel: the stdio transport does it (applyStderrPolicy). The cloud transport shares the HTTP helpers and the JSON-RPC message classification with the socket transport (a message that is none of request, notification or response gets 400), and Blocks $clientName per request. Tests: SocketServer.wlt (new), InternalFailureFormatting.wlt, StartMCPServer.wlt, CloudDeployment.wlt. Docs: docs/socket-server.md, Specs/SocketServer.md, docs/error-handling.md. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KkQjGzBbQb5J2q858mMvvy
- initialize no longer advertises the MCP Apps UI extension: the socket transport Blocks mcpAppsEnabledQ, as every other request has UI off - "Authentication" values that cannot be functions (False, True, numbers, lists) give InvalidSocketServerAuthentication instead of starting a server that refuses every request - Requests held behind a deferred call are read chunk by chunk, so many pipelined requests no longer take quadratic time inside PreemptProtect - A maintenance task that cannot be submitted fails the start, which stops the server again - Persistent responses send Connection: keep-alive, which HTTP/1.0 clients need to keep the connection - One jobErrorResponse replaces the three copies of the tools/call vs JSON-RPC error branching; internalErrorResponse moves to Shared.wl and is used by the stdio, cloud and socket transports - Drop dispatchCloudMethod's unused id parameter, and build parseRequestBody on requestBodyJSON Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
StartMCPSocketServer[server, opts]. It serves anMCPServerObjectover MCP's Streamable HTTP transport (the stateless subset, revision 2025-11-25) from inside the current kernel, including a front end's kernel. It listens on127.0.0.1withSocketListenand returns anMCPSocketServerObjectat once;DeleteObjectstops the server. Chatbook's ACP window uses it to give a coding agent (OpenCode) tools that run in the user's kernel.The user-facing description is in
docs/socket-server.md, and the design decisions are inSpecs/SocketServer.md.The socket transport (
Kernel/Server/Socket.wl)Mcp-Session-Id.SocketListendelivers raw chunks of at most 8 KB.SocketListenhandler is a preemptive evaluation, so it only frames requests and answers the cheap methods (initialize,ping,tools/list, ...).tools/callandprompts/getare handed to the"EvaluationFunction"asf[run, info]. The caller decides whererun[]evaluates the call (for example on the main link), andrun[]writes the answer. Every call is answered exactly once, also on aborts, cancellations (notifications/cancelled), rejections, disconnects and internal failures.None, or the caller's authentication function. Tokens are compared in constant time.HostandOriginchecks against DNS rebinding."Port","Path","Authentication","EvaluationFunction","KeepAliveInterval","ToolOptions"."URL","Port","Path","Token","JSONConfiguration","Running","PendingRequests", and more.run[]Blocks all server session globals and$Messages, so nothing a client sends changes the kernel's state.WolframLanguageEvaluatordefaults to the"Local"method, so agent code doesn't run in the user's session.Wolfram`AgentToolsState`SocketServer`, so servers survive a paclet reload.Changes to shared code
Kernel/Server/HTTP.wl(new): the request accessors,Acceptnegotiation, the protocol-version check, JSON/SSE response strings and a new JSON-RPC message classification (jsonRPCMessageType) moved out ofCloud.wl, so the cloud and socket transports share them.Cloud transport behavior changes:
idmakes a request; a request without one is accepted but never evaluated.$clientNameisBlocked per request.handleMethod["initialize"]no longer sets$Messages = {}, which used to silence the whole kernel for the HTTP transports. The stdio read loop now applies that policy itself (applyStderrPolicyinLocal.wl), before it handles the message, as before.catchTopIsolated(Common.wl): acatchTopthat always starts its own error scope. Preemptive evaluations see theBlocks of the evaluation they interrupt, including anothercatchTop.redactSecretsandwithFailureSecrets(Common.wl): internal-failure data, messages, bug reports and log files no longer show secrets. That covers:Authorization:header lines andBearertokensThe evaluation stack is not searched. The
InternalFailureslog directory is made private (0700) on Unix-like systems. Seedocs/error-handling.md.Small fix:
cleanupOldFailureLogsusedQuiet @ DeleteFile /@ files, which parses as(Quiet @ DeleteFile) /@ filesand so never quieted anything.Review fixes (second commit)
A review of the first commit found these; they are fixed and tested:
initializeadvertised the MCP Apps UI extension to UI-capable clients, though the socket transport has UI off for every other request."Authentication"values that can't be functions (False,True, numbers, lists) started a server that refused every request. They now giveInvalidSocketServerAuthentication.PreemptProtect. They are now read chunk by chunk.Connection: keep-alive, which HTTP/1.0 clients need.jobErrorResponseinstead of three copies of the same branchinginternalErrorResponse(inShared.wl) for the stdio, cloud and socket transportsidparameter indispatchCloudMethodparseRequestBodybuilt onrequestBodyJSONFor reviewers
These were raised in the review and deliberately left as they are:
"EvaluationFunction"(#1[ ] &) runs tools inside the handler. While a tool runs there are no aborts, no keep-alives and no other requests, and in a front end kernel a tool that calls the front end does so from a preemptive evaluation. Chatbook passes its own function. This is documented as a known limitation.docs/socket-server.md.Authorization:line in unrelated failure data is redacted too.catchSocketinstead ofcatchMine: the socket entry points, including the exportedStartMCPSocketServer, usecatchSocket(catchTopIsolated). That breaks the AGENTS.md "usecatchMine" rule on purpose, becausecatchMinewould share failure state with an evaluation the handler interrupted.Testing
Tests/SocketServer.wlt(119, with real loopback clients),Tests/CloudDeployment.wlt(179),Tests/InternalFailureFormatting.wlt(45),Tests/StartMCPServer.wlt(94). The rest of the suite was not run.Kernel/Server/,Kernel/Common.wlor the new tests.initializefrom a UI-capable clienttools/callwith the default evaluation functioninitialize,tools/list,ping, and an unknown method.🤖 Generated with Claude Code