@sjawhar/whatsapp-mcp 2.1.1 → 2.2.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 (114) hide show
  1. package/dist/db.d.ts +27 -1
  2. package/dist/db.d.ts.map +1 -1
  3. package/dist/db.js +134 -31
  4. package/dist/db.js.map +1 -1
  5. package/dist/http-server.d.ts +8 -0
  6. package/dist/http-server.d.ts.map +1 -0
  7. package/dist/http-server.js +198 -0
  8. package/dist/http-server.js.map +1 -0
  9. package/dist/import-contacts.d.ts +6 -3
  10. package/dist/import-contacts.d.ts.map +1 -1
  11. package/dist/import-contacts.js +28 -14
  12. package/dist/import-contacts.js.map +1 -1
  13. package/dist/index.js +187 -64
  14. package/dist/index.js.map +1 -1
  15. package/dist/resources.d.ts +16 -0
  16. package/dist/resources.d.ts.map +1 -0
  17. package/dist/resources.js +84 -0
  18. package/dist/resources.js.map +1 -0
  19. package/dist/tools.d.ts.map +1 -1
  20. package/dist/tools.js +15 -16
  21. package/dist/tools.js.map +1 -1
  22. package/dist/whatsapp.d.ts +12 -0
  23. package/dist/whatsapp.d.ts.map +1 -1
  24. package/dist/whatsapp.js +153 -30
  25. package/dist/whatsapp.js.map +1 -1
  26. package/package.json +4 -1
  27. package/dist/__tests__/connection.test.d.ts +0 -2
  28. package/dist/__tests__/connection.test.d.ts.map +0 -1
  29. package/dist/__tests__/connection.test.js +0 -105
  30. package/dist/__tests__/connection.test.js.map +0 -1
  31. package/dist/__tests__/disconnect.test.d.ts +0 -2
  32. package/dist/__tests__/disconnect.test.d.ts.map +0 -1
  33. package/dist/__tests__/disconnect.test.js +0 -166
  34. package/dist/__tests__/disconnect.test.js.map +0 -1
  35. package/dist/__tests__/download-media.test.d.ts +0 -2
  36. package/dist/__tests__/download-media.test.d.ts.map +0 -1
  37. package/dist/__tests__/download-media.test.js +0 -110
  38. package/dist/__tests__/download-media.test.js.map +0 -1
  39. package/dist/__tests__/failures/connection-failures.test.d.ts +0 -2
  40. package/dist/__tests__/failures/connection-failures.test.d.ts.map +0 -1
  41. package/dist/__tests__/failures/connection-failures.test.js +0 -146
  42. package/dist/__tests__/failures/connection-failures.test.js.map +0 -1
  43. package/dist/__tests__/failures/edge-cases.test.d.ts +0 -2
  44. package/dist/__tests__/failures/edge-cases.test.d.ts.map +0 -1
  45. package/dist/__tests__/failures/edge-cases.test.js +0 -121
  46. package/dist/__tests__/failures/edge-cases.test.js.map +0 -1
  47. package/dist/__tests__/failures/resource-failures.test.d.ts +0 -2
  48. package/dist/__tests__/failures/resource-failures.test.d.ts.map +0 -1
  49. package/dist/__tests__/failures/resource-failures.test.js +0 -136
  50. package/dist/__tests__/failures/resource-failures.test.js.map +0 -1
  51. package/dist/__tests__/failures/security-failures.test.d.ts +0 -2
  52. package/dist/__tests__/failures/security-failures.test.d.ts.map +0 -1
  53. package/dist/__tests__/failures/security-failures.test.js +0 -0
  54. package/dist/__tests__/failures/security-failures.test.js.map +0 -1
  55. package/dist/__tests__/helpers/fake-baileys.d.ts +0 -52
  56. package/dist/__tests__/helpers/fake-baileys.d.ts.map +0 -1
  57. package/dist/__tests__/helpers/fake-baileys.js +0 -60
  58. package/dist/__tests__/helpers/fake-baileys.js.map +0 -1
  59. package/dist/__tests__/helpers/mcp-test-client.d.ts +0 -9
  60. package/dist/__tests__/helpers/mcp-test-client.d.ts.map +0 -1
  61. package/dist/__tests__/helpers/mcp-test-client.js +0 -40
  62. package/dist/__tests__/helpers/mcp-test-client.js.map +0 -1
  63. package/dist/__tests__/helpers/test-db.d.ts +0 -4
  64. package/dist/__tests__/helpers/test-db.d.ts.map +0 -1
  65. package/dist/__tests__/helpers/test-db.js +0 -32
  66. package/dist/__tests__/helpers/test-db.js.map +0 -1
  67. package/dist/__tests__/integration/chat-navigation.test.d.ts +0 -2
  68. package/dist/__tests__/integration/chat-navigation.test.d.ts.map +0 -1
  69. package/dist/__tests__/integration/chat-navigation.test.js +0 -171
  70. package/dist/__tests__/integration/chat-navigation.test.js.map +0 -1
  71. package/dist/__tests__/integration/contacts-flow.test.d.ts +0 -2
  72. package/dist/__tests__/integration/contacts-flow.test.d.ts.map +0 -1
  73. package/dist/__tests__/integration/contacts-flow.test.js +0 -150
  74. package/dist/__tests__/integration/contacts-flow.test.js.map +0 -1
  75. package/dist/__tests__/integration/media-flow.test.d.ts +0 -2
  76. package/dist/__tests__/integration/media-flow.test.d.ts.map +0 -1
  77. package/dist/__tests__/integration/media-flow.test.js +0 -225
  78. package/dist/__tests__/integration/media-flow.test.js.map +0 -1
  79. package/dist/__tests__/integration/search-flow.test.d.ts +0 -2
  80. package/dist/__tests__/integration/search-flow.test.d.ts.map +0 -1
  81. package/dist/__tests__/integration/search-flow.test.js +0 -44
  82. package/dist/__tests__/integration/search-flow.test.js.map +0 -1
  83. package/dist/__tests__/integration/send-message.test.d.ts +0 -2
  84. package/dist/__tests__/integration/send-message.test.d.ts.map +0 -1
  85. package/dist/__tests__/integration/send-message.test.js +0 -160
  86. package/dist/__tests__/integration/send-message.test.js.map +0 -1
  87. package/dist/__tests__/lock-file.test.d.ts +0 -2
  88. package/dist/__tests__/lock-file.test.d.ts.map +0 -1
  89. package/dist/__tests__/lock-file.test.js +0 -63
  90. package/dist/__tests__/lock-file.test.js.map +0 -1
  91. package/dist/__tests__/medium-fixes.test.d.ts +0 -2
  92. package/dist/__tests__/medium-fixes.test.d.ts.map +0 -1
  93. package/dist/__tests__/medium-fixes.test.js +0 -141
  94. package/dist/__tests__/medium-fixes.test.js.map +0 -1
  95. package/dist/__tests__/rate-limit.test.d.ts +0 -2
  96. package/dist/__tests__/rate-limit.test.d.ts.map +0 -1
  97. package/dist/__tests__/rate-limit.test.js +0 -193
  98. package/dist/__tests__/rate-limit.test.js.map +0 -1
  99. package/dist/__tests__/send-file.test.d.ts +0 -2
  100. package/dist/__tests__/send-file.test.d.ts.map +0 -1
  101. package/dist/__tests__/send-file.test.js +0 -237
  102. package/dist/__tests__/send-file.test.js.map +0 -1
  103. package/dist/__tests__/smoke.test.d.ts +0 -2
  104. package/dist/__tests__/smoke.test.d.ts.map +0 -1
  105. package/dist/__tests__/smoke.test.js +0 -28
  106. package/dist/__tests__/smoke.test.js.map +0 -1
  107. package/dist/__tests__/transcribe.test.d.ts +0 -2
  108. package/dist/__tests__/transcribe.test.d.ts.map +0 -1
  109. package/dist/__tests__/transcribe.test.js +0 -71
  110. package/dist/__tests__/transcribe.test.js.map +0 -1
  111. package/dist/__tests__/zombie.test.d.ts +0 -2
  112. package/dist/__tests__/zombie.test.d.ts.map +0 -1
  113. package/dist/__tests__/zombie.test.js +0 -145
  114. package/dist/__tests__/zombie.test.js.map +0 -1
@@ -83,27 +83,41 @@ function phoneToJid(phone) {
83
83
  return `${digits}@s.whatsapp.net`;
84
84
  }
85
85
  /**
86
- * Import contacts from a VCF file into the database.
86
+ * Import contacts from a VCF file or string into the database.
87
87
  * Can be called from the MCP tool or standalone CLI.
88
88
  *
89
89
  * @param dbInstance - An open better-sqlite3 database instance.
90
90
  * When called from the MCP server, pass the shared DB.
91
91
  * When called from CLI, opens its own connection.
92
- * @param vcfPath - Path to the .vcf file. Defaults to contacts/contacts.vcf.
92
+ * @param vcfContent - Optional VCF content as a string. If provided, parses this directly.
93
+ * If not provided, reads from vcfPath (defaults to contacts/contacts.vcf).
94
+ * @param vcfPath - Path to the .vcf file. Only used if vcfContent is not provided.
95
+ * Defaults to contacts/contacts.vcf.
93
96
  */
94
- export function importContactsFromVcf(dbInstance, vcfPath) {
95
- const absPath = path.resolve(vcfPath || DEFAULT_VCF);
96
- // Containment check: VCF path must be inside the allowed contacts directory
97
- const allowedBase = path.resolve(process.env.CONTACTS_DIR || CONTACTS_DIR);
98
- const allowedPrefix = `${allowedBase}${path.sep}`;
99
- if (!absPath.startsWith(allowedPrefix)) {
100
- throw new Error(`VCF path not allowed: must be within ${allowedBase}`);
97
+ export function importContactsFromVcf(dbInstance, vcfContent, vcfPath) {
98
+ let content;
99
+ let absPath;
100
+ if (vcfContent) {
101
+ // Use provided VCF content directly
102
+ content = vcfContent;
103
+ absPath = "[provided-content]";
101
104
  }
102
- if (!fs.existsSync(absPath)) {
103
- throw new Error(`VCF file not found: ${absPath}`);
105
+ else {
106
+ // Read from file
107
+ const filePath = vcfPath || DEFAULT_VCF;
108
+ absPath = path.resolve(filePath);
109
+ // Containment check: VCF path must be inside the allowed contacts directory
110
+ const allowedBase = path.resolve(process.env.CONTACTS_DIR || CONTACTS_DIR);
111
+ const allowedPrefix = `${allowedBase}${path.sep}`;
112
+ if (!absPath.startsWith(allowedPrefix)) {
113
+ throw new Error(`VCF path not allowed: must be within ${allowedBase}`);
114
+ }
115
+ if (!fs.existsSync(absPath)) {
116
+ throw new Error(`VCF file not found: ${absPath}`);
117
+ }
118
+ // Parse VCF
119
+ content = fs.readFileSync(absPath, "utf-8");
104
120
  }
105
- // Parse VCF
106
- const content = fs.readFileSync(absPath, "utf-8");
107
121
  const contacts = parseVcf(content);
108
122
  // Build lookup maps for all known JIDs (from chats and contacts tables)
109
123
  const knownJids = new Set();
@@ -224,7 +238,7 @@ function main() {
224
238
  }
225
239
  const db = new Database(DB_PATH);
226
240
  db.pragma("journal_mode = WAL");
227
- const result = importContactsFromVcf(db, absPath);
241
+ const result = importContactsFromVcf(db, undefined, absPath);
228
242
  console.log(`Parsed ${result.totalParsed} contacts with phone numbers from VCF`);
229
243
  console.log(`\nMatched ${result.totalUpdated} phone numbers to existing WhatsApp JIDs`);
230
244
  console.log(` Exact matches: ${result.exactMatches}`);
@@ -1 +1 @@
1
- {"version":3,"file":"import-contacts.js","sourceRoot":"","sources":["../src/import-contacts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"import-contacts.js","sourceRoot":"","sources":["../src/import-contacts.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACrD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AACpD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;AAS5D,SAAS,QAAQ,CAAC,OAAe;IAC/B,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAE3C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;YAAE,SAAS;QAE1C,wEAAwE;QACxE,IAAI,IAAI,GAAkB,IAAI,CAAC;QAE/B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAC5C,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3B,CAAC;QAED,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YAC1C,IAAI,MAAM,EAAE,CAAC;gBACX,kDAAkD;gBAClD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBACxE,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;oBACtB,IAAI,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,aAAa;gBACjD,CAAC;qBAAM,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC9B,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBAClB,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,0DAA0D;QAC1D,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,wFAAwF;QACxF,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;QACjD,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;QAC1D,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC5B,mCAAmC;YACnC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YAC3C,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gBACxB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,uEAAuE;AAEvE;;;GAGG;AACH,SAAS,UAAU,CAAC,KAAa;IAC/B,IAAI,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEtC,0CAA0C;IAC1C,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IAED,iFAAiF;IACjF,wEAAwE;IAExE,OAAO,GAAG,MAAM,iBAAiB,CAAC;AACpC,CAAC;AAcD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CAAC,UAA6B,EAAE,UAAmB,EAAE,OAAgB;IACxG,IAAI,OAAe,CAAC;IACpB,IAAI,OAAe,CAAC;IAEpB,IAAI,UAAU,EAAE,CAAC;QACf,oCAAoC;QACpC,OAAO,GAAG,UAAU,CAAC;QACrB,OAAO,GAAG,oBAAoB,CAAC;IACjC,CAAC;SAAM,CAAC;QACN,iBAAiB;QACjB,MAAM,QAAQ,GAAG,OAAO,IAAI,WAAW,CAAC;QACxC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAEjC,4EAA4E;QAC5E,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,YAAY,CAAC,CAAC;QAC3E,MAAM,aAAa,GAAG,GAAG,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAClD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,wCAAwC,WAAW,EAAE,CAAC,CAAC;QACzE,CAAC;QAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,uBAAuB,OAAO,EAAE,CAAC,CAAC;QACpD,CAAC;QAED,YAAY;QACZ,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEnC,wEAAwE;IACxE,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,yDAAyD,CAAC,CAAC,GAAG,EAAuB,CAAC;IAC1H,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,4DAA4D,CAAC,CAAC,GAAG,EAAuB,CAAC;IAChI,KAAK,MAAM,GAAG,IAAI,QAAQ;QAAE,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnD,KAAK,MAAM,GAAG,IAAI,WAAW;QAAE,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAEtD,6DAA6D;IAC7D,4FAA4F;IAC5F,MAAM,UAAU,GAAG,CAAC,CAAC;IACrB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC9C,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;QAClD,IAAI,MAAM,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;YAChC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC;YACzC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YACtD,SAAS,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,CAAC;;;;;GAKxC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC;;;;;GAKrC,CAAC,CAAC;IAEH,oEAAoE;IACpE,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC,CAAC,yCAAyC;IAEhF,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,EAAE;QAC5C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnC,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;gBAE9B,cAAc;gBACd,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBAChD,YAAY,EAAE,CAAC;oBACf,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBACrB,aAAa,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;oBAC/C,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;oBAC5C,SAAS;gBACX,CAAC;gBAED,qCAAqC;gBACrC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACxC,IAAI,MAAM,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;oBAChC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC;oBACzC,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;oBACzC,IAAI,UAAU,EAAE,CAAC;wBACf,KAAK,MAAM,YAAY,IAAI,UAAU,EAAE,CAAC;4BACtC,IAAI,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC;gCAAE,SAAS;4BAC5C,YAAY,EAAE,CAAC;4BACf,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;4BAC9B,aAAa,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;4BAC7D,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;wBAC5D,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,SAAS,EAAE,CAAC;IAEZ,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC;;;GAGnC,CAAC,CAAC,GAAG,EAAqB,CAAC;IAE5B,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,QAAQ,CAAC,MAAM;QAC5B,YAAY;QACZ,YAAY;QACZ,YAAY,EAAE,YAAY,GAAG,YAAY;QACzC,sBAAsB,EAAE,QAAQ,CAAC,GAAG;KACrC,CAAC;AACJ,CAAC;AAED,uEAAuE;AAEvE,SAAS,IAAI;IACX,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAEtD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC9C,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,mBAAmB,OAAO,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,uBAAuB,OAAO,EAAE,CAAC,CAAC;QAChD,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,uDAAuD;QACvD,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAEhC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,UAAU,QAAQ,CAAC,MAAM,uCAAuC,CAAC,CAAC;QAC9E,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAC7C,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;IACT,CAAC;IAED,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC;IACjC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAEhC,MAAM,MAAM,GAAG,qBAAqB,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAE7D,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,WAAW,uCAAuC,CAAC,CAAC;IACjF,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,YAAY,0CAA0C,CAAC,CAAC;IACxF,OAAO,CAAC,GAAG,CAAC,oBAAoB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,oCAAoC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;IACvE,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,YAAY,mCAAmC,CAAC,CAAC;IACjF,OAAO,CAAC,GAAG,CAAC,+BAA+B,MAAM,CAAC,sBAAsB,EAAE,CAAC,CAAC;IAE5E,EAAE,CAAC,KAAK,EAAE,CAAC;AACb,CAAC;AAED,qDAAqD;AACrD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5E,IAAI,WAAW,EAAE,CAAC;IAChB,IAAI,EAAE,CAAC;AACT,CAAC"}
package/dist/index.js CHANGED
@@ -1,91 +1,214 @@
1
1
  #!/usr/bin/env node
2
+ import { randomUUID } from "node:crypto";
2
3
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
4
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
5
  import fs from "fs";
5
6
  import { initDb, closeDb } from "./db.js";
6
- import { initWhatsApp, closeWhatsApp, resolveConnectionAsReadOnly } from "./whatsapp.js";
7
+ import { initWhatsApp, closeWhatsApp, resolveConnectionAsReadOnly, setMessageNotificationHandler, } from "./whatsapp.js";
7
8
  import { registerTools } from "./tools.js";
8
9
  import { acquireWhatsAppLock, releaseWhatsAppLock } from "./lock.js";
9
10
  import { LOCK_FILE, DATA_DIR } from "./paths.js";
11
+ import { createHttpServer } from "./http-server.js";
12
+ import { NEW_MESSAGES_RESOURCE_URI, createResourceSubscriptionStore, registerResourceSubscriptionHandlers, registerResources, } from "./resources.js";
10
13
  console.error(`Data directory: ${DATA_DIR}`);
14
+ function parseCliOptions(argv) {
15
+ let http = false;
16
+ let port = 3456;
17
+ let host = "0.0.0.0";
18
+ for (let i = 0; i < argv.length; i += 1) {
19
+ const arg = argv[i];
20
+ if (arg === "--http") {
21
+ http = true;
22
+ continue;
23
+ }
24
+ if (arg === "--port") {
25
+ const value = argv[i + 1];
26
+ if (!value) {
27
+ throw new Error("--port requires a value");
28
+ }
29
+ const parsedPort = Number.parseInt(value, 10);
30
+ if (Number.isNaN(parsedPort) || parsedPort < 0 || parsedPort > 65_535) {
31
+ throw new Error(`Invalid --port value: ${value}`);
32
+ }
33
+ port = parsedPort;
34
+ i += 1;
35
+ continue;
36
+ }
37
+ if (arg.startsWith("--port=")) {
38
+ const value = arg.slice("--port=".length);
39
+ const parsedPort = Number.parseInt(value, 10);
40
+ if (Number.isNaN(parsedPort) || parsedPort < 0 || parsedPort > 65_535) {
41
+ throw new Error(`Invalid --port value: ${value}`);
42
+ }
43
+ port = parsedPort;
44
+ continue;
45
+ }
46
+ if (arg === "--host") {
47
+ const value = argv[i + 1];
48
+ if (!value) {
49
+ throw new Error("--host requires a value");
50
+ }
51
+ host = value;
52
+ i += 1;
53
+ continue;
54
+ }
55
+ if (arg.startsWith("--host=")) {
56
+ host = arg.slice("--host=".length);
57
+ }
58
+ }
59
+ return { http, port, host };
60
+ }
11
61
  async function main() {
12
62
  console.error("Starting WhatsApp MCP Server...");
63
+ const options = parseCliOptions(process.argv.slice(2));
64
+ let stdioServer;
65
+ let httpController;
66
+ let stdioSessionId;
67
+ let parentWatchdog;
68
+ let lockRetryInterval;
69
+ let ownsWhatsAppLock = false;
70
+ let shuttingDown = false;
71
+ const resourceSubscriptions = createResourceSubscriptionStore();
72
+ let debouncedNotificationTimer;
73
+ setMessageNotificationHandler(() => {
74
+ if (debouncedNotificationTimer) {
75
+ clearTimeout(debouncedNotificationTimer);
76
+ }
77
+ debouncedNotificationTimer = setTimeout(() => {
78
+ debouncedNotificationTimer = undefined;
79
+ void resourceSubscriptions.notifyResourceUpdated(NEW_MESSAGES_RESOURCE_URI);
80
+ }, 500);
81
+ });
13
82
  // 1. Initialize SQLite database (synchronous, instant).
14
83
  initDb();
15
- // 2. Create MCP server and connect to stdio transport FIRST
16
- // so the client doesn't time out waiting for the initialize handshake.
17
- const server = new McpServer({
18
- name: "whatsapp",
19
- version: "1.0.0",
20
- });
21
- registerTools(server);
22
- const transport = new StdioServerTransport();
23
- await server.connect(transport);
24
- console.error("MCP server running on stdio");
25
- // Detect parent death via two mechanisms:
26
- // 1. stdin EOF — works when process is spawned directly (not via npm wrapper chain)
27
- process.stdin.on('end', () => {
28
- console.error('stdin closed (parent disconnected) — shutting down');
29
- shutdown();
30
- });
31
- // 2. Parent PID polling — catches cases where npm/sh wrapper absorbs the signal
32
- // but the actual parent (OpenCode) is gone. On Linux, orphaned processes get
33
- // reparented to PID 1 (init/systemd).
34
- // Note: process.ppid is cached at startup and doesn't update, so we read
35
- // the live value from /proc/self/stat.
36
- const originalPpid = process.ppid;
37
- const getLivePpid = () => {
38
- try {
39
- const stat = fs.readFileSync('/proc/self/stat', 'utf8');
40
- return parseInt(stat.split(' ')[3], 10);
41
- }
42
- catch {
43
- return process.ppid; // Fallback for non-Linux
84
+ const shutdown = async () => {
85
+ if (shuttingDown) {
86
+ return;
44
87
  }
45
- };
46
- const parentWatchdog = setInterval(() => {
47
- const currentPpid = getLivePpid();
48
- if (currentPpid !== originalPpid) {
49
- console.error(`Parent changed (${originalPpid} → ${currentPpid}) — shutting down`);
88
+ shuttingDown = true;
89
+ console.error("Shutting down...");
90
+ if (parentWatchdog) {
50
91
  clearInterval(parentWatchdog);
51
- shutdown();
92
+ parentWatchdog = undefined;
93
+ }
94
+ if (lockRetryInterval) {
95
+ clearInterval(lockRetryInterval);
96
+ lockRetryInterval = undefined;
97
+ }
98
+ if (debouncedNotificationTimer) {
99
+ clearTimeout(debouncedNotificationTimer);
100
+ debouncedNotificationTimer = undefined;
52
101
  }
53
- }, 5_000);
54
- // 3. Initialize WhatsApp in the background — but only if no other instance
55
- // already owns the WhatsApp connection. This prevents status 515/440
56
- // when the host spawns multiple MCP server instances.
57
- if (acquireWhatsAppLock(LOCK_FILE)) {
58
- console.error("WhatsApp lock acquired — connecting...");
102
+ setMessageNotificationHandler(undefined);
103
+ await closeWhatsApp();
104
+ if (ownsWhatsAppLock) {
105
+ releaseWhatsAppLock(LOCK_FILE);
106
+ }
107
+ closeDb();
108
+ if (httpController) {
109
+ await httpController.closeHttpServer();
110
+ }
111
+ if (stdioServer) {
112
+ if (stdioSessionId) {
113
+ resourceSubscriptions.removeSession(stdioSessionId);
114
+ stdioSessionId = undefined;
115
+ }
116
+ await stdioServer.close();
117
+ }
118
+ process.exit(0);
119
+ };
120
+ if (options.http) {
121
+ const apiKey = process.env.MCP_API_KEY;
122
+ if (!apiKey) {
123
+ throw new Error("MCP_API_KEY is required when using --http mode");
124
+ }
125
+ httpController = await createHttpServer(options.port, options.host, apiKey, resourceSubscriptions);
126
+ console.error(`MCP server running on HTTP ${options.host}:${httpController.port}`);
59
127
  initWhatsApp().catch((err) => {
60
128
  console.error("Failed to initialize WhatsApp:", err);
61
129
  });
62
130
  }
63
131
  else {
64
- console.error("Another instance owns the WhatsApp connection running as read-only from SQLite");
65
- resolveConnectionAsReadOnly();
66
- // Periodically check if the lock holder died — if so, take over
67
- const lockRetryInterval = setInterval(() => {
68
- if (acquireWhatsAppLock(LOCK_FILE)) {
69
- console.error("Lock holder died — upgrading to read-write mode");
70
- clearInterval(lockRetryInterval);
71
- initWhatsApp().catch((err) => {
72
- console.error("Failed to initialize WhatsApp after lock takeover:", err);
73
- });
132
+ // 2. Create MCP server and connect to stdio transport FIRST
133
+ // so the client doesn't time out waiting for the initialize handshake.
134
+ stdioServer = new McpServer({
135
+ name: "whatsapp",
136
+ version: "1.0.0",
137
+ }, {
138
+ capabilities: {
139
+ resources: {
140
+ subscribe: true,
141
+ listChanged: true,
142
+ },
143
+ },
144
+ });
145
+ const activeStdioServer = stdioServer;
146
+ registerTools(activeStdioServer);
147
+ registerResources(activeStdioServer);
148
+ stdioSessionId = `stdio-${randomUUID()}`;
149
+ resourceSubscriptions.registerSession(stdioSessionId, (uri) => activeStdioServer.server.sendResourceUpdated({ uri }));
150
+ registerResourceSubscriptionHandlers(activeStdioServer, stdioSessionId, resourceSubscriptions);
151
+ const transport = new StdioServerTransport();
152
+ await activeStdioServer.connect(transport);
153
+ console.error("MCP server running on stdio");
154
+ // Detect parent death via two mechanisms:
155
+ // 1. stdin EOF — works when process is spawned directly (not via npm wrapper chain)
156
+ process.stdin.on("end", () => {
157
+ console.error("stdin closed (parent disconnected) — shutting down");
158
+ shutdown();
159
+ });
160
+ // 2. Parent PID polling — catches cases where npm/sh wrapper absorbs the signal
161
+ // but the actual parent (OpenCode) is gone. On Linux, orphaned processes get
162
+ // reparented to PID 1 (init/systemd).
163
+ // Note: process.ppid is cached at startup and doesn't update, so we read
164
+ // the live value from /proc/self/stat.
165
+ const originalPpid = process.ppid;
166
+ const getLivePpid = () => {
167
+ try {
168
+ const stat = fs.readFileSync("/proc/self/stat", "utf8");
169
+ return parseInt(stat.split(" ")[3], 10);
170
+ }
171
+ catch {
172
+ return process.ppid; // Fallback for non-Linux
173
+ }
174
+ };
175
+ parentWatchdog = setInterval(() => {
176
+ const currentPpid = getLivePpid();
177
+ if (currentPpid !== originalPpid) {
178
+ console.error(`Parent changed (${originalPpid} → ${currentPpid}) — shutting down`);
179
+ shutdown();
74
180
  }
75
- }, 10_000); // Check every 10 seconds
76
- // Clean up the interval on shutdown
77
- process.on("SIGINT", () => clearInterval(lockRetryInterval));
78
- process.on("SIGTERM", () => clearInterval(lockRetryInterval));
181
+ }, 5_000);
182
+ // 3. Initialize WhatsApp in the background but only if no other instance
183
+ // already owns the WhatsApp connection. This prevents status 515/440
184
+ // when the host spawns multiple MCP server instances.
185
+ if (acquireWhatsAppLock(LOCK_FILE)) {
186
+ ownsWhatsAppLock = true;
187
+ console.error("WhatsApp lock acquired — connecting...");
188
+ initWhatsApp().catch((err) => {
189
+ console.error("Failed to initialize WhatsApp:", err);
190
+ });
191
+ }
192
+ else {
193
+ console.error("Another instance owns the WhatsApp connection — running as read-only from SQLite");
194
+ resolveConnectionAsReadOnly();
195
+ // Periodically check if the lock holder died — if so, take over
196
+ lockRetryInterval = setInterval(() => {
197
+ if (acquireWhatsAppLock(LOCK_FILE)) {
198
+ ownsWhatsAppLock = true;
199
+ console.error("Lock holder died — upgrading to read-write mode");
200
+ if (lockRetryInterval) {
201
+ clearInterval(lockRetryInterval);
202
+ lockRetryInterval = undefined;
203
+ }
204
+ initWhatsApp().catch((err) => {
205
+ console.error("Failed to initialize WhatsApp after lock takeover:", err);
206
+ });
207
+ }
208
+ }, 10_000); // Check every 10 seconds
209
+ }
79
210
  }
80
211
  // 4. Graceful shutdown
81
- const shutdown = async () => {
82
- console.error("Shutting down...");
83
- await closeWhatsApp();
84
- releaseWhatsAppLock(LOCK_FILE);
85
- closeDb();
86
- await server.close();
87
- process.exit(0);
88
- };
89
212
  process.on("SIGINT", shutdown);
90
213
  process.on("SIGTERM", shutdown);
91
214
  process.on("unhandledRejection", (reason) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare const NEW_MESSAGES_RESOURCE_URI = "whatsapp://messages/new";
3
+ type ResourceUpdateSender = (uri: string) => Promise<void> | void;
4
+ export type ResourceSubscriptionStore = {
5
+ registerSession: (sessionId: string, sendResourceUpdated: ResourceUpdateSender) => void;
6
+ removeSession: (sessionId: string) => void;
7
+ subscribe: (sessionId: string, uri: string) => void;
8
+ unsubscribe: (sessionId: string, uri: string) => void;
9
+ notifyResourceUpdated: (uri: string) => Promise<void>;
10
+ getSubscriberCount: (uri: string) => number;
11
+ };
12
+ export declare function createResourceSubscriptionStore(): ResourceSubscriptionStore;
13
+ export declare function registerResources(server: McpServer): void;
14
+ export declare function registerResourceSubscriptionHandlers(server: McpServer, sessionId: string, store: ResourceSubscriptionStore): void;
15
+ export {};
16
+ //# sourceMappingURL=resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,eAAO,MAAM,yBAAyB,4BAA4B,CAAC;AAEnE,KAAK,oBAAoB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAElE,MAAM,MAAM,yBAAyB,GAAG;IACtC,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,mBAAmB,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACxF,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,qBAAqB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;CAC7C,CAAC;AAEF,wBAAgB,+BAA+B,IAAI,yBAAyB,CAgE3E;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAiBzD;AAED,wBAAgB,oCAAoC,CAClD,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,yBAAyB,GAC/B,IAAI,CAUN"}
@@ -0,0 +1,84 @@
1
+ import { SubscribeRequestSchema, UnsubscribeRequestSchema } from "@modelcontextprotocol/sdk/types.js";
2
+ import { getRecentMessages } from "./db.js";
3
+ export const NEW_MESSAGES_RESOURCE_URI = "whatsapp://messages/new";
4
+ export function createResourceSubscriptionStore() {
5
+ const subscriptions = new Map();
6
+ const sessionSenders = new Map();
7
+ const subscribe = (sessionId, uri) => {
8
+ const sessionIds = subscriptions.get(uri) ?? new Set();
9
+ sessionIds.add(sessionId);
10
+ subscriptions.set(uri, sessionIds);
11
+ };
12
+ const unsubscribe = (sessionId, uri) => {
13
+ const sessionIds = subscriptions.get(uri);
14
+ if (!sessionIds) {
15
+ return;
16
+ }
17
+ sessionIds.delete(sessionId);
18
+ if (sessionIds.size === 0) {
19
+ subscriptions.delete(uri);
20
+ }
21
+ };
22
+ const removeSession = (sessionId) => {
23
+ sessionSenders.delete(sessionId);
24
+ for (const [uri, sessionIds] of subscriptions) {
25
+ sessionIds.delete(sessionId);
26
+ if (sessionIds.size === 0) {
27
+ subscriptions.delete(uri);
28
+ }
29
+ }
30
+ };
31
+ return {
32
+ registerSession(sessionId, sendResourceUpdated) {
33
+ sessionSenders.set(sessionId, sendResourceUpdated);
34
+ },
35
+ removeSession,
36
+ subscribe,
37
+ unsubscribe,
38
+ async notifyResourceUpdated(uri) {
39
+ const sessionIds = subscriptions.get(uri);
40
+ if (!sessionIds || sessionIds.size === 0) {
41
+ return;
42
+ }
43
+ for (const sessionId of [...sessionIds]) {
44
+ const sender = sessionSenders.get(sessionId);
45
+ if (!sender) {
46
+ sessionIds.delete(sessionId);
47
+ continue;
48
+ }
49
+ await sender(uri);
50
+ }
51
+ if (sessionIds.size === 0) {
52
+ subscriptions.delete(uri);
53
+ }
54
+ },
55
+ getSubscriberCount(uri) {
56
+ return subscriptions.get(uri)?.size ?? 0;
57
+ },
58
+ };
59
+ }
60
+ export function registerResources(server) {
61
+ server.resource("new_messages", NEW_MESSAGES_RESOURCE_URI, async (uri) => {
62
+ const messages = getRecentMessages(10);
63
+ return {
64
+ contents: [
65
+ {
66
+ uri: uri.href,
67
+ mimeType: "application/json",
68
+ text: JSON.stringify(messages),
69
+ },
70
+ ],
71
+ };
72
+ });
73
+ }
74
+ export function registerResourceSubscriptionHandlers(server, sessionId, store) {
75
+ server.server.setRequestHandler(SubscribeRequestSchema, async (request) => {
76
+ store.subscribe(sessionId, request.params.uri);
77
+ return {};
78
+ });
79
+ server.server.setRequestHandler(UnsubscribeRequestSchema, async (request) => {
80
+ store.unsubscribe(sessionId, request.params.uri);
81
+ return {};
82
+ });
83
+ }
84
+ //# sourceMappingURL=resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA0BpE;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAmdrD"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4BpE;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAidrD"}
package/dist/tools.js CHANGED
@@ -1,16 +1,17 @@
1
1
  import { z } from "zod";
2
2
  import fs from "fs";
3
3
  import path from "path";
4
- import { getChats, getChat, getMessages, searchMessages, searchContacts, getMessageContext, getRecipientInfo, sendTextMessage, sendFileMessage, downloadMessageMedia, transcribeVoiceNote, deleteMessage, deleteChat, updateContact, getMyInfo, resolveUnknownContacts, } from "./whatsapp.js";
4
+ import { getChats, getChat, getMessages, searchMessages, searchContacts, getMessageContext, getRecipientInfo, sendTextMessage, sendFileMessage, downloadMessageMedia, transcribeVoiceNote, deleteMessage, deleteChat, updateContact, getMyInfo, resolveUnknownContacts, getReadOnlyErrorMessage, } from "./whatsapp.js";
5
5
  import { getDb, getUnreadChats } from "./db.js";
6
6
  import { importContactsFromVcf } from "./import-contacts.js";
7
7
  import { validateFilePath } from "./utils.js";
8
+ import { LOCK_FILE } from "./paths.js";
8
9
  /**
9
10
  * Register all WhatsApp MCP tools on the server.
10
11
  */
11
12
  export function registerTools(server) {
12
13
  // ─── Reading Tools ──────────────────────────────────────────
13
- server.tool("list_chats", "List all WhatsApp chats sorted by last activity. Optionally filter by name.", {
14
+ server.tool("list_chats", "List all WhatsApp chats sorted by last activity. Optionally filter by name. Contacts with multiple WhatsApp identities are automatically merged into a single entry.", {
14
15
  nameFilter: z.string().optional().describe("Filter chats by name (case-insensitive substring match)"),
15
16
  limit: z.number().min(1).max(100).default(20).describe("Max number of chats to return"),
16
17
  }, async ({ nameFilter, limit }) => {
@@ -42,7 +43,7 @@ export function registerTools(server) {
42
43
  return { content: [{ type: "text", text: `Error: ${err.message}` }], isError: true };
43
44
  }
44
45
  });
45
- server.tool("list_messages", "Get messages from a specific chat. Returns most recent messages first.", {
46
+ server.tool("list_messages", "Get messages from a specific chat. Returns most recent messages first. Accepts any contact identifier. Messages from all of a contact's identities are returned transparently.", {
46
47
  jid: z.string().describe("Chat JID or phone number"),
47
48
  limit: z.number().min(1).max(100).default(50).describe("Number of messages to return"),
48
49
  }, async ({ jid, limit }) => {
@@ -56,7 +57,7 @@ export function registerTools(server) {
56
57
  return { content: [{ type: "text", text: `Error: ${err.message}` }], isError: true };
57
58
  }
58
59
  });
59
- server.tool("search_messages", "Substring search across messages. Can search in a specific chat or across all chats.", {
60
+ server.tool("search_messages", "Substring search across messages. Can search in a specific chat or across all chats. Search results automatically unify contacts with multiple identities into a single canonical entry.", {
60
61
  query: z.string().describe("Text to search for (case-insensitive)"),
61
62
  jid: z.string().optional().describe("Optional: limit search to a specific chat JID"),
62
63
  }, async ({ query, jid }) => {
@@ -80,7 +81,7 @@ export function registerTools(server) {
80
81
  return { content: [{ type: "text", text: `Error: ${err.message}` }], isError: true };
81
82
  }
82
83
  });
83
- server.tool("search_contacts", "Find contacts by name or phone number.", {
84
+ server.tool("search_contacts", "Find contacts by name or phone number. Contacts with multiple WhatsApp identities are automatically deduplicated into a single entry.", {
84
85
  query: z.string().describe("Name or phone number to search for"),
85
86
  }, async ({ query }) => {
86
87
  try {
@@ -123,7 +124,7 @@ export function registerTools(server) {
123
124
  return {
124
125
  content: [{
125
126
  type: "text",
126
- text: "Not connected yet — WhatsApp identity not available. Try again in a moment.",
127
+ text: getReadOnlyErrorMessage(LOCK_FILE),
127
128
  }],
128
129
  isError: true,
129
130
  };
@@ -151,11 +152,14 @@ export function registerTools(server) {
151
152
  return { content: [{ type: "text", text: `Error: ${err.message}` }], isError: true };
152
153
  }
153
154
  });
154
- server.tool("sync_contacts", "Import phone contacts from the contacts/contacts.vcf file into the database. " +
155
+ server.tool("sync_contacts", "Import phone contacts from a VCF file or string into the database. " +
155
156
  "Matches phone numbers from the VCF to existing WhatsApp JIDs and updates their display names. " +
156
- "Use this after a fresh QR code scan to populate contact names from your address book.", {}, async () => {
157
+ "Use this after a fresh QR code scan to populate contact names from your address book. " +
158
+ "Optionally pass vcf_content to sync from a string instead of the default file.", {
159
+ vcf_content: z.string().optional().describe("Optional VCF content as a string. If provided, syncs from this content instead of reading from file."),
160
+ }, async ({ vcf_content }) => {
157
161
  try {
158
- const result = importContactsFromVcf(getDb());
162
+ const result = importContactsFromVcf(getDb(), vcf_content);
159
163
  return {
160
164
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
161
165
  };
@@ -164,9 +168,7 @@ export function registerTools(server) {
164
168
  return { content: [{ type: "text", text: `Error: ${err.message}` }], isError: true };
165
169
  }
166
170
  });
167
- server.tool("get_unread_messages", "Get all chats with unread messages and their recent messages in one call. " +
168
- "Returns each unread chat with its name, unread count, and the last N messages. " +
169
- "Use this for a quick \"what did I miss\" summary.", {
171
+ server.tool("get_unread_messages", "Get all chats with unread messages and their recent messages in one call. Returns each unread chat with its name, unread count, and the last N messages. Contacts with multiple WhatsApp identities are automatically unified into a single view. Use this for a quick \"what did I miss\" summary.", {
170
172
  messagesPerChat: z.number().min(1).max(20).default(5).describe("Number of recent messages to include per chat"),
171
173
  }, async ({ messagesPerChat }) => {
172
174
  try {
@@ -186,10 +188,7 @@ export function registerTools(server) {
186
188
  }
187
189
  });
188
190
  // ─── Writing Tools ──────────────────────────────────────────
189
- server.tool("send_message", "Send a text message to a WhatsApp contact or group. " +
190
- "Optionally reply to a specific message by providing its ID. " +
191
- "First call without confirmed=true returns a preview for user approval. " +
192
- "Call again with confirmed=true to actually send.", {
191
+ server.tool("send_message", "Send a text message to a WhatsApp contact or group. Optionally reply to a specific message by providing its ID. First call without confirmed=true returns a preview for user approval. Call again with confirmed=true to actually send. Messages are automatically routed to the contact's most recently active thread.", {
193
192
  jid: z.string().describe("Recipient JID (phone@s.whatsapp.net), group JID, or phone number"),
194
193
  text: z.string().describe("Message text to send"),
195
194
  quotedMessageId: z.string().optional().describe("Message ID to reply to / quote. Get this from list_messages or search_messages."),