weixin-mcp 1.2.0 → 1.2.2

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/api.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import crypto from "node:crypto";
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
- import os from "node:os";
5
4
  export const DEFAULT_BASE_URL = "https://ilinkai.weixin.qq.com";
6
5
  const CHANNEL_VERSION = "1.0.2";
7
6
  export class WeixinAuthError extends Error {
@@ -35,10 +34,9 @@ function buildHeaders(token, bodyStr) {
35
34
  };
36
35
  }
37
36
  // ── Cursor persistence ─────────────────────────────────────────────────────
38
- const STATE_DIR = process.env.OPENCLAW_STATE_DIR?.trim() ||
39
- path.join(os.homedir(), ".openclaw");
37
+ import { ACCOUNTS_DIR } from "./paths.js";
40
38
  function cursorPath(accountId) {
41
- return path.join(STATE_DIR, "openclaw-weixin", "accounts", `${accountId}.cursor.json`);
39
+ return path.join(ACCOUNTS_DIR, `${accountId}.cursor.json`);
42
40
  }
43
41
  export function loadCursor(accountId) {
44
42
  try {
package/dist/cli.js CHANGED
File without changes
package/dist/index.js CHANGED
@@ -8,13 +8,10 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
8
8
  import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
9
9
  import fs from "node:fs";
10
10
  import path from "node:path";
11
- import os from "node:os";
12
11
  import { DEFAULT_BASE_URL, getUpdates, getConfig, sendTextMessage, loadCursor, saveCursor, WeixinAuthError, WeixinNetworkError, } from "./api.js";
12
+ import { ACCOUNTS_DIR } from "./paths.js";
13
13
  // ── Auth / config ──────────────────────────────────────────────────────────
14
- const STATE_DIR = process.env.OPENCLAW_STATE_DIR?.trim() ||
15
- process.env.CLAWDBOT_STATE_DIR?.trim() ||
16
- path.join(os.homedir(), ".openclaw");
17
- const WEIXIN_DIR = path.join(STATE_DIR, "openclaw-weixin", "accounts");
14
+ const WEIXIN_DIR = ACCOUNTS_DIR;
18
15
  function loadAccount() {
19
16
  const files = fs
20
17
  .readdirSync(WEIXIN_DIR)
package/dist/login.d.ts CHANGED
@@ -1,10 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * weixin-login — standalone QR login for weixin-mcp
4
- * Usage: node dist/login.js
3
+ * weixin-login — QR login for weixin-mcp
4
+ * Usage: npx weixin-mcp login
5
5
  *
6
- * Fetches a QR code from Weixin API, renders it in terminal,
7
- * polls for scan confirmation, then saves token to:
8
- * ~/.openclaw/openclaw-weixin/accounts/<accountId>.json
6
+ * Token saved to: ~/.weixin-mcp/accounts/ (or ~/.openclaw/openclaw-weixin/accounts/ if OpenClaw is installed)
9
7
  */
10
8
  export declare function main(): Promise<void>;
package/dist/login.js CHANGED
@@ -1,23 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * weixin-login — standalone QR login for weixin-mcp
4
- * Usage: node dist/login.js
3
+ * weixin-login — QR login for weixin-mcp
4
+ * Usage: npx weixin-mcp login
5
5
  *
6
- * Fetches a QR code from Weixin API, renders it in terminal,
7
- * polls for scan confirmation, then saves token to:
8
- * ~/.openclaw/openclaw-weixin/accounts/<accountId>.json
6
+ * Token saved to: ~/.weixin-mcp/accounts/ (or ~/.openclaw/openclaw-weixin/accounts/ if OpenClaw is installed)
9
7
  */
10
8
  import fs from "node:fs";
11
9
  import path from "node:path";
12
- import os from "node:os";
13
10
  import crypto from "node:crypto";
14
11
  // @ts-ignore — no types for qrcode-terminal
15
12
  import qrcode from "qrcode-terminal";
13
+ import { ACCOUNTS_DIR } from "./paths.js";
16
14
  const BASE_URL = "https://ilinkai.weixin.qq.com";
17
15
  const BOT_TYPE = "3";
18
- const STATE_DIR = process.env.OPENCLAW_STATE_DIR?.trim() ||
19
- path.join(os.homedir(), ".openclaw");
20
- const ACCOUNTS_DIR = path.join(STATE_DIR, "openclaw-weixin", "accounts");
21
16
  async function fetchQRCode() {
22
17
  const base = BASE_URL.endsWith("/") ? BASE_URL : `${BASE_URL}/`;
23
18
  const url = `${base}ilink/bot/get_bot_qrcode?bot_type=${BOT_TYPE}`;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Resolve the accounts directory.
3
+ *
4
+ * Priority:
5
+ * 1. WEIXIN_MCP_DIR env var (explicit override)
6
+ * 2. If OpenClaw state dir exists → ~/.openclaw/openclaw-weixin/accounts/ (backward compat)
7
+ * 3. Default → ~/.weixin-mcp/accounts/
8
+ */
9
+ export declare const ACCOUNTS_DIR: string;
package/dist/paths.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Resolve the accounts directory.
3
+ *
4
+ * Priority:
5
+ * 1. WEIXIN_MCP_DIR env var (explicit override)
6
+ * 2. If OpenClaw state dir exists → ~/.openclaw/openclaw-weixin/accounts/ (backward compat)
7
+ * 3. Default → ~/.weixin-mcp/accounts/
8
+ */
9
+ import fs from "node:fs";
10
+ import path from "node:path";
11
+ import os from "node:os";
12
+ function resolveAccountsDir() {
13
+ // Explicit override
14
+ if (process.env.WEIXIN_MCP_DIR?.trim()) {
15
+ return process.env.WEIXIN_MCP_DIR.trim();
16
+ }
17
+ // OpenClaw compat: if the OpenClaw weixin accounts dir exists, use it
18
+ const openclawStateDir = process.env.OPENCLAW_STATE_DIR?.trim() ||
19
+ process.env.CLAWDBOT_STATE_DIR?.trim() ||
20
+ path.join(os.homedir(), ".openclaw");
21
+ const openclawAccountsDir = path.join(openclawStateDir, "openclaw-weixin", "accounts");
22
+ if (fs.existsSync(openclawAccountsDir)) {
23
+ return openclawAccountsDir;
24
+ }
25
+ // Default: standalone ~/.weixin-mcp/accounts/
26
+ return path.join(os.homedir(), ".weixin-mcp", "accounts");
27
+ }
28
+ export const ACCOUNTS_DIR = resolveAccountsDir();
package/dist/status.js CHANGED
@@ -1,9 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import os from "node:os";
4
- const STATE_DIR = process.env.OPENCLAW_STATE_DIR?.trim() ||
5
- path.join(os.homedir(), ".openclaw");
6
- const ACCOUNTS_DIR = path.join(STATE_DIR, "openclaw-weixin", "accounts");
3
+ import { ACCOUNTS_DIR } from "./paths.js";
7
4
  export async function showStatus() {
8
5
  console.log("🔍 weixin-mcp status\n");
9
6
  let files;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ // weixin-login — shorthand for: npx weixin-mcp login
3
+ import { main } from "./login.js";
4
+ main().catch((err) => { console.error(err); process.exit(1); });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "weixin-mcp",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "MCP server for WeChat (Weixin) — send messages via OpenClaw weixin plugin auth",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "bin": {
15
15
  "weixin-mcp": "dist/cli.js",
16
- "weixin-login": "dist/login.js"
16
+ "weixin-login": "dist/weixin-login.js"
17
17
  },
18
18
  "dependencies": {
19
19
  "@modelcontextprotocol/sdk": "^1.0.0",
package/src/api.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import crypto from "node:crypto";
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
- import os from "node:os";
5
4
 
6
5
  export const DEFAULT_BASE_URL = "https://ilinkai.weixin.qq.com";
7
6
  const CHANNEL_VERSION = "1.0.2";
@@ -44,12 +43,10 @@ function buildHeaders(token: string, bodyStr: string): Record<string, string> {
44
43
 
45
44
  // ── Cursor persistence ─────────────────────────────────────────────────────
46
45
 
47
- const STATE_DIR =
48
- process.env.OPENCLAW_STATE_DIR?.trim() ||
49
- path.join(os.homedir(), ".openclaw");
46
+ import { ACCOUNTS_DIR } from "./paths.js";
50
47
 
51
48
  function cursorPath(accountId: string): string {
52
- return path.join(STATE_DIR, "openclaw-weixin", "accounts", `${accountId}.cursor.json`);
49
+ return path.join(ACCOUNTS_DIR, `${accountId}.cursor.json`);
53
50
  }
54
51
 
55
52
  export function loadCursor(accountId: string): string {
package/src/index.ts CHANGED
@@ -12,7 +12,6 @@ import {
12
12
  } from "@modelcontextprotocol/sdk/types.js";
13
13
  import fs from "node:fs";
14
14
  import path from "node:path";
15
- import os from "node:os";
16
15
  import {
17
16
  DEFAULT_BASE_URL,
18
17
  getUpdates,
@@ -23,15 +22,11 @@ import {
23
22
  WeixinAuthError,
24
23
  WeixinNetworkError,
25
24
  } from "./api.js";
25
+ import { ACCOUNTS_DIR } from "./paths.js";
26
26
 
27
27
  // ── Auth / config ──────────────────────────────────────────────────────────
28
28
 
29
- const STATE_DIR =
30
- process.env.OPENCLAW_STATE_DIR?.trim() ||
31
- process.env.CLAWDBOT_STATE_DIR?.trim() ||
32
- path.join(os.homedir(), ".openclaw");
33
-
34
- const WEIXIN_DIR = path.join(STATE_DIR, "openclaw-weixin", "accounts");
29
+ const WEIXIN_DIR = ACCOUNTS_DIR;
35
30
 
36
31
  interface AccountData {
37
32
  token?: string;
package/src/login.ts CHANGED
@@ -1,26 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * weixin-login — standalone QR login for weixin-mcp
4
- * Usage: node dist/login.js
3
+ * weixin-login — QR login for weixin-mcp
4
+ * Usage: npx weixin-mcp login
5
5
  *
6
- * Fetches a QR code from Weixin API, renders it in terminal,
7
- * polls for scan confirmation, then saves token to:
8
- * ~/.openclaw/openclaw-weixin/accounts/<accountId>.json
6
+ * Token saved to: ~/.weixin-mcp/accounts/ (or ~/.openclaw/openclaw-weixin/accounts/ if OpenClaw is installed)
9
7
  */
10
8
 
11
9
  import fs from "node:fs";
12
10
  import path from "node:path";
13
- import os from "node:os";
14
11
  import crypto from "node:crypto";
15
12
  // @ts-ignore — no types for qrcode-terminal
16
13
  import qrcode from "qrcode-terminal";
14
+ import { ACCOUNTS_DIR } from "./paths.js";
17
15
 
18
16
  const BASE_URL = "https://ilinkai.weixin.qq.com";
19
17
  const BOT_TYPE = "3";
20
- const STATE_DIR =
21
- process.env.OPENCLAW_STATE_DIR?.trim() ||
22
- path.join(os.homedir(), ".openclaw");
23
- const ACCOUNTS_DIR = path.join(STATE_DIR, "openclaw-weixin", "accounts");
24
18
 
25
19
  async function fetchQRCode(): Promise<{ qrcode: string; qrcode_img_content: string }> {
26
20
  const base = BASE_URL.endsWith("/") ? BASE_URL : `${BASE_URL}/`;
package/src/paths.ts ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Resolve the accounts directory.
3
+ *
4
+ * Priority:
5
+ * 1. WEIXIN_MCP_DIR env var (explicit override)
6
+ * 2. If OpenClaw state dir exists → ~/.openclaw/openclaw-weixin/accounts/ (backward compat)
7
+ * 3. Default → ~/.weixin-mcp/accounts/
8
+ */
9
+
10
+ import fs from "node:fs";
11
+ import path from "node:path";
12
+ import os from "node:os";
13
+
14
+ function resolveAccountsDir(): string {
15
+ // Explicit override
16
+ if (process.env.WEIXIN_MCP_DIR?.trim()) {
17
+ return process.env.WEIXIN_MCP_DIR.trim();
18
+ }
19
+
20
+ // OpenClaw compat: if the OpenClaw weixin accounts dir exists, use it
21
+ const openclawStateDir =
22
+ process.env.OPENCLAW_STATE_DIR?.trim() ||
23
+ process.env.CLAWDBOT_STATE_DIR?.trim() ||
24
+ path.join(os.homedir(), ".openclaw");
25
+
26
+ const openclawAccountsDir = path.join(openclawStateDir, "openclaw-weixin", "accounts");
27
+ if (fs.existsSync(openclawAccountsDir)) {
28
+ return openclawAccountsDir;
29
+ }
30
+
31
+ // Default: standalone ~/.weixin-mcp/accounts/
32
+ return path.join(os.homedir(), ".weixin-mcp", "accounts");
33
+ }
34
+
35
+ export const ACCOUNTS_DIR = resolveAccountsDir();
package/src/status.ts CHANGED
@@ -1,12 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import os from "node:os";
4
-
5
- const STATE_DIR =
6
- process.env.OPENCLAW_STATE_DIR?.trim() ||
7
- path.join(os.homedir(), ".openclaw");
8
-
9
- const ACCOUNTS_DIR = path.join(STATE_DIR, "openclaw-weixin", "accounts");
3
+ import { ACCOUNTS_DIR } from "./paths.js";
10
4
 
11
5
  export async function showStatus() {
12
6
  console.log("🔍 weixin-mcp status\n");
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ // weixin-login — shorthand for: npx weixin-mcp login
3
+ import { main } from "./login.js";
4
+ main().catch((err) => { console.error(err); process.exit(1); });