@tempad-dev/mcp 0.3.4 → 0.3.6
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/dist/cli.mjs +147 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/hub.mjs +4321 -0
- package/dist/hub.mjs.map +1 -0
- package/dist/instructions.md +11 -0
- package/dist/shared-DisdM-7P.mjs +92 -0
- package/dist/shared-DisdM-7P.mjs.map +1 -0
- package/package.json +15 -4
- package/dist/cli.js +0 -236
- package/dist/cli.js.map +0 -7
- package/dist/hub.js +0 -1328
- package/dist/hub.js.map +0 -7
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
You are connected to a Figma design file via the MCP server. Convert design elements into production code, preserving design intent while fitting the user’s codebase conventions.
|
|
2
|
+
|
|
3
|
+
- Start from `get_code` as the baseline, then refactor to match project conventions (components, styling system, file structure, naming).
|
|
4
|
+
- Layout confidence:
|
|
5
|
+
- If `get_code` contains no `data-hint-auto-layout`, it likely indicates the layout is explicit. You can be more confident implementing directly from `get_code`.
|
|
6
|
+
- If any `data-hint-auto-layout` is `none` or `inferred`, the corresponding layout may be uncertain. If you feel ambiguity or uncertainty, consult `get_structure` (hierarchy + geometry) and `get_screenshot` (visual intent such as layering/overlap/masks/shadows/translucency).
|
|
7
|
+
- If `data-hint-component` plus repetition supports it, extract reusable components/variants aligned with project patterns. Do not preserve hint strings in output.
|
|
8
|
+
- Tokens: follow the project’s token/theming framework; if needed, use `get_code.usedToken` metadata (collection, mode) to extend a responsive token system within that framework.
|
|
9
|
+
- Assets: follow the project’s existing conventions/practices (icon system, asset pipeline, import/path rules, optimization) to decide how to represent and reference assets. If `get_code` uses resource URIs, you may replace them with the project’s canonical references when appropriate without changing rendering.
|
|
10
|
+
- Do not output any `data-*` attributes returned by `get_code`.
|
|
11
|
+
- For SVG/vector assets: use the exact provided asset, preserving `path` data, `viewBox`, and full SVG structure. Never redraw or approximate vectors.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { closeSync, mkdirSync, openSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import pino from "pino";
|
|
5
|
+
|
|
6
|
+
//#region package.json
|
|
7
|
+
var package_default = {
|
|
8
|
+
name: "@tempad-dev/mcp",
|
|
9
|
+
description: "MCP server for TemPad Dev.",
|
|
10
|
+
version: "0.3.6",
|
|
11
|
+
type: "module",
|
|
12
|
+
main: "dist/cli.js",
|
|
13
|
+
bin: "dist/cli.js",
|
|
14
|
+
files: ["dist/**/*", "README.md"],
|
|
15
|
+
scripts: {
|
|
16
|
+
"build": "tsdown && cp src/instructions.md dist/instructions.md",
|
|
17
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
18
|
+
"lint": "eslint . --ext .ts,.mts,.cts,.js,.mjs,.cjs",
|
|
19
|
+
"format": "prettier --write \"**/*.{js,ts,mjs,cjs,cts,mts,json,md}\"",
|
|
20
|
+
"prepublishOnly": "pnpm run build"
|
|
21
|
+
},
|
|
22
|
+
dependencies: {
|
|
23
|
+
"@tempad-dev/mcp-shared": "workspace:^0.1.0",
|
|
24
|
+
"@modelcontextprotocol/sdk": "^1.24.0",
|
|
25
|
+
"nanoid": "^5.1.6",
|
|
26
|
+
"pino": "^9.14.0",
|
|
27
|
+
"pino-pretty": "^11.2.2",
|
|
28
|
+
"proper-lockfile": "^4.1.2",
|
|
29
|
+
"ws": "^8.18.3"
|
|
30
|
+
},
|
|
31
|
+
devDependencies: {
|
|
32
|
+
"@types/node": "^22.10.2",
|
|
33
|
+
"@types/proper-lockfile": "^4.1.4",
|
|
34
|
+
"@types/ws": "^8.5.12",
|
|
35
|
+
"tsdown": "^0.17.2",
|
|
36
|
+
"typescript": "^5.9.3",
|
|
37
|
+
"zod": "^4.1.12"
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/shared.ts
|
|
43
|
+
function ensureDir(dirPath) {
|
|
44
|
+
mkdirSync(dirPath, {
|
|
45
|
+
recursive: true,
|
|
46
|
+
mode: 448
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const pkg = package_default;
|
|
50
|
+
const PACKAGE_VERSION = typeof pkg.version === "string" ? pkg.version : "0.0.0";
|
|
51
|
+
function resolveRuntimeDir() {
|
|
52
|
+
if (process.env.TEMPAD_MCP_RUNTIME_DIR) return process.env.TEMPAD_MCP_RUNTIME_DIR;
|
|
53
|
+
return join(tmpdir(), "tempad-dev", "run");
|
|
54
|
+
}
|
|
55
|
+
function resolveLogDir() {
|
|
56
|
+
if (process.env.TEMPAD_MCP_LOG_DIR) return process.env.TEMPAD_MCP_LOG_DIR;
|
|
57
|
+
return join(tmpdir(), "tempad-dev", "log");
|
|
58
|
+
}
|
|
59
|
+
function resolveAssetDir() {
|
|
60
|
+
if (process.env.TEMPAD_MCP_ASSET_DIR) return process.env.TEMPAD_MCP_ASSET_DIR;
|
|
61
|
+
return join(tmpdir(), "tempad-dev", "assets");
|
|
62
|
+
}
|
|
63
|
+
const RUNTIME_DIR = resolveRuntimeDir();
|
|
64
|
+
const LOG_DIR = resolveLogDir();
|
|
65
|
+
const ASSET_DIR = resolveAssetDir();
|
|
66
|
+
ensureDir(RUNTIME_DIR);
|
|
67
|
+
ensureDir(LOG_DIR);
|
|
68
|
+
ensureDir(ASSET_DIR);
|
|
69
|
+
function ensureFile(filePath) {
|
|
70
|
+
closeSync(openSync(filePath, "a"));
|
|
71
|
+
}
|
|
72
|
+
const LOCK_PATH = join(RUNTIME_DIR, "mcp.lock");
|
|
73
|
+
ensureFile(LOCK_PATH);
|
|
74
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-").replaceAll(".", "-");
|
|
75
|
+
const pid = process.pid;
|
|
76
|
+
const LOG_FILE = join(LOG_DIR, `mcp-${timestamp}-${pid}.log`);
|
|
77
|
+
const prettyTransport = pino.transport({
|
|
78
|
+
target: "pino-pretty",
|
|
79
|
+
options: {
|
|
80
|
+
translateTime: "SYS:HH:MM:ss",
|
|
81
|
+
destination: LOG_FILE
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
const log = pino({
|
|
85
|
+
level: process.env.DEBUG ? "debug" : "info",
|
|
86
|
+
msgPrefix: "[tempad-dev/mcp] "
|
|
87
|
+
}, prettyTransport);
|
|
88
|
+
const SOCK_PATH = process.platform === "win32" ? "\\\\.\\pipe\\tempad-mcp" : join(RUNTIME_DIR, "mcp.sock");
|
|
89
|
+
|
|
90
|
+
//#endregion
|
|
91
|
+
export { SOCK_PATH as a, log as c, RUNTIME_DIR as i, LOCK_PATH as n, ensureDir as o, PACKAGE_VERSION as r, ensureFile as s, ASSET_DIR as t };
|
|
92
|
+
//# sourceMappingURL=shared-DisdM-7P.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-DisdM-7P.mjs","names":["packageJson"],"sources":["../package.json","../src/shared.ts"],"sourcesContent":["{\n \"name\": \"@tempad-dev/mcp\",\n \"description\": \"MCP server for TemPad Dev.\",\n \"version\": \"0.3.6\",\n \"type\": \"module\",\n \"main\": \"dist/cli.js\",\n \"bin\": \"dist/cli.js\",\n \"files\": [\n \"dist/**/*\",\n \"README.md\"\n ],\n \"scripts\": {\n \"build\": \"tsdown && cp src/instructions.md dist/instructions.md\",\n \"typecheck\": \"tsc -p tsconfig.json --noEmit\",\n \"lint\": \"eslint . --ext .ts,.mts,.cts,.js,.mjs,.cjs\",\n \"format\": \"prettier --write \\\"**/*.{js,ts,mjs,cjs,cts,mts,json,md}\\\"\",\n \"prepublishOnly\": \"pnpm run build\"\n },\n \"dependencies\": {\n \"@tempad-dev/mcp-shared\": \"workspace:^0.1.0\",\n \"@modelcontextprotocol/sdk\": \"^1.24.0\",\n \"nanoid\": \"^5.1.6\",\n \"pino\": \"^9.14.0\",\n \"pino-pretty\": \"^11.2.2\",\n \"proper-lockfile\": \"^4.1.2\",\n \"ws\": \"^8.18.3\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^22.10.2\",\n \"@types/proper-lockfile\": \"^4.1.4\",\n \"@types/ws\": \"^8.5.12\",\n \"tsdown\": \"^0.17.2\",\n \"typescript\": \"^5.9.3\",\n \"zod\": \"^4.1.12\"\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\nimport packageJson from '../package.json' assert { type: 'json' }\n\nexport function ensureDir(dirPath: string): void {\n mkdirSync(dirPath, { recursive: true, mode: 0o700 })\n}\n\nconst pkg = packageJson as { version?: unknown }\nexport const PACKAGE_VERSION = typeof pkg.version === 'string' ? pkg.version : '0.0.0'\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"],"mappings":";;;;;;sBAAA;OACU;cACO;UACJ;OACH;OACA;MACD;QACE,CACP,aACA,YACD;UACU;EACT,SAAS;EACT,aAAa;EACb,QAAQ;EACR,UAAU;EACV,kBAAkB;EACnB;eACe;EACd,0BAA0B;EAC1B,6BAA6B;EAC7B,UAAU;EACV,QAAQ;EACR,eAAe;EACf,mBAAmB;EACnB,MAAM;EACP;kBACkB;EACjB,eAAe;EACf,0BAA0B;EAC1B,aAAa;EACb,UAAU;EACV,cAAc;EACd,OAAO;EACR;CACF;;;;AC5BD,SAAgB,UAAU,SAAuB;AAC/C,WAAU,SAAS;EAAE,WAAW;EAAM,MAAM;EAAO,CAAC;;AAGtD,MAAM,MAAMA;AACZ,MAAa,kBAAkB,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU;AAE/E,SAAS,oBAA4B;AACnC,KAAI,QAAQ,IAAI,uBAAwB,QAAO,QAAQ,IAAI;AAC3D,QAAO,KAAK,QAAQ,EAAE,cAAc,MAAM;;AAG5C,SAAS,gBAAwB;AAC/B,KAAI,QAAQ,IAAI,mBAAoB,QAAO,QAAQ,IAAI;AACvD,QAAO,KAAK,QAAQ,EAAE,cAAc,MAAM;;AAG5C,SAAS,kBAA0B;AACjC,KAAI,QAAQ,IAAI,qBAAsB,QAAO,QAAQ,IAAI;AACzD,QAAO,KAAK,QAAQ,EAAE,cAAc,SAAS;;AAG/C,MAAa,cAAc,mBAAmB;AAC9C,MAAa,UAAU,eAAe;AACtC,MAAa,YAAY,iBAAiB;AAE1C,UAAU,YAAY;AACtB,UAAU,QAAQ;AAClB,UAAU,UAAU;AAEpB,SAAgB,WAAW,UAAwB;AAEjD,WADW,SAAS,UAAU,IAAI,CACrB;;AAGf,MAAa,YAAY,KAAK,aAAa,WAAW;AACtD,WAAW,UAAU;AAErB,MAAM,6BAAY,IAAI,MAAM,EAAC,aAAa,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW,KAAK,IAAI;AACpF,MAAM,MAAM,QAAQ;AACpB,MAAM,WAAW,KAAK,SAAS,OAAO,UAAU,GAAG,IAAI,MAAM;AAE7D,MAAM,kBAAkB,KAAK,UAAU;CACrC,QAAQ;CACR,SAAS;EACP,eAAe;EACf,aAAa;EACd;CACF,CAAC;AAEF,MAAa,MAAM,KACjB;CACE,OAAO,QAAQ,IAAI,QAAQ,UAAU;CACrC,WAAW;CACZ,EACD,gBACD;AAED,MAAa,YACX,QAAQ,aAAa,UAAU,4BAA4B,KAAK,aAAa,WAAW"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tempad-dev/mcp",
|
|
3
3
|
"description": "MCP server for TemPad Dev.",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.6",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cli.js",
|
|
7
7
|
"bin": "dist/cli.js",
|
|
@@ -10,15 +10,26 @@
|
|
|
10
10
|
"README.md"
|
|
11
11
|
],
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@
|
|
13
|
+
"@tempad-dev/mcp-shared": "^0.1.0",
|
|
14
|
+
"@modelcontextprotocol/sdk": "^1.24.0",
|
|
14
15
|
"nanoid": "^5.1.6",
|
|
15
16
|
"pino": "^9.14.0",
|
|
16
17
|
"pino-pretty": "^11.2.2",
|
|
17
18
|
"proper-lockfile": "^4.1.2",
|
|
18
|
-
"ws": "^8.18.3"
|
|
19
|
+
"ws": "^8.18.3"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^22.10.2",
|
|
23
|
+
"@types/proper-lockfile": "^4.1.4",
|
|
24
|
+
"@types/ws": "^8.5.12",
|
|
25
|
+
"tsdown": "^0.17.2",
|
|
26
|
+
"typescript": "^5.9.3",
|
|
19
27
|
"zod": "^4.1.12"
|
|
20
28
|
},
|
|
21
29
|
"scripts": {
|
|
22
|
-
"build": "
|
|
30
|
+
"build": "tsdown && cp src/instructions.md dist/instructions.md",
|
|
31
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
32
|
+
"lint": "eslint . --ext .ts,.mts,.cts,.js,.mjs,.cjs",
|
|
33
|
+
"format": "prettier --write \"**/*.{js,ts,mjs,cjs,cts,mts,json,md}\""
|
|
23
34
|
}
|
|
24
35
|
}
|
package/dist/cli.js
DELETED
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/cli.ts
|
|
4
|
-
import { spawn } from "node:child_process";
|
|
5
|
-
import { connect } from "node:net";
|
|
6
|
-
import { join as join2 } from "node:path";
|
|
7
|
-
import { fileURLToPath } from "node:url";
|
|
8
|
-
import lockfile from "proper-lockfile";
|
|
9
|
-
|
|
10
|
-
// src/shared.ts
|
|
11
|
-
import { closeSync, mkdirSync, openSync } from "node:fs";
|
|
12
|
-
import { tmpdir } from "node:os";
|
|
13
|
-
import { join } from "node:path";
|
|
14
|
-
import pino from "pino";
|
|
15
|
-
|
|
16
|
-
// package.json
|
|
17
|
-
var package_default = {
|
|
18
|
-
name: "@tempad-dev/mcp",
|
|
19
|
-
description: "MCP server for TemPad Dev.",
|
|
20
|
-
version: "0.3.4",
|
|
21
|
-
type: "module",
|
|
22
|
-
main: "dist/cli.js",
|
|
23
|
-
bin: "dist/cli.js",
|
|
24
|
-
files: [
|
|
25
|
-
"dist/**/*",
|
|
26
|
-
"README.md"
|
|
27
|
-
],
|
|
28
|
-
scripts: {
|
|
29
|
-
build: "tsc -p ./tsconfig.json --noEmit && node ./scripts/build.mjs",
|
|
30
|
-
prepublishOnly: "npm run build"
|
|
31
|
-
},
|
|
32
|
-
dependencies: {
|
|
33
|
-
"@modelcontextprotocol/sdk": "^1.22.0",
|
|
34
|
-
nanoid: "^5.1.6",
|
|
35
|
-
pino: "^9.14.0",
|
|
36
|
-
"pino-pretty": "^11.2.2",
|
|
37
|
-
"proper-lockfile": "^4.1.2",
|
|
38
|
-
ws: "^8.18.3",
|
|
39
|
-
zod: "^4.1.12"
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
// src/shared.ts
|
|
44
|
-
function ensureDir(dirPath) {
|
|
45
|
-
mkdirSync(dirPath, { recursive: true, mode: 448 });
|
|
46
|
-
}
|
|
47
|
-
var pkg = package_default;
|
|
48
|
-
var PACKAGE_VERSION = typeof pkg.version === "string" ? pkg.version : "0.0.0";
|
|
49
|
-
function resolveRuntimeDir() {
|
|
50
|
-
if (process.env.TEMPAD_MCP_RUNTIME_DIR) return process.env.TEMPAD_MCP_RUNTIME_DIR;
|
|
51
|
-
return join(tmpdir(), "tempad-dev", "run");
|
|
52
|
-
}
|
|
53
|
-
function resolveLogDir() {
|
|
54
|
-
if (process.env.TEMPAD_MCP_LOG_DIR) return process.env.TEMPAD_MCP_LOG_DIR;
|
|
55
|
-
return join(tmpdir(), "tempad-dev", "log");
|
|
56
|
-
}
|
|
57
|
-
function resolveAssetDir() {
|
|
58
|
-
if (process.env.TEMPAD_MCP_ASSET_DIR) return process.env.TEMPAD_MCP_ASSET_DIR;
|
|
59
|
-
return join(tmpdir(), "tempad-dev", "assets");
|
|
60
|
-
}
|
|
61
|
-
var RUNTIME_DIR = resolveRuntimeDir();
|
|
62
|
-
var LOG_DIR = resolveLogDir();
|
|
63
|
-
var ASSET_DIR = resolveAssetDir();
|
|
64
|
-
ensureDir(RUNTIME_DIR);
|
|
65
|
-
ensureDir(LOG_DIR);
|
|
66
|
-
ensureDir(ASSET_DIR);
|
|
67
|
-
function ensureFile(filePath) {
|
|
68
|
-
const fd = openSync(filePath, "a");
|
|
69
|
-
closeSync(fd);
|
|
70
|
-
}
|
|
71
|
-
var LOCK_PATH = join(RUNTIME_DIR, "mcp.lock");
|
|
72
|
-
ensureFile(LOCK_PATH);
|
|
73
|
-
var timestamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-").replaceAll(".", "-");
|
|
74
|
-
var pid = process.pid;
|
|
75
|
-
var LOG_FILE = join(LOG_DIR, `mcp-${timestamp}-${pid}.log`);
|
|
76
|
-
var prettyTransport = pino.transport({
|
|
77
|
-
target: "pino-pretty",
|
|
78
|
-
options: {
|
|
79
|
-
translateTime: "SYS:HH:MM:ss",
|
|
80
|
-
destination: LOG_FILE
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
var log = pino(
|
|
84
|
-
{
|
|
85
|
-
level: process.env.DEBUG ? "debug" : "info",
|
|
86
|
-
msgPrefix: "[tempad-dev/mcp] "
|
|
87
|
-
},
|
|
88
|
-
prettyTransport
|
|
89
|
-
);
|
|
90
|
-
var SOCK_PATH = process.platform === "win32" ? "\\\\.\\pipe\\tempad-mcp" : join(RUNTIME_DIR, "mcp.sock");
|
|
91
|
-
|
|
92
|
-
// src/cli.ts
|
|
93
|
-
var activeSocket = null;
|
|
94
|
-
var shuttingDown = false;
|
|
95
|
-
function closeActiveSocket() {
|
|
96
|
-
if (!activeSocket) return;
|
|
97
|
-
try {
|
|
98
|
-
activeSocket.end();
|
|
99
|
-
} catch {
|
|
100
|
-
}
|
|
101
|
-
try {
|
|
102
|
-
activeSocket.destroy();
|
|
103
|
-
} catch {
|
|
104
|
-
}
|
|
105
|
-
activeSocket = null;
|
|
106
|
-
}
|
|
107
|
-
function shutdownCli(reason) {
|
|
108
|
-
if (shuttingDown) return;
|
|
109
|
-
shuttingDown = true;
|
|
110
|
-
log.info(`${reason} Shutting down CLI.`);
|
|
111
|
-
closeActiveSocket();
|
|
112
|
-
process.exit(0);
|
|
113
|
-
}
|
|
114
|
-
process.on("SIGINT", () => shutdownCli("SIGINT received."));
|
|
115
|
-
process.on("SIGTERM", () => shutdownCli("SIGTERM received."));
|
|
116
|
-
var HUB_STARTUP_TIMEOUT = 5e3;
|
|
117
|
-
var CONNECT_RETRY_DELAY = 200;
|
|
118
|
-
var FAILED_RESTART_DELAY = 5e3;
|
|
119
|
-
var HERE = fileURLToPath(new URL(".", import.meta.url));
|
|
120
|
-
var HUB_ENTRY = join2(HERE, "hub.js");
|
|
121
|
-
ensureDir(RUNTIME_DIR);
|
|
122
|
-
function bridge(socket) {
|
|
123
|
-
return new Promise((resolve) => {
|
|
124
|
-
log.info("Bridge established with Hub. Forwarding I/O.");
|
|
125
|
-
activeSocket = socket;
|
|
126
|
-
const onStdinEnd = () => {
|
|
127
|
-
shutdownCli("Consumer stream ended.");
|
|
128
|
-
};
|
|
129
|
-
process.stdin.once("end", onStdinEnd);
|
|
130
|
-
const onSocketClose = () => {
|
|
131
|
-
log.warn("Connection to Hub lost. Attempting to reconnect...");
|
|
132
|
-
activeSocket = null;
|
|
133
|
-
process.stdin.removeListener("end", onStdinEnd);
|
|
134
|
-
process.stdin.unpipe(socket);
|
|
135
|
-
socket.unpipe(process.stdout);
|
|
136
|
-
socket.removeAllListeners();
|
|
137
|
-
resolve();
|
|
138
|
-
};
|
|
139
|
-
socket.once("close", onSocketClose);
|
|
140
|
-
socket.on("error", (err) => log.warn({ err }, "Socket error occurred."));
|
|
141
|
-
process.stdin.pipe(socket, { end: false }).pipe(process.stdout);
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
function connectHub() {
|
|
145
|
-
return new Promise((resolve, reject) => {
|
|
146
|
-
const socket = connect(SOCK_PATH);
|
|
147
|
-
socket.on("connect", () => {
|
|
148
|
-
socket.removeAllListeners("error");
|
|
149
|
-
resolve(socket);
|
|
150
|
-
});
|
|
151
|
-
socket.on("error", reject);
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
async function connectWithRetry(timeout) {
|
|
155
|
-
const startTime = Date.now();
|
|
156
|
-
let delay = CONNECT_RETRY_DELAY;
|
|
157
|
-
while (Date.now() - startTime < timeout) {
|
|
158
|
-
try {
|
|
159
|
-
return await connectHub();
|
|
160
|
-
} catch (err) {
|
|
161
|
-
if (err && typeof err === "object" && "code" in err && (err.code === "ENOENT" || err.code === "ECONNREFUSED")) {
|
|
162
|
-
const remainingTime = timeout - (Date.now() - startTime);
|
|
163
|
-
const waitTime = Math.min(delay, remainingTime);
|
|
164
|
-
if (waitTime <= 0) break;
|
|
165
|
-
await new Promise((r) => setTimeout(r, waitTime));
|
|
166
|
-
delay = Math.min(delay * 1.5, 1e3);
|
|
167
|
-
} else {
|
|
168
|
-
throw err;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
throw new Error(`Failed to connect to Hub within ${timeout}ms.`);
|
|
173
|
-
}
|
|
174
|
-
function startHub() {
|
|
175
|
-
log.info("Spawning new Hub process...");
|
|
176
|
-
return spawn(process.execPath, [HUB_ENTRY], {
|
|
177
|
-
detached: true,
|
|
178
|
-
stdio: "ignore"
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
async function tryBecomeLeaderAndStartHub() {
|
|
182
|
-
let releaseLock = null;
|
|
183
|
-
try {
|
|
184
|
-
releaseLock = await lockfile.lock(LOCK_PATH, {
|
|
185
|
-
retries: { retries: 5, factor: 1.2, minTimeout: 50 },
|
|
186
|
-
stale: 15e3
|
|
187
|
-
});
|
|
188
|
-
} catch {
|
|
189
|
-
log.info("Another process is starting the Hub. Waiting...");
|
|
190
|
-
return connectWithRetry(HUB_STARTUP_TIMEOUT);
|
|
191
|
-
}
|
|
192
|
-
log.info("Acquired lock. Starting Hub as the leader...");
|
|
193
|
-
let child = null;
|
|
194
|
-
try {
|
|
195
|
-
try {
|
|
196
|
-
return await connectHub();
|
|
197
|
-
} catch {
|
|
198
|
-
log.info("Hub not running. Proceeding to start it...");
|
|
199
|
-
}
|
|
200
|
-
child = startHub();
|
|
201
|
-
child.on("error", (err) => log.error({ err }, "Hub child process error."));
|
|
202
|
-
const socket = await connectWithRetry(HUB_STARTUP_TIMEOUT);
|
|
203
|
-
child.unref();
|
|
204
|
-
return socket;
|
|
205
|
-
} catch (err) {
|
|
206
|
-
log.error({ err }, "Failed to start or connect to the Hub.");
|
|
207
|
-
if (child && !child.killed) {
|
|
208
|
-
log.warn(`Killing stale Hub process (PID: ${child.pid})...`);
|
|
209
|
-
child.kill("SIGTERM");
|
|
210
|
-
}
|
|
211
|
-
throw err;
|
|
212
|
-
} finally {
|
|
213
|
-
if (releaseLock) await releaseLock();
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
async function main() {
|
|
217
|
-
log.info({ version: PACKAGE_VERSION }, "TemPad MCP Client starting...");
|
|
218
|
-
while (true) {
|
|
219
|
-
try {
|
|
220
|
-
const socket = await connectHub().catch(() => {
|
|
221
|
-
log.info("Hub not running. Initiating startup sequence...");
|
|
222
|
-
return tryBecomeLeaderAndStartHub();
|
|
223
|
-
});
|
|
224
|
-
await bridge(socket);
|
|
225
|
-
log.info("Bridge disconnected. Restarting connection process...");
|
|
226
|
-
} catch (err) {
|
|
227
|
-
log.error(
|
|
228
|
-
{ err },
|
|
229
|
-
`Connection attempt failed. Retrying in ${FAILED_RESTART_DELAY / 1e3}s...`
|
|
230
|
-
);
|
|
231
|
-
await new Promise((r) => setTimeout(r, FAILED_RESTART_DELAY));
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
main();
|
|
236
|
-
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/cli.ts", "../src/shared.ts", "../package.json"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\n\nimport type { ChildProcess } from 'node:child_process'\nimport type { Socket } from 'node:net'\n\nimport { spawn } from 'node:child_process'\nimport { connect } from 'node:net'\nimport { join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport lockfile from 'proper-lockfile'\n\nimport { PACKAGE_VERSION, log, LOCK_PATH, RUNTIME_DIR, SOCK_PATH, ensureDir } from './shared'\n\nlet activeSocket: Socket | null = null\nlet shuttingDown = false\n\nfunction closeActiveSocket() {\n if (!activeSocket) return\n try {\n activeSocket.end()\n } catch {\n // ignore\n }\n try {\n activeSocket.destroy()\n } catch {\n // ignore\n }\n activeSocket = null\n}\n\nfunction shutdownCli(reason: string) {\n if (shuttingDown) return\n shuttingDown = true\n log.info(`${reason} Shutting down CLI.`)\n closeActiveSocket()\n process.exit(0)\n}\n\nprocess.on('SIGINT', () => shutdownCli('SIGINT received.'))\nprocess.on('SIGTERM', () => shutdownCli('SIGTERM received.'))\n\nconst HUB_STARTUP_TIMEOUT = 5000\nconst CONNECT_RETRY_DELAY = 200\nconst FAILED_RESTART_DELAY = 5000\nconst HERE = fileURLToPath(new URL('.', import.meta.url))\nconst HUB_ENTRY = join(HERE, 'hub.js')\n\nensureDir(RUNTIME_DIR)\n\nfunction bridge(socket: Socket): Promise<void> {\n return new Promise((resolve) => {\n log.info('Bridge established with Hub. Forwarding I/O.')\n activeSocket = socket\n\n const onStdinEnd = () => {\n shutdownCli('Consumer stream ended.')\n }\n process.stdin.once('end', onStdinEnd)\n\n const onSocketClose = () => {\n log.warn('Connection to Hub lost. Attempting to reconnect...')\n activeSocket = null\n process.stdin.removeListener('end', onStdinEnd)\n process.stdin.unpipe(socket)\n socket.unpipe(process.stdout)\n socket.removeAllListeners()\n resolve()\n }\n socket.once('close', onSocketClose)\n socket.on('error', (err) => log.warn({ err }, 'Socket error occurred.'))\n\n // The `{ end: false }` option prevents stdin from closing the socket.\n process.stdin.pipe(socket, { end: false }).pipe(process.stdout)\n })\n}\n\nfunction connectHub(): Promise<Socket> {\n return new Promise((resolve, reject) => {\n const socket = connect(SOCK_PATH)\n socket.on('connect', () => {\n socket.removeAllListeners('error')\n resolve(socket)\n })\n socket.on('error', reject)\n })\n}\n\nasync function connectWithRetry(timeout: number): Promise<Socket> {\n const startTime = Date.now()\n let delay = CONNECT_RETRY_DELAY\n while (Date.now() - startTime < timeout) {\n try {\n return await connectHub()\n } catch (err: unknown) {\n if (\n err &&\n typeof err === 'object' &&\n 'code' in err &&\n (err.code === 'ENOENT' || err.code === 'ECONNREFUSED')\n ) {\n const remainingTime = timeout - (Date.now() - startTime)\n const waitTime = Math.min(delay, remainingTime)\n if (waitTime <= 0) break\n await new Promise((r) => setTimeout(r, waitTime))\n delay = Math.min(delay * 1.5, 1000)\n } else {\n throw err\n }\n }\n }\n throw new Error(`Failed to connect to Hub within ${timeout}ms.`)\n}\n\nfunction startHub(): ChildProcess {\n log.info('Spawning new Hub process...')\n return spawn(process.execPath, [HUB_ENTRY], {\n detached: true,\n stdio: 'ignore'\n })\n}\n\nasync function tryBecomeLeaderAndStartHub(): Promise<Socket> {\n let releaseLock: (() => Promise<void>) | null = null\n try {\n releaseLock = await lockfile.lock(LOCK_PATH, {\n retries: { retries: 5, factor: 1.2, minTimeout: 50 },\n stale: 15000\n })\n } catch {\n log.info('Another process is starting the Hub. Waiting...')\n return connectWithRetry(HUB_STARTUP_TIMEOUT)\n }\n\n log.info('Acquired lock. Starting Hub as the leader...')\n let child: ChildProcess | null = null\n try {\n try {\n return await connectHub()\n } catch {\n // If the Hub is not running, we proceed to start it.\n log.info('Hub not running. Proceeding to start it...')\n }\n child = startHub()\n child.on('error', (err) => log.error({ err }, 'Hub child process error.'))\n const socket = await connectWithRetry(HUB_STARTUP_TIMEOUT)\n child.unref()\n return socket\n } catch (err: unknown) {\n log.error({ err }, 'Failed to start or connect to the Hub.')\n if (child && !child.killed) {\n log.warn(`Killing stale Hub process (PID: ${child.pid})...`)\n child.kill('SIGTERM')\n }\n throw err\n } finally {\n if (releaseLock) await releaseLock()\n }\n}\n\nasync function main() {\n log.info({ version: PACKAGE_VERSION }, 'TemPad MCP Client starting...')\n\n while (true) {\n try {\n const socket = await connectHub().catch(() => {\n log.info('Hub not running. Initiating startup sequence...')\n return tryBecomeLeaderAndStartHub()\n })\n await bridge(socket)\n log.info('Bridge disconnected. Restarting connection process...')\n } catch (err: unknown) {\n log.error(\n { err },\n `Connection attempt failed. Retrying in ${FAILED_RESTART_DELAY / 1000}s...`\n )\n await new Promise((r) => setTimeout(r, FAILED_RESTART_DELAY))\n }\n }\n}\n\nmain()\n", "import { closeSync, mkdirSync, openSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport pino from 'pino'\n\nimport packageJson from '../package.json' assert { type: 'json' }\n\nexport function ensureDir(dirPath: string): void {\n mkdirSync(dirPath, { recursive: true, mode: 0o700 })\n}\n\nconst pkg = packageJson as { version?: unknown }\nexport const PACKAGE_VERSION = typeof pkg.version === 'string' ? pkg.version : '0.0.0'\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", "{\n \"name\": \"@tempad-dev/mcp\",\n \"description\": \"MCP server for TemPad Dev.\",\n \"version\": \"0.3.4\",\n \"type\": \"module\",\n \"main\": \"dist/cli.js\",\n \"bin\": \"dist/cli.js\",\n \"files\": [\n \"dist/**/*\",\n \"README.md\"\n ],\n \"scripts\": {\n \"build\": \"tsc -p ./tsconfig.json --noEmit && node ./scripts/build.mjs\",\n \"prepublishOnly\": \"npm run build\"\n },\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.22.0\",\n \"nanoid\": \"^5.1.6\",\n \"pino\": \"^9.14.0\",\n \"pino-pretty\": \"^11.2.2\",\n \"proper-lockfile\": \"^4.1.2\",\n \"ws\": \"^8.18.3\",\n \"zod\": \"^4.1.12\"\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["join", "join"]
|
|
7
|
-
}
|