@gjsify/devtools-mcp 0.38.0 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/generic-tools.js +1 -1
- package/package.json +6 -6
package/lib/esm/generic-tools.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{image as e}from"./tool-result.js";import t from"@girs/glib-2.0";import{z as n}from"zod";const strv=e=>t.Variant.new_string(e),r={instance:n.string().optional().describe(`App instance label; omit for the default app`)};function delay(e){return new Promise(n=>{t.timeout_add(t.PRIORITY_DEFAULT,e,()=>(n(),t.SOURCE_REMOVE))})}function registerGenericTools(i,a=`all`){let{server:o,client:s,ok:c,fail:l,dbusError:u}=i,want=e=>a===`all`||a.includes(e);want(`get_status`)&&o.registerTool(`get_status`,{description:`JSON snapshot of the running app: app id, active window, toplevel count, focused widget, pause state, plus any app-specific status contributed by extensions.`,inputSchema:n.object({...r})},async({instance:e})=>{try{return c(await s.jsonCall(e,`GetStatus`))}catch(t){return u(t,e)}}),want(`screenshot`)&&o.registerTool(`screenshot`,{description
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{image as e}from"./tool-result.js";import t from"@girs/glib-2.0";import{z as n}from"zod";const strv=e=>t.Variant.new_string(e),r={instance:n.string().optional().describe(`App instance label; omit for the default app`)};function delay(e){return new Promise(n=>{t.timeout_add(t.PRIORITY_DEFAULT,e,()=>(n(),t.SOURCE_REMOVE))})}function registerGenericTools(i,a=`all`){let{server:o,client:s,ok:c,fail:l,dbusError:u}=i,want=e=>a===`all`||a.includes(e);want(`get_status`)&&o.registerTool(`get_status`,{description:`JSON snapshot of the running app: app id, active window, toplevel count, focused widget, pause state, plus any app-specific status contributed by extensions.`,inputSchema:n.object({...r})},async({instance:e})=>{try{return c(await s.jsonCall(e,`GetStatus`))}catch(t){return u(t,e)}}),want(`screenshot`)&&o.registerTool(`screenshot`,{description:"Capture a PNG screenshot via the GTK GSK pipeline. `scope` chooses WHAT is captured: the active window by default, or a single widget inside it by path. Needs a visible window (auto-raises + retries once when the capture comes back empty).",inputSchema:n.object({scope:n.string().optional().describe('What to capture: omitted, "window" or "active" for the active window, or a `toplevel:N/child:M` path from dump_tree for one widget. An explicit path matching no live widget is an error, not a silent whole-window shot.'),...r})},async({scope:n,instance:r})=>{try{let grab=async()=>(await s.control(r,`Screenshot`,t.Variant.new_tuple([strv(n??`window`)]),`(ay)`)).get_child_value(0).deepUnpack(),i=await grab();return(!i||i.length===0)&&(await s.control(r,`PresentWindow`,null,null),await delay(350),i=await grab()),!i||i.length===0?l(`Screenshot returned no data — the window is likely occluded or minimized. Bring it to the foreground (present_window) and retry.`):e(t.base64_encode(i))}catch(e){return u(e,r)}}),want(`list_actions`)&&o.registerTool(`list_actions`,{description:`List the app.* and win.* GActions (name, enabled, parameter/state types) that activate_action / change_action_state can drive.`,inputSchema:n.object({...r})},async({instance:e})=>{try{return c(await s.jsonCall(e,`ListActions`))}catch(t){return u(t,e)}}),want(`activate_action`)&&o.registerTool(`activate_action`,{description:`Activate a GAction by scope + name, with an optional parameter (a plain JSON value coerced to the action's declared type).`,inputSchema:n.object({scope:n.enum([`app`,`win`]),name:n.string(),value:n.union([n.string(),n.number(),n.boolean()]).optional(),...r})},async({scope:e,name:n,value:r,instance:i})=>{try{let a=r===void 0?``:JSON.stringify(r);return await s.control(i,`ActivateAction`,t.Variant.new_tuple([strv(e),strv(n),strv(a)]),null),c(`Activated ${e}.${n}`)}catch(e){return u(e,i)}}),want(`change_action_state`)&&o.registerTool(`change_action_state`,{description:`Set a stateful GAction’s state — for idempotent toggles like win.toggle-grid.`,inputSchema:n.object({scope:n.enum([`app`,`win`]),name:n.string(),value:n.union([n.string(),n.number(),n.boolean()]),...r})},async({scope:e,name:n,value:r,instance:i})=>{try{return await s.control(i,`ChangeActionState`,t.Variant.new_tuple([strv(e),strv(n),strv(JSON.stringify(r))]),null),c(`Set state ${e}.${n} = ${JSON.stringify(r)}`)}catch(e){return u(e,i)}}),want(`present_window`)&&o.registerTool(`present_window`,{description:`Raise + focus the app’s active window.`,inputSchema:n.object({...r})},async({instance:e})=>{try{return await s.control(e,`PresentWindow`,null,null),c(`Presented the window.`)}catch(t){return u(t,e)}}),want(`resize_window`)&&o.registerTool(`resize_window`,{description:`Resize the active window to an absolute pixel size (exercises responsive breakpoints). Returns the requested size.`,inputSchema:n.object({width:n.number(),height:n.number(),...r})},async({width:e,height:n,instance:r})=>{try{let[i,a]=(await s.control(r,`ResizeWindow`,t.Variant.new_tuple([t.Variant.new_int32(e),t.Variant.new_int32(n)]),`(ii)`)).recursiveUnpack();return c(`Resized to ${i}×${a}.`)}catch(e){return u(e,r)}}),want(`list_toplevels`)&&o.registerTool(`list_toplevels`,{description:`List the app’s live toplevel windows (path, type, title, mapped, focused).`,inputSchema:n.object({...r})},async({instance:e})=>{try{return c(await s.jsonCall(e,`ListToplevels`))}catch(t){return u(t,e)}}),want(`dump_tree`)&&o.registerTool(`dump_tree`,{description:'Dump the widget tree as JSON from `root` (a widget path like "toplevel:0/child:2", or omit for the active window), bounded by `depth`.',inputSchema:n.object({root:n.string().optional(),depth:n.number().optional(),...r})},async({root:e,depth:n,instance:r})=>{try{let i=t.Variant.new_tuple([strv(e??``),t.Variant.new_int32(n??8)]);return c(await s.jsonCall(r,`DumpTree`,i))}catch(e){return u(e,r)}}),want(`get_property`)&&o.registerTool(`get_property`,{description:`Read a widget’s GObject property by widget path + property name (JSON-safe value).`,inputSchema:n.object({path:n.string(),prop:n.string(),...r})},async({path:e,prop:n,instance:r})=>{try{let i=t.Variant.new_tuple([strv(e),strv(n)]);return c(await s.jsonCall(r,`GetProperty`,i))}catch(e){return u(e,r)}}),want(`get_focused`)&&o.registerTool(`get_focused`,{description:`The currently-focused widget (path, name, type), or null.`,inputSchema:n.object({...r})},async({instance:e})=>{try{return c(await s.jsonCall(e,`GetFocused`))}catch(t){return u(t,e)}}),want(`activate_widget`)&&o.registerTool(`activate_widget`,{description:`Activate the widget at a widget path (from dump_tree) — the click-drive counterpart of get_property: a Button emits clicked, an Entry activates, a Toggle toggles; a list/nav/preference row (GtkListBoxRow/AdwActionRow) is clicked on its GtkListBox (selected + row-activated). Returns whether the widget activated.`,inputSchema:n.object({path:n.string(),...r})},async({path:e,instance:n})=>{try{let[r]=(await s.control(n,`ActivateWidget`,t.Variant.new_tuple([strv(e)]),`(b)`)).recursiveUnpack();return c(r?`Activated widget at "${e}".`:`Widget at "${e}" is not activatable (no default activation).`)}catch(e){return u(e,n)}}),want(`dump_gsettings`)&&o.registerTool(`dump_gsettings`,{description:`Dump every key + value of an installed GSettings schema (read-only).`,inputSchema:n.object({schema:n.string(),...r})},async({schema:e,instance:n})=>{try{return c(await s.jsonCall(n,`DumpGSettings`,t.Variant.new_tuple([strv(e)])))}catch(e){return u(e,n)}}),want(`dump_css`)&&o.registerTool(`dump_css`,{description:`List the devtools-installed CSS provider names.`,inputSchema:n.object({...r})},async({instance:e})=>{try{return c(await s.jsonCall(e,`DumpCss`))}catch(t){return u(t,e)}}),want(`swap_css`)&&o.registerTool(`swap_css`,{description:`Live-install or replace a named CSS provider (high priority) — re-theme the running app without a restart. Returns applied.`,inputSchema:n.object({name:n.string(),css:n.string(),...r})},async({name:e,css:n,instance:r})=>{try{let[i]=(await s.control(r,`SwapCss`,t.Variant.new_tuple([strv(e),strv(n)]),`(b)`)).recursiveUnpack();return c(i?`Applied CSS provider "${e}".`:`No display — CSS not applied.`)}catch(e){return u(e,r)}}),want(`list_instances`)&&o.registerTool(`list_instances`,{description:`List reachable devtools-enabled app instances — every default/labelled bus name on the session bus, or (on the bus-less peer transport) the single app this bridge is dialling.`,inputSchema:n.object({})},async()=>{try{return c(JSON.stringify(await s.listInstances(),null,2))}catch(e){return u(e)}})}export{registerGenericTools};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/devtools-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.39.0",
|
|
4
4
|
"description": "MCP↔devtools bridge for GJS apps — exposes a running app's org.gjsify.Devtools control plane (DBus) to an AI agent as MCP tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -39,12 +39,12 @@
|
|
|
39
39
|
"@girs/gjs": "^4.1.0",
|
|
40
40
|
"@girs/glib-2.0": "^4.1.0",
|
|
41
41
|
"@girs/soup-3.0": "^4.1.0",
|
|
42
|
-
"@gjsify/devtools-protocol": "^0.
|
|
42
|
+
"@gjsify/devtools-protocol": "^0.39.0",
|
|
43
43
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
44
44
|
"zod": "^4.4.3"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@gjsify/devtools-cdp": "^0.
|
|
47
|
+
"@gjsify/devtools-cdp": "^0.39.0"
|
|
48
48
|
},
|
|
49
49
|
"peerDependenciesMeta": {
|
|
50
50
|
"@gjsify/devtools-cdp": {
|
|
@@ -52,9 +52,9 @@
|
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@gjsify/cli": "^0.
|
|
56
|
-
"@gjsify/devtools-cdp": "^0.
|
|
57
|
-
"@gjsify/unit": "^0.
|
|
55
|
+
"@gjsify/cli": "^0.39.0",
|
|
56
|
+
"@gjsify/devtools-cdp": "^0.39.0",
|
|
57
|
+
"@gjsify/unit": "^0.39.0",
|
|
58
58
|
"@types/node": "^25.9.2",
|
|
59
59
|
"typescript": "^6.0.3"
|
|
60
60
|
},
|