feat: add interactive NX GUI bridge as a C# add-in - #7
Open
mikbalarikan wants to merge 2 commits into
Open
mikbalarikan wants to merge 2 commits into
mikbalarikan wants to merge 2 commits into
Conversation
MSIX-packaged MCP clients, such as Store-installed desktop apps, and every process they start see a private copy of %LOCALAPPDATA%. A sidecar they launch therefore never finds the bridge.json written by an NX started from Explorer. NX_MCP_STATE_DIR selects a shared directory outside AppData; the default location is unchanged. Tests pin the variable so a developer's environment cannot redirect them to a live bridge. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The bundled Python runner pumps requests in a blocking journal, so the NX UI freezes. A Python UI-thread scheduler is not possible on NX2206: NX runs Python startup scripts in a sub-interpreter whose UI thread holds the GIL, and a ctypes Win32 timer callback deadlocked that thread. Following the fallback in docs/architecture.md, nx_gui_bridge/ adds an NX Open .NET add-in that serves bridge protocol v1 unchanged. A background thread owns the loopback socket; each call runs on the NX UI thread through a hidden WinForms control, only while UF_UI_lock_ug_access succeeds. It ports the 16 certified commands, reads gui-bridge.json beside the DLL and honors state_dir / NX_MCP_STATE_DIR. build.ps1 uses the in-box csc.exe. Validated on NX2206 only (see docs/gui-bridge.md): 20-iteration acceptance plus negative cases, 21 protocol parity checks against the Python server, no hung-window probes during the run, and a live session in an NX started from Explorer with an MSIX-packaged MCP client. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Warning Review limit reachedNext included review available in 59 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (8)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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
docs/architecture.mdnames a fallback for NX builds that cannot provide a non-blocking GUI scheduler: a minimal C# NX-side bridge. This PR implements it.nx_gui_bridge/adds an NX Open .NET add-in that serves bridge protocol v1 from an interactive NX session. NX stays usable, and the model updates on screen while MCP tools run.These stay unchanged:
The only Python change is the optional
NX_MCP_STATE_DIRvariable. Most of the diff is one C# file of 2,348 lines.Why
Changes
1.
feat: allow NX_MCP_STATE_DIR to relocate the bridge descriptor(src/nx_mcp/bridge.pyand tests)NX_MCP_STATE_DIRis set,default_descriptor_path()returns$NX_MCP_STATE_DIR/bridge.json. The default location is unchanged.%LOCALAPPDATA%. Its sidecar therefore never finds thebridge.jsonwritten by an NX started from Explorer. On the test machine, the Claude desktop app was such a client.2.
feat: add interactive NX GUI bridge as a C# add-in(nx_gui_bridge/and docs)A background .NET thread owns the loopback listener with the same limits as
nx_mcp.bridge:127.0.0.1on a random port;Requests are handled one at a time.
Each call runs on NX's UI thread through a hidden WinForms control. It starts only after
UF_UI_lock_ug_access(UF_UI_FROM_CUSTOM)returnsUF_UI_LOCK_SET.NX_MAIN_THREAD_UNAVAILABLE(not_started, retryable).The executor is a C# port of
NXOpenExecutorfor the 16 certified commands. It keeps:Legacy and experimental commands are not available.
Configuration comes from
gui-bridge.jsonnext to the DLL. If that file is missing, the bridge reads%LOCALAPPDATA%\nx-mcp\gui-bridge.json, and environment variables override both.workspaceis required.state_dirandstop_fileare optional.Two ways to load it:
startupfolder of a custom directory.The bridge logs each method, its outcome and its duration. The token is never logged.
build.ps1compiles with the in-box .NET Frameworkcsc.exe(C# 5), so no SDK is needed. NX loads an unsigned add-in only with adotnet_authorlicense; otherwise, sign the DLL withSignDotNet.exe.Docs:
docs/gui-bridge.mdcovers the build, configuration, limits and the validation record.docs/architecture.mdpoints to the add-in.Validation
Local checks (Windows 11, Python 3.12.13):
pytest -q -p no:cacheprovider -m "not real_nx": 299 passed, 14 skipped. Branch coverage is 82.95%.ruff check,ruff format --checkandmypy src/nx_mcpare clean.Real NX was NX2206 build 2206.9101 only, on 2026-09-18. The add-in was built with the in-box .NET Framework 4.8
csc.exe, without an SDK. The runs used a branch that combined this PR and #6. Its tree is identical to the result of merging both PRs.startupfolderStartup()on the UI thread.python -m nx_mcp.real_smoke --iterations 1pytest -m real_nx tests/test_real_nx.py(20 iterations plus negative cases)execution_statematched the Python server.NX_BRIDGE_UNAVAILABLE(not_started).state_dirUI responsiveness was probed every 250 ms during the whole acceptance run: 1,491 probes over 570 s.
Not yet exercised
Notes for reviewers
.github/workflows/real-nx.ymlstill polls%LOCALAPPDATA%\nx-mcp\bridge.json. This only matters if a runner setsNX_MCP_STATE_DIR.🤖 Generated with Claude Code