pattern-mcp 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/index.js +7 -0
- package/dist/init-enforcement.js +69 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,9 +15,10 @@ design reference.
|
|
|
15
15
|
|
|
16
16
|
[Website](https://usepattern.sh) · [npm](https://www.npmjs.com/package/pattern-mcp) · [Report an issue](https://github.com/donaldrichard19-LVD/pattern-mcp/issues/new/choose)
|
|
17
17
|
|
|
18
|
-
**Current release: v0.
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
**Current release: v0.11.0** — adds `pattern-check-gate init`, a guided
|
|
19
|
+
setup for the opt-in enforcement boundary (a `PreToolUse` hook plus a
|
|
20
|
+
paired CI check) so a new component decision can be required, not just
|
|
21
|
+
logged. See [Enforcement boundary: hook + CI
|
|
21
22
|
gate](#enforcement-boundary-hook--ci-gate).
|
|
22
23
|
|
|
23
24
|
<details>
|
package/dist/index.js
CHANGED
|
@@ -38,6 +38,7 @@ import { homedir } from "node:os";
|
|
|
38
38
|
import { dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
39
39
|
import { fileURLToPath } from "node:url";
|
|
40
40
|
import { captureApiError, captureRecommendation, getClient as getPostHogClient, installId, printTelemetryNoticeOnce, shutdownTelemetry, TELEMETRY_ENABLED, } from "./telemetry.js";
|
|
41
|
+
import { offerEnforcementSetupOnce } from "./init-enforcement.js";
|
|
41
42
|
export const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
|
|
42
43
|
// Only required for org-scoped keys (not tied to one workspace); unset for
|
|
43
44
|
// legacy workspace-scoped keys, which don't need it.
|
|
@@ -3864,6 +3865,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3864
3865
|
});
|
|
3865
3866
|
async function main() {
|
|
3866
3867
|
printTelemetryNoticeOnce();
|
|
3868
|
+
// Piggybacks on this same first-run moment (Option B, see
|
|
3869
|
+
// init-enforcement.ts) -- always prints a one-time, non-blocking mention;
|
|
3870
|
+
// only prompts interactively when stdin is a real TTY, never when a real
|
|
3871
|
+
// MCP client has piped stdio into this process for JSON-RPC. Always
|
|
3872
|
+
// returns before the transport below claims stdin.
|
|
3873
|
+
await offerEnforcementSetupOnce(PROJECT_ROOT);
|
|
3867
3874
|
const transport = new StdioServerTransport();
|
|
3868
3875
|
await server.connect(transport);
|
|
3869
3876
|
// Best-effort telemetry drain on clean shutdown -- no-op when telemetry
|
package/dist/init-enforcement.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
// post_ledger_provenance_to_github.
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
14
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
15
|
+
import { homedir } from "node:os";
|
|
15
16
|
import { dirname, join } from "node:path";
|
|
16
17
|
import { fileURLToPath } from "node:url";
|
|
17
18
|
import { createInterface } from "node:readline";
|
|
@@ -314,3 +315,71 @@ export async function runInit(root, options) {
|
|
|
314
315
|
}
|
|
315
316
|
console.log("\nDone. Review the changes with `git status` / `git diff`, then commit when ready.");
|
|
316
317
|
}
|
|
318
|
+
// Option B from BACKLOG.md's "Enforcement boundary setup" entry: piggyback
|
|
319
|
+
// on the moment someone's already setting Pattern up, rather than leaving
|
|
320
|
+
// enforcement as something only the README mentions. Called once from
|
|
321
|
+
// index.ts's main(), right alongside printTelemetryNoticeOnce, before the
|
|
322
|
+
// stdio transport connects.
|
|
323
|
+
//
|
|
324
|
+
// The literal original phrasing of this option ("extend the first-run
|
|
325
|
+
// notice into a [y/N] prompt") turns out not to be safely buildable as
|
|
326
|
+
// written: stdin is the live JSON-RPC channel a real MCP client uses to
|
|
327
|
+
// talk to this process (see telemetry.ts's printTelemetryNoticeOnce for
|
|
328
|
+
// the same constraint, stated first). Blocking it on a keypress here would
|
|
329
|
+
// fight the protocol handshake, not show a dialog. So this does two
|
|
330
|
+
// different things depending on how stdin is actually connected:
|
|
331
|
+
//
|
|
332
|
+
// - Always (any context, including a real client subprocess): print a
|
|
333
|
+
// one-time, non-blocking mention that the enforcement boundary exists
|
|
334
|
+
// and how to set it up. Same "print once, gated by a marker file"
|
|
335
|
+
// pattern as the telemetry notice, deliberately a separate marker/
|
|
336
|
+
// message so the two stay independently legible in a terminal.
|
|
337
|
+
// - Only when process.stdin.isTTY is true -- which a real MCP client's
|
|
338
|
+
// spawned subprocess never has, since it always pipes stdio to speak
|
|
339
|
+
// JSON-RPC over it, but a human running `npx pattern-mcp` bare in
|
|
340
|
+
// their own terminal does -- also offer a real interactive prompt,
|
|
341
|
+
// reusing runInit itself rather than duplicating its logic.
|
|
342
|
+
const ENFORCEMENT_NOTICE_PATH = process.env.PATTERN_ENFORCEMENT_NOTICE_PATH ?? join(homedir(), ".pattern", "enforcement_notice_shown");
|
|
343
|
+
export async function offerEnforcementSetupOnce(root) {
|
|
344
|
+
if (process.env.PATTERN_NO_ENFORCEMENT_NOTICE)
|
|
345
|
+
return;
|
|
346
|
+
try {
|
|
347
|
+
readFileSync(ENFORCEMENT_NOTICE_PATH, "utf8");
|
|
348
|
+
return; // Already shown -- never repeat, same discipline as the telemetry notice.
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
// No marker yet -- fall through and show it.
|
|
352
|
+
}
|
|
353
|
+
console.error([
|
|
354
|
+
"",
|
|
355
|
+
"Pattern -- enforcement boundary available (this will not print again)",
|
|
356
|
+
"By default, Pattern is something the calling agent chooses to use.",
|
|
357
|
+
"An opt-in hook + CI check can require it instead: run `npx pattern-check-gate init`",
|
|
358
|
+
"in your repo to set it up.",
|
|
359
|
+
"Full details: https://github.com/donaldrichard19-LVD/pattern-mcp#enforcement-boundary-hook--ci-gate",
|
|
360
|
+
"",
|
|
361
|
+
].join("\n"));
|
|
362
|
+
try {
|
|
363
|
+
mkdirSync(dirname(ENFORCEMENT_NOTICE_PATH), { recursive: true });
|
|
364
|
+
writeFileSync(ENFORCEMENT_NOTICE_PATH, new Date().toISOString(), "utf8");
|
|
365
|
+
}
|
|
366
|
+
catch {
|
|
367
|
+
// Couldn't persist the marker -- worst case this prints again next
|
|
368
|
+
// run. Never blocks startup over it, same as the telemetry notice.
|
|
369
|
+
}
|
|
370
|
+
if (!process.stdin.isTTY)
|
|
371
|
+
return;
|
|
372
|
+
try {
|
|
373
|
+
const setUpNow = await confirm("Set it up now?", { yes: false }, false);
|
|
374
|
+
if (setUpNow) {
|
|
375
|
+
await runInit(root, { yes: false }); // closes the shared readline itself, in its own finally block
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
finally {
|
|
379
|
+
// closeRl() is safe to call even if runInit already closed it (checks
|
|
380
|
+
// rl?.close() and no-ops on null) -- this just guarantees stdin is
|
|
381
|
+
// always released back before main() connects the stdio transport,
|
|
382
|
+
// whether the answer was no or runInit already cleaned up after itself.
|
|
383
|
+
closeRl();
|
|
384
|
+
}
|
|
385
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pattern-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "MCP server that turns your design guidance into a checkable process -- evaluates UI components from external libraries (shadcn/ui, 21st.dev, ReUI) or your own registered design system against a requirements checklist, then tells the agent whether to reuse an existing component or build one from a concrete design reference.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|