summaryrefslogtreecommitdiff
path: root/README.md
blob: 23257e17036fc174204109da59eb79e93ec17b27 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# Sailfish Devel MCP

Host-side Model Context Protocol server for Sailfish OS development workflows.

This first iteration is dependency-free: it implements MCP over stdio directly
with Python's standard library and exposes typed tools around commands that are
easy to get wrong during day-to-day Sailfish work.

## Scope

The server currently exposes tools for:

- Sailfish device access over SSH
- defaultuser session-bus calls
- Lipstick screenshots
- touchscreen discovery and tap/swipe injection
- combined screenshot, touchscreen discovery, and touch injection workflows
- topmost window PID lookup
- process map inspection
- journal log reads
- RPM copy/install on a device
- system and user service management
- user-session command execution with the configured D-Bus environment
- Sailfish Browser launch/debug helpers
- Docker/mb2 RPM builds through the local `build-sailfishos` helper
- installed SDK repository metadata refresh
- Jolla OBS result and build-log lookup through `osc`
- repository status and search under the configured git root
- RPM spec metadata summaries
- QML translation search and Sailfish ternary translation checks

The committed defaults are deliberately generic. Device tools default to the
placeholder SSH target `root@device`, the Sailfish user-session bus at
`/run/user/100000/dbus/user_bus_socket`, `~/git` as the local source root,
`~/OBS` as the OBS checkout root, and the vendored build helper at
`src/sailfish_devel_mcp/vendor/build_sailfishos.py`. Put a config file at
`~/.config/sailfish-devel-mcp/config.json` or pass `--config` to provide your
real device and OBS settings. Device entries can also carry the preferred
user, architecture, and current release label. If an installed SDK is
available, set `paths.local_sdk` to its `sdk-chroot` path; builds will use it
when it has a target matching the requested release and architecture, otherwise
they fall back to the coderus SDK image.

## Running

From a checkout:

```sh
/path/to/sailfish-devel-mcp/bin/sailfish-devel-mcp
```

To inspect the effective configuration:

```sh
/path/to/sailfish-devel-mcp/bin/sailfish-devel-mcp --dump-config
```

Example MCP client configuration:

```json
{
  "mcpServers": {
    "sailfish-devel": {
      "command": "/path/to/sailfish-devel-mcp/bin/sailfish-devel-mcp"
    }
  }
}
```

## Configuration

Example:

```json
{
  "default_device": "phone",
  "devices": {
    "phone": {
      "ssh_target": "root@phone",
      "username": "defaultuser",
      "architecture": "aarch64",
      "release": "live",
      "user_bus_runtime_dir": "/run/user/100000",
      "user_bus_address": "unix:path=/run/user/100000/dbus/user_bus_socket"
    }
  },
  "paths": {
    "git_root": "~/git",
    "obs_root": "~/OBS",
    "ssh_config": "~/.ssh/config",
    "local_sdk": "/srv/mer/sdks/sfossdk/sdk-chroot",
    "osc_api_alias": "your-obs-alias"
  }
}
```

## Tool Notes

The server keeps local paths scoped to the configured git root, OBS checkout
root, and `/tmp` for tools that read or write files. Device access still uses
SSH, so the usual SSH prompts, permissions, and command failures are surfaced
as tool results.

Mutating tools are annotated as non-read-only:

- `sailfish_device_lipstick_screenshot`
- `sailfish_device_touch`
- `sailfish_device_touch_workflow`
- `sailfish_device_user_bus_call`
- `sailfish_device_user_session_command`
- `sailfish_device_install_rpm`
- `sailfish_device_restart_service`
- `sailfish_device_browser_launch`
- `sailfish_build_rpm`
- `sailfish_sdk_refresh_metadata`

`sailfish_device_lipstick_screenshot` defaults to
`~/Pictures/Screenshots/lipstick-<timestamp>.png` under `/home/<username>`,
where `username` comes from the device config. Lipstick rejects screenshot save
paths outside the home directory. When that directory is missing, the tool
derives ownership with `stat -L`, creates `Pictures` as that owner/group with
mode `775`, and creates `Pictures/Screenshots` as that owner and the
`privileged` group with mode `755` when the group exists.

`sailfish_device_touch` supports `discover`, `tap`, and `swipe`. Discovery
prints `/proc/bus/input/devices` and can also run `evdev_trace -i` when
`include_evdev_trace` is true. Tap and swipe auto-select a likely touchscreen
input event device unless `input_device` is supplied. Coordinates are raw
input/display coordinates, so pair this tool with a current screenshot when
choosing points.

`sailfish_device_touch_workflow` wraps the common UI-debugging sequence:
capture a Lipstick screenshot, optionally list touch devices, inject a tap or
swipe, and optionally capture a second screenshot. It returns each step's
structured result separately.

`sailfish_device_user_session_command` runs an argv command with
`XDG_RUNTIME_DIR` and `DBUS_SESSION_BUS_ADDRESS` set from the configured device.
Set `run_as_user` when the command should execute as the configured Sailfish
username through `runuser` or `su`.

`sailfish_device_browser_launch` stops the browser booster service and stale
browser/firejail PIDs when requested, launches Sailfish Browser through
`invoker` with the display and user-session environment, then queries Lipstick
for the topmost PID and checks whether that process has `libxul.so` mapped.

`sailfish_build_rpm` can use a configured device's `architecture` and `release`
as defaults when the call includes `device`. If `paths.local_sdk` is set, the
build defaults to `live` and first checks the installed SDK targets. `live` uses
the unversioned local target for the requested architecture, for example
`aarch64`. A named production release such as `5.0.0` is used only when passed
explicitly through the tool arguments, environment, or device config; it uses a
matching versioned local target such as `aarch64-5.0.0` when available, and
otherwise falls back to the release-specific coderus Docker SDK image. The
wrapper image defaults to `sailfish-sdk-build-engine:$USER` and can be
overridden with
`SAILFISH_SDK_BUILD_ENGINE_IMAGE`.

`sailfish_sdk_refresh_metadata` refreshes zypper metadata in the installed SDK
main target, for example `aarch64.default`, using the same privileged Docker
wrapper style as local SDK builds. Use it when local SDK builds fail because a
package listed in repository metadata cannot be downloaded.

`sailfish_obs_buildlog` defaults to `osc api` with `nostream=1` so a build log
request does not become a long-running live stream. Set `nostream` to `false`
to use `osc remotebuildlog`.

Read-only tools include the journal, topmost PID, process maps, OBS lookup,
repo search, spec summary, and QML checks.

## Smoke Test

```sh
printf '%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
  | /path/to/sailfish-devel-mcp/bin/sailfish-devel-mcp
```

## Development

Run tests without installing the package:

```sh
PYTHONPATH=src python3 -m unittest discover -s tests
```