@csmodding/gameface-devtools-mcp 1.2.0 → 1.2.1
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 +5 -4
- package/dist/server.mjs +48 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -148,10 +148,11 @@ Or in `.vscode/mcp.json` (note the `servers` key, not `mcpServers`):
|
|
|
148
148
|
|
|
149
149
|
> [!IMPORTANT]
|
|
150
150
|
> **Input is done via DOM events, not CDP `Input`.** Gameface accepts `Input.dispatchMouseEvent` /
|
|
151
|
-
> `dispatchKeyEvent` but never delivers them to the UI
|
|
152
|
-
>
|
|
153
|
-
>
|
|
154
|
-
>
|
|
151
|
+
> `dispatchKeyEvent` but never delivers them to the UI — the mouse command measured on Cohtml 1.64
|
|
152
|
+
> and 2.2, the key and text ones on 2.2, with a 3.x Player untested. So `game_click`, `game_fill`,
|
|
153
|
+
> `game_type`, `game_key`, and `game_hover` dispatch real DOM events in the page. These reach the
|
|
154
|
+
> UI's own JS handlers, but not any input the game routes at the native/engine level (e.g.
|
|
155
|
+
> Escape-to-close is often handled natively and will not respond to a dispatched key).
|
|
155
156
|
|
|
156
157
|
### JS debugger tools
|
|
157
158
|
|
package/dist/server.mjs
CHANGED
|
@@ -30622,12 +30622,16 @@ var SUPPORTED_PSEUDOS = new Set([
|
|
|
30622
30622
|
":before",
|
|
30623
30623
|
":after",
|
|
30624
30624
|
"::before",
|
|
30625
|
-
"::after"
|
|
30625
|
+
"::after",
|
|
30626
|
+
":host"
|
|
30626
30627
|
]);
|
|
30628
|
+
var ANSWERED_NOT_REJECTED = new Set(["::slotted", "::part", "::selection"]);
|
|
30629
|
+
var ARGUMENTLESS_ANSWERED = new Set(["::selection"]);
|
|
30627
30630
|
var SUPPORTED_SUMMARY = import_common_tags2.oneLine`
|
|
30628
30631
|
type, class, id and attribute selectors, combinators, \`:first-child\`, \`:last-child\`,
|
|
30629
|
-
\`:only-child\`, \`:nth-child()\`, \`:root\`, \`:hover\`, \`:focus\`, \`:active\`, \`::before
|
|
30630
|
-
and
|
|
30632
|
+
\`:only-child\`, \`:nth-child()\`, \`:root\`, \`:hover\`, \`:focus\`, \`:active\`, \`::before\`,
|
|
30633
|
+
\`::after\`, and \`:host\` matched off the element alone rather than from a scoped query, which
|
|
30634
|
+
answers nothing
|
|
30631
30635
|
`;
|
|
30632
30636
|
var NTH_CHILD_ARGUMENT = /^\s*(?:[+-]?\d+|even|odd|[+-]?\d*n)\s*$/iu;
|
|
30633
30637
|
var PSEUDO_TOKEN = /(?<colons>::?)(?<name>[a-z][a-z-]*)(?:\((?<argument>[^()]*)\))?/giu;
|
|
@@ -30723,6 +30727,9 @@ function maskLiterals(selector) {
|
|
|
30723
30727
|
return LITERAL_SPANS.reduce((masked, span) => masked.replace(span, (literal3) => MASK_FILLER.repeat(literal3.length)), selector);
|
|
30724
30728
|
}
|
|
30725
30729
|
function isSupported(key, argument) {
|
|
30730
|
+
if (ANSWERED_NOT_REJECTED.has(key)) {
|
|
30731
|
+
return ARGUMENTLESS_ANSWERED.has(key) || argument != null && argument.trim() != "";
|
|
30732
|
+
}
|
|
30726
30733
|
if (!SUPPORTED_PSEUDOS.has(key)) {
|
|
30727
30734
|
return false;
|
|
30728
30735
|
}
|
|
@@ -32503,6 +32510,8 @@ function clickFn(sel, index) {
|
|
|
32503
32510
|
cancelable: true,
|
|
32504
32511
|
view: window,
|
|
32505
32512
|
button: 0,
|
|
32513
|
+
screenX: cx,
|
|
32514
|
+
screenY: cy,
|
|
32506
32515
|
clientX: cx,
|
|
32507
32516
|
clientY: cy
|
|
32508
32517
|
};
|
|
@@ -32606,14 +32615,10 @@ function typeFn(sel, textToType, index, commit) {
|
|
|
32606
32615
|
key: ch,
|
|
32607
32616
|
view: window
|
|
32608
32617
|
};
|
|
32609
|
-
|
|
32610
|
-
el.dispatchEvent(new KeyboardEvent("keydown", opts));
|
|
32611
|
-
} catch {}
|
|
32618
|
+
sendKey("keydown", ch, opts);
|
|
32612
32619
|
setValue(current() + ch);
|
|
32613
32620
|
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
32614
|
-
|
|
32615
|
-
el.dispatchEvent(new KeyboardEvent("keyup", opts));
|
|
32616
|
-
} catch {}
|
|
32621
|
+
sendKey("keyup", ch, opts);
|
|
32617
32622
|
typed++;
|
|
32618
32623
|
}
|
|
32619
32624
|
el.dispatchEvent(new Event("change", { bubbles: true }));
|
|
@@ -32627,6 +32632,38 @@ function typeFn(sel, textToType, index, commit) {
|
|
|
32627
32632
|
el.dispatchEvent(event);
|
|
32628
32633
|
}
|
|
32629
32634
|
return { found: true, count, typed, value: current() };
|
|
32635
|
+
function sendKey(type, ch, init) {
|
|
32636
|
+
try {
|
|
32637
|
+
const ev = new KeyboardEvent(type, init);
|
|
32638
|
+
force(ev, "key", ch);
|
|
32639
|
+
const legacy = codeForChar(ch);
|
|
32640
|
+
if (legacy) {
|
|
32641
|
+
force(ev, "code", legacy.code);
|
|
32642
|
+
force(ev, "keyCode", legacy.keyCode);
|
|
32643
|
+
force(ev, "which", legacy.keyCode);
|
|
32644
|
+
}
|
|
32645
|
+
el.dispatchEvent(ev);
|
|
32646
|
+
} catch {}
|
|
32647
|
+
}
|
|
32648
|
+
function codeForChar(ch) {
|
|
32649
|
+
const SPACE_KEY_CODE = 32;
|
|
32650
|
+
if (ch == " ") {
|
|
32651
|
+
return { code: "Space", keyCode: SPACE_KEY_CODE };
|
|
32652
|
+
}
|
|
32653
|
+
if (/^[a-zA-Z]$/u.test(ch)) {
|
|
32654
|
+
const upper = ch.toUpperCase();
|
|
32655
|
+
return { code: `Key${upper}`, keyCode: upper.codePointAt(0) ?? 0 };
|
|
32656
|
+
}
|
|
32657
|
+
if (/^[0-9]$/u.test(ch)) {
|
|
32658
|
+
return { code: `Digit${ch}`, keyCode: ch.codePointAt(0) ?? 0 };
|
|
32659
|
+
}
|
|
32660
|
+
return;
|
|
32661
|
+
}
|
|
32662
|
+
function force(ev, prop, value) {
|
|
32663
|
+
try {
|
|
32664
|
+
Object.defineProperty(ev, prop, { get: () => value, configurable: true });
|
|
32665
|
+
} catch {}
|
|
32666
|
+
}
|
|
32630
32667
|
function current() {
|
|
32631
32668
|
if (editable) {
|
|
32632
32669
|
return el.textContent ?? "";
|
|
@@ -32661,6 +32698,8 @@ function hoverFn(sel, index) {
|
|
|
32661
32698
|
bubbles: true,
|
|
32662
32699
|
cancelable: true,
|
|
32663
32700
|
view: window,
|
|
32701
|
+
screenX: cx,
|
|
32702
|
+
screenY: cy,
|
|
32664
32703
|
clientX: cx,
|
|
32665
32704
|
clientY: cy
|
|
32666
32705
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@csmodding/gameface-devtools-mcp",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "MCP server that drives a running Coherent Gameface (Cohtml) game UI over a direct Chrome DevTools Protocol connection: evaluate JS, screenshot, inspect and drive the DOM, capture the console, and set JS breakpoints.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"browser-automation",
|