pattern-mcp 0.15.0 → 0.16.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 CHANGED
@@ -15,22 +15,22 @@ 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.15.0** — `npx pattern-mcp init` is now the first
19
- and only command shown for getting started, everywhere (this README
20
- and the website); bare `npx pattern-mcp` is documented as the server
21
- command your client uses, not something to run yourself. The connect
22
- wizard also no longer asks just once: if you run Pattern bare in your
23
- own terminal and skip or miss it, it keeps offering on every later run
24
- until it can actually confirm a client is connected, instead of going
25
- silent forever after the first try. Previously: v0.14.1 made the
26
- crash/exit telemetry added in v0.14.0 (`pattern_cli_exited`) register
27
- before any of this file's own module-level code runs, and tagged both
28
- it and `pattern_cli_started` with the running package version, so a
29
- crash right around a release can be tied to the old or new binary. Before
30
- that: v0.14.0 made a crash on startup diagnosable instead of silent,
31
- warned at startup if `ANTHROPIC_API_KEY` is missing or clearly
32
- malformed instead of only surfacing a raw 401 mid-call, and added one
33
- respectful retry on a 429 (honoring `Retry-After`). See
18
+ **Current release: v0.16.0** — a component request that's on the
19
+ skip-list (`button`, `input`, ...) now succeeds with no
20
+ `ANTHROPIC_API_KEY` at all, instead of failing before it ever reached
21
+ that free, local check. When a real call does fail for a missing key,
22
+ the error now names two concrete fixes (re-run `init`, or export the
23
+ key directly) instead of just naming the problem. Codex CLI's connect
24
+ instructions also now carry whatever API key you entered in the
25
+ wizard, as a ready-to-run shell export, instead of silently dropping
26
+ it. Previously: v0.15.0 made `npx pattern-mcp init` the first and only
27
+ command shown for getting started, everywhere (this README and the
28
+ website), and the connect wizard stopped asking just once -- it now
29
+ keeps offering on later bare runs until it can confirm a client is
30
+ actually connected. Before that: v0.14.1 made the crash/exit telemetry
31
+ added in v0.14.0 (`pattern_cli_exited`) register before any of this
32
+ file's own module-level code runs, and tagged it and
33
+ `pattern_cli_started` with the running package version. See
34
34
  [Connect Pattern to your MCP client](#connect-pattern-to-your-mcp-client)
35
35
  for more details.
36
36
 
@@ -192,10 +192,21 @@ async function setupCursor(root, apiKey, options) {
192
192
  // existing config is worse than just telling them what to add. Detected
193
193
  // the same way as the other targets (evidence it's actually used), but
194
194
  // only ever prints instructions.
195
- function offerCodexInstructions() {
195
+ //
196
+ // Deliberately does NOT print a per-server `env = {...}` TOML snippet for
197
+ // the API key, unlike the command/args lines above -- checked directly
198
+ // (openai/codex#7521, open as of 2026-09): Codex's own maintainers hadn't
199
+ // settled which env-var syntax their TOML config actually supports at the
200
+ // time this was written. Printing a guessed snippet risked giving
201
+ // confidently wrong instructions, worse than the honest "it depends on
202
+ // your version, here's what works regardless" below. A plain shell
203
+ // export is the one method that works the same way across every Codex
204
+ // version and every other client here, since it never depends on a
205
+ // client-specific config format at all.
206
+ function offerCodexInstructions(apiKey) {
196
207
  if (!existsSync(join(homedir(), ".codex")))
197
208
  return;
198
- console.log([
209
+ const lines = [
199
210
  "\nCodex CLI detected (~/.codex exists). Pattern doesn't auto-write Codex's",
200
211
  "TOML config -- add this to ~/.codex/config.toml (or .codex/config.json for",
201
212
  "this project only):",
@@ -203,7 +214,15 @@ function offerCodexInstructions() {
203
214
  ' [mcp_servers.pattern]',
204
215
  ' command = "npx"',
205
216
  ' args = ["pattern-mcp"]',
206
- ].join("\n"));
217
+ "",
218
+ ];
219
+ if (apiKey) {
220
+ lines.push("You entered an API key above. Codex's own per-server TOML env syntax isn't", "reliably documented across versions, so the safest way to get it to Codex", "is exporting it in the shell you launch Codex from:", "", ` export ANTHROPIC_API_KEY="${apiKey}"`);
221
+ }
222
+ else {
223
+ lines.push("Codex also needs ANTHROPIC_API_KEY available in its own environment.", "Export it in the shell you launch Codex from:", "", " export ANTHROPIC_API_KEY=sk-ant-...");
224
+ }
225
+ console.log(lines.join("\n"));
207
226
  }
208
227
  async function promptApiKey(options) {
209
228
  if (options.yes)
@@ -233,7 +252,7 @@ export async function runConnect(root, options) {
233
252
  }
234
253
  if (existsSync(join(homedir(), ".codex"))) {
235
254
  anyDetected = true;
236
- offerCodexInstructions();
255
+ offerCodexInstructions(apiKey);
237
256
  }
238
257
  if (!anyDetected) {
239
258
  console.log("\nNo supported MCP client was detected on this machine automatically.\n" + connectInstructionsText());
package/dist/index.js CHANGED
@@ -111,6 +111,19 @@ function warnIfAnthropicKeyLooksWrong() {
111
111
  "\"sk-ant-\"). If a tool call fails with a 401, check this value first.");
112
112
  }
113
113
  }
114
+ // Thrown by recommend_component/extract_requirements when they actually
115
+ // need the API and no key is present -- this is what the calling agent
116
+ // sees as the tool's error result, so unlike warnIfAnthropicKeyLooksWrong's
117
+ // stderr line (invisible in most real clients -- see
118
+ // project_pattern_activation_funnel memory), this is the message a real
119
+ // user is actually likely to see. Gives two concrete fixes rather than
120
+ // just naming the problem: re-running `init` (which already offers to
121
+ // write the key into every client it detects), or exporting it directly --
122
+ // the one method that works the same way across every client, since it
123
+ // doesn't depend on any client-specific config format.
124
+ const MISSING_API_KEY_MESSAGE = "Pattern: ANTHROPIC_API_KEY is not set, so this call can't reach the Anthropic API. Fix it one of two ways: " +
125
+ "re-run `npx pattern-mcp init` to add it to your MCP client's config, or export it directly -- " +
126
+ "`export ANTHROPIC_API_KEY=sk-ant-...` in the shell your client launches Pattern from, then restart the client.";
114
127
  // Configurable so Sonnet vs. Haiku can be A/B tested without a code change.
115
128
  // Defaults to Sonnet 5. Try MODEL=claude-haiku-4-5-20251001 to test the
116
129
  // cheaper tier -- re-run the 5 validated test cases from the product brief
@@ -1173,14 +1186,15 @@ export function estimateExtractionConfidence(componentNeed) {
1173
1186
  return "high";
1174
1187
  }
1175
1188
  async function runSinglePass(input) {
1176
- if (!ANTHROPIC_API_KEY) {
1177
- throw new Error("ANTHROPIC_API_KEY is not set. Export it in the environment running this MCP server.");
1178
- }
1179
1189
  const passStartMs = Date.now();
1180
1190
  const checklistSource = input.checklist && input.checklist.length > 0 ? "provided" : "extracted";
1181
1191
  // Fast path: skip-list check happens locally too, so trivial primitives
1182
1192
  // never spend a real API call. The system prompt also enforces this, but
1183
- // checking here avoids the round-trip entirely for the common case.
1193
+ // checking here avoids the round-trip entirely for the common case. The
1194
+ // ANTHROPIC_API_KEY check used to run before this, unconditionally --
1195
+ // meaning a keyless install couldn't get even this free, local path.
1196
+ // Moved below the skip-list return so a missing/invalid key only ever
1197
+ // blocks the cases that actually need the API.
1184
1198
  if (isSkipListMatch(input.component_need)) {
1185
1199
  const skipListElapsedMs = Math.max(1, Date.now() - passStartMs);
1186
1200
  return {
@@ -1213,6 +1227,9 @@ async function runSinglePass(input) {
1213
1227
  },
1214
1228
  };
1215
1229
  }
1230
+ if (!ANTHROPIC_API_KEY) {
1231
+ throw new Error(MISSING_API_KEY_MESSAGE);
1232
+ }
1216
1233
  // Coverage still computes fresh below regardless of what this finds --
1217
1234
  // memory (MEMORY_PATH/record_component_decision) only ever adds context
1218
1235
  // to the user message, it never short-circuits search/scoring or gets
@@ -1526,9 +1543,6 @@ existing_stack: ${input.existing_stack ?? "(not specified)"}${checklistBlock}${p
1526
1543
  // for the same reason (trivial primitives shouldn't cost an API call here
1527
1544
  // either).
1528
1545
  async function runExtraction(input) {
1529
- if (!ANTHROPIC_API_KEY) {
1530
- throw new Error("ANTHROPIC_API_KEY is not set. Export it in the environment running this MCP server.");
1531
- }
1532
1546
  const startMs = Date.now();
1533
1547
  if (isSkipListMatch(input.component_need)) {
1534
1548
  const elapsedMs = Math.max(1, Date.now() - startMs);
@@ -1546,6 +1560,9 @@ async function runExtraction(input) {
1546
1560
  },
1547
1561
  };
1548
1562
  }
1563
+ if (!ANTHROPIC_API_KEY) {
1564
+ throw new Error(MISSING_API_KEY_MESSAGE);
1565
+ }
1549
1566
  const userMessage = `component_need: ${input.component_need}\ndomain: ${input.domain}`;
1550
1567
  const data = await streamAnthropicMessage({
1551
1568
  model: MODEL,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pattern-mcp",
3
- "version": "0.15.0",
3
+ "version": "0.16.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",