@tempad-dev/mcp 0.2.1 → 0.3.1
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 +16 -0
- package/dist/hub.js +324 -215
- package/dist/hub.js.map +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,13 +13,29 @@
|
|
|
13
13
|
}
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
+
Quick setup helpers:
|
|
17
|
+
|
|
18
|
+
- VS Code / Cursor / TRAE: use the deep links in TemPad Dev (Preferences → MCP server).
|
|
19
|
+
- Windsurf: copy the JSON snippet from the same panel.
|
|
20
|
+
- CLI: `claude mcp add --transport stdio "TemPad Dev" -- npx -y @tempad-dev/mcp` or `codex mcp add "TemPad Dev" -- npx -y @tempad-dev/mcp`.
|
|
21
|
+
|
|
22
|
+
Supported tools/resources:
|
|
23
|
+
|
|
24
|
+
- `get_code`: Tailwind-first JSX/Vue markup plus assets and token references.
|
|
25
|
+
- `get_structure`: Hierarchy/geometry outline for the selection.
|
|
26
|
+
- `get_screenshot`: PNG capture with a downloadable asset link.
|
|
27
|
+
- `tempad-assets` resource template (`asset://tempad/{hash}`) for binaries referenced by tool responses.
|
|
28
|
+
|
|
16
29
|
## Configuration
|
|
17
30
|
|
|
18
31
|
Optional environment variables:
|
|
19
32
|
|
|
20
33
|
- `TEMPAD_MCP_TOOL_TIMEOUT`: Tool call timeout in milliseconds (default `15000`).
|
|
34
|
+
- `TEMPAD_MCP_AUTO_ACTIVATE_GRACE`: Delay before auto-activating the sole connected extension (default `1500`).
|
|
35
|
+
- `TEMPAD_MCP_MAX_ASSET_BYTES`: Maximum upload size for captured assets/screenshots in bytes (default `8388608`).
|
|
21
36
|
- `TEMPAD_MCP_RUNTIME_DIR`: Override runtime directory (defaults to system temp under `tempad-dev/run`).
|
|
22
37
|
- `TEMPAD_MCP_LOG_DIR`: Override log directory (defaults to system temp under `tempad-dev/log`).
|
|
38
|
+
- `TEMPAD_MCP_ASSET_DIR`: Override asset storage directory (defaults to system temp under `tempad-dev/assets`).
|
|
23
39
|
|
|
24
40
|
## Requirements
|
|
25
41
|
|
package/dist/hub.js
CHANGED
|
@@ -593,13 +593,47 @@ function cleanupAll() {
|
|
|
593
593
|
|
|
594
594
|
// src/tools.ts
|
|
595
595
|
import { z as z2 } from "zod";
|
|
596
|
+
|
|
597
|
+
// src/instructions.ts
|
|
598
|
+
var MCP_INSTRUCTIONS = `
|
|
599
|
+
## MCP Server Instructions (Design to Code)
|
|
600
|
+
|
|
601
|
+
You are connected to a Figma design file via the MCP server. Help convert design elements into code, preserving design intent and fitting the user\u2019s codebase conventions.
|
|
602
|
+
|
|
603
|
+
### P0 (must)
|
|
604
|
+
|
|
605
|
+
- Do not output \`data-hint*\` attributes. They are guidance only.
|
|
606
|
+
- For SVG/vector assets: use the exact provided asset (preserve \`path\` data and \`viewBox\`). Never redraw or approximate vectors.
|
|
607
|
+
|
|
608
|
+
### P1 (policy)
|
|
609
|
+
|
|
610
|
+
- Prefer calling \`get_structure\` early to understand hierarchy and layout intent.
|
|
611
|
+
- Treat \`get_code\` as the implementation baseline; refine it to match the current project\u2019s conventions.
|
|
612
|
+
- Use \`get_screenshot\` only when structure and hints cannot resolve major ambiguities, or to sanity-check the final result.
|
|
613
|
+
|
|
614
|
+
### Layout uncertainty (\`data-hint-auto-layout\`)
|
|
615
|
+
|
|
616
|
+
- If \`data-hint-auto-layout\` is \`none\` or \`inferred\`, treat layout as uncertain.
|
|
617
|
+
- Use \`get_structure\` geometry (positions, sizes, gaps, alignment, bounds) to choose layout. Prefer flex/grid when patterns support it; use absolute only when necessary.
|
|
618
|
+
|
|
619
|
+
### Component intent (\`data-hint-component\`)
|
|
620
|
+
|
|
621
|
+
- If \`data-hint-component\` suggests a reusable component/variant and repetition supports it, factor it into a component API (props/variants). Do not preserve the hint string in output.
|
|
622
|
+
|
|
623
|
+
### Assets and tokens
|
|
624
|
+
|
|
625
|
+
- If \`get_code\` references assets or tokens, handle them according to the current project\u2019s conventions (local asset paths, existing token/variable systems, theming rules).
|
|
626
|
+
`.trim();
|
|
627
|
+
|
|
628
|
+
// src/tools.ts
|
|
596
629
|
var GetCodeParametersSchema = z2.object({
|
|
597
|
-
nodeId: z2.string().optional(),
|
|
598
|
-
preferredLang: z2.enum(["jsx", "vue"]).optional(),
|
|
599
|
-
resolveTokens: z2.boolean().optional()
|
|
630
|
+
nodeId: z2.string().describe("Optional node id to target; defaults to the current single selection.").optional(),
|
|
631
|
+
preferredLang: z2.enum(["jsx", "vue"]).describe("Preferred output language; otherwise uses the design\u2019s hint/detected language, then JSX.").optional(),
|
|
632
|
+
resolveTokens: z2.boolean().describe("Resolve token references to concrete values; default false returns token metadata.").optional()
|
|
600
633
|
});
|
|
601
634
|
var GetTokenDefsParametersSchema = z2.object({
|
|
602
|
-
|
|
635
|
+
names: z2.array(z2.string().regex(/^--[a-zA-Z0-9-_]+$/)).min(1).describe("Canonical token names (CSS variable form) to resolve, e.g., --color-primary."),
|
|
636
|
+
includeAllModes: z2.boolean().describe("Include all token modes instead of just the active one; default false.").optional()
|
|
603
637
|
});
|
|
604
638
|
var AssetDescriptorSchema = z2.object({
|
|
605
639
|
hash: z2.string().min(1),
|
|
@@ -611,43 +645,179 @@ var AssetDescriptorSchema = z2.object({
|
|
|
611
645
|
height: z2.number().int().positive().optional()
|
|
612
646
|
});
|
|
613
647
|
var GetScreenshotParametersSchema = z2.object({
|
|
614
|
-
nodeId: z2.string().optional()
|
|
648
|
+
nodeId: z2.string().describe("Optional node id to screenshot; defaults to the current single selection.").optional()
|
|
615
649
|
});
|
|
616
650
|
var GetStructureParametersSchema = z2.object({
|
|
617
|
-
nodeId: z2.string().optional(),
|
|
651
|
+
nodeId: z2.string().describe("Optional node id to outline; defaults to the current single selection.").optional(),
|
|
618
652
|
options: z2.object({
|
|
619
|
-
depth: z2.number().int().positive().optional()
|
|
653
|
+
depth: z2.number().int().positive().describe("Limit traversal depth; defaults to full tree (subject to safety caps).").optional()
|
|
620
654
|
}).optional()
|
|
621
655
|
});
|
|
622
656
|
var GetAssetsParametersSchema = z2.object({
|
|
623
|
-
hashes: z2.array(z2.string().regex(MCP_HASH_PATTERN)).min(1)
|
|
657
|
+
hashes: z2.array(z2.string().regex(MCP_HASH_PATTERN)).min(1).describe("Asset hashes returned from other tools to download/resolve.")
|
|
624
658
|
});
|
|
625
659
|
var GetAssetsResultSchema = z2.object({
|
|
626
660
|
assets: z2.array(AssetDescriptorSchema),
|
|
627
661
|
missing: z2.array(z2.string().min(1))
|
|
628
662
|
});
|
|
629
|
-
|
|
630
|
-
|
|
663
|
+
function extTool(definition) {
|
|
664
|
+
return definition;
|
|
665
|
+
}
|
|
666
|
+
function hubTool(definition) {
|
|
667
|
+
return definition;
|
|
668
|
+
}
|
|
669
|
+
var TOOL_DEFS = [
|
|
670
|
+
extTool({
|
|
631
671
|
name: "get_code",
|
|
632
|
-
description: "
|
|
633
|
-
parameters: GetCodeParametersSchema
|
|
634
|
-
|
|
635
|
-
|
|
672
|
+
description: "Get a high-fidelity code snapshot for a nodeId (or current selection), including assets/usedTokens and `codegen` preset/config.",
|
|
673
|
+
parameters: GetCodeParametersSchema,
|
|
674
|
+
target: "extension",
|
|
675
|
+
format: createCodeToolResponse
|
|
676
|
+
}),
|
|
677
|
+
extTool({
|
|
636
678
|
name: "get_token_defs",
|
|
637
|
-
description: "
|
|
638
|
-
parameters: GetTokenDefsParametersSchema
|
|
639
|
-
|
|
640
|
-
|
|
679
|
+
description: "Resolve canonical token names to values (including modes) for tokens referenced by `get_code`.",
|
|
680
|
+
parameters: GetTokenDefsParametersSchema,
|
|
681
|
+
target: "extension",
|
|
682
|
+
exposed: false
|
|
683
|
+
}),
|
|
684
|
+
extTool({
|
|
641
685
|
name: "get_screenshot",
|
|
642
|
-
description: "
|
|
643
|
-
parameters: GetScreenshotParametersSchema
|
|
644
|
-
|
|
645
|
-
|
|
686
|
+
description: "Capture a rendered screenshot for a nodeId (or current selection) for visual verification.",
|
|
687
|
+
parameters: GetScreenshotParametersSchema,
|
|
688
|
+
target: "extension",
|
|
689
|
+
format: createScreenshotToolResponse
|
|
690
|
+
}),
|
|
691
|
+
extTool({
|
|
646
692
|
name: "get_structure",
|
|
647
|
-
description: "
|
|
648
|
-
parameters: GetStructureParametersSchema
|
|
649
|
-
|
|
693
|
+
description: "Get a structural + geometry outline for a nodeId (or current selection) to understand hierarchy and layout intent.",
|
|
694
|
+
parameters: GetStructureParametersSchema,
|
|
695
|
+
target: "extension"
|
|
696
|
+
}),
|
|
697
|
+
hubTool({
|
|
698
|
+
name: "get_assets",
|
|
699
|
+
description: "Resolve asset hashes to downloadable URLs/URIs for assets referenced by `get_code`.",
|
|
700
|
+
parameters: GetAssetsParametersSchema,
|
|
701
|
+
target: "hub",
|
|
702
|
+
outputSchema: GetAssetsResultSchema,
|
|
703
|
+
exposed: false
|
|
704
|
+
})
|
|
650
705
|
];
|
|
706
|
+
function createToolErrorResponse(toolName, error) {
|
|
707
|
+
const message = error instanceof Error ? error.message || "Unknown error occurred." : typeof error === "string" ? error : "Unknown error occurred.";
|
|
708
|
+
return {
|
|
709
|
+
content: [
|
|
710
|
+
{
|
|
711
|
+
type: "text",
|
|
712
|
+
text: `Tool "${toolName}" failed: ${message}`
|
|
713
|
+
}
|
|
714
|
+
]
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
function formatBytes(bytes) {
|
|
718
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
719
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
720
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
721
|
+
}
|
|
722
|
+
function createCodeToolResponse(payload) {
|
|
723
|
+
if (!isCodeResult(payload)) {
|
|
724
|
+
throw new Error("Invalid get_code payload received from extension.");
|
|
725
|
+
}
|
|
726
|
+
const summary = [];
|
|
727
|
+
const codeSize = Buffer.byteLength(payload.code, "utf8");
|
|
728
|
+
summary.push(`Generated ${payload.lang.toUpperCase()} snippet (${formatBytes(codeSize)}).`);
|
|
729
|
+
if (payload.message) {
|
|
730
|
+
summary.push(payload.message);
|
|
731
|
+
}
|
|
732
|
+
summary.push(
|
|
733
|
+
payload.assets.length ? `Assets attached: ${payload.assets.length}. Fetch bytes via resources/read using resourceUri.` : "No binary assets were attached to this response."
|
|
734
|
+
);
|
|
735
|
+
if (payload.usedTokens?.length) {
|
|
736
|
+
summary.push(`Token references included: ${payload.usedTokens.length}.`);
|
|
737
|
+
}
|
|
738
|
+
summary.push("Read structuredContent for the full code string and asset metadata.");
|
|
739
|
+
const assetLinks = payload.assets.length > 0 ? payload.assets.map((asset) => createAssetResourceLinkBlock(asset)) : [];
|
|
740
|
+
return {
|
|
741
|
+
content: [
|
|
742
|
+
{
|
|
743
|
+
type: "text",
|
|
744
|
+
text: summary.join("\n")
|
|
745
|
+
},
|
|
746
|
+
...assetLinks
|
|
747
|
+
],
|
|
748
|
+
structuredContent: payload
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
function createScreenshotToolResponse(payload) {
|
|
752
|
+
if (!isScreenshotResult(payload)) {
|
|
753
|
+
throw new Error("Invalid get_screenshot payload received from extension.");
|
|
754
|
+
}
|
|
755
|
+
const descriptionBlock = {
|
|
756
|
+
type: "text",
|
|
757
|
+
text: describeScreenshot(payload)
|
|
758
|
+
};
|
|
759
|
+
return {
|
|
760
|
+
content: [
|
|
761
|
+
descriptionBlock,
|
|
762
|
+
{
|
|
763
|
+
type: "text",
|
|
764
|
+
text: ``
|
|
765
|
+
},
|
|
766
|
+
createResourceLinkBlock(payload.asset, payload)
|
|
767
|
+
],
|
|
768
|
+
structuredContent: payload
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
function createResourceLinkBlock(asset, result) {
|
|
772
|
+
return {
|
|
773
|
+
type: "resource_link",
|
|
774
|
+
name: "Screenshot",
|
|
775
|
+
uri: asset.resourceUri,
|
|
776
|
+
mimeType: asset.mimeType,
|
|
777
|
+
description: `Screenshot ${result.width}x${result.height} @${result.scale}x - Download: ${asset.url}`
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
function describeScreenshot(result) {
|
|
781
|
+
return `Screenshot ${result.width}x${result.height} @${result.scale}x (${formatBytes(result.bytes)})`;
|
|
782
|
+
}
|
|
783
|
+
function isScreenshotResult(payload) {
|
|
784
|
+
if (typeof payload !== "object" || !payload) return false;
|
|
785
|
+
const candidate = payload;
|
|
786
|
+
return typeof candidate.asset === "object" && candidate.asset !== null && typeof candidate.width === "number" && typeof candidate.height === "number" && typeof candidate.scale === "number" && typeof candidate.bytes === "number" && typeof candidate.format === "string";
|
|
787
|
+
}
|
|
788
|
+
function isCodeResult(payload) {
|
|
789
|
+
if (typeof payload !== "object" || !payload) return false;
|
|
790
|
+
const candidate = payload;
|
|
791
|
+
return typeof candidate.code === "string" && typeof candidate.lang === "string" && Array.isArray(candidate.assets);
|
|
792
|
+
}
|
|
793
|
+
function createAssetResourceLinkBlock(asset) {
|
|
794
|
+
return {
|
|
795
|
+
type: "resource_link",
|
|
796
|
+
name: formatAssetResourceName(asset.hash),
|
|
797
|
+
uri: asset.resourceUri,
|
|
798
|
+
mimeType: asset.mimeType,
|
|
799
|
+
description: `${describeAsset(asset)} - Download: ${asset.url}`
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
function describeAsset(asset) {
|
|
803
|
+
return `${asset.mimeType} (${formatBytes(asset.size)})`;
|
|
804
|
+
}
|
|
805
|
+
function formatAssetResourceName(hash) {
|
|
806
|
+
return `asset:${hash.slice(0, 8)}`;
|
|
807
|
+
}
|
|
808
|
+
function coercePayloadToToolResponse(payload) {
|
|
809
|
+
if (payload && typeof payload === "object" && Array.isArray(payload.content)) {
|
|
810
|
+
return payload;
|
|
811
|
+
}
|
|
812
|
+
return {
|
|
813
|
+
content: [
|
|
814
|
+
{
|
|
815
|
+
type: "text",
|
|
816
|
+
text: typeof payload === "string" ? payload : JSON.stringify(payload, null, 2)
|
|
817
|
+
}
|
|
818
|
+
]
|
|
819
|
+
};
|
|
820
|
+
}
|
|
651
821
|
|
|
652
822
|
// src/hub.ts
|
|
653
823
|
var SHUTDOWN_TIMEOUT = 2e3;
|
|
@@ -656,7 +826,36 @@ var extensions = [];
|
|
|
656
826
|
var consumerCount = 0;
|
|
657
827
|
var autoActivateTimer = null;
|
|
658
828
|
var selectedWsPort = 0;
|
|
659
|
-
var mcp = new McpServer(
|
|
829
|
+
var mcp = new McpServer(
|
|
830
|
+
{ name: "tempad-dev-mcp", version: "0.1.0" },
|
|
831
|
+
MCP_INSTRUCTIONS ? { instructions: MCP_INSTRUCTIONS } : void 0
|
|
832
|
+
);
|
|
833
|
+
function enrichToolDefinition(tool) {
|
|
834
|
+
if (tool.target === "extension") {
|
|
835
|
+
return tool;
|
|
836
|
+
}
|
|
837
|
+
switch (tool.name) {
|
|
838
|
+
case "get_assets":
|
|
839
|
+
return {
|
|
840
|
+
...tool,
|
|
841
|
+
handler: handleGetAssets
|
|
842
|
+
};
|
|
843
|
+
default:
|
|
844
|
+
throw new Error("No handler configured for hub tool.");
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
var TOOL_DEFINITIONS = TOOL_DEFS.map(
|
|
848
|
+
(tool) => enrichToolDefinition(tool)
|
|
849
|
+
);
|
|
850
|
+
function hasFormatter(tool) {
|
|
851
|
+
return tool.target === "extension" && "format" in tool;
|
|
852
|
+
}
|
|
853
|
+
var TOOL_BY_NAME = Object.fromEntries(
|
|
854
|
+
TOOL_DEFINITIONS.map((tool) => [tool.name, tool])
|
|
855
|
+
);
|
|
856
|
+
function getToolDefinition(name) {
|
|
857
|
+
return TOOL_BY_NAME[name];
|
|
858
|
+
}
|
|
660
859
|
var assetStore = createAssetStore();
|
|
661
860
|
var assetHttpServer = createAssetHttpServer(assetStore);
|
|
662
861
|
await assetHttpServer.start();
|
|
@@ -666,8 +865,8 @@ function registerAssetResources() {
|
|
|
666
865
|
list: async () => ({
|
|
667
866
|
resources: assetStore.list().filter((record) => existsSync3(record.filePath)).map((record) => ({
|
|
668
867
|
uri: buildAssetResourceUri(record.hash),
|
|
669
|
-
name:
|
|
670
|
-
description: `${record.mimeType} (${
|
|
868
|
+
name: formatAssetResourceName2(record.hash),
|
|
869
|
+
description: `${record.mimeType} (${formatBytes2(record.size)})`,
|
|
671
870
|
mimeType: record.mimeType
|
|
672
871
|
}))
|
|
673
872
|
})
|
|
@@ -700,7 +899,7 @@ async function readAssetResource(hash) {
|
|
|
700
899
|
const estimatedSize = Math.ceil(stat.size / 3) * 4;
|
|
701
900
|
if (estimatedSize > maxPayloadBytes) {
|
|
702
901
|
throw new Error(
|
|
703
|
-
`Asset ${hash} is too large (${
|
|
902
|
+
`Asset ${hash} is too large (${formatBytes2(stat.size)}, encoded: ${formatBytes2(estimatedSize)}) to read via MCP protocol. Use HTTP download.`
|
|
704
903
|
);
|
|
705
904
|
}
|
|
706
905
|
assetStore.touch(hash);
|
|
@@ -733,7 +932,7 @@ function isTextualMime(mimeType) {
|
|
|
733
932
|
function buildAssetResourceUri(hash) {
|
|
734
933
|
return `${MCP_ASSET_URI_PREFIX}${hash}`;
|
|
735
934
|
}
|
|
736
|
-
function
|
|
935
|
+
function formatAssetResourceName2(hash) {
|
|
737
936
|
return `asset:${hash.slice(0, 8)}`;
|
|
738
937
|
}
|
|
739
938
|
function buildAssetDescriptor(record) {
|
|
@@ -747,72 +946,36 @@ function buildAssetDescriptor(record) {
|
|
|
747
946
|
height: record.metadata?.height
|
|
748
947
|
};
|
|
749
948
|
}
|
|
750
|
-
function
|
|
949
|
+
function createAssetResourceLinkBlock2(asset) {
|
|
751
950
|
return {
|
|
752
951
|
type: "resource_link",
|
|
753
|
-
name:
|
|
952
|
+
name: formatAssetResourceName2(asset.hash),
|
|
754
953
|
uri: asset.resourceUri,
|
|
755
954
|
mimeType: asset.mimeType,
|
|
756
|
-
description: `${
|
|
955
|
+
description: `${describeAsset2(asset)} - Download: ${asset.url}`
|
|
757
956
|
};
|
|
758
957
|
}
|
|
759
|
-
function
|
|
760
|
-
return `${asset.mimeType} (${
|
|
958
|
+
function describeAsset2(asset) {
|
|
959
|
+
return `${asset.mimeType} (${formatBytes2(asset.size)})`;
|
|
761
960
|
}
|
|
762
|
-
function
|
|
763
|
-
|
|
764
|
-
|
|
961
|
+
function registerTools() {
|
|
962
|
+
const registered = [];
|
|
963
|
+
for (const tool of TOOL_DEFINITIONS) {
|
|
964
|
+
if ("exposed" in tool && tool.exposed === false) continue;
|
|
965
|
+
registerTool(tool);
|
|
966
|
+
registered.push(tool.name);
|
|
967
|
+
}
|
|
968
|
+
log.info({ tools: registered }, "Registered tools.");
|
|
969
|
+
}
|
|
970
|
+
registerTools();
|
|
971
|
+
function registerTool(tool) {
|
|
972
|
+
if (tool.target === "extension") {
|
|
973
|
+
registerProxiedTool(tool);
|
|
974
|
+
} else {
|
|
975
|
+
registerLocalTool(tool);
|
|
765
976
|
}
|
|
766
|
-
mcp.registerTool(
|
|
767
|
-
"get_assets",
|
|
768
|
-
{
|
|
769
|
-
description: "Resolve uploaded asset hashes to downloadable URLs and resource URIs for resources/read calls.",
|
|
770
|
-
inputSchema: GetAssetsParametersSchema,
|
|
771
|
-
outputSchema: GetAssetsResultSchema
|
|
772
|
-
},
|
|
773
|
-
async (args) => {
|
|
774
|
-
const { hashes } = GetAssetsParametersSchema.parse(args);
|
|
775
|
-
if (hashes.length > 100) {
|
|
776
|
-
throw new Error("Too many hashes requested. Limit is 100.");
|
|
777
|
-
}
|
|
778
|
-
const unique = Array.from(new Set(hashes));
|
|
779
|
-
const records = assetStore.getMany(unique).filter((record) => {
|
|
780
|
-
if (existsSync3(record.filePath)) return true;
|
|
781
|
-
assetStore.remove(record.hash, { removeFile: false });
|
|
782
|
-
return false;
|
|
783
|
-
});
|
|
784
|
-
const found = new Set(records.map((record) => record.hash));
|
|
785
|
-
const payload = GetAssetsResultSchema.parse({
|
|
786
|
-
assets: records.map((record) => buildAssetDescriptor(record)),
|
|
787
|
-
missing: unique.filter((hash) => !found.has(hash))
|
|
788
|
-
});
|
|
789
|
-
const summary = [];
|
|
790
|
-
summary.push(
|
|
791
|
-
payload.assets.length ? `Resolved ${payload.assets.length} asset${payload.assets.length === 1 ? "" : "s"}.` : "No assets were resolved for the requested hashes."
|
|
792
|
-
);
|
|
793
|
-
if (payload.missing.length) {
|
|
794
|
-
summary.push(`Missing: ${payload.missing.join(", ")}`);
|
|
795
|
-
}
|
|
796
|
-
summary.push(
|
|
797
|
-
"Use resources/read with each resourceUri or fetch the fallback URL to download bytes."
|
|
798
|
-
);
|
|
799
|
-
const content = [
|
|
800
|
-
{
|
|
801
|
-
type: "text",
|
|
802
|
-
text: summary.join("\n")
|
|
803
|
-
},
|
|
804
|
-
...payload.assets.map((asset) => createAssetResourceLinkBlock(asset))
|
|
805
|
-
];
|
|
806
|
-
return {
|
|
807
|
-
content,
|
|
808
|
-
structuredContent: payload
|
|
809
|
-
};
|
|
810
|
-
}
|
|
811
|
-
);
|
|
812
977
|
}
|
|
813
|
-
|
|
814
|
-
log.info({ tools: TOOLS.map((t) => t.name) }, "Registered tools.");
|
|
815
|
-
function registerExtensionTool(tool) {
|
|
978
|
+
function registerProxiedTool(tool) {
|
|
816
979
|
const schema = tool.parameters;
|
|
817
980
|
mcp.registerTool(
|
|
818
981
|
tool.name,
|
|
@@ -821,117 +984,100 @@ function registerExtensionTool(tool) {
|
|
|
821
984
|
inputSchema: schema
|
|
822
985
|
},
|
|
823
986
|
async (args) => {
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
987
|
+
try {
|
|
988
|
+
const parsedArgs = schema.parse(args);
|
|
989
|
+
const activeExt = extensions.find((e) => e.active);
|
|
990
|
+
if (!activeExt) throw new Error("No active TemPad Dev extension available.");
|
|
991
|
+
const { promise, requestId } = register(activeExt.id, toolTimeoutMs);
|
|
992
|
+
const message = {
|
|
993
|
+
type: "toolCall",
|
|
994
|
+
id: requestId,
|
|
995
|
+
payload: {
|
|
996
|
+
name: tool.name,
|
|
997
|
+
args: parsedArgs
|
|
998
|
+
}
|
|
999
|
+
};
|
|
1000
|
+
activeExt.ws.send(JSON.stringify(message));
|
|
1001
|
+
log.info({ tool: tool.name, req: requestId, extId: activeExt.id }, "Forwarded tool call.");
|
|
1002
|
+
const payload = await promise;
|
|
1003
|
+
return createToolResponse(tool.name, payload);
|
|
1004
|
+
} catch (error) {
|
|
1005
|
+
log.error({ tool: tool.name, error }, "Tool invocation failed before reaching extension.");
|
|
1006
|
+
return createToolErrorResponse(tool.name, error);
|
|
1007
|
+
}
|
|
840
1008
|
}
|
|
841
1009
|
);
|
|
842
1010
|
}
|
|
843
|
-
function
|
|
844
|
-
|
|
1011
|
+
function registerLocalTool(tool) {
|
|
1012
|
+
const schema = tool.parameters;
|
|
1013
|
+
const handler = tool.handler;
|
|
1014
|
+
const registrationOptions = {
|
|
1015
|
+
description: tool.description,
|
|
1016
|
+
inputSchema: schema
|
|
1017
|
+
};
|
|
1018
|
+
if (tool.outputSchema) {
|
|
1019
|
+
registrationOptions.outputSchema = tool.outputSchema;
|
|
1020
|
+
}
|
|
1021
|
+
mcp.registerTool(tool.name, registrationOptions, async (args) => {
|
|
845
1022
|
try {
|
|
846
|
-
|
|
1023
|
+
const parsed = schema.parse(args);
|
|
1024
|
+
return await handler(parsed);
|
|
847
1025
|
} catch (error) {
|
|
848
|
-
log.
|
|
849
|
-
return
|
|
1026
|
+
log.error({ tool: tool.name, error }, "Local tool invocation failed.");
|
|
1027
|
+
return createToolErrorResponse(tool.name, error);
|
|
850
1028
|
}
|
|
851
|
-
}
|
|
852
|
-
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
function createToolResponse(toolName, payload) {
|
|
1032
|
+
const definition = getToolDefinition(toolName);
|
|
1033
|
+
if (definition && hasFormatter(definition)) {
|
|
853
1034
|
try {
|
|
854
|
-
|
|
1035
|
+
const formatter = definition.format;
|
|
1036
|
+
return formatter(payload);
|
|
855
1037
|
} catch (error) {
|
|
856
|
-
log.warn({ error }, "Failed to format
|
|
1038
|
+
log.warn({ tool: toolName, error }, "Failed to format tool result; returning raw payload.");
|
|
857
1039
|
return coercePayloadToToolResponse(payload);
|
|
858
1040
|
}
|
|
859
1041
|
}
|
|
860
1042
|
return coercePayloadToToolResponse(payload);
|
|
861
1043
|
}
|
|
862
|
-
function
|
|
863
|
-
if (
|
|
864
|
-
|
|
865
|
-
}
|
|
866
|
-
return {
|
|
867
|
-
content: [
|
|
868
|
-
{
|
|
869
|
-
type: "text",
|
|
870
|
-
text: typeof payload === "string" ? payload : JSON.stringify(payload, null, 2)
|
|
871
|
-
}
|
|
872
|
-
]
|
|
873
|
-
};
|
|
874
|
-
}
|
|
875
|
-
function createCodeToolResponse(payload) {
|
|
876
|
-
if (!isCodeResult(payload)) {
|
|
877
|
-
throw new Error("Invalid get_code payload received from extension.");
|
|
1044
|
+
async function handleGetAssets({ hashes }) {
|
|
1045
|
+
if (hashes.length > 100) {
|
|
1046
|
+
throw new Error("Too many hashes requested. Limit is 100.");
|
|
878
1047
|
}
|
|
879
|
-
const
|
|
1048
|
+
const unique = Array.from(new Set(hashes));
|
|
1049
|
+
const records = assetStore.getMany(unique).filter((record) => {
|
|
1050
|
+
if (existsSync3(record.filePath)) return true;
|
|
1051
|
+
assetStore.remove(record.hash, { removeFile: false });
|
|
1052
|
+
return false;
|
|
1053
|
+
});
|
|
1054
|
+
const found = new Set(records.map((record) => record.hash));
|
|
1055
|
+
const payload = GetAssetsResultSchema.parse({
|
|
1056
|
+
assets: records.map((record) => buildAssetDescriptor(record)),
|
|
1057
|
+
missing: unique.filter((hash) => !found.has(hash))
|
|
1058
|
+
});
|
|
880
1059
|
const summary = [];
|
|
881
|
-
const codeSize = Buffer.byteLength(normalized.code, "utf8");
|
|
882
|
-
summary.push(`Generated ${normalized.lang.toUpperCase()} snippet (${formatBytes(codeSize)}).`);
|
|
883
|
-
if (normalized.message) {
|
|
884
|
-
summary.push(normalized.message);
|
|
885
|
-
}
|
|
886
1060
|
summary.push(
|
|
887
|
-
|
|
1061
|
+
payload.assets.length ? `Resolved ${payload.assets.length} asset${payload.assets.length === 1 ? "" : "s"}.` : "No assets were resolved for the requested hashes."
|
|
888
1062
|
);
|
|
889
|
-
if (
|
|
890
|
-
summary.push(`
|
|
1063
|
+
if (payload.missing.length) {
|
|
1064
|
+
summary.push(`Missing: ${payload.missing.join(", ")}`);
|
|
891
1065
|
}
|
|
892
|
-
summary.push(
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
}
|
|
903
|
-
function isCodeResult(payload) {
|
|
904
|
-
if (typeof payload !== "object" || !payload) return false;
|
|
905
|
-
const candidate = payload;
|
|
906
|
-
return typeof candidate.code === "string" && typeof candidate.lang === "string" && Array.isArray(candidate.assets);
|
|
907
|
-
}
|
|
908
|
-
function normalizeCodeResult(result) {
|
|
909
|
-
const updatedAssets = result.assets.map((asset) => enrichAssetDescriptor(asset));
|
|
910
|
-
const rewrittenCode = rewriteCodeAssetUrls(result.code, updatedAssets);
|
|
1066
|
+
summary.push(
|
|
1067
|
+
"Use resources/read with each resourceUri or fetch the fallback URL to download bytes."
|
|
1068
|
+
);
|
|
1069
|
+
const content = [
|
|
1070
|
+
{
|
|
1071
|
+
type: "text",
|
|
1072
|
+
text: summary.join("\n")
|
|
1073
|
+
},
|
|
1074
|
+
...payload.assets.map((asset) => createAssetResourceLinkBlock2(asset))
|
|
1075
|
+
];
|
|
911
1076
|
return {
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
assets: updatedAssets
|
|
1077
|
+
content,
|
|
1078
|
+
structuredContent: payload
|
|
915
1079
|
};
|
|
916
1080
|
}
|
|
917
|
-
function rewriteCodeAssetUrls(code, assets) {
|
|
918
|
-
let updatedCode = code;
|
|
919
|
-
for (const asset of assets) {
|
|
920
|
-
const uriPattern = new RegExp(escapeRegExp(asset.resourceUri), "g");
|
|
921
|
-
updatedCode = updatedCode.replace(uriPattern, asset.url);
|
|
922
|
-
}
|
|
923
|
-
return updatedCode;
|
|
924
|
-
}
|
|
925
|
-
function enrichAssetDescriptor(asset) {
|
|
926
|
-
const record = assetStore.get(asset.hash);
|
|
927
|
-
if (!record) {
|
|
928
|
-
return asset;
|
|
929
|
-
}
|
|
930
|
-
return buildAssetDescriptor(record);
|
|
931
|
-
}
|
|
932
|
-
function escapeRegExp(value) {
|
|
933
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
934
|
-
}
|
|
935
1081
|
function getActiveId() {
|
|
936
1082
|
return extensions.find((e) => e.active)?.id ?? null;
|
|
937
1083
|
}
|
|
@@ -987,48 +1133,11 @@ function rawDataToBuffer(raw) {
|
|
|
987
1133
|
if (raw instanceof ArrayBuffer) return Buffer.from(raw);
|
|
988
1134
|
return Buffer.concat(raw);
|
|
989
1135
|
}
|
|
990
|
-
function
|
|
991
|
-
if (!isScreenshotResult(payload)) {
|
|
992
|
-
throw new Error("Invalid get_screenshot payload received from extension.");
|
|
993
|
-
}
|
|
994
|
-
const descriptionBlock = {
|
|
995
|
-
type: "text",
|
|
996
|
-
text: describeScreenshot(payload)
|
|
997
|
-
};
|
|
998
|
-
return {
|
|
999
|
-
content: [
|
|
1000
|
-
descriptionBlock,
|
|
1001
|
-
{
|
|
1002
|
-
type: "text",
|
|
1003
|
-
text: ``
|
|
1004
|
-
},
|
|
1005
|
-
createResourceLinkBlock(payload.asset, payload)
|
|
1006
|
-
],
|
|
1007
|
-
structuredContent: payload
|
|
1008
|
-
};
|
|
1009
|
-
}
|
|
1010
|
-
function createResourceLinkBlock(asset, result) {
|
|
1011
|
-
return {
|
|
1012
|
-
type: "resource_link",
|
|
1013
|
-
name: "Screenshot",
|
|
1014
|
-
uri: asset.resourceUri,
|
|
1015
|
-
mimeType: asset.mimeType,
|
|
1016
|
-
description: `Screenshot ${result.width}x${result.height} @${result.scale}x - Download: ${asset.url}`
|
|
1017
|
-
};
|
|
1018
|
-
}
|
|
1019
|
-
function describeScreenshot(result) {
|
|
1020
|
-
return `Screenshot ${result.width}x${result.height} @${result.scale}x (${formatBytes(result.bytes)})`;
|
|
1021
|
-
}
|
|
1022
|
-
function formatBytes(bytes) {
|
|
1136
|
+
function formatBytes2(bytes) {
|
|
1023
1137
|
if (bytes < 1024) return `${bytes} B`;
|
|
1024
1138
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1025
1139
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1026
1140
|
}
|
|
1027
|
-
function isScreenshotResult(payload) {
|
|
1028
|
-
if (typeof payload !== "object" || !payload) return false;
|
|
1029
|
-
const candidate = payload;
|
|
1030
|
-
return typeof candidate.asset === "object" && candidate.asset !== null && typeof candidate.width === "number" && typeof candidate.height === "number" && typeof candidate.scale === "number" && typeof candidate.bytes === "number" && typeof candidate.format === "string";
|
|
1031
|
-
}
|
|
1032
1141
|
function shutdown() {
|
|
1033
1142
|
log.info("Hub is shutting down...");
|
|
1034
1143
|
assetStore.flush();
|
package/dist/hub.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/hub.ts", "../../mcp/shared/constants.ts", "../src/asset-http-server.ts", "../src/config.ts", "../src/shared.ts", "../src/asset-store.ts", "../src/protocol.ts", "../src/request.ts", "../src/tools.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { RawData } from 'ws'\n\nimport { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { nanoid } from 'nanoid'\nimport { existsSync, rmSync, chmodSync, readFileSync, statSync } from 'node:fs'\nimport { createServer } from 'node:net'\nimport { WebSocketServer } from 'ws'\n\nimport type { AssetRecord, ExtensionConnection } from './types'\n\nimport {\n MCP_ASSET_RESOURCE_NAME,\n MCP_ASSET_URI_PREFIX,\n MCP_ASSET_URI_TEMPLATE\n} from '../../mcp/shared/constants'\nimport { createAssetHttpServer } from './asset-http-server'\nimport { createAssetStore } from './asset-store'\nimport { getMcpServerConfig } from './config'\nimport {\n MessageFromExtensionSchema,\n RegisteredMessage,\n StateMessage,\n ToolCallMessage,\n ToolResultMessage\n} from './protocol'\nimport { register, resolve, reject, cleanupForExtension, cleanupAll } from './request'\nimport { log, RUNTIME_DIR, SOCK_PATH, ensureDir } from './shared'\nimport {\n TOOLS,\n GetAssetsParametersSchema,\n GetAssetsResultSchema,\n type AssetDescriptor,\n type GetAssetsResult,\n type GetScreenshotResult,\n type ToolResultMap,\n type ToolName\n} from './tools'\n\nconst SHUTDOWN_TIMEOUT = 2000\nconst { wsPortCandidates, toolTimeoutMs, maxPayloadBytes, autoActivateGraceMs } =\n getMcpServerConfig()\n\nconst extensions: ExtensionConnection[] = []\nlet consumerCount = 0\ntype TimeoutHandle = ReturnType<typeof setTimeout>\nlet autoActivateTimer: TimeoutHandle | null = null\nlet selectedWsPort = 0\n\nconst mcp = new McpServer({ name: 'tempad-dev-mcp', version: '0.1.0' })\ntype McpInputSchema = Parameters<typeof mcp.registerTool>[1]['inputSchema']\ntype McpOutputSchema = Parameters<typeof mcp.registerTool>[1]['outputSchema']\ntype RegisteredTool = (typeof TOOLS)[number]\n\nconst assetStore = createAssetStore()\nconst assetHttpServer = createAssetHttpServer(assetStore)\nawait assetHttpServer.start()\nregisterAssetResources()\n\nfunction registerAssetResources(): void {\n const template = new ResourceTemplate(MCP_ASSET_URI_TEMPLATE, {\n list: async () => ({\n resources: assetStore\n .list()\n .filter((record) => existsSync(record.filePath))\n .map((record) => ({\n uri: buildAssetResourceUri(record.hash),\n name: formatAssetResourceName(record.hash),\n description: `${record.mimeType} (${formatBytes(record.size)})`,\n mimeType: record.mimeType\n }))\n })\n })\n\n mcp.registerResource(\n MCP_ASSET_RESOURCE_NAME,\n template,\n {\n description: 'Binary assets captured by the TemPad Dev hub.'\n },\n async (_uri, variables) => {\n const hash = typeof variables.hash === 'string' ? variables.hash : ''\n return readAssetResource(hash)\n }\n )\n}\n\nasync function readAssetResource(hash: string) {\n if (!hash) {\n throw new Error('Missing asset hash in resource URI.')\n }\n const record = assetStore.get(hash)\n if (!record) {\n throw new Error(`Asset ${hash} not found.`)\n }\n\n if (!existsSync(record.filePath)) {\n assetStore.remove(hash, { removeFile: false })\n throw new Error(`Asset ${hash} file is missing.`)\n }\n\n const stat = statSync(record.filePath)\n // Base64 encoding increases size by ~33% (4 bytes for every 3 bytes)\n const estimatedSize = Math.ceil(stat.size / 3) * 4\n if (estimatedSize > maxPayloadBytes) {\n throw new Error(\n `Asset ${hash} is too large (${formatBytes(stat.size)}, encoded: ${formatBytes(estimatedSize)}) to read via MCP protocol. Use HTTP download.`\n )\n }\n\n assetStore.touch(hash)\n const buffer = readFileSync(record.filePath)\n const resourceUri = buildAssetResourceUri(hash)\n\n if (isTextualMime(record.mimeType)) {\n return {\n contents: [\n {\n uri: resourceUri,\n mimeType: record.mimeType,\n text: buffer.toString('utf8')\n }\n ]\n }\n }\n\n return {\n contents: [\n {\n uri: resourceUri,\n mimeType: record.mimeType,\n blob: buffer.toString('base64')\n }\n ]\n }\n}\n\nfunction isTextualMime(mimeType: string): boolean {\n return mimeType === 'image/svg+xml' || mimeType.startsWith('text/')\n}\n\nfunction buildAssetResourceUri(hash: string): string {\n return `${MCP_ASSET_URI_PREFIX}${hash}`\n}\n\nfunction formatAssetResourceName(hash: string): string {\n return `asset:${hash.slice(0, 8)}`\n}\n\nfunction buildAssetDescriptor(record: AssetRecord): AssetDescriptor {\n return {\n hash: record.hash,\n url: `${assetHttpServer.getBaseUrl()}/assets/${record.hash}`,\n mimeType: record.mimeType,\n size: record.size,\n resourceUri: buildAssetResourceUri(record.hash),\n width: record.metadata?.width,\n height: record.metadata?.height\n }\n}\n\nfunction createAssetResourceLinkBlock(asset: AssetDescriptor) {\n return {\n type: 'resource_link' as const,\n name: formatAssetResourceName(asset.hash),\n uri: asset.resourceUri,\n mimeType: asset.mimeType,\n description: `${describeAsset(asset)} - Download: ${asset.url}`\n }\n}\n\nfunction describeAsset(asset: AssetDescriptor): string {\n return `${asset.mimeType} (${formatBytes(asset.size)})`\n}\n\nfunction registerHubTools(): void {\n for (const tool of TOOLS) {\n registerExtensionTool(tool)\n }\n\n mcp.registerTool(\n 'get_assets',\n {\n description:\n 'Resolve uploaded asset hashes to downloadable URLs and resource URIs for resources/read calls.',\n inputSchema: GetAssetsParametersSchema as unknown as McpInputSchema,\n outputSchema: GetAssetsResultSchema as unknown as McpOutputSchema\n },\n async (args: unknown) => {\n const { hashes } = GetAssetsParametersSchema.parse(args)\n if (hashes.length > 100) {\n throw new Error('Too many hashes requested. Limit is 100.')\n }\n const unique = Array.from(new Set(hashes))\n const records = assetStore.getMany(unique).filter((record) => {\n if (existsSync(record.filePath)) return true\n assetStore.remove(record.hash, { removeFile: false })\n return false\n })\n const found = new Set(records.map((record) => record.hash))\n const payload: GetAssetsResult = GetAssetsResultSchema.parse({\n assets: records.map((record) => buildAssetDescriptor(record)),\n missing: unique.filter((hash) => !found.has(hash))\n })\n\n const summary: string[] = []\n summary.push(\n payload.assets.length\n ? `Resolved ${payload.assets.length} asset${payload.assets.length === 1 ? '' : 's'}.`\n : 'No assets were resolved for the requested hashes.'\n )\n if (payload.missing.length) {\n summary.push(`Missing: ${payload.missing.join(', ')}`)\n }\n summary.push(\n 'Use resources/read with each resourceUri or fetch the fallback URL to download bytes.'\n )\n\n const content = [\n {\n type: 'text' as const,\n text: summary.join('\\n')\n },\n ...payload.assets.map((asset) => createAssetResourceLinkBlock(asset))\n ]\n\n return {\n content,\n structuredContent: payload\n }\n }\n )\n}\n\nregisterHubTools()\nlog.info({ tools: TOOLS.map((t) => t.name) }, 'Registered tools.')\nfunction registerExtensionTool<T extends RegisteredTool>(tool: T): void {\n type Name = T['name']\n type Result = ToolResultMap[Name]\n\n const schema = tool.parameters\n mcp.registerTool(\n tool.name,\n {\n description: tool.description,\n inputSchema: schema as unknown as McpInputSchema\n },\n async (args: unknown) => {\n const parsedArgs = schema.parse(args)\n const activeExt = extensions.find((e) => e.active)\n if (!activeExt) throw new Error('No active TemPad Dev extension available.')\n\n const { promise, requestId } = register<Result>(activeExt.id, toolTimeoutMs)\n\n const message: ToolCallMessage = {\n type: 'toolCall',\n id: requestId,\n payload: {\n name: tool.name,\n args: parsedArgs\n }\n }\n activeExt.ws.send(JSON.stringify(message))\n log.info({ tool: tool.name, req: requestId, extId: activeExt.id }, 'Forwarded tool call.')\n\n const payload = await promise\n return createToolResponse(tool.name, payload)\n }\n )\n}\n\ntype ToolResponse = CallToolResult\n\nfunction createToolResponse<Name extends ToolName>(\n toolName: Name,\n payload: ToolResultMap[Name]\n): ToolResponse {\n if (toolName === 'get_screenshot') {\n try {\n // TS cannot narrow ToolResultMap[Name] to the screenshot payload even though the tool name is literal.\n return createScreenshotToolResponse(payload as ToolResultMap['get_screenshot'])\n } catch (error) {\n log.warn({ error }, 'Failed to format get_screenshot result; returning raw payload.')\n return coercePayloadToToolResponse(payload)\n }\n }\n if (toolName === 'get_code') {\n try {\n return createCodeToolResponse(payload as ToolResultMap['get_code'])\n } catch (error) {\n log.warn({ error }, 'Failed to format get_code result; returning raw payload.')\n return coercePayloadToToolResponse(payload)\n }\n }\n\n return coercePayloadToToolResponse(payload)\n}\nfunction coercePayloadToToolResponse(payload: unknown): ToolResponse {\n if (payload && typeof payload === 'object' && Array.isArray((payload as ToolResponse).content)) {\n return payload as ToolResponse\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: typeof payload === 'string' ? payload : JSON.stringify(payload, null, 2)\n }\n ]\n }\n}\n\nfunction createCodeToolResponse(payload: ToolResultMap['get_code']): ToolResponse {\n if (!isCodeResult(payload)) {\n throw new Error('Invalid get_code payload received from extension.')\n }\n\n const normalized = normalizeCodeResult(payload)\n const summary: string[] = []\n const codeSize = Buffer.byteLength(normalized.code, 'utf8')\n summary.push(`Generated ${normalized.lang.toUpperCase()} snippet (${formatBytes(codeSize)}).`)\n if (normalized.message) {\n summary.push(normalized.message)\n }\n summary.push(\n normalized.assets.length\n ? `Assets attached: ${normalized.assets.length}. Fetch bytes via resources/read using resourceUri or call get_assets.`\n : 'No binary assets were attached to this response.'\n )\n if (normalized.usedTokens?.length) {\n summary.push(`Token references included: ${normalized.usedTokens.length}.`)\n }\n summary.push('Read structuredContent for the full code string and asset metadata.')\n\n return {\n content: [\n {\n type: 'text' as const,\n text: summary.join('\\n')\n }\n ],\n structuredContent: normalized\n }\n}\n\nfunction isCodeResult(payload: unknown): payload is ToolResultMap['get_code'] {\n if (typeof payload !== 'object' || !payload) return false\n const candidate = payload as Partial<ToolResultMap['get_code'] & Record<string, unknown>>\n return (\n typeof candidate.code === 'string' &&\n typeof candidate.lang === 'string' &&\n Array.isArray(candidate.assets)\n )\n}\n\nfunction normalizeCodeResult(result: ToolResultMap['get_code']): ToolResultMap['get_code'] {\n const updatedAssets = result.assets.map((asset) => enrichAssetDescriptor(asset))\n const rewrittenCode = rewriteCodeAssetUrls(result.code, updatedAssets)\n return {\n ...result,\n code: rewrittenCode,\n assets: updatedAssets\n }\n}\n\nfunction rewriteCodeAssetUrls(code: string, assets: AssetDescriptor[]): string {\n let updatedCode = code\n for (const asset of assets) {\n // Replace asset:// URIs with the HTTP URL\n const uriPattern = new RegExp(escapeRegExp(asset.resourceUri), 'g')\n updatedCode = updatedCode.replace(uriPattern, asset.url)\n }\n return updatedCode\n}\n\nfunction enrichAssetDescriptor(asset: AssetDescriptor): AssetDescriptor {\n const record = assetStore.get(asset.hash)\n if (!record) {\n return asset\n }\n return buildAssetDescriptor(record)\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nfunction getActiveId(): string | null {\n return extensions.find((e) => e.active)?.id ?? null\n}\n\nfunction setActive(targetId: string | null): void {\n extensions.forEach((e) => {\n e.active = targetId !== null && e.id === targetId\n })\n}\n\nfunction clearAutoActivateTimer(): void {\n if (autoActivateTimer) {\n clearTimeout(autoActivateTimer)\n autoActivateTimer = null\n }\n}\n\nfunction scheduleAutoActivate(): void {\n clearAutoActivateTimer()\n\n if (extensions.length !== 1 || getActiveId()) {\n return\n }\n\n const target = extensions[0]\n autoActivateTimer = setTimeout(() => {\n autoActivateTimer = null\n if (extensions.length === 1 && !getActiveId()) {\n setActive(target.id)\n log.info({ id: target.id }, 'Auto-activated sole extension after grace period.')\n broadcastState()\n }\n }, autoActivateGraceMs)\n}\n\nfunction unrefTimer(timer: TimeoutHandle): void {\n if (typeof timer === 'object' && timer !== null) {\n const handle = timer as NodeJS.Timeout\n if (typeof handle.unref === 'function') {\n handle.unref()\n }\n }\n}\n\nfunction broadcastState(): void {\n const activeId = getActiveId()\n const message: StateMessage = {\n type: 'state',\n activeId,\n count: extensions.length,\n port: selectedWsPort,\n assetServerUrl: assetHttpServer.getBaseUrl()\n }\n extensions.forEach((ext) => ext.ws.send(JSON.stringify(message)))\n log.debug({ activeId, count: extensions.length }, 'Broadcasted state.')\n}\n\nfunction rawDataToBuffer(raw: RawData): Buffer {\n if (typeof raw === 'string') return Buffer.from(raw)\n if (Buffer.isBuffer(raw)) return raw\n if (raw instanceof ArrayBuffer) return Buffer.from(raw)\n return Buffer.concat(raw)\n}\n\nfunction createScreenshotToolResponse(payload: ToolResultMap['get_screenshot']): ToolResponse {\n if (!isScreenshotResult(payload)) {\n throw new Error('Invalid get_screenshot payload received from extension.')\n }\n\n const descriptionBlock = {\n type: 'text' as const,\n text: describeScreenshot(payload)\n }\n\n return {\n content: [\n descriptionBlock,\n {\n type: 'text' as const,\n text: ``\n },\n createResourceLinkBlock(payload.asset, payload)\n ],\n structuredContent: payload\n }\n}\n\nfunction createResourceLinkBlock(asset: AssetDescriptor, result: GetScreenshotResult) {\n return {\n type: 'resource_link' as const,\n name: 'Screenshot',\n uri: asset.resourceUri,\n mimeType: asset.mimeType,\n description: `Screenshot ${result.width}x${result.height} @${result.scale}x - Download: ${asset.url}`\n }\n}\n\nfunction describeScreenshot(result: GetScreenshotResult): string {\n return `Screenshot ${result.width}x${result.height} @${result.scale}x (${formatBytes(result.bytes)})`\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction isScreenshotResult(payload: unknown): payload is GetScreenshotResult {\n if (typeof payload !== 'object' || !payload) return false\n const candidate = payload as Partial<GetScreenshotResult & Record<string, unknown>>\n return (\n typeof candidate.asset === 'object' &&\n candidate.asset !== null &&\n typeof candidate.width === 'number' &&\n typeof candidate.height === 'number' &&\n typeof candidate.scale === 'number' &&\n typeof candidate.bytes === 'number' &&\n typeof candidate.format === 'string'\n )\n}\n\nfunction shutdown(): void {\n log.info('Hub is shutting down...')\n assetStore.flush()\n assetHttpServer.stop()\n netServer.close(() => log.info('Net server closed.'))\n wss?.close(() => log.info('WebSocket server closed.'))\n cleanupAll()\n const timer = setTimeout(() => {\n log.warn('Shutdown timed out. Forcing exit.')\n process.exit(1)\n }, SHUTDOWN_TIMEOUT)\n unrefTimer(timer)\n}\n\ntry {\n ensureDir(RUNTIME_DIR)\n if (process.platform !== 'win32' && existsSync(SOCK_PATH)) {\n log.warn({ sock: SOCK_PATH }, 'Removing stale socket file.')\n rmSync(SOCK_PATH)\n }\n} catch (error: unknown) {\n log.error({ err: error }, 'Failed to initialize runtime environment.')\n process.exit(1)\n}\n\nconst netServer = createServer((sock) => {\n consumerCount++\n log.info(`Consumer connected. Total: ${consumerCount}`)\n const transport = new StdioServerTransport(sock, sock)\n mcp.connect(transport).catch((err) => {\n log.error({ err }, 'Failed to attach MCP transport.')\n transport.close().catch((closeErr) => log.warn({ err: closeErr }, 'Transport close failed.'))\n sock.destroy()\n })\n sock.on('error', (err) => {\n log.warn({ err }, 'Consumer socket error.')\n transport.close().catch((closeErr) => log.warn({ err: closeErr }, 'Transport close failed.'))\n })\n sock.on('close', async () => {\n await transport.close()\n consumerCount--\n log.info(`Consumer disconnected. Remaining: ${consumerCount}`)\n if (consumerCount === 0) {\n log.info('Last consumer disconnected. Shutting down.')\n shutdown()\n }\n })\n})\nnetServer.on('error', (err) => {\n log.error({ err }, 'Net server error.')\n process.exit(1)\n})\nnetServer.listen(SOCK_PATH, () => {\n try {\n if (process.platform !== 'win32') chmodSync(SOCK_PATH, 0o600)\n } catch (err) {\n log.error({ err }, 'Failed to set socket permissions. Shutting down.')\n process.exit(1)\n }\n log.info({ sock: SOCK_PATH }, 'Hub socket ready.')\n})\n\nasync function startWebSocketServer(): Promise<{ wss: WebSocketServer; port: number }> {\n for (const candidate of wsPortCandidates) {\n const server = new WebSocketServer({\n host: '127.0.0.1',\n port: candidate,\n maxPayload: maxPayloadBytes\n })\n\n try {\n await new Promise<void>((resolve, reject) => {\n const onError = (err: NodeJS.ErrnoException) => {\n server.off('listening', onListening)\n reject(err)\n }\n const onListening = () => {\n server.off('error', onError)\n resolve()\n }\n server.once('error', onError)\n server.once('listening', onListening)\n })\n return { wss: server, port: candidate }\n } catch (err) {\n server.close()\n const errno = err as NodeJS.ErrnoException\n if (errno.code === 'EADDRINUSE') {\n log.warn({ port: candidate }, 'WebSocket port in use, trying next candidate.')\n continue\n }\n log.error({ err: errno, port: candidate }, 'Failed to start WebSocket server.')\n process.exit(1)\n }\n }\n\n log.error(\n { candidates: wsPortCandidates },\n 'Unable to start WebSocket server on any candidate port.'\n )\n process.exit(1)\n}\n\nconst { wss, port } = await startWebSocketServer()\nselectedWsPort = port\n\n// Add an error handler to prevent crashes from port conflicts, etc.\nwss.on('error', (err) => {\n log.error({ err }, 'WebSocket server critical error. Exiting.')\n process.exit(1)\n})\n\nwss.on('connection', (ws) => {\n const ext: ExtensionConnection = { id: nanoid(), ws, active: false }\n extensions.push(ext)\n log.info({ id: ext.id }, `Extension connected. Total: ${extensions.length}`)\n\n const message: RegisteredMessage = { type: 'registered', id: ext.id }\n ws.send(JSON.stringify(message))\n broadcastState()\n scheduleAutoActivate()\n\n ws.on('message', (raw: RawData, isBinary: boolean) => {\n if (isBinary) {\n log.warn({ extId: ext.id }, 'Unexpected binary message received.')\n return\n }\n\n const messageBuffer = rawDataToBuffer(raw)\n\n let parsedJson: unknown\n try {\n parsedJson = JSON.parse(messageBuffer.toString('utf-8'))\n } catch (e: unknown) {\n log.warn({ err: e, extId: ext.id }, 'Failed to parse message.')\n return\n }\n\n const parseResult = MessageFromExtensionSchema.safeParse(parsedJson)\n if (!parseResult.success) {\n log.warn({ error: parseResult.error.flatten(), extId: ext.id }, 'Invalid message shape.')\n return\n }\n const msg = parseResult.data\n\n switch (msg.type) {\n case 'activate': {\n setActive(ext.id)\n log.info({ id: ext.id }, 'Extension activated.')\n broadcastState()\n scheduleAutoActivate()\n break\n }\n case 'toolResult': {\n const { id, payload, error } = msg as ToolResultMessage\n if (error) {\n reject(id, error instanceof Error ? error : new Error(String(error)))\n } else {\n resolve(id, payload)\n }\n break\n }\n }\n })\n\n ws.on('close', () => {\n const index = extensions.findIndex((e) => e.id === ext.id)\n if (index > -1) extensions.splice(index, 1)\n\n log.info({ id: ext.id }, `Extension disconnected. Remaining: ${extensions.length}`)\n cleanupForExtension(ext.id)\n\n if (ext.active) {\n log.warn({ id: ext.id }, 'Active extension disconnected.')\n setActive(null)\n }\n\n broadcastState()\n scheduleAutoActivate()\n })\n})\n\nlog.info({ port: selectedWsPort }, 'WebSocket server ready.')\n\nprocess.on('SIGINT', shutdown)\nprocess.on('SIGTERM', shutdown)\n", "export const MCP_PORT_CANDIDATES = [6220, 7431, 8127]\n\n// Upper bound for MCP message payloads in bytes.\nexport const MCP_MAX_PAYLOAD_BYTES = 4 * 1024 * 1024\n\n// Default tool timeout used by the MCP hub (ms).\nexport const MCP_TOOL_TIMEOUT_MS = 15000\n\n// Grace period before auto-activating the sole extension (ms).\nexport const MCP_AUTO_ACTIVATE_GRACE_MS = 1500\n\n// Maximum allowed size for uploaded assets (bytes).\nexport const MCP_MAX_ASSET_BYTES = 8 * 1024 * 1024\n\nexport const MCP_ASSET_RESOURCE_NAME = 'tempad-assets'\nexport const MCP_ASSET_URI_PREFIX = 'asset://tempad/'\nexport const MCP_ASSET_URI_TEMPLATE = `${MCP_ASSET_URI_PREFIX}{hash}`\n\nexport const MCP_HASH_PATTERN = /^[a-f0-9]{64}$/i\n", "import { nanoid } from 'nanoid'\nimport { createHash } from 'node:crypto'\nimport {\n createReadStream,\n createWriteStream,\n existsSync,\n renameSync,\n statSync,\n unlinkSync\n} from 'node:fs'\nimport { createServer, type IncomingMessage, type ServerResponse } from 'node:http'\nimport { join } from 'node:path'\nimport { pipeline, Transform } from 'node:stream'\nimport { URL } from 'node:url'\n\nimport type { AssetStore } from './asset-store'\n\nimport { MCP_HASH_PATTERN } from '../../mcp/shared/constants'\nimport { getMcpServerConfig } from './config'\nimport { ASSET_DIR, log } from './shared'\n\nconst LOOPBACK_HOST = '127.0.0.1'\nconst { maxAssetSizeBytes } = getMcpServerConfig()\n\nexport interface AssetHttpServer {\n start(): Promise<void>\n stop(): void\n getBaseUrl(): string\n}\n\nexport function createAssetHttpServer(store: AssetStore): AssetHttpServer {\n const server = createServer(handleRequest)\n let port: number | null = null\n\n async function start(): Promise<void> {\n if (port !== null) return\n await new Promise<void>((resolve, reject) => {\n const onError = (error: Error) => {\n server.off('listening', onListening)\n reject(error)\n }\n const onListening = () => {\n server.off('error', onError)\n const address = server.address()\n if (address && typeof address === 'object') {\n port = address.port\n resolve()\n } else {\n reject(new Error('Failed to determine HTTP server port.'))\n }\n }\n server.once('error', onError)\n server.once('listening', onListening)\n server.listen(0, LOOPBACK_HOST)\n })\n log.info({ port }, 'Asset HTTP server ready.')\n }\n\n function stop(): void {\n if (port === null) return\n server.close()\n port = null\n }\n\n function getBaseUrl(): string {\n if (port === null) throw new Error('Asset HTTP server is not running.')\n return `http://${LOOPBACK_HOST}:${port}`\n }\n\n function handleRequest(req: IncomingMessage, res: ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Asset-Width, X-Asset-Height')\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204)\n res.end()\n return\n }\n\n if (!req.url) {\n res.writeHead(400)\n res.end('Missing URL')\n return\n }\n\n const url = new URL(req.url, getBaseUrl())\n const segments = url.pathname.split('/').filter(Boolean)\n if (segments.length !== 2 || segments[0] !== 'assets') {\n res.writeHead(404)\n res.end('Not Found')\n return\n }\n\n const hash = segments[1]\n\n if (req.method === 'POST') {\n handleUpload(req, res, hash)\n return\n }\n\n if (req.method === 'GET') {\n handleDownload(req, res, hash)\n return\n }\n\n res.writeHead(405)\n res.end('Method Not Allowed')\n }\n\n function handleDownload(req: IncomingMessage, res: ServerResponse, hash: string): void {\n const record = store.get(hash)\n if (!record) {\n res.writeHead(404)\n res.end('Not Found')\n return\n }\n\n let stat\n try {\n stat = statSync(record.filePath)\n } catch (error) {\n const err = error as NodeJS.ErrnoException\n if (err.code === 'ENOENT') {\n store.remove(hash, { removeFile: false })\n res.writeHead(404)\n res.end('Not Found')\n } else {\n log.error({ error, hash }, 'Failed to stat asset file.')\n res.writeHead(500)\n res.end('Internal Server Error')\n }\n return\n }\n\n res.writeHead(200, {\n 'Content-Type': record.mimeType,\n 'Content-Length': stat.size.toString(),\n 'Cache-Control': 'public, max-age=31536000, immutable'\n })\n\n const stream = createReadStream(record.filePath)\n stream.on('error', (error) => {\n log.warn({ error, hash }, 'Failed to stream asset file.')\n if (!res.headersSent) {\n res.writeHead(500)\n }\n res.end('Internal Server Error')\n })\n stream.on('open', () => {\n store.touch(hash)\n })\n stream.pipe(res)\n }\n\n function handleUpload(req: IncomingMessage, res: ServerResponse, hash: string): void {\n if (!MCP_HASH_PATTERN.test(hash)) {\n res.writeHead(400)\n res.end('Invalid Hash Format')\n return\n }\n\n const mimeType = req.headers['content-type'] || 'application/octet-stream'\n const filePath = join(ASSET_DIR, hash)\n\n const width = parseInt(req.headers['x-asset-width'] as string, 10)\n const height = parseInt(req.headers['x-asset-height'] as string, 10)\n const metadata =\n !isNaN(width) && !isNaN(height) && width > 0 && height > 0 ? { width, height } : undefined\n\n // If asset already exists and file is present, skip write\n if (store.has(hash) && existsSync(filePath)) {\n // Drain request to ensure connection is clean\n req.resume()\n\n const existing = store.get(hash)!\n let changed = false\n if (metadata) {\n existing.metadata = metadata\n changed = true\n }\n if (existing.mimeType !== mimeType) {\n existing.mimeType = mimeType\n changed = true\n }\n if (changed) {\n store.upsert(existing)\n }\n store.touch(hash)\n res.writeHead(200)\n res.end('OK')\n return\n }\n\n const tmpPath = `${filePath}.tmp.${nanoid()}`\n const writeStream = createWriteStream(tmpPath)\n const hasher = createHash('sha256')\n let size = 0\n\n const cleanup = () => {\n if (existsSync(tmpPath)) {\n try {\n unlinkSync(tmpPath)\n } catch (e) {\n log.warn({ error: e, tmpPath }, 'Failed to cleanup temp file.')\n }\n }\n }\n\n const monitor = new Transform({\n transform(chunk, encoding, callback) {\n size += chunk.length\n if (size > maxAssetSizeBytes) {\n callback(new Error('PayloadTooLarge'))\n return\n }\n hasher.update(chunk)\n callback(null, chunk)\n }\n })\n\n pipeline(req, monitor, writeStream, (err) => {\n if (err) {\n cleanup()\n if (err.message === 'PayloadTooLarge') {\n res.writeHead(413)\n res.end('Payload Too Large')\n } else if (err.code === 'ERR_STREAM_PREMATURE_CLOSE') {\n log.warn({ hash }, 'Upload request closed prematurely.')\n } else {\n log.error({ error: err, hash }, 'Upload pipeline failed.')\n if (!res.headersSent) {\n res.writeHead(500)\n res.end('Internal Server Error')\n }\n }\n return\n }\n\n const computedHash = hasher.digest('hex')\n if (computedHash !== hash) {\n cleanup()\n res.writeHead(400)\n res.end('Hash Mismatch')\n return\n }\n\n try {\n renameSync(tmpPath, filePath)\n } catch (error) {\n log.error({ error, hash }, 'Failed to rename temp file to asset.')\n cleanup()\n res.writeHead(500)\n res.end('Internal Server Error')\n return\n }\n\n store.upsert({\n hash,\n filePath,\n mimeType,\n size,\n metadata\n })\n log.info({ hash, size }, 'Stored uploaded asset via HTTP.')\n res.writeHead(201)\n res.end('Created')\n })\n }\n\n return {\n start,\n stop,\n getBaseUrl\n }\n}\n", "import {\n MCP_AUTO_ACTIVATE_GRACE_MS,\n MCP_MAX_ASSET_BYTES,\n MCP_MAX_PAYLOAD_BYTES,\n MCP_PORT_CANDIDATES,\n MCP_TOOL_TIMEOUT_MS\n} from '../../mcp/shared/constants'\n\nfunction parsePositiveInt(envValue: string | undefined, fallback: number): number {\n const parsed = envValue ? Number.parseInt(envValue, 10) : Number.NaN\n return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback\n}\n\nfunction resolveToolTimeoutMs(): number {\n return parsePositiveInt(process.env.TEMPAD_MCP_TOOL_TIMEOUT, MCP_TOOL_TIMEOUT_MS)\n}\n\nfunction resolveAutoActivateGraceMs(): number {\n return parsePositiveInt(process.env.TEMPAD_MCP_AUTO_ACTIVATE_GRACE, MCP_AUTO_ACTIVATE_GRACE_MS)\n}\n\nfunction resolveMaxAssetSizeBytes(): number {\n return parsePositiveInt(process.env.TEMPAD_MCP_MAX_ASSET_BYTES, MCP_MAX_ASSET_BYTES)\n}\n\nexport function getMcpServerConfig() {\n return {\n wsPortCandidates: [...MCP_PORT_CANDIDATES],\n toolTimeoutMs: resolveToolTimeoutMs(),\n maxPayloadBytes: MCP_MAX_PAYLOAD_BYTES,\n autoActivateGraceMs: resolveAutoActivateGraceMs(),\n maxAssetSizeBytes: resolveMaxAssetSizeBytes()\n }\n}\n", "import { closeSync, mkdirSync, openSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport pino from 'pino'\n\nexport function ensureDir(dirPath: string): void {\n mkdirSync(dirPath, { recursive: true, mode: 0o700 })\n}\n\nfunction resolveRuntimeDir(): string {\n if (process.env.TEMPAD_MCP_RUNTIME_DIR) return process.env.TEMPAD_MCP_RUNTIME_DIR\n return join(tmpdir(), 'tempad-dev', 'run')\n}\n\nfunction resolveLogDir(): string {\n if (process.env.TEMPAD_MCP_LOG_DIR) return process.env.TEMPAD_MCP_LOG_DIR\n return join(tmpdir(), 'tempad-dev', 'log')\n}\n\nfunction resolveAssetDir(): string {\n if (process.env.TEMPAD_MCP_ASSET_DIR) return process.env.TEMPAD_MCP_ASSET_DIR\n return join(tmpdir(), 'tempad-dev', 'assets')\n}\n\nexport const RUNTIME_DIR = resolveRuntimeDir()\nexport const LOG_DIR = resolveLogDir()\nexport const ASSET_DIR = resolveAssetDir()\n\nensureDir(RUNTIME_DIR)\nensureDir(LOG_DIR)\nensureDir(ASSET_DIR)\n\nexport function ensureFile(filePath: string): void {\n const fd = openSync(filePath, 'a')\n closeSync(fd)\n}\n\nexport const LOCK_PATH = join(RUNTIME_DIR, 'mcp.lock')\nensureFile(LOCK_PATH)\n\nconst timestamp = new Date().toISOString().replaceAll(':', '-').replaceAll('.', '-')\nconst pid = process.pid\nconst LOG_FILE = join(LOG_DIR, `mcp-${timestamp}-${pid}.log`)\n\nconst prettyTransport = pino.transport({\n target: 'pino-pretty',\n options: {\n translateTime: 'SYS:HH:MM:ss',\n destination: LOG_FILE\n }\n})\n\nexport const log = pino(\n {\n level: process.env.DEBUG ? 'debug' : 'info',\n msgPrefix: '[tempad-dev/mcp] '\n },\n prettyTransport\n)\n\nexport const SOCK_PATH =\n process.platform === 'win32' ? '\\\\\\\\.\\\\pipe\\\\tempad-mcp' : join(RUNTIME_DIR, 'mcp.sock')\n", "import { existsSync, readFileSync, rmSync, writeFileSync, readdirSync, statSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport type { AssetRecord } from './types'\n\nimport { ASSET_DIR, ensureDir, ensureFile, log } from './shared'\n\nconst INDEX_FILENAME = 'assets.json'\nconst DEFAULT_INDEX_PATH = join(ASSET_DIR, INDEX_FILENAME)\n\nexport interface AssetStoreOptions {\n indexPath?: string\n}\n\nexport interface AssetStore {\n list(): AssetRecord[]\n has(hash: string): boolean\n get(hash: string): AssetRecord | undefined\n getMany(hashes: string[]): AssetRecord[]\n upsert(\n input: Omit<AssetRecord, 'uploadedAt' | 'lastAccess'> &\n Partial<Pick<AssetRecord, 'uploadedAt' | 'lastAccess'>>\n ): AssetRecord\n touch(hash: string): AssetRecord | undefined\n remove(hash: string, opts?: { removeFile?: boolean }): void\n reconcile(): void\n flush(): void\n}\n\nfunction readIndex(indexPath: string): AssetRecord[] {\n if (!existsSync(indexPath)) return []\n try {\n const raw = readFileSync(indexPath, 'utf8').trim()\n if (!raw) return []\n const parsed = JSON.parse(raw)\n return Array.isArray(parsed) ? (parsed as AssetRecord[]) : []\n } catch (error) {\n log.warn({ error, indexPath }, 'Failed to read asset catalog; starting fresh.')\n return []\n }\n}\n\nfunction writeIndex(indexPath: string, values: AssetRecord[]): void {\n const payload = JSON.stringify(values, null, 2)\n writeFileSync(indexPath, payload, 'utf8')\n}\n\nexport function createAssetStore(options: AssetStoreOptions = {}): AssetStore {\n ensureDir(ASSET_DIR)\n const indexPath = options.indexPath ?? DEFAULT_INDEX_PATH\n ensureFile(indexPath)\n const records = new Map<string, AssetRecord>()\n let persistTimer: NodeJS.Timeout | null = null\n\n function loadExisting(): void {\n const list = readIndex(indexPath)\n for (const record of list) {\n if (record?.hash && record?.filePath) {\n records.set(record.hash, record)\n }\n }\n }\n\n function persist(): void {\n if (persistTimer) return\n persistTimer = setTimeout(() => {\n persistTimer = null\n writeIndex(indexPath, [...records.values()])\n }, 5000)\n if (typeof persistTimer.unref === 'function') {\n persistTimer.unref()\n }\n }\n\n function flush(): void {\n if (persistTimer) {\n clearTimeout(persistTimer)\n persistTimer = null\n }\n writeIndex(indexPath, [...records.values()])\n }\n\n function list(): AssetRecord[] {\n return [...records.values()]\n }\n\n function has(hash: string): boolean {\n return records.has(hash)\n }\n\n function get(hash: string): AssetRecord | undefined {\n return records.get(hash)\n }\n\n function getMany(hashes: string[]): AssetRecord[] {\n return hashes\n .map((hash) => records.get(hash))\n .filter((record): record is AssetRecord => !!record)\n }\n\n function upsert(\n input: Omit<AssetRecord, 'uploadedAt' | 'lastAccess'> &\n Partial<Pick<AssetRecord, 'uploadedAt' | 'lastAccess'>>\n ): AssetRecord {\n const now = Date.now()\n const record: AssetRecord = {\n ...input,\n uploadedAt: input.uploadedAt ?? now,\n lastAccess: input.lastAccess ?? now\n }\n records.set(record.hash, record)\n persist()\n return record\n }\n\n function touch(hash: string): AssetRecord | undefined {\n const existing = records.get(hash)\n if (!existing) return undefined\n existing.lastAccess = Date.now()\n persist()\n return existing\n }\n\n function remove(hash: string, { removeFile = true } = {}): void {\n const record = records.get(hash)\n if (!record) return\n records.delete(hash)\n persist()\n\n if (removeFile) {\n try {\n rmSync(record.filePath, { force: true })\n } catch (error) {\n log.warn({ hash, error }, 'Failed to remove asset file on delete.')\n }\n }\n }\n\n function reconcile(): void {\n let changed = false\n for (const [hash, record] of records) {\n if (!existsSync(record.filePath)) {\n records.delete(hash)\n changed = true\n }\n }\n\n try {\n const files = readdirSync(ASSET_DIR)\n const now = Date.now()\n for (const file of files) {\n if (file === INDEX_FILENAME) continue\n\n // Cleanup stale tmp files (> 1 hour)\n if (file.includes('.tmp.')) {\n try {\n const filePath = join(ASSET_DIR, file)\n const stat = statSync(filePath)\n if (now - stat.mtimeMs > 3600 * 1000) {\n rmSync(filePath, { force: true })\n log.info({ file }, 'Cleaned up stale temp file.')\n }\n } catch (e) {\n // Ignore errors during cleanup\n log.debug({ error: e, file }, 'Failed to cleanup stale temp file.')\n }\n continue\n }\n\n if (!/^[a-f0-9]{64}$/i.test(file)) continue\n\n if (!records.has(file)) {\n const filePath = join(ASSET_DIR, file)\n try {\n const stat = statSync(filePath)\n records.set(file, {\n hash: file,\n filePath,\n mimeType: 'application/octet-stream',\n size: stat.size,\n uploadedAt: stat.birthtimeMs,\n lastAccess: stat.atimeMs\n })\n changed = true\n log.info({ hash: file }, 'Recovered orphan asset file.')\n } catch (e) {\n log.warn({ error: e, file }, 'Failed to stat orphan file.')\n }\n }\n }\n } catch (error) {\n log.warn({ error }, 'Failed to scan asset directory for orphans.')\n }\n\n if (changed) flush()\n }\n\n loadExisting()\n reconcile()\n\n return {\n list,\n has,\n get,\n getMany,\n upsert,\n touch,\n remove,\n reconcile,\n flush\n }\n}\n", "import { z } from 'zod'\n\n// Messages from hub to extension\nexport const RegisteredMessageSchema = z.object({\n type: z.literal('registered'),\n id: z.string()\n})\n\nexport const StateMessageSchema = z.object({\n type: z.literal('state'),\n activeId: z.string().nullable(),\n count: z.number().nonnegative(),\n port: z.number().positive(),\n assetServerUrl: z.string().url()\n})\n\nexport const ToolCallPayloadSchema = z.object({\n name: z.string(),\n args: z.unknown()\n})\n\nexport const ToolCallMessageSchema = z.object({\n type: z.literal('toolCall'),\n id: z.string(),\n payload: ToolCallPayloadSchema\n})\n\nexport const MessageToExtensionSchema = z.discriminatedUnion('type', [\n RegisteredMessageSchema,\n StateMessageSchema,\n ToolCallMessageSchema\n])\n\n// Messages from extension to hub\nexport const ActivateMessageSchema = z.object({\n type: z.literal('activate')\n})\n\nexport const ToolResultMessageSchema = z.object({\n type: z.literal('toolResult'),\n id: z.string(),\n payload: z.unknown().optional(),\n error: z.unknown().optional()\n})\n\nexport const MessageFromExtensionSchema = z.discriminatedUnion('type', [\n ActivateMessageSchema,\n ToolResultMessageSchema\n])\n\nexport type RegisteredMessage = z.infer<typeof RegisteredMessageSchema>\nexport type StateMessage = z.infer<typeof StateMessageSchema>\nexport type ToolCallPayload = z.infer<typeof ToolCallPayloadSchema>\nexport type ToolCallMessage = z.infer<typeof ToolCallMessageSchema>\nexport type MessageToExtension = z.infer<typeof MessageToExtensionSchema>\nexport type ActivateMessage = z.infer<typeof ActivateMessageSchema>\nexport type ToolResultMessage = z.infer<typeof ToolResultMessageSchema>\nexport type MessageFromExtension = z.infer<typeof MessageFromExtensionSchema>\n\nexport function parseMessageToExtension(data: string): MessageToExtension | null {\n let parsed: unknown\n try {\n parsed = JSON.parse(data)\n } catch {\n return null\n }\n const result = MessageToExtensionSchema.safeParse(parsed)\n return result.success ? result.data : null\n}\n\nexport function parseMessageFromExtension(data: string): MessageFromExtension | null {\n let parsed: unknown\n try {\n parsed = JSON.parse(data)\n } catch {\n return null\n }\n const result = MessageFromExtensionSchema.safeParse(parsed)\n return result.success ? result.data : null\n}\n", "import { nanoid } from 'nanoid'\n\nimport type { PendingToolCall } from './types'\n\nimport { log } from './shared'\n\nconst pendingCalls = new Map<string, PendingToolCall>()\n\nexport function register<T>(\n extensionId: string,\n timeout: number\n): { promise: Promise<T>; requestId: string } {\n const requestId = nanoid()\n const promise = new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingCalls.delete(requestId)\n reject(new Error(`Extension did not respond within ${timeout / 1000}s.`))\n }, timeout)\n\n pendingCalls.set(requestId, {\n resolve: resolve as (value: unknown) => void,\n reject,\n timer,\n extensionId\n })\n })\n return { promise, requestId }\n}\n\nexport function resolve(requestId: string, payload: unknown): void {\n const call = pendingCalls.get(requestId)\n if (call) {\n const { timer, resolve: finish } = call\n clearTimeout(timer)\n finish(payload)\n pendingCalls.delete(requestId)\n } else {\n log.warn({ reqId: requestId }, 'Received result for unknown/timed-out call.')\n }\n}\n\nexport function reject(requestId: string, error: Error): void {\n const call = pendingCalls.get(requestId)\n if (call) {\n const { timer, reject: fail } = call\n clearTimeout(timer)\n fail(error)\n pendingCalls.delete(requestId)\n } else {\n log.warn({ reqId: requestId }, 'Received error for unknown/timed-out call.')\n }\n}\n\nexport function cleanupForExtension(extensionId: string): void {\n for (const [reqId, call] of pendingCalls.entries()) {\n const { timer, reject: fail, extensionId: extId } = call\n if (extId === extensionId) {\n clearTimeout(timer)\n fail(new Error('Extension disconnected before providing a result.'))\n pendingCalls.delete(reqId)\n log.warn({ reqId, extId: extensionId }, 'Rejected pending call from disconnected extension.')\n }\n }\n}\n\nexport function cleanupAll(): void {\n pendingCalls.forEach((call, reqId) => {\n const { timer, reject: fail } = call\n clearTimeout(timer)\n fail(new Error('Hub is shutting down.'))\n log.debug({ reqId }, 'Rejected pending tool call due to shutdown.')\n })\n pendingCalls.clear()\n}\n", "import { z } from 'zod'\n\nimport type { AssetDescriptor } from '../../mcp/shared/types'\n\nimport { MCP_HASH_PATTERN } from '../../mcp/shared/constants'\n\nexport type { AssetDescriptor }\n\n// get_code\nexport const GetCodeParametersSchema = z.object({\n nodeId: z.string().optional(),\n preferredLang: z.enum(['jsx', 'vue']).optional(),\n resolveTokens: z.boolean().optional()\n})\n\nexport type GetCodeParametersInput = z.input<typeof GetCodeParametersSchema>\nexport type GetCodeResult = {\n code: string\n lang: 'vue' | 'jsx'\n message?: string\n usedTokens?: GetTokenDefsResult['tokens']\n assets: AssetDescriptor[]\n}\n\n// get_token_defs\nexport const GetTokenDefsParametersSchema = z.object({\n nodeId: z.string().optional()\n})\n\nexport type GetTokenDefsParametersInput = z.input<typeof GetTokenDefsParametersSchema>\nexport type GetTokenDefsResult = {\n tokens: Array<{\n name: string\n value: string | Record<string, unknown>\n kind: 'color' | 'spacing' | 'typography' | 'effect' | 'other'\n }>\n}\n\nexport const AssetDescriptorSchema = z.object({\n hash: z.string().min(1),\n url: z.string().url(),\n mimeType: z.string().min(1),\n size: z.number().int().nonnegative(),\n resourceUri: z.string().regex(/^asset:\\/\\/tempad\\/[a-f0-9]{64}$/i),\n width: z.number().int().positive().optional(),\n height: z.number().int().positive().optional()\n})\n\n// get_screenshot\nexport const GetScreenshotParametersSchema = z.object({\n nodeId: z.string().optional()\n})\n\nexport type GetScreenshotParametersInput = z.input<typeof GetScreenshotParametersSchema>\nexport type GetScreenshotResult = {\n format: 'png'\n width: number\n height: number\n scale: number\n bytes: number\n asset: AssetDescriptor\n}\n\n// get_structure\nexport const GetStructureParametersSchema = z.object({\n nodeId: z.string().optional(),\n options: z\n .object({\n depth: z.number().int().positive().optional()\n })\n .optional()\n})\n\nexport type GetStructureParametersInput = z.input<typeof GetStructureParametersSchema>\nexport type OutlineNode = {\n id: string\n name: string\n type: string\n x: number\n y: number\n width: number\n height: number\n children?: OutlineNode[]\n}\nexport type GetStructureResult = {\n roots: OutlineNode[]\n}\n\n// get_assets (hub only)\nexport const GetAssetsParametersSchema = z.object({\n hashes: z.array(z.string().regex(MCP_HASH_PATTERN)).min(1)\n})\n\nexport const GetAssetsResultSchema = z.object({\n assets: z.array(AssetDescriptorSchema),\n missing: z.array(z.string().min(1))\n})\n\nexport type GetAssetsParametersInput = z.input<typeof GetAssetsParametersSchema>\nexport type GetAssetsResult = z.infer<typeof GetAssetsResultSchema>\n\nexport const TOOLS = [\n {\n name: 'get_code',\n description: 'High fidelity code snapshot for the current selection or provided node ids.',\n parameters: GetCodeParametersSchema\n },\n {\n name: 'get_token_defs',\n description: 'Token definitions referenced by the current selection or provided node ids.',\n parameters: GetTokenDefsParametersSchema\n },\n {\n name: 'get_screenshot',\n description: 'Rendered screenshot for the requested node.',\n parameters: GetScreenshotParametersSchema\n },\n {\n name: 'get_structure',\n description: 'Structural outline of the current selection or provided node ids.',\n parameters: GetStructureParametersSchema\n }\n] as const\n\nexport type ToolName = (typeof TOOLS)[number]['name']\n\nexport type ToolResultMap = {\n get_code: GetCodeResult\n get_token_defs: GetTokenDefsResult\n get_screenshot: GetScreenshotResult\n get_structure: GetStructureResult\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["nanoid", "existsSync", "rmSync", "readFileSync", "statSync", "createServer", "join", "port", "resolve", "reject", "join", "existsSync", "statSync", "join", "join", "existsSync", "list", "statSync", "nanoid", "nanoid", "resolve", "reject", "z", "z", "existsSync", "statSync", "readFileSync", "rmSync", "createServer", "resolve", "reject", "nanoid"]
|
|
3
|
+
"sources": ["../src/hub.ts", "../../mcp/shared/constants.ts", "../src/asset-http-server.ts", "../src/config.ts", "../src/shared.ts", "../src/asset-store.ts", "../src/protocol.ts", "../src/request.ts", "../src/tools.ts", "../src/instructions.ts"],
|
|
4
|
+
"sourcesContent": ["import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { RawData } from 'ws'\nimport type { ZodType } from 'zod'\n\nimport { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { nanoid } from 'nanoid'\nimport { existsSync, rmSync, chmodSync, readFileSync, statSync } from 'node:fs'\nimport { createServer } from 'node:net'\nimport { WebSocketServer } from 'ws'\n\nimport type {\n AssetDescriptor,\n GetAssetsParametersInput,\n GetAssetsResult,\n ToolResultMap,\n ToolName\n} from './tools'\nimport type { AssetRecord, ExtensionConnection } from './types'\n\nimport {\n MCP_ASSET_RESOURCE_NAME,\n MCP_ASSET_URI_PREFIX,\n MCP_ASSET_URI_TEMPLATE\n} from '../../mcp/shared/constants'\nimport { createAssetHttpServer } from './asset-http-server'\nimport { createAssetStore } from './asset-store'\nimport { getMcpServerConfig } from './config'\nimport {\n MessageFromExtensionSchema,\n RegisteredMessage,\n StateMessage,\n ToolCallMessage,\n ToolResultMessage\n} from './protocol'\nimport { register, resolve, reject, cleanupForExtension, cleanupAll } from './request'\nimport { log, RUNTIME_DIR, SOCK_PATH, ensureDir } from './shared'\nimport {\n GetAssetsResultSchema,\n TOOL_DEFS,\n MCP_INSTRUCTIONS,\n coercePayloadToToolResponse,\n createToolErrorResponse\n} from './tools'\n\nconst SHUTDOWN_TIMEOUT = 2000\nconst { wsPortCandidates, toolTimeoutMs, maxPayloadBytes, autoActivateGraceMs } =\n getMcpServerConfig()\n\nconst extensions: ExtensionConnection[] = []\nlet consumerCount = 0\ntype TimeoutHandle = ReturnType<typeof setTimeout>\nlet autoActivateTimer: TimeoutHandle | null = null\nlet selectedWsPort = 0\n\nconst mcp = new McpServer(\n { name: 'tempad-dev-mcp', version: '0.1.0' },\n MCP_INSTRUCTIONS ? { instructions: MCP_INSTRUCTIONS } : undefined\n)\ntype McpInputSchema = Parameters<typeof mcp.registerTool>[1]['inputSchema']\ntype McpOutputSchema = Parameters<typeof mcp.registerTool>[1]['outputSchema']\ntype ToolResponse = CallToolResult\ntype SchemaOutput<Schema extends ZodType> = Schema['_output']\ntype ToolMetadataEntry = (typeof TOOL_DEFS)[number]\ntype ExtensionToolMetadata = Extract<ToolMetadataEntry, { target: 'extension' }>\ntype HubToolMetadata = Extract<ToolMetadataEntry, { target: 'hub' }>\n\ntype HubToolWithHandler<T extends HubToolMetadata = HubToolMetadata> = T & {\n handler: (args: SchemaOutput<T['parameters']>) => Promise<ToolResponse>\n}\n\ntype RegisteredToolDefinition = ExtensionToolMetadata | HubToolWithHandler\n\nfunction enrichToolDefinition(tool: ToolMetadataEntry): RegisteredToolDefinition {\n if (tool.target === 'extension') {\n return tool\n }\n\n switch (tool.name) {\n case 'get_assets':\n return {\n ...tool,\n handler: handleGetAssets\n } satisfies HubToolWithHandler\n default:\n throw new Error('No handler configured for hub tool.')\n }\n}\n\nconst TOOL_DEFINITIONS: ReadonlyArray<RegisteredToolDefinition> = TOOL_DEFS.map((tool) =>\n enrichToolDefinition(tool)\n)\n\ntype RegisteredTool = (typeof TOOL_DEFINITIONS)[number]\ntype ExtensionTool = Extract<RegisteredTool, { target: 'extension' }>\ntype HubOnlyTool = Extract<RegisteredTool, { target: 'hub' }>\n\nfunction hasFormatter(tool: RegisteredToolDefinition): tool is ExtensionTool & {\n format: (payload: unknown) => ToolResponse\n} {\n return tool.target === 'extension' && 'format' in tool\n}\n\ntype ToolDefinitionByName = {\n [T in RegisteredToolDefinition as T['name']]: T\n}\n\nconst TOOL_BY_NAME: ToolDefinitionByName = Object.fromEntries(\n TOOL_DEFINITIONS.map((tool) => [tool.name, tool] as const)\n) as ToolDefinitionByName\n\nfunction getToolDefinition<Name extends ToolName>(name: Name): ToolDefinitionByName[Name] {\n return TOOL_BY_NAME[name]\n}\n\nconst assetStore = createAssetStore()\nconst assetHttpServer = createAssetHttpServer(assetStore)\nawait assetHttpServer.start()\nregisterAssetResources()\n\nfunction registerAssetResources(): void {\n const template = new ResourceTemplate(MCP_ASSET_URI_TEMPLATE, {\n list: async () => ({\n resources: assetStore\n .list()\n .filter((record) => existsSync(record.filePath))\n .map((record) => ({\n uri: buildAssetResourceUri(record.hash),\n name: formatAssetResourceName(record.hash),\n description: `${record.mimeType} (${formatBytes(record.size)})`,\n mimeType: record.mimeType\n }))\n })\n })\n\n mcp.registerResource(\n MCP_ASSET_RESOURCE_NAME,\n template,\n {\n description: 'Binary assets captured by the TemPad Dev hub.'\n },\n async (_uri, variables) => {\n const hash = typeof variables.hash === 'string' ? variables.hash : ''\n return readAssetResource(hash)\n }\n )\n}\n\nasync function readAssetResource(hash: string) {\n if (!hash) {\n throw new Error('Missing asset hash in resource URI.')\n }\n const record = assetStore.get(hash)\n if (!record) {\n throw new Error(`Asset ${hash} not found.`)\n }\n\n if (!existsSync(record.filePath)) {\n assetStore.remove(hash, { removeFile: false })\n throw new Error(`Asset ${hash} file is missing.`)\n }\n\n const stat = statSync(record.filePath)\n // Base64 encoding increases size by ~33% (4 bytes for every 3 bytes)\n const estimatedSize = Math.ceil(stat.size / 3) * 4\n if (estimatedSize > maxPayloadBytes) {\n throw new Error(\n `Asset ${hash} is too large (${formatBytes(stat.size)}, encoded: ${formatBytes(estimatedSize)}) to read via MCP protocol. Use HTTP download.`\n )\n }\n\n assetStore.touch(hash)\n const buffer = readFileSync(record.filePath)\n const resourceUri = buildAssetResourceUri(hash)\n\n if (isTextualMime(record.mimeType)) {\n return {\n contents: [\n {\n uri: resourceUri,\n mimeType: record.mimeType,\n text: buffer.toString('utf8')\n }\n ]\n }\n }\n\n return {\n contents: [\n {\n uri: resourceUri,\n mimeType: record.mimeType,\n blob: buffer.toString('base64')\n }\n ]\n }\n}\n\nfunction isTextualMime(mimeType: string): boolean {\n return mimeType === 'image/svg+xml' || mimeType.startsWith('text/')\n}\n\nfunction buildAssetResourceUri(hash: string): string {\n return `${MCP_ASSET_URI_PREFIX}${hash}`\n}\n\nfunction formatAssetResourceName(hash: string): string {\n return `asset:${hash.slice(0, 8)}`\n}\n\nfunction buildAssetDescriptor(record: AssetRecord): AssetDescriptor {\n return {\n hash: record.hash,\n url: `${assetHttpServer.getBaseUrl()}/assets/${record.hash}`,\n mimeType: record.mimeType,\n size: record.size,\n resourceUri: buildAssetResourceUri(record.hash),\n width: record.metadata?.width,\n height: record.metadata?.height\n }\n}\n\nfunction createAssetResourceLinkBlock(asset: AssetDescriptor) {\n return {\n type: 'resource_link' as const,\n name: formatAssetResourceName(asset.hash),\n uri: asset.resourceUri,\n mimeType: asset.mimeType,\n description: `${describeAsset(asset)} - Download: ${asset.url}`\n }\n}\n\nfunction describeAsset(asset: AssetDescriptor): string {\n return `${asset.mimeType} (${formatBytes(asset.size)})`\n}\n\nfunction registerTools(): void {\n const registered: string[] = []\n for (const tool of TOOL_DEFINITIONS) {\n if ('exposed' in tool && tool.exposed === false) continue\n registerTool(tool)\n registered.push(tool.name)\n }\n log.info({ tools: registered }, 'Registered tools.')\n}\n\nregisterTools()\nfunction registerTool(tool: RegisteredTool): void {\n if (tool.target === 'extension') {\n registerProxiedTool(tool)\n } else {\n registerLocalTool(tool)\n }\n}\n\nfunction registerProxiedTool<T extends ExtensionTool>(tool: T): void {\n type Name = T['name']\n type Result = ToolResultMap[Name]\n\n const schema = tool.parameters\n mcp.registerTool(\n tool.name,\n {\n description: tool.description,\n inputSchema: schema as unknown as McpInputSchema\n },\n async (args: unknown) => {\n try {\n const parsedArgs = schema.parse(args)\n const activeExt = extensions.find((e) => e.active)\n if (!activeExt) throw new Error('No active TemPad Dev extension available.')\n\n const { promise, requestId } = register<Result>(activeExt.id, toolTimeoutMs)\n\n const message: ToolCallMessage = {\n type: 'toolCall',\n id: requestId,\n payload: {\n name: tool.name,\n args: parsedArgs\n }\n }\n activeExt.ws.send(JSON.stringify(message))\n log.info({ tool: tool.name, req: requestId, extId: activeExt.id }, 'Forwarded tool call.')\n\n const payload = await promise\n return createToolResponse(tool.name, payload)\n } catch (error) {\n log.error({ tool: tool.name, error }, 'Tool invocation failed before reaching extension.')\n return createToolErrorResponse(tool.name, error)\n }\n }\n )\n}\n\nfunction registerLocalTool(tool: HubOnlyTool): void {\n const schema = tool.parameters\n const handler = tool.handler\n\n const registrationOptions: {\n description: string\n inputSchema: McpInputSchema\n outputSchema?: McpOutputSchema\n } = {\n description: tool.description,\n inputSchema: schema as unknown as McpInputSchema\n }\n\n if (tool.outputSchema) {\n registrationOptions.outputSchema = tool.outputSchema as unknown as McpOutputSchema\n }\n\n mcp.registerTool(tool.name, registrationOptions, async (args: unknown) => {\n try {\n const parsed = schema.parse(args)\n return await handler(parsed)\n } catch (error) {\n log.error({ tool: tool.name, error }, 'Local tool invocation failed.')\n return createToolErrorResponse(tool.name, error)\n }\n })\n}\n\nfunction createToolResponse<Name extends ToolName>(\n toolName: Name,\n payload: ToolResultMap[Name]\n): ToolResponse {\n const definition = getToolDefinition(toolName)\n if (definition && hasFormatter(definition)) {\n try {\n const formatter = definition.format as (input: ToolResultMap[Name]) => ToolResponse\n return formatter(payload)\n } catch (error) {\n log.warn({ tool: toolName, error }, 'Failed to format tool result; returning raw payload.')\n return coercePayloadToToolResponse(payload)\n }\n }\n\n return coercePayloadToToolResponse(payload)\n}\n\nasync function handleGetAssets({ hashes }: GetAssetsParametersInput): Promise<ToolResponse> {\n if (hashes.length > 100) {\n throw new Error('Too many hashes requested. Limit is 100.')\n }\n const unique = Array.from(new Set(hashes))\n const records = assetStore.getMany(unique).filter((record) => {\n if (existsSync(record.filePath)) return true\n assetStore.remove(record.hash, { removeFile: false })\n return false\n })\n const found = new Set(records.map((record) => record.hash))\n const payload: GetAssetsResult = GetAssetsResultSchema.parse({\n assets: records.map((record) => buildAssetDescriptor(record)),\n missing: unique.filter((hash) => !found.has(hash))\n })\n\n const summary: string[] = []\n summary.push(\n payload.assets.length\n ? `Resolved ${payload.assets.length} asset${payload.assets.length === 1 ? '' : 's'}.`\n : 'No assets were resolved for the requested hashes.'\n )\n if (payload.missing.length) {\n summary.push(`Missing: ${payload.missing.join(', ')}`)\n }\n summary.push(\n 'Use resources/read with each resourceUri or fetch the fallback URL to download bytes.'\n )\n\n const content = [\n {\n type: 'text' as const,\n text: summary.join('\\n')\n },\n ...payload.assets.map((asset) => createAssetResourceLinkBlock(asset))\n ]\n\n return {\n content,\n structuredContent: payload\n }\n}\n\nfunction getActiveId(): string | null {\n return extensions.find((e) => e.active)?.id ?? null\n}\n\nfunction setActive(targetId: string | null): void {\n extensions.forEach((e) => {\n e.active = targetId !== null && e.id === targetId\n })\n}\n\nfunction clearAutoActivateTimer(): void {\n if (autoActivateTimer) {\n clearTimeout(autoActivateTimer)\n autoActivateTimer = null\n }\n}\n\nfunction scheduleAutoActivate(): void {\n clearAutoActivateTimer()\n\n if (extensions.length !== 1 || getActiveId()) {\n return\n }\n\n const target = extensions[0]\n autoActivateTimer = setTimeout(() => {\n autoActivateTimer = null\n if (extensions.length === 1 && !getActiveId()) {\n setActive(target.id)\n log.info({ id: target.id }, 'Auto-activated sole extension after grace period.')\n broadcastState()\n }\n }, autoActivateGraceMs)\n}\n\nfunction unrefTimer(timer: TimeoutHandle): void {\n if (typeof timer === 'object' && timer !== null) {\n const handle = timer as NodeJS.Timeout\n if (typeof handle.unref === 'function') {\n handle.unref()\n }\n }\n}\n\nfunction broadcastState(): void {\n const activeId = getActiveId()\n const message: StateMessage = {\n type: 'state',\n activeId,\n count: extensions.length,\n port: selectedWsPort,\n assetServerUrl: assetHttpServer.getBaseUrl()\n }\n extensions.forEach((ext) => ext.ws.send(JSON.stringify(message)))\n log.debug({ activeId, count: extensions.length }, 'Broadcasted state.')\n}\n\nfunction rawDataToBuffer(raw: RawData): Buffer {\n if (typeof raw === 'string') return Buffer.from(raw)\n if (Buffer.isBuffer(raw)) return raw\n if (raw instanceof ArrayBuffer) return Buffer.from(raw)\n return Buffer.concat(raw)\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction shutdown(): void {\n log.info('Hub is shutting down...')\n assetStore.flush()\n assetHttpServer.stop()\n netServer.close(() => log.info('Net server closed.'))\n wss?.close(() => log.info('WebSocket server closed.'))\n cleanupAll()\n const timer = setTimeout(() => {\n log.warn('Shutdown timed out. Forcing exit.')\n process.exit(1)\n }, SHUTDOWN_TIMEOUT)\n unrefTimer(timer)\n}\n\ntry {\n ensureDir(RUNTIME_DIR)\n if (process.platform !== 'win32' && existsSync(SOCK_PATH)) {\n log.warn({ sock: SOCK_PATH }, 'Removing stale socket file.')\n rmSync(SOCK_PATH)\n }\n} catch (error: unknown) {\n log.error({ err: error }, 'Failed to initialize runtime environment.')\n process.exit(1)\n}\n\nconst netServer = createServer((sock) => {\n consumerCount++\n log.info(`Consumer connected. Total: ${consumerCount}`)\n const transport = new StdioServerTransport(sock, sock)\n mcp.connect(transport).catch((err) => {\n log.error({ err }, 'Failed to attach MCP transport.')\n transport.close().catch((closeErr) => log.warn({ err: closeErr }, 'Transport close failed.'))\n sock.destroy()\n })\n sock.on('error', (err) => {\n log.warn({ err }, 'Consumer socket error.')\n transport.close().catch((closeErr) => log.warn({ err: closeErr }, 'Transport close failed.'))\n })\n sock.on('close', async () => {\n await transport.close()\n consumerCount--\n log.info(`Consumer disconnected. Remaining: ${consumerCount}`)\n if (consumerCount === 0) {\n log.info('Last consumer disconnected. Shutting down.')\n shutdown()\n }\n })\n})\nnetServer.on('error', (err) => {\n log.error({ err }, 'Net server error.')\n process.exit(1)\n})\nnetServer.listen(SOCK_PATH, () => {\n try {\n if (process.platform !== 'win32') chmodSync(SOCK_PATH, 0o600)\n } catch (err) {\n log.error({ err }, 'Failed to set socket permissions. Shutting down.')\n process.exit(1)\n }\n log.info({ sock: SOCK_PATH }, 'Hub socket ready.')\n})\n\nasync function startWebSocketServer(): Promise<{ wss: WebSocketServer; port: number }> {\n for (const candidate of wsPortCandidates) {\n const server = new WebSocketServer({\n host: '127.0.0.1',\n port: candidate,\n maxPayload: maxPayloadBytes\n })\n\n try {\n await new Promise<void>((resolve, reject) => {\n const onError = (err: NodeJS.ErrnoException) => {\n server.off('listening', onListening)\n reject(err)\n }\n const onListening = () => {\n server.off('error', onError)\n resolve()\n }\n server.once('error', onError)\n server.once('listening', onListening)\n })\n return { wss: server, port: candidate }\n } catch (err) {\n server.close()\n const errno = err as NodeJS.ErrnoException\n if (errno.code === 'EADDRINUSE') {\n log.warn({ port: candidate }, 'WebSocket port in use, trying next candidate.')\n continue\n }\n log.error({ err: errno, port: candidate }, 'Failed to start WebSocket server.')\n process.exit(1)\n }\n }\n\n log.error(\n { candidates: wsPortCandidates },\n 'Unable to start WebSocket server on any candidate port.'\n )\n process.exit(1)\n}\n\nconst { wss, port } = await startWebSocketServer()\nselectedWsPort = port\n\n// Add an error handler to prevent crashes from port conflicts, etc.\nwss.on('error', (err) => {\n log.error({ err }, 'WebSocket server critical error. Exiting.')\n process.exit(1)\n})\n\nwss.on('connection', (ws) => {\n const ext: ExtensionConnection = { id: nanoid(), ws, active: false }\n extensions.push(ext)\n log.info({ id: ext.id }, `Extension connected. Total: ${extensions.length}`)\n\n const message: RegisteredMessage = { type: 'registered', id: ext.id }\n ws.send(JSON.stringify(message))\n broadcastState()\n scheduleAutoActivate()\n\n ws.on('message', (raw: RawData, isBinary: boolean) => {\n if (isBinary) {\n log.warn({ extId: ext.id }, 'Unexpected binary message received.')\n return\n }\n\n const messageBuffer = rawDataToBuffer(raw)\n\n let parsedJson: unknown\n try {\n parsedJson = JSON.parse(messageBuffer.toString('utf-8'))\n } catch (e: unknown) {\n log.warn({ err: e, extId: ext.id }, 'Failed to parse message.')\n return\n }\n\n const parseResult = MessageFromExtensionSchema.safeParse(parsedJson)\n if (!parseResult.success) {\n log.warn({ error: parseResult.error.flatten(), extId: ext.id }, 'Invalid message shape.')\n return\n }\n const msg = parseResult.data\n\n switch (msg.type) {\n case 'activate': {\n setActive(ext.id)\n log.info({ id: ext.id }, 'Extension activated.')\n broadcastState()\n scheduleAutoActivate()\n break\n }\n case 'toolResult': {\n const { id, payload, error } = msg as ToolResultMessage\n if (error) {\n reject(id, error instanceof Error ? error : new Error(String(error)))\n } else {\n resolve(id, payload)\n }\n break\n }\n }\n })\n\n ws.on('close', () => {\n const index = extensions.findIndex((e) => e.id === ext.id)\n if (index > -1) extensions.splice(index, 1)\n\n log.info({ id: ext.id }, `Extension disconnected. Remaining: ${extensions.length}`)\n cleanupForExtension(ext.id)\n\n if (ext.active) {\n log.warn({ id: ext.id }, 'Active extension disconnected.')\n setActive(null)\n }\n\n broadcastState()\n scheduleAutoActivate()\n })\n})\n\nlog.info({ port: selectedWsPort }, 'WebSocket server ready.')\n\nprocess.on('SIGINT', shutdown)\nprocess.on('SIGTERM', shutdown)\n", "export const MCP_PORT_CANDIDATES = [6220, 7431, 8127]\n\n// Upper bound for MCP message payloads in bytes.\nexport const MCP_MAX_PAYLOAD_BYTES = 4 * 1024 * 1024\n\n// Default tool timeout used by the MCP hub (ms).\nexport const MCP_TOOL_TIMEOUT_MS = 15000\n\n// Grace period before auto-activating the sole extension (ms).\nexport const MCP_AUTO_ACTIVATE_GRACE_MS = 1500\n\n// Maximum allowed size for uploaded assets (bytes).\nexport const MCP_MAX_ASSET_BYTES = 8 * 1024 * 1024\n\nexport const MCP_ASSET_RESOURCE_NAME = 'tempad-assets'\nexport const MCP_ASSET_URI_PREFIX = 'asset://tempad/'\nexport const MCP_ASSET_URI_TEMPLATE = `${MCP_ASSET_URI_PREFIX}{hash}`\n\nexport const MCP_HASH_PATTERN = /^[a-f0-9]{64}$/i\n", "import { nanoid } from 'nanoid'\nimport { createHash } from 'node:crypto'\nimport {\n createReadStream,\n createWriteStream,\n existsSync,\n renameSync,\n statSync,\n unlinkSync\n} from 'node:fs'\nimport { createServer, type IncomingMessage, type ServerResponse } from 'node:http'\nimport { join } from 'node:path'\nimport { pipeline, Transform } from 'node:stream'\nimport { URL } from 'node:url'\n\nimport type { AssetStore } from './asset-store'\n\nimport { MCP_HASH_PATTERN } from '../../mcp/shared/constants'\nimport { getMcpServerConfig } from './config'\nimport { ASSET_DIR, log } from './shared'\n\nconst LOOPBACK_HOST = '127.0.0.1'\nconst { maxAssetSizeBytes } = getMcpServerConfig()\n\nexport interface AssetHttpServer {\n start(): Promise<void>\n stop(): void\n getBaseUrl(): string\n}\n\nexport function createAssetHttpServer(store: AssetStore): AssetHttpServer {\n const server = createServer(handleRequest)\n let port: number | null = null\n\n async function start(): Promise<void> {\n if (port !== null) return\n await new Promise<void>((resolve, reject) => {\n const onError = (error: Error) => {\n server.off('listening', onListening)\n reject(error)\n }\n const onListening = () => {\n server.off('error', onError)\n const address = server.address()\n if (address && typeof address === 'object') {\n port = address.port\n resolve()\n } else {\n reject(new Error('Failed to determine HTTP server port.'))\n }\n }\n server.once('error', onError)\n server.once('listening', onListening)\n server.listen(0, LOOPBACK_HOST)\n })\n log.info({ port }, 'Asset HTTP server ready.')\n }\n\n function stop(): void {\n if (port === null) return\n server.close()\n port = null\n }\n\n function getBaseUrl(): string {\n if (port === null) throw new Error('Asset HTTP server is not running.')\n return `http://${LOOPBACK_HOST}:${port}`\n }\n\n function handleRequest(req: IncomingMessage, res: ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Asset-Width, X-Asset-Height')\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204)\n res.end()\n return\n }\n\n if (!req.url) {\n res.writeHead(400)\n res.end('Missing URL')\n return\n }\n\n const url = new URL(req.url, getBaseUrl())\n const segments = url.pathname.split('/').filter(Boolean)\n if (segments.length !== 2 || segments[0] !== 'assets') {\n res.writeHead(404)\n res.end('Not Found')\n return\n }\n\n const hash = segments[1]\n\n if (req.method === 'POST') {\n handleUpload(req, res, hash)\n return\n }\n\n if (req.method === 'GET') {\n handleDownload(req, res, hash)\n return\n }\n\n res.writeHead(405)\n res.end('Method Not Allowed')\n }\n\n function handleDownload(req: IncomingMessage, res: ServerResponse, hash: string): void {\n const record = store.get(hash)\n if (!record) {\n res.writeHead(404)\n res.end('Not Found')\n return\n }\n\n let stat\n try {\n stat = statSync(record.filePath)\n } catch (error) {\n const err = error as NodeJS.ErrnoException\n if (err.code === 'ENOENT') {\n store.remove(hash, { removeFile: false })\n res.writeHead(404)\n res.end('Not Found')\n } else {\n log.error({ error, hash }, 'Failed to stat asset file.')\n res.writeHead(500)\n res.end('Internal Server Error')\n }\n return\n }\n\n res.writeHead(200, {\n 'Content-Type': record.mimeType,\n 'Content-Length': stat.size.toString(),\n 'Cache-Control': 'public, max-age=31536000, immutable'\n })\n\n const stream = createReadStream(record.filePath)\n stream.on('error', (error) => {\n log.warn({ error, hash }, 'Failed to stream asset file.')\n if (!res.headersSent) {\n res.writeHead(500)\n }\n res.end('Internal Server Error')\n })\n stream.on('open', () => {\n store.touch(hash)\n })\n stream.pipe(res)\n }\n\n function handleUpload(req: IncomingMessage, res: ServerResponse, hash: string): void {\n if (!MCP_HASH_PATTERN.test(hash)) {\n res.writeHead(400)\n res.end('Invalid Hash Format')\n return\n }\n\n const mimeType = req.headers['content-type'] || 'application/octet-stream'\n const filePath = join(ASSET_DIR, hash)\n\n const width = parseInt(req.headers['x-asset-width'] as string, 10)\n const height = parseInt(req.headers['x-asset-height'] as string, 10)\n const metadata =\n !isNaN(width) && !isNaN(height) && width > 0 && height > 0 ? { width, height } : undefined\n\n // If asset already exists and file is present, skip write\n if (store.has(hash) && existsSync(filePath)) {\n // Drain request to ensure connection is clean\n req.resume()\n\n const existing = store.get(hash)!\n let changed = false\n if (metadata) {\n existing.metadata = metadata\n changed = true\n }\n if (existing.mimeType !== mimeType) {\n existing.mimeType = mimeType\n changed = true\n }\n if (changed) {\n store.upsert(existing)\n }\n store.touch(hash)\n res.writeHead(200)\n res.end('OK')\n return\n }\n\n const tmpPath = `${filePath}.tmp.${nanoid()}`\n const writeStream = createWriteStream(tmpPath)\n const hasher = createHash('sha256')\n let size = 0\n\n const cleanup = () => {\n if (existsSync(tmpPath)) {\n try {\n unlinkSync(tmpPath)\n } catch (e) {\n log.warn({ error: e, tmpPath }, 'Failed to cleanup temp file.')\n }\n }\n }\n\n const monitor = new Transform({\n transform(chunk, encoding, callback) {\n size += chunk.length\n if (size > maxAssetSizeBytes) {\n callback(new Error('PayloadTooLarge'))\n return\n }\n hasher.update(chunk)\n callback(null, chunk)\n }\n })\n\n pipeline(req, monitor, writeStream, (err) => {\n if (err) {\n cleanup()\n if (err.message === 'PayloadTooLarge') {\n res.writeHead(413)\n res.end('Payload Too Large')\n } else if (err.code === 'ERR_STREAM_PREMATURE_CLOSE') {\n log.warn({ hash }, 'Upload request closed prematurely.')\n } else {\n log.error({ error: err, hash }, 'Upload pipeline failed.')\n if (!res.headersSent) {\n res.writeHead(500)\n res.end('Internal Server Error')\n }\n }\n return\n }\n\n const computedHash = hasher.digest('hex')\n if (computedHash !== hash) {\n cleanup()\n res.writeHead(400)\n res.end('Hash Mismatch')\n return\n }\n\n try {\n renameSync(tmpPath, filePath)\n } catch (error) {\n log.error({ error, hash }, 'Failed to rename temp file to asset.')\n cleanup()\n res.writeHead(500)\n res.end('Internal Server Error')\n return\n }\n\n store.upsert({\n hash,\n filePath,\n mimeType,\n size,\n metadata\n })\n log.info({ hash, size }, 'Stored uploaded asset via HTTP.')\n res.writeHead(201)\n res.end('Created')\n })\n }\n\n return {\n start,\n stop,\n getBaseUrl\n }\n}\n", "import {\n MCP_AUTO_ACTIVATE_GRACE_MS,\n MCP_MAX_ASSET_BYTES,\n MCP_MAX_PAYLOAD_BYTES,\n MCP_PORT_CANDIDATES,\n MCP_TOOL_TIMEOUT_MS\n} from '../../mcp/shared/constants'\n\nfunction parsePositiveInt(envValue: string | undefined, fallback: number): number {\n const parsed = envValue ? Number.parseInt(envValue, 10) : Number.NaN\n return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback\n}\n\nfunction resolveToolTimeoutMs(): number {\n return parsePositiveInt(process.env.TEMPAD_MCP_TOOL_TIMEOUT, MCP_TOOL_TIMEOUT_MS)\n}\n\nfunction resolveAutoActivateGraceMs(): number {\n return parsePositiveInt(process.env.TEMPAD_MCP_AUTO_ACTIVATE_GRACE, MCP_AUTO_ACTIVATE_GRACE_MS)\n}\n\nfunction resolveMaxAssetSizeBytes(): number {\n return parsePositiveInt(process.env.TEMPAD_MCP_MAX_ASSET_BYTES, MCP_MAX_ASSET_BYTES)\n}\n\nexport function getMcpServerConfig() {\n return {\n wsPortCandidates: [...MCP_PORT_CANDIDATES],\n toolTimeoutMs: resolveToolTimeoutMs(),\n maxPayloadBytes: MCP_MAX_PAYLOAD_BYTES,\n autoActivateGraceMs: resolveAutoActivateGraceMs(),\n maxAssetSizeBytes: resolveMaxAssetSizeBytes()\n }\n}\n", "import { closeSync, mkdirSync, openSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport pino from 'pino'\n\nexport function ensureDir(dirPath: string): void {\n mkdirSync(dirPath, { recursive: true, mode: 0o700 })\n}\n\nfunction resolveRuntimeDir(): string {\n if (process.env.TEMPAD_MCP_RUNTIME_DIR) return process.env.TEMPAD_MCP_RUNTIME_DIR\n return join(tmpdir(), 'tempad-dev', 'run')\n}\n\nfunction resolveLogDir(): string {\n if (process.env.TEMPAD_MCP_LOG_DIR) return process.env.TEMPAD_MCP_LOG_DIR\n return join(tmpdir(), 'tempad-dev', 'log')\n}\n\nfunction resolveAssetDir(): string {\n if (process.env.TEMPAD_MCP_ASSET_DIR) return process.env.TEMPAD_MCP_ASSET_DIR\n return join(tmpdir(), 'tempad-dev', 'assets')\n}\n\nexport const RUNTIME_DIR = resolveRuntimeDir()\nexport const LOG_DIR = resolveLogDir()\nexport const ASSET_DIR = resolveAssetDir()\n\nensureDir(RUNTIME_DIR)\nensureDir(LOG_DIR)\nensureDir(ASSET_DIR)\n\nexport function ensureFile(filePath: string): void {\n const fd = openSync(filePath, 'a')\n closeSync(fd)\n}\n\nexport const LOCK_PATH = join(RUNTIME_DIR, 'mcp.lock')\nensureFile(LOCK_PATH)\n\nconst timestamp = new Date().toISOString().replaceAll(':', '-').replaceAll('.', '-')\nconst pid = process.pid\nconst LOG_FILE = join(LOG_DIR, `mcp-${timestamp}-${pid}.log`)\n\nconst prettyTransport = pino.transport({\n target: 'pino-pretty',\n options: {\n translateTime: 'SYS:HH:MM:ss',\n destination: LOG_FILE\n }\n})\n\nexport const log = pino(\n {\n level: process.env.DEBUG ? 'debug' : 'info',\n msgPrefix: '[tempad-dev/mcp] '\n },\n prettyTransport\n)\n\nexport const SOCK_PATH =\n process.platform === 'win32' ? '\\\\\\\\.\\\\pipe\\\\tempad-mcp' : join(RUNTIME_DIR, 'mcp.sock')\n", "import { existsSync, readFileSync, rmSync, writeFileSync, readdirSync, statSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport type { AssetRecord } from './types'\n\nimport { ASSET_DIR, ensureDir, ensureFile, log } from './shared'\n\nconst INDEX_FILENAME = 'assets.json'\nconst DEFAULT_INDEX_PATH = join(ASSET_DIR, INDEX_FILENAME)\n\nexport interface AssetStoreOptions {\n indexPath?: string\n}\n\nexport interface AssetStore {\n list(): AssetRecord[]\n has(hash: string): boolean\n get(hash: string): AssetRecord | undefined\n getMany(hashes: string[]): AssetRecord[]\n upsert(\n input: Omit<AssetRecord, 'uploadedAt' | 'lastAccess'> &\n Partial<Pick<AssetRecord, 'uploadedAt' | 'lastAccess'>>\n ): AssetRecord\n touch(hash: string): AssetRecord | undefined\n remove(hash: string, opts?: { removeFile?: boolean }): void\n reconcile(): void\n flush(): void\n}\n\nfunction readIndex(indexPath: string): AssetRecord[] {\n if (!existsSync(indexPath)) return []\n try {\n const raw = readFileSync(indexPath, 'utf8').trim()\n if (!raw) return []\n const parsed = JSON.parse(raw)\n return Array.isArray(parsed) ? (parsed as AssetRecord[]) : []\n } catch (error) {\n log.warn({ error, indexPath }, 'Failed to read asset catalog; starting fresh.')\n return []\n }\n}\n\nfunction writeIndex(indexPath: string, values: AssetRecord[]): void {\n const payload = JSON.stringify(values, null, 2)\n writeFileSync(indexPath, payload, 'utf8')\n}\n\nexport function createAssetStore(options: AssetStoreOptions = {}): AssetStore {\n ensureDir(ASSET_DIR)\n const indexPath = options.indexPath ?? DEFAULT_INDEX_PATH\n ensureFile(indexPath)\n const records = new Map<string, AssetRecord>()\n let persistTimer: NodeJS.Timeout | null = null\n\n function loadExisting(): void {\n const list = readIndex(indexPath)\n for (const record of list) {\n if (record?.hash && record?.filePath) {\n records.set(record.hash, record)\n }\n }\n }\n\n function persist(): void {\n if (persistTimer) return\n persistTimer = setTimeout(() => {\n persistTimer = null\n writeIndex(indexPath, [...records.values()])\n }, 5000)\n if (typeof persistTimer.unref === 'function') {\n persistTimer.unref()\n }\n }\n\n function flush(): void {\n if (persistTimer) {\n clearTimeout(persistTimer)\n persistTimer = null\n }\n writeIndex(indexPath, [...records.values()])\n }\n\n function list(): AssetRecord[] {\n return [...records.values()]\n }\n\n function has(hash: string): boolean {\n return records.has(hash)\n }\n\n function get(hash: string): AssetRecord | undefined {\n return records.get(hash)\n }\n\n function getMany(hashes: string[]): AssetRecord[] {\n return hashes\n .map((hash) => records.get(hash))\n .filter((record): record is AssetRecord => !!record)\n }\n\n function upsert(\n input: Omit<AssetRecord, 'uploadedAt' | 'lastAccess'> &\n Partial<Pick<AssetRecord, 'uploadedAt' | 'lastAccess'>>\n ): AssetRecord {\n const now = Date.now()\n const record: AssetRecord = {\n ...input,\n uploadedAt: input.uploadedAt ?? now,\n lastAccess: input.lastAccess ?? now\n }\n records.set(record.hash, record)\n persist()\n return record\n }\n\n function touch(hash: string): AssetRecord | undefined {\n const existing = records.get(hash)\n if (!existing) return undefined\n existing.lastAccess = Date.now()\n persist()\n return existing\n }\n\n function remove(hash: string, { removeFile = true } = {}): void {\n const record = records.get(hash)\n if (!record) return\n records.delete(hash)\n persist()\n\n if (removeFile) {\n try {\n rmSync(record.filePath, { force: true })\n } catch (error) {\n log.warn({ hash, error }, 'Failed to remove asset file on delete.')\n }\n }\n }\n\n function reconcile(): void {\n let changed = false\n for (const [hash, record] of records) {\n if (!existsSync(record.filePath)) {\n records.delete(hash)\n changed = true\n }\n }\n\n try {\n const files = readdirSync(ASSET_DIR)\n const now = Date.now()\n for (const file of files) {\n if (file === INDEX_FILENAME) continue\n\n // Cleanup stale tmp files (> 1 hour)\n if (file.includes('.tmp.')) {\n try {\n const filePath = join(ASSET_DIR, file)\n const stat = statSync(filePath)\n if (now - stat.mtimeMs > 3600 * 1000) {\n rmSync(filePath, { force: true })\n log.info({ file }, 'Cleaned up stale temp file.')\n }\n } catch (e) {\n // Ignore errors during cleanup\n log.debug({ error: e, file }, 'Failed to cleanup stale temp file.')\n }\n continue\n }\n\n if (!/^[a-f0-9]{64}$/i.test(file)) continue\n\n if (!records.has(file)) {\n const filePath = join(ASSET_DIR, file)\n try {\n const stat = statSync(filePath)\n records.set(file, {\n hash: file,\n filePath,\n mimeType: 'application/octet-stream',\n size: stat.size,\n uploadedAt: stat.birthtimeMs,\n lastAccess: stat.atimeMs\n })\n changed = true\n log.info({ hash: file }, 'Recovered orphan asset file.')\n } catch (e) {\n log.warn({ error: e, file }, 'Failed to stat orphan file.')\n }\n }\n }\n } catch (error) {\n log.warn({ error }, 'Failed to scan asset directory for orphans.')\n }\n\n if (changed) flush()\n }\n\n loadExisting()\n reconcile()\n\n return {\n list,\n has,\n get,\n getMany,\n upsert,\n touch,\n remove,\n reconcile,\n flush\n }\n}\n", "import { z } from 'zod'\n\n// Messages from hub to extension\nexport const RegisteredMessageSchema = z.object({\n type: z.literal('registered'),\n id: z.string()\n})\n\nexport const StateMessageSchema = z.object({\n type: z.literal('state'),\n activeId: z.string().nullable(),\n count: z.number().nonnegative(),\n port: z.number().positive(),\n assetServerUrl: z.string().url()\n})\n\nexport const ToolCallPayloadSchema = z.object({\n name: z.string(),\n args: z.unknown()\n})\n\nexport const ToolCallMessageSchema = z.object({\n type: z.literal('toolCall'),\n id: z.string(),\n payload: ToolCallPayloadSchema\n})\n\nexport const MessageToExtensionSchema = z.discriminatedUnion('type', [\n RegisteredMessageSchema,\n StateMessageSchema,\n ToolCallMessageSchema\n])\n\n// Messages from extension to hub\nexport const ActivateMessageSchema = z.object({\n type: z.literal('activate')\n})\n\nexport const ToolResultMessageSchema = z.object({\n type: z.literal('toolResult'),\n id: z.string(),\n payload: z.unknown().optional(),\n error: z.unknown().optional()\n})\n\nexport const MessageFromExtensionSchema = z.discriminatedUnion('type', [\n ActivateMessageSchema,\n ToolResultMessageSchema\n])\n\nexport type RegisteredMessage = z.infer<typeof RegisteredMessageSchema>\nexport type StateMessage = z.infer<typeof StateMessageSchema>\nexport type ToolCallPayload = z.infer<typeof ToolCallPayloadSchema>\nexport type ToolCallMessage = z.infer<typeof ToolCallMessageSchema>\nexport type MessageToExtension = z.infer<typeof MessageToExtensionSchema>\nexport type ActivateMessage = z.infer<typeof ActivateMessageSchema>\nexport type ToolResultMessage = z.infer<typeof ToolResultMessageSchema>\nexport type MessageFromExtension = z.infer<typeof MessageFromExtensionSchema>\n\nexport function parseMessageToExtension(data: string): MessageToExtension | null {\n let parsed: unknown\n try {\n parsed = JSON.parse(data)\n } catch {\n return null\n }\n const result = MessageToExtensionSchema.safeParse(parsed)\n return result.success ? result.data : null\n}\n\nexport function parseMessageFromExtension(data: string): MessageFromExtension | null {\n let parsed: unknown\n try {\n parsed = JSON.parse(data)\n } catch {\n return null\n }\n const result = MessageFromExtensionSchema.safeParse(parsed)\n return result.success ? result.data : null\n}\n", "import { nanoid } from 'nanoid'\n\nimport type { PendingToolCall } from './types'\n\nimport { log } from './shared'\n\nconst pendingCalls = new Map<string, PendingToolCall>()\n\nexport function register<T>(\n extensionId: string,\n timeout: number\n): { promise: Promise<T>; requestId: string } {\n const requestId = nanoid()\n const promise = new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingCalls.delete(requestId)\n reject(new Error(`Extension did not respond within ${timeout / 1000}s.`))\n }, timeout)\n\n pendingCalls.set(requestId, {\n resolve: resolve as (value: unknown) => void,\n reject,\n timer,\n extensionId\n })\n })\n return { promise, requestId }\n}\n\nexport function resolve(requestId: string, payload: unknown): void {\n const call = pendingCalls.get(requestId)\n if (call) {\n const { timer, resolve: finish } = call\n clearTimeout(timer)\n finish(payload)\n pendingCalls.delete(requestId)\n } else {\n log.warn({ reqId: requestId }, 'Received result for unknown/timed-out call.')\n }\n}\n\nexport function reject(requestId: string, error: Error): void {\n const call = pendingCalls.get(requestId)\n if (call) {\n const { timer, reject: fail } = call\n clearTimeout(timer)\n fail(error)\n pendingCalls.delete(requestId)\n } else {\n log.warn({ reqId: requestId }, 'Received error for unknown/timed-out call.')\n }\n}\n\nexport function cleanupForExtension(extensionId: string): void {\n for (const [reqId, call] of pendingCalls.entries()) {\n const { timer, reject: fail, extensionId: extId } = call\n if (extId === extensionId) {\n clearTimeout(timer)\n fail(new Error('Extension disconnected before providing a result.'))\n pendingCalls.delete(reqId)\n log.warn({ reqId, extId: extensionId }, 'Rejected pending call from disconnected extension.')\n }\n }\n}\n\nexport function cleanupAll(): void {\n pendingCalls.forEach((call, reqId) => {\n const { timer, reject: fail } = call\n clearTimeout(timer)\n fail(new Error('Hub is shutting down.'))\n log.debug({ reqId }, 'Rejected pending tool call due to shutdown.')\n })\n pendingCalls.clear()\n}\n", "import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { ZodType } from 'zod'\n\nimport { z } from 'zod'\n\nimport type { AssetDescriptor } from '../../mcp/shared/types'\n\nimport { MCP_HASH_PATTERN } from '../../mcp/shared/constants'\n\nexport type { AssetDescriptor }\n\n// get_code\nexport const GetCodeParametersSchema = z.object({\n nodeId: z\n .string()\n .describe('Optional node id to target; defaults to the current single selection.')\n .optional(),\n preferredLang: z\n .enum(['jsx', 'vue'])\n .describe('Preferred output language; otherwise uses the design\u2019s hint/detected language, then JSX.')\n .optional(),\n resolveTokens: z\n .boolean()\n .describe('Resolve token references to concrete values; default false returns token metadata.')\n .optional()\n})\n\nexport type GetCodeParametersInput = z.input<typeof GetCodeParametersSchema>\nexport type GetCodeResult = {\n code: string\n lang: 'vue' | 'jsx'\n message?: string\n usedTokens?: GetTokenDefsResult['tokens']\n assets: AssetDescriptor[]\n codegen: {\n preset: string\n config: {\n cssUnit: 'px' | 'rem'\n rootFontSize: number\n scale: number\n }\n }\n}\n\n// get_token_defs\nexport const GetTokenDefsParametersSchema = z.object({\n names: z\n .array(z.string().regex(/^--[a-zA-Z0-9-_]+$/))\n .min(1)\n .describe('Canonical token names (CSS variable form) to resolve, e.g., --color-primary.'),\n includeAllModes: z\n .boolean()\n .describe('Include all token modes instead of just the active one; default false.')\n .optional()\n})\n\nexport type GetTokenDefsParametersInput = z.input<typeof GetTokenDefsParametersSchema>\nexport type GetTokenDefsResult = {\n tokens: Array<{\n name: string\n value: string | Record<string, unknown> | null\n current: {\n modeId: string\n value?: string | Record<string, unknown>\n aliasTo?: string\n resolved: string | Record<string, unknown> | null\n aliasChain?: string[]\n }\n modes?: Array<{\n modeId: string\n value?: string | Record<string, unknown>\n aliasTo?: string\n resolved: string | Record<string, unknown> | null\n }>\n collection?: {\n id?: string\n name?: string\n activeModeId?: string\n defaultModeId?: string\n }\n kind: 'color' | 'spacing' | 'typography' | 'effect' | 'other'\n }>\n}\n\nexport const AssetDescriptorSchema = z.object({\n hash: z.string().min(1),\n url: z.string().url(),\n mimeType: z.string().min(1),\n size: z.number().int().nonnegative(),\n resourceUri: z.string().regex(/^asset:\\/\\/tempad\\/[a-f0-9]{64}$/i),\n width: z.number().int().positive().optional(),\n height: z.number().int().positive().optional()\n})\n\n// get_screenshot\nexport const GetScreenshotParametersSchema = z.object({\n nodeId: z\n .string()\n .describe('Optional node id to screenshot; defaults to the current single selection.')\n .optional()\n})\n\nexport type GetScreenshotParametersInput = z.input<typeof GetScreenshotParametersSchema>\nexport type GetScreenshotResult = {\n format: 'png'\n width: number\n height: number\n scale: number\n bytes: number\n asset: AssetDescriptor\n}\n\n// get_structure\nexport const GetStructureParametersSchema = z.object({\n nodeId: z\n .string()\n .describe('Optional node id to outline; defaults to the current single selection.')\n .optional(),\n options: z\n .object({\n depth: z\n .number()\n .int()\n .positive()\n .describe('Limit traversal depth; defaults to full tree (subject to safety caps).')\n .optional()\n })\n .optional()\n})\n\nexport type GetStructureParametersInput = z.input<typeof GetStructureParametersSchema>\nexport type OutlineNode = {\n id: string\n name: string\n type: string\n x: number\n y: number\n width: number\n height: number\n children?: OutlineNode[]\n}\nexport type GetStructureResult = {\n roots: OutlineNode[]\n}\n\n// get_assets (hub only)\nexport const GetAssetsParametersSchema = z.object({\n hashes: z\n .array(z.string().regex(MCP_HASH_PATTERN))\n .min(1)\n .describe('Asset hashes returned from other tools to download/resolve.')\n})\n\nexport const GetAssetsResultSchema = z.object({\n assets: z.array(AssetDescriptorSchema),\n missing: z.array(z.string().min(1))\n})\n\nexport type GetAssetsParametersInput = z.input<typeof GetAssetsParametersSchema>\nexport type GetAssetsResult = z.infer<typeof GetAssetsResultSchema>\n\nexport type ToolResultMap = {\n get_code: GetCodeResult\n get_token_defs: GetTokenDefsResult\n get_screenshot: GetScreenshotResult\n get_structure: GetStructureResult\n get_assets: GetAssetsResult\n}\n\nexport type ToolName = keyof ToolResultMap\n\nexport { MCP_INSTRUCTIONS } from './instructions'\n\ntype BaseToolMetadata<Name extends ToolName, Schema extends ZodType> = {\n name: Name\n description: string\n parameters: Schema\n exposed?: boolean\n format?: (payload: ToolResultMap[Name]) => CallToolResult\n}\n\ntype ExtensionToolMetadata<Name extends ToolName, Schema extends ZodType> = BaseToolMetadata<\n Name,\n Schema\n> & {\n target: 'extension'\n}\n\ntype HubToolMetadata<Name extends ToolName, Schema extends ZodType> = BaseToolMetadata<\n Name,\n Schema\n> & {\n target: 'hub'\n outputSchema?: ZodType\n}\n\nfunction extTool<Name extends ToolName, Schema extends ZodType>(\n definition: ExtensionToolMetadata<Name, Schema>\n): ExtensionToolMetadata<Name, Schema> {\n return definition\n}\n\nfunction hubTool<Name extends ToolName, Schema extends ZodType>(\n definition: HubToolMetadata<Name, Schema>\n): HubToolMetadata<Name, Schema> {\n return definition\n}\n\nexport const TOOL_DEFS = [\n extTool({\n name: 'get_code',\n description:\n 'Get a high-fidelity code snapshot for a nodeId (or current selection), including assets/usedTokens and `codegen` preset/config.',\n parameters: GetCodeParametersSchema,\n target: 'extension',\n format: createCodeToolResponse\n }),\n extTool({\n name: 'get_token_defs',\n description:\n 'Resolve canonical token names to values (including modes) for tokens referenced by `get_code`.',\n parameters: GetTokenDefsParametersSchema,\n target: 'extension',\n exposed: false\n }),\n extTool({\n name: 'get_screenshot',\n description:\n 'Capture a rendered screenshot for a nodeId (or current selection) for visual verification.',\n parameters: GetScreenshotParametersSchema,\n target: 'extension',\n format: createScreenshotToolResponse\n }),\n extTool({\n name: 'get_structure',\n description:\n 'Get a structural + geometry outline for a nodeId (or current selection) to understand hierarchy and layout intent.',\n parameters: GetStructureParametersSchema,\n target: 'extension'\n }),\n hubTool({\n name: 'get_assets',\n description:\n 'Resolve asset hashes to downloadable URLs/URIs for assets referenced by `get_code`.',\n parameters: GetAssetsParametersSchema,\n target: 'hub',\n outputSchema: GetAssetsResultSchema,\n exposed: false\n })\n] as const\n\nfunction createToolErrorResponse(toolName: string, error: unknown): CallToolResult {\n const message =\n error instanceof Error\n ? error.message || 'Unknown error occurred.'\n : typeof error === 'string'\n ? error\n : 'Unknown error occurred.'\n return {\n content: [\n {\n type: 'text' as const,\n text: `Tool \"${toolName}\" failed: ${message}`\n }\n ]\n }\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nexport function createCodeToolResponse(payload: ToolResultMap['get_code']): CallToolResult {\n if (!isCodeResult(payload)) {\n throw new Error('Invalid get_code payload received from extension.')\n }\n\n const summary: string[] = []\n const codeSize = Buffer.byteLength(payload.code, 'utf8')\n summary.push(`Generated ${payload.lang.toUpperCase()} snippet (${formatBytes(codeSize)}).`)\n if (payload.message) {\n summary.push(payload.message)\n }\n summary.push(\n payload.assets.length\n ? `Assets attached: ${payload.assets.length}. Fetch bytes via resources/read using resourceUri.`\n : 'No binary assets were attached to this response.'\n )\n if (payload.usedTokens?.length) {\n summary.push(`Token references included: ${payload.usedTokens.length}.`)\n }\n summary.push('Read structuredContent for the full code string and asset metadata.')\n\n const assetLinks =\n payload.assets.length > 0\n ? payload.assets.map((asset) => createAssetResourceLinkBlock(asset))\n : []\n\n return {\n content: [\n {\n type: 'text' as const,\n text: summary.join('\\n')\n },\n ...assetLinks\n ],\n structuredContent: payload\n }\n}\n\nexport function createScreenshotToolResponse(\n payload: ToolResultMap['get_screenshot']\n): CallToolResult {\n if (!isScreenshotResult(payload)) {\n throw new Error('Invalid get_screenshot payload received from extension.')\n }\n\n const descriptionBlock = {\n type: 'text' as const,\n text: describeScreenshot(payload)\n }\n\n return {\n content: [\n descriptionBlock,\n {\n type: 'text' as const,\n text: ``\n },\n createResourceLinkBlock(payload.asset, payload)\n ],\n structuredContent: payload\n }\n}\n\nfunction createResourceLinkBlock(asset: AssetDescriptor, result: GetScreenshotResult) {\n return {\n type: 'resource_link' as const,\n name: 'Screenshot',\n uri: asset.resourceUri,\n mimeType: asset.mimeType,\n description: `Screenshot ${result.width}x${result.height} @${result.scale}x - Download: ${asset.url}`\n }\n}\n\nfunction describeScreenshot(result: GetScreenshotResult): string {\n return `Screenshot ${result.width}x${result.height} @${result.scale}x (${formatBytes(result.bytes)})`\n}\n\nfunction isScreenshotResult(payload: unknown): payload is GetScreenshotResult {\n if (typeof payload !== 'object' || !payload) return false\n const candidate = payload as Partial<GetScreenshotResult & Record<string, unknown>>\n return (\n typeof candidate.asset === 'object' &&\n candidate.asset !== null &&\n typeof candidate.width === 'number' &&\n typeof candidate.height === 'number' &&\n typeof candidate.scale === 'number' &&\n typeof candidate.bytes === 'number' &&\n typeof candidate.format === 'string'\n )\n}\n\nfunction isCodeResult(payload: unknown): payload is ToolResultMap['get_code'] {\n if (typeof payload !== 'object' || !payload) return false\n const candidate = payload as Partial<ToolResultMap['get_code'] & Record<string, unknown>>\n return (\n typeof candidate.code === 'string' &&\n typeof candidate.lang === 'string' &&\n Array.isArray(candidate.assets)\n )\n}\n\nfunction createAssetResourceLinkBlock(asset: AssetDescriptor) {\n return {\n type: 'resource_link' as const,\n name: formatAssetResourceName(asset.hash),\n uri: asset.resourceUri,\n mimeType: asset.mimeType,\n description: `${describeAsset(asset)} - Download: ${asset.url}`\n }\n}\n\nfunction describeAsset(asset: AssetDescriptor): string {\n return `${asset.mimeType} (${formatBytes(asset.size)})`\n}\n\nfunction formatAssetResourceName(hash: string): string {\n return `asset:${hash.slice(0, 8)}`\n}\n\nexport function coercePayloadToToolResponse(payload: unknown): CallToolResult {\n if (\n payload &&\n typeof payload === 'object' &&\n Array.isArray((payload as CallToolResult).content)\n ) {\n return payload as CallToolResult\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: typeof payload === 'string' ? payload : JSON.stringify(payload, null, 2)\n }\n ]\n }\n}\n\nexport { createToolErrorResponse }\n", "export const MCP_INSTRUCTIONS = `\n## MCP Server Instructions (Design to Code)\n\nYou are connected to a Figma design file via the MCP server. Help convert design elements into code, preserving design intent and fitting the user\u2019s codebase conventions.\n\n### P0 (must)\n\n- Do not output \\`data-hint*\\` attributes. They are guidance only.\n- For SVG/vector assets: use the exact provided asset (preserve \\`path\\` data and \\`viewBox\\`). Never redraw or approximate vectors.\n\n### P1 (policy)\n\n- Prefer calling \\`get_structure\\` early to understand hierarchy and layout intent.\n- Treat \\`get_code\\` as the implementation baseline; refine it to match the current project\u2019s conventions.\n- Use \\`get_screenshot\\` only when structure and hints cannot resolve major ambiguities, or to sanity-check the final result.\n\n### Layout uncertainty (\\`data-hint-auto-layout\\`)\n\n- If \\`data-hint-auto-layout\\` is \\`none\\` or \\`inferred\\`, treat layout as uncertain.\n- Use \\`get_structure\\` geometry (positions, sizes, gaps, alignment, bounds) to choose layout. Prefer flex/grid when patterns support it; use absolute only when necessary.\n\n### Component intent (\\`data-hint-component\\`)\n\n- If \\`data-hint-component\\` suggests a reusable component/variant and repetition supports it, factor it into a component API (props/variants). Do not preserve the hint string in output.\n\n### Assets and tokens\n\n- If \\`get_code\\` references assets or tokens, handle them according to the current project\u2019s conventions (local asset paths, existing token/variable systems, theming rules).\n`.trim()\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["nanoid", "existsSync", "rmSync", "readFileSync", "statSync", "createServer", "join", "port", "resolve", "reject", "join", "existsSync", "statSync", "join", "join", "existsSync", "list", "statSync", "nanoid", "nanoid", "resolve", "reject", "z", "z", "existsSync", "formatAssetResourceName", "formatBytes", "statSync", "readFileSync", "createAssetResourceLinkBlock", "describeAsset", "rmSync", "createServer", "resolve", "reject", "nanoid"]
|
|
7
7
|
}
|