@langapi/mcp-server 1.0.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.
- package/README.md +551 -0
- package/bin/langapi-mcp.js +11 -0
- package/dist/api/client.d.ts +24 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +145 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/types.d.ts +56 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +6 -0
- package/dist/api/types.js.map +1 -0
- package/dist/config/env.d.ts +18 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +29 -0
- package/dist/config/env.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/locale-detection/index.d.ts +41 -0
- package/dist/locale-detection/index.d.ts.map +1 -0
- package/dist/locale-detection/index.js +188 -0
- package/dist/locale-detection/index.js.map +1 -0
- package/dist/locale-detection/patterns.d.ts +21 -0
- package/dist/locale-detection/patterns.d.ts.map +1 -0
- package/dist/locale-detection/patterns.js +135 -0
- package/dist/locale-detection/patterns.js.map +1 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +24 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/get-diff.d.ts +23 -0
- package/dist/tools/get-diff.d.ts.map +1 -0
- package/dist/tools/get-diff.js +88 -0
- package/dist/tools/get-diff.js.map +1 -0
- package/dist/tools/get-translation-status.d.ts +47 -0
- package/dist/tools/get-translation-status.d.ts.map +1 -0
- package/dist/tools/get-translation-status.js +176 -0
- package/dist/tools/get-translation-status.js.map +1 -0
- package/dist/tools/list-local-locales.d.ts +39 -0
- package/dist/tools/list-local-locales.d.ts.map +1 -0
- package/dist/tools/list-local-locales.js +52 -0
- package/dist/tools/list-local-locales.js.map +1 -0
- package/dist/tools/sync-translations.d.ts +35 -0
- package/dist/tools/sync-translations.d.ts.map +1 -0
- package/dist/tools/sync-translations.js +629 -0
- package/dist/tools/sync-translations.js.map +1 -0
- package/dist/utils/format-preserve.d.ts +25 -0
- package/dist/utils/format-preserve.d.ts.map +1 -0
- package/dist/utils/format-preserve.js +56 -0
- package/dist/utils/format-preserve.js.map +1 -0
- package/dist/utils/json-parser.d.ts +33 -0
- package/dist/utils/json-parser.d.ts.map +1 -0
- package/dist/utils/json-parser.js +92 -0
- package/dist/utils/json-parser.js.map +1 -0
- package/dist/utils/sync-cache.d.ts +40 -0
- package/dist/utils/sync-cache.d.ts.map +1 -0
- package/dist/utils/sync-cache.js +153 -0
- package/dist/utils/sync-cache.js.map +1 -0
- package/dist/utils/sync-cache.test.d.ts +2 -0
- package/dist/utils/sync-cache.test.d.ts.map +1 -0
- package/dist/utils/sync-cache.test.js +205 -0
- package/dist/utils/sync-cache.test.js.map +1 -0
- package/dist/utils/validation.d.ts +37 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +67 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { mkdir, rm, readFile } from "fs/promises";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { tmpdir } from "os";
|
|
5
|
+
import { detectLocalDelta, getFullDiff, readSyncCache, writeSyncCache, } from "./sync-cache.js";
|
|
6
|
+
describe("detectLocalDelta", () => {
|
|
7
|
+
it("should mark all keys as new when cache is null", () => {
|
|
8
|
+
const currentContent = [
|
|
9
|
+
{ key: "hello", value: "Hello" },
|
|
10
|
+
{ key: "world", value: "World" },
|
|
11
|
+
];
|
|
12
|
+
const result = detectLocalDelta(currentContent, null);
|
|
13
|
+
expect(result.newKeys).toEqual(["hello", "world"]);
|
|
14
|
+
expect(result.changedKeys).toEqual([]);
|
|
15
|
+
expect(result.unchangedKeys).toEqual([]);
|
|
16
|
+
expect(result.contentToSync).toEqual(currentContent);
|
|
17
|
+
});
|
|
18
|
+
it("should return empty arrays when current content is empty", () => {
|
|
19
|
+
const cachedContent = { hello: "Hello", world: "World" };
|
|
20
|
+
const result = detectLocalDelta([], cachedContent);
|
|
21
|
+
expect(result.newKeys).toEqual([]);
|
|
22
|
+
expect(result.changedKeys).toEqual([]);
|
|
23
|
+
expect(result.unchangedKeys).toEqual([]);
|
|
24
|
+
expect(result.contentToSync).toEqual([]);
|
|
25
|
+
});
|
|
26
|
+
it("should detect all new keys when none exist in cache", () => {
|
|
27
|
+
const currentContent = [
|
|
28
|
+
{ key: "new1", value: "New 1" },
|
|
29
|
+
{ key: "new2", value: "New 2" },
|
|
30
|
+
];
|
|
31
|
+
const cachedContent = { existing: "Existing" };
|
|
32
|
+
const result = detectLocalDelta(currentContent, cachedContent);
|
|
33
|
+
expect(result.newKeys).toEqual(["new1", "new2"]);
|
|
34
|
+
expect(result.changedKeys).toEqual([]);
|
|
35
|
+
expect(result.unchangedKeys).toEqual([]);
|
|
36
|
+
expect(result.contentToSync).toHaveLength(2);
|
|
37
|
+
});
|
|
38
|
+
it("should detect all unchanged keys when values match", () => {
|
|
39
|
+
const currentContent = [
|
|
40
|
+
{ key: "hello", value: "Hello" },
|
|
41
|
+
{ key: "world", value: "World" },
|
|
42
|
+
];
|
|
43
|
+
const cachedContent = { hello: "Hello", world: "World" };
|
|
44
|
+
const result = detectLocalDelta(currentContent, cachedContent);
|
|
45
|
+
expect(result.newKeys).toEqual([]);
|
|
46
|
+
expect(result.changedKeys).toEqual([]);
|
|
47
|
+
expect(result.unchangedKeys).toEqual(["hello", "world"]);
|
|
48
|
+
expect(result.contentToSync).toEqual([]);
|
|
49
|
+
});
|
|
50
|
+
it("should detect changed keys when values differ", () => {
|
|
51
|
+
const currentContent = [
|
|
52
|
+
{ key: "hello", value: "Hello there" },
|
|
53
|
+
{ key: "world", value: "World" },
|
|
54
|
+
];
|
|
55
|
+
const cachedContent = { hello: "Hello", world: "World" };
|
|
56
|
+
const result = detectLocalDelta(currentContent, cachedContent);
|
|
57
|
+
expect(result.newKeys).toEqual([]);
|
|
58
|
+
expect(result.changedKeys).toEqual(["hello"]);
|
|
59
|
+
expect(result.unchangedKeys).toEqual(["world"]);
|
|
60
|
+
expect(result.contentToSync).toHaveLength(1);
|
|
61
|
+
expect(result.contentToSync[0]).toEqual({ key: "hello", value: "Hello there" });
|
|
62
|
+
});
|
|
63
|
+
it("should handle mixed new, changed, and unchanged keys", () => {
|
|
64
|
+
const currentContent = [
|
|
65
|
+
{ key: "new", value: "New key" },
|
|
66
|
+
{ key: "changed", value: "Changed value" },
|
|
67
|
+
{ key: "unchanged", value: "Same value" },
|
|
68
|
+
];
|
|
69
|
+
const cachedContent = {
|
|
70
|
+
changed: "Original value",
|
|
71
|
+
unchanged: "Same value",
|
|
72
|
+
removed: "This will be ignored by detectLocalDelta",
|
|
73
|
+
};
|
|
74
|
+
const result = detectLocalDelta(currentContent, cachedContent);
|
|
75
|
+
expect(result.newKeys).toEqual(["new"]);
|
|
76
|
+
expect(result.changedKeys).toEqual(["changed"]);
|
|
77
|
+
expect(result.unchangedKeys).toEqual(["unchanged"]);
|
|
78
|
+
expect(result.contentToSync).toHaveLength(2);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe("getFullDiff", () => {
|
|
82
|
+
it("should mark all keys as new when cache is null", () => {
|
|
83
|
+
const currentContent = [
|
|
84
|
+
{ key: "hello", value: "Hello" },
|
|
85
|
+
{ key: "world", value: "World" },
|
|
86
|
+
];
|
|
87
|
+
const result = getFullDiff(currentContent, null);
|
|
88
|
+
expect(result.newKeys).toEqual(["hello", "world"]);
|
|
89
|
+
expect(result.changedKeys).toEqual([]);
|
|
90
|
+
expect(result.unchangedKeys).toEqual([]);
|
|
91
|
+
expect(result.removedKeys).toEqual([]);
|
|
92
|
+
});
|
|
93
|
+
it("should detect removed keys", () => {
|
|
94
|
+
const currentContent = [
|
|
95
|
+
{ key: "remaining", value: "Still here" },
|
|
96
|
+
];
|
|
97
|
+
const cachedContent = {
|
|
98
|
+
remaining: "Still here",
|
|
99
|
+
removed1: "Gone",
|
|
100
|
+
removed2: "Also gone",
|
|
101
|
+
};
|
|
102
|
+
const result = getFullDiff(currentContent, cachedContent);
|
|
103
|
+
expect(result.newKeys).toEqual([]);
|
|
104
|
+
expect(result.changedKeys).toEqual([]);
|
|
105
|
+
expect(result.unchangedKeys).toEqual(["remaining"]);
|
|
106
|
+
expect(result.removedKeys).toEqual(["removed1", "removed2"]);
|
|
107
|
+
});
|
|
108
|
+
it("should include old and new values for changed keys", () => {
|
|
109
|
+
const currentContent = [
|
|
110
|
+
{ key: "greeting", value: "Welcome" },
|
|
111
|
+
];
|
|
112
|
+
const cachedContent = { greeting: "Hello there" };
|
|
113
|
+
const result = getFullDiff(currentContent, cachedContent);
|
|
114
|
+
expect(result.changedKeys).toHaveLength(1);
|
|
115
|
+
expect(result.changedKeys[0]).toEqual({
|
|
116
|
+
key: "greeting",
|
|
117
|
+
oldValue: "Hello there",
|
|
118
|
+
newValue: "Welcome",
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
it("should handle mixed scenario with all change types", () => {
|
|
122
|
+
const currentContent = [
|
|
123
|
+
{ key: "new", value: "Brand new" },
|
|
124
|
+
{ key: "changed", value: "Updated value" },
|
|
125
|
+
{ key: "unchanged", value: "Same" },
|
|
126
|
+
];
|
|
127
|
+
const cachedContent = {
|
|
128
|
+
changed: "Old value",
|
|
129
|
+
unchanged: "Same",
|
|
130
|
+
removed: "Will be detected as removed",
|
|
131
|
+
};
|
|
132
|
+
const result = getFullDiff(currentContent, cachedContent);
|
|
133
|
+
expect(result.newKeys).toEqual(["new"]);
|
|
134
|
+
expect(result.changedKeys).toEqual([
|
|
135
|
+
{ key: "changed", oldValue: "Old value", newValue: "Updated value" },
|
|
136
|
+
]);
|
|
137
|
+
expect(result.unchangedKeys).toEqual(["unchanged"]);
|
|
138
|
+
expect(result.removedKeys).toEqual(["removed"]);
|
|
139
|
+
});
|
|
140
|
+
it("should handle empty current content with cached content", () => {
|
|
141
|
+
const cachedContent = { key1: "Value 1", key2: "Value 2" };
|
|
142
|
+
const result = getFullDiff([], cachedContent);
|
|
143
|
+
expect(result.newKeys).toEqual([]);
|
|
144
|
+
expect(result.changedKeys).toEqual([]);
|
|
145
|
+
expect(result.unchangedKeys).toEqual([]);
|
|
146
|
+
expect(result.removedKeys).toEqual(["key1", "key2"]);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
describe("readSyncCache / writeSyncCache", () => {
|
|
150
|
+
let testDir;
|
|
151
|
+
beforeEach(async () => {
|
|
152
|
+
testDir = join(tmpdir(), `sync-cache-test-${Date.now()}`);
|
|
153
|
+
await mkdir(testDir, { recursive: true });
|
|
154
|
+
});
|
|
155
|
+
afterEach(async () => {
|
|
156
|
+
try {
|
|
157
|
+
await rm(testDir, { recursive: true, force: true });
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
// Ignore cleanup errors
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
it("should write and read back same content", async () => {
|
|
164
|
+
const content = [
|
|
165
|
+
{ key: "hello", value: "Hello" },
|
|
166
|
+
{ key: "world", value: "World" },
|
|
167
|
+
];
|
|
168
|
+
await writeSyncCache(testDir, "en", content);
|
|
169
|
+
const result = await readSyncCache(testDir, "en");
|
|
170
|
+
expect(result).toEqual({
|
|
171
|
+
hello: "Hello",
|
|
172
|
+
world: "World",
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
it("should return null when cache file does not exist", async () => {
|
|
176
|
+
const result = await readSyncCache(testDir, "en");
|
|
177
|
+
expect(result).toBeNull();
|
|
178
|
+
});
|
|
179
|
+
it("should return null when source language does not match", async () => {
|
|
180
|
+
const content = [{ key: "hello", value: "Hello" }];
|
|
181
|
+
await writeSyncCache(testDir, "en", content);
|
|
182
|
+
const result = await readSyncCache(testDir, "de");
|
|
183
|
+
expect(result).toBeNull();
|
|
184
|
+
});
|
|
185
|
+
it("should create cache directory if it does not exist", async () => {
|
|
186
|
+
const nestedDir = join(testDir, "nested", "path");
|
|
187
|
+
const content = [{ key: "test", value: "Test" }];
|
|
188
|
+
await writeSyncCache(nestedDir, "en", content);
|
|
189
|
+
const cacheFile = join(nestedDir, ".langapi", "sync-cache.json");
|
|
190
|
+
const fileContent = await readFile(cacheFile, "utf-8");
|
|
191
|
+
const cache = JSON.parse(fileContent);
|
|
192
|
+
expect(cache.sourceLang).toBe("en");
|
|
193
|
+
expect(cache.content).toEqual({ test: "Test" });
|
|
194
|
+
expect(cache.lastSync).toBeDefined();
|
|
195
|
+
});
|
|
196
|
+
it("should overwrite existing cache on subsequent writes", async () => {
|
|
197
|
+
const content1 = [{ key: "old", value: "Old value" }];
|
|
198
|
+
const content2 = [{ key: "new", value: "New value" }];
|
|
199
|
+
await writeSyncCache(testDir, "en", content1);
|
|
200
|
+
await writeSyncCache(testDir, "en", content2);
|
|
201
|
+
const result = await readSyncCache(testDir, "en");
|
|
202
|
+
expect(result).toEqual({ new: "New value" });
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
//# sourceMappingURL=sync-cache.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-cache.test.js","sourceRoot":"","sources":["../../src/utils/sync-cache.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation utilities for input sanitization
|
|
3
|
+
*/
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
/**
|
|
6
|
+
* RFC 5646 language code pattern
|
|
7
|
+
* Matches: en, de, fr, pt-BR, zh-CN, etc.
|
|
8
|
+
*/
|
|
9
|
+
export declare const LANGUAGE_CODE_PATTERN: RegExp;
|
|
10
|
+
/**
|
|
11
|
+
* Zod schema for language code validation
|
|
12
|
+
*/
|
|
13
|
+
export declare const languageCodeSchema: z.ZodString;
|
|
14
|
+
/**
|
|
15
|
+
* Zod schema for array of language codes
|
|
16
|
+
*/
|
|
17
|
+
export declare const languageCodesArraySchema: z.ZodArray<z.ZodString, "many">;
|
|
18
|
+
/**
|
|
19
|
+
* Validate a language code
|
|
20
|
+
*/
|
|
21
|
+
export declare function isValidLanguageCode(code: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Validate that a path is within the project directory
|
|
24
|
+
* Prevents path traversal attacks
|
|
25
|
+
*/
|
|
26
|
+
export declare function isPathWithinProject(filePath: string, projectPath: string): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Get a safe file path within the project directory
|
|
29
|
+
* Returns null if path would escape project directory
|
|
30
|
+
*/
|
|
31
|
+
export declare function getSafeFilePath(relativePath: string, projectPath: string): string | null;
|
|
32
|
+
/**
|
|
33
|
+
* Sanitize a language code by ensuring it matches the expected pattern
|
|
34
|
+
* Returns the sanitized code or null if invalid
|
|
35
|
+
*/
|
|
36
|
+
export declare function sanitizeLanguageCode(code: string): string | null;
|
|
37
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAA6B,CAAC;AAEhE;;GAEG;AACH,eAAO,MAAM,kBAAkB,aAO3B,CAAC;AAEL;;GAEG;AACH,eAAO,MAAM,wBAAwB,iCAE6B,CAAC;AAEnE;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAMT;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,IAAI,CAUf;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMhE"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation utilities for input sanitization
|
|
3
|
+
*/
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { resolve } from "path";
|
|
6
|
+
/**
|
|
7
|
+
* RFC 5646 language code pattern
|
|
8
|
+
* Matches: en, de, fr, pt-BR, zh-CN, etc.
|
|
9
|
+
*/
|
|
10
|
+
export const LANGUAGE_CODE_PATTERN = /^[a-z]{2,3}(-[A-Z]{2})?$/;
|
|
11
|
+
/**
|
|
12
|
+
* Zod schema for language code validation
|
|
13
|
+
*/
|
|
14
|
+
export const languageCodeSchema = z
|
|
15
|
+
.string()
|
|
16
|
+
.min(2)
|
|
17
|
+
.max(6)
|
|
18
|
+
.regex(LANGUAGE_CODE_PATTERN, {
|
|
19
|
+
message: "Invalid language code. Expected format: 'en', 'de', 'pt-BR', etc.",
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* Zod schema for array of language codes
|
|
23
|
+
*/
|
|
24
|
+
export const languageCodesArraySchema = z
|
|
25
|
+
.array(languageCodeSchema)
|
|
26
|
+
.min(1, { message: "At least one target language is required" });
|
|
27
|
+
/**
|
|
28
|
+
* Validate a language code
|
|
29
|
+
*/
|
|
30
|
+
export function isValidLanguageCode(code) {
|
|
31
|
+
return LANGUAGE_CODE_PATTERN.test(code);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Validate that a path is within the project directory
|
|
35
|
+
* Prevents path traversal attacks
|
|
36
|
+
*/
|
|
37
|
+
export function isPathWithinProject(filePath, projectPath) {
|
|
38
|
+
const resolvedProject = resolve(projectPath);
|
|
39
|
+
const resolvedFile = resolve(projectPath, filePath);
|
|
40
|
+
// Check that resolved file path starts with project path
|
|
41
|
+
return resolvedFile.startsWith(resolvedProject);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get a safe file path within the project directory
|
|
45
|
+
* Returns null if path would escape project directory
|
|
46
|
+
*/
|
|
47
|
+
export function getSafeFilePath(relativePath, projectPath) {
|
|
48
|
+
const resolvedProject = resolve(projectPath);
|
|
49
|
+
const resolvedFile = resolve(projectPath, relativePath);
|
|
50
|
+
// Check that resolved file path starts with project path
|
|
51
|
+
if (!resolvedFile.startsWith(resolvedProject)) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
return resolvedFile;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Sanitize a language code by ensuring it matches the expected pattern
|
|
58
|
+
* Returns the sanitized code or null if invalid
|
|
59
|
+
*/
|
|
60
|
+
export function sanitizeLanguageCode(code) {
|
|
61
|
+
const trimmed = code.trim();
|
|
62
|
+
if (isValidLanguageCode(trimmed)) {
|
|
63
|
+
return trimmed;
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,OAAO,EAAwB,MAAM,MAAM,CAAC;AAErD;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,0BAA0B,CAAC;AAEhE;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC;KAChC,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CAAC,CAAC,CAAC;KACN,KAAK,CAAC,qBAAqB,EAAE;IAC5B,OAAO,EACL,mEAAmE;CACtE,CAAC,CAAC;AAEL;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC;KACtC,KAAK,CAAC,kBAAkB,CAAC;KACzB,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,0CAA0C,EAAE,CAAC,CAAC;AAEnE;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,WAAmB;IAEnB,MAAM,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAEpD,yDAAyD;IACzD,OAAO,YAAY,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AAClD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,YAAoB,EACpB,WAAmB;IAEnB,MAAM,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAExD,yDAAyD;IACzD,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@langapi/mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for LangAPI - AI-powered translation management for i18n projects",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"langapi-mcp": "./bin/langapi-mcp.js",
|
|
10
|
+
"@langapi/mcp-server": "./bin/langapi-mcp.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"bin"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"dev": "tsx watch src/index.ts",
|
|
19
|
+
"start": "node dist/index.js",
|
|
20
|
+
"lint": "eslint src/**/*.ts",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest",
|
|
23
|
+
"prepublishOnly": "npm run build"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"mcp",
|
|
27
|
+
"model-context-protocol",
|
|
28
|
+
"i18n",
|
|
29
|
+
"internationalization",
|
|
30
|
+
"translation",
|
|
31
|
+
"langapi",
|
|
32
|
+
"ai",
|
|
33
|
+
"claude",
|
|
34
|
+
"cursor"
|
|
35
|
+
],
|
|
36
|
+
"author": "LangAPI",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/TedyHub/-langapi-mcp-server"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
44
|
+
"glob": "^11.0.0",
|
|
45
|
+
"zod": "^3.24.0"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "^22.0.0",
|
|
49
|
+
"tsx": "^4.19.0",
|
|
50
|
+
"typescript": "^5.6.0",
|
|
51
|
+
"vitest": "^4.0.16"
|
|
52
|
+
},
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=18.0.0"
|
|
55
|
+
}
|
|
56
|
+
}
|