@hyperfixi/mcp-server 3.1.1 → 3.3.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 (3) hide show
  1. package/README.md +6 -6
  2. package/dist/index.js +61 -18
  3. package/package.json +24 -24
package/README.md CHANGED
@@ -118,12 +118,12 @@ The **103** tools below, plus the **5** GRAIL tools above, total **108** defined
118
118
 
119
119
  ### Pattern Lookup (4)
120
120
 
121
- | Tool | Description |
122
- | ----------------------- | -------------------------------------------------------------- |
123
- | `get_examples` | Get working code examples matching a task description |
124
- | `search_patterns` | Search pattern database by keyword or category |
125
- | `translate_hyperscript` | Translate keywords between 24 languages (pattern substitution) |
126
- | `get_pattern_stats` | Get statistics about patterns and languages |
121
+ | Tool | Description |
122
+ | ----------------------- | ------------------------------------------------------------------------------------------ |
123
+ | `get_examples` | Get working code examples matching a task description |
124
+ | `search_patterns` | Search pattern database by keyword or category |
125
+ | `translate_hyperscript` | Translate between 24 languages (same engine as `translate_code`, without its verification) |
126
+ | `get_pattern_stats` | Get statistics about patterns and languages |
127
127
 
128
128
  ### LSP Bridge (4)
129
129
 
package/dist/index.js CHANGED
@@ -474,7 +474,7 @@ function simpleIntentRecognition(code) {
474
474
  var patternTools = [
475
475
  {
476
476
  name: "get_examples",
477
- description: 'Get hyperscript code examples matching a natural language task description (e.g., "toggle a class on click"). Returns working code with quality scores. Best for generating new code by example.',
477
+ description: 'Get hyperscript code examples matching a natural language task description (e.g., "toggle a class on click"). Returns code verified to run on at least one engine, each tagged with `engine` (both = upstream _hyperscript and hyperfixi, hyperscript = upstream only, lokascript = hyperfixi only), plus quality scores. Best for generating new code by example.',
478
478
  inputSchema: {
479
479
  type: "object",
480
480
  properties: {
@@ -498,7 +498,7 @@ var patternTools = [
498
498
  },
499
499
  {
500
500
  name: "search_patterns",
501
- description: "Search the pattern database by keyword or category filter (class-manipulation, visibility, async, validation, etc.). Unlike get_examples which takes task descriptions, this searches pattern names and content.",
501
+ description: "Search the pattern database by keyword, optionally within one category (events, dom-manipulation, class-manipulation, visibility, forms, async, etc.). Unlike get_examples which takes task descriptions, this searches pattern names and content.",
502
502
  inputSchema: {
503
503
  type: "object",
504
504
  properties: {
@@ -521,7 +521,7 @@ var patternTools = [
521
521
  },
522
522
  {
523
523
  name: "translate_hyperscript",
524
- description: "Translate hyperscript keywords between any of 24 languages via pattern substitution. Preserves selectors and values. For higher-fidelity translation with grammar transformation, use translate_code instead.",
524
+ description: "Translate hyperscript between any of 24 languages with @lokascript/semantic (parse, then render in the target language's word order); selectors and values are preserved. Same engine as translate_code, which also returns a fidelity verification and name-collision warnings.",
525
525
  inputSchema: {
526
526
  type: "object",
527
527
  properties: {
@@ -576,7 +576,11 @@ async function handlePatternTool(name, args) {
576
576
  examples: examples.map((ex) => ({
577
577
  task: ex.prompt,
578
578
  code: ex.completion,
579
- quality: ex.qualityScore
579
+ quality: ex.qualityScore,
580
+ // Which engine(s) are verified to run it (both | lokascript |
581
+ // hyperscript) — patterns-reference never serves one that
582
+ // runs on neither.
583
+ engine: ex.engine
580
584
  })),
581
585
  count: examples.length,
582
586
  language
@@ -599,11 +603,7 @@ async function handlePatternTool(name, args) {
599
603
  const ref = patternsRef.createPatternsReference({ readonly: true });
600
604
  let patterns;
601
605
  try {
602
- if (category) {
603
- patterns = await ref.getPatternsByCategory(category);
604
- } else {
605
- patterns = await ref.searchPatterns(query, { limit });
606
- }
606
+ patterns = await ref.searchPatterns(query, { category, limit });
607
607
  } finally {
608
608
  ref.close();
609
609
  }
@@ -617,7 +617,7 @@ async function handlePatternTool(name, args) {
617
617
  id: p.id,
618
618
  title: p.title,
619
619
  code: p.rawCode,
620
- category: p.feature
620
+ category: p.category
621
621
  })),
622
622
  count: patterns.length,
623
623
  query
@@ -920,7 +920,7 @@ function handleWithBuiltinExamples(name, args) {
920
920
  builtinExamples: BUILTIN_EXAMPLES.length,
921
921
  categories: [...new Set(BUILTIN_EXAMPLES.map((ex) => ex.category))],
922
922
  supportedLanguages: ["en"],
923
- note: "Install @hyperfixi/patterns-reference for 106 patterns, 1378 translations, 414 LLM examples"
923
+ note: "Install @hyperfixi/patterns-reference for the full pattern database: patterns, their translations in 24 languages, and LLM examples"
924
924
  },
925
925
  null,
926
926
  2
@@ -1255,6 +1255,11 @@ try {
1255
1255
  semanticPackage = await import("@lokascript/semantic");
1256
1256
  } catch {
1257
1257
  }
1258
+ var coreParse = null;
1259
+ try {
1260
+ coreParse = (await import("@hyperfixi/core")).parse;
1261
+ } catch {
1262
+ }
1258
1263
  var cachedAnalyzer = null;
1259
1264
  function getSemanticAnalyzer() {
1260
1265
  if (!semanticPackage) return null;
@@ -1274,6 +1279,8 @@ function getSemanticAnalyzer() {
1274
1279
  if (result.tokensConsumed !== void 0) out.tokensConsumed = result.tokensConsumed;
1275
1280
  if (result.node) {
1276
1281
  out.command = { name: result.node.action, roles: result.node.roles };
1282
+ const unconsumed = (result.node.diagnostics ?? []).filter((d) => d.code === "unconsumed-input" && d.message).map((d) => d.message);
1283
+ if (unconsumed.length > 0) out.unconsumed = unconsumed;
1277
1284
  }
1278
1285
  if (result.error) out.errors = [result.error];
1279
1286
  return out;
@@ -1291,7 +1298,7 @@ function getSemanticAnalyzer() {
1291
1298
  var validationTools = [
1292
1299
  {
1293
1300
  name: "validate_hyperscript",
1294
- description: "Check hyperscript code for syntax errors and role warnings. Use as the FIRST validation step before returning code to users. For detailed line/column positions, use get_diagnostics instead.",
1301
+ description: `Check hyperscript code for syntax errors and role warnings. Use as the FIRST validation step before returning code to users. English is also checked against hyperfixi's own parser (errors with source "core-parser"); tokens the semantic parser could not bind are warned as UNCONSUMED_INPUT, and a translation of that code drops them. It checks one snippet on its own, so it cannot tell whether a translation kept every clause: use score_fidelity (or translate_code's verification) for that. For detailed line/column positions, use get_diagnostics instead.`,
1295
1302
  inputSchema: {
1296
1303
  type: "object",
1297
1304
  properties: {
@@ -1626,6 +1633,7 @@ function validateHyperscript(code, language) {
1626
1633
  const validCommands = getValidCommandsForLanguage(language);
1627
1634
  const eventKeywords = getEventHandlerKeywords(language);
1628
1635
  let semanticInfo = null;
1636
+ let semanticEvent;
1629
1637
  const analyzer = getSemanticAnalyzer();
1630
1638
  if (analyzer) {
1631
1639
  try {
@@ -1648,6 +1656,28 @@ function validateHyperscript(code, language) {
1648
1656
  errors.push({ message: err, source: "semantic-parser" });
1649
1657
  }
1650
1658
  }
1659
+ const ev = result2.command?.roles?.get("event");
1660
+ const evName = ev?.value ?? ev?.raw;
1661
+ if (result2.command?.name === "on" && typeof evName === "string") semanticEvent = evName;
1662
+ for (const msg of result2.unconsumed ?? []) {
1663
+ warnings.push({
1664
+ code: "UNCONSUMED_INPUT",
1665
+ message: `Semantic parser ${msg.replace(/^body clause /, "left part of the body unbound: ")}`,
1666
+ suggestion: "translate_code and the semantic IR drop these tokens. Rephrase with an explicit command or role marker (e.g. `call me.click()`), or check the translation's verification.referenceComplete.",
1667
+ source: "semantic-parser"
1668
+ });
1669
+ }
1670
+ if (language !== "en" && result2.confidence >= 0.5) {
1671
+ const findings = semanticPackage?.findNameCollisions?.(code, language) ?? [];
1672
+ for (const finding of findings) {
1673
+ warnings.push({
1674
+ code: "NAME_COLLISION",
1675
+ message: finding.message,
1676
+ suggestion: finding.rename ? `Rename \`${finding.name}\` to \`${finding.rename}\` in the ${finding.occurrences.length} place(s) the parse reads it as the variable.` : `Rename \`${finding.name}\`.`,
1677
+ source: "semantic-parser"
1678
+ });
1679
+ }
1680
+ }
1651
1681
  if (result2.confidence > 0 && result2.confidence < 0.5) {
1652
1682
  warnings.push({
1653
1683
  message: `Low parsing confidence (${(result2.confidence * 100).toFixed(0)}%)`,
@@ -1760,7 +1790,7 @@ function validateHyperscript(code, language) {
1760
1790
  });
1761
1791
  }
1762
1792
  const eventPattern = new RegExp(
1763
- `(?:^|\\n|;|\\bthen\\b)\\s*(${eventKeywords.join("|")})\\s+(\\w+)`,
1793
+ `(?:^|\\n|;|\\bthen\\b)\\s*(${eventKeywords.join("|")})\\s+([\\w:.-]+)`,
1764
1794
  "gim"
1765
1795
  );
1766
1796
  const eventMatches = code.matchAll(eventPattern);
@@ -1814,16 +1844,29 @@ function validateHyperscript(code, language) {
1814
1844
  "window",
1815
1845
  "document"
1816
1846
  ];
1817
- for (const match of eventMatches) {
1818
- const event = match[2].toLowerCase();
1819
- if (!validEvents.includes(event) && !event.includes(".") && !targetKeywords.includes(event)) {
1847
+ const judged = semanticEvent ? [semanticEvent.toLowerCase().split("[")[0]] : [...eventMatches].map((m) => m[2].toLowerCase());
1848
+ for (const event of judged) {
1849
+ if (!validEvents.includes(event) && !event.includes(".") && !event.includes(":") && !targetKeywords.includes(event)) {
1820
1850
  warnings.push({
1821
1851
  message: `Unknown event type: ${event}`,
1822
1852
  suggestion: `Did you mean one of: ${validEvents.slice(0, 5).join(", ")}...?`
1823
1853
  });
1824
1854
  }
1825
1855
  }
1826
- const commandPattern = new RegExp(`\\b(${validCommands.slice(0, 30).join("|")})\\b`, "gi");
1856
+ if (coreParse && (language === "en" || language.startsWith("en-"))) {
1857
+ try {
1858
+ for (const err of coreParse(code).errors ?? []) {
1859
+ errors.push({
1860
+ message: err.message,
1861
+ source: "core-parser",
1862
+ suggestion: "hyperfixi's parser rejects this, so hyperfixi cannot run it as written (get_diagnostics gives the position)."
1863
+ });
1864
+ }
1865
+ } catch (e) {
1866
+ errors.push({ message: e instanceof Error ? e.message : String(e), source: "core-parser" });
1867
+ }
1868
+ }
1869
+ const commandPattern = new RegExp(`\\b(${validCommands.join("|")})\\b`, "gi");
1827
1870
  const commandMatches = code.match(commandPattern);
1828
1871
  if (!semanticInfo?.usedSemanticParsing) {
1829
1872
  const toggleVariants = ["toggle"];
@@ -5541,7 +5584,7 @@ var compilationTools = [
5541
5584
  },
5542
5585
  {
5543
5586
  name: "translate_code",
5544
- description: 'Translate hyperscript between any of 24 languages via full semantic parsing \u2014 deterministic grammar transformation (SVO/SOV/VSO word order), not LLM translation. Every result carries a `verification` report (the output scored against the source via score_fidelity): verification.faithful === true is the claim "this rendering is structurally exact", so present it alongside the translation when showing code to a user for review. Higher fidelity than translate_hyperscript; preferred for production translations.',
5587
+ description: 'Translate hyperscript between any of 24 languages via full semantic parsing \u2014 deterministic grammar transformation (SVO/SOV/VSO word order), not LLM translation. Every result carries a `verification` report (the output scored against the source via score_fidelity): verification.faithful === true is the claim "this rendering is structurally exact", so present it alongside the translation when showing code to a user for review. A variable the target language reads as a pronoun or another value word (tl `ako` is `me`) comes back as a NAME_COLLISION warning with a rename: rename it in the source and translate again. Higher fidelity than translate_hyperscript; preferred for production translations.',
5545
5588
  inputSchema: {
5546
5589
  type: "object",
5547
5590
  properties: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperfixi/mcp-server",
3
- "version": "3.1.1",
3
+ "version": "3.3.0",
4
4
  "description": "Model Context Protocol server for HyperFixi hyperscript development",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -13,7 +13,7 @@
13
13
  "start": "node dist/index.js",
14
14
  "dev": "tsx src/index.ts",
15
15
  "dev:watch": "tsx watch src/index.ts",
16
- "pretest": "../../scripts/ensure-fresh.sh ../compilation-service ../semantic ../framework ../intent ../planner",
16
+ "pretest": "../../scripts/ensure-fresh.sh ../compilation-service ../semantic ../framework ../intent ../planner ../patterns-reference",
17
17
  "test": "vitest",
18
18
  "typecheck": "tsc --noEmit",
19
19
  "service:setup": "echo 'Copy com.lokascript.mcp-server.plist.example to com.lokascript.mcp-server.plist and update paths, then run service:install'",
@@ -37,22 +37,22 @@
37
37
  "author": "LokaScript Contributors",
38
38
  "license": "MIT",
39
39
  "dependencies": {
40
- "@hyperfixi/patterns-reference": "^3.1.1",
41
- "@lokascript/compilation-service": "^3.1.1",
40
+ "@hyperfixi/patterns-reference": "^3.3.0",
41
+ "@lokascript/compilation-service": "^3.3.0",
42
42
  "@lokascript/domains": "^3.0.0",
43
- "@lokascript/framework": "^3.1.1",
44
- "@lokascript/planner": "^3.1.1",
45
- "@lokascript/semantic": "^3.1.1",
46
- "@modelcontextprotocol/server": "^2.0.0",
47
- "yaml": "^2.8.3"
43
+ "@lokascript/framework": "^3.3.0",
44
+ "@lokascript/planner": "^3.3.0",
45
+ "@lokascript/semantic": "^3.3.0",
46
+ "@modelcontextprotocol/server": "^2.1.0",
47
+ "yaml": "^2.9.1"
48
48
  },
49
49
  "peerDependencies": {
50
- "@hyperfixi/core": "^3.1.1",
51
- "@hyperfixi/patterns-reference": "^3.1.1",
52
- "@hyperfixi/server-bridge": "^3.1.1",
53
- "@lokascript/compilation-service": "^3.1.1",
54
- "@lokascript/framework": "^3.1.1",
55
- "@lokascript/semantic": "^3.1.1"
50
+ "@hyperfixi/core": "^3.3.0",
51
+ "@hyperfixi/patterns-reference": "^3.3.0",
52
+ "@hyperfixi/server-bridge": "^3.3.0",
53
+ "@lokascript/compilation-service": "^3.3.0",
54
+ "@lokascript/framework": "^3.3.0",
55
+ "@lokascript/semantic": "^3.3.0"
56
56
  },
57
57
  "peerDependenciesMeta": {
58
58
  "@lokascript/compilation-service": {
@@ -75,17 +75,17 @@
75
75
  }
76
76
  },
77
77
  "devDependencies": {
78
- "@hyperfixi/core": "^3.1.1",
79
- "@hyperfixi/patterns-reference": "^3.1.1",
80
- "@hyperfixi/server-bridge": "^3.1.1",
81
- "@lokascript/compilation-service": "^3.1.1",
82
- "@lokascript/framework": "^3.1.1",
83
- "@lokascript/semantic": "^3.1.1",
84
- "@types/node": "^26.1.2",
78
+ "@hyperfixi/core": "^3.3.0",
79
+ "@hyperfixi/patterns-reference": "^3.3.0",
80
+ "@hyperfixi/server-bridge": "^3.3.0",
81
+ "@lokascript/compilation-service": "^3.3.0",
82
+ "@lokascript/framework": "^3.3.0",
83
+ "@lokascript/semantic": "^3.3.0",
84
+ "@types/node": "^26.6.3",
85
85
  "tsup": "^8.0.0",
86
- "tsx": "^4.23.1",
86
+ "tsx": "^4.23.15",
87
87
  "typescript": "^5.0.0",
88
- "vitest": "^4.1.5"
88
+ "vitest": "^5.0.2"
89
89
  },
90
90
  "files": [
91
91
  "dist",