@pecot/visual-mcp 1.0.0 → 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.
@@ -22,7 +22,7 @@ import { readSlidesTitle } from './dom-converter.js';
22
22
  import { buildOnlySteps, scanSlideSteps } from './scanner.js';
23
23
  import { DEPENDENCY_RECOVERY_HINT, resolveDependency } from '../_shared/dependency-root.js';
24
24
  import { chromiumLaunchError } from '../playwright/launch.js';
25
- import { resolveBoundPort, startServer } from './server.js';
25
+ import { LOOPBACK_HOST, resolveBoundPort, startServer } from './server.js';
26
26
  import { runWithConcurrency } from './concurrency.js';
27
27
  import { convertStepsSinglePass, removeStepArtifacts } from './single-pass-worker.js';
28
28
  import { convertSingleSlideWithRetry } from './slide-worker.js';
@@ -354,7 +354,7 @@ export async function convertToPptx(config, deps = {}) {
354
354
  // baseUrl は、要求ポートでなく実際に bind されたポートで組む。
355
355
  // port=0 (ephemeral、既定) では OS が空きポートを採番する。
356
356
  // そのため、並行する別プロセスの convert と衝突しない。
357
- const baseUrl = `http://localhost:${resolveBoundPort(server, port).toString()}`;
357
+ const baseUrl = `http://${LOOPBACK_HOST}:${resolveBoundPort(server, port).toString()}`;
358
358
  logger.info(`HTTPサーバー起動: ${baseUrl}`);
359
359
  let browser;
360
360
  try {
@@ -1,10 +1,11 @@
1
1
  import { type Server } from 'node:http';
2
+ export declare const LOOPBACK_HOST = "127.0.0.1";
2
3
  /**
3
4
  dist 配信サーバが実際に bind したポートを解決する。
4
5
  listen 後の `address()` が AddressInfo を返せば、その port を使う。
5
6
  返さない場合 (address() が null / パイプ名を返す stub 等) は、要求ポートへフォールバックする。
6
7
  要求ポートが 0 (ephemeral) のまま実ポートを取れないときは throw する。
7
- `http://localhost:0` という到達不能な baseUrl を組ませないため。
8
+ `http://127.0.0.1:0` という到達不能な baseUrl を組ませないため。
8
9
  */
9
10
  export declare function resolveBoundPort(server: Server, fallbackPort: number): number;
10
11
  /**
@@ -3,15 +3,16 @@
3
3
  /* eslint-disable security/detect-non-literal-fs-filename */
4
4
  import { createServer } from 'node:http';
5
5
  import { readFile } from 'node:fs/promises';
6
- import { join } from 'node:path';
6
+ import { join, resolve as resolvePath, sep } from 'node:path';
7
7
  import * as mimeTypes from 'mime-types';
8
8
  const lookup = mimeTypes.lookup.bind(mimeTypes);
9
+ export const LOOPBACK_HOST = '127.0.0.1';
9
10
  /**
10
11
  dist 配信サーバが実際に bind したポートを解決する。
11
12
  listen 後の `address()` が AddressInfo を返せば、その port を使う。
12
13
  返さない場合 (address() が null / パイプ名を返す stub 等) は、要求ポートへフォールバックする。
13
14
  要求ポートが 0 (ephemeral) のまま実ポートを取れないときは throw する。
14
- `http://localhost:0` という到達不能な baseUrl を組ませないため。
15
+ `http://127.0.0.1:0` という到達不能な baseUrl を組ませないため。
15
16
  */
16
17
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types -- Server は mutable 型
17
18
  export function resolveBoundPort(server, fallbackPort) {
@@ -35,7 +36,14 @@ export function startServer(distDir, port) {
35
36
  void (async () => {
36
37
  const urlPath = (request.url ?? '/').split('?', 1)[0];
37
38
  const safePath = urlPath ?? '/';
38
- const filePath = join(distDir, safePath === '/' ? 'index.html' : safePath);
39
+ const root = resolvePath(distDir);
40
+ const filePath = resolvePath(root, '.' + (safePath === '/' ? '/index.html' : safePath));
41
+ // `..` を含む要求で dist の外を読ませない。dist 自身に正規化される要求 (`/.`・`//` など) も、この判定で 404 にする
42
+ if (!filePath.startsWith(root + sep)) {
43
+ res.writeHead(404);
44
+ res.end('Not found');
45
+ return;
46
+ }
39
47
  try {
40
48
  const content = await readFile(filePath);
41
49
  const contentType = lookup(filePath) || 'application/octet-stream';
@@ -66,7 +74,8 @@ export function startServer(distDir, port) {
66
74
  // リスナーは dom-to-pptx の Emscripten ランタイムが登録する。
67
75
  // すると Promise は永遠に pending のままになり、CLI が無限ハングする。
68
76
  server.once('error', reject);
69
- server.listen(port, () => {
77
+ // ループバックだけで待ち受け、同じネットワークの他の端末から届かないようにする
78
+ server.listen(port, LOOPBACK_HOST, () => {
70
79
  // listen 成功後は Promise が settled 済みで reject が無効になる。
71
80
  // そのため reject リスナーを外し、stderr 出力へ差し替える。
72
81
  // 以後のサーバエラー (配信中の socket error 等) は通知なしで捨てず、変換ログから観測できるようにする。
@@ -38,7 +38,7 @@ export declare function otherContainersHiddenCss(containerIds: readonly string[]
38
38
  export interface SinglePassRequest {
39
39
  readonly browser: Browser;
40
40
  /**
41
- dist 配信サーバの origin(`http://localhost:<port>`)
41
+ dist 配信サーバの origin(`http://127.0.0.1:<port>`)
42
42
  */
43
43
  readonly baseUrl: string;
44
44
  /**
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@pecot/visual-mcp",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@pecot/visual-mcp",
9
- "version": "1.0.0",
9
+ "version": "1.1.0",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@cffnpwr/textlint-plugin-comments": "1.0.0",
@@ -18,7 +18,7 @@
18
18
  "@textlint/textlint-plugin-markdown": "^15.8.0",
19
19
  "@xmldom/xmldom": "^0.9.12",
20
20
  "ajv": "^6.15.0",
21
- "commander": "^14.0.3",
21
+ "commander": "^15.0.0",
22
22
  "eslint": "^10.13.0",
23
23
  "js-yaml": "^4.3.2",
24
24
  "mime-types": "^2.1.35",
@@ -71,9 +71,9 @@
71
71
  }
72
72
  },
73
73
  "node_modules/@babel/helper-string-parser": {
74
- "version": "7.29.11",
75
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.11.tgz",
76
- "integrity": "sha512-snZbO7MEDOof+hvNa97EjEY7qD7h2kwvQr5AJC3ZhQudKW5dnej6k3kP9NQV88hJwaS8vDqRLFo9rivLEhle2g==",
74
+ "version": "7.29.13",
75
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.13.tgz",
76
+ "integrity": "sha512-fWegr+WsEsiMVW4KUNdIIzzMTZSzNiqhy0//6+2MRi2d5NFNsL/AYwBQW8eBnRbTBVRnDVzjaJEUqKaCWjMMdQ==",
77
77
  "license": "MIT",
78
78
  "engines": {
79
79
  "node": ">=6.9.0"
@@ -89,9 +89,9 @@
89
89
  }
90
90
  },
91
91
  "node_modules/@babel/parser": {
92
- "version": "7.29.12",
93
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.12.tgz",
94
- "integrity": "sha512-WJ7JBp/Q4+z/ImydtI7jS6NVco5++632ExBemSX+Ysb+G1lCwQ5BVo3SY+jGGOcZXI4ZccbZSUSJLNBW6eEpJg==",
92
+ "version": "7.29.13",
93
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.13.tgz",
94
+ "integrity": "sha512-fJM50YYjlTiBhgdkGmC1tBpv+FMAyo4annf2X6Aks+0yRlaiVkYW/3f07xAfVVkYIoZ9fFZp+mEThUFnuybhkQ==",
95
95
  "license": "MIT",
96
96
  "dependencies": {
97
97
  "@babel/types": "^7.29.11"
@@ -192,9 +192,9 @@
192
192
  }
193
193
  },
194
194
  "node_modules/@eslint-community/regexpp": {
195
- "version": "4.12.2",
196
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
197
- "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
195
+ "version": "4.12.3",
196
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.3.tgz",
197
+ "integrity": "sha512-R76UKbvsqI68DJJVTVyqFKqU98CN4+B+acxNfEA2IFarSzP0SjtKf/3+fFiXzTyv5Fj3PxLkGHe2wnVWWMxobQ==",
198
198
  "license": "MIT",
199
199
  "engines": {
200
200
  "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
@@ -1161,12 +1161,12 @@
1161
1161
  }
1162
1162
  },
1163
1163
  "node_modules/commander": {
1164
- "version": "14.0.3",
1165
- "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
1166
- "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==",
1164
+ "version": "15.1.0",
1165
+ "resolved": "https://registry.npmjs.org/commander/-/commander-15.1.0.tgz",
1166
+ "integrity": "sha512-cgnQ88TRrWcC7pVq46RzJVRMktu3W2RcbnoidnfBsl1bmDCBwJS/udcIZpKoCrbAYYaCqsz1yZCVIgbIaU3ddQ==",
1167
1167
  "license": "MIT",
1168
1168
  "engines": {
1169
- "node": ">=20"
1169
+ "node": ">=22.12.0"
1170
1170
  }
1171
1171
  },
1172
1172
  "node_modules/commandpost": {
@@ -1984,9 +1984,9 @@
1984
1984
  "license": "ISC"
1985
1985
  },
1986
1986
  "node_modules/glob": {
1987
- "version": "13.0.6",
1988
- "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz",
1989
- "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==",
1987
+ "version": "13.0.7",
1988
+ "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.7.tgz",
1989
+ "integrity": "sha512-wfsFgXQ8A3SEI9XGf7Nl3Y9l7ffSrGh7SUCT7vU/2CzYPep9kjxAn1S40F9OPKxAMGCVl7HtNlJhrCJUeUq83g==",
1990
1990
  "license": "BlueOak-1.0.0",
1991
1991
  "dependencies": {
1992
1992
  "minimatch": "^10.2.2",
@@ -3257,9 +3257,9 @@
3257
3257
  }
3258
3258
  },
3259
3259
  "node_modules/mdast-util-gfm-task-list-item": {
3260
- "version": "2.0.0",
3261
- "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz",
3262
- "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==",
3260
+ "version": "2.0.1",
3261
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.1.tgz",
3262
+ "integrity": "sha512-jXVO1hvB2hs82g1esi7I9nIJDqiijbQLIyH2jDUb5s7jIAZMr/79h0VHSq7XHKTqpLARRm+DDNjduB7S9+6XZA==",
3263
3263
  "license": "MIT",
3264
3264
  "dependencies": {
3265
3265
  "@types/mdast": "^4.0.0",
@@ -3311,9 +3311,9 @@
3311
3311
  }
3312
3312
  },
3313
3313
  "node_modules/mdast-util-gfm/node_modules/mdast-util-gfm-autolink-literal": {
3314
- "version": "2.0.1",
3315
- "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz",
3316
- "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==",
3314
+ "version": "2.1.0",
3315
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.1.0.tgz",
3316
+ "integrity": "sha512-Jx6QSK8wDo558Bcf7q+1pe0v81g2PVs09Hlvu9xJHmCFRF3sAPW7vXFVIAwBncs3sde92WbsVqNxwdqViA2XnQ==",
3317
3317
  "license": "MIT",
3318
3318
  "dependencies": {
3319
3319
  "@types/mdast": "^4.0.0",
@@ -3401,9 +3401,9 @@
3401
3401
  }
3402
3402
  },
3403
3403
  "node_modules/mdast-util-to-markdown": {
3404
- "version": "2.2.2",
3405
- "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.2.2.tgz",
3406
- "integrity": "sha512-ELNT5jYDUdx0B/hlUSSAiAEtvqkY3Oriwkp1KEYseF1Ccu4MnKkmE5yK3oE3WGT/Pq8VTE+XwP0GLL5pafY8yA==",
3404
+ "version": "2.2.3",
3405
+ "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.2.3.tgz",
3406
+ "integrity": "sha512-dImdB6VZRMRac1SwAW6o1c0ESk/7pFFAMCMuKM+9v7LpTSthMM5nzXpqKw4Mjo66aXVKhNkyrP4bMB9MurPyWg==",
3407
3407
  "license": "MIT",
3408
3408
  "dependencies": {
3409
3409
  "@types/mdast": "^4.0.0",
@@ -4433,12 +4433,12 @@
4433
4433
  "license": "ISC"
4434
4434
  },
4435
4435
  "node_modules/playwright": {
4436
- "version": "1.64.1",
4437
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.64.1.tgz",
4438
- "integrity": "sha512-HCrVhHr5QQuwYoswEUGTb7gGp522yflbv/ST8nF4sFWGuLjQCt17Q/EubpGGSNKYn1tsTCPZxqHhHCfVURu7UA==",
4436
+ "version": "1.65.0",
4437
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.65.0.tgz",
4438
+ "integrity": "sha512-F3AMWcR44qMBt4kq+6Kb6mX7bjGXshktKFOPULd7reED6ZJWevjbNRqysP7q+AATE9kdPEZBibex1BYsvpVoeA==",
4439
4439
  "license": "Apache-2.0",
4440
4440
  "dependencies": {
4441
- "playwright-core": "1.64.1"
4441
+ "playwright-core": "1.65.0"
4442
4442
  },
4443
4443
  "bin": {
4444
4444
  "playwright": "cli.js"
@@ -4448,9 +4448,9 @@
4448
4448
  }
4449
4449
  },
4450
4450
  "node_modules/playwright-core": {
4451
- "version": "1.64.1",
4452
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.64.1.tgz",
4453
- "integrity": "sha512-BC4s8y6SEVA6Q1rSxZTto8hI1KUI3xXlHGZgvGqP4IqPdI/a6FX9H29IDNz7vKo9l21b6LfYosScPL6M3xxyDQ==",
4451
+ "version": "1.65.0",
4452
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.65.0.tgz",
4453
+ "integrity": "sha512-vNSKgH6YqtN7cdT/L334zo0a+YwkrpicyrHJlWWPIm/Q+Nn2SWInil01oT0mbu96U4GgoRtCYQD9CzJQgju+lA==",
4454
4454
  "license": "Apache-2.0",
4455
4455
  "bin": {
4456
4456
  "playwright-core": "cli.js"
@@ -6014,6 +6014,15 @@
6014
6014
  "integrity": "sha512-4YPL7IRAuaZflE10+BVhKr6k5KQl/DiLeNCIF7ISqKr0ogM2hqm9ztRNCPqL/xYDI7hfuIHR8T+U7mIDRLQNXw==",
6015
6015
  "license": "MIT"
6016
6016
  },
6017
+ "node_modules/textlint-rule-preset-jtf-style/node_modules/commander": {
6018
+ "version": "14.0.3",
6019
+ "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
6020
+ "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==",
6021
+ "license": "MIT",
6022
+ "engines": {
6023
+ "node": ">=20"
6024
+ }
6025
+ },
6017
6026
  "node_modules/textlint-rule-preset-jtf-style/node_modules/diff": {
6018
6027
  "version": "9.0.0",
6019
6028
  "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pecot/visual-mcp",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "description": "pecotv MCP server (standalone distribution)",
6
6
  "license": "MIT",
@@ -18,7 +18,7 @@
18
18
  "dependencies": {
19
19
  "@modelcontextprotocol/server": "^2.4.0",
20
20
  "@xmldom/xmldom": "^0.9.12",
21
- "commander": "^14.0.3",
21
+ "commander": "^15.0.0",
22
22
  "mime-types": "^2.1.35",
23
23
  "playwright": "^1.64.1",
24
24
  "xpath": "^0.0.34",
@@ -1 +1 @@
1
- 9ea131d250c0fbc923b5c1320c9f15795653279ec92188ccd4e5e5098821f18c
1
+ ec820409145799b4c3a658fe56e75da77f7c867333b9e04bd617c584d5abd8cf