@l10nmonster/mcp 3.0.0-alpha.17 → 3.1.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.
@@ -0,0 +1,31 @@
1
+ {
2
+ "branches": [
3
+ "main",
4
+ {
5
+ "name": "next",
6
+ "prerelease": "alpha"
7
+ },
8
+ {
9
+ "name": "beta",
10
+ "prerelease": "beta"
11
+ }
12
+ ],
13
+ "tagFormat": "@l10nmonster/mcp@${version}",
14
+ "plugins": [
15
+ "@semantic-release/commit-analyzer",
16
+ "@semantic-release/release-notes-generator",
17
+ {
18
+ "path": "@semantic-release/changelog",
19
+ "changelogFile": "CHANGELOG.md"
20
+ },
21
+ {
22
+ "path": "@semantic-release/npm",
23
+ "npmPublish": false
24
+ },
25
+ {
26
+ "path": "@semantic-release/git",
27
+ "assets": ["CHANGELOG.md", "package.json"],
28
+ "message": "chore(release): @l10nmonster/mcp@${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
29
+ }
30
+ ]
31
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # @l10nmonster/mcp [3.1.0](https://public-github/l10nmonster/l10nmonster/compare/@l10nmonster/mcp@3.0.0...@l10nmonster/mcp@3.1.0) (2025-12-20)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Make source query channel optional ([1addc68](https://public-github/l10nmonster/l10nmonster/commit/1addc68d009794a92588a28b816d7e9edbab6b47))
7
+ * Pluralization improvements ([5964250](https://public-github/l10nmonster/l10nmonster/commit/596425092c425cc8d6c312ef58509c4c3c537431))
8
+ * Version bumps ([d3030bd](https://public-github/l10nmonster/l10nmonster/commit/d3030bdd0af6ddbc79b3076af7427111ca9b04d0))
9
+
10
+
11
+ ### Features
12
+
13
+ * implement an approach for mcp extensibility ([#50](https://public-github/l10nmonster/l10nmonster/issues/50)) ([5fcc89b](https://public-github/l10nmonster/l10nmonster/commit/5fcc89bef8c8af01d88f35dece8290989d04e4d5))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@l10nmonster/mcp",
3
- "version": "3.0.0-alpha.17",
3
+ "version": "3.1.0",
4
4
  "description": "L10n Monster Model Context Protocol (MCP) Server",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -12,7 +12,7 @@
12
12
  "zod": "^3"
13
13
  },
14
14
  "peerDependencies": {
15
- "@l10nmonster/core": "^3.0.0-alpha.0"
15
+ "@l10nmonster/core": "3.1.0"
16
16
  },
17
17
  "engines": {
18
18
  "node": ">=22.11.0"
@@ -352,16 +352,16 @@ describe('MCP Tool Input Validation and Output', () => {
352
352
  assert.ok(result2.isError);
353
353
  });
354
354
 
355
- it('should require channel parameter', async () => {
355
+ it('should query all channels when channel is omitted', async () => {
356
356
  const handler = SourceQueryTool.handler(mockMM);
357
357
  const result = await handler({
358
358
  sourceLang: 'en',
359
359
  targetLang: 'fr'
360
360
  });
361
-
362
- assert.ok(result.isError);
363
- const payload = JSON.parse(result.content[1].text);
364
- assert.strictEqual(payload.code, 'INVALID_INPUT');
361
+
362
+ assert.ok(!result.isError);
363
+ const json = JSON.parse(result.content[0].text);
364
+ assert.ok(json.translationUnits);
365
365
  });
366
366
 
367
367
  it('should accept optional whereCondition', async () => {
@@ -385,16 +385,18 @@ describe('MCP Tool Input Validation and Output', () => {
385
385
  assert.ok(!result2.isError);
386
386
  });
387
387
 
388
- it('should reject empty channel', async () => {
388
+ it('should treat empty channel as query all channels', async () => {
389
389
  const handler = SourceQueryTool.handler(mockMM);
390
390
  const result = await handler({
391
391
  sourceLang: 'en',
392
392
  targetLang: 'fr',
393
393
  channel: ''
394
394
  });
395
-
396
- // Empty string should fail Zod validation (string().min(1) implicit)
397
- assert.ok(result.isError);
395
+
396
+ // Empty string channel is falsy, so queries all channels
397
+ assert.ok(!result.isError);
398
+ const json = JSON.parse(result.content[0].text);
399
+ assert.ok(json.translationUnits);
398
400
  });
399
401
  });
400
402
 
@@ -32,7 +32,8 @@ You can write your own where conditions using SQL syntaxt against the following
32
32
  targetLang: z.string()
33
33
  .describe('Target language code (e.g., "es-419")'),
34
34
  channel: z.string()
35
- .describe('Channel ID to query sources from'),
35
+ .optional()
36
+ .describe('Channel ID to query sources from. If omitted, queries all channels.'),
36
37
  whereCondition: z.string()
37
38
  .optional()
38
39
  .describe('SQL WHERE condition against sources (default: "true" to match all)'),
@@ -40,12 +41,14 @@ You can write your own where conditions using SQL syntaxt against the following
40
41
  };
41
42
 
42
43
  static async execute(mm, args) {
43
- const { sourceLang, targetLang, channel: channelId } = args;
44
+ const { sourceLang, targetLang, channel } = args;
44
45
  const whereCondition = args.whereCondition ?? 'true';
45
46
 
46
47
  const availableChannels = mm.rm.channelIds ?? [];
47
- if (availableChannels.length > 0 && !availableChannels.includes(channelId)) {
48
- throw new McpNotFoundError(`Channel "${channelId}" not found`, {
48
+ const channels = channel ? [channel] : availableChannels;
49
+
50
+ if (channel && availableChannels.length > 0 && !availableChannels.includes(channel)) {
51
+ throw new McpNotFoundError(`Channel "${channel}" not found`, {
49
52
  hints: [`Available channels: ${availableChannels.join(', ')}`]
50
53
  });
51
54
  }
@@ -61,19 +64,22 @@ You can write your own where conditions using SQL syntaxt against the following
61
64
  });
62
65
  }
63
66
 
64
- let tus;
65
- try {
66
- tus = await tm.querySource(channelId, whereCondition);
67
- } catch (error) {
68
- throw new McpToolError('Failed to execute query against source snapshot', {
69
- code: 'QUERY_FAILED',
70
- hints: [
71
- 'Verify that your SQL WHERE clause only references supported columns.',
72
- 'Escaping: wrap string literals in single quotes.'
73
- ],
74
- details: { channelId, whereCondition },
75
- cause: error
76
- });
67
+ const tus = [];
68
+ for (const channelId of channels) {
69
+ try {
70
+ const channelTus = await tm.querySource(channelId, whereCondition);
71
+ tus.push(...channelTus);
72
+ } catch (error) {
73
+ throw new McpToolError('Failed to execute query against source snapshot', {
74
+ code: 'QUERY_FAILED',
75
+ hints: [
76
+ 'Verify that your SQL WHERE clause only references supported columns.',
77
+ 'Escaping: wrap string literals in single quotes.'
78
+ ],
79
+ details: { channelId, whereCondition },
80
+ cause: error
81
+ });
82
+ }
77
83
  }
78
84
 
79
85
  return {