@page2ai/mcp 0.4.1 → 0.5.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.
- package/CHANGELOG.md +24 -0
- package/dist/bridge/protocol.d.ts +68 -0
- package/dist/bridge/protocol.d.ts.map +1 -0
- package/dist/bridge/protocol.js +6 -0
- package/dist/bridge/protocol.js.map +1 -0
- package/dist/bridge/server.d.ts +24 -0
- package/dist/bridge/server.d.ts.map +1 -0
- package/dist/bridge/server.js +213 -0
- package/dist/bridge/server.js.map +1 -0
- package/dist/index.js +21 -2
- package/dist/index.js.map +1 -1
- package/dist/tools/page-to-markdown.d.ts +9 -2
- package/dist/tools/page-to-markdown.d.ts.map +1 -1
- package/dist/tools/page-to-markdown.js +67 -15
- package/dist/tools/page-to-markdown.js.map +1 -1
- package/manifest.json +2 -2
- package/package.json +3 -1
- package/server.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,30 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
|
|
|
5
5
|
project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html); while the
|
|
6
6
|
major version is `0`, a minor bump may carry breaking changes.
|
|
7
7
|
|
|
8
|
+
## 0.5.0 - 2026-10-22
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Agent Bridge: localhost WebSocket server for the Page2AI browser extension.** When the
|
|
12
|
+
user enables "Agent Bridge" in the extension popup, `page_to_markdown` routes through the
|
|
13
|
+
user's real browser — cookies, JavaScript rendering and extension-quality extraction —
|
|
14
|
+
instead of a cookieless fetch. The bridge binds `127.0.0.1:3025` (override with
|
|
15
|
+
`PAGE2AI_BRIDGE_PORT`), validates the extension's `chrome-extension://` or
|
|
16
|
+
`moz-extension://` Origin, and authenticates with a per-session 32-byte token. Protocol:
|
|
17
|
+
`page2ai-bridge/1`. Skipped on serverless (Vercel, Lambda).
|
|
18
|
+
- **`html` input parameter** (closes #1): pass raw HTML directly instead of fetching a URL.
|
|
19
|
+
Use it when you already have the page HTML from a browser tool; the server converts it
|
|
20
|
+
locally via `htmlToMarkdown` from `@page2ai/core`. Provide either `url` or `html`, not
|
|
21
|
+
both; when both are absent the tool returns an error.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- **3-path routing for `page_to_markdown`:** (1) `html` parameter → local conversion,
|
|
25
|
+
(2) bridge connected → extension, (3) `url` → fetch. When the extension is connected,
|
|
26
|
+
a `url` request goes through the browser automatically; a `url` + `html` request is
|
|
27
|
+
rejected. The fetch path is unchanged from 0.4.1.
|
|
28
|
+
- `ws` added as a production dependency (`^8.22.0`) for the bridge WebSocket server.
|
|
29
|
+
- Tool description updated to mention the bridge and the `html` parameter.
|
|
30
|
+
- MCPB manifest `long_description` updated to mention the bridge.
|
|
31
|
+
|
|
8
32
|
## 0.4.1 - 2026-10-20
|
|
9
33
|
|
|
10
34
|
### Fixed
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export declare const BRIDGE_PROTOCOL = "page2ai-bridge/1";
|
|
2
|
+
export declare const DEFAULT_BRIDGE_PORT = 3025;
|
|
3
|
+
export interface HelloMessage {
|
|
4
|
+
type: 'hello';
|
|
5
|
+
protocol: typeof BRIDGE_PROTOCOL;
|
|
6
|
+
extensionId: string;
|
|
7
|
+
extensionVersion: string;
|
|
8
|
+
}
|
|
9
|
+
export interface PingMessage {
|
|
10
|
+
type: 'ping';
|
|
11
|
+
token: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ConvertResultMessage {
|
|
14
|
+
type: 'result';
|
|
15
|
+
id: string;
|
|
16
|
+
token: string;
|
|
17
|
+
markdown: string;
|
|
18
|
+
title: string;
|
|
19
|
+
url: string;
|
|
20
|
+
charCount: number;
|
|
21
|
+
source: 'extension';
|
|
22
|
+
}
|
|
23
|
+
export interface ConvertErrorMessage {
|
|
24
|
+
type: 'error';
|
|
25
|
+
id: string;
|
|
26
|
+
token: string;
|
|
27
|
+
code: 'TAB_LOAD_FAILED' | 'EXTRACTION_FAILED' | 'TIMEOUT' | 'RESTRICTED_URL';
|
|
28
|
+
message: string;
|
|
29
|
+
}
|
|
30
|
+
export type ExtensionMessage = HelloMessage | PingMessage | ConvertResultMessage | ConvertErrorMessage;
|
|
31
|
+
export interface WelcomeMessage {
|
|
32
|
+
type: 'welcome';
|
|
33
|
+
protocol: typeof BRIDGE_PROTOCOL;
|
|
34
|
+
serverVersion: string;
|
|
35
|
+
token: string;
|
|
36
|
+
}
|
|
37
|
+
export interface ServerErrorMessage {
|
|
38
|
+
type: 'error';
|
|
39
|
+
code: string;
|
|
40
|
+
message: string;
|
|
41
|
+
}
|
|
42
|
+
export interface ConvertRequestMessage {
|
|
43
|
+
type: 'convert';
|
|
44
|
+
id: string;
|
|
45
|
+
url: string;
|
|
46
|
+
options: {
|
|
47
|
+
includeImages: boolean;
|
|
48
|
+
includeFrontmatter: boolean;
|
|
49
|
+
timeoutMs: number;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export interface PongMessage {
|
|
53
|
+
type: 'pong';
|
|
54
|
+
}
|
|
55
|
+
export type ServerMessage = WelcomeMessage | ServerErrorMessage | ConvertRequestMessage | PongMessage;
|
|
56
|
+
export interface BridgeConvertOptions {
|
|
57
|
+
url: string;
|
|
58
|
+
includeImages: boolean;
|
|
59
|
+
includeFrontmatter: boolean;
|
|
60
|
+
timeoutMs: number;
|
|
61
|
+
}
|
|
62
|
+
export interface BridgeConvertResult {
|
|
63
|
+
markdown: string;
|
|
64
|
+
title: string;
|
|
65
|
+
url: string;
|
|
66
|
+
charCount: number;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/bridge/protocol.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,eAAe,qBAAqB,CAAC;AAClD,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAIxC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,OAAO,eAAe,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,QAAQ,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,iBAAiB,GAAG,mBAAmB,GAAG,SAAS,GAAG,gBAAgB,CAAC;IAC7E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,WAAW,GAAG,oBAAoB,GAAG,mBAAmB,CAAC;AAIvG,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,OAAO,eAAe,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE;QACP,aAAa,EAAE,OAAO,CAAC;QACvB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,kBAAkB,GAAG,qBAAqB,GAAG,WAAW,CAAC;AAItG,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Agent Bridge WebSocket protocol types.
|
|
2
|
+
// Transport: JSON text frames over ws://127.0.0.1:PORT.
|
|
3
|
+
// Security model: BrowserTools MCP v2.0 (post GHSA-xvrv-w8pg-f25f).
|
|
4
|
+
export const BRIDGE_PROTOCOL = 'page2ai-bridge/1';
|
|
5
|
+
export const DEFAULT_BRIDGE_PORT = 3025;
|
|
6
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/bridge/protocol.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,wDAAwD;AACxD,oEAAoE;AAEpE,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,CAAC;AAClD,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type BridgeConvertOptions, type BridgeConvertResult } from './protocol.js';
|
|
2
|
+
export declare class BridgeServer {
|
|
3
|
+
private httpServer;
|
|
4
|
+
private wss;
|
|
5
|
+
private client;
|
|
6
|
+
private sessionToken;
|
|
7
|
+
private pending;
|
|
8
|
+
private requestCounter;
|
|
9
|
+
private readonly port;
|
|
10
|
+
private readonly serverVersion;
|
|
11
|
+
private readonly log;
|
|
12
|
+
constructor(opts: {
|
|
13
|
+
port?: number;
|
|
14
|
+
serverVersion: string;
|
|
15
|
+
log: (msg: string) => void;
|
|
16
|
+
});
|
|
17
|
+
isConnected(): boolean;
|
|
18
|
+
start(): Promise<void>;
|
|
19
|
+
stop(): Promise<void>;
|
|
20
|
+
convert(opts: BridgeConvertOptions): Promise<BridgeConvertResult>;
|
|
21
|
+
private verifyUpgrade;
|
|
22
|
+
private handleConnection;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/bridge/server.ts"],"names":[],"mappings":"AAaA,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EAMzB,MAAM,eAAe,CAAC;AAQvB,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,GAAG,CAAgC;IAC3C,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAwB;gBAEhC,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE;IAMtF,WAAW,IAAI,OAAO;IAIhB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA6BtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBrB,OAAO,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA4BvE,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,gBAAgB;CAyGzB"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// Agent Bridge: localhost-only WebSocket server that connects @page2ai/mcp
|
|
2
|
+
// to the Page2AI browser extension for extraction through the user's real
|
|
3
|
+
// browser (cookies, JS rendering, extension-quality Markdown).
|
|
4
|
+
//
|
|
5
|
+
// Security model (BrowserTools MCP v2.0, post GHSA-xvrv-w8pg-f25f):
|
|
6
|
+
// 1. Bind 127.0.0.1 only (never 0.0.0.0)
|
|
7
|
+
// 2. Origin validation: accept chrome-extension:// and moz-extension:// only
|
|
8
|
+
// 3. Host header: must be 127.0.0.1:PORT or localhost:PORT
|
|
9
|
+
// 4. Per-session token: generated on auth, required on every message
|
|
10
|
+
import { createServer } from 'node:http';
|
|
11
|
+
import { randomBytes } from 'node:crypto';
|
|
12
|
+
import { WebSocketServer, WebSocket } from 'ws';
|
|
13
|
+
import { BRIDGE_PROTOCOL, DEFAULT_BRIDGE_PORT, } from './protocol.js';
|
|
14
|
+
export class BridgeServer {
|
|
15
|
+
httpServer = null;
|
|
16
|
+
wss = null;
|
|
17
|
+
client = null;
|
|
18
|
+
sessionToken = null;
|
|
19
|
+
pending = new Map();
|
|
20
|
+
requestCounter = 0;
|
|
21
|
+
port;
|
|
22
|
+
serverVersion;
|
|
23
|
+
log;
|
|
24
|
+
constructor(opts) {
|
|
25
|
+
this.port = opts.port ?? DEFAULT_BRIDGE_PORT;
|
|
26
|
+
this.serverVersion = opts.serverVersion;
|
|
27
|
+
this.log = opts.log;
|
|
28
|
+
}
|
|
29
|
+
isConnected() {
|
|
30
|
+
return this.client !== null && this.client.readyState === WebSocket.OPEN;
|
|
31
|
+
}
|
|
32
|
+
async start() {
|
|
33
|
+
this.httpServer = createServer((_req, res) => {
|
|
34
|
+
res.writeHead(426, { 'Content-Type': 'text/plain' });
|
|
35
|
+
res.end('WebSocket upgrade required');
|
|
36
|
+
});
|
|
37
|
+
this.wss = new WebSocketServer({
|
|
38
|
+
server: this.httpServer,
|
|
39
|
+
verifyClient: (info, cb) => {
|
|
40
|
+
const allowed = this.verifyUpgrade(info.req);
|
|
41
|
+
if (!allowed) {
|
|
42
|
+
cb(false, 403, 'Forbidden');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
cb(true);
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
this.wss.on('connection', (ws, req) => this.handleConnection(ws, req));
|
|
49
|
+
await new Promise((resolve, reject) => {
|
|
50
|
+
this.httpServer.on('error', reject);
|
|
51
|
+
this.httpServer.listen(this.port, '127.0.0.1', () => {
|
|
52
|
+
this.log(`bridge listening on ws://127.0.0.1:${this.port}`);
|
|
53
|
+
resolve();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async stop() {
|
|
58
|
+
for (const [id, req] of this.pending) {
|
|
59
|
+
clearTimeout(req.timer);
|
|
60
|
+
req.reject(new Error('Bridge shutting down'));
|
|
61
|
+
this.pending.delete(id);
|
|
62
|
+
}
|
|
63
|
+
this.client?.close();
|
|
64
|
+
this.client = null;
|
|
65
|
+
this.sessionToken = null;
|
|
66
|
+
if (this.wss) {
|
|
67
|
+
this.wss.close();
|
|
68
|
+
this.wss = null;
|
|
69
|
+
}
|
|
70
|
+
if (this.httpServer) {
|
|
71
|
+
await new Promise((resolve) => {
|
|
72
|
+
this.httpServer.close(() => resolve());
|
|
73
|
+
});
|
|
74
|
+
this.httpServer = null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async convert(opts) {
|
|
78
|
+
if (!this.isConnected()) {
|
|
79
|
+
throw new Error('Extension not connected');
|
|
80
|
+
}
|
|
81
|
+
const id = `req_${Date.now()}_${++this.requestCounter}`;
|
|
82
|
+
const msg = {
|
|
83
|
+
type: 'convert',
|
|
84
|
+
id,
|
|
85
|
+
url: opts.url,
|
|
86
|
+
options: {
|
|
87
|
+
includeImages: opts.includeImages,
|
|
88
|
+
includeFrontmatter: opts.includeFrontmatter,
|
|
89
|
+
timeoutMs: opts.timeoutMs,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
return new Promise((resolve, reject) => {
|
|
93
|
+
const timer = setTimeout(() => {
|
|
94
|
+
this.pending.delete(id);
|
|
95
|
+
reject(new Error(`Bridge request timed out after ${opts.timeoutMs}ms`));
|
|
96
|
+
}, opts.timeoutMs + 5000);
|
|
97
|
+
this.pending.set(id, { resolve, reject, timer });
|
|
98
|
+
this.client.send(JSON.stringify(msg));
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
verifyUpgrade(req) {
|
|
102
|
+
const origin = req.headers.origin ?? '';
|
|
103
|
+
if (!origin.startsWith('chrome-extension://') && !origin.startsWith('moz-extension://')) {
|
|
104
|
+
this.log(`bridge: rejected Origin "${origin}"`);
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
const host = req.headers.host ?? '';
|
|
108
|
+
const allowed = [`127.0.0.1:${this.port}`, `localhost:${this.port}`];
|
|
109
|
+
if (!allowed.includes(host)) {
|
|
110
|
+
this.log(`bridge: rejected Host "${host}"`);
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
handleConnection(ws, _req) {
|
|
116
|
+
if (this.client && this.client.readyState === WebSocket.OPEN) {
|
|
117
|
+
const err = {
|
|
118
|
+
type: 'error',
|
|
119
|
+
code: 'ALREADY_CONNECTED',
|
|
120
|
+
message: 'Another extension is already connected',
|
|
121
|
+
};
|
|
122
|
+
ws.send(JSON.stringify(err));
|
|
123
|
+
ws.close();
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
let authenticated = false;
|
|
127
|
+
const authTimeout = setTimeout(() => {
|
|
128
|
+
if (!authenticated) {
|
|
129
|
+
ws.close();
|
|
130
|
+
}
|
|
131
|
+
}, 5000);
|
|
132
|
+
ws.on('message', (data) => {
|
|
133
|
+
let msg;
|
|
134
|
+
try {
|
|
135
|
+
msg = JSON.parse(String(data));
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
ws.close();
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (!authenticated) {
|
|
142
|
+
if (msg.type === 'hello' && msg.protocol === BRIDGE_PROTOCOL) {
|
|
143
|
+
clearTimeout(authTimeout);
|
|
144
|
+
authenticated = true;
|
|
145
|
+
this.sessionToken = randomBytes(32).toString('hex');
|
|
146
|
+
this.client = ws;
|
|
147
|
+
const welcome = {
|
|
148
|
+
type: 'welcome',
|
|
149
|
+
protocol: BRIDGE_PROTOCOL,
|
|
150
|
+
serverVersion: this.serverVersion,
|
|
151
|
+
token: this.sessionToken,
|
|
152
|
+
};
|
|
153
|
+
ws.send(JSON.stringify(welcome));
|
|
154
|
+
this.log(`bridge: extension connected (${msg.extensionId} v${msg.extensionVersion})`);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
const err = {
|
|
158
|
+
type: 'error',
|
|
159
|
+
code: 'AUTH_FAILED',
|
|
160
|
+
message: `Expected hello with protocol ${BRIDGE_PROTOCOL}`,
|
|
161
|
+
};
|
|
162
|
+
ws.send(JSON.stringify(err));
|
|
163
|
+
ws.close();
|
|
164
|
+
}
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (!('token' in msg) || msg.token !== this.sessionToken) {
|
|
168
|
+
ws.close();
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (msg.type === 'ping') {
|
|
172
|
+
const pong = { type: 'pong' };
|
|
173
|
+
ws.send(JSON.stringify(pong));
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (msg.type === 'result' && 'id' in msg) {
|
|
177
|
+
const pending = this.pending.get(msg.id);
|
|
178
|
+
if (pending) {
|
|
179
|
+
clearTimeout(pending.timer);
|
|
180
|
+
this.pending.delete(msg.id);
|
|
181
|
+
pending.resolve({
|
|
182
|
+
markdown: msg.markdown,
|
|
183
|
+
title: msg.title,
|
|
184
|
+
url: msg.url,
|
|
185
|
+
charCount: msg.charCount,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (msg.type === 'error' && 'id' in msg && msg.id) {
|
|
191
|
+
const pending = this.pending.get(msg.id);
|
|
192
|
+
if (pending) {
|
|
193
|
+
clearTimeout(pending.timer);
|
|
194
|
+
this.pending.delete(msg.id);
|
|
195
|
+
pending.reject(new Error(`${msg.code}: ${msg.message}`));
|
|
196
|
+
}
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
ws.on('close', () => {
|
|
201
|
+
clearTimeout(authTimeout);
|
|
202
|
+
if (this.client === ws) {
|
|
203
|
+
this.client = null;
|
|
204
|
+
this.sessionToken = null;
|
|
205
|
+
this.log('bridge: extension disconnected');
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
ws.on('error', (err) => {
|
|
209
|
+
this.log(`bridge: ws error: ${err.message}`);
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/bridge/server.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,9 @@ import { readFileSync } from 'node:fs';
|
|
|
15
15
|
import { fileURLToPath } from 'node:url';
|
|
16
16
|
import { serveStdio } from '@modelcontextprotocol/server/stdio';
|
|
17
17
|
import { Server } from '@modelcontextprotocol/server';
|
|
18
|
-
import { handlePageToMarkdown, pageToMarkdownDefinition } from './tools/page-to-markdown.js';
|
|
18
|
+
import { handlePageToMarkdown, pageToMarkdownDefinition, setBridge } from './tools/page-to-markdown.js';
|
|
19
|
+
import { BridgeServer } from './bridge/server.js';
|
|
20
|
+
import { DEFAULT_BRIDGE_PORT } from './bridge/protocol.js';
|
|
19
21
|
const SERVER_NAME = 'page2ai-mcp';
|
|
20
22
|
// Read the version from package.json instead of restating it here.
|
|
21
23
|
//
|
|
@@ -79,10 +81,27 @@ const handle = serveStdio(buildServer, {
|
|
|
79
81
|
legacy: 'serve',
|
|
80
82
|
onerror: (err) => log(`transport error: ${err.message}`),
|
|
81
83
|
});
|
|
84
|
+
// --- Agent Bridge: localhost WS for the Page2AI browser extension ---
|
|
85
|
+
// Starts only in local mode (not on Vercel/serverless). The extension connects
|
|
86
|
+
// when the user enables "Agent Bridge" in its popup. When connected, the
|
|
87
|
+
// page_to_markdown tool routes through the user's real browser.
|
|
88
|
+
const isServerless = !!(process.env.VERCEL || process.env.AWS_LAMBDA_FUNCTION_NAME);
|
|
89
|
+
let bridge = null;
|
|
90
|
+
if (!isServerless) {
|
|
91
|
+
const bridgePort = parseInt(process.env.PAGE2AI_BRIDGE_PORT ?? '', 10) || DEFAULT_BRIDGE_PORT;
|
|
92
|
+
bridge = new BridgeServer({ port: bridgePort, serverVersion: SERVER_VERSION, log });
|
|
93
|
+
setBridge(bridge);
|
|
94
|
+
bridge.start().then(() => log(`bridge ready on ws://127.0.0.1:${bridgePort}`), (err) => {
|
|
95
|
+
log(`bridge failed to start: ${err instanceof Error ? err.message : String(err)} (the server continues without it)`);
|
|
96
|
+
bridge = null;
|
|
97
|
+
setBridge(null);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
82
100
|
log(`server ${SERVER_VERSION} ready on stdio (tools: page_to_markdown)`);
|
|
83
101
|
const shutdown = (signal) => {
|
|
84
102
|
log(`${signal} received, closing`);
|
|
85
|
-
|
|
103
|
+
const bridgeStop = bridge ? bridge.stop() : Promise.resolve();
|
|
104
|
+
Promise.all([handle.close(), bridgeStop]).then(() => process.exit(0), (err) => {
|
|
86
105
|
log(`close failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
87
106
|
process.exit(1);
|
|
88
107
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,yCAAyC;AACzC,+EAA+E;AAC/E,4EAA4E;AAC5E,2EAA2E;AAC3E,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,gFAAgF;AAChF,+EAA+E;AAC/E,8EAA8E;AAC9E,2EAA2E;AAC3E,qEAAqE;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { CallToolResult } from '@modelcontextprotocol/server';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import type { BridgeServer } from '../bridge/server.js';
|
|
3
4
|
export declare const pageToMarkdownInputSchema: z.ZodObject<{
|
|
4
|
-
url: z.ZodString
|
|
5
|
+
url: z.ZodOptional<z.ZodString>;
|
|
6
|
+
html: z.ZodOptional<z.ZodString>;
|
|
5
7
|
include_images: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
6
8
|
include_frontmatter: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
7
9
|
timeout_ms: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
@@ -20,6 +22,11 @@ export declare const pageToMarkdownDefinition: {
|
|
|
20
22
|
format: string;
|
|
21
23
|
description: string;
|
|
22
24
|
};
|
|
25
|
+
html: {
|
|
26
|
+
type: "string";
|
|
27
|
+
maxLength: number;
|
|
28
|
+
description: string;
|
|
29
|
+
};
|
|
23
30
|
include_images: {
|
|
24
31
|
type: "boolean";
|
|
25
32
|
default: boolean;
|
|
@@ -38,7 +45,6 @@ export declare const pageToMarkdownDefinition: {
|
|
|
38
45
|
description: string;
|
|
39
46
|
};
|
|
40
47
|
};
|
|
41
|
-
required: string[];
|
|
42
48
|
additionalProperties: boolean;
|
|
43
49
|
};
|
|
44
50
|
annotations: {
|
|
@@ -48,5 +54,6 @@ export declare const pageToMarkdownDefinition: {
|
|
|
48
54
|
destructiveHint: boolean;
|
|
49
55
|
};
|
|
50
56
|
};
|
|
57
|
+
export declare const setBridge: (bridge: BridgeServer | null) => void;
|
|
51
58
|
export declare const handlePageToMarkdown: (rawInput: unknown) => Promise<PageToMarkdownResult>;
|
|
52
59
|
//# sourceMappingURL=page-to-markdown.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-to-markdown.d.ts","sourceRoot":"","sources":["../../src/tools/page-to-markdown.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"page-to-markdown.d.ts","sourceRoot":"","sources":["../../src/tools/page-to-markdown.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,eAAO,MAAM,yBAAyB;;;;;;iBAsBpC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAG5E,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC;AAElD,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwDpC,CAAC;AAWF,eAAO,MAAM,SAAS,GAAI,QAAQ,YAAY,GAAG,IAAI,KAAG,IAEvD,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,UAAU,OAAO,KAChB,OAAO,CAAC,oBAAoB,CAyE9B,CAAC"}
|
|
@@ -3,27 +3,33 @@
|
|
|
3
3
|
// 15s AbortController timeout, the page-only fetch (no `.md` twin, a browser's
|
|
4
4
|
// Accept header; core 0.2.0, BL-49), and static tab discovery (emits
|
|
5
5
|
// `### Tab: {label}` sections for docs sites).
|
|
6
|
-
import { fetchAndConvert, SsrfBlockedError, FetchProtectionError } from '@page2ai/core';
|
|
6
|
+
import { fetchAndConvert, htmlToMarkdown, SsrfBlockedError, FetchProtectionError } from '@page2ai/core';
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
export const pageToMarkdownInputSchema = z.object({
|
|
9
|
-
url: z.string().url().describe('Absolute HTTP or HTTPS URL of the web page to convert. Blocks private ranges, loopback, and cloud metadata endpoints.'),
|
|
9
|
+
url: z.string().url().optional().describe('Absolute HTTP or HTTPS URL of the web page to convert. Blocks private ranges, loopback, and cloud metadata endpoints. Provide either `url` or `html`, not both.'),
|
|
10
|
+
html: z.string().max(10_000_000).optional().describe('Raw HTML string to convert to Markdown instead of fetching a URL. ' +
|
|
11
|
+
'Use this when you already have the page HTML from a browser tool. ' +
|
|
12
|
+
'Provide either `url` or `html`, not both. When both are absent, returns an error.'),
|
|
10
13
|
include_images: z.boolean().optional().default(true).describe('Include image references () in the output. Default: true.'),
|
|
11
14
|
include_frontmatter: z.boolean().optional().default(true).describe('Prepend a YAML frontmatter block with title, source URL, capture timestamp, language, description, and canonical URL. Default: true.'),
|
|
12
15
|
timeout_ms: z.number().int().min(1000).max(60000).optional().default(15000).describe('Abort the fetch after N milliseconds. Range: 1000-60000. Default: 15000.'),
|
|
16
|
+
}).refine((data) => data.url || data.html, {
|
|
17
|
+
message: 'Provide either `url` or `html`.',
|
|
18
|
+
}).refine((data) => !(data.url && data.html), {
|
|
19
|
+
message: 'Provide either `url` or `html`, not both.',
|
|
13
20
|
});
|
|
14
21
|
export const pageToMarkdownDefinition = {
|
|
15
22
|
name: 'page_to_markdown',
|
|
16
23
|
title: 'Convert Page to Markdown',
|
|
17
|
-
description: '
|
|
24
|
+
description: 'Convert a web page to clean Markdown optimized for LLM context. ' +
|
|
25
|
+
'Provide a `url` to fetch, or `html` if you already have the page HTML from a browser tool. ' +
|
|
26
|
+
'When the Page2AI browser extension is connected via Agent Bridge, the extension converts ' +
|
|
27
|
+
'the page in the user\'s real browser (with cookies and JavaScript) and returns extension-quality Markdown. ' +
|
|
28
|
+
'Without the bridge, `url` fetches without cookies and runs no page scripts, so a page behind ' +
|
|
29
|
+
'a sign-in comes back as its login page; read those through a browser tool and pass the HTML here. ' +
|
|
18
30
|
'Preserves headings, code blocks (with language hints), links, and tables; keeps the ' +
|
|
19
|
-
'main content and drops navigation, headers, footers, and sidebars.
|
|
20
|
-
'
|
|
21
|
-
'JavaScript comes back as its login page or with no content; read those through a browser ' +
|
|
22
|
-
'tool instead. It requests only the URL given, as a browser opens a page, so docs sites ' +
|
|
23
|
-
'return the page itself, not a Markdown copy of it; a URL that names a Markdown or text ' +
|
|
24
|
-
'file (a raw GitHub README.md, an llms.txt) comes back as written. ' +
|
|
25
|
-
'Discovers tab groups statically and emits each panel as a `### Tab: {label}` section ' +
|
|
26
|
-
'instead of concatenating (prevents Python+TypeScript examples merging into one broken block). ' +
|
|
31
|
+
'main content and drops navigation, headers, footers, and sidebars. ' +
|
|
32
|
+
'Discovers tab groups statically and emits each panel as a `### Tab: {label}` section. ' +
|
|
27
33
|
'Zero external API calls — parses locally via linkedom.',
|
|
28
34
|
inputSchema: {
|
|
29
35
|
type: 'object',
|
|
@@ -31,7 +37,12 @@ export const pageToMarkdownDefinition = {
|
|
|
31
37
|
url: {
|
|
32
38
|
type: 'string',
|
|
33
39
|
format: 'uri',
|
|
34
|
-
description: 'Absolute HTTP or HTTPS URL of the web page to convert. Blocks private ranges, loopback, and cloud metadata endpoints.',
|
|
40
|
+
description: 'Absolute HTTP or HTTPS URL of the web page to convert. Blocks private ranges, loopback, and cloud metadata endpoints. Provide either `url` or `html`.',
|
|
41
|
+
},
|
|
42
|
+
html: {
|
|
43
|
+
type: 'string',
|
|
44
|
+
maxLength: 10_000_000,
|
|
45
|
+
description: 'Raw HTML string to convert to Markdown instead of fetching a URL. Use this when you already have the page HTML from a browser tool. Provide either `url` or `html`, not both.',
|
|
35
46
|
},
|
|
36
47
|
include_images: {
|
|
37
48
|
type: 'boolean',
|
|
@@ -51,7 +62,6 @@ export const pageToMarkdownDefinition = {
|
|
|
51
62
|
description: 'Abort the fetch after N milliseconds. Range: 1000-60000.',
|
|
52
63
|
},
|
|
53
64
|
},
|
|
54
|
-
required: ['url'],
|
|
55
65
|
additionalProperties: false,
|
|
56
66
|
},
|
|
57
67
|
annotations: {
|
|
@@ -67,6 +77,10 @@ const errorResult = (message) => ({
|
|
|
67
77
|
isError: true,
|
|
68
78
|
content: [{ type: 'text', text: message }],
|
|
69
79
|
});
|
|
80
|
+
let bridgeRef = null;
|
|
81
|
+
export const setBridge = (bridge) => {
|
|
82
|
+
bridgeRef = bridge;
|
|
83
|
+
};
|
|
70
84
|
export const handlePageToMarkdown = async (rawInput) => {
|
|
71
85
|
let input;
|
|
72
86
|
try {
|
|
@@ -79,8 +93,46 @@ export const handlePageToMarkdown = async (rawInput) => {
|
|
|
79
93
|
: String(e);
|
|
80
94
|
return errorResult(`Invalid input: ${msg}`);
|
|
81
95
|
}
|
|
96
|
+
// --- Path 1: raw HTML provided → convert locally via htmlToMarkdown (mcp#1) ---
|
|
97
|
+
if (input.html) {
|
|
98
|
+
try {
|
|
99
|
+
const result = htmlToMarkdown(input.html, {
|
|
100
|
+
baseUrl: input.url,
|
|
101
|
+
includeImages: input.include_images,
|
|
102
|
+
includeFrontmatter: input.include_frontmatter,
|
|
103
|
+
});
|
|
104
|
+
return {
|
|
105
|
+
content: [{ type: 'text', text: result.markdown }],
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
110
|
+
return errorResult(`HTML conversion failed: ${msg}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// url is guaranteed present here by the schema refinement (url || html required).
|
|
114
|
+
const url = input.url;
|
|
115
|
+
// --- Path 2: extension bridge connected → route through the user's browser ---
|
|
116
|
+
if (bridgeRef?.isConnected()) {
|
|
117
|
+
try {
|
|
118
|
+
const result = await bridgeRef.convert({
|
|
119
|
+
url,
|
|
120
|
+
includeImages: input.include_images,
|
|
121
|
+
includeFrontmatter: input.include_frontmatter,
|
|
122
|
+
timeoutMs: input.timeout_ms,
|
|
123
|
+
});
|
|
124
|
+
return {
|
|
125
|
+
content: [{ type: 'text', text: result.markdown }],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
130
|
+
return errorResult(`Bridge conversion failed: ${msg}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// --- Path 3: fetch + linkedom (current behavior) ---
|
|
82
134
|
try {
|
|
83
|
-
const result = await fetchAndConvert(
|
|
135
|
+
const result = await fetchAndConvert(url, {
|
|
84
136
|
timeoutMs: input.timeout_ms,
|
|
85
137
|
includeImages: input.include_images,
|
|
86
138
|
includeFrontmatter: input.include_frontmatter,
|
|
@@ -97,7 +149,7 @@ export const handlePageToMarkdown = async (rawInput) => {
|
|
|
97
149
|
return errorResult(`Fetch failed: ${e.message}`);
|
|
98
150
|
}
|
|
99
151
|
if (e instanceof Error && e.name === 'AbortError') {
|
|
100
|
-
return errorResult(`Fetch timed out after ${input.timeout_ms}ms: ${
|
|
152
|
+
return errorResult(`Fetch timed out after ${input.timeout_ms}ms: ${url}`);
|
|
101
153
|
}
|
|
102
154
|
const msg = e instanceof Error ? e.message : String(e);
|
|
103
155
|
return errorResult(`Unexpected error: ${msg}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-to-markdown.js","sourceRoot":"","sources":["../../src/tools/page-to-markdown.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,+EAA+E;AAC/E,+EAA+E;AAC/E,qEAAqE;AACrE,+CAA+C;AAE/C,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"page-to-markdown.js","sourceRoot":"","sources":["../../src/tools/page-to-markdown.ts"],"names":[],"mappings":"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"}
|
package/manifest.json
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"manifest_version": "0.3",
|
|
3
3
|
"name": "page2ai-mcp",
|
|
4
4
|
"display_name": "Page2AI — Web to Markdown",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.5.0",
|
|
6
6
|
"description": "Convert any web page to clean Markdown for LLM context",
|
|
7
|
-
"long_description": "Page2AI MCP converts a web page URL to Markdown for AI context windows. It keeps the page's main content (its <main> or dominant <article>), preserves code blocks with language hints, converts tables and lists, and drops navigation, headers, footers and sidebars. The only network requests go to the URL you pass it and the addresses it redirects to, asked for as a browser opens a page, so docs platforms return the page itself rather than a Markdown copy of it: pure Node + linkedom, no
|
|
7
|
+
"long_description": "Page2AI MCP converts a web page URL to Markdown for AI context windows. It keeps the page's main content (its <main> or dominant <article>), preserves code blocks with language hints, converts tables and lists, and drops navigation, headers, footers and sidebars. The only network requests go to the URL you pass it and the addresses it redirects to, asked for as a browser opens a page, so docs platforms return the page itself rather than a Markdown copy of it: pure Node + linkedom, no external services, no telemetry.\n\nAgent Bridge: when the Page2AI browser extension is connected, the tool routes through the user's real browser — cookies, JavaScript rendering, extension-quality extraction — so pages behind a sign-in and JS-rendered content are within reach. Without the bridge, a page behind a sign-in or rendered only by JavaScript is out of the tool's reach; pass its HTML directly via the `html` parameter.\n\nCompanion to the Page2AI browser extension (https://github.com/igorsaevets/page2ai-extension), which converts the live page in your own browser, including pages behind a sign-in. Built on the open-source @page2ai/core library.",
|
|
8
8
|
"author": {
|
|
9
9
|
"name": "Igor Saevets",
|
|
10
10
|
"url": "https://github.com/igorsaevets"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@page2ai/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"mcpName": "io.github.igorsaevets/page2ai-mcp",
|
|
5
5
|
"description": "MCP server that converts any web page URL to clean Markdown for LLM context. Processing is local and SSRF-guarded; no external APIs, no telemetry.",
|
|
6
6
|
"type": "module",
|
|
@@ -36,10 +36,12 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@modelcontextprotocol/server": "^2.0.0",
|
|
38
38
|
"@page2ai/core": "^0.3.1",
|
|
39
|
+
"ws": "^8.22.0",
|
|
39
40
|
"zod": "^4.2.0"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
42
43
|
"@types/node": "^26.2.0",
|
|
44
|
+
"@types/ws": "^8.18.2",
|
|
43
45
|
"typescript": "^5.7.2",
|
|
44
46
|
"vitest": "^5.0.5"
|
|
45
47
|
},
|
package/server.json
CHANGED
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
10
|
"websiteUrl": "https://github.com/igorsaevets/page2ai-mcp#readme",
|
|
11
|
-
"version": "0.
|
|
11
|
+
"version": "0.5.0",
|
|
12
12
|
"packages": [
|
|
13
13
|
{
|
|
14
14
|
"registryType": "npm",
|
|
15
15
|
"identifier": "@page2ai/mcp",
|
|
16
|
-
"version": "0.
|
|
16
|
+
"version": "0.5.0",
|
|
17
17
|
"transport": {
|
|
18
18
|
"type": "stdio"
|
|
19
19
|
}
|