@babelize/mcp 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/LICENSE +6 -0
- package/README.md +119 -0
- package/dist/client.d.ts +3 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +22 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +46 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +63 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +109 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/glossary-get.d.ts +20 -0
- package/dist/tools/glossary-get.d.ts.map +1 -0
- package/dist/tools/glossary-get.js +53 -0
- package/dist/tools/glossary-get.js.map +1 -0
- package/dist/tools/glossary-set.d.ts +23 -0
- package/dist/tools/glossary-set.d.ts.map +1 -0
- package/dist/tools/glossary-set.js +64 -0
- package/dist/tools/glossary-set.js.map +1 -0
- package/dist/tools/run.d.ts +21 -0
- package/dist/tools/run.d.ts.map +1 -0
- package/dist/tools/run.js +41 -0
- package/dist/tools/run.js.map +1 -0
- package/dist/tools/scan.d.ts +19 -0
- package/dist/tools/scan.d.ts.map +1 -0
- package/dist/tools/scan.js +60 -0
- package/dist/tools/scan.js.map +1 -0
- package/dist/tools/status.d.ts +19 -0
- package/dist/tools/status.d.ts.map +1 -0
- package/dist/tools/status.js +36 -0
- package/dist/tools/status.js.map +1 -0
- package/dist/utils/scan-strings.d.ts +13 -0
- package/dist/utils/scan-strings.d.ts.map +1 -0
- package/dist/utils/scan-strings.js +144 -0
- package/dist/utils/scan-strings.js.map +1 -0
- package/package.json +53 -0
package/LICENSE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# @babelize/mcp
|
|
2
|
+
|
|
3
|
+
**MCP (Model Context Protocol) server for Babelize** — let AI coding agents translate your apps directly from your editor.
|
|
4
|
+
|
|
5
|
+
Works with any MCP-compatible client: Cursor, Claude Desktop, opencode, VS Code (via extension), and more.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @babelize/mcp
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or run on-demand without installing:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx -y @babelize/mcp
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
1. **Get an API key** from [babelize.co](https://babelize.co)
|
|
22
|
+
2. **Set your API key:**
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
export BABELIZE_API_KEY=bblz_sk_...
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or create `.babelize/config.json` in your project:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{ "apiKey": "bblz_sk_..." }
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
3. **Configure your editor** (see below)
|
|
35
|
+
|
|
36
|
+
## IDE Configuration
|
|
37
|
+
|
|
38
|
+
### Cursor
|
|
39
|
+
|
|
40
|
+
Add to `.cursor/mcp.json`:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"mcpServers": {
|
|
45
|
+
"babelize": {
|
|
46
|
+
"command": "npx",
|
|
47
|
+
"args": ["-y", "@babelize/mcp"],
|
|
48
|
+
"env": {
|
|
49
|
+
"BABELIZE_API_KEY": "bblz_sk_..."
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Claude Desktop
|
|
57
|
+
|
|
58
|
+
Add to `claude_desktop_config.json`:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"mcpServers": {
|
|
63
|
+
"babelize": {
|
|
64
|
+
"command": "npx",
|
|
65
|
+
"args": ["-y", "@babelize/mcp"]
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### opencode
|
|
72
|
+
|
|
73
|
+
Add to `.opencode.json`:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"mcpServers": {
|
|
78
|
+
"babelize": {
|
|
79
|
+
"command": "npx",
|
|
80
|
+
"args": ["-y", "@babelize/mcp"],
|
|
81
|
+
"env": []
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Available Tools
|
|
88
|
+
|
|
89
|
+
| Tool | Description |
|
|
90
|
+
|------|-------------|
|
|
91
|
+
| `babelize_run_start` | Start a translation pipeline run for the project |
|
|
92
|
+
| `babelize_run_status` | Check the status of a running translation |
|
|
93
|
+
| `babelize_glossary_get` | View the translation glossary |
|
|
94
|
+
| `babelize_glossary_set` | Add or update terms in the translation glossary |
|
|
95
|
+
| `babelize_scan` | Scan project files for translatable strings |
|
|
96
|
+
| `babelize_status` | Check Babelize API server health |
|
|
97
|
+
|
|
98
|
+
## Configuration
|
|
99
|
+
|
|
100
|
+
The server resolves configuration in this priority order:
|
|
101
|
+
|
|
102
|
+
1. **CLI args** — `--api-key`, `--api-url`, `--api-base`
|
|
103
|
+
2. **Environment variables** — `BABELIZE_API_KEY`, `BABELIZE_API_URL`
|
|
104
|
+
3. **Local config file** — `.babelize/config.json` in the current working directory
|
|
105
|
+
|
|
106
|
+
### Options
|
|
107
|
+
|
|
108
|
+
| Option / Env Var | Description | Default |
|
|
109
|
+
|-----------------|-------------|---------|
|
|
110
|
+
| `--api-key` / `BABELIZE_API_KEY` | Your Babelize API key | — |
|
|
111
|
+
| `--api-url` / `BABELIZE_API_URL` | API base URL | `https://api.babelize.co/api` |
|
|
112
|
+
| `--api-base` | API base path (without `/api` suffix) | — |
|
|
113
|
+
|
|
114
|
+
## Links
|
|
115
|
+
|
|
116
|
+
- [Website](https://babelize.co)
|
|
117
|
+
- [Docs](https://docs.babelize.co)
|
|
118
|
+
- [GitHub](https://github.com/babelize/babelize-dashboard)
|
|
119
|
+
- [npm](https://www.npmjs.com/package/@babelize/mcp)
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAK7C,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,aAAa,CAoBxE"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import pkg from '../package.json' with { type: 'json' };
|
|
3
|
+
const CLI_VERSION = pkg.version;
|
|
4
|
+
export function getClient(apiUrl, apiKey) {
|
|
5
|
+
const baseURL = apiUrl.replace(/\/+$/, '') + '/api';
|
|
6
|
+
const client = axios.create({
|
|
7
|
+
baseURL,
|
|
8
|
+
timeout: 60_000,
|
|
9
|
+
headers: {
|
|
10
|
+
'Content-Type': 'application/json',
|
|
11
|
+
'User-Agent': `babelize-mcp/${CLI_VERSION}`,
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
if (apiKey) {
|
|
15
|
+
client.interceptors.request.use((req) => {
|
|
16
|
+
req.headers['Authorization'] = `Bearer ${apiKey}`;
|
|
17
|
+
return req;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return client;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAwB,MAAM,OAAO,CAAC;AAC7C,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAExD,MAAM,WAAW,GAAG,GAAG,CAAC,OAAiB,CAAC;AAE1C,MAAM,UAAU,SAAS,CAAC,MAAc,EAAE,MAAe;IACvD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC;IAEpD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC1B,OAAO;QACP,OAAO,EAAE,MAAM;QACf,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,YAAY,EAAE,gBAAgB,WAAW,EAAE;SAC5C;KACF,CAAC,CAAC;IAEH,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YACtC,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,MAAM,EAAE,CAAC;YAClD,OAAO,GAAG,CAAC;QACb,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AA4BD,wBAAgB,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAyBjD"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
function extractArg(args, name) {
|
|
4
|
+
const index = args.indexOf(name);
|
|
5
|
+
if (index !== -1 && index + 1 < args.length) {
|
|
6
|
+
return args[index + 1];
|
|
7
|
+
}
|
|
8
|
+
// Also support --key=value format
|
|
9
|
+
for (const arg of args) {
|
|
10
|
+
if (arg.startsWith(`${name}=`)) {
|
|
11
|
+
return arg.slice(name.length + 1);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
function readLocalConfig(cwd) {
|
|
17
|
+
try {
|
|
18
|
+
const configPath = join(cwd ?? process.cwd(), '.babelize', 'config.json');
|
|
19
|
+
if (existsSync(configPath)) {
|
|
20
|
+
return JSON.parse(readFileSync(configPath, 'utf8'));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Silently ignore malformed config
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
export function getConfig(cwd) {
|
|
29
|
+
const args = process.argv.slice(2);
|
|
30
|
+
const localConfig = readLocalConfig(cwd);
|
|
31
|
+
const apiKey = extractArg(args, '--api-key') ??
|
|
32
|
+
extractArg(args, '--apiKey') ??
|
|
33
|
+
process.env.BABELIZE_API_KEY ??
|
|
34
|
+
localConfig?.apiKey;
|
|
35
|
+
const apiUrl = extractArg(args, '--api-url') ??
|
|
36
|
+
extractArg(args, '--apiUrl') ??
|
|
37
|
+
process.env.BABELIZE_API_URL ??
|
|
38
|
+
localConfig?.apiUrl ??
|
|
39
|
+
'https://api.babelize.co';
|
|
40
|
+
if (apiKey && !apiKey.startsWith('bblz_sk_')) {
|
|
41
|
+
throw new Error('Invalid API key format. Expected bblz_sk_... prefix.\n' +
|
|
42
|
+
'Generate a valid key at https://app.babelize.co/settings/api-keys');
|
|
43
|
+
}
|
|
44
|
+
return { apiKey, apiUrl };
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAOjC,SAAS,UAAU,CAAC,IAAc,EAAE,IAAY;IAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5C,OAAO,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IACzB,CAAC;IACD,kCAAkC;IAClC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;YAC/B,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,eAAe,CAAC,GAAY;IACnC,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;QAC1E,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;IACrC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAY;IACpC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,WAAW,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAEzC,MAAM,MAAM,GACV,UAAU,CAAC,IAAI,EAAE,WAAW,CAAC;QAC7B,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,gBAAgB;QAC3B,WAAW,EAAE,MAA6B,CAAC;IAE9C,MAAM,MAAM,GACV,UAAU,CAAC,IAAI,EAAE,WAAW,CAAC;QAC7B,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,gBAAgB;QAC3B,WAAW,EAAE,MAA6B;QAC3C,yBAAyB,CAAC;IAE5B,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CACb,wDAAwD;YACxD,mEAAmE,CACpE,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC5B,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { createServer } from './server.js';
|
|
4
|
+
import { getConfig } from './config.js';
|
|
5
|
+
import pkg from '../package.json' with { type: 'json' };
|
|
6
|
+
const CLI_VERSION = pkg.version;
|
|
7
|
+
function showHelp() {
|
|
8
|
+
const help = `
|
|
9
|
+
@babelize/mcp v${CLI_VERSION} — MCP server for Babelize AI-powered i18n
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
babelize-mcp [options]
|
|
13
|
+
|
|
14
|
+
Options:
|
|
15
|
+
--api-key <key> Babelize API key (or BABELIZE_API_KEY env)
|
|
16
|
+
--apiKey <key> Alternative form of --api-key
|
|
17
|
+
--api-url <url> API base URL (default: https://api.babelize.co)
|
|
18
|
+
--apiUrl <url> Alternative form of --api-url
|
|
19
|
+
--help, -h Show this help message
|
|
20
|
+
--version, -v Show version
|
|
21
|
+
|
|
22
|
+
Environment variables:
|
|
23
|
+
BABELIZE_API_KEY API key (fallback if --api-key not provided)
|
|
24
|
+
BABELIZE_API_URL API URL (fallback if --api-url not provided)
|
|
25
|
+
|
|
26
|
+
Configuration file:
|
|
27
|
+
.babelize/config.json in the current working directory
|
|
28
|
+
|
|
29
|
+
Available tools (via MCP):
|
|
30
|
+
babelize_scan Scan a local directory for hardcoded strings
|
|
31
|
+
babelize_scan_strings Extract translatable strings from a code snippet
|
|
32
|
+
babelize_run Start a translation pipeline run
|
|
33
|
+
babelize_status Check status of a running translation
|
|
34
|
+
babelize_glossary_get List glossary entries for a project
|
|
35
|
+
babelize_glossary_set Add or update a glossary entry
|
|
36
|
+
|
|
37
|
+
Documentation: https://docs.babelize.co
|
|
38
|
+
`.trim();
|
|
39
|
+
console.error(help);
|
|
40
|
+
}
|
|
41
|
+
async function main() {
|
|
42
|
+
const args = process.argv.slice(2);
|
|
43
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
44
|
+
showHelp();
|
|
45
|
+
process.exit(0);
|
|
46
|
+
}
|
|
47
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
48
|
+
console.error(`@babelize/mcp v${CLI_VERSION}`);
|
|
49
|
+
process.exit(0);
|
|
50
|
+
}
|
|
51
|
+
const { apiKey, apiUrl } = getConfig();
|
|
52
|
+
const server = createServer(apiUrl, apiKey);
|
|
53
|
+
const transport = new StdioServerTransport();
|
|
54
|
+
console.error(`@babelize/mcp v${CLI_VERSION} server starting...`);
|
|
55
|
+
console.error(` API URL: ${apiUrl}`);
|
|
56
|
+
console.error(` Transport: stdio`);
|
|
57
|
+
await server.connect(transport);
|
|
58
|
+
}
|
|
59
|
+
main().catch((err) => {
|
|
60
|
+
console.error('Fatal error:', err);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
});
|
|
63
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAExD,MAAM,WAAW,GAAG,GAAG,CAAC,OAAiB,CAAC;AAE1C,SAAS,QAAQ;IACf,MAAM,IAAI,GAAG;iBACE,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6B3B,CAAC,IAAI,EAAE,CAAC;IACP,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,QAAQ,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,OAAO,CAAC,KAAK,CAAC,kBAAkB,WAAW,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;IAEvC,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,OAAO,CAAC,KAAK,CAAC,kBAAkB,WAAW,qBAAqB,CAAC,CAAC;IAClE,OAAO,CAAC,KAAK,CAAC,cAAc,MAAM,EAAE,CAAC,CAAC;IACtC,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAEpC,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAgBpE,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CA+HvE"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { getClient } from './client.js';
|
|
4
|
+
import { handleScan } from './tools/scan.js';
|
|
5
|
+
import { handleRun } from './tools/run.js';
|
|
6
|
+
import { handleStatus } from './tools/status.js';
|
|
7
|
+
import { handleGlossaryGet } from './tools/glossary-get.js';
|
|
8
|
+
import { handleGlossarySet } from './tools/glossary-set.js';
|
|
9
|
+
import { extractStrings } from './utils/scan-strings.js';
|
|
10
|
+
import pkg from '../package.json' with { type: 'json' };
|
|
11
|
+
const CLI_VERSION = pkg.version;
|
|
12
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
13
|
+
export function createServer(apiUrl, apiKey) {
|
|
14
|
+
const client = apiKey ? getClient(apiUrl, apiKey) : null;
|
|
15
|
+
const server = new McpServer({
|
|
16
|
+
name: '@babelize/mcp',
|
|
17
|
+
version: CLI_VERSION,
|
|
18
|
+
}, {
|
|
19
|
+
capabilities: {
|
|
20
|
+
tools: {},
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
const register = server.registerTool.bind(server);
|
|
24
|
+
register('babelize_scan', {
|
|
25
|
+
description: 'Scan a local directory for hardcoded strings. No API key required.',
|
|
26
|
+
inputSchema: z.object({ directory: z.string(), extensions: z.array(z.string()).optional() }),
|
|
27
|
+
}, async (params) => {
|
|
28
|
+
return handleScan(params);
|
|
29
|
+
});
|
|
30
|
+
register('babelize_run', {
|
|
31
|
+
description: 'Trigger a Babelize translation run for target languages. Requires API key.',
|
|
32
|
+
inputSchema: z.object({
|
|
33
|
+
project_id: z.string(),
|
|
34
|
+
target_locales: z.array(z.string()),
|
|
35
|
+
source_locale: z.string().optional(),
|
|
36
|
+
}),
|
|
37
|
+
}, async (params) => {
|
|
38
|
+
if (!client)
|
|
39
|
+
return {
|
|
40
|
+
content: [{ type: 'text', text: '❌ API key required. Set BABELIZE_API_KEY or pass --api-key.' }],
|
|
41
|
+
isError: true,
|
|
42
|
+
};
|
|
43
|
+
return handleRun(client, params);
|
|
44
|
+
});
|
|
45
|
+
register('babelize_status', {
|
|
46
|
+
description: 'Check status of a translation run. Requires API key.',
|
|
47
|
+
inputSchema: z.object({ babel_id: z.string() }),
|
|
48
|
+
}, async (params) => {
|
|
49
|
+
if (!client)
|
|
50
|
+
return {
|
|
51
|
+
content: [{ type: 'text', text: '❌ API key required. Set BABELIZE_API_KEY or pass --api-key.' }],
|
|
52
|
+
isError: true,
|
|
53
|
+
};
|
|
54
|
+
return handleStatus(client, params);
|
|
55
|
+
});
|
|
56
|
+
register('babelize_glossary_get', {
|
|
57
|
+
description: 'List glossary entries for a project. Requires API key.',
|
|
58
|
+
inputSchema: z.object({
|
|
59
|
+
project_id: z.string(),
|
|
60
|
+
search: z.string().optional(),
|
|
61
|
+
}),
|
|
62
|
+
}, async (params) => {
|
|
63
|
+
if (!client)
|
|
64
|
+
return {
|
|
65
|
+
content: [{ type: 'text', text: '❌ API key required. Set BABELIZE_API_KEY or pass --api-key.' }],
|
|
66
|
+
isError: true,
|
|
67
|
+
};
|
|
68
|
+
return handleGlossaryGet(client, params);
|
|
69
|
+
});
|
|
70
|
+
register('babelize_glossary_set', {
|
|
71
|
+
description: 'Add a glossary entry to ensure consistent translations. Requires API key.',
|
|
72
|
+
inputSchema: z.object({
|
|
73
|
+
project_id: z.string(),
|
|
74
|
+
source: z.string(),
|
|
75
|
+
target: z.string(),
|
|
76
|
+
type: z.string().optional(),
|
|
77
|
+
locale: z.string().optional(),
|
|
78
|
+
}),
|
|
79
|
+
}, async (params) => {
|
|
80
|
+
if (!client)
|
|
81
|
+
return {
|
|
82
|
+
content: [{ type: 'text', text: '❌ API key required. Set BABELIZE_API_KEY or pass --api-key.' }],
|
|
83
|
+
isError: true,
|
|
84
|
+
};
|
|
85
|
+
return handleGlossarySet(client, params);
|
|
86
|
+
});
|
|
87
|
+
register('babelize_scan_strings', {
|
|
88
|
+
description: 'Extract hardcoded translatable strings from a code snippet. No API key required.',
|
|
89
|
+
inputSchema: z.object({ code: z.string() }),
|
|
90
|
+
}, ({ code }) => {
|
|
91
|
+
const results = extractStrings(code);
|
|
92
|
+
if (results.length === 0) {
|
|
93
|
+
return {
|
|
94
|
+
content: [{ type: 'text', text: 'No translatable strings found.' }],
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const lines = results.map((s) => ` Line ${s.line}: "${s.text}"`);
|
|
98
|
+
return {
|
|
99
|
+
content: [
|
|
100
|
+
{
|
|
101
|
+
type: 'text',
|
|
102
|
+
text: [`Found ${results.length} translatable strings:`, ...lines].join('\n'),
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
return server;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
interface GlossaryGetParams {
|
|
3
|
+
project_id: string;
|
|
4
|
+
search?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function handleGlossaryGet(client: AxiosInstance, params: GlossaryGetParams): Promise<{
|
|
7
|
+
content: {
|
|
8
|
+
type: "text";
|
|
9
|
+
text: string;
|
|
10
|
+
}[];
|
|
11
|
+
isError?: undefined;
|
|
12
|
+
} | {
|
|
13
|
+
content: {
|
|
14
|
+
type: "text";
|
|
15
|
+
text: string;
|
|
16
|
+
}[];
|
|
17
|
+
isError: boolean;
|
|
18
|
+
}>;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=glossary-get.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glossary-get.d.ts","sourceRoot":"","sources":["../../src/tools/glossary-get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,UAAU,iBAAiB;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,iBAAiB;;;;;;;;;;;;GAwDvF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export async function handleGlossaryGet(client, params) {
|
|
2
|
+
const { project_id, search } = params;
|
|
3
|
+
try {
|
|
4
|
+
const searchParams = new URLSearchParams();
|
|
5
|
+
if (search)
|
|
6
|
+
searchParams.set('search', search);
|
|
7
|
+
const query = searchParams.toString();
|
|
8
|
+
const url = `/projects/${project_id}/glossary${query ? `?${query}` : ''}`;
|
|
9
|
+
const response = await client.get(url);
|
|
10
|
+
const data = response.data;
|
|
11
|
+
const rawEntries = Array.isArray(data) ? data : data.data ?? [];
|
|
12
|
+
const entries = [];
|
|
13
|
+
for (const e of rawEntries) {
|
|
14
|
+
if (e && typeof e === 'object') {
|
|
15
|
+
entries.push({
|
|
16
|
+
term: String(e.term ?? ''),
|
|
17
|
+
type: String(e.type ?? 'never_translate'),
|
|
18
|
+
translations: e.translations,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (entries.length === 0) {
|
|
23
|
+
return {
|
|
24
|
+
content: [{ type: 'text', text: '📖 No glossary entries found.' }],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const lines = [
|
|
28
|
+
`📖 Glossary (${entries.length} entries)${search ? ` matching "${search}"` : ''}:`,
|
|
29
|
+
'',
|
|
30
|
+
];
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
const translationStr = entry.translations && Object.keys(entry.translations).length > 0
|
|
33
|
+
? Object.entries(entry.translations).map(([l, t]) => `${l}: "${t}"`).join(', ')
|
|
34
|
+
: '(never translated)';
|
|
35
|
+
lines.push(` • "${entry.term}" → ${translationStr} [${entry.type}]`);
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
const message = err instanceof Object && err !== null && 'response' in err
|
|
43
|
+
? (err.response?.data?.error || 'Unknown error')
|
|
44
|
+
: err instanceof Error
|
|
45
|
+
? err.message
|
|
46
|
+
: 'Unknown error';
|
|
47
|
+
return {
|
|
48
|
+
content: [{ type: 'text', text: `❌ Failed to get glossary: ${message}` }],
|
|
49
|
+
isError: true,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=glossary-get.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glossary-get.js","sourceRoot":"","sources":["../../src/tools/glossary-get.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
interface GlossarySetParams {
|
|
3
|
+
project_id: string;
|
|
4
|
+
source: string;
|
|
5
|
+
target: string;
|
|
6
|
+
type?: string;
|
|
7
|
+
locale?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function handleGlossarySet(client: AxiosInstance, params: GlossarySetParams): Promise<{
|
|
10
|
+
content: {
|
|
11
|
+
type: "text";
|
|
12
|
+
text: string;
|
|
13
|
+
}[];
|
|
14
|
+
isError: boolean;
|
|
15
|
+
} | {
|
|
16
|
+
content: {
|
|
17
|
+
type: "text";
|
|
18
|
+
text: string;
|
|
19
|
+
}[];
|
|
20
|
+
isError?: undefined;
|
|
21
|
+
}>;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=glossary-set.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glossary-set.d.ts","sourceRoot":"","sources":["../../src/tools/glossary-set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,UAAU,iBAAiB;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,iBAAiB;;;;;;;;;;;;GAqEvF"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export async function handleGlossarySet(client, params) {
|
|
2
|
+
const { project_id, source, target, type, locale } = params;
|
|
3
|
+
if (!source.trim() || !target.trim()) {
|
|
4
|
+
return {
|
|
5
|
+
content: [{ type: 'text', text: '❌ Both source and target are required.' }],
|
|
6
|
+
isError: true,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
const backendType = type === 'always_translate_as' || type === 'always_translate'
|
|
10
|
+
? 'always_translate_as'
|
|
11
|
+
: 'never_translate';
|
|
12
|
+
const trimmedLocale = locale?.trim();
|
|
13
|
+
if (backendType === 'always_translate_as' && !trimmedLocale) {
|
|
14
|
+
return {
|
|
15
|
+
content: [{ type: 'text', text: '❌ locale is required when type is always_translate_as.' }],
|
|
16
|
+
isError: true,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const translations = backendType === 'always_translate_as'
|
|
20
|
+
? { [trimmedLocale]: target.trim() }
|
|
21
|
+
: {};
|
|
22
|
+
try {
|
|
23
|
+
const response = await client.post(`/projects/${project_id}/glossary`, {
|
|
24
|
+
term: source.trim(),
|
|
25
|
+
type: backendType,
|
|
26
|
+
translations,
|
|
27
|
+
});
|
|
28
|
+
const entry = response.data;
|
|
29
|
+
const term = String(entry?.term ?? source.trim());
|
|
30
|
+
const eType = String(entry?.type ?? backendType);
|
|
31
|
+
const rawTranslations = entry?.translations;
|
|
32
|
+
const responseTranslations = rawTranslations && typeof rawTranslations === 'object'
|
|
33
|
+
? rawTranslations
|
|
34
|
+
: {};
|
|
35
|
+
const translationDisplay = Object.keys(responseTranslations).length > 0
|
|
36
|
+
? Object.entries(responseTranslations).map(([l, t]) => `${l}: "${t}"`).join(', ')
|
|
37
|
+
: '(none)';
|
|
38
|
+
return {
|
|
39
|
+
content: [
|
|
40
|
+
{
|
|
41
|
+
type: 'text',
|
|
42
|
+
text: [
|
|
43
|
+
`✅ Glossary entry added:`,
|
|
44
|
+
` Term: "${term}"`,
|
|
45
|
+
` Type: ${eType}`,
|
|
46
|
+
` Translations: ${translationDisplay}`,
|
|
47
|
+
].join('\n'),
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
const message = err instanceof Object && err !== null && 'response' in err
|
|
54
|
+
? (err.response?.data?.error || 'Unknown error')
|
|
55
|
+
: err instanceof Error
|
|
56
|
+
? err.message
|
|
57
|
+
: 'Unknown error';
|
|
58
|
+
return {
|
|
59
|
+
content: [{ type: 'text', text: `❌ Failed to set glossary entry: ${message}` }],
|
|
60
|
+
isError: true,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=glossary-set.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glossary-set.js","sourceRoot":"","sources":["../../src/tools/glossary-set.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
interface RunParams {
|
|
3
|
+
project_id: string;
|
|
4
|
+
target_locales: string[];
|
|
5
|
+
source_locale?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function handleRun(client: AxiosInstance, params: RunParams): Promise<{
|
|
8
|
+
content: {
|
|
9
|
+
type: "text";
|
|
10
|
+
text: string;
|
|
11
|
+
}[];
|
|
12
|
+
isError?: undefined;
|
|
13
|
+
} | {
|
|
14
|
+
content: {
|
|
15
|
+
type: "text";
|
|
16
|
+
text: string;
|
|
17
|
+
}[];
|
|
18
|
+
isError: boolean;
|
|
19
|
+
}>;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/tools/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,UAAU,SAAS;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS;;;;;;;;;;;;GAyCvE"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export async function handleRun(client, params) {
|
|
2
|
+
const { project_id, target_locales, source_locale } = params;
|
|
3
|
+
try {
|
|
4
|
+
const response = await client.post('/engine/babel', {
|
|
5
|
+
project_id,
|
|
6
|
+
target_locales,
|
|
7
|
+
source_locale: source_locale || 'en',
|
|
8
|
+
dry_run: false,
|
|
9
|
+
});
|
|
10
|
+
const data = response.data;
|
|
11
|
+
const babelId = (data.babel_id ?? data.id);
|
|
12
|
+
return {
|
|
13
|
+
content: [
|
|
14
|
+
{
|
|
15
|
+
type: 'text',
|
|
16
|
+
text: [
|
|
17
|
+
`🚀 Babel translation run started!`,
|
|
18
|
+
``,
|
|
19
|
+
` Babel ID: ${babelId}`,
|
|
20
|
+
` Target languages: ${target_locales.join(', ')}`,
|
|
21
|
+
` Source language: ${source_locale || 'en'}`,
|
|
22
|
+
``,
|
|
23
|
+
`Use babelize_status to check progress.`,
|
|
24
|
+
].join('\n'),
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
const message = err instanceof Object && err !== null && 'response' in err
|
|
31
|
+
? (err.response?.data?.error || 'Unknown error')
|
|
32
|
+
: err instanceof Error
|
|
33
|
+
? err.message
|
|
34
|
+
: 'Unknown error';
|
|
35
|
+
return {
|
|
36
|
+
content: [{ type: 'text', text: `❌ Failed to start babel run: ${message}` }],
|
|
37
|
+
isError: true,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/tools/run.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAqB,EAAE,MAAiB;IACtE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC;IAE7D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE;YAClD,UAAU;YACV,cAAc;YACd,aAAa,EAAE,aAAa,IAAI,IAAI;YACpC,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAA+B,CAAC;QACtD,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,EAAE,CAAW,CAAC;QAErD,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE;wBACJ,mCAAmC;wBACnC,EAAE;wBACF,eAAe,OAAO,EAAE;wBACxB,uBAAuB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;wBAClD,sBAAsB,aAAa,IAAI,IAAI,EAAE;wBAC7C,EAAE;wBACF,wCAAwC;qBACzC,CAAC,IAAI,CAAC,IAAI,CAAC;iBACb;aACF;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,GAAG,YAAY,MAAM,IAAI,GAAG,KAAK,IAAI,IAAI,UAAU,IAAI,GAAG;YACxE,CAAC,CAAC,CAAE,GAAiD,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,IAAI,eAAe,CAAC;YAC/F,CAAC,CAAC,GAAG,YAAY,KAAK;gBACpB,CAAC,CAAC,GAAG,CAAC,OAAO;gBACb,CAAC,CAAC,eAAe,CAAC;QACtB,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,gCAAgC,OAAO,EAAE,EAAE,CAAC;YACrF,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface ScanParams {
|
|
2
|
+
directory: string;
|
|
3
|
+
extensions?: string[];
|
|
4
|
+
}
|
|
5
|
+
export declare function handleScan(params: ScanParams): Promise<{
|
|
6
|
+
content: {
|
|
7
|
+
type: "text";
|
|
8
|
+
text: string;
|
|
9
|
+
}[];
|
|
10
|
+
isError: boolean;
|
|
11
|
+
} | {
|
|
12
|
+
content: {
|
|
13
|
+
type: "text";
|
|
14
|
+
text: string;
|
|
15
|
+
}[];
|
|
16
|
+
isError?: undefined;
|
|
17
|
+
}>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/tools/scan.ts"],"names":[],"mappings":"AAGA,UAAU,UAAU;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,UAAU;;;;;;;;;;;;GAiElD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
|
+
import { scanDirectory } from '../utils/scan-strings.js';
|
|
3
|
+
export async function handleScan(params) {
|
|
4
|
+
const { directory, extensions } = params;
|
|
5
|
+
// Verify the directory exists
|
|
6
|
+
try {
|
|
7
|
+
const dirStat = await stat(directory);
|
|
8
|
+
if (!dirStat.isDirectory()) {
|
|
9
|
+
return {
|
|
10
|
+
content: [{ type: 'text', text: 'Error: Path is not a directory' }],
|
|
11
|
+
isError: true,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return {
|
|
17
|
+
content: [{ type: 'text', text: `Error: Directory not found: ${directory}` }],
|
|
18
|
+
isError: true,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
// Progress indicator for large directories
|
|
22
|
+
const startTime = Date.now();
|
|
23
|
+
process.stderr.write(`Scanning ${directory} for hardcoded strings...\n`);
|
|
24
|
+
const results = await scanDirectory(directory, extensions);
|
|
25
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
26
|
+
process.stderr.write(`Scan complete in ${elapsed}s. Found ${results.length} files with strings.\n`);
|
|
27
|
+
if (results.length === 0) {
|
|
28
|
+
return {
|
|
29
|
+
content: [
|
|
30
|
+
{
|
|
31
|
+
type: 'text',
|
|
32
|
+
text: '✅ No hardcoded strings found. Your codebase looks clean!',
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const totalCount = results.reduce((sum, f) => sum + f.hardcoded_strings.length, 0);
|
|
38
|
+
const totalFiles = results.length;
|
|
39
|
+
const lines = [
|
|
40
|
+
`Found ${totalCount} hardcoded strings across ${totalFiles} files.\n`,
|
|
41
|
+
];
|
|
42
|
+
for (const file of results.slice(0, 10)) {
|
|
43
|
+
lines.push(`📄 ${file.path}`);
|
|
44
|
+
const previews = file.hardcoded_strings.slice(0, 5);
|
|
45
|
+
for (const s of previews) {
|
|
46
|
+
lines.push(` Line ${s.line}: "${s.text}"`);
|
|
47
|
+
}
|
|
48
|
+
if (file.hardcoded_strings.length > 5) {
|
|
49
|
+
lines.push(` ... and ${file.hardcoded_strings.length - 5} more`);
|
|
50
|
+
}
|
|
51
|
+
lines.push('');
|
|
52
|
+
}
|
|
53
|
+
if (results.length > 10) {
|
|
54
|
+
lines.push(`... and ${results.length - 10} more files with hardcoded strings.`);
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/tools/scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
interface StatusParams {
|
|
3
|
+
babel_id: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function handleStatus(client: AxiosInstance, params: StatusParams): Promise<{
|
|
6
|
+
content: {
|
|
7
|
+
type: "text";
|
|
8
|
+
text: string;
|
|
9
|
+
}[];
|
|
10
|
+
isError?: undefined;
|
|
11
|
+
} | {
|
|
12
|
+
content: {
|
|
13
|
+
type: "text";
|
|
14
|
+
text: string;
|
|
15
|
+
}[];
|
|
16
|
+
isError: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/tools/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY;;;;;;;;;;;;GAuC7E"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export async function handleStatus(client, params) {
|
|
2
|
+
const { babel_id } = params;
|
|
3
|
+
try {
|
|
4
|
+
const response = await client.get(`/engine/status/${babel_id}`);
|
|
5
|
+
const data = response.data;
|
|
6
|
+
const status = data.status ?? 'unknown';
|
|
7
|
+
const completedAt = data.completed_at ?? null;
|
|
8
|
+
const error = data.error ?? null;
|
|
9
|
+
const lines = [
|
|
10
|
+
`📊 Babel Run Status: ${babel_id}`,
|
|
11
|
+
``,
|
|
12
|
+
` Status: ${status}`,
|
|
13
|
+
];
|
|
14
|
+
if (completedAt) {
|
|
15
|
+
lines.push(` Completed: ${completedAt}`);
|
|
16
|
+
}
|
|
17
|
+
if (error) {
|
|
18
|
+
lines.push(` Error: ${error}`);
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
const message = err instanceof Object && err !== null && 'response' in err
|
|
26
|
+
? (err.response?.data?.error || 'Unknown error')
|
|
27
|
+
: err instanceof Error
|
|
28
|
+
? err.message
|
|
29
|
+
: 'Unknown error';
|
|
30
|
+
return {
|
|
31
|
+
content: [{ type: 'text', text: `❌ Failed to get status: ${message}` }],
|
|
32
|
+
isError: true,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/tools/status.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAqB,EAAE,MAAoB;IAC5E,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;IAE5B,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,kBAAkB,QAAQ,EAAE,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG,QAAQ,CAAC,IAA+B,CAAC;QAEtD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAgB,IAAI,SAAS,CAAC;QAClD,MAAM,WAAW,GAAG,IAAI,CAAC,YAAsB,IAAI,IAAI,CAAC;QACxD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAe,IAAI,IAAI,CAAC;QAE3C,MAAM,KAAK,GAAa;YACtB,wBAAwB,QAAQ,EAAE;YAClC,EAAE;YACF,aAAa,MAAM,EAAE;SACtB,CAAC;QAEF,IAAI,WAAW,EAAE,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,gBAAgB,WAAW,EAAE,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,IAAI,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;QAClC,CAAC;QAED,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;SAC7D,CAAC;IACJ,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,GAAG,YAAY,MAAM,IAAI,GAAG,KAAK,IAAI,IAAI,UAAU,IAAI,GAAG;YACxE,CAAC,CAAC,CAAE,GAAiD,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,IAAI,eAAe,CAAC;YAC/F,CAAC,CAAC,GAAG,YAAY,KAAK;gBACpB,CAAC,CAAC,GAAG,CAAC,OAAO;gBACb,CAAC,CAAC,eAAe,CAAC;QACtB,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,2BAA2B,OAAO,EAAE,EAAE,CAAC;YAChF,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface HardcodedString {
|
|
2
|
+
text: string;
|
|
3
|
+
line: number;
|
|
4
|
+
}
|
|
5
|
+
interface ScanResult {
|
|
6
|
+
path: string;
|
|
7
|
+
hardcoded_strings: HardcodedString[];
|
|
8
|
+
}
|
|
9
|
+
export declare function isTranslatable(text: string): boolean;
|
|
10
|
+
export declare function extractStrings(content: string): HardcodedString[];
|
|
11
|
+
export declare function scanDirectory(dirPath: string, extensions?: string[]): Promise<ScanResult[]>;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=scan-strings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-strings.d.ts","sourceRoot":"","sources":["../../src/utils/scan-strings.ts"],"names":[],"mappings":"AAeA,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,eAAe,EAAE,CAAC;CACtC;AA4BD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAkBpD;AAMD,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,EAAE,CA+BjE;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,UAAU,GAAE,MAAM,EAAuB,GACxC,OAAO,CAAC,UAAU,EAAE,CAAC,CAoDvB"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
const DEFAULT_EXTENSIONS = ['.tsx', '.jsx', '.ts', '.js', '.vue'];
|
|
4
|
+
const ALWAYS_IGNORE = new Set([
|
|
5
|
+
'node_modules',
|
|
6
|
+
'dist',
|
|
7
|
+
'.git',
|
|
8
|
+
'.next',
|
|
9
|
+
'build',
|
|
10
|
+
'coverage',
|
|
11
|
+
'.cache',
|
|
12
|
+
]);
|
|
13
|
+
// Matches string literals: '...', "...", or `...` (template literals)
|
|
14
|
+
const STRING_RE = /(['"`])((?:(?!\1|\\).|\\.)*?)\1/g;
|
|
15
|
+
// JSX text content: bare text between `>` or `}` and the next `{`, `<`, or end of line
|
|
16
|
+
const JSX_TEXT_RE = /(?:>|})([^{}<>]+?)(?=\{|<|$)/g;
|
|
17
|
+
// Context lines to skip: imports, requires, exports, CSS classNames, etc.
|
|
18
|
+
const SKIP_PATTERNS = [
|
|
19
|
+
/^\s*import\s/,
|
|
20
|
+
/^\s*export\s/,
|
|
21
|
+
/^\s*const\s+\w+\s*=\s*require\(/,
|
|
22
|
+
/^\s*\/\//,
|
|
23
|
+
/^\s*\*/, // JSDoc
|
|
24
|
+
/^\s*\/\*\*/,
|
|
25
|
+
/className:/,
|
|
26
|
+
/className=/,
|
|
27
|
+
/style=/,
|
|
28
|
+
/\.css$/,
|
|
29
|
+
/^\s*'use /,
|
|
30
|
+
/^\s*"use /,
|
|
31
|
+
/^\s*\/\/\s*eslint/,
|
|
32
|
+
/^\s*\/\/\s*@ts-/,
|
|
33
|
+
/^\s*\/\/\s*istanbul/,
|
|
34
|
+
];
|
|
35
|
+
// Only match strings that look like user-facing text
|
|
36
|
+
export function isTranslatable(text) {
|
|
37
|
+
const trimmed = text.trim();
|
|
38
|
+
if (trimmed.length < 2)
|
|
39
|
+
return false;
|
|
40
|
+
// Skip single characters, numbers, short fragments
|
|
41
|
+
if (trimmed.length <= 2 && /^[\d\s\W]+$/.test(trimmed))
|
|
42
|
+
return false;
|
|
43
|
+
// Skip template literals with interpolation
|
|
44
|
+
if (/\$\{/.test(trimmed))
|
|
45
|
+
return false;
|
|
46
|
+
// Skip URLs
|
|
47
|
+
if (/^https?:\/\//.test(trimmed))
|
|
48
|
+
return false;
|
|
49
|
+
// Skip file paths
|
|
50
|
+
if (/^\.?\//.test(trimmed))
|
|
51
|
+
return false;
|
|
52
|
+
// Skip common non-translatable patterns
|
|
53
|
+
if (/^[a-z_]+$/.test(trimmed) && trimmed.length < 20)
|
|
54
|
+
return false;
|
|
55
|
+
// Must contain at least one letter
|
|
56
|
+
if (!/[a-zA-Z]/.test(trimmed))
|
|
57
|
+
return false;
|
|
58
|
+
// Skip empty JSX expressions like {true}, {false}, {0}
|
|
59
|
+
if (/^(true|false|null|undefined|\d+)$/.test(trimmed))
|
|
60
|
+
return false;
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
function shouldSkipLine(line) {
|
|
64
|
+
return SKIP_PATTERNS.some((p) => p.test(line));
|
|
65
|
+
}
|
|
66
|
+
export function extractStrings(content) {
|
|
67
|
+
const lines = content.split('\n');
|
|
68
|
+
const results = [];
|
|
69
|
+
for (let i = 0; i < lines.length; i++) {
|
|
70
|
+
const line = lines[i];
|
|
71
|
+
if (shouldSkipLine(line))
|
|
72
|
+
continue;
|
|
73
|
+
let match;
|
|
74
|
+
STRING_RE.lastIndex = 0;
|
|
75
|
+
while ((match = STRING_RE.exec(line)) !== null) {
|
|
76
|
+
const text = match[2];
|
|
77
|
+
if (isTranslatable(text)) {
|
|
78
|
+
results.push({ text, line: i + 1 });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
JSX_TEXT_RE.lastIndex = 0;
|
|
82
|
+
while ((match = JSX_TEXT_RE.exec(line)) !== null) {
|
|
83
|
+
const text = match[1].trim();
|
|
84
|
+
if (text && isTranslatable(text)) {
|
|
85
|
+
if (!results.some(r => r.text === text && r.line === i + 1)) {
|
|
86
|
+
results.push({ text, line: i + 1 });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return results;
|
|
92
|
+
}
|
|
93
|
+
export async function scanDirectory(dirPath, extensions = DEFAULT_EXTENSIONS) {
|
|
94
|
+
const extSet = new Set(extensions);
|
|
95
|
+
const results = [];
|
|
96
|
+
async function walk(currentPath) {
|
|
97
|
+
let entries;
|
|
98
|
+
try {
|
|
99
|
+
entries = await readdir(currentPath, { withFileTypes: false });
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const dirEntries = await Promise.all(entries.map(async (name) => {
|
|
105
|
+
if (ALWAYS_IGNORE.has(name))
|
|
106
|
+
return null;
|
|
107
|
+
try {
|
|
108
|
+
const fullPath = path.join(currentPath, name);
|
|
109
|
+
const entryStat = await stat(fullPath);
|
|
110
|
+
return { name, fullPath, isDirectory: entryStat.isDirectory(), isFile: entryStat.isFile() };
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}));
|
|
116
|
+
for (const entry of dirEntries) {
|
|
117
|
+
if (!entry)
|
|
118
|
+
continue;
|
|
119
|
+
if (entry.isDirectory) {
|
|
120
|
+
await walk(entry.fullPath);
|
|
121
|
+
}
|
|
122
|
+
else if (entry.isFile && extSet.has(path.extname(entry.name))) {
|
|
123
|
+
try {
|
|
124
|
+
const content = await readFile(entry.fullPath, 'utf-8');
|
|
125
|
+
const strings = extractStrings(content);
|
|
126
|
+
if (strings.length > 0) {
|
|
127
|
+
results.push({
|
|
128
|
+
path: entry.fullPath,
|
|
129
|
+
hardcoded_strings: strings,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Skip unreadable files
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
await walk(dirPath);
|
|
140
|
+
// Sort by most strings found (descending), limit to top 50 files
|
|
141
|
+
results.sort((a, b) => b.hardcoded_strings.length - a.hardcoded_strings.length);
|
|
142
|
+
return results.slice(0, 50);
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=scan-strings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-strings.js","sourceRoot":"","sources":["../../src/utils/scan-strings.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@babelize/mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP (Model Context Protocol) server for Babelize AI-powered i18n — let AI coding agents translate your apps",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"babelize",
|
|
7
|
+
"mcp",
|
|
8
|
+
"i18n",
|
|
9
|
+
"translation",
|
|
10
|
+
"ai",
|
|
11
|
+
"llm",
|
|
12
|
+
"cursor",
|
|
13
|
+
"claude",
|
|
14
|
+
"codex"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://babelize.co",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/babelize/babelize-dashboard.git"
|
|
20
|
+
},
|
|
21
|
+
"type": "module",
|
|
22
|
+
"bin": {
|
|
23
|
+
"babelize-mcp": "dist/index.js"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"README.md",
|
|
28
|
+
"LICENSE"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc",
|
|
32
|
+
"dev": "tsc --watch",
|
|
33
|
+
"start": "node dist/index.js",
|
|
34
|
+
"typecheck": "tsc --noEmit --project tsconfig.typecheck.json",
|
|
35
|
+
"lint": "eslint src",
|
|
36
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --config jest.config.cjs",
|
|
37
|
+
"prepack": "rm -rf dist/__tests__",
|
|
38
|
+
"prepublishOnly": "npm test && npm run typecheck"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
42
|
+
"axios": "^1.15.2",
|
|
43
|
+
"zod": "^3.24.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@jest/globals": "^30.2.0",
|
|
47
|
+
"@types/jest": "^30.0.0",
|
|
48
|
+
"@types/node": "^22.0.0",
|
|
49
|
+
"jest": "^30.2.0",
|
|
50
|
+
"ts-jest": "^29.4.6",
|
|
51
|
+
"typescript": "^5.7.3"
|
|
52
|
+
}
|
|
53
|
+
}
|