@kakedashi/md-to-article-mcp 1.0.1 → 1.0.4

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/dist/clipboard.js CHANGED
@@ -15,14 +15,27 @@ function copyHtmlToClipboard(html) {
15
15
  }
16
16
  }
17
17
  function copyHtmlMacOS(html) {
18
+ // HTML バイト列を hex に変換して AppleScript リテラルとして埋め込む。
19
+ // hex は [0-9A-F] のみで構成されるためインジェクション不可。
18
20
  const hex = Buffer.from(html, "utf-8").toString("hex").toUpperCase();
19
21
  const script = `set the clipboard to «data HTML${hex}»`;
20
- (0, child_process_1.execSync)(`osascript -e '${script.replace(/'/g, "'\"'\"'")}'`);
22
+ // osascript に配列で渡すことでシェル展開を経由しない。
23
+ const result = (0, child_process_1.spawnSync)("osascript", ["-e", script]);
24
+ if (result.status !== 0) {
25
+ throw new Error(result.stderr?.toString() ?? "osascript failed");
26
+ }
21
27
  }
22
28
  function copyHtmlWindows(html) {
23
- const escaped = html.replace(/"/g, '\\"');
24
- (0, child_process_1.execSync)(`powershell -Command "Set-Clipboard -Value \\"${escaped}\\" -AsHtml"`, { shell: "powershell.exe" });
29
+ // PowerShell HTML を stdin 経由で渡し、コマンド文字列への展開を避ける。
30
+ const result = (0, child_process_1.spawnSync)("powershell", ["-NoProfile", "-Command", "$input | Set-Clipboard -AsHtml"], { input: html, encoding: "utf-8", shell: false });
31
+ if (result.status !== 0) {
32
+ throw new Error(result.stderr?.toString() ?? "Set-Clipboard failed");
33
+ }
25
34
  }
26
35
  function copyHtmlLinux(html) {
27
- (0, child_process_1.execSync)(`echo ${JSON.stringify(html)} | xclip -selection clipboard -t text/html`);
36
+ // xclip HTML stdin 経由で渡す。シェルを介さないので展開なし。
37
+ const result = (0, child_process_1.spawnSync)("xclip", ["-selection", "clipboard", "-t", "text/html"], { input: html, encoding: "utf-8", shell: false });
38
+ if (result.status !== 0) {
39
+ throw new Error(result.stderr?.toString() ?? "xclip failed");
40
+ }
28
41
  }
package/dist/index.js CHANGED
@@ -70,6 +70,12 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
70
70
  }
71
71
  const { filepath } = request.params.arguments;
72
72
  const resolvedPath = path.resolve(filepath.replace(/^~/, os_1.default.homedir()));
73
+ if (path.extname(resolvedPath) !== ".md") {
74
+ return {
75
+ content: [{ type: "text", text: `ファイルの拡張子が .md ではありません: ${filepath}` }],
76
+ isError: true,
77
+ };
78
+ }
73
79
  // ファイル読み込み
74
80
  let markdown;
75
81
  try {
@@ -130,6 +136,19 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
130
136
  };
131
137
  });
132
138
  async function main() {
139
+ const filepath = process.argv[2];
140
+ if (filepath) {
141
+ const resolvedPath = path.resolve(filepath.replace(/^~/, os_1.default.homedir()));
142
+ if (path.extname(resolvedPath) !== ".md") {
143
+ console.error(`ファイルの拡張子が .md ではありません: ${filepath}`);
144
+ process.exit(1);
145
+ }
146
+ const markdown = fs.readFileSync(resolvedPath, "utf-8");
147
+ const html = (0, converter_js_1.convertMarkdownToHtml)(markdown);
148
+ (0, clipboard_js_1.copyHtmlToClipboard)(html);
149
+ console.log(`コピーしました: ${filepath}`);
150
+ process.exit(0);
151
+ }
133
152
  const transport = new stdio_js_1.StdioServerTransport();
134
153
  await server.connect(transport);
135
154
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kakedashi/md-to-article-mcp",
3
- "version": "1.0.1",
3
+ "version": "1.0.4",
4
4
  "description": "MCP tool to convert Markdown files to rich text and copy to clipboard for X Article editor",
5
5
  "main": "dist/index.js",
6
6
  "bin": {