cssprobe-cli 0.2.25 → 0.3.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.
@@ -0,0 +1,261 @@
1
+ export declare function getToolDefinitions(): ({
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {
7
+ url: {
8
+ type: "string";
9
+ description: string;
10
+ };
11
+ headed: {
12
+ type: "boolean";
13
+ description: string;
14
+ };
15
+ viewport: {
16
+ type: "string";
17
+ description: string;
18
+ };
19
+ browser: {
20
+ type: "string";
21
+ enum: string[];
22
+ description: string;
23
+ };
24
+ state: {
25
+ type: "string";
26
+ description: string;
27
+ };
28
+ selector?: undefined;
29
+ depth?: undefined;
30
+ brief?: undefined;
31
+ expression?: undefined;
32
+ full_page?: undefined;
33
+ out?: undefined;
34
+ css?: undefined;
35
+ all?: undefined;
36
+ };
37
+ required: never[];
38
+ };
39
+ } | {
40
+ name: string;
41
+ description: string;
42
+ inputSchema: {
43
+ type: "object";
44
+ properties: {
45
+ selector: {
46
+ type: "string";
47
+ description: string;
48
+ };
49
+ depth: {
50
+ type: "number";
51
+ description: string;
52
+ };
53
+ brief: {
54
+ type: "boolean";
55
+ description: string;
56
+ };
57
+ url?: undefined;
58
+ headed?: undefined;
59
+ viewport?: undefined;
60
+ browser?: undefined;
61
+ state?: undefined;
62
+ expression?: undefined;
63
+ full_page?: undefined;
64
+ out?: undefined;
65
+ css?: undefined;
66
+ all?: undefined;
67
+ };
68
+ required: string[];
69
+ };
70
+ } | {
71
+ name: string;
72
+ description: string;
73
+ inputSchema: {
74
+ type: "object";
75
+ properties: {
76
+ selector: {
77
+ type: "string";
78
+ description: string;
79
+ };
80
+ depth: {
81
+ type: "number";
82
+ description: string;
83
+ };
84
+ url?: undefined;
85
+ headed?: undefined;
86
+ viewport?: undefined;
87
+ browser?: undefined;
88
+ state?: undefined;
89
+ brief?: undefined;
90
+ expression?: undefined;
91
+ full_page?: undefined;
92
+ out?: undefined;
93
+ css?: undefined;
94
+ all?: undefined;
95
+ };
96
+ required: string[];
97
+ };
98
+ } | {
99
+ name: string;
100
+ description: string;
101
+ inputSchema: {
102
+ type: "object";
103
+ properties: {
104
+ selector: {
105
+ type: "string";
106
+ description: string;
107
+ };
108
+ url?: undefined;
109
+ headed?: undefined;
110
+ viewport?: undefined;
111
+ browser?: undefined;
112
+ state?: undefined;
113
+ depth?: undefined;
114
+ brief?: undefined;
115
+ expression?: undefined;
116
+ full_page?: undefined;
117
+ out?: undefined;
118
+ css?: undefined;
119
+ all?: undefined;
120
+ };
121
+ required: string[];
122
+ };
123
+ } | {
124
+ name: string;
125
+ description: string;
126
+ inputSchema: {
127
+ type: "object";
128
+ properties: {
129
+ expression: {
130
+ type: "string";
131
+ description: string;
132
+ };
133
+ url?: undefined;
134
+ headed?: undefined;
135
+ viewport?: undefined;
136
+ browser?: undefined;
137
+ state?: undefined;
138
+ selector?: undefined;
139
+ depth?: undefined;
140
+ brief?: undefined;
141
+ full_page?: undefined;
142
+ out?: undefined;
143
+ css?: undefined;
144
+ all?: undefined;
145
+ };
146
+ required: string[];
147
+ };
148
+ } | {
149
+ name: string;
150
+ description: string;
151
+ inputSchema: {
152
+ type: "object";
153
+ properties: {
154
+ full_page: {
155
+ type: "boolean";
156
+ description: string;
157
+ };
158
+ out: {
159
+ type: "string";
160
+ description: string;
161
+ };
162
+ url?: undefined;
163
+ headed?: undefined;
164
+ viewport?: undefined;
165
+ browser?: undefined;
166
+ state?: undefined;
167
+ selector?: undefined;
168
+ depth?: undefined;
169
+ brief?: undefined;
170
+ expression?: undefined;
171
+ css?: undefined;
172
+ all?: undefined;
173
+ };
174
+ required: never[];
175
+ };
176
+ } | {
177
+ name: string;
178
+ description: string;
179
+ inputSchema: {
180
+ type: "object";
181
+ properties: {
182
+ css: {
183
+ type: "string";
184
+ description: string;
185
+ };
186
+ url?: undefined;
187
+ headed?: undefined;
188
+ viewport?: undefined;
189
+ browser?: undefined;
190
+ state?: undefined;
191
+ selector?: undefined;
192
+ depth?: undefined;
193
+ brief?: undefined;
194
+ expression?: undefined;
195
+ full_page?: undefined;
196
+ out?: undefined;
197
+ all?: undefined;
198
+ };
199
+ required: string[];
200
+ };
201
+ } | {
202
+ name: string;
203
+ description: string;
204
+ inputSchema: {
205
+ type: "object";
206
+ properties: {
207
+ all: {
208
+ type: "boolean";
209
+ description: string;
210
+ };
211
+ url?: undefined;
212
+ headed?: undefined;
213
+ viewport?: undefined;
214
+ browser?: undefined;
215
+ state?: undefined;
216
+ selector?: undefined;
217
+ depth?: undefined;
218
+ brief?: undefined;
219
+ expression?: undefined;
220
+ full_page?: undefined;
221
+ out?: undefined;
222
+ css?: undefined;
223
+ };
224
+ required: never[];
225
+ };
226
+ } | {
227
+ name: string;
228
+ description: string;
229
+ inputSchema: {
230
+ type: "object";
231
+ properties: {
232
+ url?: undefined;
233
+ headed?: undefined;
234
+ viewport?: undefined;
235
+ browser?: undefined;
236
+ state?: undefined;
237
+ selector?: undefined;
238
+ depth?: undefined;
239
+ brief?: undefined;
240
+ expression?: undefined;
241
+ full_page?: undefined;
242
+ out?: undefined;
243
+ css?: undefined;
244
+ all?: undefined;
245
+ };
246
+ required: never[];
247
+ };
248
+ })[];
249
+ export declare class MCPToolHandler {
250
+ private runSession;
251
+ open(args: Record<string, unknown>): Promise<string>;
252
+ inspect(args: Record<string, unknown>): Promise<string>;
253
+ tree(args: Record<string, unknown>): Promise<string>;
254
+ layout(args: Record<string, unknown>): Promise<string>;
255
+ findings(args: Record<string, unknown>): Promise<string>;
256
+ evalExpression(args: Record<string, unknown>): Promise<string>;
257
+ screenshot(args: Record<string, unknown>): Promise<string>;
258
+ injectCss(args: Record<string, unknown>): Promise<string>;
259
+ close(args: Record<string, unknown>): Promise<string>;
260
+ status(): Promise<string>;
261
+ }
@@ -0,0 +1,238 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MCPToolHandler = void 0;
4
+ exports.getToolDefinitions = getToolDefinitions;
5
+ const commands_1 = require("../cli/commands");
6
+ const session_ops_1 = require("../cli/session-ops");
7
+ const GUIDANCE_PATTERN = /No active session|Browser is not open|Daemon failed to become ready/;
8
+ function getToolDefinitions() {
9
+ return [
10
+ {
11
+ name: 'cssprobe_open',
12
+ description: 'Open a browser session (non-blocking). Required before any inspect/layout/findings call. ' +
13
+ 'Use headed: true when the target page needs a manual login.',
14
+ inputSchema: {
15
+ type: 'object',
16
+ properties: {
17
+ url: { type: 'string', description: 'URL, file:// path, or local HTML file path (default: about:blank)' },
18
+ headed: { type: 'boolean', description: 'show the browser window (default: false)' },
19
+ viewport: { type: 'string', description: 'viewport size as WxH (e.g. 1280x720)' },
20
+ browser: { type: 'string', enum: ['chromium', 'firefox', 'webkit'], description: 'browser engine (default: chromium)' },
21
+ state: { type: 'string', description: 'path to a saved state file (cookies + localStorage)' },
22
+ },
23
+ required: [],
24
+ },
25
+ },
26
+ {
27
+ name: 'cssprobe_inspect',
28
+ description: 'Inspect the runtime CSS of an element: DOM tree, computed styles, layout diagram and ' +
29
+ 'confidence-classified findings in one call.',
30
+ inputSchema: {
31
+ type: 'object',
32
+ properties: {
33
+ selector: { type: 'string', description: 'CSS selector for the root element (e.g. ".sidebar")' },
34
+ depth: { type: 'number', description: 'DOM tree depth (default: auto, max 20)' },
35
+ brief: { type: 'boolean', description: 'compact output: tree sketch + warnings/errors only' },
36
+ },
37
+ required: ['selector'],
38
+ },
39
+ },
40
+ {
41
+ name: 'cssprobe_tree',
42
+ description: 'Show the DOM tree structure under a selector.',
43
+ inputSchema: {
44
+ type: 'object',
45
+ properties: {
46
+ selector: { type: 'string', description: 'CSS selector for the root element' },
47
+ depth: { type: 'number', description: 'tree depth (default: auto, max 20)' },
48
+ },
49
+ required: ['selector'],
50
+ },
51
+ },
52
+ {
53
+ name: 'cssprobe_layout',
54
+ description: 'Show the ASCII layout diagram (element positions and sizes) for a selector.',
55
+ inputSchema: {
56
+ type: 'object',
57
+ properties: {
58
+ selector: { type: 'string', description: 'CSS selector for the root element' },
59
+ },
60
+ required: ['selector'],
61
+ },
62
+ },
63
+ {
64
+ name: 'cssprobe_findings',
65
+ description: 'Show only issues/warnings/errors with confidence levels for a selector.',
66
+ inputSchema: {
67
+ type: 'object',
68
+ properties: {
69
+ selector: { type: 'string', description: 'CSS selector for the root element' },
70
+ },
71
+ required: ['selector'],
72
+ },
73
+ },
74
+ {
75
+ name: 'cssprobe_eval',
76
+ description: 'Evaluate a JavaScript expression in the browser page context and return the result.',
77
+ inputSchema: {
78
+ type: 'object',
79
+ properties: {
80
+ expression: { type: 'string', description: 'JavaScript expression to evaluate' },
81
+ },
82
+ required: ['expression'],
83
+ },
84
+ },
85
+ {
86
+ name: 'cssprobe_screenshot',
87
+ description: 'Take a screenshot of the page and save it as a PNG file; returns the file path.',
88
+ inputSchema: {
89
+ type: 'object',
90
+ properties: {
91
+ full_page: { type: 'boolean', description: 'capture the full scrollable page (default: viewport only)' },
92
+ out: { type: 'string', description: 'output file path (default: ~/.cssprobe-cli/screenshots/<timestamp>.png)' },
93
+ },
94
+ required: [],
95
+ },
96
+ },
97
+ {
98
+ name: 'cssprobe_inject_css',
99
+ description: 'Inject CSS into the current page (useful for live experiments).',
100
+ inputSchema: {
101
+ type: 'object',
102
+ properties: {
103
+ css: { type: 'string', description: 'CSS code to inject' },
104
+ },
105
+ required: ['css'],
106
+ },
107
+ },
108
+ {
109
+ name: 'cssprobe_close',
110
+ description: 'Close the browser session. Pass all: true to close sessions across all workspaces.',
111
+ inputSchema: {
112
+ type: 'object',
113
+ properties: {
114
+ all: { type: 'boolean', description: 'close all sessions across all workspaces' },
115
+ },
116
+ required: [],
117
+ },
118
+ },
119
+ {
120
+ name: 'cssprobe_status',
121
+ description: 'Show the current session status (alive / dead / none).',
122
+ inputSchema: {
123
+ type: 'object',
124
+ properties: {},
125
+ required: [],
126
+ },
127
+ },
128
+ ];
129
+ }
130
+ function toMessage(e) {
131
+ return e instanceof Error ? e.message : String(e);
132
+ }
133
+ class MCPToolHandler {
134
+ async runSession(commandName, parsed) {
135
+ const command = commands_1.commands[commandName];
136
+ if (!command)
137
+ throw new Error(`Unknown command: ${commandName}`);
138
+ try {
139
+ const result = await (0, session_ops_1.runSessionCommand)(commandName, command, parsed);
140
+ if (commandName === 'screenshot' && typeof result.text === 'string' && result.text.startsWith('data:image/png;base64,')) {
141
+ const saved = (0, session_ops_1.saveScreenshotFile)(result.text, parsed.out);
142
+ return `Screenshot saved: ${saved}`;
143
+ }
144
+ return result.text;
145
+ }
146
+ catch (e) {
147
+ const msg = toMessage(e);
148
+ if (GUIDANCE_PATTERN.test(msg))
149
+ return msg;
150
+ throw e;
151
+ }
152
+ }
153
+ async open(args) {
154
+ const opts = {
155
+ url: typeof args.url === 'string' ? args.url : undefined,
156
+ browser: typeof args.browser === 'string' ? args.browser : undefined,
157
+ headed: args.headed === true,
158
+ state: typeof args.state === 'string' ? args.state : undefined,
159
+ };
160
+ if (typeof args.viewport === 'string') {
161
+ const parts = args.viewport.split('x');
162
+ const width = parseInt(parts[0] || '', 10);
163
+ const height = parseInt(parts[1] || '', 10);
164
+ if (parts.length === 2 && !isNaN(width) && !isNaN(height)) {
165
+ opts.viewport = { width, height };
166
+ }
167
+ else {
168
+ return 'Invalid viewport format. Use WxH (e.g. 1280x720).';
169
+ }
170
+ }
171
+ try {
172
+ const result = await (0, session_ops_1.openSession)(opts);
173
+ return [
174
+ `Browser opened at ${result.url}`,
175
+ `Session ID: ${result.sessionId}`,
176
+ `PID: ${result.pid ?? 'unknown'}`,
177
+ `Viewport: ${result.viewport.width}x${result.viewport.height}`,
178
+ ].join('\n');
179
+ }
180
+ catch (e) {
181
+ const msg = toMessage(e);
182
+ if (GUIDANCE_PATTERN.test(msg))
183
+ return msg;
184
+ throw e;
185
+ }
186
+ }
187
+ async inspect(args) {
188
+ return this.runSession('inspect', {
189
+ selector: args.selector,
190
+ depth: args.depth,
191
+ brief: args.brief,
192
+ });
193
+ }
194
+ async tree(args) {
195
+ return this.runSession('tree', { selector: args.selector, depth: args.depth });
196
+ }
197
+ async layout(args) {
198
+ return this.runSession('layout', { selector: args.selector });
199
+ }
200
+ async findings(args) {
201
+ return this.runSession('findings', { selector: args.selector });
202
+ }
203
+ async evalExpression(args) {
204
+ return this.runSession('eval', { expression: args.expression });
205
+ }
206
+ async screenshot(args) {
207
+ return this.runSession('screenshot', { 'full-page': args.full_page, out: args.out });
208
+ }
209
+ async injectCss(args) {
210
+ return this.runSession('inject-css', { css: args.css });
211
+ }
212
+ async close(args) {
213
+ try {
214
+ const result = await (0, session_ops_1.closeSession)(args.all === true);
215
+ return result.sessions
216
+ .map(s => (s.closed ? `Closed: ${s.sessionId}` : `Failed: ${s.sessionId} (${s.error})`))
217
+ .join('\n');
218
+ }
219
+ catch (e) {
220
+ const msg = toMessage(e);
221
+ if (GUIDANCE_PATTERN.test(msg))
222
+ return msg;
223
+ throw e;
224
+ }
225
+ }
226
+ async status() {
227
+ const result = await (0, session_ops_1.getSessionStatus)();
228
+ if (!result.config)
229
+ return 'No active session. Run cssprobe_open to start one.';
230
+ const config = result.config;
231
+ const lines = [`Session: ${result.sessionId}`, `Status: ${result.alive ? 'alive' : 'dead'}`];
232
+ if (result.alive && config.browser?.browserName)
233
+ lines.push(`Browser: ${config.browser.browserName}`);
234
+ return lines.join('\n');
235
+ }
236
+ }
237
+ exports.MCPToolHandler = MCPToolHandler;
238
+ //# sourceMappingURL=tools.js.map
package/llms.txt ADDED
@@ -0,0 +1,15 @@
1
+ # cssprobe-cli
2
+
3
+ > Runtime CSS probe — inspect layout, scroll, colors, backgrounds, fonts in a live browser. Returns DOM tree, ASCII layout diagram and confidence-classified findings for humans and AI agents.
4
+
5
+ ## Documentation
6
+
7
+ - [README](https://raw.githubusercontent.com/mack-peng/cssprobe-cli/main/README.md): overview, quick start, configuration
8
+ - [MCP server usage](https://raw.githubusercontent.com/mack-peng/cssprobe-cli/main/README.md): `cssprobe-cli mcp-install` — native tools for Claude Code / Cursor / Codex / opencode / Gemini / Hermes (10 tools: open, inspect, tree, layout, findings, eval, screenshot, inject_css, close, status)
9
+ - [Installation guide](https://raw.githubusercontent.com/mack-peng/cssprobe-cli/main/docs/guide/installation.md): agent-friendly install and skill wiring (Claude Code, Cursor, Codex, …)
10
+ - [npm package](https://www.npmjs.com/package/cssprobe-cli): `npm install -g cssprobe-cli`
11
+
12
+ ## Optional
13
+
14
+ - [GitHub repository](https://github.com/mack-peng/cssprobe-cli): source code, issues, releases
15
+ - [cssgraph](https://github.com/mack-peng/cssgraph): companion static CSS knowledge graph for AI agents
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "cssprobe-cli",
3
- "version": "0.2.25",
3
+ "version": "0.3.0",
4
+ "mcpName": "io.github.mack-peng/cssprobe-cli",
4
5
  "description": "Runtime CSS probe — inspect layout, colors, backgrounds, fonts and more in a live browser. AI agents and shell automation.",
5
6
  "keywords": [
6
7
  "css",
@@ -30,7 +31,9 @@
30
31
  "docs",
31
32
  "README.md",
32
33
  "LICENSE",
33
- "AGENTS.md"
34
+ "AGENTS.md",
35
+ "CHANGELOG.md",
36
+ "llms.txt"
34
37
  ],
35
38
  "engines": {
36
39
  "node": ">=18"