@usercase/mcp 0.2.1-next.1 → 0.2.1
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 +2 -2
- package/agents/condition.md +1 -1
- package/agents/steps.md +5 -3
- package/mcp/server.js +16 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -83,13 +83,13 @@ Claude reads your code to work out the route each task is meant to take, tells y
|
|
|
83
83
|
|
|
84
84
|
The dashboard's **New question** picks one simple moment (on arrival, after a pause, when leaving, after a click). For a moment made of several steps — "typed a search, opened no result, then did nothing for 10 seconds" — Claude writes it from your code and checks it against your recent real visits. Both need the API key.
|
|
85
85
|
|
|
86
|
-
**You wrote the question, and want it to appear at a precise moment.** In New question, choose **Several steps
|
|
86
|
+
**You wrote the question, and want it to appear at a precise moment.** In New question, choose **Several steps** and copy the command it gives you:
|
|
87
87
|
|
|
88
88
|
```
|
|
89
89
|
/mcp__usercase__steps <window id>
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
Claude reads
|
|
92
|
+
Claude reads your question, asks you when it should appear, writes the steps, and sends them back to that window. You see them there, and save the question as usual.
|
|
93
93
|
|
|
94
94
|
**You're not sure what to ask.** Run this and tell Claude who you want to hear from:
|
|
95
95
|
|
package/agents/condition.md
CHANGED
|
@@ -23,7 +23,7 @@ Rules that make a card actually appear and mean something:
|
|
|
23
23
|
|
|
24
24
|
Call `question_check` with the condition. Read the result:
|
|
25
25
|
- **Problems**: fix them and check again. The server refuses the condition while there are any.
|
|
26
|
-
- **
|
|
26
|
+
- **Does not match recent visits** (matched 0, a path or word not seen): usually a wrong path or word — compare with `question_context` and the code, and fix it. But the screen or button may be new or not live yet. Then tell the user it has not been seen in recent visits, and send it with `acceptWarnings: true` only if they say so.
|
|
27
27
|
- **Examples**: read what the matched visitors did. If it is not the situation the user meant, the condition is wrong even if it passes.
|
|
28
28
|
- **Overlaps**: an existing question fires at the same moment; only one card shows per visit. Tell the user.
|
|
29
29
|
- `idle` and `leave` moments are not counted by the check — it counts visits where the steps happened. Fewer people will actually see the card.
|
package/agents/steps.md
CHANGED
|
@@ -6,11 +6,11 @@ The user is writing a question in the Usercase dashboard (New question → Sever
|
|
|
6
6
|
|
|
7
7
|
You may read the code: the routes, the components, the labels on buttons.
|
|
8
8
|
|
|
9
|
-
## 1. Read
|
|
9
|
+
## 1. Read their question, then ask about the moment
|
|
10
10
|
|
|
11
|
-
Call `steps_brief` with the window id. It gives
|
|
11
|
+
Call `steps_brief` with the window id. It gives what is in their window right now: the page under Where and their question — either may still be empty, because people often choose Several steps before writing the question. That is normal; do not point it out. If the window id is missing or unknown, ask the user to choose Several steps again and copy the new command.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Then ask the user, in one short question, when the card should appear — what the visitor has done just before. If there is a question, suggest one moment that fits it so they can just say yes. If there is none, just ask about the moment; they will write the question in their window. If their answer is still vague, ask once more. Call `steps_brief` again before writing the condition — they may have filled in the window meanwhile.
|
|
14
14
|
|
|
15
15
|
## 2. Read the code and the visits
|
|
16
16
|
|
|
@@ -27,4 +27,6 @@ Make sure the moment fits their question: the card should appear when the visito
|
|
|
27
27
|
|
|
28
28
|
Tell the user in plain words when it will appear and how many recent visits matched, and anything you could not express. Then call `steps_send` with the window id, the condition and `triggerEn`. The steps appear in their dashboard window right away; they save the question there. Do not save a question yourself.
|
|
29
29
|
|
|
30
|
+
If they want it changed, fix it, check it again and send it to the same window id — the new steps replace the old ones in their window.
|
|
31
|
+
|
|
30
32
|
Do not change any code.
|
package/mcp/server.js
CHANGED
|
@@ -330,8 +330,16 @@ const QCondition = z.object({
|
|
|
330
330
|
function describeCheck(r) {
|
|
331
331
|
const L = [`Checked against ${r.visits} visits from the last ${r.days} days: matched ${r.matched}.`];
|
|
332
332
|
if (!r.visits) L.push("There are no recent visits yet, so the condition could only be checked for shape, not against real behavior.");
|
|
333
|
-
if (r.issues.length) L.push("", "Problems — fix these
|
|
333
|
+
if (r.issues.length) L.push("", "Problems — fix these; it cannot be saved with them:", ...r.issues.map((s) => `- ${s}`));
|
|
334
334
|
else L.push("No problems found.");
|
|
335
|
+
const warnings = r.warnings || [];
|
|
336
|
+
if (warnings.length)
|
|
337
|
+
L.push(
|
|
338
|
+
"",
|
|
339
|
+
"Does not match recent visits — fine if the screen or button is new or not live yet, otherwise likely a wrong path or word:",
|
|
340
|
+
...warnings.map((s) => `- ${s}`),
|
|
341
|
+
"To save anyway, tell the user, and only if they say so pass acceptWarnings: true.",
|
|
342
|
+
);
|
|
335
343
|
if (r.overlaps.length)
|
|
336
344
|
L.push("", "Fires at the same moment as existing questions (only one card shows per visit, so one of them would rarely appear):", ...r.overlaps.map((o) => `- "${o.question}" (${o.status})`));
|
|
337
345
|
if (r.examples.length) L.push("", "What some matched visitors did, up to the moment the question would appear:", ...r.examples.map((e) => "```\n" + e + "\n```"));
|
|
@@ -390,6 +398,7 @@ server.registerTool(
|
|
|
390
398
|
title: z.string().optional().describe("English, a few words, for the Inbox"),
|
|
391
399
|
why: z.string().optional().describe("English. What the team wants to learn, shown in the Inbox"),
|
|
392
400
|
triggerEn: z.string().optional().describe("English. One plain sentence: when and in what situation it appears. No paths or class names"),
|
|
401
|
+
acceptWarnings: z.boolean().optional().describe("true only after the user said to save even though it does not match recent visits"),
|
|
393
402
|
},
|
|
394
403
|
},
|
|
395
404
|
wrap(async (args) => {
|
|
@@ -398,6 +407,7 @@ server.registerTool(
|
|
|
398
407
|
r = await report.saveQuestion(args);
|
|
399
408
|
} catch (e) {
|
|
400
409
|
if (e.status === 422) throw new Error("The condition did not pass the check. Run question_check, fix the problems, then save again");
|
|
410
|
+
if (e.status === 409) throw new Error("It does not match recent visits. Tell the user; if they want it anyway (a new screen or button), save again with acceptWarnings: true");
|
|
401
411
|
throw e;
|
|
402
412
|
}
|
|
403
413
|
const L = [`Saved as a draft — matched ${r.matched} of ${r.visits} recent visits.`, `Open it in the Inbox to turn it on: ${report.dashboardUrl(r.inboxPath)}`];
|
|
@@ -410,14 +420,13 @@ server.registerTool(
|
|
|
410
420
|
server.registerTool(
|
|
411
421
|
"steps_brief",
|
|
412
422
|
{
|
|
413
|
-
description: "What the user wrote in their New question window: the
|
|
423
|
+
description: "What the user wrote in their New question window: the page under Where and their question. Call first in the steps procedure.",
|
|
414
424
|
inputSchema: { session: z.string().describe("The window id from the dashboard command") },
|
|
415
425
|
},
|
|
416
426
|
wrap(async ({ session }) => {
|
|
417
427
|
const b = await report.getStepsBrief(session);
|
|
418
428
|
return text(
|
|
419
429
|
[
|
|
420
|
-
`Moment they described: ${b.moment || "(nothing — ask the user)"}`,
|
|
421
430
|
`Where: ${b.where || "(empty)"}`,
|
|
422
431
|
`Their question: ${b.question || "(not written yet)"}`,
|
|
423
432
|
b.sent ? "Steps were already sent to this window once; sending again replaces them." : "",
|
|
@@ -437,14 +446,16 @@ server.registerTool(
|
|
|
437
446
|
session: z.string().describe("The window id from the dashboard command"),
|
|
438
447
|
condition: QCondition,
|
|
439
448
|
triggerEn: z.string().describe("English. One plain sentence: when and in what situation it appears. No paths or class names"),
|
|
449
|
+
acceptWarnings: z.boolean().optional().describe("true only after the user said to send it even though it does not match recent visits"),
|
|
440
450
|
},
|
|
441
451
|
},
|
|
442
|
-
wrap(async ({ session, condition, triggerEn }) => {
|
|
452
|
+
wrap(async ({ session, condition, triggerEn, acceptWarnings }) => {
|
|
443
453
|
let r;
|
|
444
454
|
try {
|
|
445
|
-
r = await report.sendSteps(session, { condition, triggerEn });
|
|
455
|
+
r = await report.sendSteps(session, { condition, triggerEn, acceptWarnings });
|
|
446
456
|
} catch (e) {
|
|
447
457
|
if (e.status === 422) throw new Error("The condition did not pass the check. Run question_check, fix the problems, then send again");
|
|
458
|
+
if (e.status === 409) throw new Error("It does not match recent visits. Tell the user; if they want it anyway (a new screen or button), send again with acceptWarnings: true");
|
|
448
459
|
throw e;
|
|
449
460
|
}
|
|
450
461
|
const L = [`Sent — the steps are now in the user's New question window (matched ${r.matched} of ${r.visits} recent visits). They save the question there.`];
|
package/package.json
CHANGED