Repository navigation
Agent mcp server - #1519
Draft
Gin890 wants to merge 20 commits into
Draft
Agent mcp server#1519Gin890 wants to merge 20 commits into
Gin890 wants to merge 20 commits into
Conversation
Mysticial
marked this pull request as draft
September 26, 2026 23:07
Collaborator
|
No chance this is going in as-is. Way too big. Way too much slop. We'll need to break this into many smaller PRs to incrementally build it and understand every step of it. Like why is there Python here? But we can keep this PR for reference or if anyone wants to try it. |
Gin890
force-pushed
the
agent-mcp-server
branch
from
October 6, 2026 06:03
3dd248d to
b61d840
Compare
The controller logged through global_logger_command_line(), which also prints every line to stdout. Python callers, and MCP servers that use stdio for their protocol, need stdout to stay clean. Log to global_logger_raw() instead; lines still reach every listener of the global logger, e.g. SerialProgramsCommandLine's log file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ntroller is ready Commands used to log "Controller is not ready." and silently do nothing, so a caller couldn't tell that its input was dropped. Throw InvalidConnectionStateException with the connection status instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
current_status() returned ControllerConnection::status_text(), which is formatted for the GUI: each line wrapped in <font color=...> tags, lines joined with <br>. Add ControllerConnection::raw_status_text(), which keeps the text of each status line as it was set (without colors) and joins the lines with a newline, and use it in current_status(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- controller_name(): the active controller implementation, e.g. "Nintendo Switch: Pro Controller". - cancel_all(): drop queued commands and release all inputs. Safe to call from another thread while one is blocked in wait_for_all_requests(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cancel_all_commands() only starts the cancellation: it returns as soon as the cancel request is handed to the connection, and the host marks its command queue empty at that moment, so waiting for the queue proves nothing. release_all_and_confirm() cancels, queues a 10 ms neutral no-op, and waits (bounded by a timeout) for the device to report that the no-op finished. Commands are delivered in order, so that report means the device has processed the cancel and is holding the neutral state. Uses only the AbstractController interface, so it works for any controller. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cancel_all() plus a bounded wait for the device to confirm the neutral state, using release_all_and_confirm(). Returns false on timeout, e.g. when the Switch is asleep and the device can't execute commands. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Start the pokemon_automation Python package (SerialPrograms/Source/PythonBindings/).
- _core.py: finds and imports the compiled _pa_core module (added next) lazily,
so the pure-Python parts work without it.
- buttons.py: the input vocabulary scripts and AI agents use: button names and
aliases ("A", "L+R", "start", "L3"), d-pad directions ("up", "up-right"), and
joystick positions (direction names or [x, y], +y = up). Bit values match
NintendoSwitch::Button and DpadPosition.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
_pa_core wraps PybindSwitchProController for Python. It links only CoreLib (no Qt, OpenCV or Tesseract), so it also builds with -DPA_CORE_ONLY=ON. - CMake option PA_PYTHON_BINDINGS (OFF by default, since it needs a Python interpreter with development headers), in both the full and the core-only build. pybind11 is taken from the environment or downloaded. - The built module is copied into the pokemon_automation package folder. - A log sink that never writes to stdout (stdout carries the protocol for MCP over stdio), with recent lines available to Python. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- SwitchController: press buttons/d-pad, tilt sticks, hold combinations, run sequences of InputSteps, flush, stop and release_all. - InputStep: one step of a sequence (buttons, sticks, hold, release, repeat, wait). The same step dicts are used by the MCP run_inputs tool. - FakeController: records commands, for tests without hardware. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pure Python, outside the C++ codebase: - video.py: continuous capture with opencv-python (only the latest frame is kept, so a frame taken after an input shows its effect), JPEG/PNG encoding, cropping with ImageFloatBox-style boxes, OCR with pytesseract (optional). - devices.py: list serial ports and video devices (device names on macOS via pyobjc AVFoundation, in OpenCV's index order). - FakeVideoCapture for tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Console: a controller plus a video source. act() sends inputs, waits until the device has executed them, waits for the game to react, then returns a frame captured after all of that. - selftest.py: `python -m pokemon_automation.selftest --serial ... --video ...` checks real hardware with harmless inputs and saves screenshots. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The MCP interface for AI agents that control the Switch, as data, so the Python MCP server and the upcoming SerialPrograms app server expose exactly the same tools: names, descriptions, JSON Schemas of the arguments, which host implements each tool, and the instructions sent to agents. AgentInputTestCases.json lists inputs (buttons, sticks, steps) and their expected parse results or errors; both the Python and C++ parsers are tested against it. Also: agent_tools.py loads the file (inlining $refs), tests that the Python input vocabulary passes the shared cases, and the build copies both files into the Python package. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pokemon_automation.mcp_server serves a Console to AI agents over MCP (stdio or streamable HTTP). Tools, descriptions and schemas come from AgentTools.json; tests check that the Python functions accept exactly the shared arguments. Input tools return a screenshot taken after the game reacts; release_all works while another call is running; per-call input limits; read-only mode; --fake runs without hardware. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
How to build _pa_core, install the package, run the self-test, use the Python API and the MCP server, and run the tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The app needs a local HTTP endpoint for AI agents (MCP's Streamable HTTP transport). Qt's QHttpServer module is GPL-3.0-only, which this project doesn't take, so this is a small HTTP/1.1 server on QTcpServer (Qt Network, LGPL): Content-Length bodies, keep-alive and "Expect: 100-continue"; no chunked requests or pipelining. The listener and sockets live on their own thread with its own event loop; each request is handled on a worker thread, so a slow request doesn't block others. stop() closes connections and waits for running handlers. Qt Network is now listed explicitly. The app already used it (FileDownloader, DiscordWebhook) but only got it through other Qt modules. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- AgentTools.json is compiled into SerialProgramsLib with a new CMake helper, pa_embed_text_file() (cmake/EmbedTextFile.cmake), as a byte array, so it isn't limited by compilers' string-literal size limits. - AgentToolDefinitions parses it, keeps the tools for host "app", inlines $refs (same as the Python loader), and validates tool arguments against the schemas with a small validator for the keywords the file uses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Parse the input vocabulary of AgentTools.json (button names, d-pad, sticks, input steps) into NintendoSwitch::Button, DpadPosition and JoystickPosition. The C++ twin of pokemon_automation/buttons.py; both pass the shared AgentInputTestCases.json. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MCP over Streamable HTTP at POST /mcp: JSON-RPC 2.0 with the initialize handshake (protocol versions 2024-11-05 to 2025-11-25; newer clients' probe gets "method not found" and falls back to it), ping, tools/list and tools/call, sessions, and plain JSON responses. Security: an optional bearer token, and DNS-rebinding protection (Origin and Host checks). The tools themselves are implemented by an McpToolHandler. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- ConsoleSystemSession::Listener gets on_controller_input(), called after the user's keyboard input was sent to the console's controllers (not for input suppressed because the console isn't focused or its controllers are locked). It runs outside the session lock; the forwarding code itself is unchanged. - ConsoleHandle::system_session() gives programs access to their session, so they can register such a listener. Used by the AI Agent Server program to notice when the user takes over. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A program in the ML tab (developer mode only) that hosts the MCP server, so AI agents (Claude Code, Codex, ...) can control the Switch through SerialPrograms while the user watches. Agent inputs run on the program's controller context; screenshots come from its video feed; read_text uses the app's Tesseract OCR. Pressing a key hands control to the user: running agent inputs are interrupted and new ones refused until the user clicks "Return control to agent" (or after an optional idle time). Stop shuts the server down and releases the controller. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gin890
force-pushed
the
agent-mcp-server
branch
from
October 7, 2026 05:14
b61d840 to
b940dba
Compare
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.
Used Claude to create a Python interface to connect to the mincrocontroller and control Switch. It also created an MCP server for AI agent use as part of the Python codebase.
It also adds a new automation program in the C++ app to act as a MCP server so users can monitor and intervene agent control of Switch.
From now on, if you want to automate sth unimplemented, just pay Anthropic/OpenAI to let agent play it for you 😜