browser-lens-mcp 1.1.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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +341 -0
  3. package/dist/src/index.d.ts +3 -0
  4. package/dist/src/index.d.ts.map +1 -0
  5. package/dist/src/index.js +25 -0
  6. package/dist/src/index.js.map +1 -0
  7. package/dist/src/prompts/index.d.ts +4 -0
  8. package/dist/src/prompts/index.d.ts.map +1 -0
  9. package/dist/src/prompts/index.js +180 -0
  10. package/dist/src/prompts/index.js.map +1 -0
  11. package/dist/src/resources/index.d.ts +4 -0
  12. package/dist/src/resources/index.d.ts.map +1 -0
  13. package/dist/src/resources/index.js +64 -0
  14. package/dist/src/resources/index.js.map +1 -0
  15. package/dist/src/server.d.ts +4 -0
  16. package/dist/src/server.d.ts.map +1 -0
  17. package/dist/src/server.js +15 -0
  18. package/dist/src/server.js.map +1 -0
  19. package/dist/src/store/browser-store.d.ts +45 -0
  20. package/dist/src/store/browser-store.d.ts.map +1 -0
  21. package/dist/src/store/browser-store.js +240 -0
  22. package/dist/src/store/browser-store.js.map +1 -0
  23. package/dist/src/store/types.d.ts +342 -0
  24. package/dist/src/store/types.d.ts.map +1 -0
  25. package/dist/src/store/types.js +3 -0
  26. package/dist/src/store/types.js.map +1 -0
  27. package/dist/src/tools/index.d.ts +4 -0
  28. package/dist/src/tools/index.d.ts.map +1 -0
  29. package/dist/src/tools/index.js +889 -0
  30. package/dist/src/tools/index.js.map +1 -0
  31. package/dist/src/transport/connector-script.d.ts +2 -0
  32. package/dist/src/transport/connector-script.d.ts.map +1 -0
  33. package/dist/src/transport/connector-script.js +336 -0
  34. package/dist/src/transport/connector-script.js.map +1 -0
  35. package/dist/src/transport/http-receiver.d.ts +4 -0
  36. package/dist/src/transport/http-receiver.d.ts.map +1 -0
  37. package/dist/src/transport/http-receiver.js +218 -0
  38. package/dist/src/transport/http-receiver.js.map +1 -0
  39. package/dist/src/transport/ws-receiver.d.ts +4 -0
  40. package/dist/src/transport/ws-receiver.d.ts.map +1 -0
  41. package/dist/src/transport/ws-receiver.js +39 -0
  42. package/dist/src/transport/ws-receiver.js.map +1 -0
  43. package/package.json +79 -0
@@ -0,0 +1,64 @@
1
+ function jsonResource(uri, data) {
2
+ return {
3
+ contents: [
4
+ {
5
+ uri: uri.href,
6
+ mimeType: "application/json",
7
+ text: JSON.stringify(data, null, 2),
8
+ },
9
+ ],
10
+ };
11
+ }
12
+ export function registerResources(server, store) {
13
+ server.resource("dom-snapshot", "dom://snapshot", (uri) => jsonResource(uri, store.getDom() ?? { message: "No DOM data captured yet." }));
14
+ server.resource("dom-elements", "dom://elements", (uri) => {
15
+ const elements = store.getElements();
16
+ return jsonResource(uri, {
17
+ total: Object.keys(elements).length,
18
+ selectors: Object.keys(elements),
19
+ });
20
+ });
21
+ server.resource("css-variables", "css://variables", (uri) => jsonResource(uri, store.getCssVariables() ?? { message: "No CSS variable data captured." }));
22
+ server.resource("css-typography", "css://typography", (uri) => jsonResource(uri, store.getTypography() ?? { message: "No typography data captured." }));
23
+ server.resource("css-colors", "css://colors", (uri) => jsonResource(uri, store.getColors() ?? { message: "No color data captured." }));
24
+ server.resource("layout-responsive", "layout://responsive", (uri) => jsonResource(uri, store.getResponsive() ?? { message: "No responsive data captured." }));
25
+ server.resource("layout-spacing", "layout://spacing", (uri) => jsonResource(uri, store.getSpacing() ?? { message: "No spacing data captured." }));
26
+ server.resource("visual-screenshots", "visual://screenshots", (uri) => {
27
+ const shots = store.getScreenshots();
28
+ return jsonResource(uri, {
29
+ total: shots.length,
30
+ screenshots: shots.map((s, i) => ({
31
+ index: i,
32
+ type: s.type,
33
+ width: s.width,
34
+ height: s.height,
35
+ timestamp: s.timestamp,
36
+ })),
37
+ });
38
+ });
39
+ server.resource("accessibility-info", "a11y://audit", (uri) => jsonResource(uri, store.getAccessibility() ?? {
40
+ message: "No accessibility data captured.",
41
+ }));
42
+ server.resource("mutations-log", "dom://mutations", (uri) => {
43
+ const mutations = store.getMutations();
44
+ return jsonResource(uri, {
45
+ total: mutations.length,
46
+ mutations: mutations.slice(0, 50),
47
+ });
48
+ });
49
+ server.resource("comparison-results", "figma://comparisons", (uri) => {
50
+ const comparisons = store.getComparisons();
51
+ return jsonResource(uri, {
52
+ total: comparisons.length,
53
+ comparisons: comparisons.map((c) => ({
54
+ selector: c.selector,
55
+ score: c.score,
56
+ status: c.status,
57
+ diffCount: c.differences.length,
58
+ timestamp: c.timestamp,
59
+ })),
60
+ });
61
+ });
62
+ server.resource("page-info", "browser://page", (uri) => jsonResource(uri, store.getPageInfo()));
63
+ }
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/resources/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { BrowserStore } from "./store/browser-store.js";
3
+ export declare function createMcpServer(store: BrowserStore): McpServer;
4
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAK7D,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,CAW9D"}
@@ -0,0 +1,15 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { registerResources } from "./resources/index.js";
3
+ import { registerTools } from "./tools/index.js";
4
+ import { registerPrompts } from "./prompts/index.js";
5
+ export function createMcpServer(store) {
6
+ const server = new McpServer({
7
+ name: "mcp-browser-lens",
8
+ version: "1.0.0",
9
+ });
10
+ registerResources(server, store);
11
+ registerTools(server, store);
12
+ registerPrompts(server, store);
13
+ return server;
14
+ }
15
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,UAAU,eAAe,CAAC,KAAmB;IACjD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACjC,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC7B,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAE/B,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,45 @@
1
+ import type { IngestPayload, DOMSnapshot, ElementDetail, ComputedStyleData, LayoutInfo, ScreenshotData, CSSVariablesData, TypographyData, ColorPaletteData, AccessibilityInfo, ResponsiveInfo, DOMMutation, SpacingAnalysis, ComparisonResult, ElementSnapshot, ViewportInfo } from "./types.js";
2
+ export declare class BrowserStore {
3
+ private filePath;
4
+ constructor();
5
+ private read;
6
+ private write;
7
+ private enforce;
8
+ ingest(payload: IngestPayload): void;
9
+ getDom(): DOMSnapshot | null;
10
+ getElement(selector: string): ElementDetail | undefined;
11
+ getElements(): Record<string, ElementDetail>;
12
+ getComputedStyle(selector: string): ComputedStyleData | undefined;
13
+ getLayout(selector: string): LayoutInfo | undefined;
14
+ getScreenshots(): ScreenshotData[];
15
+ getLatestScreenshot(): ScreenshotData | null;
16
+ getCssVariables(): CSSVariablesData | null;
17
+ getTypography(): TypographyData | null;
18
+ getColors(): ColorPaletteData | null;
19
+ getAccessibility(): AccessibilityInfo | null;
20
+ getResponsive(): ResponsiveInfo | null;
21
+ getMutations(since?: number): DOMMutation[];
22
+ getSpacing(): SpacingAnalysis | null;
23
+ getComparisons(): ComparisonResult[];
24
+ addComparison(result: ComparisonResult): void;
25
+ getPageInfo(): {
26
+ url?: string;
27
+ title?: string;
28
+ viewport?: ViewportInfo;
29
+ totalElements: number;
30
+ screenshotCount: number;
31
+ hasDom: boolean;
32
+ hasCssVariables: boolean;
33
+ hasTypography: boolean;
34
+ hasColors: boolean;
35
+ hasAccessibility: boolean;
36
+ hasResponsive: boolean;
37
+ hasSpacing: boolean;
38
+ mutationCount: number;
39
+ comparisonCount: number;
40
+ };
41
+ querySelector(selector: string): ElementSnapshot[];
42
+ clear(): void;
43
+ getElementCount(): number;
44
+ }
45
+ //# sourceMappingURL=browser-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-store.d.ts","sourceRoot":"","sources":["../../../src/store/browser-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,aAAa,EACb,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,YAAY,EACb,MAAM,YAAY,CAAC;AAuCpB,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAS;;IAMzB,OAAO,CAAC,IAAI;IAiBZ,OAAO,CAAC,KAAK;IAUb,OAAO,CAAC,OAAO;IAwBf,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IA4CpC,MAAM,IAAI,WAAW,GAAG,IAAI;IAI5B,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAIvD,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;IAI5C,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAKjE,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAKnD,cAAc,IAAI,cAAc,EAAE;IAIlC,mBAAmB,IAAI,cAAc,GAAG,IAAI;IAK5C,eAAe,IAAI,gBAAgB,GAAG,IAAI;IAI1C,aAAa,IAAI,cAAc,GAAG,IAAI;IAItC,SAAS,IAAI,gBAAgB,GAAG,IAAI;IAIpC,gBAAgB,IAAI,iBAAiB,GAAG,IAAI;IAI5C,aAAa,IAAI,cAAc,GAAG,IAAI;IAItC,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE;IAM3C,UAAU,IAAI,eAAe,GAAG,IAAI;IAIpC,cAAc,IAAI,gBAAgB,EAAE;IAIpC,aAAa,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI;IAO7C,WAAW,IAAI;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,YAAY,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;QACtB,eAAe,EAAE,MAAM,CAAC;QACxB,MAAM,EAAE,OAAO,CAAC;QAChB,eAAe,EAAE,OAAO,CAAC;QACzB,aAAa,EAAE,OAAO,CAAC;QACvB,SAAS,EAAE,OAAO,CAAC;QACnB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,aAAa,EAAE,OAAO,CAAC;QACvB,UAAU,EAAE,OAAO,CAAC;QACpB,aAAa,EAAE,MAAM,CAAC;QACtB,eAAe,EAAE,MAAM,CAAC;KACzB;IAoBD,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,EAAE;IAoBlD,KAAK,IAAI,IAAI;IAIb,eAAe,IAAI,MAAM;CAG1B"}
@@ -0,0 +1,240 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ const __filename = fileURLToPath(import.meta.url);
5
+ const __dirname = path.dirname(__filename);
6
+ const MAX_SCREENSHOTS = 20;
7
+ const MAX_MUTATIONS = 500;
8
+ const MAX_ELEMENTS = 1000;
9
+ const MAX_COMPARISONS = 50;
10
+ function getStoreFilePath() {
11
+ const customPath = process.env.MCP_BROWSER_LENS_STORE_PATH;
12
+ if (customPath)
13
+ return customPath;
14
+ const packageRoot = path.resolve(__dirname, "..", "..", "..");
15
+ const storeDir = path.join(packageRoot, ".store");
16
+ if (!fs.existsSync(storeDir))
17
+ fs.mkdirSync(storeDir, { recursive: true });
18
+ return path.join(storeDir, "browser.json");
19
+ }
20
+ function emptyData() {
21
+ return {
22
+ timestamp: 0,
23
+ url: undefined,
24
+ userAgent: undefined,
25
+ dom: null,
26
+ elements: {},
27
+ styles: {},
28
+ layout: {},
29
+ screenshots: [],
30
+ cssVariables: null,
31
+ typography: null,
32
+ colors: null,
33
+ accessibility: null,
34
+ responsive: null,
35
+ mutations: [],
36
+ spacing: null,
37
+ comparisons: [],
38
+ };
39
+ }
40
+ export class BrowserStore {
41
+ filePath;
42
+ constructor() {
43
+ this.filePath = getStoreFilePath();
44
+ }
45
+ read() {
46
+ try {
47
+ if (!fs.existsSync(this.filePath))
48
+ return emptyData();
49
+ const raw = fs.readFileSync(this.filePath, "utf-8");
50
+ const data = JSON.parse(raw);
51
+ data.elements = data.elements ?? {};
52
+ data.styles = data.styles ?? {};
53
+ data.layout = data.layout ?? {};
54
+ data.screenshots = data.screenshots ?? [];
55
+ data.mutations = data.mutations ?? [];
56
+ data.comparisons = data.comparisons ?? [];
57
+ return data;
58
+ }
59
+ catch {
60
+ return emptyData();
61
+ }
62
+ }
63
+ write(data) {
64
+ try {
65
+ fs.writeFileSync(this.filePath, JSON.stringify(data), "utf-8");
66
+ }
67
+ catch {
68
+ process.stderr.write(`[mcp-browser-lens] Failed to write store: ${this.filePath}\n`);
69
+ }
70
+ }
71
+ enforce(data) {
72
+ if (data.screenshots.length > MAX_SCREENSHOTS) {
73
+ data.screenshots = data.screenshots.slice(-MAX_SCREENSHOTS);
74
+ }
75
+ if (data.mutations.length > MAX_MUTATIONS) {
76
+ data.mutations = data.mutations.slice(-MAX_MUTATIONS);
77
+ }
78
+ const elementKeys = Object.keys(data.elements);
79
+ if (elementKeys.length > MAX_ELEMENTS) {
80
+ const toRemove = elementKeys.slice(0, elementKeys.length - MAX_ELEMENTS);
81
+ for (const key of toRemove) {
82
+ delete data.elements[key];
83
+ delete data.styles[key];
84
+ delete data.layout[key];
85
+ }
86
+ }
87
+ if (data.comparisons.length > MAX_COMPARISONS) {
88
+ data.comparisons = data.comparisons.slice(-MAX_COMPARISONS);
89
+ }
90
+ }
91
+ ingest(payload) {
92
+ const data = this.read();
93
+ data.timestamp = payload.timestamp;
94
+ if (payload.url)
95
+ data.url = payload.url;
96
+ if (payload.userAgent)
97
+ data.userAgent = payload.userAgent;
98
+ if (payload.dom)
99
+ data.dom = payload.dom;
100
+ if (payload.elements) {
101
+ for (const [sel, detail] of Object.entries(payload.elements)) {
102
+ data.elements[sel] = detail;
103
+ }
104
+ }
105
+ if (payload.styles) {
106
+ for (const [sel, style] of Object.entries(payload.styles)) {
107
+ data.styles[sel] = style;
108
+ }
109
+ }
110
+ if (payload.layout) {
111
+ for (const [sel, info] of Object.entries(payload.layout)) {
112
+ data.layout[sel] = info;
113
+ }
114
+ }
115
+ if (payload.screenshots) {
116
+ data.screenshots.push(...payload.screenshots);
117
+ }
118
+ if (payload.cssVariables)
119
+ data.cssVariables = payload.cssVariables;
120
+ if (payload.typography)
121
+ data.typography = payload.typography;
122
+ if (payload.colors)
123
+ data.colors = payload.colors;
124
+ if (payload.accessibility)
125
+ data.accessibility = payload.accessibility;
126
+ if (payload.responsive)
127
+ data.responsive = payload.responsive;
128
+ if (payload.spacing)
129
+ data.spacing = payload.spacing;
130
+ if (payload.mutations) {
131
+ data.mutations.push(...payload.mutations);
132
+ }
133
+ this.enforce(data);
134
+ this.write(data);
135
+ }
136
+ getDom() {
137
+ return this.read().dom;
138
+ }
139
+ getElement(selector) {
140
+ return this.read().elements[selector];
141
+ }
142
+ getElements() {
143
+ return this.read().elements;
144
+ }
145
+ getComputedStyle(selector) {
146
+ const data = this.read();
147
+ return data.styles[selector] ?? data.elements[selector]?.computedStyle;
148
+ }
149
+ getLayout(selector) {
150
+ const data = this.read();
151
+ return data.layout[selector] ?? data.elements[selector]?.layout;
152
+ }
153
+ getScreenshots() {
154
+ return this.read().screenshots;
155
+ }
156
+ getLatestScreenshot() {
157
+ const shots = this.read().screenshots;
158
+ return shots.length > 0 ? shots[shots.length - 1] : null;
159
+ }
160
+ getCssVariables() {
161
+ return this.read().cssVariables;
162
+ }
163
+ getTypography() {
164
+ return this.read().typography;
165
+ }
166
+ getColors() {
167
+ return this.read().colors;
168
+ }
169
+ getAccessibility() {
170
+ return this.read().accessibility;
171
+ }
172
+ getResponsive() {
173
+ return this.read().responsive;
174
+ }
175
+ getMutations(since) {
176
+ let mutations = this.read().mutations;
177
+ if (since)
178
+ mutations = mutations.filter((m) => m.timestamp >= since);
179
+ return mutations.sort((a, b) => b.timestamp - a.timestamp);
180
+ }
181
+ getSpacing() {
182
+ return this.read().spacing;
183
+ }
184
+ getComparisons() {
185
+ return this.read().comparisons;
186
+ }
187
+ addComparison(result) {
188
+ const data = this.read();
189
+ data.comparisons.push(result);
190
+ this.enforce(data);
191
+ this.write(data);
192
+ }
193
+ getPageInfo() {
194
+ const data = this.read();
195
+ return {
196
+ url: data.url,
197
+ title: data.dom?.title,
198
+ viewport: data.dom?.viewport ?? data.responsive?.viewport,
199
+ totalElements: Object.keys(data.elements).length,
200
+ screenshotCount: data.screenshots.length,
201
+ hasDom: !!data.dom,
202
+ hasCssVariables: !!data.cssVariables,
203
+ hasTypography: !!data.typography,
204
+ hasColors: !!data.colors,
205
+ hasAccessibility: !!data.accessibility,
206
+ hasResponsive: !!data.responsive,
207
+ hasSpacing: !!data.spacing,
208
+ mutationCount: data.mutations.length,
209
+ comparisonCount: data.comparisons.length,
210
+ };
211
+ }
212
+ querySelector(selector) {
213
+ const dom = this.read().dom;
214
+ if (!dom)
215
+ return [];
216
+ const results = [];
217
+ const search = (node) => {
218
+ const matches = (selector.startsWith(".") &&
219
+ node.classNames.includes(selector.slice(1))) ||
220
+ (selector.startsWith("#") && node.id === selector.slice(1)) ||
221
+ node.tagName.toLowerCase() === selector.toLowerCase() ||
222
+ node.selector === selector;
223
+ if (matches)
224
+ results.push(node);
225
+ if (node.children) {
226
+ for (const child of node.children)
227
+ search(child);
228
+ }
229
+ };
230
+ search(dom.rootElement);
231
+ return results;
232
+ }
233
+ clear() {
234
+ this.write(emptyData());
235
+ }
236
+ getElementCount() {
237
+ return Object.keys(this.read().elements).length;
238
+ }
239
+ }
240
+ //# sourceMappingURL=browser-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-store.js","sourceRoot":"","sources":["../../../src/store/browser-store.ts"],"names":[],"mappings":"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"}