Compare commits
2 Commits
a6335429e5
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| e60b19acaf | |||
| a3380dbab5 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -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
|
||||||
|
|||||||
4
PLAN.md
4
PLAN.md
@@ -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.
|
||||||
|
|||||||
44
README.md
44
README.md
@@ -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).
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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" "$@"
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user