@chrome-agent-bridge/mcp-server 0.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 (49) hide show
  1. package/dist/__tests__/data-store.property.test.d.ts +2 -0
  2. package/dist/__tests__/data-store.property.test.d.ts.map +1 -0
  3. package/dist/__tests__/data-store.property.test.js +146 -0
  4. package/dist/__tests__/data-store.property.test.js.map +1 -0
  5. package/dist/__tests__/data-store.test.d.ts +2 -0
  6. package/dist/__tests__/data-store.test.d.ts.map +1 -0
  7. package/dist/__tests__/data-store.test.js +163 -0
  8. package/dist/__tests__/data-store.test.js.map +1 -0
  9. package/dist/__tests__/http-server.property.test.d.ts +2 -0
  10. package/dist/__tests__/http-server.property.test.d.ts.map +1 -0
  11. package/dist/__tests__/http-server.property.test.js +173 -0
  12. package/dist/__tests__/http-server.property.test.js.map +1 -0
  13. package/dist/__tests__/http-server.test.d.ts +2 -0
  14. package/dist/__tests__/http-server.test.d.ts.map +1 -0
  15. package/dist/__tests__/http-server.test.js +180 -0
  16. package/dist/__tests__/http-server.test.js.map +1 -0
  17. package/dist/__tests__/mcp-tools.property.test.d.ts +2 -0
  18. package/dist/__tests__/mcp-tools.property.test.d.ts.map +1 -0
  19. package/dist/__tests__/mcp-tools.property.test.js +189 -0
  20. package/dist/__tests__/mcp-tools.property.test.js.map +1 -0
  21. package/dist/__tests__/mcp-tools.test.d.ts +2 -0
  22. package/dist/__tests__/mcp-tools.test.d.ts.map +1 -0
  23. package/dist/__tests__/mcp-tools.test.js +53 -0
  24. package/dist/__tests__/mcp-tools.test.js.map +1 -0
  25. package/dist/__tests__/validator.test.d.ts +2 -0
  26. package/dist/__tests__/validator.test.d.ts.map +1 -0
  27. package/dist/__tests__/validator.test.js +143 -0
  28. package/dist/__tests__/validator.test.js.map +1 -0
  29. package/dist/data-store.d.ts +20 -0
  30. package/dist/data-store.d.ts.map +1 -0
  31. package/dist/data-store.js +59 -0
  32. package/dist/data-store.js.map +1 -0
  33. package/dist/http-server.d.ts +30 -0
  34. package/dist/http-server.d.ts.map +1 -0
  35. package/dist/http-server.js +164 -0
  36. package/dist/http-server.js.map +1 -0
  37. package/dist/index.d.ts +3 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +39 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/mcp-tools.d.ts +8 -0
  42. package/dist/mcp-tools.d.ts.map +1 -0
  43. package/dist/mcp-tools.js +77 -0
  44. package/dist/mcp-tools.js.map +1 -0
  45. package/dist/validator.d.ts +10 -0
  46. package/dist/validator.d.ts.map +1 -0
  47. package/dist/validator.js +68 -0
  48. package/dist/validator.js.map +1 -0
  49. package/package.json +39 -0
@@ -0,0 +1,20 @@
1
+ import type { CapturedElementData, CapturedElementSummary } from '@chrome-agent-bridge/shared';
2
+ export declare class DataStore {
3
+ private items;
4
+ private order;
5
+ private readonly MAX_CAPACITY;
6
+ /**
7
+ * Store captured element data, generating a UUID v4 as unique ID.
8
+ * Evicts the oldest record when capacity exceeds MAX_CAPACITY.
9
+ */
10
+ store(data: CapturedElementData): string;
11
+ /** Get a record by its unique ID. */
12
+ getById(id: string): CapturedElementData | null;
13
+ /** Get the most recently stored record. */
14
+ getLatest(): CapturedElementData | null;
15
+ /** List summaries of all cached records. */
16
+ list(): CapturedElementSummary[];
17
+ /** Clear all cached data. */
18
+ clear(): void;
19
+ }
20
+ //# sourceMappingURL=data-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-store.d.ts","sourceRoot":"","sources":["../src/data-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAE/F,qBAAa,SAAS;IACpB,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAM;IAEnC;;;OAGG;IACH,KAAK,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM;IAgBxC,qCAAqC;IACrC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI;IAI/C,2CAA2C;IAC3C,SAAS,IAAI,mBAAmB,GAAG,IAAI;IAMvC,4CAA4C;IAC5C,IAAI,IAAI,sBAAsB,EAAE;IAgBhC,6BAA6B;IAC7B,KAAK,IAAI,IAAI;CAId"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataStore = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ class DataStore {
6
+ items = new Map();
7
+ order = [];
8
+ MAX_CAPACITY = 20;
9
+ /**
10
+ * Store captured element data, generating a UUID v4 as unique ID.
11
+ * Evicts the oldest record when capacity exceeds MAX_CAPACITY.
12
+ */
13
+ store(data) {
14
+ const id = (0, node_crypto_1.randomUUID)();
15
+ const record = { ...data, id };
16
+ this.items.set(id, record);
17
+ this.order.push(id);
18
+ // Evict oldest records when over capacity
19
+ while (this.order.length > this.MAX_CAPACITY) {
20
+ const oldestId = this.order.shift();
21
+ this.items.delete(oldestId);
22
+ }
23
+ return id;
24
+ }
25
+ /** Get a record by its unique ID. */
26
+ getById(id) {
27
+ return this.items.get(id) ?? null;
28
+ }
29
+ /** Get the most recently stored record. */
30
+ getLatest() {
31
+ if (this.order.length === 0)
32
+ return null;
33
+ const latestId = this.order[this.order.length - 1];
34
+ return this.items.get(latestId) ?? null;
35
+ }
36
+ /** List summaries of all cached records. */
37
+ list() {
38
+ return this.order.map((id) => {
39
+ const item = this.items.get(id);
40
+ return {
41
+ id: item.id,
42
+ timestamp: item.timestamp,
43
+ url: item.url,
44
+ tagName: item.element.tagName,
45
+ classes: item.element.classes,
46
+ text: item.element.text.length > 100
47
+ ? item.element.text.slice(0, 100) + '...'
48
+ : item.element.text,
49
+ };
50
+ });
51
+ }
52
+ /** Clear all cached data. */
53
+ clear() {
54
+ this.items.clear();
55
+ this.order = [];
56
+ }
57
+ }
58
+ exports.DataStore = DataStore;
59
+ //# sourceMappingURL=data-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-store.js","sourceRoot":"","sources":["../src/data-store.ts"],"names":[],"mappings":";;;AAAA,6CAAyC;AAGzC,MAAa,SAAS;IACZ,KAAK,GAAqC,IAAI,GAAG,EAAE,CAAC;IACpD,KAAK,GAAa,EAAE,CAAC;IACZ,YAAY,GAAG,EAAE,CAAC;IAEnC;;;OAGG;IACH,KAAK,CAAC,IAAyB;QAC7B,MAAM,EAAE,GAAG,IAAA,wBAAU,GAAE,CAAC;QACxB,MAAM,MAAM,GAAwB,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC;QAEpD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEpB,0CAA0C;QAC1C,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;YAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAC;YACrC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9B,CAAC;QAED,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,qCAAqC;IACrC,OAAO,CAAC,EAAU;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;IACpC,CAAC;IAED,2CAA2C;IAC3C,SAAS;QACP,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC;IAC1C,CAAC;IAED,4CAA4C;IAC5C,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;YAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC;YACjC,OAAO;gBACL,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;gBAC7B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;gBAC7B,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG;oBAClC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK;oBACzC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI;aACtB,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,6BAA6B;IAC7B,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;IAClB,CAAC;CACF;AA3DD,8BA2DC"}
@@ -0,0 +1,30 @@
1
+ import type { CaptureResponse, CaptureErrorResponse, PingResponse } from '@chrome-agent-bridge/shared';
2
+ import type { DataStore } from './data-store.js';
3
+ export declare class HttpServer {
4
+ private readonly dataStore;
5
+ private server;
6
+ constructor(dataStore: DataStore);
7
+ /**
8
+ * Start the HTTP server listening on localhost at the given port.
9
+ */
10
+ start(port: number): Promise<void>;
11
+ /**
12
+ * Stop the HTTP server.
13
+ */
14
+ stop(): Promise<void>;
15
+ private handleRequest;
16
+ /**
17
+ * Handle GET /ping — health check endpoint.
18
+ */
19
+ handlePing(): PingResponse;
20
+ /**
21
+ * Handle POST /capture — validate and store captured element data.
22
+ */
23
+ handleCapture(body: unknown): {
24
+ status: number;
25
+ body: CaptureResponse | CaptureErrorResponse;
26
+ };
27
+ private readBody;
28
+ private sendJson;
29
+ }
30
+ //# sourceMappingURL=http-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AACvG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AASjD,qBAAa,UAAU;IAGT,OAAO,CAAC,QAAQ,CAAC,SAAS;IAFtC,OAAO,CAAC,MAAM,CAA4B;gBAEb,SAAS,EAAE,SAAS;IAEjD;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBlC;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAarB,OAAO,CAAC,aAAa;IAgCrB;;OAEG;IACH,UAAU,IAAI,YAAY;IAI1B;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,GAAG,oBAAoB,CAAA;KAAE;IAiB9F,OAAO,CAAC,QAAQ;IAgBhB,OAAO,CAAC,QAAQ;CAejB"}
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.HttpServer = void 0;
37
+ const http = __importStar(require("node:http"));
38
+ const validator_js_1 = require("./validator.js");
39
+ const CORS_HEADERS = {
40
+ 'Access-Control-Allow-Origin': '*',
41
+ 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
42
+ 'Access-Control-Allow-Headers': 'Content-Type',
43
+ };
44
+ class HttpServer {
45
+ dataStore;
46
+ server = null;
47
+ constructor(dataStore) {
48
+ this.dataStore = dataStore;
49
+ }
50
+ /**
51
+ * Start the HTTP server listening on localhost at the given port.
52
+ */
53
+ start(port) {
54
+ return new Promise((resolve, reject) => {
55
+ this.server = http.createServer((req, res) => {
56
+ this.handleRequest(req, res);
57
+ });
58
+ this.server.on('error', (err) => {
59
+ reject(err);
60
+ });
61
+ this.server.listen(port, '127.0.0.1', () => {
62
+ resolve();
63
+ });
64
+ });
65
+ }
66
+ /**
67
+ * Stop the HTTP server.
68
+ */
69
+ stop() {
70
+ return new Promise((resolve, reject) => {
71
+ if (!this.server) {
72
+ resolve();
73
+ return;
74
+ }
75
+ this.server.close((err) => {
76
+ if (err)
77
+ reject(err);
78
+ else
79
+ resolve();
80
+ });
81
+ });
82
+ }
83
+ handleRequest(req, res) {
84
+ // Handle CORS preflight
85
+ if (req.method === 'OPTIONS') {
86
+ this.sendJson(res, 204, null);
87
+ return;
88
+ }
89
+ const url = req.url ?? '/';
90
+ if (req.method === 'GET' && url === '/ping') {
91
+ const response = this.handlePing();
92
+ this.sendJson(res, 200, response);
93
+ return;
94
+ }
95
+ if (req.method === 'POST' && url === '/capture') {
96
+ this.readBody(req)
97
+ .then((body) => this.handleCapture(body))
98
+ .then(({ status, body }) => {
99
+ this.sendJson(res, status, body);
100
+ })
101
+ .catch(() => {
102
+ const errorResponse = { success: false, error: 'Invalid JSON' };
103
+ this.sendJson(res, 400, errorResponse);
104
+ });
105
+ return;
106
+ }
107
+ // Unknown route
108
+ this.sendJson(res, 404, { error: 'Not found' });
109
+ }
110
+ /**
111
+ * Handle GET /ping — health check endpoint.
112
+ */
113
+ handlePing() {
114
+ return { status: 'ok', timestamp: Date.now() };
115
+ }
116
+ /**
117
+ * Handle POST /capture — validate and store captured element data.
118
+ */
119
+ handleCapture(body) {
120
+ const validation = (0, validator_js_1.validateCapturedElementData)(body);
121
+ if (!validation.valid) {
122
+ return {
123
+ status: 400,
124
+ body: { success: false, error: validation.errors.join('; ') },
125
+ };
126
+ }
127
+ const id = this.dataStore.store(body);
128
+ return {
129
+ status: 200,
130
+ body: { success: true, id },
131
+ };
132
+ }
133
+ readBody(req) {
134
+ return new Promise((resolve, reject) => {
135
+ const chunks = [];
136
+ req.on('data', (chunk) => chunks.push(chunk));
137
+ req.on('end', () => {
138
+ try {
139
+ const raw = Buffer.concat(chunks).toString('utf-8');
140
+ resolve(JSON.parse(raw));
141
+ }
142
+ catch {
143
+ reject(new Error('Invalid JSON'));
144
+ }
145
+ });
146
+ req.on('error', reject);
147
+ });
148
+ }
149
+ sendJson(res, statusCode, body) {
150
+ for (const [key, value] of Object.entries(CORS_HEADERS)) {
151
+ res.setHeader(key, value);
152
+ }
153
+ if (body === null) {
154
+ res.writeHead(statusCode);
155
+ res.end();
156
+ return;
157
+ }
158
+ res.setHeader('Content-Type', 'application/json');
159
+ res.writeHead(statusCode);
160
+ res.end(JSON.stringify(body));
161
+ }
162
+ }
163
+ exports.HttpServer = HttpServer;
164
+ //# sourceMappingURL=http-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-server.js","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
5
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
6
+ const data_store_js_1 = require("./data-store.js");
7
+ const http_server_js_1 = require("./http-server.js");
8
+ const mcp_tools_js_1 = require("./mcp-tools.js");
9
+ const HTTP_PORT = 19816;
10
+ async function main() {
11
+ // Shared DataStore instance used by both HTTP Server and MCP Tools
12
+ const dataStore = new data_store_js_1.DataStore();
13
+ // Start HTTP Server for receiving data from Chrome Extension
14
+ const httpServer = new http_server_js_1.HttpServer(dataStore);
15
+ try {
16
+ await httpServer.start(HTTP_PORT);
17
+ }
18
+ catch (err) {
19
+ const code = err.code;
20
+ if (code === 'EADDRINUSE') {
21
+ process.stderr.write(`错误: 端口 ${HTTP_PORT} 已被占用,请关闭占用该端口的进程后重试。\n`);
22
+ process.exit(1);
23
+ }
24
+ throw err;
25
+ }
26
+ // Initialize MCP Server with stdio transport
27
+ const mcpServer = new mcp_js_1.McpServer({
28
+ name: 'chrome-agent-bridge',
29
+ version: '0.1.0',
30
+ });
31
+ (0, mcp_tools_js_1.registerTools)(mcpServer, dataStore);
32
+ const transport = new stdio_js_1.StdioServerTransport();
33
+ await mcpServer.connect(transport);
34
+ }
35
+ main().catch((err) => {
36
+ process.stderr.write(`启动失败: ${String(err)}\n`);
37
+ process.exit(1);
38
+ });
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,oEAAoE;AACpE,wEAAiF;AACjF,mDAA4C;AAC5C,qDAA8C;AAC9C,iDAA+C;AAE/C,MAAM,SAAS,GAAG,KAAK,CAAC;AAExB,KAAK,UAAU,IAAI;IACjB,mEAAmE;IACnE,MAAM,SAAS,GAAG,IAAI,yBAAS,EAAE,CAAC;IAElC,6DAA6D;IAC7D,MAAM,UAAU,GAAG,IAAI,2BAAU,CAAC,SAAS,CAAC,CAAC;IAC7C,IAAI,CAAC;QACH,MAAM,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;QACjD,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;YAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,UAAU,SAAS,yBAAyB,CAC7C,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,6CAA6C;IAC7C,MAAM,SAAS,GAAG,IAAI,kBAAS,CAAC;QAC9B,IAAI,EAAE,qBAAqB;QAC3B,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,IAAA,4BAAa,EAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAEpC,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AACrC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { DataStore } from './data-store.js';
3
+ /**
4
+ * Register all MCP tools on the given McpServer instance.
5
+ * Tools read from the shared DataStore.
6
+ */
7
+ export declare function registerTools(server: McpServer, dataStore: DataStore): void;
8
+ //# sourceMappingURL=mcp-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-tools.d.ts","sourceRoot":"","sources":["../src/mcp-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQjD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI,CA2F3E"}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerTools = registerTools;
4
+ const zod_1 = require("zod");
5
+ const NO_DATA_MSG = '当前无已采集的元素数据,请先在浏览器中选择元素';
6
+ function notFoundMsg(id) {
7
+ return `未找到 ID 为 ${id} 的元素数据`;
8
+ }
9
+ /**
10
+ * Register all MCP tools on the given McpServer instance.
11
+ * Tools read from the shared DataStore.
12
+ */
13
+ function registerTools(server, dataStore) {
14
+ // get_selected_element: return full CapturedElementData + screenshot as image
15
+ server.tool('get_selected_element', '获取最近一次或指定 ID 的已采集元素完整信息(HTML、CSS、元数据),同时返回元素截图', { id: zod_1.z.optional(zod_1.z.string()) }, async ({ id }) => {
16
+ const data = id ? dataStore.getById(id) : dataStore.getLatest();
17
+ if (!data) {
18
+ return {
19
+ content: [{ type: 'text', text: id ? notFoundMsg(id) : NO_DATA_MSG }],
20
+ };
21
+ }
22
+ const { screenshot, ...rest } = data;
23
+ const content = [
24
+ { type: 'text', text: JSON.stringify(rest, null, 2) },
25
+ ];
26
+ if (screenshot) {
27
+ content.push({
28
+ type: 'image',
29
+ data: screenshot,
30
+ mimeType: 'image/jpeg',
31
+ });
32
+ }
33
+ return { content };
34
+ });
35
+ // get_element_screenshot: return Base64 JPEG screenshot
36
+ server.tool('get_element_screenshot', '获取最近一次或指定 ID 的元素截图(Base64 JPEG)', { id: zod_1.z.optional(zod_1.z.string()) }, async ({ id }) => {
37
+ const data = id ? dataStore.getById(id) : dataStore.getLatest();
38
+ if (!data) {
39
+ return {
40
+ content: [{ type: 'text', text: id ? notFoundMsg(id) : NO_DATA_MSG }],
41
+ };
42
+ }
43
+ if (!data.screenshot) {
44
+ return {
45
+ content: [{ type: 'text', text: '该元素没有截图数据' }],
46
+ };
47
+ }
48
+ return {
49
+ content: [{ type: 'image', data: data.screenshot, mimeType: 'image/jpeg' }],
50
+ };
51
+ });
52
+ // get_element_styles: return CSS style details
53
+ server.tool('get_element_styles', '获取最近一次或指定 ID 的元素 CSS 样式详情(计算样式和匹配规则)', { id: zod_1.z.optional(zod_1.z.string()) }, async ({ id }) => {
54
+ const data = id ? dataStore.getById(id) : dataStore.getLatest();
55
+ if (!data) {
56
+ return {
57
+ content: [{ type: 'text', text: id ? notFoundMsg(id) : NO_DATA_MSG }],
58
+ };
59
+ }
60
+ return {
61
+ content: [{ type: 'text', text: JSON.stringify(data.styles, null, 2) }],
62
+ };
63
+ });
64
+ // list_captured_elements: return all cached summaries
65
+ server.tool('list_captured_elements', '列出所有已采集元素的摘要列表', async () => {
66
+ const summaries = dataStore.list();
67
+ if (summaries.length === 0) {
68
+ return {
69
+ content: [{ type: 'text', text: NO_DATA_MSG }],
70
+ };
71
+ }
72
+ return {
73
+ content: [{ type: 'text', text: JSON.stringify(summaries, null, 2) }],
74
+ };
75
+ });
76
+ }
77
+ //# sourceMappingURL=mcp-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-tools.js","sourceRoot":"","sources":["../src/mcp-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface ValidationResult {
2
+ valid: boolean;
3
+ errors: string[];
4
+ }
5
+ /**
6
+ * Validate that the given data conforms to the CapturedElementData structure.
7
+ * Returns a validation result with specific error messages for each invalid field.
8
+ */
9
+ export declare function validateCapturedElementData(data: unknown): ValidationResult;
10
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAgE3E"}
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateCapturedElementData = validateCapturedElementData;
4
+ /**
5
+ * Validate that the given data conforms to the CapturedElementData structure.
6
+ * Returns a validation result with specific error messages for each invalid field.
7
+ */
8
+ function validateCapturedElementData(data) {
9
+ const errors = [];
10
+ if (data === null || typeof data !== 'object' || Array.isArray(data)) {
11
+ return { valid: false, errors: ['Data must be a non-null object'] };
12
+ }
13
+ const d = data;
14
+ // Required string fields
15
+ if (typeof d.url !== 'string') {
16
+ errors.push('Missing or invalid field: url (expected string)');
17
+ }
18
+ if (typeof d.title !== 'string') {
19
+ errors.push('Missing or invalid field: title (expected string)');
20
+ }
21
+ // screenshot: string | null
22
+ if (d.screenshot !== null && typeof d.screenshot !== 'string') {
23
+ errors.push('Invalid field: screenshot (expected string or null)');
24
+ }
25
+ // element validation
26
+ if (d.element === null || typeof d.element !== 'object' || Array.isArray(d.element)) {
27
+ errors.push('Missing or invalid field: element (expected object)');
28
+ }
29
+ else {
30
+ const el = d.element;
31
+ if (typeof el.tagName !== 'string') {
32
+ errors.push('Missing or invalid field: element.tagName (expected string)');
33
+ }
34
+ if (typeof el.html !== 'string') {
35
+ errors.push('Missing or invalid field: element.html (expected string)');
36
+ }
37
+ if (typeof el.text !== 'string') {
38
+ errors.push('Missing or invalid field: element.text (expected string)');
39
+ }
40
+ if (!Array.isArray(el.classes) || !el.classes.every((c) => typeof c === 'string')) {
41
+ errors.push('Missing or invalid field: element.classes (expected string[])');
42
+ }
43
+ if (el.id !== null && typeof el.id !== 'string') {
44
+ errors.push('Invalid field: element.id (expected string or null)');
45
+ }
46
+ if (el.attributes === null || typeof el.attributes !== 'object' || Array.isArray(el.attributes)) {
47
+ errors.push('Missing or invalid field: element.attributes (expected object)');
48
+ }
49
+ if (typeof el.domPath !== 'string') {
50
+ errors.push('Missing or invalid field: element.domPath (expected string)');
51
+ }
52
+ }
53
+ // styles validation
54
+ if (d.styles === null || typeof d.styles !== 'object' || Array.isArray(d.styles)) {
55
+ errors.push('Missing or invalid field: styles (expected object)');
56
+ }
57
+ else {
58
+ const st = d.styles;
59
+ if (st.computed === null || typeof st.computed !== 'object' || Array.isArray(st.computed)) {
60
+ errors.push('Missing or invalid field: styles.computed (expected object)');
61
+ }
62
+ if (!Array.isArray(st.matched)) {
63
+ errors.push('Missing or invalid field: styles.matched (expected array)');
64
+ }
65
+ }
66
+ return { valid: errors.length === 0, errors };
67
+ }
68
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@chrome-agent-bridge/mcp-server",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "description": "MCP Server for Chrome-Agent Bridge — capture web elements and expose them to AI Agent IDEs",
6
+ "license": "MIT",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "bin": {
10
+ "chrome-agent-bridge": "dist/index.js"
11
+ },
12
+ "dependencies": {
13
+ "@modelcontextprotocol/sdk": "^1.27.1",
14
+ "zod": "^4.3.6",
15
+ "@chrome-agent-bridge/shared": "0.1.0"
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/user/chrome-agent-bridge",
23
+ "directory": "packages/mcp-server"
24
+ },
25
+ "keywords": [
26
+ "mcp",
27
+ "chrome",
28
+ "agent",
29
+ "cursor",
30
+ "kiro",
31
+ "web-element",
32
+ "capture"
33
+ ],
34
+ "scripts": {
35
+ "build": "tsc",
36
+ "start": "node dist/index.js",
37
+ "test": "vitest --run"
38
+ }
39
+ }