@hyperfixi/mcp-server 3.1.1 → 3.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.
- package/README.md +6 -6
- package/dist/index.js +61 -18
- 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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
|
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:
|
|
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
|
-
|
|
1818
|
-
|
|
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
|
-
|
|
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.
|
|
3
|
+
"version": "3.2.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.
|
|
41
|
-
"@lokascript/compilation-service": "^3.
|
|
40
|
+
"@hyperfixi/patterns-reference": "^3.2.0",
|
|
41
|
+
"@lokascript/compilation-service": "^3.2.0",
|
|
42
42
|
"@lokascript/domains": "^3.0.0",
|
|
43
|
-
"@lokascript/framework": "^3.
|
|
44
|
-
"@lokascript/planner": "^3.
|
|
45
|
-
"@lokascript/semantic": "^3.
|
|
46
|
-
"@modelcontextprotocol/server": "^2.
|
|
47
|
-
"yaml": "^2.
|
|
43
|
+
"@lokascript/framework": "^3.2.0",
|
|
44
|
+
"@lokascript/planner": "^3.2.0",
|
|
45
|
+
"@lokascript/semantic": "^3.2.0",
|
|
46
|
+
"@modelcontextprotocol/server": "^2.1.0",
|
|
47
|
+
"yaml": "^2.9.1"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@hyperfixi/core": "^3.
|
|
51
|
-
"@hyperfixi/patterns-reference": "^3.
|
|
52
|
-
"@hyperfixi/server-bridge": "^3.
|
|
53
|
-
"@lokascript/compilation-service": "^3.
|
|
54
|
-
"@lokascript/framework": "^3.
|
|
55
|
-
"@lokascript/semantic": "^3.
|
|
50
|
+
"@hyperfixi/core": "^3.2.0",
|
|
51
|
+
"@hyperfixi/patterns-reference": "^3.2.0",
|
|
52
|
+
"@hyperfixi/server-bridge": "^3.2.0",
|
|
53
|
+
"@lokascript/compilation-service": "^3.2.0",
|
|
54
|
+
"@lokascript/framework": "^3.2.0",
|
|
55
|
+
"@lokascript/semantic": "^3.2.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.
|
|
79
|
-
"@hyperfixi/patterns-reference": "^3.
|
|
80
|
-
"@hyperfixi/server-bridge": "^3.
|
|
81
|
-
"@lokascript/compilation-service": "^3.
|
|
82
|
-
"@lokascript/framework": "^3.
|
|
83
|
-
"@lokascript/semantic": "^3.
|
|
84
|
-
"@types/node": "^26.
|
|
78
|
+
"@hyperfixi/core": "^3.2.0",
|
|
79
|
+
"@hyperfixi/patterns-reference": "^3.2.0",
|
|
80
|
+
"@hyperfixi/server-bridge": "^3.2.0",
|
|
81
|
+
"@lokascript/compilation-service": "^3.2.0",
|
|
82
|
+
"@lokascript/framework": "^3.2.0",
|
|
83
|
+
"@lokascript/semantic": "^3.2.0",
|
|
84
|
+
"@types/node": "^26.6.3",
|
|
85
85
|
"tsup": "^8.0.0",
|
|
86
|
-
"tsx": "^4.23.
|
|
86
|
+
"tsx": "^4.23.15",
|
|
87
87
|
"typescript": "^5.0.0",
|
|
88
|
-
"vitest": "^
|
|
88
|
+
"vitest": "^5.0.2"
|
|
89
89
|
},
|
|
90
90
|
"files": [
|
|
91
91
|
"dist",
|