plonk-mcp 0.2.2 → 0.2.4
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/README.md +1 -1
- package/dist/tools/screenshot.js +27 -5
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -58,7 +58,7 @@ config to tell two sessions of the same client apart.
|
|
|
58
58
|
| `save_workspace` · `launch_workspace` · `delete_workspace` | Named desktops that reopen their apps and restore every window |
|
|
59
59
|
| `save_zone_set` · `assign_zone_set` · `delete_zone_set` | Snap zones, assigned per monitor |
|
|
60
60
|
| `set_awake` | Keep-awake, optionally time-limited |
|
|
61
|
-
| `take_screenshot` · `annotate_screenshot` | Capture, mark up, hand the image back |
|
|
61
|
+
| `take_screenshot` · `annotate_screenshot` | Capture, mark up, hand the image back — `mode: "app"` photographs one named window even when it is buried, without raising it |
|
|
62
62
|
| `select_agent` | Make an agent the active one, optionally the only one allowed to control |
|
|
63
63
|
| `check_for_update` · `install_update` | Ask GitHub for a newer release and install it |
|
|
64
64
|
|
package/dist/tools/screenshot.js
CHANGED
|
@@ -2,13 +2,34 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { call, text } from "../api.js";
|
|
4
4
|
// The interactive modes hand the user a crosshair and wait for them.
|
|
5
|
+
const INTERACTIVE_MODES = new Set(["region", "window"]);
|
|
5
6
|
const INTERACTIVE_TIMEOUT_MS = 5 * 60_000;
|
|
6
7
|
// Refuse to inline anything larger; a full retina desktop is easily 10 MB,
|
|
7
8
|
// which is dead weight in the conversation.
|
|
8
9
|
const MAX_INLINE_BYTES = 4 << 20;
|
|
10
|
+
/**
|
|
11
|
+
* Which mode a call really asks for.
|
|
12
|
+
*
|
|
13
|
+
* Naming a window is asking for that window, so a caller that passes 'app' and
|
|
14
|
+
* leaves 'mode' at its default gets the window rather than the whole screen —
|
|
15
|
+
* which would answer a question nobody asked and look right enough to be
|
|
16
|
+
* believed. Only the default is overridden: asking for a crosshair outright
|
|
17
|
+
* still hands the user a crosshair.
|
|
18
|
+
*/
|
|
19
|
+
export function captureMode(mode, app, titleContains) {
|
|
20
|
+
return mode === "screen" && (app || titleContains) ? "app" : mode;
|
|
21
|
+
}
|
|
9
22
|
export function register(server) {
|
|
10
|
-
server.tool("take_screenshot", "Capture the screen and return the image so it can be looked at. mode 'screen' captures everything (no user interaction), 'region' and 'window' hand the user the native crosshair/window picker and wait for them. Set annotate=true to open Plonk's drawing editor on the capture instead of returning it — use that when the user wants to mark the shot up themselves. Optional 'path' writes to an explicit file, otherwise the configured screenshot folder is used; 'clipboard' overrides the configured copy-to-clipboard behavior. The returned image is scaled down for legibility; the file at 'path' keeps full resolution. To draw on the result, pass that 'path' to annotate_screenshot.", {
|
|
11
|
-
mode: z.enum(["screen", "region", "window"]).default("screen"),
|
|
23
|
+
server.tool("take_screenshot", "Capture the screen and return the image so it can be looked at. mode 'screen' captures everything (no user interaction); mode 'app' captures one named window and needs no user interaction either — pass 'app' and/or 'title_contains', and it works even when that window is behind others, minimized excepted, without raising it or taking focus; 'region' and 'window' hand the user the native crosshair/window picker and wait for them. Prefer 'app' whenever the user asks about a particular program (\"what is playing in Spotify\", \"read the error in Xcode\") — it is the only mode that can see a window the user cannot, and it does not disturb their desktop. Set annotate=true to open Plonk's drawing editor on the capture instead of returning it — use that when the user wants to mark the shot up themselves. Optional 'path' writes to an explicit file, otherwise the configured screenshot folder is used; 'clipboard' overrides the configured copy-to-clipboard behavior. The returned image is scaled down for legibility; the file at 'path' keeps full resolution. To draw on the result, pass that 'path' to annotate_screenshot.", {
|
|
24
|
+
mode: z.enum(["screen", "app", "region", "window"]).default("screen"),
|
|
25
|
+
app: z
|
|
26
|
+
.string()
|
|
27
|
+
.optional()
|
|
28
|
+
.describe("mode 'app': app name or bundle id, case-insensitive substring (e.g. 'Spotify')"),
|
|
29
|
+
title_contains: z
|
|
30
|
+
.string()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("mode 'app': narrows to a window whose title contains this, for an app with several"),
|
|
12
33
|
annotate: z.boolean().optional().describe("Open the annotation editor instead of returning the image"),
|
|
13
34
|
path: z.string().optional().describe("Explicit output file path (.png)"),
|
|
14
35
|
clipboard: z.boolean().optional().describe("Also copy the capture to the clipboard"),
|
|
@@ -16,11 +37,12 @@ export function register(server) {
|
|
|
16
37
|
.boolean()
|
|
17
38
|
.optional()
|
|
18
39
|
.describe("Return the image content itself, so it can be inspected (default true)"),
|
|
19
|
-
}, async ({ mode, annotate, path, clipboard, include_image }) => {
|
|
40
|
+
}, async ({ mode, app, title_contains, annotate, path, clipboard, include_image }) => {
|
|
41
|
+
const wanted = captureMode(mode, app, title_contains);
|
|
20
42
|
const result = await call("/shot/capture", {
|
|
21
43
|
method: "POST",
|
|
22
|
-
body: { mode, annotate, path, clipboard, preview: include_image !== false },
|
|
23
|
-
timeoutMs:
|
|
44
|
+
body: { mode: wanted, app, title_contains, annotate, path, clipboard, preview: include_image !== false },
|
|
45
|
+
timeoutMs: INTERACTIVE_MODES.has(wanted) ? INTERACTIVE_TIMEOUT_MS : undefined,
|
|
24
46
|
});
|
|
25
47
|
const savedPath = "path" in result && typeof result.path === "string" ? result.path : undefined;
|
|
26
48
|
if (!savedPath || include_image === false)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plonk-mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"mcpName": "io.github.ostapondo/plonk",
|
|
5
5
|
"description": "MCP server for Plonk, a macOS window manager: zones you draw yourself, workspaces, keep-awake, screenshots and on-device OCR, as tools an agent can call.",
|
|
6
6
|
"type": "module",
|
|
@@ -16,10 +16,14 @@
|
|
|
16
16
|
"mcp",
|
|
17
17
|
"model-context-protocol",
|
|
18
18
|
"claude",
|
|
19
|
+
"claude-code",
|
|
19
20
|
"macos",
|
|
20
21
|
"window-manager",
|
|
21
22
|
"workspaces",
|
|
22
|
-
"
|
|
23
|
+
"zones",
|
|
24
|
+
"screenshots",
|
|
25
|
+
"ocr",
|
|
26
|
+
"accessibility"
|
|
23
27
|
],
|
|
24
28
|
"engines": {
|
|
25
29
|
"node": ">=18"
|