tdk-api-wrapper 1.6.1 → 1.7.1
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/LICENSE +674 -21
- package/README.md +23 -3
- package/dist/{chunk-ZFWZXNGY.mjs → chunk-YY4WA2AO.mjs} +126 -142
- package/dist/chunk-ZG7YRT7V.mjs +279 -0
- package/dist/cli.js +2489 -2127
- package/dist/cli.mjs +12 -5
- package/dist/index.d.mts +23 -38
- package/dist/index.d.ts +23 -38
- package/dist/index.js +402 -143
- package/dist/index.mjs +8 -2
- package/dist/mcp-GBTXQJLW.mjs +9 -0
- package/package.json +13 -5
package/dist/index.js
CHANGED
|
@@ -37,13 +37,15 @@ __export(src_exports, {
|
|
|
37
37
|
TDKValidationError: () => TDKValidationError,
|
|
38
38
|
TURKISH_SUFFIXES: () => TURKISH_SUFFIXES,
|
|
39
39
|
TURKISH_VOWELS: () => TURKISH_VOWELS,
|
|
40
|
+
createMcpServer: () => createMcpServer,
|
|
40
41
|
getStemCandidates: () => getStemCandidates,
|
|
41
42
|
isVowel: () => isVowel,
|
|
42
43
|
restoreConsonantSoftening: () => restoreConsonantSoftening,
|
|
43
44
|
restoreGemination: () => restoreGemination,
|
|
44
45
|
restoreInfinitive: () => restoreInfinitive,
|
|
45
46
|
restoreVowelDrop: () => restoreVowelDrop,
|
|
46
|
-
restoreVowelNarrowing: () => restoreVowelNarrowing
|
|
47
|
+
restoreVowelNarrowing: () => restoreVowelNarrowing,
|
|
48
|
+
runMcpServer: () => runMcpServer
|
|
47
49
|
});
|
|
48
50
|
module.exports = __toCommonJS(src_exports);
|
|
49
51
|
|
|
@@ -74,11 +76,7 @@ var TDKNetworkError = class extends TDKError {
|
|
|
74
76
|
}
|
|
75
77
|
};
|
|
76
78
|
|
|
77
|
-
// src/
|
|
78
|
-
var TURKISH_VOWELS = "ae\u0131io\xF6u\xFC";
|
|
79
|
-
function isVowel(ch) {
|
|
80
|
-
return TURKISH_VOWELS.includes(ch);
|
|
81
|
-
}
|
|
79
|
+
// src/data/suffixes.ts
|
|
82
80
|
var TURKISH_SUFFIXES = [
|
|
83
81
|
// 9-letter composite suffixes
|
|
84
82
|
"lerimizden",
|
|
@@ -481,6 +479,12 @@ var TURKISH_SUFFIXES = [
|
|
|
481
479
|
"u",
|
|
482
480
|
"\xFC"
|
|
483
481
|
];
|
|
482
|
+
|
|
483
|
+
// src/morphology.ts
|
|
484
|
+
var TURKISH_VOWELS = "ae\u0131io\xF6u\xFC";
|
|
485
|
+
function isVowel(ch) {
|
|
486
|
+
return TURKISH_VOWELS.includes(ch);
|
|
487
|
+
}
|
|
484
488
|
function restoreConsonantSoftening(stem) {
|
|
485
489
|
if (stem.length < 2)
|
|
486
490
|
return [];
|
|
@@ -634,12 +638,7 @@ function getStemCandidates(word, minStemLength = 2, maxDepth = 4) {
|
|
|
634
638
|
return [...new Set(candidatesWithWeight.map((c) => c.candidate))];
|
|
635
639
|
}
|
|
636
640
|
|
|
637
|
-
// src/
|
|
638
|
-
var fs = __toESM(require("fs"));
|
|
639
|
-
var path = __toESM(require("path"));
|
|
640
|
-
var os = __toESM(require("os"));
|
|
641
|
-
var https = __toESM(require("https"));
|
|
642
|
-
var tls = __toESM(require("tls"));
|
|
641
|
+
// src/data/misspellings.ts
|
|
643
642
|
var COMMON_MISSPELLINGS = {
|
|
644
643
|
// -şey ile biten ve ayrı yazılması zorunlu söz öbekleri
|
|
645
644
|
her\u015Fey: "her \u015Fey",
|
|
@@ -793,75 +792,10 @@ var COMMON_MISSPELLINGS = {
|
|
|
793
792
|
babaanne: "babaanne"
|
|
794
793
|
};
|
|
795
794
|
var SEY_EXCEPTIONS = /* @__PURE__ */ new Set(["d\xFC\u015Fey", "e\u015Fey", "konsey", "jersey", "\u015Fey"]);
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
];
|
|
801
|
-
var KEYBOARD_COORDS = (() => {
|
|
802
|
-
const coords = {};
|
|
803
|
-
KEYBOARD_ROWS.forEach(([keys, offset], row) => {
|
|
804
|
-
[...keys].forEach((key, col) => {
|
|
805
|
-
coords[key] = [col + offset, row];
|
|
806
|
-
});
|
|
807
|
-
});
|
|
808
|
-
return coords;
|
|
809
|
-
})();
|
|
810
|
-
var DIACRITIC_SIBLINGS = {
|
|
811
|
-
\u0131: "i",
|
|
812
|
-
i: "\u0131",
|
|
813
|
-
\u00F6: "o",
|
|
814
|
-
o: "\xF6",
|
|
815
|
-
\u00FC: "u",
|
|
816
|
-
u: "\xFC",
|
|
817
|
-
\u015F: "s",
|
|
818
|
-
s: "\u015F",
|
|
819
|
-
\u00E7: "c",
|
|
820
|
-
c: "\xE7",
|
|
821
|
-
\u011F: "g",
|
|
822
|
-
g: "\u011F",
|
|
823
|
-
\u00E2: "a",
|
|
824
|
-
a: "\xE2"
|
|
825
|
-
};
|
|
826
|
-
var KEYBOARD_ROW_SUB_COST = 0.4;
|
|
827
|
-
var KEYBOARD_DIAGONAL_SUB_COST = 0.55;
|
|
828
|
-
var DIACRITIC_SUB_COST = 0.3;
|
|
829
|
-
var TRANSPOSITION_COST = 0.8;
|
|
830
|
-
function keyboardSubCost(a, b) {
|
|
831
|
-
if (a === b)
|
|
832
|
-
return 0;
|
|
833
|
-
if (DIACRITIC_SIBLINGS[a] === b)
|
|
834
|
-
return DIACRITIC_SUB_COST;
|
|
835
|
-
const pa = KEYBOARD_COORDS[a];
|
|
836
|
-
const pb = KEYBOARD_COORDS[b];
|
|
837
|
-
if (!pa || !pb)
|
|
838
|
-
return 1;
|
|
839
|
-
const dx = Math.abs(pa[0] - pb[0]);
|
|
840
|
-
const dy = Math.abs(pa[1] - pb[1]);
|
|
841
|
-
if (dy === 0 && dx <= 1 + 1e-9)
|
|
842
|
-
return KEYBOARD_ROW_SUB_COST;
|
|
843
|
-
if (dy === 1 && dx <= 1 + 1e-9)
|
|
844
|
-
return KEYBOARD_DIAGONAL_SUB_COST;
|
|
845
|
-
return 1;
|
|
846
|
-
}
|
|
847
|
-
var TDK = class {
|
|
848
|
-
static BASE_URL = "https://sozluk.gov.tr";
|
|
849
|
-
static AUDIO_API_HOST = "api.sozluk.gov.tr";
|
|
850
|
-
static KUBBEALTI_HOST = "eski.lugatim.com";
|
|
851
|
-
/**
|
|
852
|
-
* `eski.lugatim.com` (Kubbealtı Lugatı's data API) sends only its leaf
|
|
853
|
-
* certificate during the TLS handshake, omitting the intermediates a
|
|
854
|
-
* correctly configured server would include — a server-side misconfiguration,
|
|
855
|
-
* not something we should paper over by disabling verification. These are
|
|
856
|
-
* the two certificates the server *should* be sending (fetched from the
|
|
857
|
-
* leaf's own Authority Information Access URLs), supplied here so Node can
|
|
858
|
-
* still build a full, properly verified chain up to a root it already
|
|
859
|
-
* trusts (ISRG Root X1). If Let's Encrypt rotates this intermediate, this
|
|
860
|
-
* stops working and every Kubbealtı call fails closed to `null` — same
|
|
861
|
-
* fail-closed contract as the rest of this file's fragile integrations.
|
|
862
|
-
*/
|
|
863
|
-
static KUBBEALTI_EXTRA_CA = [
|
|
864
|
-
`-----BEGIN CERTIFICATE-----
|
|
795
|
+
|
|
796
|
+
// src/data/kubbealti-ca.ts
|
|
797
|
+
var KUBBEALTI_EXTRA_CA = [
|
|
798
|
+
`-----BEGIN CERTIFICATE-----
|
|
865
799
|
MIIE2jCCAsKgAwIBAgIQTr0klH4k05SALYSlL9WzGTANBgkqhkiG9w0BAQsFADAu
|
|
866
800
|
MQswCQYDVQQGEwJVUzENMAsGA1UEChMESVNSRzEQMA4GA1UEAxMHUm9vdCBZUjAe
|
|
867
801
|
Fw0yNTA5MDMwMDAwMDBaFw0yODA5MDIyMzU5NTlaMDMxCzAJBgNVBAYTAlVTMRYw
|
|
@@ -889,7 +823,7 @@ NA3wJdl4DDUuQSV8hBgx6zoI1ZSGORprDFux7c6rhc77QZMSRrEgomBeklervEve
|
|
|
889
823
|
86ylWmZ3WWHV6RLMi8xNvjd71r4EPIGgY7BZU/VPBkq+uA7Gb6mbJnFgV43uh3xy
|
|
890
824
|
LRFgxIAphIukwTGSMZZR+AI+Qnp0BYTWovHXozOf3H8r6hozEoT02JHn0AeTfA==
|
|
891
825
|
-----END CERTIFICATE-----`,
|
|
892
|
-
|
|
826
|
+
`-----BEGIN CERTIFICATE-----
|
|
893
827
|
MIIF9DCCA9ygAwIBAgIRAPJLbRf52a18scn+p4eCaZ8wDQYJKoZIhvcNAQELBQAw
|
|
894
828
|
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
|
895
829
|
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjYwNTEzMDAwMDAw
|
|
@@ -923,7 +857,112 @@ RGMuHGnzS3hFIrRTfKxrzUZ9RzQWzEG3K6fJ3r2nqSltkeytis9DIBoFY9VmVyjL
|
|
|
923
857
|
M71DMi+y1+TRSJVClEMwvA4yL++7q9XZx5r5wBRWB4kQTKH5qyoZnDw7iiuh1lID
|
|
924
858
|
yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
925
859
|
-----END CERTIFICATE-----`
|
|
926
|
-
|
|
860
|
+
];
|
|
861
|
+
|
|
862
|
+
// src/data/keyboard-layout.ts
|
|
863
|
+
var KEYBOARD_ROWS = [
|
|
864
|
+
["qwertyu\u0131op\u011F\xFC", 0],
|
|
865
|
+
["asdfghjkl\u015Fi", 0.5],
|
|
866
|
+
["zxcvbnm\xF6\xE7", 1]
|
|
867
|
+
];
|
|
868
|
+
var KEYBOARD_COORDS = (() => {
|
|
869
|
+
const coords = {};
|
|
870
|
+
KEYBOARD_ROWS.forEach(([keys, offset], row) => {
|
|
871
|
+
[...keys].forEach((key, col) => {
|
|
872
|
+
coords[key] = [col + offset, row];
|
|
873
|
+
});
|
|
874
|
+
});
|
|
875
|
+
return coords;
|
|
876
|
+
})();
|
|
877
|
+
var DIACRITIC_SIBLINGS = {
|
|
878
|
+
\u0131: "i",
|
|
879
|
+
i: "\u0131",
|
|
880
|
+
\u00F6: "o",
|
|
881
|
+
o: "\xF6",
|
|
882
|
+
\u00FC: "u",
|
|
883
|
+
u: "\xFC",
|
|
884
|
+
\u015F: "s",
|
|
885
|
+
s: "\u015F",
|
|
886
|
+
\u00E7: "c",
|
|
887
|
+
c: "\xE7",
|
|
888
|
+
\u011F: "g",
|
|
889
|
+
g: "\u011F",
|
|
890
|
+
\u00E2: "a",
|
|
891
|
+
a: "\xE2"
|
|
892
|
+
};
|
|
893
|
+
var KEYBOARD_ROW_SUB_COST = 0.4;
|
|
894
|
+
var KEYBOARD_DIAGONAL_SUB_COST = 0.55;
|
|
895
|
+
var DIACRITIC_SUB_COST = 0.3;
|
|
896
|
+
var TRANSPOSITION_COST = 0.8;
|
|
897
|
+
function keyboardSubCost(a, b) {
|
|
898
|
+
if (a === b)
|
|
899
|
+
return 0;
|
|
900
|
+
if (DIACRITIC_SIBLINGS[a] === b)
|
|
901
|
+
return DIACRITIC_SUB_COST;
|
|
902
|
+
const pa = KEYBOARD_COORDS[a];
|
|
903
|
+
const pb = KEYBOARD_COORDS[b];
|
|
904
|
+
if (!pa || !pb)
|
|
905
|
+
return 1;
|
|
906
|
+
const dx = Math.abs(pa[0] - pb[0]);
|
|
907
|
+
const dy = Math.abs(pa[1] - pb[1]);
|
|
908
|
+
if (dy === 0 && dx <= 1 + 1e-9)
|
|
909
|
+
return KEYBOARD_ROW_SUB_COST;
|
|
910
|
+
if (dy === 1 && dx <= 1 + 1e-9)
|
|
911
|
+
return KEYBOARD_DIAGONAL_SUB_COST;
|
|
912
|
+
return 1;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
// src/lib/edit-distance.ts
|
|
916
|
+
function damerauLevenshtein(a, b) {
|
|
917
|
+
const dp = Array.from({ length: a.length + 1 }, () => new Array(b.length + 1).fill(0));
|
|
918
|
+
for (let i = 0; i <= a.length; i++)
|
|
919
|
+
dp[i][0] = i;
|
|
920
|
+
for (let j = 0; j <= b.length; j++)
|
|
921
|
+
dp[0][j] = j;
|
|
922
|
+
for (let i = 1; i <= a.length; i++) {
|
|
923
|
+
for (let j = 1; j <= b.length; j++) {
|
|
924
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
925
|
+
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
926
|
+
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
|
|
927
|
+
dp[i][j] = Math.min(dp[i][j], dp[i - 2][j - 2] + cost);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
return dp[a.length][b.length];
|
|
932
|
+
}
|
|
933
|
+
function keyboardAwareDistance(a, b) {
|
|
934
|
+
const dp = Array.from({ length: a.length + 1 }, () => new Array(b.length + 1).fill(0));
|
|
935
|
+
for (let i = 0; i <= a.length; i++)
|
|
936
|
+
dp[i][0] = i;
|
|
937
|
+
for (let j = 0; j <= b.length; j++)
|
|
938
|
+
dp[0][j] = j;
|
|
939
|
+
for (let i = 1; i <= a.length; i++) {
|
|
940
|
+
for (let j = 1; j <= b.length; j++) {
|
|
941
|
+
const cost = keyboardSubCost(a[i - 1], b[j - 1]);
|
|
942
|
+
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
943
|
+
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
|
|
944
|
+
dp[i][j] = Math.min(dp[i][j], dp[i - 2][j - 2] + TRANSPOSITION_COST);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
return dp[a.length][b.length];
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
// src/lib/html.ts
|
|
952
|
+
function htmlToPlainText(html) {
|
|
953
|
+
return html.replace(/<br\s*\/?>/gi, "\n").replace(/<\/(p|div)>/gi, "\n\n").replace(/<[^>]+>/g, "").replace(/ /gi, " ").replace(/</gi, "<").replace(/>/gi, ">").replace(/"/gi, '"').replace(/'|’/gi, "'").replace(/&/gi, "&").replace(/[ \t]+/g, " ").replace(/[ \t]*\n[ \t]*/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
// src/tdk.ts
|
|
957
|
+
var fs = __toESM(require("fs"));
|
|
958
|
+
var path = __toESM(require("path"));
|
|
959
|
+
var os = __toESM(require("os"));
|
|
960
|
+
var https = __toESM(require("https"));
|
|
961
|
+
var tls = __toESM(require("tls"));
|
|
962
|
+
var TDK = class {
|
|
963
|
+
static BASE_URL = "https://sozluk.gov.tr";
|
|
964
|
+
static AUDIO_API_HOST = "api.sozluk.gov.tr";
|
|
965
|
+
static KUBBEALTI_HOST = "eski.lugatim.com";
|
|
927
966
|
// Configuration
|
|
928
967
|
static defaultTimeoutMs = 8e3;
|
|
929
968
|
static defaultRetries = 1;
|
|
@@ -1470,12 +1509,12 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
1470
1509
|
continue;
|
|
1471
1510
|
if (Math.abs(candidate.length - cleanWord.length) > 2)
|
|
1472
1511
|
continue;
|
|
1473
|
-
const rawDist =
|
|
1512
|
+
const rawDist = damerauLevenshtein(cleanWord, candidate);
|
|
1474
1513
|
if (rawDist === 0 || rawDist > 2)
|
|
1475
1514
|
continue;
|
|
1476
1515
|
const firstMismatch = candidate[0] === cleanWord[0] ? 0 : 1;
|
|
1477
1516
|
const lengthMismatch = candidate.length === cleanWord.length ? 0 : 1;
|
|
1478
|
-
const score =
|
|
1517
|
+
const score = keyboardAwareDistance(cleanWord, candidate) + (firstMismatch > 0 ? 1.2 : 0);
|
|
1479
1518
|
const better = !best || score < best.score - 1e-9 || Math.abs(score - best.score) < 1e-9 && firstMismatch < best.firstMismatch || Math.abs(score - best.score) < 1e-9 && firstMismatch === best.firstMismatch && lengthMismatch < best.lengthMismatch;
|
|
1480
1519
|
if (better) {
|
|
1481
1520
|
best = { candidate, score, rawDist, firstMismatch, lengthMismatch };
|
|
@@ -1606,14 +1645,11 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
1606
1645
|
const contentEnd = html.indexOf("<footer", contentStart);
|
|
1607
1646
|
if (contentEnd === -1)
|
|
1608
1647
|
return null;
|
|
1609
|
-
return
|
|
1648
|
+
return htmlToPlainText(html.slice(contentStart, contentEnd));
|
|
1610
1649
|
} catch {
|
|
1611
1650
|
return null;
|
|
1612
1651
|
}
|
|
1613
1652
|
}
|
|
1614
|
-
static htmlToPlainText(html) {
|
|
1615
|
-
return html.replace(/<br\s*\/?>/gi, "\n").replace(/<\/(p|div)>/gi, "\n\n").replace(/<[^>]+>/g, "").replace(/ /gi, " ").replace(/</gi, "<").replace(/>/gi, ">").replace(/"/gi, '"').replace(/'|’/gi, "'").replace(/&/gi, "&").replace(/[ \t]+/g, " ").replace(/[ \t]*\n[ \t]*/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
1616
|
-
}
|
|
1617
1653
|
/**
|
|
1618
1654
|
* GETs a JSON path from Kubbealtı Lugatı's data API (`eski.lugatim.com`),
|
|
1619
1655
|
* supplying `KUBBEALTI_EXTRA_CA` to work around that host's incomplete
|
|
@@ -1627,7 +1663,7 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
1627
1663
|
hostname: this.KUBBEALTI_HOST,
|
|
1628
1664
|
path: path2,
|
|
1629
1665
|
method: "GET",
|
|
1630
|
-
ca: [...tls.rootCertificates, ...
|
|
1666
|
+
ca: [...tls.rootCertificates, ...KUBBEALTI_EXTRA_CA],
|
|
1631
1667
|
headers: {
|
|
1632
1668
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"
|
|
1633
1669
|
}
|
|
@@ -1719,7 +1755,7 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
1719
1755
|
const entries = await this.getKubbealti(word);
|
|
1720
1756
|
if (!entries)
|
|
1721
1757
|
return null;
|
|
1722
|
-
return entries.map((e) =>
|
|
1758
|
+
return entries.map((e) => htmlToPlainText(e.anlam));
|
|
1723
1759
|
}
|
|
1724
1760
|
/**
|
|
1725
1761
|
* Autocomplete suggestions from Kubbealtı Lugatı's own typeahead endpoint
|
|
@@ -1755,7 +1791,7 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
1755
1791
|
const match = html.match(/<meta name="description" content="([^"]*)"/);
|
|
1756
1792
|
if (!match)
|
|
1757
1793
|
return null;
|
|
1758
|
-
const description =
|
|
1794
|
+
const description = htmlToPlainText(match[1]);
|
|
1759
1795
|
if (description === "\xC7a\u011Fda\u015F T\xFCrk\xE7enin Etimolojisi")
|
|
1760
1796
|
return null;
|
|
1761
1797
|
return description;
|
|
@@ -1986,56 +2022,6 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
1986
2022
|
}
|
|
1987
2023
|
return analyses;
|
|
1988
2024
|
}
|
|
1989
|
-
/**
|
|
1990
|
-
* Damerau-Levenshtein edit-distance (optimal string alignment variant):
|
|
1991
|
-
* like classic Levenshtein but also counts an adjacent-character
|
|
1992
|
-
* transposition (e.g. "yanlız" -> "yalnız") as a single edit instead of
|
|
1993
|
-
* two substitutions — a very common class of typo that plain Levenshtein
|
|
1994
|
-
* otherwise misses.
|
|
1995
|
-
*/
|
|
1996
|
-
static damerauLevenshtein(a, b) {
|
|
1997
|
-
const dp = Array.from({ length: a.length + 1 }, () => new Array(b.length + 1).fill(0));
|
|
1998
|
-
for (let i = 0; i <= a.length; i++)
|
|
1999
|
-
dp[i][0] = i;
|
|
2000
|
-
for (let j = 0; j <= b.length; j++)
|
|
2001
|
-
dp[0][j] = j;
|
|
2002
|
-
for (let i = 1; i <= a.length; i++) {
|
|
2003
|
-
for (let j = 1; j <= b.length; j++) {
|
|
2004
|
-
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
2005
|
-
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
2006
|
-
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
|
|
2007
|
-
dp[i][j] = Math.min(dp[i][j], dp[i - 2][j - 2] + cost);
|
|
2008
|
-
}
|
|
2009
|
-
}
|
|
2010
|
-
}
|
|
2011
|
-
return dp[a.length][b.length];
|
|
2012
|
-
}
|
|
2013
|
-
/**
|
|
2014
|
-
* Keyboard- and diacritic-aware edit distance: same optimal-string-alignment
|
|
2015
|
-
* recurrence as {@link damerauLevenshtein}, but a substitution is charged by
|
|
2016
|
-
* {@link keyboardSubCost} (a fraction of an edit when the two letters are
|
|
2017
|
-
* adjacent on a Turkish Q keyboard or are ASCII/diacritic siblings) and a
|
|
2018
|
-
* transposition costs {@link TRANSPOSITION_COST}. Insertions and deletions
|
|
2019
|
-
* still cost a full 1. Used only to *rank* spelling candidates; the plain
|
|
2020
|
-
* integer distance still gates whether a suggestion is offered at all.
|
|
2021
|
-
*/
|
|
2022
|
-
static keyboardAwareDistance(a, b) {
|
|
2023
|
-
const dp = Array.from({ length: a.length + 1 }, () => new Array(b.length + 1).fill(0));
|
|
2024
|
-
for (let i = 0; i <= a.length; i++)
|
|
2025
|
-
dp[i][0] = i;
|
|
2026
|
-
for (let j = 0; j <= b.length; j++)
|
|
2027
|
-
dp[0][j] = j;
|
|
2028
|
-
for (let i = 1; i <= a.length; i++) {
|
|
2029
|
-
for (let j = 1; j <= b.length; j++) {
|
|
2030
|
-
const cost = keyboardSubCost(a[i - 1], b[j - 1]);
|
|
2031
|
-
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
2032
|
-
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
|
|
2033
|
-
dp[i][j] = Math.min(dp[i][j], dp[i - 2][j - 2] + TRANSPOSITION_COST);
|
|
2034
|
-
}
|
|
2035
|
-
}
|
|
2036
|
-
}
|
|
2037
|
-
return dp[a.length][b.length];
|
|
2038
|
-
}
|
|
2039
2025
|
/**
|
|
2040
2026
|
* Fetches multiple words concurrently with a small delay to avoid rate limiting.
|
|
2041
2027
|
*/
|
|
@@ -2504,6 +2490,277 @@ var TDKClient = class {
|
|
|
2504
2490
|
return TDK.checkLabialHarmony(word);
|
|
2505
2491
|
}
|
|
2506
2492
|
};
|
|
2493
|
+
|
|
2494
|
+
// src/mcp.ts
|
|
2495
|
+
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
2496
|
+
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
2497
|
+
var import_zod = require("zod");
|
|
2498
|
+
var VERSION = "1.7.0";
|
|
2499
|
+
function ok(data) {
|
|
2500
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
2501
|
+
}
|
|
2502
|
+
function fail(message) {
|
|
2503
|
+
return {
|
|
2504
|
+
content: [{ type: "text", text: JSON.stringify({ error: message }, null, 2) }],
|
|
2505
|
+
isError: true
|
|
2506
|
+
};
|
|
2507
|
+
}
|
|
2508
|
+
function guard(fn) {
|
|
2509
|
+
return async (args) => {
|
|
2510
|
+
try {
|
|
2511
|
+
return await fn(args);
|
|
2512
|
+
} catch (error) {
|
|
2513
|
+
return fail(error instanceof Error ? error.message : String(error));
|
|
2514
|
+
}
|
|
2515
|
+
};
|
|
2516
|
+
}
|
|
2517
|
+
function createMcpServer() {
|
|
2518
|
+
const server = new import_mcp.McpServer({
|
|
2519
|
+
name: "TDK API Server",
|
|
2520
|
+
version: VERSION
|
|
2521
|
+
});
|
|
2522
|
+
server.tool(
|
|
2523
|
+
"tdk_lookup",
|
|
2524
|
+
"Bir kelimenin TDK G\xFCncel T\xFCrk\xE7e S\xF6zl\xFCk'teki ham kayd\u0131n\u0131 (t\xFCm anlamlar, \xF6rnekler, birle\u015Fikler, k\xF6ken, atas\xF6zleri) d\xF6nd\xFCr\xFCr.",
|
|
2525
|
+
{ word: import_zod.z.string().describe("Aranacak T\xFCrk\xE7e kelime (\xF6rn: 'kalem').") },
|
|
2526
|
+
guard(async ({ word }) => {
|
|
2527
|
+
const results = await TDK.getWord(word);
|
|
2528
|
+
if (results.length === 0)
|
|
2529
|
+
return fail(`"${word}" TDK s\xF6zl\xFC\u011F\xFCnde bulunamad\u0131.`);
|
|
2530
|
+
return ok(results);
|
|
2531
|
+
})
|
|
2532
|
+
);
|
|
2533
|
+
server.tool(
|
|
2534
|
+
"tdk_meanings",
|
|
2535
|
+
"Bir kelimenin sadele\u015Ftirilmi\u015F anlam listesini (madde madde tan\u0131mlar) d\xF6nd\xFCr\xFCr.",
|
|
2536
|
+
{ word: import_zod.z.string().describe("Aranacak T\xFCrk\xE7e kelime.") },
|
|
2537
|
+
guard(async ({ word }) => ok({ word, meanings: await TDK.getMeanings(word) }))
|
|
2538
|
+
);
|
|
2539
|
+
server.tool(
|
|
2540
|
+
"tdk_examples",
|
|
2541
|
+
"Bir kelimenin s\xF6zl\xFCkteki \xF6rnek c\xFCmlelerini (varsa yazar\u0131yla) d\xF6nd\xFCr\xFCr.",
|
|
2542
|
+
{ word: import_zod.z.string().describe("Aranacak T\xFCrk\xE7e kelime.") },
|
|
2543
|
+
guard(async ({ word }) => ok({ word, examples: await TDK.getExamples(word) }))
|
|
2544
|
+
);
|
|
2545
|
+
server.tool(
|
|
2546
|
+
"tdk_proverbs",
|
|
2547
|
+
"Bir kelime ile kurulan atas\xF6z\xFC ve deyimleri listeler.",
|
|
2548
|
+
{ word: import_zod.z.string().describe("Aranacak T\xFCrk\xE7e kelime (\xF6rn: 'g\xF6z').") },
|
|
2549
|
+
guard(async ({ word }) => ok({ word, proverbs: await TDK.getProverbs(word) }))
|
|
2550
|
+
);
|
|
2551
|
+
server.tool(
|
|
2552
|
+
"tdk_compound_words",
|
|
2553
|
+
"Bir kelime ile olu\u015Fturulmu\u015F birle\u015Fik kelimeleri listeler (\xF6rn: 'kalem' -> 'dolma kalem').",
|
|
2554
|
+
{ word: import_zod.z.string().describe("Aranacak T\xFCrk\xE7e kelime.") },
|
|
2555
|
+
guard(async ({ word }) => ok({ word, compounds: await TDK.getCompoundWords(word) }))
|
|
2556
|
+
);
|
|
2557
|
+
server.tool(
|
|
2558
|
+
"tdk_part_of_speech",
|
|
2559
|
+
"Bir kelimenin s\xF6zc\xFCk t\xFCrlerini (isim, s\u0131fat, zarf, fiil vb.) d\xF6nd\xFCr\xFCr.",
|
|
2560
|
+
{ word: import_zod.z.string().describe("Aranacak T\xFCrk\xE7e kelime.") },
|
|
2561
|
+
guard(async ({ word }) => ok({ word, partsOfSpeech: await TDK.getPartOfSpeech(word) }))
|
|
2562
|
+
);
|
|
2563
|
+
server.tool(
|
|
2564
|
+
"tdk_synonyms",
|
|
2565
|
+
"Bir kelimenin e\u015F anlaml\u0131lar\u0131n\u0131 (yak\u0131n anlaml\u0131 kelimeler) d\xF6nd\xFCr\xFCr.",
|
|
2566
|
+
{ word: import_zod.z.string().describe("Aranacak T\xFCrk\xE7e kelime.") },
|
|
2567
|
+
guard(async ({ word }) => ok({ word, synonyms: await TDK.getSynonyms(word) }))
|
|
2568
|
+
);
|
|
2569
|
+
server.tool(
|
|
2570
|
+
"tdk_antonyms",
|
|
2571
|
+
"Bir kelimenin z\u0131t (kar\u015F\u0131t) anlaml\u0131lar\u0131n\u0131 d\xF6nd\xFCr\xFCr.",
|
|
2572
|
+
{ word: import_zod.z.string().describe("Aranacak T\xFCrk\xE7e kelime.") },
|
|
2573
|
+
guard(async ({ word }) => ok({ word, antonyms: await TDK.getAntonyms(word) }))
|
|
2574
|
+
);
|
|
2575
|
+
server.tool(
|
|
2576
|
+
"tdk_origin",
|
|
2577
|
+
"Bir kelimenin TDK'deki k\xF6ken bilgisini ve yabanc\u0131 k\xF6kenli olup olmad\u0131\u011F\u0131n\u0131 d\xF6nd\xFCr\xFCr.",
|
|
2578
|
+
{ word: import_zod.z.string().describe("Aranacak T\xFCrk\xE7e kelime.") },
|
|
2579
|
+
guard(async ({ word }) => {
|
|
2580
|
+
const [origin, foreign] = await Promise.all([TDK.getOrigin(word), TDK.isForeignWord(word)]);
|
|
2581
|
+
return ok({ word, origin, isForeign: foreign });
|
|
2582
|
+
})
|
|
2583
|
+
);
|
|
2584
|
+
server.tool(
|
|
2585
|
+
"tdk_nisanyan",
|
|
2586
|
+
"Ni\u015Fanyan S\xF6zl\xFCk'ten bir kelimenin ayr\u0131nt\u0131l\u0131 etimolojisini (server-rendered meta a\xE7\u0131klamas\u0131) \xE7eker.",
|
|
2587
|
+
{ word: import_zod.z.string().describe("Etimolojisi aranacak kelime.") },
|
|
2588
|
+
guard(async ({ word }) => {
|
|
2589
|
+
const etymology = await TDK.getNisanyan(word);
|
|
2590
|
+
return etymology ? ok({ word, etymology }) : fail(`Ni\u015Fanyan S\xF6zl\xFCk'te "${word}" bulunamad\u0131.`);
|
|
2591
|
+
})
|
|
2592
|
+
);
|
|
2593
|
+
server.tool(
|
|
2594
|
+
"tdk_kubbealti",
|
|
2595
|
+
"Kubbealt\u0131 Lugat\u0131'ndan (ticari s\xF6zl\xFCk) bir kelimenin anlamlar\u0131n\u0131 \xE7eker.",
|
|
2596
|
+
{ word: import_zod.z.string().describe("Aranacak kelime.") },
|
|
2597
|
+
guard(async ({ word }) => {
|
|
2598
|
+
const meanings = await TDK.getKubbealtiMeanings(word);
|
|
2599
|
+
if (meanings === null)
|
|
2600
|
+
return fail("Kubbealt\u0131 Lugat\u0131'na ula\u015F\u0131lamad\u0131.");
|
|
2601
|
+
return ok({ word, meanings });
|
|
2602
|
+
})
|
|
2603
|
+
);
|
|
2604
|
+
server.tool(
|
|
2605
|
+
"tdk_wiktionary",
|
|
2606
|
+
"T\xFCrk\xE7e Wiktionary'den (tr.wiktionary.org, resmi MediaWiki API) bir maddenin b\xF6l\xFCmlere ayr\u0131lm\u0131\u015F i\xE7eri\u011Fini \xE7eker.",
|
|
2607
|
+
{
|
|
2608
|
+
word: import_zod.z.string().describe("Aranacak madde ba\u015Fl\u0131\u011F\u0131."),
|
|
2609
|
+
section: import_zod.z.string().optional().describe("Sadece belirli bir b\xF6l\xFCm istenirse ba\u015Fl\u0131k ad\u0131 (\xF6rn: 'K\xF6ken', '\xC7eviriler').")
|
|
2610
|
+
},
|
|
2611
|
+
guard(async ({ word, section }) => {
|
|
2612
|
+
if (section) {
|
|
2613
|
+
const text = await TDK.getWiktionarySection(word, section);
|
|
2614
|
+
return text ? ok({ word, section, text }) : fail(`Wiktionary'de "${word}" i\xE7in "${section}" b\xF6l\xFCm\xFC bulunamad\u0131.`);
|
|
2615
|
+
}
|
|
2616
|
+
const entry = await TDK.getWiktionary(word);
|
|
2617
|
+
return entry ? ok(entry) : fail(`Wiktionary'de "${word}" bulunamad\u0131.`);
|
|
2618
|
+
})
|
|
2619
|
+
);
|
|
2620
|
+
server.tool(
|
|
2621
|
+
"tdk_spell_check",
|
|
2622
|
+
"Bir kelimenin do\u011Fru yaz\u0131l\u0131p yaz\u0131lmad\u0131\u011F\u0131n\u0131 denetler; yanl\u0131\u015Fsa klavye/diakritik fark\u0131ndal\u0131kl\u0131 en yak\u0131n madde \xF6nerisi verir, \xE7ekimli bi\xE7imse k\xF6k\xFCn\xFC d\xF6nd\xFCr\xFCr.",
|
|
2623
|
+
{ word: import_zod.z.string().describe("Yaz\u0131m\u0131 denetlenecek kelime (\xF6rn: 'yanl\u0131z', 'arabs').") },
|
|
2624
|
+
guard(async ({ word }) => ok(await TDK.checkSpelling(word)))
|
|
2625
|
+
);
|
|
2626
|
+
server.tool(
|
|
2627
|
+
"tdk_proofread",
|
|
2628
|
+
"Bir T\xFCrk\xE7e metni imla, ayr\u0131/biti\u015Fik yaz\u0131m ve 'da/de', 'ki', 'mi' ba\u011Fla\xE7/ek hatalar\u0131 a\xE7\u0131s\u0131ndan denetler.",
|
|
2629
|
+
{ text: import_zod.z.string().describe("Denetlenecek T\xFCrk\xE7e metin.") },
|
|
2630
|
+
guard(async ({ text }) => ok(await TDK.proofread(text)))
|
|
2631
|
+
);
|
|
2632
|
+
server.tool(
|
|
2633
|
+
"tdk_stem",
|
|
2634
|
+
"Bir kelimenin morfolojik k\xF6k\xFCn\xFC (ek s\u0131y\u0131rma / stemming) bulur ve \xE7ekimli olup olmad\u0131\u011F\u0131n\u0131 belirtir (\xF6rn: 'kitab\u0131m\u0131z\u0131n' -> 'kitap').",
|
|
2635
|
+
{ word: import_zod.z.string().describe("K\xF6k\xFC aranacak kelime.") },
|
|
2636
|
+
guard(async ({ word }) => {
|
|
2637
|
+
const result = await TDK.stem(word);
|
|
2638
|
+
return result ? ok(result) : fail(`"${word}" i\xE7in k\xF6k tespit edilemedi.`);
|
|
2639
|
+
})
|
|
2640
|
+
);
|
|
2641
|
+
server.tool(
|
|
2642
|
+
"tdk_analyze_text",
|
|
2643
|
+
"Bir metindeki her kelime i\xE7in k\xF6k, anlam ve k\xF6ken bilgisini toplu olarak \xE7\u0131kar\u0131r.",
|
|
2644
|
+
{ text: import_zod.z.string().describe("Analiz edilecek T\xFCrk\xE7e metin.") },
|
|
2645
|
+
guard(async ({ text }) => ok(await TDK.analyzeText(text)))
|
|
2646
|
+
);
|
|
2647
|
+
server.tool(
|
|
2648
|
+
"tdk_syllables",
|
|
2649
|
+
"Bir kelimeyi T\xFCrk\xE7e hece kurallar\u0131na g\xF6re hecelere ay\u0131r\u0131r (tamamen yerel, a\u011F iste\u011Fi yok).",
|
|
2650
|
+
{ word: import_zod.z.string().describe("Hecelenecek kelime.") },
|
|
2651
|
+
guard(async ({ word }) => ok({ word, syllables: TDK.syllabicate(word) }))
|
|
2652
|
+
);
|
|
2653
|
+
server.tool(
|
|
2654
|
+
"tdk_vowel_harmony",
|
|
2655
|
+
"Bir kelimenin b\xFCy\xFCk \xFCnl\xFC uyumuna ve k\xFC\xE7\xFCk \xFCnl\xFC uyumuna (d\xFCzl\xFCk-yuvarlakl\u0131k) uyup uymad\u0131\u011F\u0131n\u0131 kontrol eder.",
|
|
2656
|
+
{ word: import_zod.z.string().describe("Kontrol edilecek kelime.") },
|
|
2657
|
+
guard(
|
|
2658
|
+
async ({ word }) => ok({
|
|
2659
|
+
word,
|
|
2660
|
+
vowelHarmony: TDK.checkVowelHarmony(word),
|
|
2661
|
+
labialHarmony: TDK.checkLabialHarmony(word)
|
|
2662
|
+
})
|
|
2663
|
+
)
|
|
2664
|
+
);
|
|
2665
|
+
server.tool(
|
|
2666
|
+
"tdk_autocomplete",
|
|
2667
|
+
"Bir \xF6nek ile ba\u015Flayan s\xF6zl\xFCk maddelerini (autocomplete) d\xF6nd\xFCr\xFCr.",
|
|
2668
|
+
{ prefix: import_zod.z.string().describe("Aranacak \xF6nek (\xF6rn: 'kalem').") },
|
|
2669
|
+
guard(async ({ prefix }) => ok({ prefix, suggestions: await TDK.getSuggestions(prefix) }))
|
|
2670
|
+
);
|
|
2671
|
+
server.tool(
|
|
2672
|
+
"tdk_pattern_search",
|
|
2673
|
+
"Bulmaca deseni ile e\u015Fle\u015Fen s\xF6zl\xFCk maddelerini bulur: '_' veya '?' tek harf, '*' s\u0131f\u0131r ya da daha fazla harf yerine ge\xE7er (\xF6rn: 'k_l_m').",
|
|
2674
|
+
{
|
|
2675
|
+
pattern: import_zod.z.string().describe("Desen. '_'/'?' = tek harf, '*' = s\u0131f\u0131r ya da daha fazla harf."),
|
|
2676
|
+
max_results: import_zod.z.number().int().min(1).max(500).default(50).describe("En fazla sonu\xE7 say\u0131s\u0131.")
|
|
2677
|
+
},
|
|
2678
|
+
guard(async ({ pattern, max_results }) => {
|
|
2679
|
+
const matches = await TDK.patternSearch(pattern, { maxResults: max_results });
|
|
2680
|
+
return ok({ pattern, count: matches.length, matches });
|
|
2681
|
+
})
|
|
2682
|
+
);
|
|
2683
|
+
server.tool(
|
|
2684
|
+
"tdk_anagram",
|
|
2685
|
+
"Verilen harflerle kurulabilecek T\xFCrk\xE7e s\xF6zl\xFCk maddelerini bulur. Birebir anagram varsa onlar, yoksa harflerin bir alt k\xFCmesiyle kurulan kelimeler d\xF6ner.",
|
|
2686
|
+
{
|
|
2687
|
+
letters: import_zod.z.string().describe("Kullan\u0131lacak harfler (\xF6rn: 'kalem')."),
|
|
2688
|
+
exact_length: import_zod.z.boolean().default(false).describe("Sadece harflerin tamam\u0131n\u0131 kullanan birebir anagramlar\u0131 d\xF6nd\xFCr."),
|
|
2689
|
+
max_results: import_zod.z.number().int().min(1).max(500).default(50).describe("En fazla sonu\xE7 say\u0131s\u0131.")
|
|
2690
|
+
},
|
|
2691
|
+
guard(async ({ letters, exact_length, max_results }) => {
|
|
2692
|
+
const words = await TDK.findAnagrams(letters, { exactLength: exact_length, maxResults: max_results });
|
|
2693
|
+
return ok({ letters, count: words.length, words });
|
|
2694
|
+
})
|
|
2695
|
+
);
|
|
2696
|
+
server.tool(
|
|
2697
|
+
"tdk_rhymes",
|
|
2698
|
+
"Bir kelime ile kafiyeli (son harfleri uyu\u015Fan) s\xF6zl\xFCk maddelerini bulur.",
|
|
2699
|
+
{
|
|
2700
|
+
word: import_zod.z.string().describe("Kafiyesi aranacak kelime."),
|
|
2701
|
+
min_letters: import_zod.z.number().int().min(1).default(3).describe("Uyu\u015Fmas\u0131 gereken en az son harf say\u0131s\u0131."),
|
|
2702
|
+
max_results: import_zod.z.number().int().min(1).max(500).default(50).describe("En fazla sonu\xE7 say\u0131s\u0131.")
|
|
2703
|
+
},
|
|
2704
|
+
guard(async ({ word, min_letters, max_results }) => {
|
|
2705
|
+
const rhymes = await TDK.findRhymes(word, { minLetters: min_letters, maxResults: max_results });
|
|
2706
|
+
return ok({ word, count: rhymes.length, rhymes });
|
|
2707
|
+
})
|
|
2708
|
+
);
|
|
2709
|
+
server.tool(
|
|
2710
|
+
"tdk_compare",
|
|
2711
|
+
"\u0130ki kelimeyi anlam say\u0131s\u0131, k\xF6ken, hece b\xF6l\xFCn\xFC\u015F\xFC ve \xFCnl\xFC uyumu a\xE7\u0131s\u0131ndan kar\u015F\u0131la\u015Ft\u0131r\u0131r.",
|
|
2712
|
+
{
|
|
2713
|
+
a: import_zod.z.string().describe("Birinci kelime."),
|
|
2714
|
+
b: import_zod.z.string().describe("\u0130kinci kelime.")
|
|
2715
|
+
},
|
|
2716
|
+
guard(async ({ a, b }) => ok(await TDK.compareWords(a, b)))
|
|
2717
|
+
);
|
|
2718
|
+
server.tool(
|
|
2719
|
+
"tdk_audio_url",
|
|
2720
|
+
"Bir kelimenin TDK seslendirme (.wav) URL'sini d\xF6nd\xFCr\xFCr (bulunamazsa null).",
|
|
2721
|
+
{ word: import_zod.z.string().describe("Seslendirmesi aranacak kelime.") },
|
|
2722
|
+
guard(async ({ word }) => ok({ word, audioUrl: await TDK.getAudioUrl(word) }))
|
|
2723
|
+
);
|
|
2724
|
+
server.tool(
|
|
2725
|
+
"tdk_word_of_the_day",
|
|
2726
|
+
"TDK'nin 'g\xFCn\xFCn kelimesi'ni anlamlar\u0131yla d\xF6nd\xFCr\xFCr.",
|
|
2727
|
+
{},
|
|
2728
|
+
guard(async () => {
|
|
2729
|
+
const wotd = await TDK.getWordOfTheDay();
|
|
2730
|
+
return wotd ? ok(wotd) : fail("G\xFCn\xFCn kelimesi al\u0131namad\u0131.");
|
|
2731
|
+
})
|
|
2732
|
+
);
|
|
2733
|
+
server.tool(
|
|
2734
|
+
"tdk_random_word",
|
|
2735
|
+
"TDK i\xE7eri\u011Finden rastgele bir kelime ya da atas\xF6z\xFC d\xF6nd\xFCr\xFCr.",
|
|
2736
|
+
{},
|
|
2737
|
+
guard(async () => {
|
|
2738
|
+
const pick = await TDK.getRandomWord();
|
|
2739
|
+
return pick ? ok(pick) : fail("Rastgele i\xE7erik al\u0131namad\u0131.");
|
|
2740
|
+
})
|
|
2741
|
+
);
|
|
2742
|
+
server.tool(
|
|
2743
|
+
"tdk_rules",
|
|
2744
|
+
"TDK Yaz\u0131m K\u0131lavuzu kurallar\u0131n\u0131 listeler; 'name' verilirse o kural\u0131n tam metnini d\xF6nd\xFCr\xFCr.",
|
|
2745
|
+
{
|
|
2746
|
+
name: import_zod.z.string().optional().describe("\u0130stenirse tek bir kural\u0131n ad\u0131 (\xF6rn: 'Ba\u011Fla\xE7 Olan da, de'nin Yaz\u0131l\u0131\u015F\u0131').")
|
|
2747
|
+
},
|
|
2748
|
+
guard(async ({ name }) => {
|
|
2749
|
+
if (name) {
|
|
2750
|
+
const rule = await TDK.getRule(name);
|
|
2751
|
+
return rule ? ok({ name, rule }) : fail(`"${name}" kural\u0131 bulunamad\u0131.`);
|
|
2752
|
+
}
|
|
2753
|
+
const rules = await TDK.getKurallar();
|
|
2754
|
+
return ok({ count: rules.length, rules });
|
|
2755
|
+
})
|
|
2756
|
+
);
|
|
2757
|
+
return server;
|
|
2758
|
+
}
|
|
2759
|
+
async function runMcpServer() {
|
|
2760
|
+
const server = createMcpServer();
|
|
2761
|
+
const transport = new import_stdio.StdioServerTransport();
|
|
2762
|
+
await server.connect(transport);
|
|
2763
|
+
}
|
|
2507
2764
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2508
2765
|
0 && (module.exports = {
|
|
2509
2766
|
TDK,
|
|
@@ -2513,11 +2770,13 @@ var TDKClient = class {
|
|
|
2513
2770
|
TDKValidationError,
|
|
2514
2771
|
TURKISH_SUFFIXES,
|
|
2515
2772
|
TURKISH_VOWELS,
|
|
2773
|
+
createMcpServer,
|
|
2516
2774
|
getStemCandidates,
|
|
2517
2775
|
isVowel,
|
|
2518
2776
|
restoreConsonantSoftening,
|
|
2519
2777
|
restoreGemination,
|
|
2520
2778
|
restoreInfinitive,
|
|
2521
2779
|
restoreVowelDrop,
|
|
2522
|
-
restoreVowelNarrowing
|
|
2780
|
+
restoreVowelNarrowing,
|
|
2781
|
+
runMcpServer
|
|
2523
2782
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createMcpServer,
|
|
3
|
+
runMcpServer
|
|
4
|
+
} from "./chunk-ZG7YRT7V.mjs";
|
|
1
5
|
import {
|
|
2
6
|
TDK,
|
|
3
7
|
TDKClient,
|
|
@@ -13,7 +17,7 @@ import {
|
|
|
13
17
|
restoreInfinitive,
|
|
14
18
|
restoreVowelDrop,
|
|
15
19
|
restoreVowelNarrowing
|
|
16
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-YY4WA2AO.mjs";
|
|
17
21
|
export {
|
|
18
22
|
TDK,
|
|
19
23
|
TDKClient,
|
|
@@ -22,11 +26,13 @@ export {
|
|
|
22
26
|
TDKValidationError,
|
|
23
27
|
TURKISH_SUFFIXES,
|
|
24
28
|
TURKISH_VOWELS,
|
|
29
|
+
createMcpServer,
|
|
25
30
|
getStemCandidates,
|
|
26
31
|
isVowel,
|
|
27
32
|
restoreConsonantSoftening,
|
|
28
33
|
restoreGemination,
|
|
29
34
|
restoreInfinitive,
|
|
30
35
|
restoreVowelDrop,
|
|
31
|
-
restoreVowelNarrowing
|
|
36
|
+
restoreVowelNarrowing,
|
|
37
|
+
runMcpServer
|
|
32
38
|
};
|