@imenam/mcp-design 1.0.7 → 1.0.9
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 +324 -305
- package/dist/shared/node-defaults.d.ts +1 -1
- package/dist/shared/node-defaults.js +9 -3
- package/dist/shared/node-fields.js +6 -2
- package/dist/shared/render.d.ts +18 -0
- package/dist/shared/render.js +22 -0
- package/dist/src/core/clone.d.ts +2 -0
- package/dist/src/core/clone.js +1 -1
- package/dist/src/core/design-store.d.ts +9 -0
- package/dist/src/core/design-store.js +26 -0
- package/dist/src/core/node-factory.js +15 -0
- package/dist/src/index.js +49 -9
- package/dist/src/tools/duplicate-design.d.ts +4 -0
- package/dist/src/tools/duplicate-design.js +18 -0
- package/dist/src/tools/duplicate-nodes.d.ts +5 -3
- package/dist/src/tools/duplicate-nodes.js +81 -24
- package/dist/src/tools/export-design.d.ts +2 -2
- package/dist/src/tools/export-design.js +28 -9
- package/dist/src/tools/relay.d.ts +27 -0
- package/dist/src/tools/relay.js +67 -0
- package/dist/src/tools/screenshot-design.js +14 -8
- package/dist/src/tools/types.d.ts +20 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/gui/dist/assets/index-DBZNXgF_.js +10 -0
- package/gui/dist/assets/{search-C-KcHHKM.js → search-CSwiX0lv.js} +1 -1
- package/gui/dist/index.html +1 -1
- package/package.json +1 -1
- package/gui/dist/assets/index-B-q92Pfu.js +0 -10
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare const RELAY_SHAPE_DESCRIPTIONS: {
|
|
2
|
+
readonly destination_path: "ABSOLUTE path of the destination DIRECTORY on the agent machine. It is created if missing, and the file keeps the name given in filename";
|
|
3
|
+
readonly filename: "Name of the file to create, extension included (e.g. 'design.html'). Must not contain path separators";
|
|
4
|
+
readonly destination_overwrite: "Replace the destination file if it already exists. Defaults to false";
|
|
5
|
+
readonly destination_relay: "Filled in by the mcp-http-gateway relay, never by the agent. Signals that the destination lives on another machine and that the file content must travel in the response";
|
|
6
|
+
};
|
|
7
|
+
export interface DeliveryTarget {
|
|
8
|
+
destination_path: string;
|
|
9
|
+
filename: string;
|
|
10
|
+
destination_overwrite?: boolean;
|
|
11
|
+
destination_relay?: boolean;
|
|
12
|
+
}
|
|
13
|
+
import type { ResourceBlock } from "./types.js";
|
|
14
|
+
type ContentBlock = {
|
|
15
|
+
type: "text";
|
|
16
|
+
text: string;
|
|
17
|
+
} | ResourceBlock;
|
|
18
|
+
/**
|
|
19
|
+
* Livre un fichier produit par le MCP, du bon côté de la chaîne.
|
|
20
|
+
*
|
|
21
|
+
* Renvoie les blocs de contenu à faire figurer dans le résultat de l'outil : un bloc
|
|
22
|
+
* `resource` que le relais interceptera et retirera, ou une simple confirmation quand
|
|
23
|
+
* l'écriture a eu lieu ici. Toute impossibilité est une erreur franche : mieux vaut un
|
|
24
|
+
* fichier perdu qu'un fichier écrit sur la mauvaise machine.
|
|
25
|
+
*/
|
|
26
|
+
export declare function deliverFile(data: Buffer, mimeType: string, target: DeliveryTarget): ContentBlock[];
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
// Un fichier produit par ce MCP n'a aucun moyen d'atteindre la machine de l'agent quand
|
|
4
|
+
// le MCP tourne derrière mcp-http-gateway : le protocole n'offre au serveur aucune
|
|
5
|
+
// primitive pour y écrire. La convention du relais règle ça — dès qu'un outil déclare la
|
|
6
|
+
// paire `destination_path` / `destination_relay`, le relais retient la destination, pose
|
|
7
|
+
// `destination_relay`, et écrit lui-même les octets qu'on lui renvoie.
|
|
8
|
+
//
|
|
9
|
+
// Ici, on ne sait pas si un relais est dans la chaîne : `destination_relay` le dit. Posé,
|
|
10
|
+
// on renvoie le contenu ; absent, les deux machines n'en font qu'une et on écrit nous-même.
|
|
11
|
+
/** Plafond de ce qui peut être encodé dans une réponse d'outil. Le relais applique sa
|
|
12
|
+
* propre limite, configurable ; celle-ci n'existe que pour qu'un fichier démesuré
|
|
13
|
+
* échoue proprement ici plutôt qu'en épuisant la mémoire pendant l'encodage base64. */
|
|
14
|
+
const RELAY_MAX_BYTES = 32 * 1024 * 1024;
|
|
15
|
+
export const RELAY_SHAPE_DESCRIPTIONS = {
|
|
16
|
+
destination_path: "ABSOLUTE path of the destination DIRECTORY on the agent machine. It is created if missing, and the file keeps the name given in filename",
|
|
17
|
+
filename: "Name of the file to create, extension included (e.g. 'design.html'). Must not contain path separators",
|
|
18
|
+
destination_overwrite: "Replace the destination file if it already exists. Defaults to false",
|
|
19
|
+
destination_relay: "Filled in by the mcp-http-gateway relay, never by the agent. Signals that the destination lives on another machine and that the file content must travel in the response",
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Livre un fichier produit par le MCP, du bon côté de la chaîne.
|
|
23
|
+
*
|
|
24
|
+
* Renvoie les blocs de contenu à faire figurer dans le résultat de l'outil : un bloc
|
|
25
|
+
* `resource` que le relais interceptera et retirera, ou une simple confirmation quand
|
|
26
|
+
* l'écriture a eu lieu ici. Toute impossibilité est une erreur franche : mieux vaut un
|
|
27
|
+
* fichier perdu qu'un fichier écrit sur la mauvaise machine.
|
|
28
|
+
*/
|
|
29
|
+
export function deliverFile(data, mimeType, target) {
|
|
30
|
+
const name = path.basename(target.filename);
|
|
31
|
+
if (name !== target.filename || name === "." || name === "..") {
|
|
32
|
+
throw new Error(`filename must be a bare file name, without path separators: ${target.filename}`);
|
|
33
|
+
}
|
|
34
|
+
if (data.length > RELAY_MAX_BYTES) {
|
|
35
|
+
throw new Error(`File too large to transfer: ${data.length} bytes, the limit is ${RELAY_MAX_BYTES}.`);
|
|
36
|
+
}
|
|
37
|
+
// Le relais tourne sur la machine de l'agent et a retenu la destination : il attend les
|
|
38
|
+
// octets, qu'il écrira lui-même. Écrire ici viserait le mauvais disque.
|
|
39
|
+
if (target.destination_relay) {
|
|
40
|
+
return [
|
|
41
|
+
{
|
|
42
|
+
type: "resource",
|
|
43
|
+
resource: {
|
|
44
|
+
uri: `file:///${name}`,
|
|
45
|
+
name,
|
|
46
|
+
mimeType,
|
|
47
|
+
blob: data.toString("base64"),
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
// Pas de relais : le MCP tourne à côté de l'agent, son disque est le bon.
|
|
53
|
+
if (!path.isAbsolute(target.destination_path)) {
|
|
54
|
+
throw new Error(`destination_path must be an absolute directory path: ${target.destination_path}`);
|
|
55
|
+
}
|
|
56
|
+
if (fs.existsSync(target.destination_path) &&
|
|
57
|
+
!fs.statSync(target.destination_path).isDirectory()) {
|
|
58
|
+
throw new Error(`destination_path must be a directory, but a file already exists there: ${target.destination_path}`);
|
|
59
|
+
}
|
|
60
|
+
const written = path.join(target.destination_path, name);
|
|
61
|
+
if (!target.destination_overwrite && fs.existsSync(written)) {
|
|
62
|
+
throw new Error(`Destination already exists: ${written}. Pass destination_overwrite to replace it.`);
|
|
63
|
+
}
|
|
64
|
+
fs.mkdirSync(target.destination_path, { recursive: true });
|
|
65
|
+
fs.writeFileSync(written, data);
|
|
66
|
+
return [{ type: "text", text: `File written to ${written} (${data.length} bytes).` }];
|
|
67
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
1
|
import { screenshotDesign } from "../core/screenshot.js";
|
|
2
|
+
import { deliverFile } from "./relay.js";
|
|
4
3
|
import { requireString } from "./types.js";
|
|
5
4
|
/** Marge par défaut autour d'un noeud capturé : de l'air, sans noyer l'élément. */
|
|
6
5
|
const NODE_PADDING = 16;
|
|
@@ -20,12 +19,19 @@ export function screenshotDesignTool(store, args) {
|
|
|
20
19
|
const subject = node ? `${node.type} "${node.name}" (${node.id})` : `design "${design.name}"`;
|
|
21
20
|
const geometry = `${Math.round(shot.sourceWidth)}x${Math.round(shot.sourceHeight)} design px ` +
|
|
22
21
|
`rendered at ${shot.width}x${shot.height} px (scale ${Math.round(shot.scale * 100) / 100})`;
|
|
23
|
-
const
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
const destination = typeof args?.destination_path === "string" ? args.destination_path.trim() : "";
|
|
23
|
+
if (destination) {
|
|
24
|
+
// Livrer le PNG et le montrer à la fois n'aurait pas de sens : le relais retire le
|
|
25
|
+
// contenu du résultat, et une image de plus dans le contexte coûte cher pour rien.
|
|
26
|
+
const blocks = deliverFile(shot.png, "image/png", {
|
|
27
|
+
destination_path: destination,
|
|
28
|
+
filename: requireString(args, "filename"),
|
|
29
|
+
destination_overwrite: args?.destination_overwrite === true,
|
|
30
|
+
destination_relay: args?.destination_relay === true,
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
content: [{ type: "text", text: `Screenshot of ${subject} — ${geometry}.` }, ...blocks],
|
|
34
|
+
};
|
|
29
35
|
}
|
|
30
36
|
return {
|
|
31
37
|
content: [
|
|
@@ -20,6 +20,25 @@ export interface ImageToolResult {
|
|
|
20
20
|
type: "image";
|
|
21
21
|
data: string;
|
|
22
22
|
mimeType: string;
|
|
23
|
-
}>;
|
|
23
|
+
} | ResourceBlock>;
|
|
24
|
+
isError?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** Bloc qu'un outil renvoie pour un fichier que le relais du gateway écrira chez l'agent. */
|
|
27
|
+
export interface ResourceBlock {
|
|
28
|
+
type: "resource";
|
|
29
|
+
resource: {
|
|
30
|
+
uri: string;
|
|
31
|
+
name: string;
|
|
32
|
+
mimeType: string;
|
|
33
|
+
blob: string;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Variante de ToolResult pour les outils qui peuvent livrer un fichier. */
|
|
37
|
+
export interface FileToolResult {
|
|
38
|
+
[key: string]: unknown;
|
|
39
|
+
content: Array<{
|
|
40
|
+
type: "text";
|
|
41
|
+
text: string;
|
|
42
|
+
} | ResourceBlock>;
|
|
24
43
|
isError?: boolean;
|
|
25
44
|
}
|
package/dist/src/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const APP_VERSION = "1.0.
|
|
1
|
+
export declare const APP_VERSION = "1.0.9";
|
package/dist/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated version file - do not edit manually
|
|
2
|
-
export const APP_VERSION = '1.0.
|
|
2
|
+
export const APP_VERSION = '1.0.9';
|