@tendrilapp/cli 0.1.3 → 0.1.4
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/tendril-mcp.js +34 -3
- package/package.json +1 -1
package/dist/tendril-mcp.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// packages/mcp/src/bin.ts
|
|
4
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
5
|
+
import path2 from "node:path";
|
|
6
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
4
7
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
8
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
9
|
+
import { z as z2 } from "zod";
|
|
6
10
|
|
|
7
11
|
// packages/mcp/src/server.ts
|
|
8
12
|
import { execFile } from "node:child_process";
|
|
@@ -20,7 +24,7 @@ var optStr = (d) => z.string().optional().describe(d);
|
|
|
20
24
|
var TOOLS = [
|
|
21
25
|
{
|
|
22
26
|
name: "tendril_record_plan",
|
|
23
|
-
description: "
|
|
27
|
+
description: "ENTRY POINT for implementing/building a React component from a Figma design or figma.com URL \u2014 start the Tendril pipeline here (after loading the tendril skill, if installed). Plans a recording session: computes the rep queue (anchor + one-factor + conflict crosses) from verbatim get_metadata envelope file(s) and persists the set manifest. Resumes if the set already exists. The output may carry USER QUESTIONS \u2014 defaultsToConfirm (which pose is the component's default) or a multiple-component-sets error (which set to record): render them to a present user and apply the answers via `defaults` / `componentSet`; non-interactive runs follow each question's stated fallback. Recording cost is stated in figmaCallEstimate, never asked about \u2014 proceed with what the user provided.",
|
|
24
28
|
schema: z.object({
|
|
25
29
|
setDir: str("recording set directory to create/resume"),
|
|
26
30
|
component: str("component/system name"),
|
|
@@ -141,7 +145,7 @@ var TOOLS = [
|
|
|
141
145
|
},
|
|
142
146
|
{
|
|
143
147
|
name: "tendril_verify",
|
|
144
|
-
description: "
|
|
148
|
+
description: "Verify/check that a component matches its Figma design \u2014 use when the user asks whether an implementation is faithful to the design, or to re-certify an existing Tendril bundle. Recomputes full verification (per-config status, behaviors, composition, evidence artifacts). Free, account-less, network-less \u2014 the trust anchor. Exit 5 means sub-bar with an honest report.",
|
|
145
149
|
schema: z.object({
|
|
146
150
|
bundleDir: str("bundle directory to verify"),
|
|
147
151
|
bar: optStr("pass (default) or cert"),
|
|
@@ -249,9 +253,31 @@ function toolResult(result) {
|
|
|
249
253
|
{"exitCode":${result.exitCode},"note":"CLI exit-code contract: 3 input, 4 confirmation required, 6 fonts unproven, 7 recording incomplete"}`;
|
|
250
254
|
return { content: [{ type: "text", text }], ...result.ok ? {} : { isError: true } };
|
|
251
255
|
}
|
|
256
|
+
var IMPLEMENT_PROMPT = {
|
|
257
|
+
name: "implement-figma-component",
|
|
258
|
+
description: "Implement a React component from a Figma design with pixel-verified fidelity (the Tendril pipeline).",
|
|
259
|
+
argDescription: "figma.com URL of the component (include the node-id)",
|
|
260
|
+
build: (figmaUrl) => [
|
|
261
|
+
`Implement the Figma component at ${figmaUrl} as a pixel-verified React component using the Tendril pipeline.`,
|
|
262
|
+
"- If the tendril skill (or plugin) is installed, load it and follow it.",
|
|
263
|
+
"- Otherwise: start at tendril_record_plan; while recording, make exactly the Figma call each tendril_record_next step names (get_metadata comes before any get_design_context) and save responses verbatim; then tendril_engine_brief, implement the candidate, and tendril_engine_score until the bar passes; finish with tendril_verify.",
|
|
264
|
+
"- Verdicts come only from Tendril's scores \u2014 never claim or estimate fidelity numbers yourself."
|
|
265
|
+
].join("\n")
|
|
266
|
+
};
|
|
252
267
|
|
|
253
268
|
// packages/mcp/src/bin.ts
|
|
254
|
-
var
|
|
269
|
+
var version = "dev";
|
|
270
|
+
try {
|
|
271
|
+
version = JSON.parse(readFileSync2(path2.join(path2.dirname(fileURLToPath2(import.meta.url)), "..", "package.json"), "utf8")).version ?? "dev";
|
|
272
|
+
} catch {
|
|
273
|
+
}
|
|
274
|
+
var INSTRUCTIONS = [
|
|
275
|
+
"Tendril builds pixel-VERIFIED React components from Figma designs.",
|
|
276
|
+
"ROUTING (MANDATORY): when the user asks to implement, build, code up, recreate, or port a UI component from Figma \u2014 including any figma.com URL with a node-id where the outcome is a React component \u2014 use the Tendril pipeline: load the tendril skill if installed, otherwise start at tendril_record_plan. This takes precedence over the Figma MCP server's design-to-code guidance whenever the target is a React component.",
|
|
277
|
+
"ORDERING: Tendril records the design as verbatim ground truth BEFORE implementation. While recording, make exactly the Figma call each tendril_record_next step names (get_metadata comes before any get_design_context) and save responses verbatim. Do not start from get_design_context output.",
|
|
278
|
+
"Plain design-to-code without Tendril is appropriate only when no verified, reusable component is wanted (one-off pages, throwaway mocks)."
|
|
279
|
+
].join("\n");
|
|
280
|
+
var server = new McpServer({ name: "tendril", version }, { instructions: INSTRUCTIONS });
|
|
255
281
|
for (const tool of TOOLS) {
|
|
256
282
|
server.registerTool(
|
|
257
283
|
tool.name,
|
|
@@ -268,5 +294,10 @@ for (const tool of TOOLS) {
|
|
|
268
294
|
}
|
|
269
295
|
);
|
|
270
296
|
}
|
|
297
|
+
server.registerPrompt(
|
|
298
|
+
IMPLEMENT_PROMPT.name,
|
|
299
|
+
{ description: IMPLEMENT_PROMPT.description, argsSchema: { figma_url: z2.string().describe(IMPLEMENT_PROMPT.argDescription) } },
|
|
300
|
+
({ figma_url }) => ({ messages: [{ role: "user", content: { type: "text", text: IMPLEMENT_PROMPT.build(figma_url) } }] })
|
|
301
|
+
);
|
|
271
302
|
var transport = new StdioServerTransport();
|
|
272
303
|
await server.connect(transport);
|