@rvry/mcp 0.13.0 → 1.0.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 +10 -5
- package/dist/client.d.ts +2 -2
- package/dist/index.d.ts +17 -6
- package/dist/index.js +133 -20
- package/dist/local-writer.d.ts +2 -0
- package/dist/local-writer.js +15 -1
- package/dist/setup.d.ts +25 -0
- package/dist/setup.js +78 -18
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -41,12 +41,15 @@ Get your token at [rvry.ai/dashboard](https://rvry.ai/dashboard) after signing u
|
|
|
41
41
|
|
|
42
42
|
| Tool | What it does | Tier |
|
|
43
43
|
|------|-------------|------|
|
|
44
|
+
| **`rvry`** | Lighter single-session analysis for questions that need structure but not the full deepthink loop. (Renamed from `think` in 1.0.0.) | All |
|
|
44
45
|
| **`deepthink`** | Extended multi-round analysis. Catches assumptions, tests them, and doesn't let your AI wrap up until it's dealt with what it found. | All |
|
|
45
|
-
| **`
|
|
46
|
+
| **`shimmer`** | Three-round reflective answering: a protected observation round surfaces commitments the answer must honor, then the answer is produced under them, then at most one resolution round. | All |
|
|
46
47
|
| **`problem_solve`** | Structured decision-making. Forces orientation, anticipation, and evaluation before committing to a recommendation. | Pro+ |
|
|
47
48
|
| **`challenge`** | Adversarial stress-testing. Finds weaknesses, tests assumptions, and surfaces failure modes in a proposal before you commit. | Pro+ |
|
|
48
49
|
| **`meta`** | Sustained metacognitive observation. Examines how your AI is thinking, not just what it's thinking. | Max |
|
|
49
50
|
|
|
51
|
+
A `think` tombstone tool remains for backward compatibility — calling it returns a notice pointing at `rvry`. It will be removed at 2.0.0.
|
|
52
|
+
|
|
50
53
|
### Parameters
|
|
51
54
|
|
|
52
55
|
All tools accept:
|
|
@@ -70,23 +73,25 @@ All tools accept:
|
|
|
70
73
|
|
|
71
74
|
## Slash Commands (Claude Code)
|
|
72
75
|
|
|
73
|
-
When you run `npx --yes --package @rvry/mcp@latest rvry-mcp setup` and select Claude Code, the wizard installs
|
|
76
|
+
When you run `npx --yes --package @rvry/mcp@latest rvry-mcp setup` and select Claude Code, the wizard installs these slash commands:
|
|
74
77
|
|
|
75
78
|
| Command | Tool | What it does |
|
|
76
79
|
|---------|------|-------------|
|
|
80
|
+
| `/rvry` | rvry | Structured single-session analysis with a Difficulty Gate |
|
|
77
81
|
| `/deepthink` | deepthink | Deep multi-round analysis |
|
|
78
|
-
| `/
|
|
82
|
+
| `/shimmer` | shimmer | Reflective answering under surfaced commitments |
|
|
79
83
|
| `/problem-solve` | problem_solve | Structured decision-making |
|
|
80
84
|
| `/challenge` | challenge | Adversarial stress-testing |
|
|
81
85
|
| `/meta` | meta | Metacognitive observation |
|
|
86
|
+
| `/think` | rvry | Deprecated alias for `/rvry` (removed next major) |
|
|
82
87
|
|
|
83
88
|
Usage: type `/deepthink [your question]` in Claude Code. Each command routes to the corresponding RVRY MCP tool and includes rendering instructions so analysis appears as visible markdown rather than hidden in tool calls.
|
|
84
89
|
|
|
85
90
|
**`--record` flag:** Append `--record` to any command (e.g. `/deepthink --record [question]`) to archive per-round bodies under `.rvry/<op>/<slug>/round-N-<mode>.md` alongside the harvest file.
|
|
86
91
|
|
|
87
|
-
**Updating commands:**
|
|
92
|
+
**Updating commands:** Re-running setup refreshes the RVRY-owned command files. Any pre-existing file is backed up to `<name>.md.bak` before it is overwritten.
|
|
88
93
|
|
|
89
|
-
Commands are installed to `~/.claude/commands/`.
|
|
94
|
+
Commands are installed to `~/.claude/commands/`.
|
|
90
95
|
|
|
91
96
|
## How it Works
|
|
92
97
|
|
package/dist/client.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* RVRY MCP Client -- HTTP client for the RVRY engine /api/v1/think endpoint.
|
|
3
3
|
*/
|
|
4
4
|
/** Valid tool names for the RVRY engine */
|
|
5
|
-
export type RvryTool = 'deepthink' | 'problem_solve' | 'think' | 'challenge' | 'meta';
|
|
5
|
+
export type RvryTool = 'deepthink' | 'problem_solve' | 'think' | 'challenge' | 'meta' | 'shimmer';
|
|
6
6
|
export interface ScopingQuestion {
|
|
7
7
|
question: string;
|
|
8
8
|
options: Array<{
|
|
@@ -13,7 +13,7 @@ export interface ScopingQuestion {
|
|
|
13
13
|
}
|
|
14
14
|
export interface ThinkResponse {
|
|
15
15
|
sessionId: string;
|
|
16
|
-
status: 'scoping' | 'orient' | 'active' | 'complete';
|
|
16
|
+
status: 'scoping' | 'shimmer' | 'orient' | 'active' | 'complete';
|
|
17
17
|
round: number;
|
|
18
18
|
prompt: string;
|
|
19
19
|
instruction: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* Thin client that proxies tool calls to the RVRY engine HTTP API.
|
|
6
6
|
* Auth via RVRY_TOKEN env var (static rvry_ token).
|
|
7
7
|
*
|
|
8
|
-
* Exposes
|
|
8
|
+
* Exposes 6 tools (rvry, deepthink, problem_solve, challenge, meta, shimmer)
|
|
9
|
+
* + RVRY_* backward-compat aliases + a `think` tombstone (renamed to rvry,
|
|
10
|
+
* removed at 2.0.0) + MCP Prompts.
|
|
9
11
|
*
|
|
10
12
|
* Also supports `npx --yes --package @rvry/mcp@latest rvry-mcp setup` to install Claude Code commands.
|
|
11
13
|
*/
|
|
@@ -14,11 +16,20 @@ import { type RvryTool, type ThinkResponse } from './client.js';
|
|
|
14
16
|
/** Cache original question per session for response enrichment */
|
|
15
17
|
declare const questionCache: Map<string, string>;
|
|
16
18
|
/**
|
|
17
|
-
* Map tool name to RvryTool.
|
|
18
|
-
*
|
|
19
|
+
* Map tool name to RvryTool (the engine wire name).
|
|
20
|
+
* `rvry` maps to the engine's think operation. `think`/`RVRY_think` are
|
|
21
|
+
* tombstones handled before this map is consulted.
|
|
19
22
|
*/
|
|
20
23
|
declare const TOOL_MAP: Record<string, RvryTool>;
|
|
24
|
+
/** Non-error tombstone notice for the renamed think tool. Removed at 2.0.0. */
|
|
25
|
+
declare const THINK_TOMBSTONE_NOTICE = "The think tool has been renamed to rvry. Call the rvry tool with the same arguments (input, sessionId, ...).";
|
|
21
26
|
declare const TOOL_DEFS: Tool[];
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Strip response fields based on status for context-efficient MCP responses.
|
|
29
|
+
*
|
|
30
|
+
* `toolName` is the public MCP tool name of the call in scope. The 'shimmer'
|
|
31
|
+
* status passthrough applies ONLY when the called tool is shimmer (R-6):
|
|
32
|
+
* legacy ops keep dropping prompt/instruction on their priming round.
|
|
33
|
+
*/
|
|
34
|
+
declare function stripResponse(result: ThinkResponse, question: string, toolName?: string): Record<string, unknown>;
|
|
35
|
+
export { TOOL_MAP, TOOL_DEFS, stripResponse, questionCache, THINK_TOMBSTONE_NOTICE };
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* Thin client that proxies tool calls to the RVRY engine HTTP API.
|
|
6
6
|
* Auth via RVRY_TOKEN env var (static rvry_ token).
|
|
7
7
|
*
|
|
8
|
-
* Exposes
|
|
8
|
+
* Exposes 6 tools (rvry, deepthink, problem_solve, challenge, meta, shimmer)
|
|
9
|
+
* + RVRY_* backward-compat aliases + a `think` tombstone (renamed to rvry,
|
|
10
|
+
* removed at 2.0.0) + MCP Prompts.
|
|
9
11
|
*
|
|
10
12
|
* Also supports `npx --yes --package @rvry/mcp@latest rvry-mcp setup` to install Claude Code commands.
|
|
11
13
|
*/
|
|
@@ -19,23 +21,26 @@ const PKG_VERSION = require('../package.json').version;
|
|
|
19
21
|
/** Cache original question per session for response enrichment */
|
|
20
22
|
const questionCache = new Map();
|
|
21
23
|
/**
|
|
22
|
-
* Map tool name to RvryTool.
|
|
23
|
-
*
|
|
24
|
+
* Map tool name to RvryTool (the engine wire name).
|
|
25
|
+
* `rvry` maps to the engine's think operation. `think`/`RVRY_think` are
|
|
26
|
+
* tombstones handled before this map is consulted.
|
|
24
27
|
*/
|
|
25
28
|
const TOOL_MAP = {
|
|
26
|
-
// Primary
|
|
27
|
-
|
|
28
|
-
RVRY_problem_solve: 'problem_solve',
|
|
29
|
-
RVRY_think: 'think',
|
|
30
|
-
RVRY_challenge: 'challenge',
|
|
31
|
-
RVRY_meta: 'meta',
|
|
32
|
-
// Backward-compat aliases (unprefixed)
|
|
29
|
+
// Primary
|
|
30
|
+
rvry: 'think',
|
|
33
31
|
deepthink: 'deepthink',
|
|
34
32
|
problem_solve: 'problem_solve',
|
|
35
|
-
think: 'think',
|
|
36
33
|
challenge: 'challenge',
|
|
37
34
|
meta: 'meta',
|
|
35
|
+
shimmer: 'shimmer',
|
|
36
|
+
// Backward-compat aliases (RVRY_ prefixed)
|
|
37
|
+
RVRY_deepthink: 'deepthink',
|
|
38
|
+
RVRY_problem_solve: 'problem_solve',
|
|
39
|
+
RVRY_challenge: 'challenge',
|
|
40
|
+
RVRY_meta: 'meta',
|
|
38
41
|
};
|
|
42
|
+
/** Non-error tombstone notice for the renamed think tool. Removed at 2.0.0. */
|
|
43
|
+
const THINK_TOMBSTONE_NOTICE = 'The think tool has been renamed to rvry. Call the rvry tool with the same arguments (input, sessionId, ...).';
|
|
39
44
|
const TOOL_DEFS = [
|
|
40
45
|
{
|
|
41
46
|
name: 'deepthink',
|
|
@@ -225,7 +230,7 @@ const TOOL_DEFS = [
|
|
|
225
230
|
},
|
|
226
231
|
},
|
|
227
232
|
{
|
|
228
|
-
name: '
|
|
233
|
+
name: 'rvry',
|
|
229
234
|
description: 'Structured analysis for questions needing more depth than a quick answer. ' +
|
|
230
235
|
'Runs 1-3 rounds; simple questions can complete in a single analytical round. ' +
|
|
231
236
|
'The first response orients you — follow the instruction field, then call again. ' +
|
|
@@ -496,9 +501,98 @@ const TOOL_DEFS = [
|
|
|
496
501
|
required: ['input'],
|
|
497
502
|
},
|
|
498
503
|
},
|
|
504
|
+
{
|
|
505
|
+
name: 'shimmer',
|
|
506
|
+
description: 'Three-round reflective answering: a protected observation round where the answer is watched forming ' +
|
|
507
|
+
'(surfacing commitments the answer must honor), then the answer itself under those commitments, ' +
|
|
508
|
+
'then at most one resolution round for anything left unaddressed. ' +
|
|
509
|
+
'The first response is a visible observation round — show it in full, beginning with the RVRY SHIMMER header. ' +
|
|
510
|
+
'Use when the quality of the answer depends on noticing what it wants to skip. ' +
|
|
511
|
+
'Call with your question to start, then send each round\'s text with the returned sessionId to continue.',
|
|
512
|
+
inputSchema: {
|
|
513
|
+
type: 'object',
|
|
514
|
+
properties: {
|
|
515
|
+
input: {
|
|
516
|
+
type: 'string',
|
|
517
|
+
description: 'The question to answer (new session) or your round text (continuation).',
|
|
518
|
+
},
|
|
519
|
+
sessionId: {
|
|
520
|
+
type: 'string',
|
|
521
|
+
description: 'Session ID for continuing an existing session. Omit to start a new session.',
|
|
522
|
+
},
|
|
523
|
+
requiresCurrentData: {
|
|
524
|
+
type: 'boolean',
|
|
525
|
+
description: 'Set to true when the question depends on facts, policies, prices, regulations, or events that may have changed.',
|
|
526
|
+
},
|
|
527
|
+
record: {
|
|
528
|
+
type: 'boolean',
|
|
529
|
+
description: 'Set to true on every call in this session when the user passed --record, so the client accumulates per-round bodies for local archive.',
|
|
530
|
+
},
|
|
531
|
+
harvest: {
|
|
532
|
+
type: 'object',
|
|
533
|
+
description: 'Final-call-only. When status will transition to complete, include your synthesis here so it can be persisted to the local session file.',
|
|
534
|
+
properties: {
|
|
535
|
+
title: { type: 'string', description: '1-4 word title for this session' },
|
|
536
|
+
summary: { type: 'string', description: '3-6 sentences synthesizing the analysis' },
|
|
537
|
+
keyFindings: { type: 'array', items: { type: 'string' }, description: '3-7 bullet findings' },
|
|
538
|
+
shimmer: { type: 'string', description: 'Full round-1 observation text, verbatim' },
|
|
539
|
+
constraintLedger: {
|
|
540
|
+
type: 'array',
|
|
541
|
+
items: { type: 'string' },
|
|
542
|
+
description: 'One line per surfaced commitment with its fate (addressed, deferred with reason, or open).',
|
|
543
|
+
},
|
|
544
|
+
openQuestions: { type: 'array', items: { type: 'string' } },
|
|
545
|
+
followUps: {
|
|
546
|
+
type: 'array',
|
|
547
|
+
items: {
|
|
548
|
+
type: 'object',
|
|
549
|
+
properties: {
|
|
550
|
+
question: { type: 'string' },
|
|
551
|
+
rationale: { type: 'string' },
|
|
552
|
+
},
|
|
553
|
+
},
|
|
554
|
+
},
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
rounds: {
|
|
558
|
+
type: 'array',
|
|
559
|
+
description: 'Final-call-only, present only when --record was set. Array of {round, mode, body} for each analytical round.',
|
|
560
|
+
items: {
|
|
561
|
+
type: 'object',
|
|
562
|
+
properties: {
|
|
563
|
+
round: { type: 'number' },
|
|
564
|
+
mode: { type: 'string' },
|
|
565
|
+
body: { type: 'string' },
|
|
566
|
+
},
|
|
567
|
+
},
|
|
568
|
+
},
|
|
569
|
+
},
|
|
570
|
+
required: ['input'],
|
|
571
|
+
},
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
name: 'think',
|
|
575
|
+
description: 'Renamed to rvry. Call the rvry tool instead — same arguments, same behavior. ' +
|
|
576
|
+
'This tombstone will be removed at 2.0.0.',
|
|
577
|
+
inputSchema: {
|
|
578
|
+
type: 'object',
|
|
579
|
+
properties: {
|
|
580
|
+
input: {
|
|
581
|
+
type: 'string',
|
|
582
|
+
description: 'Ignored. Call the rvry tool instead.',
|
|
583
|
+
},
|
|
584
|
+
},
|
|
585
|
+
},
|
|
586
|
+
},
|
|
499
587
|
];
|
|
500
|
-
/**
|
|
501
|
-
|
|
588
|
+
/**
|
|
589
|
+
* Strip response fields based on status for context-efficient MCP responses.
|
|
590
|
+
*
|
|
591
|
+
* `toolName` is the public MCP tool name of the call in scope. The 'shimmer'
|
|
592
|
+
* status passthrough applies ONLY when the called tool is shimmer (R-6):
|
|
593
|
+
* legacy ops keep dropping prompt/instruction on their priming round.
|
|
594
|
+
*/
|
|
595
|
+
function stripResponse(result, question, toolName) {
|
|
502
596
|
const stripped = {
|
|
503
597
|
sessionId: result.sessionId,
|
|
504
598
|
status: result.status,
|
|
@@ -512,6 +606,10 @@ function stripResponse(result, question) {
|
|
|
512
606
|
stripped.prompt = result.prompt;
|
|
513
607
|
stripped.instruction = result.instruction;
|
|
514
608
|
}
|
|
609
|
+
if (result.status === 'shimmer' && toolName === 'shimmer') {
|
|
610
|
+
stripped.prompt = result.prompt;
|
|
611
|
+
stripped.instruction = result.instruction;
|
|
612
|
+
}
|
|
515
613
|
if (result.status === 'orient') {
|
|
516
614
|
stripped.instruction = result.instruction;
|
|
517
615
|
}
|
|
@@ -546,6 +644,13 @@ async function main() {
|
|
|
546
644
|
}));
|
|
547
645
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
548
646
|
const { name, arguments: args } = request.params;
|
|
647
|
+
// Tombstone: the think tool was renamed to rvry. Non-error notice,
|
|
648
|
+
// returned BEFORE any engine call.
|
|
649
|
+
if (name === 'think' || name === 'RVRY_think') {
|
|
650
|
+
return {
|
|
651
|
+
content: [{ type: 'text', text: THINK_TOMBSTONE_NOTICE }],
|
|
652
|
+
};
|
|
653
|
+
}
|
|
549
654
|
const rvryTool = TOOL_MAP[name];
|
|
550
655
|
if (!rvryTool) {
|
|
551
656
|
return {
|
|
@@ -553,6 +658,8 @@ async function main() {
|
|
|
553
658
|
isError: true,
|
|
554
659
|
};
|
|
555
660
|
}
|
|
661
|
+
// Public tool name (RVRY_ aliases normalize to their unprefixed form).
|
|
662
|
+
const publicTool = name.replace(/^RVRY_/, '');
|
|
556
663
|
const typedArgs = args;
|
|
557
664
|
const input = typedArgs?.input;
|
|
558
665
|
if (!input || typeof input !== 'string') {
|
|
@@ -602,7 +709,7 @@ async function main() {
|
|
|
602
709
|
import('./local-writer.js').then(({ writeLocalSession }) => {
|
|
603
710
|
writeLocalSession({
|
|
604
711
|
sessionId: result.sessionId,
|
|
605
|
-
operationType:
|
|
712
|
+
operationType: publicTool,
|
|
606
713
|
question,
|
|
607
714
|
rounds: result.round,
|
|
608
715
|
harvest: result.harvest,
|
|
@@ -611,7 +718,7 @@ async function main() {
|
|
|
611
718
|
}).catch(() => { });
|
|
612
719
|
}).catch(() => { });
|
|
613
720
|
}
|
|
614
|
-
const stripped = stripResponse(result, question);
|
|
721
|
+
const stripped = stripResponse(result, question, publicTool);
|
|
615
722
|
return {
|
|
616
723
|
content: [{ type: 'text', text: JSON.stringify(stripped) }],
|
|
617
724
|
};
|
|
@@ -638,10 +745,15 @@ async function main() {
|
|
|
638
745
|
arguments: [{ name: 'problem', description: 'The problem or decision to analyze', required: true }],
|
|
639
746
|
},
|
|
640
747
|
{
|
|
641
|
-
name: '
|
|
748
|
+
name: 'rvry',
|
|
642
749
|
description: 'Structured analysis for questions needing more depth',
|
|
643
750
|
arguments: [{ name: 'question', description: 'The question to analyze', required: true }],
|
|
644
751
|
},
|
|
752
|
+
{
|
|
753
|
+
name: 'shimmer',
|
|
754
|
+
description: 'Reflective answering: observe the answer forming, then answer under the surfaced commitments',
|
|
755
|
+
arguments: [{ name: 'question', description: 'The question to answer reflectively', required: true }],
|
|
756
|
+
},
|
|
645
757
|
{
|
|
646
758
|
name: 'challenge',
|
|
647
759
|
description: 'Adversarial analysis that stress-tests a proposal',
|
|
@@ -659,7 +771,8 @@ async function main() {
|
|
|
659
771
|
const promptMap = {
|
|
660
772
|
deepthink: `Use the deepthink tool to analyze this question in depth: ${args?.question ?? ''}`,
|
|
661
773
|
problem_solve: `Use the problem_solve tool to work through this decision: ${args?.problem ?? ''}`,
|
|
662
|
-
|
|
774
|
+
rvry: `Use the rvry tool to analyze this question: ${args?.question ?? ''}`,
|
|
775
|
+
shimmer: `Use the shimmer tool to answer this question reflectively: ${args?.question ?? ''}`,
|
|
663
776
|
challenge: `Use the challenge tool to stress-test this proposal: ${args?.proposal ?? ''}`,
|
|
664
777
|
meta: `Use the meta tool to reflect on this topic: ${args?.topic ?? ''}`,
|
|
665
778
|
};
|
|
@@ -675,10 +788,10 @@ async function main() {
|
|
|
675
788
|
});
|
|
676
789
|
const transport = new StdioServerTransport();
|
|
677
790
|
await server.connect(transport);
|
|
678
|
-
console.error('[rvry-mcp] Connected via stdio. Tools: deepthink, problem_solve,
|
|
791
|
+
console.error('[rvry-mcp] Connected via stdio. Tools: rvry, deepthink, problem_solve, challenge, meta, shimmer (think: renamed to rvry)');
|
|
679
792
|
}
|
|
680
793
|
// Export internals for testing
|
|
681
|
-
export { TOOL_MAP, TOOL_DEFS, stripResponse, questionCache };
|
|
794
|
+
export { TOOL_MAP, TOOL_DEFS, stripResponse, questionCache, THINK_TOMBSTONE_NOTICE };
|
|
682
795
|
// Run server when executed directly (not when imported by tests).
|
|
683
796
|
// import.meta.main: true in Bun direct, false in Bun imports, undefined in Node ESM.
|
|
684
797
|
// @ts-ignore -- import.meta.main is a Bun extension, not in TS lib types
|
package/dist/local-writer.d.ts
CHANGED
|
@@ -53,6 +53,8 @@ export interface ClientHarvest {
|
|
|
53
53
|
summary?: string;
|
|
54
54
|
keyFindings?: string[];
|
|
55
55
|
shimmer?: string;
|
|
56
|
+
/** Shimmer-op: one line per surfaced commitment with its fate. */
|
|
57
|
+
constraintLedger?: string[];
|
|
56
58
|
openQuestions?: string[];
|
|
57
59
|
followUps?: Array<{
|
|
58
60
|
question: string;
|
package/dist/local-writer.js
CHANGED
|
@@ -11,13 +11,15 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { mkdirSync, writeFileSync } from 'fs';
|
|
13
13
|
import { join } from 'path';
|
|
14
|
-
/** Op label for H1 headings. */
|
|
14
|
+
/** Op label for H1 headings. Keyed by public tool name (old keys kept). */
|
|
15
15
|
const OP_LABELS = {
|
|
16
16
|
deepthink: 'RVRY Deepthink',
|
|
17
17
|
problem_solve: 'RVRY Problem-Solve',
|
|
18
18
|
think: 'RVRY Think',
|
|
19
|
+
rvry: 'RVRY',
|
|
19
20
|
challenge: 'RVRY Challenge',
|
|
20
21
|
meta: 'RVRY Meta',
|
|
22
|
+
shimmer: 'RVRY Shimmer',
|
|
21
23
|
};
|
|
22
24
|
function opLabel(operationType) {
|
|
23
25
|
return OP_LABELS[operationType] ?? `RVRY ${operationType}`;
|
|
@@ -156,6 +158,8 @@ export function buildMarkdown(data, now) {
|
|
|
156
158
|
appendProblemSolveBiasAudit(lines, harvest);
|
|
157
159
|
appendProblemSolveReversalConditions(lines, harvest);
|
|
158
160
|
}
|
|
161
|
+
// Shimmer-op commitment ledger: one line per surfaced commitment with fate.
|
|
162
|
+
appendConstraintLedger(lines, harvest);
|
|
159
163
|
if (isNonEmptyArray(harvest.keyFindings)) {
|
|
160
164
|
const findings = harvest.keyFindings.filter(isNonEmptyString);
|
|
161
165
|
if (findings.length > 0) {
|
|
@@ -237,6 +241,16 @@ function appendChallengeAssumptions(lines, harvest) {
|
|
|
237
241
|
}
|
|
238
242
|
lines.push('');
|
|
239
243
|
}
|
|
244
|
+
function appendConstraintLedger(lines, harvest) {
|
|
245
|
+
const entries = (harvest.constraintLedger ?? []).filter(isNonEmptyString);
|
|
246
|
+
if (entries.length === 0)
|
|
247
|
+
return;
|
|
248
|
+
lines.push('## Commitment Ledger');
|
|
249
|
+
lines.push('');
|
|
250
|
+
for (const entry of entries)
|
|
251
|
+
lines.push(`- ${entry.trim()}`);
|
|
252
|
+
lines.push('');
|
|
253
|
+
}
|
|
240
254
|
function appendChallengeEdgeCases(lines, harvest) {
|
|
241
255
|
const cases = (harvest.edgeCases ?? []).filter(isNonEmptyString);
|
|
242
256
|
if (cases.length === 0)
|
package/dist/setup.d.ts
CHANGED
|
@@ -9,4 +9,29 @@
|
|
|
9
9
|
* npx --yes --package @rvry/mcp@latest rvry-mcp setup --client code (Claude Code only)
|
|
10
10
|
* npx --yes --package @rvry/mcp@latest rvry-mcp setup --client desktop (Claude Desktop only)
|
|
11
11
|
*/
|
|
12
|
+
/** The /rvry shim (renamed from /think). Carries the Difficulty Gate + mode routing. */
|
|
13
|
+
declare const RVRY_SHIM_CONTENT: string;
|
|
14
|
+
/** Deprecation prefix for the /think tombstone command. */
|
|
15
|
+
declare const THINK_DEPRECATION_LINE = "FIRST: Tell the user that /think is now /rvry \u2014 the /think command will be removed in the next major version. Then proceed with the flow below.";
|
|
16
|
+
/** The /shimmer shim: 3-round reflective answering with client-owned harvest. */
|
|
17
|
+
declare const SHIMMER_SHIM_CONTENT = "Call the shimmer MCP tool with your question to start a reflective answering session.\n\nQuestion: $ARGUMENTS\n\nARGUMENT PARSING:\n1. If $ARGUMENTS contains the literal flag `--record`, remove it from the question text and REMEMBER that record mode is ON for this session.\n\nROUND 1 \u2014 OBSERVATION (status \"shimmer\"):\n1. The response's prompt field is your observation task. Work through it.\n2. Show the user your FULL observation, beginning with \"**RVRY SHIMMER**\" and the revery definition, exactly as the instruction field describes. Do NOT show a brief status line.\n3. End your observation with the commitments that surfaced, one per line as FORWARD:/FORBIDDEN:/QUESTION: lines \u2014 or the single line NOTHING if none surfaced.\n4. REMEMBER your observation text verbatim \u2014 you will pass it as harvest.shimmer on the final call.\n5. Call the shimmer tool again with your observation text as input and the sessionId.\n\nROUNDS 2-3 \u2014 ANSWER AND RESOLUTION (status \"active\"):\n1. Read the prompt field \u2014 this is your task. DO NOT display it to the user.\n2. Round 2 is the answer itself, working under the commitments you surfaced. Round 3 (if it occurs) resolves what the answer left unaddressed \u2014 engage each remaining commitment specifically or defer it with a reason.\n3. Show the user your answer as concise formatted markdown.\n4. Call the tool again with your full text as the input parameter, including the sessionId.\n - If record mode is ON, set `record: true` on every call and REMEMBER your round body as {round, mode, body} for the final call.\n\nFINAL CALL (the call whose response will have status \"complete\"):\nWhen you make the call that completes the session, also construct a `harvest` object on that SAME call:\n- title: a 1-4 word title capturing the topic\n- summary: 3-6 sentences of synthesis, leading with substance\n- keyFindings: 3-7 substantive bullet findings\n- shimmer: the full round-1 observation text you remembered, verbatim\n- constraintLedger: one line per surfaced commitment with its fate \u2014 addressed (and how), deferred (and why), or still open\n- openQuestions: [optional] remaining uncertainties\n- followUps: genuine next-question leads; omit the section if there are none\n\nIf record mode was ON, also include `rounds: [{round, mode, body}, ...]` on that final call with the bodies you remembered per round.\n\nDO NOT display: the prompt text you received (the round-1 observation you produce IS shown in full), constraint tables, quality scores, internal tracking data, or round numbers to the user.";
|
|
18
|
+
declare const SLASH_COMMANDS: {
|
|
19
|
+
file: string;
|
|
20
|
+
content: string;
|
|
21
|
+
label: string;
|
|
22
|
+
}[];
|
|
23
|
+
/**
|
|
24
|
+
* Install RVRY slash commands into the given directory.
|
|
25
|
+
* Only called when Claude Code is the selected client.
|
|
26
|
+
*
|
|
27
|
+
* RVRY owns these filenames: existing files are overwritten unconditionally,
|
|
28
|
+
* with the pre-existing content backed up to <name>.md.bak first (R-4).
|
|
29
|
+
*
|
|
30
|
+
* @param commandsDir - REQUIRED target directory. The real
|
|
31
|
+
* ~/.claude/commands path is resolved by runSetup and passed explicitly;
|
|
32
|
+
* there is deliberately no default so a bare call in a test can never
|
|
33
|
+
* touch the real directory.
|
|
34
|
+
*/
|
|
35
|
+
declare function installSlashCommands(commandsDir: string): string[];
|
|
36
|
+
export { SLASH_COMMANDS, installSlashCommands, RVRY_SHIM_CONTENT, SHIMMER_SHIM_CONTENT, THINK_DEPRECATION_LINE };
|
|
12
37
|
export declare function runSetup(): Promise<void>;
|
package/dist/setup.js
CHANGED
|
@@ -621,6 +621,53 @@ const CHALLENGE_FINAL_EXTRAS = `- verdict: GO / CONDITIONAL_GO / NO_GO. If CONDI
|
|
|
621
621
|
- edgeCases: 5-10 entries covering boundary conditions and hostile scenarios the proposal needs to survive.
|
|
622
622
|
- failureModes: 3-5 entries of \`{component, howItFails, blastRadius, detection}\` identifying what breaks and how you would notice.
|
|
623
623
|
- counterArguments: 2-3 entries of \`{argument, rebuttal}\`. Each \`argument\` is the strongest case FOR the proposal — steelman it genuinely; each \`rebuttal\` is why it's flawed or insufficient. This prevents one-sided adversarial output.`;
|
|
624
|
+
/** The /rvry shim (renamed from /think). Carries the Difficulty Gate + mode routing. */
|
|
625
|
+
const RVRY_SHIM_CONTENT = buildShim({
|
|
626
|
+
toolName: 'rvry',
|
|
627
|
+
subject: 'question',
|
|
628
|
+
orientLine: 'Orienting on the question.',
|
|
629
|
+
completionGuidance: 'Present your findings clearly with bold headings. Sessions are short; one or two analytical rounds is expected.',
|
|
630
|
+
shortSessionNote: 'NOTE: /rvry sessions are usually short (1-2 analytical rounds after orient). Expect to reach complete quickly.',
|
|
631
|
+
perRoundPrelude: THINK_DIFFICULTY_GATE,
|
|
632
|
+
analyticalGuidance: THINK_MODE_ROUTING,
|
|
633
|
+
});
|
|
634
|
+
/** Deprecation prefix for the /think tombstone command. */
|
|
635
|
+
const THINK_DEPRECATION_LINE = 'FIRST: Tell the user that /think is now /rvry — the /think command will be removed in the next major version. Then proceed with the flow below.';
|
|
636
|
+
/** The /shimmer shim: 3-round reflective answering with client-owned harvest. */
|
|
637
|
+
const SHIMMER_SHIM_CONTENT = `Call the shimmer MCP tool with your question to start a reflective answering session.
|
|
638
|
+
|
|
639
|
+
Question: $ARGUMENTS
|
|
640
|
+
|
|
641
|
+
ARGUMENT PARSING:
|
|
642
|
+
1. If $ARGUMENTS contains the literal flag \`--record\`, remove it from the question text and REMEMBER that record mode is ON for this session.
|
|
643
|
+
|
|
644
|
+
ROUND 1 — OBSERVATION (status "shimmer"):
|
|
645
|
+
1. The response's prompt field is your observation task. Work through it.
|
|
646
|
+
2. Show the user your FULL observation, beginning with "**RVRY SHIMMER**" and the revery definition, exactly as the instruction field describes. Do NOT show a brief status line.
|
|
647
|
+
3. End your observation with the commitments that surfaced, one per line as FORWARD:/FORBIDDEN:/QUESTION: lines — or the single line NOTHING if none surfaced.
|
|
648
|
+
4. REMEMBER your observation text verbatim — you will pass it as harvest.shimmer on the final call.
|
|
649
|
+
5. Call the shimmer tool again with your observation text as input and the sessionId.
|
|
650
|
+
|
|
651
|
+
ROUNDS 2-3 — ANSWER AND RESOLUTION (status "active"):
|
|
652
|
+
1. Read the prompt field — this is your task. DO NOT display it to the user.
|
|
653
|
+
2. Round 2 is the answer itself, working under the commitments you surfaced. Round 3 (if it occurs) resolves what the answer left unaddressed — engage each remaining commitment specifically or defer it with a reason.
|
|
654
|
+
3. Show the user your answer as concise formatted markdown.
|
|
655
|
+
4. Call the tool again with your full text as the input parameter, including the sessionId.
|
|
656
|
+
- If record mode is ON, set \`record: true\` on every call and REMEMBER your round body as {round, mode, body} for the final call.
|
|
657
|
+
|
|
658
|
+
FINAL CALL (the call whose response will have status "complete"):
|
|
659
|
+
When you make the call that completes the session, also construct a \`harvest\` object on that SAME call:
|
|
660
|
+
- title: a 1-4 word title capturing the topic
|
|
661
|
+
- summary: 3-6 sentences of synthesis, leading with substance
|
|
662
|
+
- keyFindings: 3-7 substantive bullet findings
|
|
663
|
+
- shimmer: the full round-1 observation text you remembered, verbatim
|
|
664
|
+
- constraintLedger: one line per surfaced commitment with its fate — addressed (and how), deferred (and why), or still open
|
|
665
|
+
- openQuestions: [optional] remaining uncertainties
|
|
666
|
+
- followUps: genuine next-question leads; omit the section if there are none
|
|
667
|
+
|
|
668
|
+
If record mode was ON, also include \`rounds: [{round, mode, body}, ...]\` on that final call with the bodies you remembered per round.
|
|
669
|
+
|
|
670
|
+
DO NOT display: the prompt text you received (the round-1 observation you produce IS shown in full), constraint tables, quality scores, internal tracking data, or round numbers to the user.`;
|
|
624
671
|
const SLASH_COMMANDS = [
|
|
625
672
|
{
|
|
626
673
|
file: 'deepthink.md',
|
|
@@ -644,18 +691,20 @@ const SLASH_COMMANDS = [
|
|
|
644
691
|
}),
|
|
645
692
|
label: '/problem-solve — structured decision-making',
|
|
646
693
|
},
|
|
694
|
+
{
|
|
695
|
+
file: 'rvry.md',
|
|
696
|
+
content: RVRY_SHIM_CONTENT,
|
|
697
|
+
label: '/rvry — structured single-session analysis',
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
file: 'shimmer.md',
|
|
701
|
+
content: SHIMMER_SHIM_CONTENT,
|
|
702
|
+
label: '/shimmer — reflective answering',
|
|
703
|
+
},
|
|
647
704
|
{
|
|
648
705
|
file: 'think.md',
|
|
649
|
-
content:
|
|
650
|
-
|
|
651
|
-
subject: 'question',
|
|
652
|
-
orientLine: 'Orienting on the question.',
|
|
653
|
-
completionGuidance: 'Present your findings clearly with bold headings. Think sessions are short; one or two analytical rounds is expected.',
|
|
654
|
-
shortSessionNote: 'NOTE: /think sessions are usually short (1-2 analytical rounds after orient). Expect to reach complete quickly.',
|
|
655
|
-
perRoundPrelude: THINK_DIFFICULTY_GATE,
|
|
656
|
-
analyticalGuidance: THINK_MODE_ROUTING,
|
|
657
|
-
}),
|
|
658
|
-
label: '/think — structured single-session analysis',
|
|
706
|
+
content: `${THINK_DEPRECATION_LINE}\n\n${RVRY_SHIM_CONTENT}`,
|
|
707
|
+
label: '/think — renamed to /rvry (deprecated alias)',
|
|
659
708
|
},
|
|
660
709
|
{
|
|
661
710
|
file: 'challenge.md',
|
|
@@ -681,12 +730,18 @@ const SLASH_COMMANDS = [
|
|
|
681
730
|
},
|
|
682
731
|
];
|
|
683
732
|
/**
|
|
684
|
-
* Install RVRY slash commands
|
|
733
|
+
* Install RVRY slash commands into the given directory.
|
|
685
734
|
* Only called when Claude Code is the selected client.
|
|
686
|
-
*
|
|
735
|
+
*
|
|
736
|
+
* RVRY owns these filenames: existing files are overwritten unconditionally,
|
|
737
|
+
* with the pre-existing content backed up to <name>.md.bak first (R-4).
|
|
738
|
+
*
|
|
739
|
+
* @param commandsDir - REQUIRED target directory. The real
|
|
740
|
+
* ~/.claude/commands path is resolved by runSetup and passed explicitly;
|
|
741
|
+
* there is deliberately no default so a bare call in a test can never
|
|
742
|
+
* touch the real directory.
|
|
687
743
|
*/
|
|
688
|
-
function installSlashCommands() {
|
|
689
|
-
const commandsDir = join(homedir(), ".claude", "commands");
|
|
744
|
+
function installSlashCommands(commandsDir) {
|
|
690
745
|
const installed = [];
|
|
691
746
|
try {
|
|
692
747
|
if (!existsSync(commandsDir)) {
|
|
@@ -694,11 +749,14 @@ function installSlashCommands() {
|
|
|
694
749
|
}
|
|
695
750
|
for (const cmd of SLASH_COMMANDS) {
|
|
696
751
|
const filePath = join(commandsDir, cmd.file);
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
752
|
+
const existed = existsSync(filePath);
|
|
753
|
+
if (existed) {
|
|
754
|
+
writeFileSync(`${filePath}.bak`, readFileSync(filePath, "utf-8"), "utf-8");
|
|
700
755
|
}
|
|
701
756
|
writeFileSync(filePath, cmd.content + "\n", "utf-8");
|
|
757
|
+
console.log(existed
|
|
758
|
+
? ` Updated ${cmd.file} (previous version backed up to ${cmd.file}.bak)`
|
|
759
|
+
: ` Installed ${cmd.file}`);
|
|
702
760
|
installed.push(cmd.label);
|
|
703
761
|
}
|
|
704
762
|
}
|
|
@@ -708,6 +766,8 @@ function installSlashCommands() {
|
|
|
708
766
|
}
|
|
709
767
|
return installed;
|
|
710
768
|
}
|
|
769
|
+
// Exported for tests (content + install behavior).
|
|
770
|
+
export { SLASH_COMMANDS, installSlashCommands, RVRY_SHIM_CONTENT, SHIMMER_SHIM_CONTENT, THINK_DEPRECATION_LINE };
|
|
711
771
|
// ── Main setup flow ────────────────────────────────────────────────
|
|
712
772
|
const BANNER = `
|
|
713
773
|
8888888b. 888 888 8888888b. Y88b d88P
|
|
@@ -855,7 +915,7 @@ export async function runSetup() {
|
|
|
855
915
|
if (claudeCodeConfigured) {
|
|
856
916
|
console.log("");
|
|
857
917
|
console.log(" Installing slash commands...");
|
|
858
|
-
installedCommands = installSlashCommands();
|
|
918
|
+
installedCommands = installSlashCommands(join(homedir(), ".claude", "commands"));
|
|
859
919
|
if (installedCommands.length > 0) {
|
|
860
920
|
console.log(` Installed ${installedCommands.length} command(s):`);
|
|
861
921
|
for (const label of installedCommands) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rvry/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "RVRY reasoning depth enforcement (RDE) engine client.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"node": ">=18.0.0"
|
|
16
16
|
},
|
|
17
17
|
"scripts": {
|
|
18
|
-
"build": "tsc && chmod 755 dist/index.js",
|
|
18
|
+
"build": "tsc -p tsconfig.build.json && chmod 755 dist/index.js",
|
|
19
19
|
"prepack": "npm run build",
|
|
20
20
|
"typecheck": "tsc --noEmit"
|
|
21
21
|
},
|