@cachly-dev/mcp-server 0.5.47 → 0.5.49
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/index.d.ts +5 -2
- package/dist/index.js +122 -23
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +145 -47
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cachly-dev/mcp-server",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.49",
|
|
4
4
|
"mcpName": "io.github.cachly-dev/mcp-server",
|
|
5
5
|
"description": "AI memory brain for Claude Code, Cursor, Copilot & Windsurf — persistent sessions, lessons learned, semantic search, team brain. 51 MCP tools.",
|
|
6
6
|
"type": "module",
|
package/src/index.ts
CHANGED
|
@@ -55,7 +55,7 @@ import { Redis } from 'ioredis';
|
|
|
55
55
|
const API_URL = process.env.CACHLY_API_URL ?? 'https://api.cachly.dev';
|
|
56
56
|
const JWT = process.env.CACHLY_JWT ?? '';
|
|
57
57
|
const EMBED_MODEL = process.env.CACHLY_EMBED_MODEL ?? '';
|
|
58
|
-
const CURRENT_VERSION = '0.5.
|
|
58
|
+
const CURRENT_VERSION = '0.5.49';
|
|
59
59
|
/**
|
|
60
60
|
* ┌──────────────────────────────────────────────────────────────────────┐
|
|
61
61
|
* │ EMBEDDING PROVIDER — pluggable, client-side first │
|
|
@@ -425,6 +425,9 @@ const SEGMENT_RE = /([\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff\uac00
|
|
|
425
425
|
|
|
426
426
|
// RTL Unicode ranges: Arabic (U+0600–U+06FF + extended), Hebrew (U+0590–U+05FF)
|
|
427
427
|
const RTL_RE = /[\u0590-\u05ff\u0600-\u06ff\u0750-\u077f\u08a0-\u08ff\ufb1d-\ufb4f\ufb50-\ufdff\ufe70-\ufeff]/;
|
|
428
|
+
// Distinguish Arabic from Hebrew within RTL segments
|
|
429
|
+
const HEBREW_CHAR_RE = /[\u0590-\u05ff\ufb1d-\ufb4f]/;
|
|
430
|
+
const ARABIC_CHAR_RE = /[\u0600-\u06ff\u0750-\u077f\u08a0-\u08ff\ufb50-\ufdff\ufe70-\ufeff]/;;
|
|
428
431
|
|
|
429
432
|
// ── Katakana → Romaji conversion table (Hepburn system) ──────────────────────
|
|
430
433
|
// Digraphs must be listed before single chars so they match first.
|
|
@@ -504,12 +507,49 @@ function katakanaToRomaji(kata: string): string {
|
|
|
504
507
|
/**
|
|
505
508
|
* Arabic light stemmer — strips definite article and common prefix particles.
|
|
506
509
|
* Handles: ال (al-), و (wa-), ب (bi-), ل (li-), ف (fa-), ك (ka-).
|
|
510
|
+
* Runs iteratively (max 3 passes) so compound prefixes like فال- are fully
|
|
511
|
+
* resolved: فالخطأ → الخطأ → خطأ.
|
|
507
512
|
* Only strips when the result is still ≥ 3 chars to avoid over-stemming.
|
|
508
513
|
*/
|
|
509
514
|
function arabicLightStem(word: string): string {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
515
|
+
let result = word;
|
|
516
|
+
for (let i = 0; i < 3; i++) {
|
|
517
|
+
const prev = result;
|
|
518
|
+
if (result.startsWith('ال') && result.length > 4) {
|
|
519
|
+
result = result.slice(2);
|
|
520
|
+
} else if (result.length > 3 && 'وبلفك'.includes(result[0]) && RTL_RE.test(result[1])) {
|
|
521
|
+
result = result.slice(1);
|
|
522
|
+
}
|
|
523
|
+
if (result === prev) break; // stable — no more prefixes to strip
|
|
524
|
+
}
|
|
525
|
+
return result;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Hebrew light stemmer — strips the definite article and common prefix particles
|
|
530
|
+
* that attach directly to words (no space) in Hebrew.
|
|
531
|
+
*
|
|
532
|
+
* Handles:
|
|
533
|
+
* ה (ha-) — definite article: הפריסה → פריסה
|
|
534
|
+
* ו (ve-/u-) — conjunction “and”: ופריסה → פריסה
|
|
535
|
+
* ב (be-/bi-) — preposition “in”: בסביבה → סביבה
|
|
536
|
+
* ל (le-/li-) — preposition “for”: לשרת → שרת
|
|
537
|
+
* מ (mi-/me-) — preposition “from”: מהשרת → השרת → שרת
|
|
538
|
+
* כ (ke-/ki-) — preposition “like”: כשרת → שרת
|
|
539
|
+
*
|
|
540
|
+
* Iterative (max 3 passes): מהפריסה → הפריסה → פריסה.
|
|
541
|
+
* Only strips when result is still ≥ 3 chars.
|
|
542
|
+
*/
|
|
543
|
+
function hebrewLightStem(word: string): string {
|
|
544
|
+
let result = word;
|
|
545
|
+
for (let i = 0; i < 3; i++) {
|
|
546
|
+
const prev = result;
|
|
547
|
+
if (result.length > 3 && 'הובלמכ'.includes(result[0]) && HEBREW_CHAR_RE.test(result[1])) {
|
|
548
|
+
result = result.slice(1);
|
|
549
|
+
}
|
|
550
|
+
if (result === prev) break;
|
|
551
|
+
}
|
|
552
|
+
return result;
|
|
513
553
|
}
|
|
514
554
|
|
|
515
555
|
// ── Cross-lingual tech term dictionary ────────────────────────────────────────
|
|
@@ -520,8 +560,8 @@ function arabicLightStem(word: string): string {
|
|
|
520
560
|
// Keys must be lowercase. CJK values will be bigram-expanded at use time.
|
|
521
561
|
const CROSS_LINGUAL_MAP = new Map<string, string[]>([
|
|
522
562
|
// English → all
|
|
523
|
-
['deploy', ['デプロイ', '部署', '배포', 'deployment', 'deploying', 'bereitstellen', 'bereitstellung', 'déployer', 'déploiement', 'desplegar', 'despliegue', 'distribuire', 'distribuzione', 'implantar', 'implantação']],
|
|
524
|
-
['deployment', ['デプロイ', '部署', '배포', 'deploy', 'bereitstellung', 'déploiement', 'despliegue', 'distribuzione', 'implantação']],
|
|
563
|
+
['deploy', ['デプロイ', '部署', '배포', 'deployment', 'deploying', 'نشر', 'פריסה', 'bereitstellen', 'bereitstellung', 'déployer', 'déploiement', 'desplegar', 'despliegue', 'distribuire', 'distribuzione', 'implantar', 'implantação']],
|
|
564
|
+
['deployment', ['デプロイ', '部署', '배포', 'deploy', 'نشر', 'פריסה', 'bereitstellung', 'déploiement', 'despliegue', 'distribuzione', 'implantação']],
|
|
525
565
|
['container', ['コンテナ', '容器', '컨테이너', 'docker']],
|
|
526
566
|
['server', ['サーバー', 'サーバ', '服务器', '서버', 'سيرفر', 'שרת']],
|
|
527
567
|
['database', ['データベース', '数据库', '데이터베이스', 'db', 'قاعدة البيانات', 'datenbank', 'base de données', 'base de datos', 'banco de dados']],
|
|
@@ -532,6 +572,10 @@ const CROSS_LINGUAL_MAP = new Map<string, string[]>([
|
|
|
532
572
|
['build', ['ビルド', '构建', '빌드', 'بناء', 'בנייה', 'bauen', 'construire', 'construir', 'costruire']],
|
|
533
573
|
['test', ['テスト', '测试', '테스트', 'اختبار', 'בדיקה', 'testen', 'tester', 'probar', 'testare', 'testar']],
|
|
534
574
|
['auth', ['認証', '认证', '인증', 'authentication', 'login', 'oauth', 'مصادقة', 'אימות', 'authentifizierung', 'authentification', 'autenticación', 'autenticazione', 'autenticação']],
|
|
575
|
+
['authentication', ['auth', 'مصادقة', 'אימות', '認証', '认证', '인증', 'login', 'oauth']],
|
|
576
|
+
['environment', ['環境', '环境', '환경', 'env', 'بيئة', 'סביבה', 'umgebung', 'environnement', 'entorno', 'ambiente']],
|
|
577
|
+
['secret', ['key', 'token', 'password', 'jwt', 'مفتاح', 'מפתח', 'geheimnis', 'schlüssel', 'clave', 'clé', 'chiave', 'chave']],
|
|
578
|
+
['problem', ['error', 'issue', 'bug', 'failure', 'مشكلة', 'بعيا', '問題', '問題', '오류', 'fehler', 'problème', 'problema']],
|
|
535
579
|
['kubernetes', ['クベルネテス', 'k8s', 'kube']],
|
|
536
580
|
['network', ['ネットワーク', '网络', '네트워크', 'شبكة', 'רשת', 'netzwerk', 'réseau', 'red', 'rete', 'rede']],
|
|
537
581
|
['timeout', ['タイムアウト', '超时', '타임아웃', 'مهلة']],
|
|
@@ -570,7 +614,7 @@ const CROSS_LINGUAL_MAP = new Map<string, string[]>([
|
|
|
570
614
|
['ci', ['pipeline', 'github actions', 'gitlab', 'jenkins', 'build']],
|
|
571
615
|
['cd', ['deploy', 'deployment', 'release']],
|
|
572
616
|
['debug', ['デバッグ', '调试', '디버그', 'debugging', 'breakpoint', 'تصحيح', 'איתור באגים', 'debuggen', 'déboguer', 'depurar']],
|
|
573
|
-
['crash', ['クラッシュ', '崩溃', '크래시', 'panic', 'segfault', 'انهيار', 'absturz', 'panne', 'plantage', 'caída', 'falha']],
|
|
617
|
+
['crash', ['クラッシュ', '崩溃', '크래시', 'panic', 'segfault', 'انهيار', 'קריסה', 'absturz', 'panne', 'plantage', 'caída', 'falha']],
|
|
574
618
|
['restart', ['再起動', '重启', '재시작', 'reboot', 'إعادة تشغيل', 'הפעלה מחדש', 'neustart', 'redémarrer', 'reiniciar', 'riavviare']],
|
|
575
619
|
['permission', ['権限', '权限', '권한', 'access', 'acl', 'chmod', 'صلاحية', 'הרשאה', 'berechtigung', 'berechtigungen', 'permiso', 'permesso', 'permissão']],
|
|
576
620
|
// Japanese katakana → English
|
|
@@ -671,43 +715,93 @@ const CROSS_LINGUAL_MAP = new Map<string, string[]>([
|
|
|
671
715
|
['재시작', ['restart']],
|
|
672
716
|
['권한', ['permission']],
|
|
673
717
|
// Arabic → English
|
|
674
|
-
['خطأ',
|
|
675
|
-
['إصلاح',
|
|
676
|
-
['بناء',
|
|
677
|
-
['اختبار',
|
|
678
|
-
['مصادقة',
|
|
679
|
-
['إعدادات',
|
|
680
|
-
['تثبيت',
|
|
681
|
-
['تحديث',
|
|
682
|
-
['سجل',
|
|
683
|
-
['صورة',
|
|
684
|
-
['خدمة',
|
|
685
|
-
['نسخ احتياطي',
|
|
686
|
-
['مراقبة',
|
|
687
|
-
['اتصال',
|
|
688
|
-
['ذاكرة',
|
|
689
|
-
['تصحيح',
|
|
690
|
-
['شبكة',
|
|
718
|
+
['خطأ', ['error']],
|
|
719
|
+
['إصلاح', ['fix']],
|
|
720
|
+
['بناء', ['build']],
|
|
721
|
+
['اختبار', ['test']],
|
|
722
|
+
['مصادقة', ['auth', 'authentication']],
|
|
723
|
+
['إعدادات', ['config', 'configuration']],
|
|
724
|
+
['تثبيت', ['install']],
|
|
725
|
+
['تحديث', ['update', 'upgrade']],
|
|
726
|
+
['سجل', ['log']],
|
|
727
|
+
['صورة', ['image']],
|
|
728
|
+
['خدمة', ['service']],
|
|
729
|
+
['نسخ احتياطي', ['backup']],
|
|
730
|
+
['مراقبة', ['monitor', 'monitoring']],
|
|
731
|
+
['اتصال', ['connection']],
|
|
732
|
+
['ذاكرة', ['memory']],
|
|
733
|
+
['تصحيح', ['debug', 'debugging']],
|
|
734
|
+
['شبكة', ['network']],
|
|
735
|
+
// Additional Arabic → English (covering blog post examples + common terms)
|
|
736
|
+
['نشر', ['deploy', 'deployment']],
|
|
737
|
+
['انهيار', ['crash', 'panic']],
|
|
738
|
+
['طابور', ['queue']],
|
|
739
|
+
['رمز', ['token', 'secret']],
|
|
740
|
+
['كاش', ['cache']],
|
|
741
|
+
['منفذ', ['port']],
|
|
742
|
+
['سيرفر', ['server']],
|
|
743
|
+
['قاعدة البيانات', ['database', 'db']],
|
|
744
|
+
['إعادة تشغيل', ['restart', 'reboot']],
|
|
745
|
+
['صلاحية', ['permission', 'access']],
|
|
746
|
+
['تطبيق', ['application', 'app']],
|
|
747
|
+
['مفتاح', ['key', 'token', 'secret']],
|
|
748
|
+
['واجهة برمجية', ['api', 'interface']],
|
|
749
|
+
['فحص الصحة', ['healthcheck', 'health']],
|
|
750
|
+
['حاوية', ['container', 'docker']],
|
|
751
|
+
['عقدة', ['node']],
|
|
752
|
+
['سرعة', ['performance', 'speed']],
|
|
753
|
+
['قرص', ['disk', 'storage']],
|
|
754
|
+
['خادم', ['server']],
|
|
755
|
+
['برنامج', ['application', 'software', 'app']],
|
|
756
|
+
// Arabic terms from blog examples
|
|
757
|
+
['مشكلة', ['error', 'issue', 'bug', 'problem', 'failure']],
|
|
758
|
+
['بيئة', ['environment', 'env']],
|
|
759
|
+
['متغيرات', ['variables', 'env', 'environment']],
|
|
760
|
+
['إنتاج', ['production', 'prod']],
|
|
761
|
+
['سري', ['secret', 'key', 'token']],
|
|
762
|
+
['مفتاح سري', ['secret', 'key']],
|
|
691
763
|
// Hebrew → English
|
|
692
|
-
['שגיאה',
|
|
693
|
-
['תיקון',
|
|
694
|
-
['בנייה',
|
|
695
|
-
['בדיקה',
|
|
696
|
-
['אימות',
|
|
697
|
-
['הגדרות',
|
|
698
|
-
['התקנה',
|
|
699
|
-
['עדכון',
|
|
700
|
-
['יומן',
|
|
701
|
-
['שרת',
|
|
702
|
-
['שירות',
|
|
703
|
-
['גיבוי',
|
|
704
|
-
['ניטור',
|
|
705
|
-
['חיבור',
|
|
706
|
-
['זיכרון',
|
|
707
|
-
['רשת',
|
|
708
|
-
['תמונה',
|
|
709
|
-
['סיסמה',
|
|
710
|
-
['הרשאה',
|
|
764
|
+
['שגיאה', ['error']],
|
|
765
|
+
['תיקון', ['fix']],
|
|
766
|
+
['בנייה', ['build']],
|
|
767
|
+
['בדיקה', ['test']],
|
|
768
|
+
['אימות', ['auth', 'authentication']],
|
|
769
|
+
['הגדרות', ['config', 'configuration']],
|
|
770
|
+
['התקנה', ['install']],
|
|
771
|
+
['עדכון', ['update', 'upgrade']],
|
|
772
|
+
['יומן', ['log']],
|
|
773
|
+
['שרת', ['server']],
|
|
774
|
+
['שירות', ['service']],
|
|
775
|
+
['גיבוי', ['backup']],
|
|
776
|
+
['ניטור', ['monitor', 'monitoring']],
|
|
777
|
+
['חיבור', ['connection']],
|
|
778
|
+
['זיכרון', ['memory']],
|
|
779
|
+
['רשת', ['network']],
|
|
780
|
+
['תמונה', ['image']],
|
|
781
|
+
['סיסמה', ['password']],
|
|
782
|
+
['הרשאה', ['permission', 'access']],
|
|
783
|
+
// Additional Hebrew → English (covering blog post examples + common terms)
|
|
784
|
+
['קריסה', ['crash', 'panic']],
|
|
785
|
+
['תור', ['queue']],
|
|
786
|
+
['מטמון', ['cache']],
|
|
787
|
+
['אסימון', ['token', 'secret']],
|
|
788
|
+
['פורט', ['port']],
|
|
789
|
+
['איתור באגים', ['debug', 'debugging']],
|
|
790
|
+
['הפעלה מחדש', ['restart', 'reboot']],
|
|
791
|
+
['מיכל', ['container', 'docker']],
|
|
792
|
+
['יישום', ['application', 'app']],
|
|
793
|
+
['מפתח', ['key', 'token', 'secret']],
|
|
794
|
+
['בדיקת תקינות', ['healthcheck', 'health']],
|
|
795
|
+
['ממשק תכנות', ['api', 'interface']],
|
|
796
|
+
['ביצועים', ['performance']],
|
|
797
|
+
['אחסון', ['storage', 'disk']],
|
|
798
|
+
// Hebrew terms from blog examples
|
|
799
|
+
['פריסה', ['deploy', 'deployment']],
|
|
800
|
+
['בעיה', ['error', 'issue', 'bug', 'problem']],
|
|
801
|
+
['סביבה', ['environment', 'env']],
|
|
802
|
+
['ייצור', ['production', 'prod']],
|
|
803
|
+
['סודי', ['secret', 'key', 'token']],
|
|
804
|
+
['מפתח סודי', ['secret', 'key']],
|
|
711
805
|
|
|
712
806
|
// ── European languages → English ─────────────────────────────────────────
|
|
713
807
|
// German (Deutsch) → English
|
|
@@ -912,8 +1006,9 @@ function expandCrossLingual(token: string): string[] {
|
|
|
912
1006
|
* Features:
|
|
913
1007
|
* • CJK → character bigrams
|
|
914
1008
|
* • Katakana → additionally emits Hepburn romaji tokens (enables romaji queries)
|
|
915
|
-
* • Arabic
|
|
916
|
-
* •
|
|
1009
|
+
* • Arabic → word tokenization + iterative prefix stemming (al-, wa-, bi-, li-, fa-)
|
|
1010
|
+
* • Hebrew → word tokenization + iterative prefix stemming (ha-, ve-, be-, le-, mi-, ke-)
|
|
1011
|
+
* • All scripts → cross-lingual synonym expansion (EN↔JA↔ZH↔KO↔AR↔HE↔DE↔FR↔ES↔IT↔PT)
|
|
917
1012
|
*/
|
|
918
1013
|
function tokenize(text: string): string[] {
|
|
919
1014
|
const tokens: string[] = [];
|
|
@@ -951,11 +1046,14 @@ function tokenize(text: string): string[] {
|
|
|
951
1046
|
}
|
|
952
1047
|
}
|
|
953
1048
|
} else if (RTL_RE.test(seg)) {
|
|
954
|
-
// RTL segment
|
|
1049
|
+
// RTL segment — split on spaces, apply language-specific prefix stemming
|
|
1050
|
+
// Arabic: strips ال/و/ب/ل/ف/ك prefixes iteratively
|
|
1051
|
+
// Hebrew: strips ה/ו/ב/ל/מ/כ prefixes iteratively
|
|
1052
|
+
const isHebrew = HEBREW_CHAR_RE.test(seg);
|
|
955
1053
|
const words = seg.trim().split(/\s+/);
|
|
956
1054
|
for (const w of words) {
|
|
957
1055
|
if (w.length <= 1 || STOPWORDS.has(w)) continue;
|
|
958
|
-
const stemmed = arabicLightStem(w);
|
|
1056
|
+
const stemmed = isHebrew ? hebrewLightStem(w) : arabicLightStem(w);
|
|
959
1057
|
if (stemmed.length > 1 && !STOPWORDS.has(stemmed)) tokens.push(stemmed);
|
|
960
1058
|
}
|
|
961
1059
|
} else {
|