Compare commits

..

2 Commits

Author SHA1 Message Date
e60b19acaf switch to use system gammaray, and CPack DEB packaging 2026-07-09 20:04:43 +08:00
a3380dbab5 update license description 2026-07-08 14:28:43 +08:00
6 changed files with 73 additions and 33 deletions

2
.gitignore vendored
View File

@@ -2,6 +2,8 @@
build/ build/
bridge/build/ bridge/build/
install-prefix/ install-prefix/
_CPack_Packages/
*.deb
# Compiled test binaries (not committed) # Compiled test binaries (not committed)
tests/testapp/widget_test_app tests/testapp/widget_test_app

View File

@@ -458,12 +458,12 @@ For headless/CI launching of the probe, `systemd-run --user --no-block` (with `S
Bridge accepts an optional default probe URL via `--connect <url>` (or `GAMMARAY_PROBE_URL` env). At runtime the connection is driven by `connectProbe`/`disconnectProbe` MCP tools; the URL is remembered so tools can auto-reconnect after a probe restart. The bridge's `GammaRaySession` state machine (`Disconnected → Connecting → Ready`, with `→ Failed` on persistent error) is the single source of truth; `probeStatus()` reports it to the client. Bridge accepts an optional default probe URL via `--connect <url>` (or `GAMMARAY_PROBE_URL` env). At runtime the connection is driven by `connectProbe`/`disconnectProbe` MCP tools; the URL is remembered so tools can auto-reconnect after a probe restart. The bridge's `GammaRaySession` state machine (`Disconnected → Connecting → Ready`, with `→ Failed` on persistent error) is the single source of truth; `probeStatus()` reports it to the client.
The bridge acts as an MCP server on stdio. The LLM host (e.g. Claude Desktop, opencode) launches the bridge as a subprocess and communicates via JSON-RPC over stdio. The bridge acts as an MCP server on stdio. The LLM host (e.g. ZCode, opencode) launches the bridge as a subprocess and communicates via JSON-RPC over stdio.
## Key gotchas to remember ## Key gotchas to remember
1. **Protocol version lock**: probe and client must be same GammaRay build. System package too old → build from 3.4.0 source. (`common/protocol.h:141`) 1. **Protocol version lock**: probe and client must be same GammaRay build. System package too old → build from 3.4.0 source. (`common/protocol.h:141`)
2. **GPL-2.0-or-later**: bridge linking gammaray_client must be GPL-compatible. Accepted. qtmcp offers GPL-2.0-only option — compatible. 2. **GPL-2.0-or-later**: bridge linking gammaray_client must be GPL-compatible. Accepted. qtmcp offers LGPL-3.0-only / GPL-2.0-only / GPL-3.0-only — we comply under GPL-2.0-only.
3. **Qt private headers**: GammaRay build needs `qt6-base-private-dev`, `qt6-declarative-private-dev`. The bridge itself only needs public Qt + installed GammaRay headers. **qtmcp requires Qt 6.8+** (newer than GammaRay's 6.5+ floor); ensure build environment Qt >= 6.8. 3. **Qt private headers**: GammaRay build needs `qt6-base-private-dev`, `qt6-declarative-private-dev`. The bridge itself only needs public Qt + installed GammaRay headers. **qtmcp requires Qt 6.8+** (newer than GammaRay's 6.5+ floor); ensure build environment Qt >= 6.8.
4. **C++20**: qtmcp requires C++20. Bridge project set to C++20; GammaRay C++17 libs link fine. 4. **C++20**: qtmcp requires C++20. Bridge project set to C++20; GammaRay C++17 libs link fine.
5. **Models only available after `ClientConnectionManager::ready()`** — do not call `ObjectBroker::model()` before handshake completes. MCP tool calls arriving before probe connection should return an error or wait. 5. **Models only available after `ClientConnectionManager::ready()`** — do not call `ObjectBroker::model()` before handshake completes. MCP tool calls arriving before probe connection should return an error or wait.

View File

@@ -7,7 +7,7 @@ A [MCP](https://modelcontextprotocol.io/) server that bridges [GammaRay](https:/
``` ```
Target Qt/QML App ──TCP──► GammaRay MCP Bridge ──stdio──► LLM / AI Agent Target Qt/QML App ──TCP──► GammaRay MCP Bridge ──stdio──► LLM / AI Agent
(GammaRay probe (GammaRay client + (opencode, (GammaRay probe (GammaRay client + (opencode,
injected) qtmcp MCP server) Claude Desktop, etc.) injected) qtmcp MCP server) ZCode, etc.)
``` ```
The bridge is a GammaRay **client**: it connects to a probe injected into a target Qt app, reads the same models the GammaRay GUI uses, and translates them into MCP JSON-RPC tool calls over stdio. Supports both QML Quick apps (SceneGraph, QML items) and Qt Widget apps (widget hierarchy, properties, attributes). The bridge is a GammaRay **client**: it connects to a probe injected into a target Qt app, reads the same models the GammaRay GUI uses, and translates them into MCP JSON-RPC tool calls over stdio. Supports both QML Quick apps (SceneGraph, QML items) and Qt Widget apps (widget hierarchy, properties, attributes).
@@ -16,26 +16,37 @@ The bridge is a GammaRay **client**: it connects to a probe injected into a targ
- Qt 6.8+ (system) - Qt 6.8+ (system)
- C++20 compiler (GCC 12+, Clang 16+) - C++20 compiler (GCC 12+, Clang 16+)
- GammaRay 3.4.0+ built from source (see [build instructions](#building-gammaray)) - GammaRay 3.4.0+ (system package: `gammaray-dev` on Debian/Deepin)
- [qtmcp](https://github.com/signal-slot/qtmcp) (consumed via FetchContent — no manual install) - [qtmcp](https://github.com/signal-slot/qtmcp) (consumed via FetchContent — no manual install)
- Python 3.10+ with `pytest` (for running the test suite) - Python 3.10+ with `pytest` (for running the test suite)
## Building ## Building
### 1. Build and install GammaRay ### 1. Install system dependencies
```bash ```bash
cmake -S /path/to/GammaRay -B /path/to/GammaRay/build \ # Debian / Deepin
-DCMAKE_INSTALL_PREFIX=$(pwd)/install-prefix sudo apt install gammaray-dev gammaray-plugin-quickinspector
cmake --build /path/to/GammaRay/build
cmake --install /path/to/GammaRay/build --prefix $(pwd)/install-prefix
``` ```
### 2. Build the bridge ### 2. Build the bridge
```bash ```bash
cd bridge cd bridge
cmake -S . -B build -G Ninja -DCMAKE_PREFIX_PATH=$(pwd)/../install-prefix cmake -S . -B build -G Ninja
cmake --build build
```
#### Offline build (using a local qtmcp clone)
If you have a local clone of qtmcp (e.g. at `/home/user/Sources/qtmcp`),
pass `FETCHCONTENT_SOURCE_DIR_QTMcp` to skip the network fetch:
```bash
cd bridge
cmake -S . -B build -G Ninja \
-DFETCHCONTENT_SOURCE_DIR_QTMcp=/home/user/Sources/qtmcp \
-DFETCHCONTENT_FULLY_DISCONNECTED=ON
cmake --build build cmake --build build
``` ```
@@ -43,11 +54,11 @@ cmake --build build
```bash ```bash
# Start a probe (inject into a QML app) # Start a probe (inject into a QML app)
install-prefix/bin/gammaray --inject-only --listen tcp://127.0.0.1:11732 \ gammaray --inject-only --listen tcp://127.0.0.1:11732 \
--injector preload /usr/lib/qt6/bin/qml /path/to/app.qml -platform offscreen --injector preload /usr/lib/qt6/bin/qml /path/to/app.qml -platform offscreen
# Or inject into a widget app # Or inject into a widget app
install-prefix/bin/gammaray --inject-only --listen tcp://127.0.0.1:11732 \ gammaray --inject-only --listen tcp://127.0.0.1:11732 \
--injector preload /path/to/widget-app --injector preload /path/to/widget-app
# Start the bridge (stdio MCP server) # Start the bridge (stdio MCP server)
@@ -56,6 +67,17 @@ bridge/run.sh
The bridge starts in lazy-connect mode. Call `connectProbe("127.0.0.1", 11732)` from your MCP client once the probe is up. The bridge starts in lazy-connect mode. Call `connectProbe("127.0.0.1", 11732)` from your MCP client once the probe is up.
### 4. Build a .deb package (optional)
```bash
cd bridge/build
cpack -G DEB
```
The package installs the bridge binary (`/usr/bin/gammaray-mcp-bridge`),
qtmcp shared libs and plugins, and the `run.sh` helper script.
System dependencies (`gammaray >= 3.4.0`, Qt6 libs) are auto-detected.
## MCP Tools ## MCP Tools
### Connection management ### Connection management
@@ -121,4 +143,4 @@ See `tests/README.md` for details.
## License ## License
GPL-2.0-or-later. The bridge links GammaRay libraries (GPL-2.0-or-later) and uses qtmcp (available under GPL-2.0-only). GPL-2.0-or-later. The bridge links GammaRay libraries (GPL-2.0-or-later) and uses qtmcp (available under LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only — we comply under GPL-2.0-only).

View File

@@ -2,7 +2,8 @@
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
# #
# Links GammaRay client libs (GPL-2.0-or-later) => this bridge must be # Links GammaRay client libs (GPL-2.0-or-later) => this bridge must be
# GPL-compatible. qtmcp is consumed under its GPL-2.0-only option (compatible). # GPL-compatible. qtmcp is triple-licensed (LGPL-3.0-only / GPL-2.0-only /
# GPL-3.0-only); we comply under GPL-2.0-only.
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
project(GammaRayMcpBridge LANGUAGES CXX) project(GammaRayMcpBridge LANGUAGES CXX)
@@ -28,10 +29,13 @@ FetchContent_Declare(
# Qt-prefixed vars (NOT BUILD_EXAMPLES) — verified to suppress example/test build. # Qt-prefixed vars (NOT BUILD_EXAMPLES) — verified to suppress example/test build.
set(QT_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) set(QT_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(QT_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(QT_BUILD_TESTS OFF CACHE BOOL "" FORCE)
# qtmcp is built as shared libs + plugins (Qt plugin system requires this).
# For a distribution deb, the package includes the qtmcp shared libs and
# stdio plugin alongside the bridge binary. CPACK_DEBIAN_PACKAGE_SHLIBDEPS
# auto-detects the required system dependencies (gammaray, qt6, etc.).
FetchContent_MakeAvailable(qtmcp) FetchContent_MakeAvailable(qtmcp)
# --- GammaRay (built & installed in ../install-prefix by Step 1) --- # --- GammaRay (system package: gammaray-dev >= 3.4.0) ---
# Pass -DCMAKE_PREFIX_PATH=$(pwd)/../install-prefix at configure.
find_package(GammaRay REQUIRED) find_package(GammaRay REQUIRED)
# --- Qt6 components for the bridge target (Qt6 already found globally by qtmcp) --- # --- Qt6 components for the bridge target (Qt6 already found globally by qtmcp) ---
@@ -67,17 +71,30 @@ target_link_libraries(gammaray-mcp-bridge PRIVATE
Qt6::McpCommon Qt6::McpCommon
) )
# Add GammaRay source common/ for message.h (not in installed headers) install(TARGETS gammaray-mcp-bridge RUNTIME DESTINATION bin)
target_include_directories(gammaray-mcp-bridge PRIVATE install(PROGRAMS run.sh DESTINATION bin)
/home/blumia/Sources/GammaRay/common
# Runtime: qtmcp shared libs and stdio plugin are built in the build tree.
# For development, run.sh sets LD_LIBRARY_PATH and QT_PLUGIN_PATH.
# For distribution, CPack bundles qtmcp's install rules automatically.
set_target_properties(gammaray-mcp-bridge PROPERTIES
BUILD_RPATH "$<TARGET_FILE_DIR:Qt6::McpServer>"
INSTALL_RPATH "$ORIGIN/../lib/x86_64-linux-gnu"
) )
# Runtime: qtmcp builds SHARED libs + the stdio backend plugin into the build # --- CPack packaging ---
# tree. Set RPATH so the bridge finds libQt6Mcp*.so, and set QT_PLUGIN_PATH at set(CPACK_PACKAGE_NAME "gammaray-mcp-bridge")
# run time (see run.sh) so Qt loads mcpserverbackend/libqmcpserverstdio.so. set(CPACK_PACKAGE_VERSION "0.1.0")
# Also add GammaRay's install lib dir for libgammaray_*.so. set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "GammaRay MCP bridge")
set(_GR_LIBDIR "$<TARGET_PROPERTY:gammaray_client,IMPORTED_LOCATION>") set(CPACK_PACKAGE_DESCRIPTION "MCP server that exposes GammaRay probe introspection data (QML SceneGraph, QML items, and Qt Widgets) to LLMs for assisted debugging.")
set_target_properties(gammaray-mcp-bridge PROPERTIES set(CPACK_PACKAGE_CONTACT "Blumia <blumia@example.com>")
BUILD_RPATH "$<TARGET_FILE_DIR:Qt6::McpServer>;${CMAKE_SOURCE_DIR}/../install-prefix/lib" set(CPACK_PACKAGE_VENDOR "gammaray-mcp")
INSTALL_RPATH "$ORIGIN/../lib" set(CPACK_PACKAGE_SECTION "devel")
) set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Blumia <blumia@example.com>")
set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/blumia/gammaray-mcp")
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "gammaray-plugin-quickinspector")
set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT")
set(CPACK_GENERATOR "DEB")
include(CPack)

View File

@@ -1,13 +1,13 @@
#!/bin/sh #!/bin/sh
# Run the GammaRay MCP bridge. # Run the GammaRay MCP bridge.
# Sets up LD_LIBRARY_PATH (GammaRay + qtmcp libs) and QT_PLUGIN_PATH (qtmcp stdio # Sets up LD_LIBRARY_PATH for qtmcp shared libs (in build tree) and QT_PLUGIN_PATH
# backend plugin) so the bridge can find everything at runtime. # (qtmcp stdio backend plugin) so the bridge can find everything at runtime.
# GammaRay libraries come from the system package (gammaray-dev).
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
set -e set -e
HERE="$(cd "$(dirname "$0")" && pwd)" HERE="$(cd "$(dirname "$0")" && pwd)"
ROOT="$HERE/.."
BLD="$HERE/build" BLD="$HERE/build"
export LD_LIBRARY_PATH="$ROOT/install-prefix/lib:$BLD/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH:-}" export LD_LIBRARY_PATH="$BLD/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH:-}"
export QT_PLUGIN_PATH="$BLD/lib/x86_64-linux-gnu/qt6/plugins:${QT_PLUGIN_PATH:-}" export QT_PLUGIN_PATH="$BLD/lib/x86_64-linux-gnu/qt6/plugins:${QT_PLUGIN_PATH:-}"
export QT_QPA_PLATFORM=offscreen export QT_QPA_PLATFORM=offscreen
exec "$BLD/gammaray-mcp-bridge" "$@" exec "$BLD/gammaray-mcp-bridge" "$@"

View File

@@ -12,7 +12,6 @@
#include "quickinspector_types.h" #include "quickinspector_types.h"
#include <endpoint.h> #include <endpoint.h>
#include <message.h>
#include <protocol.h> #include <protocol.h>
#include <objectbroker.h> #include <objectbroker.h>