localization-mcp-server 1.0.2 → 1.0.3
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/.env.example +3 -0
- package/README.md +37 -0
- package/dist/permissions.d.ts +5 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +3 -2
- package/dist/permissions.js.map +1 -1
- package/dist/prompt-loader.d.ts +7 -0
- package/dist/prompt-loader.d.ts.map +1 -0
- package/dist/prompt-loader.js +29 -0
- package/dist/prompt-loader.js.map +1 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +190 -47
- package/dist/prompts.js.map +1 -1
- package/dist/server.js +1 -1
- package/dist/tools/environment.d.ts.map +1 -1
- package/dist/tools/environment.js +73 -8
- package/dist/tools/environment.js.map +1 -1
- package/dist/tools/project-management.d.ts.map +1 -1
- package/dist/tools/project-management.js +87 -3
- package/dist/tools/project-management.js.map +1 -1
- package/dist/tools/sandbox-writes.d.ts.map +1 -1
- package/dist/tools/sandbox-writes.js +51 -12
- package/dist/tools/sandbox-writes.js.map +1 -1
- package/flows/onboarding-flow.yaml +465 -0
- package/package.json +18 -1
- package/AGENT_GUIDE.md +0 -556
- package/AUDIT_REPORT.md +0 -244
- package/PROJECT_OVERVIEW.md +0 -140
- package/migrate-expenses.cjs +0 -120
- package/src/api-client.ts +0 -68
- package/src/index.ts +0 -38
- package/src/logger.ts +0 -31
- package/src/permissions.ts +0 -91
- package/src/prompts.ts +0 -159
- package/src/server.ts +0 -27
- package/src/setup.ts +0 -100
- package/src/tools/diff.ts +0 -225
- package/src/tools/environment.ts +0 -175
- package/src/tools/production.ts +0 -196
- package/src/tools/project-management.ts +0 -740
- package/src/tools/sandbox-writes.ts +0 -321
- package/src/tools/snapshots.ts +0 -68
- package/src/tools/translations.ts +0 -167
- package/tsconfig.json +0 -17
package/.env.example
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# URL of the localization backend API
|
|
2
2
|
BACKEND_URL=http://localhost:3000
|
|
3
3
|
|
|
4
|
+
# Admin UI URL — used by the agent to provide correct links to the user
|
|
5
|
+
ADMIN_UI_URL=http://localhost:3010
|
|
6
|
+
|
|
4
7
|
# Service account credentials — MCP server logs in automatically and refreshes the token
|
|
5
8
|
BACKEND_EMAIL=admin@test.com
|
|
6
9
|
BACKEND_PASSWORD=Admin123!
|
package/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# localization-mcp-server
|
|
2
|
+
|
|
3
|
+
MCP server for the localization backend. It exposes controlled tools for reading translations, managing projects, comparing environments, and applying sandbox changes through a backend API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g localization-mcp-server
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
Set these environment variables before starting the server:
|
|
14
|
+
|
|
15
|
+
- `MCP_TOKEN`: API token used for backend authentication.
|
|
16
|
+
- `BACKEND_URL`: Base URL of the localization backend API.
|
|
17
|
+
- `NODE_ENV`: Optional. In non-production mode the server also loads `.env` from the package directory.
|
|
18
|
+
|
|
19
|
+
You can copy the included `.env.example` as a starting point.
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
Start the MCP server over stdio:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
localization-mcp-server
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Run the interactive setup helper:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
localization-mcp-server setup
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Published Files
|
|
36
|
+
|
|
37
|
+
The package publishes only the built `dist` output, `flows`, `.env.example`, and this README.
|
package/dist/permissions.d.ts
CHANGED
|
@@ -47,7 +47,7 @@ export declare const TOOL_REGISTRY: {
|
|
|
47
47
|
readonly env: "both";
|
|
48
48
|
readonly access: "read";
|
|
49
49
|
};
|
|
50
|
-
readonly
|
|
50
|
+
readonly assess_integration_state: {
|
|
51
51
|
readonly env: "both";
|
|
52
52
|
readonly access: "read";
|
|
53
53
|
};
|
|
@@ -95,6 +95,10 @@ export declare const TOOL_REGISTRY: {
|
|
|
95
95
|
readonly env: "sandbox";
|
|
96
96
|
readonly access: "write";
|
|
97
97
|
};
|
|
98
|
+
readonly create_project: {
|
|
99
|
+
readonly env: "both";
|
|
100
|
+
readonly access: "write";
|
|
101
|
+
};
|
|
98
102
|
readonly create_namespace: {
|
|
99
103
|
readonly env: "both";
|
|
100
104
|
readonly access: "write";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,YAAY,CAAC;AACnD,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AACtC,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,YAAY,CAAC;AACnD,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AACtC,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BmB,CAAC;AAE9C,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,aAAa,CAAC;AAElD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAQzD"}
|
package/dist/permissions.js
CHANGED
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
* Add every new tool here.
|
|
33
33
|
*/
|
|
34
34
|
export const TOOL_REGISTRY = {
|
|
35
|
-
// ── Read —
|
|
35
|
+
// ── Read — environment / project discovery ───────────────────────────
|
|
36
36
|
list_projects: { env: "both", access: "read" },
|
|
37
37
|
get_project_details: { env: "both", access: "read" },
|
|
38
|
-
|
|
38
|
+
assess_integration_state: { env: "both", access: "read" },
|
|
39
39
|
list_translations: { env: "both", access: "read" },
|
|
40
40
|
get_translation_diff: { env: "both", access: "read" },
|
|
41
41
|
validate_translations: { env: "both", access: "read" },
|
|
@@ -49,6 +49,7 @@ export const TOOL_REGISTRY = {
|
|
|
49
49
|
bulk_import: { env: "sandbox", access: "write" },
|
|
50
50
|
bulk_set_locale: { env: "sandbox", access: "write" },
|
|
51
51
|
// ── Project structure management ──────────────────────────────────────────
|
|
52
|
+
create_project: { env: "both", access: "write" },
|
|
52
53
|
create_namespace: { env: "both", access: "write" },
|
|
53
54
|
create_locale: { env: "both", access: "write" },
|
|
54
55
|
// ── Read-only export / analysis ───────────────────────────────────────────
|
package/dist/permissions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAWH;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAWH;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,wEAAwE;IACxE,aAAa,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IAC9C,mBAAmB,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IACpD,wBAAwB,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IACzD,iBAAiB,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IAClD,oBAAoB,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IACrD,qBAAqB,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IACtD,cAAc,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IAC/C,0BAA0B,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IAC3D,uEAAuE;IACvE,YAAY,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE;IACjD,aAAa,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE;IAClD,eAAe,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE;IACpD,kBAAkB,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE;IACvD,WAAW,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE;IAChD,eAAe,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE;IACpD,6EAA6E;IAC7E,cAAc,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;IAChD,gBAAgB,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;IAClD,aAAa,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;IAC/C,6EAA6E;IAC7E,gBAAgB,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IACjD,sBAAsB,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IACvD,uBAAuB,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IACxD,aAAa,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;CACH,CAAC;AAI9C;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAgB;IACjD,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,2BAA2B;YACzB,kDAAkD;YAClD,uEAAuE,CAC1E,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches prompt content from the backend DB.
|
|
3
|
+
* Returns DB override if available, otherwise returns the fallback (code default).
|
|
4
|
+
* Results are cached for 60s. On any error (timeout, 404, network), falls back silently.
|
|
5
|
+
*/
|
|
6
|
+
export declare function fetchPromptContent(key: string, fallback: string): Promise<string>;
|
|
7
|
+
//# sourceMappingURL=prompt-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-loader.d.ts","sourceRoot":"","sources":["../src/prompt-loader.ts"],"names":[],"mappings":"AAaA;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBvF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { apiGet } from "./api-client.js";
|
|
2
|
+
const cache = new Map();
|
|
3
|
+
const CACHE_TTL_MS = 60_000;
|
|
4
|
+
const FETCH_TIMEOUT_MS = 2_000;
|
|
5
|
+
/**
|
|
6
|
+
* Fetches prompt content from the backend DB.
|
|
7
|
+
* Returns DB override if available, otherwise returns the fallback (code default).
|
|
8
|
+
* Results are cached for 60s. On any error (timeout, 404, network), falls back silently.
|
|
9
|
+
*/
|
|
10
|
+
export async function fetchPromptContent(key, fallback) {
|
|
11
|
+
const now = Date.now();
|
|
12
|
+
const cached = cache.get(key);
|
|
13
|
+
if (cached && cached.expiresAt > now) {
|
|
14
|
+
return cached.content;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const result = await Promise.race([
|
|
18
|
+
apiGet(`/mcp-prompts/${key}`),
|
|
19
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("prompt fetch timeout")), FETCH_TIMEOUT_MS)),
|
|
20
|
+
]);
|
|
21
|
+
cache.set(key, { content: result.content, expiresAt: now + CACHE_TTL_MS });
|
|
22
|
+
return result.content;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// 404 (no override), timeout, or network error → use code default
|
|
26
|
+
return fallback;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=prompt-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-loader.js","sourceRoot":"","sources":["../src/prompt-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AASzC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkD,CAAC;AACxE,MAAM,YAAY,GAAG,MAAM,CAAC;AAC5B,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAE/B;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,GAAW,EAAE,QAAgB;IACpE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,MAAM,IAAI,MAAM,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC;QACrC,OAAO,MAAM,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAChC,MAAM,CAAiB,gBAAgB,GAAG,EAAE,CAAC;YAC7C,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAC/B,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAC9E;SACF,CAAC,CAAC;QACH,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,GAAG,YAAY,EAAE,CAAC,CAAC;QAC3E,OAAO,MAAM,CAAC,OAAO,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,kEAAkE;QAClE,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC"}
|
package/dist/prompts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA+JpE,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA0JvD"}
|
package/dist/prompts.js
CHANGED
|
@@ -1,57 +1,177 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { apiGet, ApiError } from "./api-client.js";
|
|
3
|
+
import { fetchPromptContent } from "./prompt-loader.js";
|
|
4
|
+
const DEFAULT_SETUP_CONTENT = [
|
|
5
|
+
"## Localization MCP — Quick Start",
|
|
6
|
+
"",
|
|
7
|
+
"### ⚠️ Pre-flight (mandatory before any write)",
|
|
8
|
+
"`get_project_details <slug>` — returns locale codes + sandbox state in one call",
|
|
9
|
+
"- `NOT initialized` → call `init_sandbox` first",
|
|
10
|
+
"- `HAS PENDING CHANGES` → call `get_translation_diff` to review before adding more",
|
|
11
|
+
"",
|
|
12
|
+
"### 1. Discover",
|
|
13
|
+
"- `list_projects` — see all projects and sandbox state",
|
|
14
|
+
"- `get_project_details <slug>` — get exact locale codes and namespaces",
|
|
15
|
+
"",
|
|
16
|
+
"### 2. Read translations",
|
|
17
|
+
"- `list_translations <slug> <namespace>` — browse keys; filter with `missingLocale`, `search`",
|
|
18
|
+
"- `get_translation_diff <slug>` — see what changed in sandbox vs production",
|
|
19
|
+
"",
|
|
20
|
+
"### 3. Write to sandbox",
|
|
21
|
+
"- `set_translation` — upsert one key (pass only the locales you want to update)",
|
|
22
|
+
"- `bulk_set_locale` — fill many keys for a single locale at once",
|
|
23
|
+
"- `bulk_import` — import multiple locales from a JSON map",
|
|
24
|
+
"- `delete_translation` — soft-delete a key in sandbox",
|
|
25
|
+
"",
|
|
26
|
+
"### 4. Review & push",
|
|
27
|
+
"- `validate_translations <slug>` — check for missing translations before pushing",
|
|
28
|
+
"- `get_translation_diff <slug>` — final review of pending changes",
|
|
29
|
+
"- Promote via the Admin UI — MCP has no push tool by design (human approval required)",
|
|
30
|
+
"",
|
|
31
|
+
"### Rules",
|
|
32
|
+
"- All writes go to **sandbox only** — production is never touched directly",
|
|
33
|
+
"- Locale codes must match exactly what `get_project_details` returns — never guess",
|
|
34
|
+
"- Prefer existing namespaces — only create a new one with a clear justification",
|
|
35
|
+
].join("\n");
|
|
36
|
+
const DEFAULT_ASSESS_CONTENT = [
|
|
37
|
+
"## Localization Integration Assessment",
|
|
38
|
+
"",
|
|
39
|
+
"You are now running a localization integration assessment. Follow these steps in order.",
|
|
40
|
+
"",
|
|
41
|
+
"---",
|
|
42
|
+
"",
|
|
43
|
+
"### Step 1: Get remote state",
|
|
44
|
+
"",
|
|
45
|
+
"Call `assess_integration_state`{{#projectSlug}} with projectSlug: \"{{projectSlug}}\"{{/projectSlug}}.",
|
|
46
|
+
"This gives you the remote project list, URL patterns, and classification guide.",
|
|
47
|
+
"",
|
|
48
|
+
"---",
|
|
49
|
+
"",
|
|
50
|
+
"### Step 2: Inspect the local project",
|
|
51
|
+
"",
|
|
52
|
+
"After reading the remote state, inspect the local codebase for localization setup:",
|
|
53
|
+
"",
|
|
54
|
+
"1. Search for i18n configuration files: look for files named i18n.ts, i18next.ts, i18n.js,",
|
|
55
|
+
" i18next.config.ts, or similar. Also check for vue-i18n, react-intl, lingui, or i18next",
|
|
56
|
+
" initialization in app entry points.",
|
|
57
|
+
"",
|
|
58
|
+
"2. Check environment files: read .env, .env.local, .env.development, .env.production,",
|
|
59
|
+
" .env.staging, and any other .env.* files. Look for any variable containing a URL",
|
|
60
|
+
" that relates to translations or localization.",
|
|
61
|
+
"",
|
|
62
|
+
"3. Search for the backend URL: look for the backend URL returned by assess_integration_state",
|
|
63
|
+
" in any config or env file.",
|
|
64
|
+
"",
|
|
65
|
+
"4. Check for ?env=sandbox: search for this exact string in the project. Its presence in",
|
|
66
|
+
" non-production configs is the key indicator of up-to-date integration.",
|
|
67
|
+
"",
|
|
68
|
+
"5. Look for Locize references: search for \"locize.com\" or \"localazy\" or similar third-party",
|
|
69
|
+
" localization service URLs — this indicates a migration scenario.",
|
|
70
|
+
"",
|
|
71
|
+
"---",
|
|
72
|
+
"",
|
|
73
|
+
"### Step 3: Classify the integration state",
|
|
74
|
+
"",
|
|
75
|
+
"Using what you found locally and the classification guide from assess_integration_state,",
|
|
76
|
+
"determine which state applies:",
|
|
77
|
+
"",
|
|
78
|
+
"**S1 — Correctly integrated:**",
|
|
79
|
+
"→ Confirm to the user, no action needed. Proceed with normal translation work.",
|
|
80
|
+
"",
|
|
81
|
+
"**S2 — Outdated integration (missing ?env=sandbox):**",
|
|
82
|
+
"→ Tell the user: \"Your project uses our localization server, but non-production environments",
|
|
83
|
+
"are not using sandbox mode. This means dev/staging changes go directly to production data.\"",
|
|
84
|
+
"→ Show which files need updating",
|
|
85
|
+
"→ Ask: \"Should I update these files for you, or would you prefer to do it manually?\"",
|
|
86
|
+
"→ If user approves: propose specific file edits, apply with approval per file",
|
|
87
|
+
"→ If user prefers manual: show exactly what to change and where",
|
|
88
|
+
"→ After fixing: call init_sandbox if sandbox is not initialized",
|
|
89
|
+
"",
|
|
90
|
+
"**S3 — Not integrated, remote project available:**",
|
|
91
|
+
"→ Tell the user which remote projects exist",
|
|
92
|
+
"→ Ask: \"Which project should this local project connect to?\" (show list)",
|
|
93
|
+
"→ After selection: help update local config to use the correct URL patterns",
|
|
94
|
+
"→ Then assess if the selected project needs bootstrap (S5 check)",
|
|
95
|
+
"",
|
|
96
|
+
"**S4 — Not integrated, no remote project:**",
|
|
97
|
+
"→ Tell the user no remote project exists yet",
|
|
98
|
+
"→ Ask: \"Would you like to create a new localization project?\"",
|
|
99
|
+
"→ Suggest a project name based on: package.json name field, git remote URL, or directory name",
|
|
100
|
+
"→ Present options: create now / I'll create manually in Admin UI",
|
|
101
|
+
"→ If create now: ask for slug confirmation, then call create_project, create_namespace, create_locale, init_sandbox",
|
|
102
|
+
"→ Then help configure local integration",
|
|
103
|
+
"",
|
|
104
|
+
"**S5 — Project exists but empty/incomplete:**",
|
|
105
|
+
"→ Tell the user the project exists but has not been bootstrapped",
|
|
106
|
+
"→ Offer to:",
|
|
107
|
+
" a) Create missing namespaces (ask for name, default: \"common\")",
|
|
108
|
+
" b) Create missing locales (ask for primary locale BCP 47 code)",
|
|
109
|
+
" c) Initialize sandbox",
|
|
110
|
+
" d) Scan and import local translation files if they exist",
|
|
111
|
+
"→ Do these in order, with user confirmation for each group",
|
|
112
|
+
"",
|
|
113
|
+
"**S6 — No localization system found:**",
|
|
114
|
+
"→ Tell the user no i18n setup was found",
|
|
115
|
+
"→ Ask: \"Would you like me to set up localization from scratch?\"",
|
|
116
|
+
"→ If yes:",
|
|
117
|
+
" a) Ask what i18n library they want to use (suggest i18next as default for React/Node,",
|
|
118
|
+
" vue-i18n for Vue, or a custom fetch approach)",
|
|
119
|
+
" b) Propose the integration: install library, create config, configure to fetch from our backend",
|
|
120
|
+
" c) Show what the config should look like with the correct URLs from assess_integration_state",
|
|
121
|
+
" d) Apply with user approval",
|
|
122
|
+
" e) Then continue with project creation if needed (S4 path)",
|
|
123
|
+
"",
|
|
124
|
+
"---",
|
|
125
|
+
"",
|
|
126
|
+
"### Rules for all paths",
|
|
127
|
+
"",
|
|
128
|
+
"- All writes go to sandbox only — never to production",
|
|
129
|
+
"- init_sandbox must be called before any sandbox writes",
|
|
130
|
+
"- Never create a project, namespace, or locale without user confirmation",
|
|
131
|
+
"- Always show what you're about to do before doing it",
|
|
132
|
+
"- If uncertain about the local project structure, ask rather than assume",
|
|
133
|
+
"- Namespace mapping: if the local project has its own namespace structure (multiple translation files",
|
|
134
|
+
" per area/feature), preserve that structure — create matching namespaces, don't flatten into one",
|
|
135
|
+
"- After any setup action: summarize what was done and what the user should do next",
|
|
136
|
+
"",
|
|
137
|
+
"---",
|
|
138
|
+
"",
|
|
139
|
+
"### Final step",
|
|
140
|
+
"",
|
|
141
|
+
"After completing setup (any state), summarize:",
|
|
142
|
+
"1. What integration state was detected",
|
|
143
|
+
"2. What was changed (if anything)",
|
|
144
|
+
"3. What the user needs to do manually (if anything)",
|
|
145
|
+
"4. Current sandbox state",
|
|
146
|
+
"5. Next recommended action",
|
|
147
|
+
].join("\n");
|
|
3
148
|
export function registerPrompts(server) {
|
|
4
149
|
// ─── /setup ─────────────────────────────────────────────────────────────────
|
|
5
|
-
server.prompt("setup", "Quick-start guide: how to explore projects, work with sandbox, and push translations.", {}, () =>
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
150
|
+
server.prompt("setup", "Quick-start guide: how to explore projects, work with sandbox, and push translations.", {}, async () => {
|
|
151
|
+
const assistantText = await fetchPromptContent("setup", DEFAULT_SETUP_CONTENT);
|
|
152
|
+
return {
|
|
153
|
+
messages: [
|
|
154
|
+
{
|
|
155
|
+
role: "user",
|
|
156
|
+
content: {
|
|
157
|
+
type: "text",
|
|
158
|
+
text: [
|
|
159
|
+
"Give me a quick-start guide for working with the localization MCP server.",
|
|
160
|
+
"Include: how to discover projects, namespaces, and locales; how to read and write translations in sandbox;",
|
|
161
|
+
"how to review and push changes to production. Keep it concise and practical.",
|
|
162
|
+
].join(" "),
|
|
163
|
+
},
|
|
16
164
|
},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
content: {
|
|
21
|
-
type: "text",
|
|
22
|
-
text: [
|
|
23
|
-
"## Localization MCP — Quick Start",
|
|
24
|
-
"",
|
|
25
|
-
"### 1. Discover",
|
|
26
|
-
"- `list_projects` — see all projects and sandbox state",
|
|
27
|
-
"- `get_project_details <slug>` — get exact locale codes and namespaces (**always call this before writing**)",
|
|
28
|
-
"",
|
|
29
|
-
"### 2. Read translations",
|
|
30
|
-
"- `list_translations <slug> <namespace>` — browse keys; filter with `missingLocale`, `search`",
|
|
31
|
-
"- `get_translation_diff <slug>` — see what changed in sandbox vs production",
|
|
32
|
-
"",
|
|
33
|
-
"### 3. Write to sandbox",
|
|
34
|
-
"- `set_translation` — upsert one key (pass only the locales you want to update)",
|
|
35
|
-
"- `bulk_set_locale` — fill many keys for a single locale at once",
|
|
36
|
-
"- `bulk_import` — import multiple locales from a JSON map",
|
|
37
|
-
"- `delete_translation` — soft-delete a key in sandbox",
|
|
38
|
-
"",
|
|
39
|
-
"### 4. Review & push",
|
|
40
|
-
"- `validate_translations <slug>` — check for missing translations before pushing",
|
|
41
|
-
"- `get_translation_diff <slug>` — final review of pending changes",
|
|
42
|
-
"- Promote via the Admin UI — MCP has no push tool by design (human approval required)",
|
|
43
|
-
"",
|
|
44
|
-
"### Rules",
|
|
45
|
-
"- All writes go to **sandbox only** — production is never touched directly",
|
|
46
|
-
"- Locale codes must match exactly what `get_project_details` returns — never guess",
|
|
47
|
-
"- Prefer existing namespaces — only create a new one with a clear justification",
|
|
48
|
-
].join("\n"),
|
|
165
|
+
{
|
|
166
|
+
role: "assistant",
|
|
167
|
+
content: { type: "text", text: assistantText },
|
|
49
168
|
},
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
})
|
|
169
|
+
],
|
|
170
|
+
};
|
|
171
|
+
});
|
|
53
172
|
// ─── /diagnostic ────────────────────────────────────────────────────────────
|
|
54
173
|
server.prompt("diagnostic", "Run a live health check: verify API connectivity, token validity, and list project states.", { projectSlug: z.string().optional().describe("Optional: also check sandbox status for this project") }, async ({ projectSlug }) => {
|
|
174
|
+
const diagnosticUserText = await fetchPromptContent("diagnostic", "Run diagnostic on the localization MCP server.");
|
|
55
175
|
const lines = ["## Localization MCP — Diagnostic", ""];
|
|
56
176
|
// 1. Config
|
|
57
177
|
const backendUrl = process.env.BACKEND_URL ?? "http://localhost:8080 (default)";
|
|
@@ -116,7 +236,7 @@ export function registerPrompts(server) {
|
|
|
116
236
|
messages: [
|
|
117
237
|
{
|
|
118
238
|
role: "user",
|
|
119
|
-
content: { type: "text", text:
|
|
239
|
+
content: { type: "text", text: diagnosticUserText },
|
|
120
240
|
},
|
|
121
241
|
{
|
|
122
242
|
role: "assistant",
|
|
@@ -125,5 +245,28 @@ export function registerPrompts(server) {
|
|
|
125
245
|
],
|
|
126
246
|
};
|
|
127
247
|
});
|
|
248
|
+
// ─── /assess ────────────────────────────────────────────────────────────────
|
|
249
|
+
server.prompt("assess", "Assess the current localization integration state of the local project and get guided next steps. Run this before starting any localization work.", { projectSlug: z.string().optional().describe("Optional: the project slug if you already know which project this local project should use") }, async ({ projectSlug }) => {
|
|
250
|
+
const template = await fetchPromptContent("assess", DEFAULT_ASSESS_CONTENT);
|
|
251
|
+
const placeholder = "{{#projectSlug}} with projectSlug: \"{{projectSlug}}\"{{/projectSlug}}";
|
|
252
|
+
const assistantText = projectSlug
|
|
253
|
+
? template.replace(placeholder, ` with projectSlug: "${projectSlug}"`)
|
|
254
|
+
: template.replace(placeholder, "");
|
|
255
|
+
return {
|
|
256
|
+
messages: [
|
|
257
|
+
{
|
|
258
|
+
role: "user",
|
|
259
|
+
content: {
|
|
260
|
+
type: "text",
|
|
261
|
+
text: "Assess the localization integration state of my local project and guide me to the correct next step.",
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
role: "assistant",
|
|
266
|
+
content: { type: "text", text: assistantText },
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
};
|
|
270
|
+
});
|
|
128
271
|
}
|
|
129
272
|
//# sourceMappingURL=prompts.js.map
|
package/dist/prompts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -10,7 +10,7 @@ import { registerPrompts } from "./prompts.js";
|
|
|
10
10
|
export function createServer() {
|
|
11
11
|
const server = new McpServer({
|
|
12
12
|
name: "localization-mcp-server",
|
|
13
|
-
version: "1.0.
|
|
13
|
+
version: "1.0.3",
|
|
14
14
|
});
|
|
15
15
|
registerEnvironmentTools(server);
|
|
16
16
|
registerTranslationTools(server);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/tools/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/tools/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAkCpE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4LhE"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { apiGet } from "../api-client.js";
|
|
3
|
-
import { ApiError } from "../api-client.js";
|
|
2
|
+
import { apiGet, ApiError } from "../api-client.js";
|
|
4
3
|
export function registerEnvironmentTools(server) {
|
|
5
4
|
server.tool("list_projects", "List all translation projects accessible to the service account. Returns slugs, names, and sandbox state.", {}, async () => {
|
|
6
5
|
try {
|
|
@@ -72,15 +71,81 @@ export function registerEnvironmentTools(server) {
|
|
|
72
71
|
return errorContent(error);
|
|
73
72
|
}
|
|
74
73
|
});
|
|
75
|
-
server.tool("
|
|
74
|
+
server.tool("assess_integration_state", [
|
|
75
|
+
"Starting point for localization integration assessment.",
|
|
76
|
+
"Fetches the remote project list with sandbox state, returns the correct client URL patterns for both production and non-production environments,",
|
|
77
|
+
"and provides a full classification guide so the agent can determine whether the local project is correctly integrated.",
|
|
78
|
+
"Use this as the first tool call when running /assess or whenever you need to evaluate how (or whether) a consumer app is connected to this localization backend.",
|
|
79
|
+
"If projectSlug is provided, also fetches full project details (locales, namespaces, sandbox state) for that specific project.",
|
|
80
|
+
].join(" "), { projectSlug: z.string().optional().describe("Optional: the project slug to fetch full details for") }, async ({ projectSlug }) => {
|
|
76
81
|
try {
|
|
77
|
-
const
|
|
82
|
+
const backendUrl = process.env.BACKEND_URL ?? "http://localhost:8080";
|
|
83
|
+
const adminUiUrl = process.env.ADMIN_UI_URL ?? "http://localhost:3010";
|
|
84
|
+
// Fetch projects and optional project details in parallel.
|
|
85
|
+
// The project list already includes sandboxHasChanges + sandboxInitializedAt — no extra status calls needed.
|
|
86
|
+
const [projectsData, projectDetails] = await Promise.all([
|
|
87
|
+
apiGet("/translations/projects", { page: 1, limit: 100 }),
|
|
88
|
+
projectSlug
|
|
89
|
+
? apiGet(`/translations/projects/${projectSlug}`).catch(() => null)
|
|
90
|
+
: Promise.resolve(null),
|
|
91
|
+
]);
|
|
92
|
+
const projectRows = projectsData.data.map((p) => {
|
|
93
|
+
const sandboxState = p.sandboxInitializedAt
|
|
94
|
+
? p.sandboxHasChanges
|
|
95
|
+
? "initialized, HAS PENDING CHANGES"
|
|
96
|
+
: "initialized, no changes"
|
|
97
|
+
: "not initialized";
|
|
98
|
+
return `• ${p.slug}${p.name ? ` (${p.name})` : ""} — sandbox: ${sandboxState}`;
|
|
99
|
+
});
|
|
78
100
|
const lines = [
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
`
|
|
101
|
+
`## Integration Assessment — Remote State`,
|
|
102
|
+
``,
|
|
103
|
+
`### Server Configuration`,
|
|
104
|
+
`Backend URL: ${backendUrl}`,
|
|
105
|
+
`Admin UI URL: ${adminUiUrl}`,
|
|
106
|
+
``,
|
|
107
|
+
`### Client URL Patterns`,
|
|
108
|
+
`Production: ${backendUrl}/translations/{slug}/{namespace}/{locale}`,
|
|
109
|
+
`Non-production: ${backendUrl}/translations/{slug}/{namespace}/{locale}?env=sandbox`,
|
|
110
|
+
``,
|
|
111
|
+
`Non-production environments MUST use ?env=sandbox — without it, dev/staging tests run against live production data.`,
|
|
112
|
+
``,
|
|
113
|
+
`### What to look for in the local project`,
|
|
114
|
+
`1. URL matching: ${backendUrl}`,
|
|
115
|
+
`2. ?env=sandbox in non-production localization fetch URLs`,
|
|
116
|
+
`3. i18n init files (i18next.ts, i18n.ts, vue-i18n, react-intl, etc.)`,
|
|
117
|
+
`4. .env, .env.local, .env.development, .env.production`,
|
|
118
|
+
`5. References to Locize or other external i18n services (migration scenario)`,
|
|
119
|
+
``,
|
|
120
|
+
`Use the S1–S6 classification guide in AGENT_GUIDE.md to determine integration state.`,
|
|
121
|
+
``,
|
|
122
|
+
`### Remote Projects (${projectsData.meta.total} found)`,
|
|
123
|
+
...projectRows,
|
|
83
124
|
];
|
|
125
|
+
if (projectSlug) {
|
|
126
|
+
lines.push(``, `### Project Details: ${projectSlug}`);
|
|
127
|
+
if (!projectDetails) {
|
|
128
|
+
lines.push(`Error: project "${projectSlug}" not found or not accessible.`);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
const localeCount = projectDetails.locales.length;
|
|
132
|
+
const nsCount = projectDetails.namespaces.length;
|
|
133
|
+
const isEmpty = nsCount === 0 || localeCount === 0;
|
|
134
|
+
const projectInList = projectsData.data.find((p) => p.slug === projectSlug);
|
|
135
|
+
const sandboxState = projectInList
|
|
136
|
+
? projectInList.sandboxInitializedAt
|
|
137
|
+
? projectInList.sandboxHasChanges
|
|
138
|
+
? "initialized, HAS PENDING CHANGES"
|
|
139
|
+
: "initialized, no changes"
|
|
140
|
+
: "not initialized"
|
|
141
|
+
: "unknown";
|
|
142
|
+
lines.push(`Locales (${localeCount}): ${localeCount > 0 ? projectDetails.locales.map((l) => l.code).join(", ") : "none yet"}`);
|
|
143
|
+
lines.push(`Namespaces (${nsCount}): ${nsCount > 0 ? projectDetails.namespaces.join(", ") : "none yet"}`);
|
|
144
|
+
lines.push(`Sandbox: ${sandboxState}`);
|
|
145
|
+
lines.push(`Is empty: ${isEmpty}`);
|
|
146
|
+
lines.push(`Admin UI: ${adminUiUrl} (Projects → ${projectSlug})`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
84
149
|
return {
|
|
85
150
|
content: [{ type: "text", text: lines.join("\n") }],
|
|
86
151
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../src/tools/environment.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../src/tools/environment.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-management.d.ts","sourceRoot":"","sources":["../../src/tools/project-management.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4BpE,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"project-management.d.ts","sourceRoot":"","sources":["../../src/tools/project-management.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4BpE,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAozBtE"}
|