@paigy/mcp 0.7.0 → 0.8.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.
Files changed (2) hide show
  1. package/dist/index.js +2 -2
  2. package/package.json +9 -10
package/dist/index.js CHANGED
@@ -72,7 +72,7 @@ var server = new Server(
72
72
  { name: "paigy", version: "0.0.0" },
73
73
  {
74
74
  capabilities: { tools: {} },
75
- instructions: "On startup, call check_replies once to pick up any replies or pending work you missed while away. To wait for the answer to something you just asked, call await_reply with that notification's id \u2014 it's scoped to that one request, so it never returns replies meant for other requests. Use check_replies again only when re-booting or after waiting a long time on something else. Never end a turn that still needs the user without notify_user + await_reply. When you need a decision or input, PREFER a structured answer (select:'confirm', 'one', 'many', or 'rank') over an open-ended free-text ask \u2014 structured options save the user a tap, and they can always add free text on top. If a reply comes back as { kind: 'clarify', chunks: [...] }, the user wants more detail on those chunks \u2014 respond by calling notify_user again with the SAME threadId and an expanded description covering them. When urgency is 'call', remember the title + description are spoken aloud \u2014 write them short and conversational, and name things instead of using IDs (e.g. 'the pull request about the agents page', not 'PR #235'). When the user asks you to follow up later \u2014 when you're done, if you're blocked, or at a set time \u2014 record it with schedule_callback so you don't drop it if you go idle."
75
+ instructions: "On startup, call check_replies once to pick up any replies or pending work you missed while away. To wait for the answer to something you just asked, call await_reply with that notification's id \u2014 it's scoped to that one request, so it never returns replies meant for other requests. Use check_replies again only when re-booting or after waiting a long time on something else. Never end a turn that still needs the user without notify_user + await_reply. When you need a decision or input, MATCH the answer shape to the question \u2014 don't default everything to free text, and don't reflexively make everything yes/no. Pick the best tool for the job: yes/no \u2192 select:'confirm'; approve/deny an action \u2192 select:'confirm' + confirmStyle:'approve'; pick one of several \u2192 options + select:'one'; pick several / a subset \u2192 options + select:'many'; rank or prioritize \u2192 options + select:'rank'. Reserve open-ended free text only for answers that genuinely can't be structured (the user can always add free text on top of any shape). If a reply comes back as { kind: 'clarify', chunks: [...] }, the user wants more detail on those chunks \u2014 respond by calling notify_user again with the SAME threadId and an expanded description covering them. When urgency is 'call', remember the title + description are spoken aloud \u2014 write them short and conversational, and name things instead of using IDs (e.g. 'the pull request about the agents page', not 'PR #235'). When the user asks you to follow up later \u2014 when you're done, if you're blocked, or at a set time \u2014 record it with schedule_callback so you don't drop it if you go idle."
76
76
  }
77
77
  );
78
78
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
@@ -89,7 +89,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
89
89
  },
90
90
  {
91
91
  name: "notify_user",
92
- description: "Notify the user via Paigy and get a request id to poll for their answer. Provide context.title (a specific, non-empty one-line headline \u2014 this is what the user sees first, and what shows on the ring for a call) and context.description (an array of standalone, non-empty detail chunks the user can selectively ask you to expand). Set `urgency`: 'inbox' (default) drops it silently in their inbox; 'push' is a quiet passive notification (no sound); 'banner' sends a time-sensitive banner/lock-screen push (a 'paige') they tap to open \u2014 for when you need them soon-ish but not enough to ring them; 'call' rings their phone now as a voice call \u2014 only when you genuinely need them in the moment (blocked/waiting, time-sensitive). ON A CALL, your title + description are READ ALOUD by a voice \u2014 write them to be HEARD, not read: keep it short and conversational, front-load the ask, and refer to things BY NAME, not by ID or code (say 'the pull request about the agents page', not 'PR #235'; 'the login-bug ticket', not 'ABC-1234'). Spell out only what's natural to say out loud. DEFAULT to a structured answer shape \u2014 structured options save the user a tap, and they can ALWAYS add free text on top of any structured paige, so you lose nothing by structuring it. Pick the answer shape with `select` \u2014 DON'T leave a decision as open-ended free text: a yes/no or approve/deny \u2192 select:'confirm' (set confirmStyle:'approve' for Approve/Deny); it's answerable right from the banner and arrives as {kind:'confirm', approved:boolean}. Pick one of several \u2192 options + select:'one' (default) \u2192 {kind:'option', optionId}. Pick several \u2192 select:'many' \u2192 {kind:'multi', optionIds:[...]}. Rank/order a subset \u2192 select:'rank', user taps in preferred order \u2192 {kind:'ranked', optionIds:[...]}. For visual choices give each option a sandboxed `html` or an `image` preview (e.g. layout/UI alternatives). Only leave options off (pure free text / voice) when the answer genuinely can't be structured. Plus optional visuals. If a reply comes back as {kind:'clarify', chunks:[...]}, the user wants more detail on those chunks \u2014 respond via notify_user with the SAME threadId and an expanded description. Pass `threadId` from a prior notify_user result or an await_reply reply to continue that conversation thread; omit it to start a new one. To follow up on a call (e.g. the user asked you to 'call me back when it's done'), reuse the threadId from that call's reply so it threads as the same conversation.",
92
+ description: "Notify the user via Paigy and get a request id to poll for their answer. Provide context.title (a specific, non-empty one-line headline \u2014 this is what the user sees first, and what shows on the ring for a call) and context.description (an array of standalone, non-empty detail chunks the user can selectively ask you to expand). Set `urgency`: 'inbox' (default) drops it silently in their inbox; 'push' is a quiet passive notification (no sound); 'banner' sends a time-sensitive banner/lock-screen push (a 'paige') they tap to open \u2014 for when you need them soon-ish but not enough to ring them; 'call' rings their phone now as a voice call \u2014 only when you genuinely need them in the moment (blocked/waiting, time-sensitive). ON A CALL, your title + description are READ ALOUD by a voice \u2014 write them to be HEARD, not read: keep it short and conversational, front-load the ask, and refer to things BY NAME, not by ID or code (say 'the pull request about the agents page', not 'PR #235'; 'the login-bug ticket', not 'ABC-1234'). Spell out only what's natural to say out loud. MATCH the answer shape to the question \u2014 pick the best tool for the job, not always yes/no. The user can ALWAYS add free text on top of any shape, so structuring loses nothing. Choose `select`: yes/no \u2192 select:'confirm' \u2192 {kind:'confirm', approved:boolean}. Approve/deny an action \u2192 select:'confirm' + confirmStyle:'approve' \u2192 {kind:'confirm', approved:boolean}. Both are answerable right from the banner. Pick one of several \u2192 options + select:'one' \u2192 {kind:'option', optionId}. Pick several / a subset \u2192 options + select:'many' \u2192 {kind:'multi', optionIds:[...]}. Rank or prioritize \u2192 options + select:'rank', user taps in preferred order \u2192 {kind:'ranked', optionIds:[...]}. For visual choices give each option a sandboxed `html` or an `image` preview (e.g. layout/UI alternatives). Only leave options off (pure free text / voice) when the answer genuinely can't be structured. Plus optional visuals. If a reply comes back as {kind:'clarify', chunks:[...]}, the user wants more detail on those chunks \u2014 respond via notify_user with the SAME threadId and an expanded description. Pass `threadId` from a prior notify_user result or an await_reply reply to continue that conversation thread; omit it to start a new one. To follow up on a call (e.g. the user asked you to 'call me back when it's done'), reuse the threadId from that call's reply so it threads as the same conversation.",
93
93
  inputSchema: zodToJsonSchema(NotifyRequestSchema, { target: "openApi3" })
94
94
  },
95
95
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paigy/mcp",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Paigy MCP server — a voice inbox for your AI agents. Lets an agent notify a user and await their reply.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -21,13 +21,6 @@
21
21
  "url": "git+https://github.com/mauurda/paigy.git",
22
22
  "directory": "apps/mcp"
23
23
  },
24
- "scripts": {
25
- "build": "tsup src/index.ts src/onboard.ts src/listen.ts --format esm --clean",
26
- "dev": "tsup src/index.ts src/onboard.ts src/listen.ts --format esm --watch",
27
- "typecheck": "tsc --noEmit",
28
- "test": "vitest run",
29
- "prepublishOnly": "pnpm --filter @paigy/schema build && pnpm build"
30
- },
31
24
  "dependencies": {
32
25
  "@modelcontextprotocol/sdk": "^1.0.4",
33
26
  "@supabase/supabase-js": "^2.47.10",
@@ -35,10 +28,16 @@
35
28
  "zod-to-json-schema": "^3.24.1"
36
29
  },
37
30
  "devDependencies": {
38
- "@paigy/schema": "workspace:*",
39
31
  "@types/node": "^22.0.0",
40
32
  "tsup": "^8.3.5",
41
33
  "typescript": "^5.7.2",
42
- "vitest": "^2.1.8"
34
+ "vitest": "^2.1.8",
35
+ "@paigy/schema": "0.0.0"
36
+ },
37
+ "scripts": {
38
+ "build": "tsup src/index.ts src/onboard.ts src/listen.ts --format esm --clean",
39
+ "dev": "tsup src/index.ts src/onboard.ts src/listen.ts --format esm --watch",
40
+ "typecheck": "tsc --noEmit",
41
+ "test": "vitest run"
43
42
  }
44
43
  }