localization-mcp-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/.env.example +9 -0
  2. package/AGENT_GUIDE.md +556 -0
  3. package/AUDIT_REPORT.md +244 -0
  4. package/PROJECT_OVERVIEW.md +140 -0
  5. package/dist/api-client.d.ts +11 -0
  6. package/dist/api-client.d.ts.map +1 -0
  7. package/dist/api-client.js +67 -0
  8. package/dist/api-client.js.map +1 -0
  9. package/dist/index.d.ts +3 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +21 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/locale-aliases.d.ts +46 -0
  14. package/dist/locale-aliases.d.ts.map +1 -0
  15. package/dist/locale-aliases.js +71 -0
  16. package/dist/locale-aliases.js.map +1 -0
  17. package/dist/logger.d.ts +8 -0
  18. package/dist/logger.d.ts.map +1 -0
  19. package/dist/logger.js +19 -0
  20. package/dist/logger.js.map +1 -0
  21. package/dist/permissions.d.ts +127 -0
  22. package/dist/permissions.d.ts.map +1 -0
  23. package/dist/permissions.js +75 -0
  24. package/dist/permissions.js.map +1 -0
  25. package/dist/prompts.d.ts +3 -0
  26. package/dist/prompts.d.ts.map +1 -0
  27. package/dist/prompts.js +129 -0
  28. package/dist/prompts.js.map +1 -0
  29. package/dist/server.d.ts +3 -0
  30. package/dist/server.d.ts.map +1 -0
  31. package/dist/server.js +25 -0
  32. package/dist/server.js.map +1 -0
  33. package/dist/tools/diff.d.ts +3 -0
  34. package/dist/tools/diff.d.ts.map +1 -0
  35. package/dist/tools/diff.js +166 -0
  36. package/dist/tools/diff.js.map +1 -0
  37. package/dist/tools/environment.d.ts +3 -0
  38. package/dist/tools/environment.d.ts.map +1 -0
  39. package/dist/tools/environment.js +113 -0
  40. package/dist/tools/environment.js.map +1 -0
  41. package/dist/tools/production.d.ts +3 -0
  42. package/dist/tools/production.d.ts.map +1 -0
  43. package/dist/tools/production.js +145 -0
  44. package/dist/tools/production.js.map +1 -0
  45. package/dist/tools/project-management.d.ts +3 -0
  46. package/dist/tools/project-management.d.ts.map +1 -0
  47. package/dist/tools/project-management.js +416 -0
  48. package/dist/tools/project-management.js.map +1 -0
  49. package/dist/tools/sandbox-writes.d.ts +3 -0
  50. package/dist/tools/sandbox-writes.d.ts.map +1 -0
  51. package/dist/tools/sandbox-writes.js +260 -0
  52. package/dist/tools/sandbox-writes.js.map +1 -0
  53. package/dist/tools/snapshots.d.ts +3 -0
  54. package/dist/tools/snapshots.d.ts.map +1 -0
  55. package/dist/tools/snapshots.js +50 -0
  56. package/dist/tools/snapshots.js.map +1 -0
  57. package/dist/tools/translations.d.ts +3 -0
  58. package/dist/tools/translations.d.ts.map +1 -0
  59. package/dist/tools/translations.js +135 -0
  60. package/dist/tools/translations.js.map +1 -0
  61. package/migrate-expenses.cjs +120 -0
  62. package/package.json +26 -0
  63. package/src/api-client.ts +68 -0
  64. package/src/index.ts +29 -0
  65. package/src/logger.ts +31 -0
  66. package/src/permissions.ts +89 -0
  67. package/src/prompts.ts +159 -0
  68. package/src/server.ts +27 -0
  69. package/src/tools/diff.ts +225 -0
  70. package/src/tools/environment.ts +175 -0
  71. package/src/tools/production.ts +196 -0
  72. package/src/tools/project-management.ts +517 -0
  73. package/src/tools/sandbox-writes.ts +321 -0
  74. package/src/tools/snapshots.ts +68 -0
  75. package/src/tools/translations.ts +167 -0
  76. package/tsconfig.json +17 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,QAAQ,GACZ,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,eAAe,CAAC,CAAC;AAS1E,MAAM,UAAU,QAAQ,CACtB,SAAiB,EACjB,MAA+B,EAC/B,MAAe;IAEf,MAAM,KAAK,GAAe;QACxB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,SAAS;QACT,MAAM;QACN,MAAM;KACP,CAAC;IACF,IAAI,CAAC;QACH,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,kEAAkE;QAClE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,QAAQ,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7F,CAAC;AACH,CAAC"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * MCP Server — Environment Access Policy
3
+ *
4
+ * Policy:
5
+ * sandbox → full read + write (all tools available)
6
+ * production → read-only (no production-write tools exist by design)
7
+ *
8
+ * This file is the single source of truth for which tools write where.
9
+ * All write tools are hardcoded to sandbox API endpoints.
10
+ * There are no production-write endpoints in this MCP server — intentionally.
11
+ *
12
+ * ── Where this logic lives ───────────────────────────────────────────────────
13
+ * mcp-server/src/permissions.ts ← this file (policy + registry + guard)
14
+ * mcp-server/src/tools/sandbox-writes.ts ← write tools (always sandbox)
15
+ * mcp-server/src/tools/translations.ts ← list_translations (env param)
16
+ *
17
+ * ── How to verify ────────────────────────────────────────────────────────────
18
+ * Sandbox write:
19
+ * set_translation({ projectSlug, namespace, key, values: { en: "Hello" } })
20
+ * → should succeed and appear in get_translation_diff
21
+ *
22
+ * Production read-only:
23
+ * list_translations({ ..., env: "production" }) → OK (read allowed)
24
+ * set_translation does not accept an env param → always sandbox
25
+ *
26
+ * Guard:
27
+ * assertSandboxWrite("production") → throws Error
28
+ * assertSandboxWrite("sandbox") → no-op
29
+ */
30
+ export type Environment = "sandbox" | "production";
31
+ export type Access = "read" | "write";
32
+ export type ToolEnv = "sandbox" | "production" | "both";
33
+ export interface ToolMeta {
34
+ env: ToolEnv;
35
+ access: Access;
36
+ }
37
+ /**
38
+ * Registry of all MCP tools with their environment scope and access level.
39
+ * Add every new tool here.
40
+ */
41
+ export declare const TOOL_REGISTRY: {
42
+ readonly list_projects: {
43
+ readonly env: "both";
44
+ readonly access: "read";
45
+ };
46
+ readonly get_project_details: {
47
+ readonly env: "both";
48
+ readonly access: "read";
49
+ };
50
+ readonly get_environment_status: {
51
+ readonly env: "both";
52
+ readonly access: "read";
53
+ };
54
+ readonly list_translations: {
55
+ readonly env: "both";
56
+ readonly access: "read";
57
+ };
58
+ readonly get_translation_diff: {
59
+ readonly env: "both";
60
+ readonly access: "read";
61
+ };
62
+ readonly validate_translations: {
63
+ readonly env: "both";
64
+ readonly access: "read";
65
+ };
66
+ readonly list_snapshots: {
67
+ readonly env: "both";
68
+ readonly access: "read";
69
+ };
70
+ readonly preview_push_to_production: {
71
+ readonly env: "both";
72
+ readonly access: "read";
73
+ };
74
+ readonly init_sandbox: {
75
+ readonly env: "sandbox";
76
+ readonly access: "write";
77
+ };
78
+ readonly reset_sandbox: {
79
+ readonly env: "sandbox";
80
+ readonly access: "write";
81
+ };
82
+ readonly set_translation: {
83
+ readonly env: "sandbox";
84
+ readonly access: "write";
85
+ };
86
+ readonly delete_translation: {
87
+ readonly env: "sandbox";
88
+ readonly access: "write";
89
+ };
90
+ readonly bulk_import: {
91
+ readonly env: "sandbox";
92
+ readonly access: "write";
93
+ };
94
+ readonly bulk_set_locale: {
95
+ readonly env: "sandbox";
96
+ readonly access: "write";
97
+ };
98
+ readonly create_namespace: {
99
+ readonly env: "both";
100
+ readonly access: "write";
101
+ };
102
+ readonly create_locale: {
103
+ readonly env: "both";
104
+ readonly access: "write";
105
+ };
106
+ readonly export_namespace: {
107
+ readonly env: "both";
108
+ readonly access: "read";
109
+ };
110
+ readonly get_namespace_coverage: {
111
+ readonly env: "both";
112
+ readonly access: "read";
113
+ };
114
+ };
115
+ export type ToolName = keyof typeof TOOL_REGISTRY;
116
+ /**
117
+ * Guard for write operations. Call at the start of every write tool handler.
118
+ * Throws a descriptive error if env is 'production', enforcing read-only production.
119
+ *
120
+ * @throws Error if env === 'production'
121
+ *
122
+ * @example
123
+ * assertSandboxWrite("sandbox"); // no-op
124
+ * assertSandboxWrite("production"); // throws
125
+ */
126
+ export declare function assertSandboxWrite(env: Environment): void;
127
+ //# sourceMappingURL=permissions.d.ts.map
@@ -0,0 +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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuBmB,CAAC;AAE9C,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,aAAa,CAAC;AAElD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAQzD"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * MCP Server — Environment Access Policy
3
+ *
4
+ * Policy:
5
+ * sandbox → full read + write (all tools available)
6
+ * production → read-only (no production-write tools exist by design)
7
+ *
8
+ * This file is the single source of truth for which tools write where.
9
+ * All write tools are hardcoded to sandbox API endpoints.
10
+ * There are no production-write endpoints in this MCP server — intentionally.
11
+ *
12
+ * ── Where this logic lives ───────────────────────────────────────────────────
13
+ * mcp-server/src/permissions.ts ← this file (policy + registry + guard)
14
+ * mcp-server/src/tools/sandbox-writes.ts ← write tools (always sandbox)
15
+ * mcp-server/src/tools/translations.ts ← list_translations (env param)
16
+ *
17
+ * ── How to verify ────────────────────────────────────────────────────────────
18
+ * Sandbox write:
19
+ * set_translation({ projectSlug, namespace, key, values: { en: "Hello" } })
20
+ * → should succeed and appear in get_translation_diff
21
+ *
22
+ * Production read-only:
23
+ * list_translations({ ..., env: "production" }) → OK (read allowed)
24
+ * set_translation does not accept an env param → always sandbox
25
+ *
26
+ * Guard:
27
+ * assertSandboxWrite("production") → throws Error
28
+ * assertSandboxWrite("sandbox") → no-op
29
+ */
30
+ /**
31
+ * Registry of all MCP tools with their environment scope and access level.
32
+ * Add every new tool here.
33
+ */
34
+ export const TOOL_REGISTRY = {
35
+ // ── Read — available for both environments ──────────────────────────
36
+ list_projects: { env: "both", access: "read" },
37
+ get_project_details: { env: "both", access: "read" },
38
+ get_environment_status: { env: "both", access: "read" },
39
+ list_translations: { env: "both", access: "read" },
40
+ get_translation_diff: { env: "both", access: "read" },
41
+ validate_translations: { env: "both", access: "read" },
42
+ list_snapshots: { env: "both", access: "read" },
43
+ preview_push_to_production: { env: "both", access: "read" },
44
+ // ── Write — sandbox only; no production-write tools exist ───────────
45
+ init_sandbox: { env: "sandbox", access: "write" },
46
+ reset_sandbox: { env: "sandbox", access: "write" },
47
+ set_translation: { env: "sandbox", access: "write" },
48
+ delete_translation: { env: "sandbox", access: "write" },
49
+ bulk_import: { env: "sandbox", access: "write" },
50
+ bulk_set_locale: { env: "sandbox", access: "write" },
51
+ // ── Project structure management ──────────────────────────────────────────
52
+ create_namespace: { env: "both", access: "write" },
53
+ create_locale: { env: "both", access: "write" },
54
+ // ── Read-only export / analysis ───────────────────────────────────────────
55
+ export_namespace: { env: "both", access: "read" },
56
+ get_namespace_coverage: { env: "both", access: "read" },
57
+ };
58
+ /**
59
+ * Guard for write operations. Call at the start of every write tool handler.
60
+ * Throws a descriptive error if env is 'production', enforcing read-only production.
61
+ *
62
+ * @throws Error if env === 'production'
63
+ *
64
+ * @example
65
+ * assertSandboxWrite("sandbox"); // no-op
66
+ * assertSandboxWrite("production"); // throws
67
+ */
68
+ export function assertSandboxWrite(env) {
69
+ if (env === "production") {
70
+ throw new Error("Production is read-only. " +
71
+ "All writes must target the sandbox environment. " +
72
+ "Make changes in sandbox, then promote to production via the Admin UI.");
73
+ }
74
+ }
75
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +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,uEAAuE;IACvE,aAAa,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IAC9C,mBAAmB,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IACpD,sBAAsB,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IACvD,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,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;CACZ,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,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerPrompts(server: McpServer): void;
3
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAYpE,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAkJvD"}
@@ -0,0 +1,129 @@
1
+ import { z } from "zod";
2
+ import { apiGet, ApiError } from "./api-client.js";
3
+ export function registerPrompts(server) {
4
+ // ─── /setup ─────────────────────────────────────────────────────────────────
5
+ server.prompt("setup", "Quick-start guide: how to explore projects, work with sandbox, and push translations.", {}, () => ({
6
+ messages: [
7
+ {
8
+ role: "user",
9
+ content: {
10
+ type: "text",
11
+ text: [
12
+ "Give me a quick-start guide for working with the localization MCP server.",
13
+ "Include: how to discover projects, namespaces, and locales; how to read and write translations in sandbox;",
14
+ "how to review and push changes to production. Keep it concise and practical.",
15
+ ].join(" "),
16
+ },
17
+ },
18
+ {
19
+ role: "assistant",
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"),
49
+ },
50
+ },
51
+ ],
52
+ }));
53
+ // ─── /diagnostic ────────────────────────────────────────────────────────────
54
+ 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 }) => {
55
+ const lines = ["## Localization MCP — Diagnostic", ""];
56
+ // 1. Config
57
+ const backendUrl = process.env.BACKEND_URL ?? "http://localhost:8080 (default)";
58
+ const tokenSet = !!process.env.MCP_TOKEN;
59
+ lines.push("### Config");
60
+ lines.push(`- BACKEND_URL: \`${backendUrl}\``);
61
+ lines.push(`- MCP_TOKEN: ${tokenSet ? "set ✅" : "NOT SET ❌ — all API calls will fail with 401"}`);
62
+ lines.push("");
63
+ // 2. API connectivity + project list
64
+ lines.push("### API");
65
+ try {
66
+ const data = await apiGet("/translations/projects", { page: 1, limit: 100 });
67
+ lines.push(`- Connection: ✅ OK`);
68
+ lines.push(`- Token: ✅ valid`);
69
+ lines.push(`- Projects accessible: ${data.meta.total}`);
70
+ lines.push("");
71
+ if (data.data.length > 0) {
72
+ lines.push("### Projects");
73
+ for (const p of data.data) {
74
+ const sandboxState = p.sandboxInitializedAt
75
+ ? p.sandboxHasChanges
76
+ ? "sandbox: ⚠️ HAS PENDING CHANGES"
77
+ : "sandbox: ✅ no changes"
78
+ : "sandbox: not initialized";
79
+ lines.push(`- \`${p.slug}\`${p.name ? ` (${p.name})` : ""} — ${sandboxState}`);
80
+ }
81
+ lines.push("");
82
+ }
83
+ // 3. Optional per-project sandbox check
84
+ if (projectSlug) {
85
+ lines.push(`### Sandbox: ${projectSlug}`);
86
+ try {
87
+ const status = await apiGet(`/translations/projects/${projectSlug}/sandbox/status`);
88
+ lines.push(`- Initialized: ${status.initialized ? `✅ yes (since ${status.initializedAt})` : "❌ NO — call init_sandbox before writing"}`);
89
+ lines.push(`- Has pending changes: ${status.hasChanges ? "⚠️ YES" : "✅ no"}`);
90
+ lines.push(`- Snapshots available: ${status.snapshotCount}`);
91
+ }
92
+ catch (err) {
93
+ lines.push(`- ❌ Could not fetch sandbox status: ${err instanceof ApiError ? `${err.status} ${err.message}` : String(err)}`);
94
+ }
95
+ lines.push("");
96
+ }
97
+ }
98
+ catch (err) {
99
+ if (err instanceof ApiError) {
100
+ if (err.status === 401) {
101
+ lines.push(`- Connection: ✅ reached backend`);
102
+ lines.push(`- Token: ❌ INVALID or missing (401 Unauthorized)`);
103
+ lines.push(` → Regenerate token in Admin UI → API Tokens`);
104
+ }
105
+ else {
106
+ lines.push(`- ❌ API error ${err.status}: ${err.message}`);
107
+ }
108
+ }
109
+ else {
110
+ lines.push(`- ❌ Cannot reach backend at \`${backendUrl}\``);
111
+ lines.push(` → Is the backend running? Check BACKEND_URL env var.`);
112
+ }
113
+ lines.push("");
114
+ }
115
+ return {
116
+ messages: [
117
+ {
118
+ role: "user",
119
+ content: { type: "text", text: "Run diagnostic on the localization MCP server." },
120
+ },
121
+ {
122
+ role: "assistant",
123
+ content: { type: "text", text: lines.join("\n") },
124
+ },
125
+ ],
126
+ };
127
+ });
128
+ }
129
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function createServer(): McpServer;
3
+ //# sourceMappingURL=server.d.ts.map
@@ -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;AAUpE,wBAAgB,YAAY,IAAI,SAAS,CAgBxC"}
package/dist/server.js ADDED
@@ -0,0 +1,25 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { registerEnvironmentTools } from "./tools/environment.js";
3
+ import { registerTranslationTools } from "./tools/translations.js";
4
+ import { registerSandboxWriteTools } from "./tools/sandbox-writes.js";
5
+ import { registerProjectManagementTools } from "./tools/project-management.js";
6
+ import { registerDiffTools } from "./tools/diff.js";
7
+ import { registerSnapshotTools } from "./tools/snapshots.js";
8
+ import { registerProductionTools } from "./tools/production.js";
9
+ import { registerPrompts } from "./prompts.js";
10
+ export function createServer() {
11
+ const server = new McpServer({
12
+ name: "localization-mcp-server",
13
+ version: "1.0.0",
14
+ });
15
+ registerEnvironmentTools(server);
16
+ registerTranslationTools(server);
17
+ registerSandboxWriteTools(server);
18
+ registerProjectManagementTools(server);
19
+ registerDiffTools(server);
20
+ registerSnapshotTools(server);
21
+ registerProductionTools(server);
22
+ registerPrompts(server);
23
+ return server;
24
+ }
25
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,yBAAyB;QAC/B,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClC,8BAA8B,CAAC,MAAM,CAAC,CAAC;IACvC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,eAAe,CAAC,MAAM,CAAC,CAAC;IAExB,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerDiffTools(server: McpServer): void;
3
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/tools/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAuBpE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwKzD"}
@@ -0,0 +1,166 @@
1
+ import { z } from "zod";
2
+ import { apiGet, ApiError } from "../api-client.js";
3
+ export function registerDiffTools(server) {
4
+ server.tool("get_translation_diff", "Get the full diff between sandbox and production for a project. Shows all added, changed, and deleted entries.", {
5
+ projectSlug: z.string().describe("Project slug"),
6
+ namespace: z.string().optional().describe("Filter diff to a specific namespace (optional)"),
7
+ locale: z.string().optional().describe("Filter diff to a specific locale (optional)"),
8
+ statusFilter: z
9
+ .enum(["added", "changed", "deleted", "all"])
10
+ .default("all")
11
+ .describe("Filter by change type (default: all)"),
12
+ }, async ({ projectSlug, namespace, locale, statusFilter }) => {
13
+ try {
14
+ const diff = await apiGet(`/translations/projects/${projectSlug}/sandbox/diff`);
15
+ let entries = diff.entries;
16
+ if (namespace)
17
+ entries = entries.filter((e) => e.namespace === namespace);
18
+ if (locale)
19
+ entries = entries.filter((e) => e.locale === locale);
20
+ if (statusFilter !== "all")
21
+ entries = entries.filter((e) => e.status === statusFilter);
22
+ const summary = `Diff for ${projectSlug}: ${diff.total} total changes — ${diff.added} added, ${diff.changed} changed, ${diff.deleted} deleted`;
23
+ if (entries.length === 0) {
24
+ return {
25
+ content: [
26
+ {
27
+ type: "text",
28
+ text: `${summary}\n\nNo entries match the current filters.`,
29
+ },
30
+ ],
31
+ };
32
+ }
33
+ const grouped = groupByNamespace(entries);
34
+ const sections = Object.entries(grouped).map(([ns, nsEntries]) => {
35
+ const lines = nsEntries.map((e) => formatDiffEntry(e));
36
+ return `[${ns}]\n${lines.join("\n")}`;
37
+ });
38
+ const filterNote = namespace || locale || statusFilter !== "all"
39
+ ? `\nFilters: ${[namespace && `namespace=${namespace}`, locale && `locale=${locale}`, statusFilter !== "all" && `status=${statusFilter}`].filter(Boolean).join(", ")}`
40
+ : "";
41
+ return {
42
+ content: [
43
+ {
44
+ type: "text",
45
+ text: `${summary}${filterNote}\n\n${sections.join("\n\n")}`,
46
+ },
47
+ ],
48
+ };
49
+ }
50
+ catch (error) {
51
+ return errorContent(error);
52
+ }
53
+ });
54
+ server.tool("validate_translations", "Analyze the sandbox diff for potential issues: empty values, locales missing translations that others have, and keys only partially translated.", {
55
+ projectSlug: z.string().describe("Project slug"),
56
+ namespace: z.string().optional().describe("Limit validation to a specific namespace (optional)"),
57
+ }, async ({ projectSlug, namespace }) => {
58
+ try {
59
+ const diff = await apiGet(`/translations/projects/${projectSlug}/sandbox/diff`);
60
+ let entries = diff.entries;
61
+ if (namespace)
62
+ entries = entries.filter((e) => e.namespace === namespace);
63
+ // Only check entries that will exist in production after push (not deleted)
64
+ const activeEntries = entries.filter((e) => e.status !== "deleted");
65
+ const issues = [];
66
+ // 1. Check for empty sandbox values in added/changed entries
67
+ const emptyValues = activeEntries.filter((e) => e.sandboxValue === null || e.sandboxValue.trim() === "");
68
+ if (emptyValues.length > 0) {
69
+ issues.push(`Empty translation values (${emptyValues.length} entries):\n` +
70
+ emptyValues
71
+ .slice(0, 10)
72
+ .map((e) => ` • ${e.namespace}/${e.key} [${e.locale}]`)
73
+ .join("\n") +
74
+ (emptyValues.length > 10 ? `\n ... and ${emptyValues.length - 10} more` : ""));
75
+ }
76
+ // 2. Check for keys that are only partially translated across locales
77
+ const keyLocaleMap = new Map();
78
+ for (const entry of activeEntries) {
79
+ const k = `${entry.namespace}/${entry.key}`;
80
+ if (!keyLocaleMap.has(k))
81
+ keyLocaleMap.set(k, new Set());
82
+ keyLocaleMap.get(k).add(entry.locale);
83
+ }
84
+ const allLocales = new Set(activeEntries.map((e) => e.locale));
85
+ const partialKeys = [];
86
+ for (const [key, locales] of keyLocaleMap.entries()) {
87
+ const missing = [...allLocales].filter((l) => !locales.has(l));
88
+ if (missing.length > 0 && missing.length < allLocales.size) {
89
+ partialKeys.push(` • ${key} — missing locales: ${missing.join(", ")}`);
90
+ }
91
+ }
92
+ if (partialKeys.length > 0) {
93
+ issues.push(`Partially translated keys in diff (${partialKeys.length}):\n` +
94
+ partialKeys.slice(0, 10).join("\n") +
95
+ (partialKeys.length > 10 ? `\n ... and ${partialKeys.length - 10} more` : ""));
96
+ }
97
+ // 3. Check deleted entries — flag keys being deleted for all locales
98
+ const deletedKeys = new Map();
99
+ for (const e of entries.filter((e) => e.status === "deleted")) {
100
+ const k = `${e.namespace}/${e.key}`;
101
+ deletedKeys.set(k, (deletedKeys.get(k) ?? 0) + 1);
102
+ }
103
+ if (deletedKeys.size > 0) {
104
+ issues.push(`Keys being deleted from production (${deletedKeys.size}):\n` +
105
+ [...deletedKeys.entries()]
106
+ .slice(0, 10)
107
+ .map(([k, count]) => ` • ${k} (${count} locale values)`)
108
+ .join("\n") +
109
+ (deletedKeys.size > 10 ? `\n ... and ${deletedKeys.size - 10} more` : ""));
110
+ }
111
+ const header = `Validation for ${projectSlug}${namespace ? `/${namespace}` : ""} (${diff.total} pending changes)`;
112
+ if (issues.length === 0) {
113
+ return {
114
+ content: [
115
+ {
116
+ type: "text",
117
+ text: `${header}\n\nNo issues found. All pending translations look complete.`,
118
+ },
119
+ ],
120
+ };
121
+ }
122
+ return {
123
+ content: [
124
+ {
125
+ type: "text",
126
+ text: `${header}\n\nFound ${issues.length} issue(s):\n\n${issues.join("\n\n")}`,
127
+ },
128
+ ],
129
+ };
130
+ }
131
+ catch (error) {
132
+ return errorContent(error);
133
+ }
134
+ });
135
+ }
136
+ function groupByNamespace(entries) {
137
+ const result = {};
138
+ for (const entry of entries) {
139
+ if (!result[entry.namespace])
140
+ result[entry.namespace] = [];
141
+ result[entry.namespace].push(entry);
142
+ }
143
+ return result;
144
+ }
145
+ function formatDiffEntry(e) {
146
+ const statusSymbol = e.status === "added" ? "+" : e.status === "deleted" ? "-" : "~";
147
+ const label = `${statusSymbol} ${e.key} [${e.locale}]`;
148
+ if (e.status === "added") {
149
+ return ` ${label}\n → "${e.sandboxValue}"`;
150
+ }
151
+ if (e.status === "deleted") {
152
+ return ` ${label}\n was: "${e.productionValue}"`;
153
+ }
154
+ return ` ${label}\n before: "${e.productionValue}"\n after: "${e.sandboxValue}"`;
155
+ }
156
+ function errorContent(error) {
157
+ if (error instanceof ApiError) {
158
+ return {
159
+ content: [{ type: "text", text: `Error ${error.status}: ${error.message}` }],
160
+ };
161
+ }
162
+ return {
163
+ content: [{ type: "text", text: `Unexpected error: ${String(error)}` }],
164
+ };
165
+ }
166
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/tools/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerEnvironmentTools(server: McpServer): void;
3
+ //# sourceMappingURL=environment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/tools/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAmCpE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsHhE"}