@better-i18n/mcp 0.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/README.md +105 -0
- package/dist/base-tool.d.ts +43 -0
- package/dist/base-tool.d.ts.map +1 -0
- package/dist/base-tool.js +67 -0
- package/dist/base-tool.js.map +1 -0
- package/dist/client.d.ts +18 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +71 -0
- package/dist/client.js.map +1 -0
- package/dist/helpers.d.ts +30 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +32 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +121 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/bulkCreateKeys.d.ts +8 -0
- package/dist/tools/bulkCreateKeys.d.ts.map +1 -0
- package/dist/tools/bulkCreateKeys.js +74 -0
- package/dist/tools/bulkCreateKeys.js.map +1 -0
- package/dist/tools/bulkUpdateTranslations.d.ts +8 -0
- package/dist/tools/bulkUpdateTranslations.d.ts.map +1 -0
- package/dist/tools/bulkUpdateTranslations.js +68 -0
- package/dist/tools/bulkUpdateTranslations.js.map +1 -0
- package/dist/tools/createTranslationKey.d.ts +8 -0
- package/dist/tools/createTranslationKey.d.ts.map +1 -0
- package/dist/tools/createTranslationKey.js +55 -0
- package/dist/tools/createTranslationKey.js.map +1 -0
- package/dist/tools/getProjectInfo.d.ts +8 -0
- package/dist/tools/getProjectInfo.d.ts.map +1 -0
- package/dist/tools/getProjectInfo.js +28 -0
- package/dist/tools/getProjectInfo.js.map +1 -0
- package/dist/tools/listKeys.d.ts +8 -0
- package/dist/tools/listKeys.d.ts.map +1 -0
- package/dist/tools/listKeys.js +43 -0
- package/dist/tools/listKeys.js.map +1 -0
- package/dist/tools/updateTranslation.d.ts +8 -0
- package/dist/tools/updateTranslation.d.ts.map +1 -0
- package/dist/tools/updateTranslation.js +61 -0
- package/dist/tools/updateTranslation.js.map +1 -0
- package/dist/types/index.d.ts +37 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# @better-i18n/mcp
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server for [Better i18n](https://better-i18n.com). Enables AI assistants like Claude and GPT to manage translations directly from your IDE.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🤖 **AI-Powered Translation** - Let AI handle your i18n workflow
|
|
8
|
+
- ⚡ **Instant Startup** - No filesystem scanning, starts immediately
|
|
9
|
+
- 📝 **Create & Update Keys** - Add new keys with source text and translations
|
|
10
|
+
- 🔄 **Bulk Operations** - Create/update multiple keys at once
|
|
11
|
+
- 🔍 **Smart Filtering** - Find keys by name, namespace, or search
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# With npx (no install needed)
|
|
17
|
+
npx @better-i18n/mcp
|
|
18
|
+
|
|
19
|
+
# Or install globally
|
|
20
|
+
npm install -g @better-i18n/mcp
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Setup
|
|
24
|
+
|
|
25
|
+
### 1. Get Your API Key
|
|
26
|
+
|
|
27
|
+
1. Go to [dash.better-i18n.com](https://dash.better-i18n.com)
|
|
28
|
+
2. Navigate to Settings → API Keys
|
|
29
|
+
3. Create and copy your API key
|
|
30
|
+
|
|
31
|
+
### 2. Add i18n config to your project
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
// i18n.ts
|
|
35
|
+
import { createI18n } from "@better-i18n/next";
|
|
36
|
+
|
|
37
|
+
export const i18n = createI18n({
|
|
38
|
+
project: "your-org/your-project", // Format: "org-slug/project-slug"
|
|
39
|
+
defaultLocale: "en",
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The AI assistant will read this file to get the `project` value and include it in all tool calls.
|
|
44
|
+
|
|
45
|
+
### 3. Configure Cursor
|
|
46
|
+
|
|
47
|
+
Add to `~/.cursor/mcp.json`:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"mcpServers": {
|
|
52
|
+
"better-i18n": {
|
|
53
|
+
"command": "npx",
|
|
54
|
+
"args": ["@better-i18n/mcp"],
|
|
55
|
+
"env": {
|
|
56
|
+
"BETTER_I18N_API_KEY": "your-api-key-here"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Available Tools
|
|
64
|
+
|
|
65
|
+
All tools require a `project` parameter in `org/project` format (e.g., `aliosman-co/personal`).
|
|
66
|
+
|
|
67
|
+
| Tool | Description |
|
|
68
|
+
|------|-------------|
|
|
69
|
+
| `getProjectInfo` | Get project overview: namespaces, languages, key count |
|
|
70
|
+
| `listKeys` | List all translation keys with filtering |
|
|
71
|
+
| `createTranslationKey` | Create a single key with source text |
|
|
72
|
+
| `bulkCreateKeys` | Create multiple keys at once (more efficient) |
|
|
73
|
+
| `updateTranslation` | Update a single translation |
|
|
74
|
+
| `bulkUpdateTranslations` | Update multiple translations at once (more efficient) |
|
|
75
|
+
|
|
76
|
+
## Example Prompts
|
|
77
|
+
|
|
78
|
+
Ask your AI assistant:
|
|
79
|
+
|
|
80
|
+
> "List all my translation keys"
|
|
81
|
+
|
|
82
|
+
> "Add Turkish translations for all keys missing Turkish"
|
|
83
|
+
|
|
84
|
+
> "Create a new key nav.home with text 'Home' and translate to German and Turkish"
|
|
85
|
+
|
|
86
|
+
> "Show me translation coverage stats"
|
|
87
|
+
|
|
88
|
+
## How It Works
|
|
89
|
+
|
|
90
|
+
1. AI reads `project` value from your `i18n.ts` config
|
|
91
|
+
2. AI uses tools with `project` parameter for each request
|
|
92
|
+
3. Changes sync to Better i18n dashboard via API
|
|
93
|
+
4. CDN serves updated translations to your app
|
|
94
|
+
|
|
95
|
+
## Environment Variables
|
|
96
|
+
|
|
97
|
+
| Variable | Required | Description |
|
|
98
|
+
|----------|----------|-------------|
|
|
99
|
+
| `BETTER_I18N_API_KEY` | Yes | Your API key |
|
|
100
|
+
| `BETTER_I18N_API_URL` | No | API URL (default: dash.better-i18n.com) |
|
|
101
|
+
| `BETTER_I18N_DEBUG` | No | Enable verbose logging |
|
|
102
|
+
|
|
103
|
+
## License
|
|
104
|
+
|
|
105
|
+
MIT © [Better i18n](https://better-i18n.com)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Tool Utilities
|
|
3
|
+
*
|
|
4
|
+
* Common patterns and helpers for MCP tools.
|
|
5
|
+
* All tools work with project-scoped operations.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { type ParsedProject } from "./helpers.js";
|
|
9
|
+
import type { ToolResult } from "./types/index.js";
|
|
10
|
+
/**
|
|
11
|
+
* Common project schema - all tools require this
|
|
12
|
+
*/
|
|
13
|
+
export declare const projectSchema: z.ZodObject<{
|
|
14
|
+
project: z.ZodString;
|
|
15
|
+
}, "strip", z.ZodTypeAny, {
|
|
16
|
+
project: string;
|
|
17
|
+
}, {
|
|
18
|
+
project: string;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Project field definition for tool inputSchema
|
|
22
|
+
*/
|
|
23
|
+
export declare const projectInputProperty: {
|
|
24
|
+
project: {
|
|
25
|
+
type: "string";
|
|
26
|
+
description: string;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Creates a successful tool result
|
|
31
|
+
*/
|
|
32
|
+
export declare function success(data: Record<string, unknown>): ToolResult;
|
|
33
|
+
/**
|
|
34
|
+
* Creates an error tool result
|
|
35
|
+
*/
|
|
36
|
+
export declare function error(message: string): ToolResult;
|
|
37
|
+
/**
|
|
38
|
+
* Wraps tool execution with common error handling
|
|
39
|
+
*/
|
|
40
|
+
export declare function executeTool<T extends {
|
|
41
|
+
project: string;
|
|
42
|
+
}>(args: unknown, schema: z.ZodType<T>, handler: (input: T, parsed: ParsedProject) => Promise<ToolResult>): Promise<ToolResult>;
|
|
43
|
+
//# sourceMappingURL=base-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-tool.d.ts","sourceRoot":"","sources":["../src/base-tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;;EAExB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;CAMhC,CAAC;AAEF;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CASjE;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAUjD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,CAAC,SAAS;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,EAC7D,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,UAAU,CAAC,GAChE,OAAO,CAAC,UAAU,CAAC,CAWrB"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Tool Utilities
|
|
3
|
+
*
|
|
4
|
+
* Common patterns and helpers for MCP tools.
|
|
5
|
+
* All tools work with project-scoped operations.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { parseProject } from "./helpers.js";
|
|
9
|
+
/**
|
|
10
|
+
* Common project schema - all tools require this
|
|
11
|
+
*/
|
|
12
|
+
export const projectSchema = z.object({
|
|
13
|
+
project: z.string().min(1),
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* Project field definition for tool inputSchema
|
|
17
|
+
*/
|
|
18
|
+
export const projectInputProperty = {
|
|
19
|
+
project: {
|
|
20
|
+
type: "string",
|
|
21
|
+
description: "Project identifier in 'org/project' format (e.g., 'aliosman-co/personal'). Get this from the project's i18n.ts config file.",
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Creates a successful tool result
|
|
26
|
+
*/
|
|
27
|
+
export function success(data) {
|
|
28
|
+
return {
|
|
29
|
+
content: [
|
|
30
|
+
{
|
|
31
|
+
type: "text",
|
|
32
|
+
text: JSON.stringify(data, null, 2),
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Creates an error tool result
|
|
39
|
+
*/
|
|
40
|
+
export function error(message) {
|
|
41
|
+
return {
|
|
42
|
+
content: [
|
|
43
|
+
{
|
|
44
|
+
type: "text",
|
|
45
|
+
text: message,
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
isError: true,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Wraps tool execution with common error handling
|
|
53
|
+
*/
|
|
54
|
+
export async function executeTool(args, schema, handler) {
|
|
55
|
+
try {
|
|
56
|
+
const input = schema.parse(args);
|
|
57
|
+
const parsed = parseProject(input.project);
|
|
58
|
+
return await handler(input, parsed);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
if (err instanceof z.ZodError) {
|
|
62
|
+
return error(`Validation error: ${err.errors.map(e => e.message).join(", ")}`);
|
|
63
|
+
}
|
|
64
|
+
return error(err instanceof Error ? err.message : String(err));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=base-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-tool.js","sourceRoot":"","sources":["../src/base-tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAsB,MAAM,cAAc,CAAC;AAGhE;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC3B,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,OAAO,EAAE;QACP,IAAI,EAAE,QAAiB;QACvB,WAAW,EACT,6HAA6H;KAChI;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,IAA6B;IACnD,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;aACpC;SACF;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,OAAe;IACnC,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,OAAO;aACd;SACF;QACD,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAa,EACb,MAAoB,EACpB,OAAiE;IAEjE,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3C,OAAO,MAAM,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC9B,OAAO,KAAK,CAAC,qBAAqB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjF,CAAC;QACD,OAAO,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACjE,CAAC;AACH,CAAC"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tRPC client for Better i18n API with API key authentication
|
|
3
|
+
*/
|
|
4
|
+
export interface ClientConfig {
|
|
5
|
+
apiUrl: string;
|
|
6
|
+
apiKey: string;
|
|
7
|
+
debug?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Create a tRPC client authenticated with API key
|
|
11
|
+
*
|
|
12
|
+
* @param config - API URL, API key, and optional organization ID
|
|
13
|
+
* @returns Configured tRPC client
|
|
14
|
+
*/
|
|
15
|
+
export declare function createBetterI18nClient(config: ClientConfig & {
|
|
16
|
+
organizationId?: string;
|
|
17
|
+
}): import("@trpc/client").TRPCClient<any>;
|
|
18
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,GAAG;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,0CAgExF"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tRPC client for Better i18n API with API key authentication
|
|
3
|
+
*/
|
|
4
|
+
import { createTRPCClient, httpBatchLink } from "@trpc/client";
|
|
5
|
+
/**
|
|
6
|
+
* Create a tRPC client authenticated with API key
|
|
7
|
+
*
|
|
8
|
+
* @param config - API URL, API key, and optional organization ID
|
|
9
|
+
* @returns Configured tRPC client
|
|
10
|
+
*/
|
|
11
|
+
export function createBetterI18nClient(config) {
|
|
12
|
+
// Ensure URL ends with /api/trpc for tRPC endpoint
|
|
13
|
+
const url = config.apiUrl.endsWith("/api/trpc")
|
|
14
|
+
? config.apiUrl
|
|
15
|
+
: `${config.apiUrl.replace(/\/$/, "")}/api/trpc`;
|
|
16
|
+
if (config.debug) {
|
|
17
|
+
console.error(`[better-i18n] tRPC endpoint: ${url}`);
|
|
18
|
+
}
|
|
19
|
+
// Track logged requests to avoid duplicate logs (tRPC batching can call headers multiple times)
|
|
20
|
+
let lastLoggedUrl = "";
|
|
21
|
+
return createTRPCClient({
|
|
22
|
+
links: [
|
|
23
|
+
httpBatchLink({
|
|
24
|
+
url,
|
|
25
|
+
headers: () => {
|
|
26
|
+
const headers = {
|
|
27
|
+
"x-api-key": config.apiKey,
|
|
28
|
+
};
|
|
29
|
+
if (config.organizationId) {
|
|
30
|
+
headers["x-organization-id"] = config.organizationId;
|
|
31
|
+
}
|
|
32
|
+
return headers;
|
|
33
|
+
},
|
|
34
|
+
fetch: async (input, init) => {
|
|
35
|
+
const inputUrl = String(input);
|
|
36
|
+
// Only log if this is a different request (avoid duplicate logs from tRPC batching)
|
|
37
|
+
if (config.debug && inputUrl !== lastLoggedUrl) {
|
|
38
|
+
lastLoggedUrl = inputUrl;
|
|
39
|
+
// Parse the URL to show a cleaner log
|
|
40
|
+
try {
|
|
41
|
+
const parsedUrl = new URL(inputUrl);
|
|
42
|
+
const procedure = parsedUrl.pathname.split("/").pop();
|
|
43
|
+
console.error(`[better-i18n] → ${procedure}`);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
console.error(`[better-i18n] → ${inputUrl}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const response = await fetch(input, init);
|
|
50
|
+
if (config.debug && inputUrl === lastLoggedUrl) {
|
|
51
|
+
if (response.ok) {
|
|
52
|
+
console.error(`[better-i18n] ← ${response.status} OK`);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
const clonedResponse = response.clone();
|
|
56
|
+
try {
|
|
57
|
+
const text = await clonedResponse.text();
|
|
58
|
+
console.error(`[better-i18n] ← ${response.status} ERROR: ${text.substring(0, 200)}`);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
console.error(`[better-i18n] ← ${response.status} ERROR`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return response;
|
|
66
|
+
},
|
|
67
|
+
}),
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAY/D;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAkD;IACvF,mDAAmD;IACnD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC7C,CAAC,CAAC,MAAM,CAAC,MAAM;QACf,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC;IAEnD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,gCAAgC,GAAG,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,gGAAgG;IAChG,IAAI,aAAa,GAAG,EAAE,CAAC;IAEvB,OAAO,gBAAgB,CAAY;QACjC,KAAK,EAAE;YACL,aAAa,CAAC;gBACZ,GAAG;gBACH,OAAO,EAAE,GAAG,EAAE;oBACZ,MAAM,OAAO,GAA2B;wBACtC,WAAW,EAAE,MAAM,CAAC,MAAM;qBAC3B,CAAC;oBACF,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;wBAC1B,OAAO,CAAC,mBAAmB,CAAC,GAAG,MAAM,CAAC,cAAc,CAAC;oBACvD,CAAC;oBACD,OAAO,OAAO,CAAC;gBACjB,CAAC;gBACD,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;oBAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;oBAE/B,oFAAoF;oBACpF,IAAI,MAAM,CAAC,KAAK,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;wBAC/C,aAAa,GAAG,QAAQ,CAAC;wBAEzB,sCAAsC;wBACtC,IAAI,CAAC;4BACH,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;4BACpC,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;4BACtD,OAAO,CAAC,KAAK,CAAC,mBAAmB,SAAS,EAAE,CAAC,CAAC;wBAChD,CAAC;wBAAC,MAAM,CAAC;4BACP,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;wBAC/C,CAAC;oBACH,CAAC;oBAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;oBAE1C,IAAI,MAAM,CAAC,KAAK,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;wBAC/C,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;4BAChB,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC;wBACzD,CAAC;6BAAM,CAAC;4BACN,MAAM,cAAc,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;4BACxC,IAAI,CAAC;gCACH,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,CAAC;gCACzC,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,CAAC,MAAM,WAAW,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;4BACvF,CAAC;4BAAC,MAAM,CAAC;gCACP,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,CAAC,MAAM,QAAQ,CAAC,CAAC;4BAC5D,CAAC;wBACH,CAAC;oBACH,CAAC;oBAED,OAAO,QAAQ,CAAC;gBAClB,CAAC;aACF,CAAC;SACH;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Helpers
|
|
3
|
+
*
|
|
4
|
+
* Shared utility functions for MCP tools.
|
|
5
|
+
* Uses the same project format as @better-i18n/next package.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Parsed project identifier - same structure as @better-i18n/next
|
|
9
|
+
*/
|
|
10
|
+
export interface ParsedProject {
|
|
11
|
+
workspaceId: string;
|
|
12
|
+
projectSlug: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Parse project string "org/slug" into workspaceId and projectSlug.
|
|
16
|
+
* Same format used in @better-i18n/next package's i18n.ts config.
|
|
17
|
+
*
|
|
18
|
+
* @param project - Project identifier (e.g., "aliosman-co/personal")
|
|
19
|
+
* @returns Parsed project with workspaceId and projectSlug
|
|
20
|
+
* @throws Error if format is invalid
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const { workspaceId, projectSlug } = parseProject("aliosman-co/personal");
|
|
25
|
+
* // workspaceId: "aliosman-co"
|
|
26
|
+
* // projectSlug: "personal"
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseProject(project: string): ParsedProject;
|
|
30
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAW3D"}
|
package/dist/helpers.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Helpers
|
|
3
|
+
*
|
|
4
|
+
* Shared utility functions for MCP tools.
|
|
5
|
+
* Uses the same project format as @better-i18n/next package.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Parse project string "org/slug" into workspaceId and projectSlug.
|
|
9
|
+
* Same format used in @better-i18n/next package's i18n.ts config.
|
|
10
|
+
*
|
|
11
|
+
* @param project - Project identifier (e.g., "aliosman-co/personal")
|
|
12
|
+
* @returns Parsed project with workspaceId and projectSlug
|
|
13
|
+
* @throws Error if format is invalid
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const { workspaceId, projectSlug } = parseProject("aliosman-co/personal");
|
|
18
|
+
* // workspaceId: "aliosman-co"
|
|
19
|
+
* // projectSlug: "personal"
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function parseProject(project) {
|
|
23
|
+
const parts = project.split("/");
|
|
24
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
25
|
+
throw new Error(`Invalid project format "${project}". Expected "org/project" (e.g., "aliosman-co/personal")`);
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
workspaceId: parts[0],
|
|
29
|
+
projectSlug: parts[1],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CACb,2BAA2B,OAAO,0DAA0D,CAC7F,CAAC;IACJ,CAAC;IACD,OAAO;QACL,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;QACrB,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;KACtB,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Better i18n MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Model Context Protocol server for Better i18n translation management.
|
|
6
|
+
* Enables AI assistants (Claude, ChatGPT, etc.) to manage translations
|
|
7
|
+
* directly from IDEs like Cursor.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;GAMG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Better i18n MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Model Context Protocol server for Better i18n translation management.
|
|
6
|
+
* Enables AI assistants (Claude, ChatGPT, etc.) to manage translations
|
|
7
|
+
* directly from IDEs like Cursor.
|
|
8
|
+
*/
|
|
9
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
10
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
11
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
12
|
+
import { createBetterI18nClient } from "./client.js";
|
|
13
|
+
import { bulkCreateKeys } from "./tools/bulkCreateKeys.js";
|
|
14
|
+
import { bulkUpdateTranslations } from "./tools/bulkUpdateTranslations.js";
|
|
15
|
+
import { createTranslationKey } from "./tools/createTranslationKey.js";
|
|
16
|
+
import { getProjectInfo } from "./tools/getProjectInfo.js";
|
|
17
|
+
import { listKeys } from "./tools/listKeys.js";
|
|
18
|
+
import { updateTranslation } from "./tools/updateTranslation.js";
|
|
19
|
+
class BetterI18nServer {
|
|
20
|
+
server;
|
|
21
|
+
apiClient;
|
|
22
|
+
constructor() {
|
|
23
|
+
this.server = new Server({
|
|
24
|
+
name: "better-i18n",
|
|
25
|
+
version: "0.0.1",
|
|
26
|
+
}, {
|
|
27
|
+
capabilities: {
|
|
28
|
+
tools: {},
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
this.apiClient = null;
|
|
32
|
+
}
|
|
33
|
+
async init() {
|
|
34
|
+
// Auto-detect if running from source (local dev) vs npm package (production)
|
|
35
|
+
const scriptPath = process.argv[1] || "";
|
|
36
|
+
const isLocalDev = scriptPath.includes("packages/mcp/src") ||
|
|
37
|
+
scriptPath.includes("better-i18n/packages/mcp");
|
|
38
|
+
// Read configuration from environment
|
|
39
|
+
const apiUrl = process.env.BETTER_I18N_API_URL ||
|
|
40
|
+
(isLocalDev ? "http://localhost:8787" : "https://dash.better-i18n.com");
|
|
41
|
+
const apiKey = process.env.BETTER_I18N_API_KEY;
|
|
42
|
+
const debug = process.env.BETTER_I18N_DEBUG === "true" || isLocalDev;
|
|
43
|
+
console.error(`[better-i18n] Mode: ${isLocalDev ? "LOCAL DEV" : "PRODUCTION"}`);
|
|
44
|
+
console.error(`[better-i18n] API URL: ${apiUrl}`);
|
|
45
|
+
if (!apiKey) {
|
|
46
|
+
console.error("[better-i18n] ERROR: BETTER_I18N_API_KEY environment variable is required");
|
|
47
|
+
console.error("[better-i18n] Get your API key from: https://dash.better-i18n.com/settings/api-keys");
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
// Create Better i18n API client
|
|
51
|
+
this.apiClient = createBetterI18nClient({ apiUrl, apiKey, debug });
|
|
52
|
+
this.setupHandlers();
|
|
53
|
+
console.error("[better-i18n] MCP Server ready");
|
|
54
|
+
}
|
|
55
|
+
setupHandlers() {
|
|
56
|
+
// List available tools
|
|
57
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
58
|
+
tools: [
|
|
59
|
+
getProjectInfo.definition,
|
|
60
|
+
listKeys.definition,
|
|
61
|
+
createTranslationKey.definition,
|
|
62
|
+
bulkCreateKeys.definition,
|
|
63
|
+
updateTranslation.definition,
|
|
64
|
+
bulkUpdateTranslations.definition,
|
|
65
|
+
],
|
|
66
|
+
}));
|
|
67
|
+
// Execute tools
|
|
68
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
69
|
+
const { name, arguments: args } = request.params;
|
|
70
|
+
try {
|
|
71
|
+
let result;
|
|
72
|
+
switch (name) {
|
|
73
|
+
case "getProjectInfo":
|
|
74
|
+
result = await getProjectInfo.execute(this.apiClient, args);
|
|
75
|
+
break;
|
|
76
|
+
case "createTranslationKey":
|
|
77
|
+
result = await createTranslationKey.execute(this.apiClient, args);
|
|
78
|
+
break;
|
|
79
|
+
case "updateTranslation":
|
|
80
|
+
result = await updateTranslation.execute(this.apiClient, args);
|
|
81
|
+
break;
|
|
82
|
+
case "listKeys":
|
|
83
|
+
result = await listKeys.execute(this.apiClient, args);
|
|
84
|
+
break;
|
|
85
|
+
case "bulkCreateKeys":
|
|
86
|
+
result = await bulkCreateKeys.execute(this.apiClient, args);
|
|
87
|
+
break;
|
|
88
|
+
case "bulkUpdateTranslations":
|
|
89
|
+
result = await bulkUpdateTranslations.execute(this.apiClient, args);
|
|
90
|
+
break;
|
|
91
|
+
default:
|
|
92
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
93
|
+
}
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
return {
|
|
98
|
+
content: [
|
|
99
|
+
{
|
|
100
|
+
type: "text",
|
|
101
|
+
text: `Error executing ${name}: ${error instanceof Error ? error.message : String(error)}`,
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
isError: true,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async run() {
|
|
110
|
+
const transport = new StdioServerTransport();
|
|
111
|
+
await this.server.connect(transport);
|
|
112
|
+
console.error("[better-i18n] MCP Server running on stdio");
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Start the server
|
|
116
|
+
const server = new BetterI18nServer();
|
|
117
|
+
server.init().then(() => server.run()).catch((error) => {
|
|
118
|
+
console.error("[better-i18n] Fatal error:", error);
|
|
119
|
+
process.exit(1);
|
|
120
|
+
});
|
|
121
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bulkCreateKeys.d.ts","sourceRoot":"","sources":["../../src/tools/bulkCreateKeys.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAa9C,eAAO,MAAM,cAAc,EAAE,IA8D5B,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bulkCreateKeys MCP Tool
|
|
3
|
+
*
|
|
4
|
+
* Creates multiple translation keys with all translations in a single request.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { executeTool, projectInputProperty, projectSchema, success, } from "../base-tool.js";
|
|
8
|
+
const inputSchema = projectSchema.extend({
|
|
9
|
+
keys: z.array(z.object({
|
|
10
|
+
key: z.string(),
|
|
11
|
+
namespace: z.string().optional(),
|
|
12
|
+
sourceText: z.string(),
|
|
13
|
+
translations: z.record(z.string(), z.string()).optional(),
|
|
14
|
+
})),
|
|
15
|
+
});
|
|
16
|
+
export const bulkCreateKeys = {
|
|
17
|
+
definition: {
|
|
18
|
+
name: "bulkCreateKeys",
|
|
19
|
+
description: "Create multiple translation keys in a SINGLE efficient request. ALWAYS use this instead of calling createTranslationKey multiple times when adding 2 or more keys.",
|
|
20
|
+
inputSchema: {
|
|
21
|
+
type: "object",
|
|
22
|
+
properties: {
|
|
23
|
+
...projectInputProperty,
|
|
24
|
+
keys: {
|
|
25
|
+
type: "array",
|
|
26
|
+
description: "Array of translation keys to create",
|
|
27
|
+
items: {
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: {
|
|
30
|
+
key: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description: "Translation key WITHOUT namespace prefix when namespace is provided.",
|
|
33
|
+
},
|
|
34
|
+
namespace: {
|
|
35
|
+
type: "string",
|
|
36
|
+
description: "Namespace for the key. Defaults to 'default'.",
|
|
37
|
+
},
|
|
38
|
+
sourceText: {
|
|
39
|
+
type: "string",
|
|
40
|
+
description: "English source text",
|
|
41
|
+
},
|
|
42
|
+
translations: {
|
|
43
|
+
type: "object",
|
|
44
|
+
description: "Translations for other languages. Keys are language codes, values are translated text.",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
required: ["key", "sourceText"],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
required: ["project", "keys"],
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
execute: (client, args) => executeTool(args, inputSchema, async (input, { workspaceId, projectSlug }) => {
|
|
55
|
+
const formattedKeys = input.keys.map((k) => ({
|
|
56
|
+
key: k.key,
|
|
57
|
+
namespace: k.namespace || "default",
|
|
58
|
+
sourceText: k.sourceText,
|
|
59
|
+
translations: k.translations,
|
|
60
|
+
}));
|
|
61
|
+
const result = await client.mcp.bulkCreateKeys.mutate({
|
|
62
|
+
orgSlug: workspaceId,
|
|
63
|
+
projectSlug,
|
|
64
|
+
keys: formattedKeys,
|
|
65
|
+
});
|
|
66
|
+
return success({
|
|
67
|
+
success: true,
|
|
68
|
+
project: input.project,
|
|
69
|
+
keysCreated: result.keysCreated,
|
|
70
|
+
keys: result.keys,
|
|
71
|
+
});
|
|
72
|
+
}),
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=bulkCreateKeys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bulkCreateKeys.js","sourceRoot":"","sources":["../../src/tools/bulkCreateKeys.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,OAAO,GACR,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC;IACvC,IAAI,EAAE,CAAC,CAAC,KAAK,CACX,CAAC,CAAC,MAAM,CAAC;QACP,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;QACf,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAChC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;QACtB,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;KAC1D,CAAC,CACH;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAS;IAClC,UAAU,EAAE;QACV,IAAI,EAAE,gBAAgB;QACtB,WAAW,EACT,oKAAoK;QACtK,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,GAAG,oBAAoB;gBACvB,IAAI,EAAE;oBACJ,IAAI,EAAE,OAAO;oBACb,WAAW,EAAE,qCAAqC;oBAClD,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE;4BACV,GAAG,EAAE;gCACH,IAAI,EAAE,QAAQ;gCACd,WAAW,EAAE,sEAAsE;6BACpF;4BACD,SAAS,EAAE;gCACT,IAAI,EAAE,QAAQ;gCACd,WAAW,EAAE,+CAA+C;6BAC7D;4BACD,UAAU,EAAE;gCACV,IAAI,EAAE,QAAQ;gCACd,WAAW,EAAE,qBAAqB;6BACnC;4BACD,YAAY,EAAE;gCACZ,IAAI,EAAE,QAAQ;gCACd,WAAW,EAAE,wFAAwF;6BACtG;yBACF;wBACD,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC;qBAChC;iBACF;aACF;YACD,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC;SAC9B;KACF;IAED,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CACxB,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE;QAC3E,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3C,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,SAAS,EAAE,CAAC,CAAC,SAAS,IAAI,SAAS;YACnC,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,YAAY,EAAE,CAAC,CAAC,YAAY;SAC7B,CAAC,CAAC,CAAC;QAEJ,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC;YACpD,OAAO,EAAE,WAAW;YACpB,WAAW;YACX,IAAI,EAAE,aAAa;SACpB,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;YACb,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAC,CAAC;IACL,CAAC,CAAC;CACL,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bulkUpdateTranslations MCP Tool
|
|
3
|
+
*
|
|
4
|
+
* Updates translations for multiple keys in a single request.
|
|
5
|
+
*/
|
|
6
|
+
import type { Tool } from "../types/index.js";
|
|
7
|
+
export declare const bulkUpdateTranslations: Tool;
|
|
8
|
+
//# sourceMappingURL=bulkUpdateTranslations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bulkUpdateTranslations.d.ts","sourceRoot":"","sources":["../../src/tools/bulkUpdateTranslations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAY9C,eAAO,MAAM,sBAAsB,EAAE,IAyDpC,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bulkUpdateTranslations MCP Tool
|
|
3
|
+
*
|
|
4
|
+
* Updates translations for multiple keys in a single request.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { executeTool, projectInputProperty, projectSchema, success, } from "../base-tool.js";
|
|
8
|
+
const inputSchema = projectSchema.extend({
|
|
9
|
+
updates: z.array(z.object({
|
|
10
|
+
key: z.string(),
|
|
11
|
+
namespace: z.string().optional(),
|
|
12
|
+
translations: z.record(z.string(), z.string()),
|
|
13
|
+
})),
|
|
14
|
+
});
|
|
15
|
+
export const bulkUpdateTranslations = {
|
|
16
|
+
definition: {
|
|
17
|
+
name: "bulkUpdateTranslations",
|
|
18
|
+
description: "Update translations for multiple keys in a SINGLE efficient request. ALWAYS use this instead of calling updateTranslation multiple times when updating 2 or more translations.",
|
|
19
|
+
inputSchema: {
|
|
20
|
+
type: "object",
|
|
21
|
+
properties: {
|
|
22
|
+
...projectInputProperty,
|
|
23
|
+
updates: {
|
|
24
|
+
type: "array",
|
|
25
|
+
description: "Array of translation updates",
|
|
26
|
+
items: {
|
|
27
|
+
type: "object",
|
|
28
|
+
properties: {
|
|
29
|
+
key: {
|
|
30
|
+
type: "string",
|
|
31
|
+
description: "Translation key WITHOUT namespace prefix when namespace is provided.",
|
|
32
|
+
},
|
|
33
|
+
namespace: {
|
|
34
|
+
type: "string",
|
|
35
|
+
description: "Namespace for the key. Defaults to 'default'.",
|
|
36
|
+
},
|
|
37
|
+
translations: {
|
|
38
|
+
type: "object",
|
|
39
|
+
description: "Translations for target languages. Keys are language codes, values are translated text.",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
required: ["key", "translations"],
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
required: ["project", "updates"],
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
execute: (client, args) => executeTool(args, inputSchema, async (input, { workspaceId, projectSlug }) => {
|
|
50
|
+
const formattedUpdates = input.updates.map((u) => ({
|
|
51
|
+
key: u.key,
|
|
52
|
+
namespace: u.namespace || "default",
|
|
53
|
+
translations: u.translations,
|
|
54
|
+
}));
|
|
55
|
+
const result = await client.mcp.bulkUpdateTranslations.mutate({
|
|
56
|
+
orgSlug: workspaceId,
|
|
57
|
+
projectSlug,
|
|
58
|
+
updates: formattedUpdates,
|
|
59
|
+
});
|
|
60
|
+
return success({
|
|
61
|
+
success: true,
|
|
62
|
+
project: input.project,
|
|
63
|
+
keysUpdated: result.keysUpdated,
|
|
64
|
+
updates: result.updates,
|
|
65
|
+
});
|
|
66
|
+
}),
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=bulkUpdateTranslations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bulkUpdateTranslations.js","sourceRoot":"","sources":["../../src/tools/bulkUpdateTranslations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,OAAO,GACR,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC;IACvC,OAAO,EAAE,CAAC,CAAC,KAAK,CACd,CAAC,CAAC,MAAM,CAAC;QACP,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;QACf,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAChC,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;KAC/C,CAAC,CACH;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAAS;IAC1C,UAAU,EAAE;QACV,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EACT,gLAAgL;QAClL,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,GAAG,oBAAoB;gBACvB,OAAO,EAAE;oBACP,IAAI,EAAE,OAAO;oBACb,WAAW,EAAE,8BAA8B;oBAC3C,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE;4BACV,GAAG,EAAE;gCACH,IAAI,EAAE,QAAQ;gCACd,WAAW,EAAE,sEAAsE;6BACpF;4BACD,SAAS,EAAE;gCACT,IAAI,EAAE,QAAQ;gCACd,WAAW,EAAE,+CAA+C;6BAC7D;4BACD,YAAY,EAAE;gCACZ,IAAI,EAAE,QAAQ;gCACd,WAAW,EAAE,yFAAyF;6BACvG;yBACF;wBACD,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC;qBAClC;iBACF;aACF;YACD,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;SACjC;KACF;IAED,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CACxB,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE;QAC3E,MAAM,gBAAgB,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjD,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,SAAS,EAAE,CAAC,CAAC,SAAS,IAAI,SAAS;YACnC,YAAY,EAAE,CAAC,CAAC,YAAY;SAC7B,CAAC,CAAC,CAAC;QAEJ,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,MAAM,CAAC;YAC5D,OAAO,EAAE,WAAW;YACpB,WAAW;YACX,OAAO,EAAE,gBAAgB;SAC1B,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;YACb,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,CAAC,CAAC;IACL,CAAC,CAAC;CACL,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createTranslationKey MCP Tool
|
|
3
|
+
*
|
|
4
|
+
* Creates a new translation key with source text in the default language.
|
|
5
|
+
*/
|
|
6
|
+
import type { Tool } from "../types/index.js";
|
|
7
|
+
export declare const createTranslationKey: Tool;
|
|
8
|
+
//# sourceMappingURL=createTranslationKey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createTranslationKey.d.ts","sourceRoot":"","sources":["../../src/tools/createTranslationKey.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAQ9C,eAAO,MAAM,oBAAoB,EAAE,IA6ClC,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createTranslationKey MCP Tool
|
|
3
|
+
*
|
|
4
|
+
* Creates a new translation key with source text in the default language.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { executeTool, projectInputProperty, projectSchema, success, } from "../base-tool.js";
|
|
8
|
+
const inputSchema = projectSchema.extend({
|
|
9
|
+
key: z.string().min(1),
|
|
10
|
+
sourceValue: z.string().min(1),
|
|
11
|
+
namespace: z.string().optional(),
|
|
12
|
+
});
|
|
13
|
+
export const createTranslationKey = {
|
|
14
|
+
definition: {
|
|
15
|
+
name: "createTranslationKey",
|
|
16
|
+
description: "Create a SINGLE translation key with source text. IMPORTANT: If you need to create 2 or more keys, use bulkCreateKeys instead.",
|
|
17
|
+
inputSchema: {
|
|
18
|
+
type: "object",
|
|
19
|
+
properties: {
|
|
20
|
+
...projectInputProperty,
|
|
21
|
+
key: {
|
|
22
|
+
type: "string",
|
|
23
|
+
description: "Translation key WITHOUT namespace prefix when namespace is provided.",
|
|
24
|
+
},
|
|
25
|
+
sourceValue: {
|
|
26
|
+
type: "string",
|
|
27
|
+
description: "Source text in default language (usually English)",
|
|
28
|
+
},
|
|
29
|
+
namespace: {
|
|
30
|
+
type: "string",
|
|
31
|
+
description: "Namespace for the key. Defaults to 'default'.",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
required: ["project", "key", "sourceValue"],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
execute: (client, args) => executeTool(args, inputSchema, async (input, { workspaceId, projectSlug }) => {
|
|
38
|
+
const result = await client.mcp.createKey.mutate({
|
|
39
|
+
orgSlug: workspaceId,
|
|
40
|
+
projectSlug,
|
|
41
|
+
key: input.key,
|
|
42
|
+
namespace: input.namespace || "default",
|
|
43
|
+
sourceText: input.sourceValue,
|
|
44
|
+
});
|
|
45
|
+
return success({
|
|
46
|
+
success: true,
|
|
47
|
+
keyId: result.keyId,
|
|
48
|
+
key: input.key,
|
|
49
|
+
namespace: input.namespace || "default",
|
|
50
|
+
sourceText: input.sourceValue,
|
|
51
|
+
project: input.project,
|
|
52
|
+
});
|
|
53
|
+
}),
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=createTranslationKey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createTranslationKey.js","sourceRoot":"","sources":["../../src/tools/createTranslationKey.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,OAAO,GACR,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC;IACvC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACtB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAS;IACxC,UAAU,EAAE;QACV,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EACT,gIAAgI;QAClI,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,GAAG,oBAAoB;gBACvB,GAAG,EAAE;oBACH,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,sEAAsE;iBACpF;gBACD,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,mDAAmD;iBACjE;gBACD,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,+CAA+C;iBAC7D;aACF;YACD,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,aAAa,CAAC;SAC5C;KACF;IAED,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CACxB,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE;QAC3E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC;YAC/C,OAAO,EAAE,WAAW;YACpB,WAAW;YACX,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,SAAS;YACvC,UAAU,EAAE,KAAK,CAAC,WAAW;SAC9B,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;YACb,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,SAAS;YACvC,UAAU,EAAE,KAAK,CAAC,WAAW;YAC7B,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC;IACL,CAAC,CAAC;CACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getProjectInfo.d.ts","sourceRoot":"","sources":["../../src/tools/getProjectInfo.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAI9C,eAAO,MAAM,cAAc,EAAE,IAsB5B,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* getProjectInfo MCP Tool
|
|
3
|
+
*
|
|
4
|
+
* Gets project information including available namespaces, languages, and stats.
|
|
5
|
+
*/
|
|
6
|
+
import { executeTool, projectInputProperty, projectSchema, success, } from "../base-tool.js";
|
|
7
|
+
const inputSchema = projectSchema;
|
|
8
|
+
export const getProjectInfo = {
|
|
9
|
+
definition: {
|
|
10
|
+
name: "getProjectInfo",
|
|
11
|
+
description: "Get project information including available namespaces, languages, and key count. Use this to understand the project structure before adding or updating translations.",
|
|
12
|
+
inputSchema: {
|
|
13
|
+
type: "object",
|
|
14
|
+
properties: {
|
|
15
|
+
...projectInputProperty,
|
|
16
|
+
},
|
|
17
|
+
required: ["project"],
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
execute: (client, args) => executeTool(args, inputSchema, async (input, { workspaceId, projectSlug }) => {
|
|
21
|
+
const result = await client.mcp.getProjectInfo.query({
|
|
22
|
+
orgSlug: workspaceId,
|
|
23
|
+
projectSlug,
|
|
24
|
+
});
|
|
25
|
+
return success(result);
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=getProjectInfo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getProjectInfo.js","sourceRoot":"","sources":["../../src/tools/getProjectInfo.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,OAAO,GACR,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,GAAG,aAAa,CAAC;AAElC,MAAM,CAAC,MAAM,cAAc,GAAS;IAClC,UAAU,EAAE;QACV,IAAI,EAAE,gBAAgB;QACtB,WAAW,EACT,wKAAwK;QAC1K,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,GAAG,oBAAoB;aACxB;YACD,QAAQ,EAAE,CAAC,SAAS,CAAC;SACtB;KACF;IAED,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CACxB,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE;QAC3E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC;YACnD,OAAO,EAAE,WAAW;YACpB,WAAW;SACZ,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC,CAAC;CACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listKeys.d.ts","sourceRoot":"","sources":["../../src/tools/listKeys.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAO9C,eAAO,MAAM,QAAQ,EAAE,IAiCtB,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* listKeys MCP Tool
|
|
3
|
+
*
|
|
4
|
+
* Lists ALL translation keys in a project with their source text and translations.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { executeTool, projectInputProperty, projectSchema, success, } from "../base-tool.js";
|
|
8
|
+
const inputSchema = projectSchema.extend({
|
|
9
|
+
search: z.string().optional(),
|
|
10
|
+
namespaces: z.array(z.string()).optional(),
|
|
11
|
+
});
|
|
12
|
+
export const listKeys = {
|
|
13
|
+
definition: {
|
|
14
|
+
name: "listKeys",
|
|
15
|
+
description: "Get all translation keys with their source text and translations. Returns ALL keys in a single response. Use 'namespaces' to filter by namespace or 'search' to search within key names and source text.",
|
|
16
|
+
inputSchema: {
|
|
17
|
+
type: "object",
|
|
18
|
+
properties: {
|
|
19
|
+
...projectInputProperty,
|
|
20
|
+
search: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "Search term to find in key names or source text.",
|
|
23
|
+
},
|
|
24
|
+
namespaces: {
|
|
25
|
+
type: "array",
|
|
26
|
+
items: { type: "string" },
|
|
27
|
+
description: "Filter by specific namespaces (e.g., ['nav', 'home']).",
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
required: ["project"],
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
execute: (client, args) => executeTool(args, inputSchema, async (input, { workspaceId, projectSlug }) => {
|
|
34
|
+
const result = await client.mcp.getAllTranslations.query({
|
|
35
|
+
orgSlug: workspaceId,
|
|
36
|
+
projectSlug,
|
|
37
|
+
search: input.search,
|
|
38
|
+
namespaces: input.namespaces,
|
|
39
|
+
});
|
|
40
|
+
return success(result);
|
|
41
|
+
}),
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=listKeys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listKeys.js","sourceRoot":"","sources":["../../src/tools/listKeys.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,OAAO,GACR,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC;IACvC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CAC3C,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAS;IAC5B,UAAU,EAAE;QACV,IAAI,EAAE,UAAU;QAChB,WAAW,EACT,0MAA0M;QAC5M,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,GAAG,oBAAoB;gBACvB,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,kDAAkD;iBAChE;gBACD,UAAU,EAAE;oBACV,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACzB,WAAW,EAAE,wDAAwD;iBACtE;aACF;YACD,QAAQ,EAAE,CAAC,SAAS,CAAC;SACtB;KACF;IAED,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CACxB,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE;QAC3E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,KAAK,CAAC;YACvD,OAAO,EAAE,WAAW;YACpB,WAAW;YACX,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,UAAU,EAAE,KAAK,CAAC,UAAU;SAC7B,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC,CAAC;CACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updateTranslation.d.ts","sourceRoot":"","sources":["../../src/tools/updateTranslation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAS9C,eAAO,MAAM,iBAAiB,EAAE,IAkD/B,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* updateTranslation MCP Tool
|
|
3
|
+
*
|
|
4
|
+
* Updates or creates a translation for a specific language.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { executeTool, projectInputProperty, projectSchema, success, } from "../base-tool.js";
|
|
8
|
+
const inputSchema = projectSchema.extend({
|
|
9
|
+
key: z.string().min(1),
|
|
10
|
+
languageCode: z.string().min(2).max(10),
|
|
11
|
+
value: z.string(),
|
|
12
|
+
namespace: z.string().optional(),
|
|
13
|
+
});
|
|
14
|
+
export const updateTranslation = {
|
|
15
|
+
definition: {
|
|
16
|
+
name: "updateTranslation",
|
|
17
|
+
description: "Update or create a SINGLE translation for a specific language. IMPORTANT: If you need to update 2 or more translations, use bulkUpdateTranslations instead.",
|
|
18
|
+
inputSchema: {
|
|
19
|
+
type: "object",
|
|
20
|
+
properties: {
|
|
21
|
+
...projectInputProperty,
|
|
22
|
+
key: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: "Translation key WITHOUT namespace prefix when namespace is provided.",
|
|
25
|
+
},
|
|
26
|
+
languageCode: {
|
|
27
|
+
type: "string",
|
|
28
|
+
description: "Language code (e.g., 'en', 'tr', 'de', 'fr')",
|
|
29
|
+
},
|
|
30
|
+
value: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description: "Translation text",
|
|
33
|
+
},
|
|
34
|
+
namespace: {
|
|
35
|
+
type: "string",
|
|
36
|
+
description: "Namespace for the key. Defaults to 'default'.",
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
required: ["project", "key", "languageCode", "value"],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
execute: (client, args) => executeTool(args, inputSchema, async (input, { workspaceId, projectSlug }) => {
|
|
43
|
+
await client.mcp.updateTranslation.mutate({
|
|
44
|
+
orgSlug: workspaceId,
|
|
45
|
+
projectSlug,
|
|
46
|
+
key: input.key,
|
|
47
|
+
namespace: input.namespace || "default",
|
|
48
|
+
languageCode: input.languageCode,
|
|
49
|
+
value: input.value,
|
|
50
|
+
});
|
|
51
|
+
return success({
|
|
52
|
+
success: true,
|
|
53
|
+
key: input.key,
|
|
54
|
+
namespace: input.namespace || "default",
|
|
55
|
+
languageCode: input.languageCode,
|
|
56
|
+
value: input.value,
|
|
57
|
+
project: input.project,
|
|
58
|
+
});
|
|
59
|
+
}),
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=updateTranslation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updateTranslation.js","sourceRoot":"","sources":["../../src/tools/updateTranslation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,OAAO,GACR,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC;IACvC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACtB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;IACvC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAS;IACrC,UAAU,EAAE;QACV,IAAI,EAAE,mBAAmB;QACzB,WAAW,EACT,6JAA6J;QAC/J,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,GAAG,oBAAoB;gBACvB,GAAG,EAAE;oBACH,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,sEAAsE;iBACpF;gBACD,YAAY,EAAE;oBACZ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,8CAA8C;iBAC5D;gBACD,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,kBAAkB;iBAChC;gBACD,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,+CAA+C;iBAC7D;aACF;YACD,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,CAAC;SACtD;KACF;IAED,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CACxB,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE;QAC3E,MAAM,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC;YACxC,OAAO,EAAE,WAAW;YACpB,WAAW;YACX,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,SAAS;YACvC,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,KAAK,EAAE,KAAK,CAAC,KAAK;SACnB,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;YACb,OAAO,EAAE,IAAI;YACb,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,SAAS;YACvC,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC;IACL,CAAC,CAAC;CACL,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for MCP server
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* MCP Tool definition
|
|
6
|
+
*/
|
|
7
|
+
export interface ToolDefinition {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: "object";
|
|
12
|
+
properties: Record<string, any>;
|
|
13
|
+
required?: string[];
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* MCP Tool execution result - compatible with @modelcontextprotocol/sdk
|
|
18
|
+
*/
|
|
19
|
+
export interface ToolResult {
|
|
20
|
+
content: Array<{
|
|
21
|
+
type: "text" | "image" | "resource";
|
|
22
|
+
text?: string;
|
|
23
|
+
data?: string;
|
|
24
|
+
uri?: string;
|
|
25
|
+
mimeType?: string;
|
|
26
|
+
}>;
|
|
27
|
+
isError?: boolean;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* MCP Tool implementation
|
|
32
|
+
*/
|
|
33
|
+
export interface Tool {
|
|
34
|
+
definition: ToolDefinition;
|
|
35
|
+
execute: (client: any, args: unknown) => Promise<ToolResult>;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAChC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;QACpC,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CAC9D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@better-i18n/mcp",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "MCP server for Better i18n translation management - AI-powered translation workflow for Cursor, Claude, and other AI assistants",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"better-i18n-mcp": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"package.json",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/better-i18n/better-i18n.git",
|
|
23
|
+
"directory": "packages/mcp"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://better-i18n.com",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/better-i18n/better-i18n/issues"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"mcp",
|
|
31
|
+
"model-context-protocol",
|
|
32
|
+
"i18n",
|
|
33
|
+
"internationalization",
|
|
34
|
+
"translation",
|
|
35
|
+
"better-i18n",
|
|
36
|
+
"cursor",
|
|
37
|
+
"claude",
|
|
38
|
+
"ai",
|
|
39
|
+
"localization"
|
|
40
|
+
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsc",
|
|
43
|
+
"start": "node ./dist/index.js",
|
|
44
|
+
"dev": "bun run src/index.ts",
|
|
45
|
+
"typecheck": "tsc --noEmit",
|
|
46
|
+
"clean": "rm -rf dist",
|
|
47
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
51
|
+
"@trpc/client": "^11.0.0",
|
|
52
|
+
"zod": "^3.25.1"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/node": "^20.0.0",
|
|
56
|
+
"typescript": "~5.9.2"
|
|
57
|
+
},
|
|
58
|
+
"engines": {
|
|
59
|
+
"node": ">=18.0.0"
|
|
60
|
+
}
|
|
61
|
+
}
|