cwtools-mcp 0.1.0 → 0.2.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.
@@ -592,6 +592,7 @@ var require_mcpTools = __commonJS({
592
592
  "localisation",
593
593
  "identifiers",
594
594
  "validation",
595
+ "compatibility",
595
596
  "promptCards",
596
597
  "all"
597
598
  ],
@@ -751,7 +752,11 @@ var require_mcpTools = __commonJS({
751
752
  },
752
753
  "includeReferences": {
753
754
  "type": "boolean",
754
- "description": "If true, include lightweight cross-file reference contexts captured by the index. Default false."
755
+ "description": "Include lightweight cross-file reference contexts. Default false."
756
+ },
757
+ "includeAssetChain": {
758
+ "type": "boolean",
759
+ "description": "Check bounded GUI/GFX/model targets, path case, and DDS frame layout."
755
760
  },
756
761
  "limit": {
757
762
  "type": "number",
@@ -773,7 +778,7 @@ var require_mcpTools = __commonJS({
773
778
  {
774
779
  "tool": {
775
780
  "name": "explore_pdx_project",
776
- "description": "Primary semantic exploration entry point for large Paradox projects. Queries the live CWTools type/reference graph and returns bounded entry points, typed nodes, dependency edges, file facts, provenance, truncation, and freshness without scanning or reading whole files. Use this FIRST for questions such as how an entity is connected, what calls or references an ID, what a file depends on, or what may be affected by a change. Follow with exact query_rules/query_scope/query_types/get_pdx_block checks before writing.",
781
+ "description": "Primary semantic exploration for large Paradox projects: live CWTools type/reference graph with bounded nodes, edges, file facts, provenance and freshness. Use FIRST for connectivity and impact; follow with exact query_rules/query_scope/query_types/get_pdx_block before writing.",
777
782
  "inputSchema": {
778
783
  "type": "object",
779
784
  "properties": {
@@ -814,6 +819,17 @@ var require_mcpTools = __commonJS({
814
819
  "includeMetadata": {
815
820
  "type": "boolean",
816
821
  "description": "Include documentation, variables, event targets, and block metadata. Default true."
822
+ },
823
+ "relationshipKinds": {
824
+ "type": "array",
825
+ "items": {
826
+ "type": "string",
827
+ "enum": [
828
+ "inline_invocation",
829
+ "inline_expansion"
830
+ ]
831
+ },
832
+ "description": "Extra graph kinds: inline_invocation or inline_expansion."
817
833
  }
818
834
  },
819
835
  "required": []
@@ -828,6 +844,109 @@ var require_mcpTools = __commonJS({
828
844
  "concurrencyClass": "lsp-limited"
829
845
  }
830
846
  },
847
+ {
848
+ "tool": {
849
+ "name": "query_inline_instantiation",
850
+ "description": "Preview one inline_script template instantiation: parameters, arguments, expanded symbol, and problems (missing/unused/unresolved). Precise template path or file+line only; no whole-project expansion. Use before editing a template or caller.",
851
+ "inputSchema": {
852
+ "type": "object",
853
+ "properties": {
854
+ "template": {
855
+ "type": "string",
856
+ "description": "Template path, e.g. common/inline_scripts/example.txt."
857
+ },
858
+ "file": {
859
+ "type": "string",
860
+ "description": "Caller file; narrows to one invocation."
861
+ },
862
+ "line": {
863
+ "type": "number",
864
+ "description": "Caller line; combined with file selects one invocation."
865
+ },
866
+ "limit": {
867
+ "type": "number",
868
+ "description": "Maximum invocations to return. Default 50, max 200."
869
+ }
870
+ },
871
+ "required": []
872
+ }
873
+ },
874
+ "registry": {
875
+ "name": "query_inline_instantiation",
876
+ "isWrite": false,
877
+ "isReadOnly": true,
878
+ "effect": "workspace_read",
879
+ "riskLevel": 0,
880
+ "concurrencyClass": "lsp-limited"
881
+ }
882
+ },
883
+ {
884
+ "tool": {
885
+ "name": "analyze_pdx_flow",
886
+ "description": "Static cost model and gameplay relations for a file or definition: traversals (every_*/while), pulse handlers, nested fan-out, and typed edges (tech prerequisites, special project events, megastructure upgrades). Relative weights only.",
887
+ "inputSchema": {
888
+ "type": "object",
889
+ "properties": {
890
+ "file": {
891
+ "type": "string",
892
+ "description": "Optional file path to analyze; when omitted a definitionId must be given."
893
+ },
894
+ "definitionId": {
895
+ "type": "string",
896
+ "description": "Optional exact definition ID; combined with file to scope the analysis."
897
+ },
898
+ "entityType": {
899
+ "type": "string",
900
+ "description": "Optional exact CWTools entity type; use with definitionId to disambiguate duplicate IDs."
901
+ },
902
+ "limit": {
903
+ "type": "number",
904
+ "description": "Maximum costs and relations returned per collection. Default 100, max 500."
905
+ }
906
+ },
907
+ "required": []
908
+ }
909
+ },
910
+ "registry": {
911
+ "name": "analyze_pdx_flow",
912
+ "isWrite": false,
913
+ "isReadOnly": true,
914
+ "effect": "workspace_read",
915
+ "riskLevel": 0,
916
+ "concurrencyClass": "lsp-limited"
917
+ }
918
+ },
919
+ {
920
+ "tool": {
921
+ "name": "compare_definition_with_vanilla",
922
+ "description": "Field-level diff of one definition against its vanilla counterpart: added, removed and modified fields with stable source locations. Accepts exact entityType + symbolId only; returns the resolved winner and never fabricates a conclusion when the winner is ambiguous. Use before editing any file that overrides vanilla.",
923
+ "inputSchema": {
924
+ "type": "object",
925
+ "properties": {
926
+ "entityType": {
927
+ "type": "string",
928
+ "description": "Exact CWTools type name (e.g. event, technology, ship_size)."
929
+ },
930
+ "symbolId": {
931
+ "type": "string",
932
+ "description": "Exact definition ID shared by workspace and vanilla candidates."
933
+ }
934
+ },
935
+ "required": [
936
+ "entityType",
937
+ "symbolId"
938
+ ]
939
+ }
940
+ },
941
+ "registry": {
942
+ "name": "compare_definition_with_vanilla",
943
+ "isWrite": false,
944
+ "isReadOnly": true,
945
+ "effect": "workspace_read",
946
+ "riskLevel": 0,
947
+ "concurrencyClass": "lsp-limited"
948
+ }
949
+ },
831
950
  {
832
951
  "tool": {
833
952
  "name": "query_localisation_index",
@@ -855,6 +974,26 @@ var require_mcpTools = __commonJS({
855
974
  "type": "boolean",
856
975
  "description": "Only applies to prefix/contains searches. Default false."
857
976
  },
977
+ "includeDuplicates": {
978
+ "type": "boolean",
979
+ "description": "Include per-key duplicate groups with all occurrences (file/line), so duplicate keys are auditable instead of trusting the last write. Default false."
980
+ },
981
+ "compareLanguages": {
982
+ "type": "boolean",
983
+ "description": "Include true missing/extra key-set differences per language, independent of result truncation. Default false."
984
+ },
985
+ "referenceLanguage": {
986
+ "type": "string",
987
+ "description": "Reference language for missing/extra differences. Defaults to l_english when indexed."
988
+ },
989
+ "referenceStatus": {
990
+ "type": "boolean",
991
+ "description": "Include bounded LSP reference status and origin; dynamic keys remain uncertain."
992
+ },
993
+ "auditMode": {
994
+ "type": "boolean",
995
+ "description": "Include authoritative CWTools localisation diagnostics: completely missing script-referenced keys, inline/dynamic-key provenance, and localisation command/scope issues."
996
+ },
858
997
  "limit": {
859
998
  "type": "number",
860
999
  "description": "Maximum entries to return. Default 20, max 100."
@@ -906,7 +1045,7 @@ var require_mcpTools = __commonJS({
906
1045
  {
907
1046
  "tool": {
908
1047
  "name": "get_completion_at",
909
- "description": "Get auto-completion suggestions and structured context at a specific position. The CWTools language server returns candidates from both the current mod and the vanilla game cache, plus line/token/scope context for deciding what values can go here.",
1048
+ "description": "Get auto-completion suggestions and bounded context at a specific position through the active VS Code language provider. In Paradox projects, CWTools may enrich the result with game-aware scope and schema context.",
910
1049
  "inputSchema": {
911
1050
  "type": "object",
912
1051
  "properties": {
@@ -1064,7 +1203,7 @@ var require_mcpTools = __commonJS({
1064
1203
  {
1065
1204
  "tool": {
1066
1205
  "name": "query_references",
1067
- "description": "Find all references to a specific identifier in the mod files. Use this to understand how an event, trigger, or effect is used across the codebase.",
1206
+ "description": "Find references to an identifier through the active language provider, with a bounded workspace text-search fallback.",
1068
1207
  "inputSchema": {
1069
1208
  "type": "object",
1070
1209
  "properties": {
@@ -3216,16 +3355,17 @@ var require_profile = __commonJS({
3216
3355
  }
3217
3356
  }
3218
3357
  function isProjectProfile(value) {
3219
- return !!value && typeof value === "object" && value.schemaVersion === 1 && typeof value.projectName === "string";
3358
+ return !!value && typeof value === "object" && (value.schemaVersion === 1 || value.schemaVersion === 2) && typeof value.projectName === "string";
3220
3359
  }
3221
3360
  function buildProfileSummary(profile) {
3222
3361
  const dirs = profile.keyDirectories.filter((dir) => dir.exists).map((dir) => dir.path).slice(0, 8).join(", ") || "none";
3223
3362
  const namespaces = Array.isArray(profile.identifiers.namespaces) ? profile.identifiers.namespaces.slice(0, 8).join(", ") || "none" : "none";
3224
3363
  const languages = profile.localisation.languages.join(", ") || "unknown";
3364
+ const supportedVersion = typeof profile.modInfo?.supportedVersion === "string" ? ` (${profile.modInfo.supportedVersion})` : "";
3225
3365
  return [
3226
3366
  `Project: ${profile.projectName}`,
3227
3367
  `Kind: ${profile.workspaceKind}`,
3228
- `Game: ${profile.game.displayName}`,
3368
+ `Game: ${profile.game.displayName}${supportedVersion}`,
3229
3369
  `Key dirs: ${dirs}`,
3230
3370
  `Namespaces: ${namespaces}`,
3231
3371
  `Localisation: ${languages} (${profile.localisation.encoding})`
@@ -3254,6 +3394,14 @@ var require_profile = __commonJS({
3254
3394
  return profile.identifiers;
3255
3395
  case "validation":
3256
3396
  return profile.validation;
3397
+ case "compatibility":
3398
+ return {
3399
+ supportedVersion: profile.modInfo?.supportedVersion,
3400
+ remoteFileId: profile.modInfo?.remoteFileId,
3401
+ dependencies: profile.modInfo?.dependencies ?? [],
3402
+ vanillaCache: profile.validation?.vanillaCache,
3403
+ game: profile.game
3404
+ };
3257
3405
  case "promptCards":
3258
3406
  return profile.promptCards;
3259
3407
  case "all":
@@ -3264,7 +3412,10 @@ var require_profile = __commonJS({
3264
3412
  workspaceKind: profile.workspaceKind,
3265
3413
  projectName: profile.projectName,
3266
3414
  game: profile.game,
3415
+ supportedVersion: profile.modInfo?.supportedVersion,
3267
3416
  generatedAt: profile.generatedAt,
3417
+ freshness: profile.freshness,
3418
+ warnings: profile.warnings ?? [],
3268
3419
  efficiencyHints: profile.efficiencyHints
3269
3420
  };
3270
3421
  }
@@ -3297,7 +3448,7 @@ var require_profile = __commonJS({
3297
3448
  source: "cwtools-shared",
3298
3449
  error: {
3299
3450
  code: "invalid_profile",
3300
- message: "Project profile exists but is not schemaVersion 1."
3451
+ message: "Project profile exists but is not a valid schemaVersion 1 or 2 profile."
3301
3452
  }
3302
3453
  };
3303
3454
  }
@@ -3382,21 +3533,13 @@ var require_knowledge = __commonJS({
3382
3533
  exports2.queryProjectKnowledgeWithHost = queryProjectKnowledgeWithHost;
3383
3534
  var path = __importStar(require("path"));
3384
3535
  var KNOWLEDGE_DIR = path.join(".cwtools", "project", "knowledge");
3536
+ var CURRENT_KNOWLEDGE_SCHEMA_VERSION = 7;
3385
3537
  function asRecord(value) {
3386
3538
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
3387
3539
  }
3388
3540
  function stringArray(value) {
3389
3541
  return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
3390
3542
  }
3391
- function tokensFor(args) {
3392
- return [args.intent ?? "", ...args.identifiers ?? [], ...args.entityTypes ?? []].join(" ").toLowerCase().match(/[@a-z0-9_.:-]{2,}/g)?.slice(0, 30) ?? [];
3393
- }
3394
- function score(value, tokens) {
3395
- if (tokens.length === 0)
3396
- return 1;
3397
- const text = JSON.stringify(value).toLowerCase();
3398
- return tokens.reduce((total, token) => total + (text.includes(token) ? 3 : 0), 0);
3399
- }
3400
3543
  async function readJson(host, filePath) {
3401
3544
  const read = await host.filesystem.readTextFile(filePath);
3402
3545
  if (!read.exists)
@@ -3408,19 +3551,9 @@ var require_knowledge = __commonJS({
3408
3551
  }
3409
3552
  }
3410
3553
  async function queryProjectKnowledgeWithHost(host, args = {}) {
3411
- let root = path.join(host.workspaceRoot, KNOWLEDGE_DIR);
3412
- let manifestPath = path.join(root, "manifest.json");
3413
- let manifest = await readJson(host, manifestPath);
3414
- if (!manifest) {
3415
- const legacyRoot = path.join(host.workspaceRoot, ".cwtools-ai", "project", "knowledge");
3416
- const legacyManifestPath = path.join(legacyRoot, "manifest.json");
3417
- const legacyManifest = await readJson(host, legacyManifestPath);
3418
- if (legacyManifest) {
3419
- root = legacyRoot;
3420
- manifestPath = legacyManifestPath;
3421
- manifest = legacyManifest;
3422
- }
3423
- }
3554
+ const root = path.join(host.workspaceRoot, KNOWLEDGE_DIR);
3555
+ const manifestPath = path.join(root, "manifest.json");
3556
+ const manifest = await readJson(host, manifestPath);
3424
3557
  if (!manifest) {
3425
3558
  return {
3426
3559
  ok: false,
@@ -3437,8 +3570,29 @@ var require_knowledge = __commonJS({
3437
3570
  }
3438
3571
  };
3439
3572
  }
3440
- if (Number(manifest.schemaVersion) >= 2) {
3441
- const database = asRecord(manifest.database);
3573
+ const database = asRecord(manifest.database);
3574
+ const foundSchemaVersion = Number(database.schemaVersion ?? manifest.schemaVersion) || 0;
3575
+ if (Number(manifest.schemaVersion) !== CURRENT_KNOWLEDGE_SCHEMA_VERSION || foundSchemaVersion !== CURRENT_KNOWLEDGE_SCHEMA_VERSION) {
3576
+ return {
3577
+ ok: false,
3578
+ status: "stale",
3579
+ source: "cwtools-project-knowledge-sqlite",
3580
+ error: {
3581
+ code: "knowledge_schema_obsolete",
3582
+ message: `Project knowledge schema V${foundSchemaVersion} is obsolete. Rebuild it with the current V${CURRENT_KNOWLEDGE_SCHEMA_VERSION} extension.`
3583
+ },
3584
+ data: {
3585
+ status: "stale",
3586
+ manifestPath,
3587
+ rebuildRequired: true,
3588
+ foundSchemaVersion,
3589
+ currentSchemaVersion: CURRENT_KNOWLEDGE_SCHEMA_VERSION,
3590
+ staleReasons: ["schema_version_obsolete"],
3591
+ _hint: "Run /init or reopen the project and wait for the automatic full rebuild. Old database schemas are not queried."
3592
+ }
3593
+ };
3594
+ }
3595
+ {
3442
3596
  const relativeDatabasePath = typeof database.path === "string" && database.path.trim() ? database.path : "knowledge.sqlite";
3443
3597
  const databasePath = path.resolve(root, relativeDatabasePath);
3444
3598
  const relative = path.relative(root, databasePath);
@@ -3463,74 +3617,22 @@ var require_knowledge = __commonJS({
3463
3617
  data: { manifestPath, databasePath }
3464
3618
  };
3465
3619
  }
3466
- const manifestStatus2 = String(manifest.status ?? "stale");
3467
- const staleReasons2 = stringArray(manifest.staleReasons);
3468
- const ready2 = String(result.status ?? manifestStatus2) === "ready" && manifestStatus2 === "ready" && staleReasons2.length === 0;
3469
- const partial = staleReasons2.length === 0 && (String(result.status ?? manifestStatus2) === "partial" || manifestStatus2 === "partial");
3620
+ const manifestStatus = String(manifest.status ?? "stale");
3621
+ const staleReasons = stringArray(manifest.staleReasons);
3622
+ const ready = String(result.status ?? manifestStatus) === "ready" && manifestStatus === "ready" && staleReasons.length === 0;
3623
+ const partial = staleReasons.length === 0 && (String(result.status ?? manifestStatus) === "partial" || manifestStatus === "partial");
3470
3624
  return {
3471
3625
  ok: true,
3472
- status: ready2 ? "ready" : partial ? "partial" : "stale",
3626
+ status: ready ? "ready" : partial ? "partial" : "stale",
3473
3627
  source: "cwtools-project-knowledge-sqlite",
3474
3628
  data: {
3475
3629
  ...result,
3476
- status: ready2 ? "ready" : partial ? "partial" : "stale",
3630
+ status: ready ? "ready" : partial ? "partial" : "stale",
3477
3631
  manifestPath,
3478
- staleReasons: staleReasons2
3632
+ staleReasons
3479
3633
  }
3480
3634
  };
3481
3635
  }
3482
- const manifestDomains = stringArray(manifest.domains);
3483
- const domains = (args.domains?.length ? args.domains : manifestDomains).map((value) => value.trim().toLowerCase()).filter(Boolean).slice(0, 12);
3484
- const tokens = tokensFor(args);
3485
- const limit = Math.max(1, Math.min(Number(args.limit ?? 80) || 80, 300));
3486
- const evidence = [];
3487
- const capabilities = [];
3488
- for (const domain of domains) {
3489
- const capability = await readJson(host, path.join(root, "capabilities", `${domain}.json`));
3490
- if (!capability)
3491
- continue;
3492
- capabilities.push({ domain, summary: capability.summary, evidencePolicy: capability.evidencePolicy });
3493
- const candidates = [];
3494
- if (Array.isArray(capability.definitions))
3495
- candidates.push(...capability.definitions.map(asRecord));
3496
- if (args.includeProjectPatterns !== false && Array.isArray(capability.projectExamples))
3497
- candidates.push(...capability.projectExamples.map(asRecord));
3498
- if (args.includeVanillaArchetypes !== false && Array.isArray(capability.vanillaArchetypes))
3499
- candidates.push(...capability.vanillaArchetypes.map(asRecord));
3500
- if (args.includeTopology !== false) {
3501
- const topology = asRecord(capability.topology);
3502
- if (Array.isArray(topology.edges))
3503
- candidates.push(...topology.edges.map(asRecord));
3504
- }
3505
- evidence.push(...candidates.map((item) => ({ ...item, domain, score: score(item, tokens) })).filter((item) => tokens.length === 0 || Number(item.score) > 0).sort((a, b) => Number(b.score) - Number(a.score)).slice(0, Math.max(5, Math.ceil(limit / Math.max(1, domains.length)))));
3506
- }
3507
- const unresolvedFile = args.includeUnresolved === false ? void 0 : await readJson(host, path.join(root, "unresolved.json"));
3508
- const unresolved = Array.isArray(unresolvedFile?.entries) ? unresolvedFile.entries.map(asRecord).slice(0, 100) : [];
3509
- const manifestStatus = String(manifest.status ?? "stale");
3510
- const staleReasons = stringArray(manifest.staleReasons);
3511
- const ready = manifestStatus === "ready" && staleReasons.length === 0;
3512
- return {
3513
- ok: true,
3514
- status: ready ? "ready" : "stale",
3515
- source: "cwtools-project-knowledge",
3516
- data: {
3517
- status: ready ? "ready" : "stale",
3518
- manifestPath,
3519
- generatedAt: manifest.generatedAt,
3520
- game: manifest.game,
3521
- graphVersion: manifest.graphVersion,
3522
- staleReasons,
3523
- domains,
3524
- capabilities,
3525
- evidence: evidence.slice(0, limit),
3526
- unresolved,
3527
- requiredNextChecks: [
3528
- "Use query_cwt_schema/query_rules/query_scope for legality before writing.",
3529
- "Use query_override_modes for target directories with vanilla definitions.",
3530
- "Read exact source blocks before approving a complex blueprint."
3531
- ]
3532
- }
3533
- };
3534
3636
  }
3535
3637
  }
3536
3638
  });
@@ -3711,6 +3813,9 @@ var require_names = __commonJS({
3711
3813
  "query_project_knowledge",
3712
3814
  "query_workspace_index",
3713
3815
  "explore_pdx_project",
3816
+ "query_inline_instantiation",
3817
+ "analyze_pdx_flow",
3818
+ "compare_definition_with_vanilla",
3714
3819
  "query_localisation_index",
3715
3820
  "get_pdx_block",
3716
3821
  "get_completion_at",
@@ -4753,17 +4858,81 @@ var require_toolHandlers = __commonJS({
4753
4858
  args.maxEdges ?? 80,
4754
4859
  args.includeMetadata !== false
4755
4860
  ], "Start the CWTools LSP process and wait for the game model to load before exploring the semantic graph.");
4861
+ case "analyze_pdx_flow": {
4862
+ const file = typeof args.file === "string" ? args.file.trim() : "";
4863
+ const definitionId = typeof args.definitionId === "string" ? args.definitionId.trim() : "";
4864
+ if (!file && !definitionId) {
4865
+ return {
4866
+ ok: false,
4867
+ status: "error",
4868
+ source: "cwtools-shared",
4869
+ error: {
4870
+ code: "invalid_arguments",
4871
+ message: "analyze_pdx_flow requires a file or a definitionId."
4872
+ }
4873
+ };
4874
+ }
4875
+ return executeLspTool(host, "cwtools.ai.analyzePdxFlow", [{
4876
+ ...file ? { file } : {},
4877
+ ...definitionId ? { definitionId } : {},
4878
+ ...typeof args.entityType === "string" && args.entityType.trim() ? { entityType: args.entityType.trim() } : {},
4879
+ limit: Math.max(1, Math.min(Number(args.limit ?? 100) || 100, 500))
4880
+ }], "Start the CWTools LSP process and wait for the game model to load before analyzing flow cost and gameplay relations.");
4881
+ }
4882
+ case "compare_definition_with_vanilla": {
4883
+ if (typeof args.entityType !== "string" || typeof args.symbolId !== "string" || !args.entityType.trim() || !args.symbolId.trim()) {
4884
+ return {
4885
+ ok: false,
4886
+ status: "error",
4887
+ source: "cwtools-shared",
4888
+ error: {
4889
+ code: "invalid_arguments",
4890
+ message: "compare_definition_with_vanilla requires entityType and symbolId."
4891
+ }
4892
+ };
4893
+ }
4894
+ return executeLspTool(host, "cwtools.ai.compareDefinitionWithVanilla", [args.entityType.trim(), args.symbolId.trim()], "Start the CWTools LSP process and wait for the game model to load before comparing the definition with vanilla.");
4895
+ }
4896
+ case "query_inline_instantiation": {
4897
+ const template = typeof args.template === "string" ? args.template.trim() : "";
4898
+ const file = typeof args.file === "string" ? args.file.trim() : "";
4899
+ if (!template && !file) {
4900
+ return {
4901
+ ok: false,
4902
+ status: "error",
4903
+ source: "cwtools-shared",
4904
+ error: {
4905
+ code: "invalid_arguments",
4906
+ message: "query_inline_instantiation requires a template path or a caller file (optionally with line)."
4907
+ }
4908
+ };
4909
+ }
4910
+ return executeLspTool(host, "cwtools.ai.exploreInlineGraph", [{
4911
+ ...template ? { template } : {},
4912
+ ...file ? { file } : {},
4913
+ ...Number.isInteger(args.line) ? { line: Number(args.line) } : {},
4914
+ limit: Math.max(1, Math.min(Number(args.limit ?? 50) || 50, 200))
4915
+ }], "Start the CWTools LSP process and wait for the game model to load before resolving the inline template instantiation.");
4916
+ }
4756
4917
  case "query_localisation_index": {
4757
4918
  if (!host.indexing) {
4758
4919
  return (0, schema_1.toolUnavailable)(name, "Localisation index is not available in this host.", [
4759
4920
  "Wire an LSP index command or a thin Node index before using this tool for localisation evidence."
4760
4921
  ]);
4761
4922
  }
4923
+ const data = await host.indexing.queryLocalisation(args);
4924
+ const semanticAudit = args.auditMode === true ? await executeLspTool(host, "cwtools.ai.queryLocalisationAudit", [{
4925
+ ...typeof args.key === "string" ? { key: args.key } : {},
4926
+ prefix: args.prefix === true,
4927
+ contains: args.contains === true,
4928
+ caseSensitive: args.caseSensitive === true,
4929
+ limit: Math.max(1, Math.min(Number(args.limit ?? 100) || 100, 500))
4930
+ }], "Start the CWTools LSP process and wait for localisation validation before requesting auditMode.") : void 0;
4762
4931
  return {
4763
4932
  ok: true,
4764
4933
  status: "ready",
4765
4934
  source: "cwtools-index",
4766
- data: await host.indexing.queryLocalisation(args)
4935
+ data: semanticAudit ? { ...data, semanticAudit } : data
4767
4936
  };
4768
4937
  }
4769
4938
  case "get_diagnostics": {
@@ -46446,16 +46615,8 @@ var require_resources = __commonJS({
46446
46615
  };
46447
46616
  }
46448
46617
  case "cwtools://project/knowledge-manifest": {
46449
- let manifestPath = path.join(host.workspaceRoot, ".cwtools", "project", "knowledge", "manifest.json");
46450
- let read = await host.filesystem.readTextFile(manifestPath);
46451
- if (!read.exists) {
46452
- const legacyPath = path.join(host.workspaceRoot, ".cwtools-ai", "project", "knowledge", "manifest.json");
46453
- const legacyRead = await host.filesystem.readTextFile(legacyPath);
46454
- if (legacyRead.exists) {
46455
- manifestPath = legacyPath;
46456
- read = legacyRead;
46457
- }
46458
- }
46618
+ const manifestPath = path.join(host.workspaceRoot, ".cwtools", "project", "knowledge", "manifest.json");
46619
+ const read = await host.filesystem.readTextFile(manifestPath);
46459
46620
  return read.exists ? JSON.parse(read.content) : {
46460
46621
  status: "missing",
46461
46622
  manifestPath,
@@ -121,16 +121,8 @@ async function readResourceData(host, uri) {
121
121
  };
122
122
  }
123
123
  case 'cwtools://project/knowledge-manifest': {
124
- let manifestPath = path.join(host.workspaceRoot, '.cwtools', 'project', 'knowledge', 'manifest.json');
125
- let read = await host.filesystem.readTextFile(manifestPath);
126
- if (!read.exists) {
127
- const legacyPath = path.join(host.workspaceRoot, '.cwtools-ai', 'project', 'knowledge', 'manifest.json');
128
- const legacyRead = await host.filesystem.readTextFile(legacyPath);
129
- if (legacyRead.exists) {
130
- manifestPath = legacyPath;
131
- read = legacyRead;
132
- }
133
- }
124
+ const manifestPath = path.join(host.workspaceRoot, '.cwtools', 'project', 'knowledge', 'manifest.json');
125
+ const read = await host.filesystem.readTextFile(manifestPath);
134
126
  return read.exists
135
127
  ? JSON.parse(read.content)
136
128
  : {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cwtools-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Read-only MCP server exposing CWTools Paradox/Stellaris semantic tools to external agents",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -37,7 +37,7 @@
37
37
  "dependencies": {
38
38
  "@modelcontextprotocol/sdk": "^1.29.0",
39
39
  "chokidar": "^4.0.3",
40
- "cwtools-shared": "0.1.0",
40
+ "cwtools-shared": "0.2.0",
41
41
  "vscode-jsonrpc": "^8.2.0"
42
42
  },
43
43
  "devDependencies": {