localization-mcp-server 1.0.0 → 1.0.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/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/setup.d.ts +2 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +87 -0
- package/dist/setup.js.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +9 -0
- package/src/setup.ts +100 -0
package/dist/index.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
const args = process.argv.slice(2);
|
|
3
|
+
if (args[0] === "setup") {
|
|
4
|
+
const { runSetup } = await import("./setup.js");
|
|
5
|
+
await runSetup(args.slice(1));
|
|
6
|
+
process.exit(0);
|
|
7
|
+
}
|
|
2
8
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
9
|
import { createServer } from "./server.js";
|
|
4
10
|
// Load .env from the mcp-server directory (one level above dist/)
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;IACxB,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;IAChD,MAAM,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,kEAAkE;AAClE,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;IAC1C,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;IACnD,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;IAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uFAAuF,CACxF,CAAC;AACJ,CAAC;AAED,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;IAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,+EAA+E,CAChF,CAAC;AACJ,CAAC;AAED,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;AAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
package/dist/setup.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AA0DA,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyC5D"}
|
package/dist/setup.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
const BOLD = "\x1b[1m";
|
|
3
|
+
const GREEN = "\x1b[32m";
|
|
4
|
+
const RED = "\x1b[31m";
|
|
5
|
+
const YELLOW = "\x1b[33m";
|
|
6
|
+
const RESET = "\x1b[0m";
|
|
7
|
+
const ok = (msg) => console.log(`${GREEN}✓${RESET} ${msg}`);
|
|
8
|
+
const fail = (msg) => console.error(`${RED}✗${RESET} ${msg}`);
|
|
9
|
+
const warn = (msg) => console.log(`${YELLOW}!${RESET} ${msg}`);
|
|
10
|
+
function parseArgs(args) {
|
|
11
|
+
const tokenIdx = args.indexOf("--token");
|
|
12
|
+
const backendIdx = args.indexOf("--backend-url");
|
|
13
|
+
return {
|
|
14
|
+
token: tokenIdx !== -1 ? args[tokenIdx + 1] : undefined,
|
|
15
|
+
backendUrl: backendIdx !== -1 ? args[backendIdx + 1] : undefined,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function checkClaudeCli() {
|
|
19
|
+
try {
|
|
20
|
+
execSync("claude --version", { stdio: "pipe" });
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function removeOldRegistration() {
|
|
28
|
+
try {
|
|
29
|
+
execSync('claude mcp remove "localization" -s user', { stdio: "pipe" });
|
|
30
|
+
ok("Removed old registration");
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// Not registered yet — fine
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function register(token, backendUrl) {
|
|
37
|
+
execSync(`claude mcp add "localization" -s user -e MCP_TOKEN=${token} -e BACKEND_URL=${backendUrl} -- npx -y localization-mcp-server`, { stdio: "pipe" });
|
|
38
|
+
}
|
|
39
|
+
async function verifyToken(token, backendUrl) {
|
|
40
|
+
try {
|
|
41
|
+
const response = await fetch(`${backendUrl}/translations/projects`, {
|
|
42
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
43
|
+
signal: AbortSignal.timeout(10_000),
|
|
44
|
+
});
|
|
45
|
+
return response.ok;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export async function runSetup(args) {
|
|
52
|
+
console.log(`\n${BOLD}Localization MCP — setup${RESET}\n`);
|
|
53
|
+
const { token, backendUrl = "http://localhost:8080" } = parseArgs(args);
|
|
54
|
+
if (!token) {
|
|
55
|
+
fail("Missing --token. Run the command generated by the admin panel.");
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
// 1. Check Claude CLI
|
|
59
|
+
if (!checkClaudeCli()) {
|
|
60
|
+
fail("Claude CLI not found. Install it from https://claude.ai/code");
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
ok("Claude CLI found");
|
|
64
|
+
// 2. Remove old registration
|
|
65
|
+
removeOldRegistration();
|
|
66
|
+
// 3. Register with correct token
|
|
67
|
+
try {
|
|
68
|
+
register(token, backendUrl);
|
|
69
|
+
ok("MCP server registered");
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
fail(`Failed to register MCP server: ${e}`);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
// 4. Verify token works
|
|
76
|
+
const valid = await verifyToken(token, backendUrl);
|
|
77
|
+
if (!valid) {
|
|
78
|
+
fail("Token verification failed — the token may be expired or the server is unreachable.");
|
|
79
|
+
warn("MCP is registered but will not work until the token is valid.");
|
|
80
|
+
warn("Re-run this command with a fresh token from the admin panel.");
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
ok("Token verified");
|
|
84
|
+
console.log(`\n${GREEN}${BOLD}Setup complete.${RESET}`);
|
|
85
|
+
console.log("Restart Claude for the changes to take effect.\n");
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const args = process.argv.slice(2);
|
|
4
|
+
|
|
5
|
+
if (args[0] === "setup") {
|
|
6
|
+
const { runSetup } = await import("./setup.js");
|
|
7
|
+
await runSetup(args.slice(1));
|
|
8
|
+
process.exit(0);
|
|
9
|
+
}
|
|
10
|
+
|
|
2
11
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
12
|
import { createServer } from "./server.js";
|
|
4
13
|
|
package/src/setup.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
|
|
3
|
+
const BOLD = "\x1b[1m";
|
|
4
|
+
const GREEN = "\x1b[32m";
|
|
5
|
+
const RED = "\x1b[31m";
|
|
6
|
+
const YELLOW = "\x1b[33m";
|
|
7
|
+
const RESET = "\x1b[0m";
|
|
8
|
+
|
|
9
|
+
const ok = (msg: string) => console.log(`${GREEN}✓${RESET} ${msg}`);
|
|
10
|
+
const fail = (msg: string) => console.error(`${RED}✗${RESET} ${msg}`);
|
|
11
|
+
const warn = (msg: string) => console.log(`${YELLOW}!${RESET} ${msg}`);
|
|
12
|
+
|
|
13
|
+
function parseArgs(args: string[]): { token?: string; backendUrl?: string } {
|
|
14
|
+
const tokenIdx = args.indexOf("--token");
|
|
15
|
+
const backendIdx = args.indexOf("--backend-url");
|
|
16
|
+
return {
|
|
17
|
+
token: tokenIdx !== -1 ? args[tokenIdx + 1] : undefined,
|
|
18
|
+
backendUrl: backendIdx !== -1 ? args[backendIdx + 1] : undefined,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function checkClaudeCli(): boolean {
|
|
23
|
+
try {
|
|
24
|
+
execSync("claude --version", { stdio: "pipe" });
|
|
25
|
+
return true;
|
|
26
|
+
} catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function removeOldRegistration(): void {
|
|
32
|
+
try {
|
|
33
|
+
execSync('claude mcp remove "localization" -s user', { stdio: "pipe" });
|
|
34
|
+
ok("Removed old registration");
|
|
35
|
+
} catch {
|
|
36
|
+
// Not registered yet — fine
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function register(token: string, backendUrl: string): void {
|
|
41
|
+
execSync(
|
|
42
|
+
`claude mcp add "localization" -s user -e MCP_TOKEN=${token} -e BACKEND_URL=${backendUrl} -- npx -y localization-mcp-server`,
|
|
43
|
+
{ stdio: "pipe" },
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function verifyToken(token: string, backendUrl: string): Promise<boolean> {
|
|
48
|
+
try {
|
|
49
|
+
const response = await fetch(`${backendUrl}/translations/projects`, {
|
|
50
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
51
|
+
signal: AbortSignal.timeout(10_000),
|
|
52
|
+
});
|
|
53
|
+
return response.ok;
|
|
54
|
+
} catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function runSetup(args: string[]): Promise<void> {
|
|
60
|
+
console.log(`\n${BOLD}Localization MCP — setup${RESET}\n`);
|
|
61
|
+
|
|
62
|
+
const { token, backendUrl = "http://localhost:8080" } = parseArgs(args);
|
|
63
|
+
|
|
64
|
+
if (!token) {
|
|
65
|
+
fail("Missing --token. Run the command generated by the admin panel.");
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 1. Check Claude CLI
|
|
70
|
+
if (!checkClaudeCli()) {
|
|
71
|
+
fail("Claude CLI not found. Install it from https://claude.ai/code");
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
ok("Claude CLI found");
|
|
75
|
+
|
|
76
|
+
// 2. Remove old registration
|
|
77
|
+
removeOldRegistration();
|
|
78
|
+
|
|
79
|
+
// 3. Register with correct token
|
|
80
|
+
try {
|
|
81
|
+
register(token, backendUrl);
|
|
82
|
+
ok("MCP server registered");
|
|
83
|
+
} catch (e) {
|
|
84
|
+
fail(`Failed to register MCP server: ${e}`);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// 4. Verify token works
|
|
89
|
+
const valid = await verifyToken(token, backendUrl);
|
|
90
|
+
if (!valid) {
|
|
91
|
+
fail("Token verification failed — the token may be expired or the server is unreachable.");
|
|
92
|
+
warn("MCP is registered but will not work until the token is valid.");
|
|
93
|
+
warn("Re-run this command with a fresh token from the admin panel.");
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
ok("Token verified");
|
|
97
|
+
|
|
98
|
+
console.log(`\n${GREEN}${BOLD}Setup complete.${RESET}`);
|
|
99
|
+
console.log("Restart Claude for the changes to take effect.\n");
|
|
100
|
+
}
|