@rvry/mcp 0.12.2 → 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 +33 -41
- package/dist/client.d.ts +2 -2
- package/dist/index.d.ts +17 -6
- package/dist/index.js +444 -38
- package/dist/local-writer.d.ts +104 -16
- package/dist/local-writer.js +365 -56
- package/dist/setup.d.ts +25 -0
- package/dist/setup.js +202 -304
- package/package.json +2 -2
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,28 +21,31 @@ 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
|
-
name: '
|
|
46
|
+
name: 'deepthink',
|
|
42
47
|
description: 'Deep, multi-round structured analysis for high-stakes or complex questions. ' +
|
|
43
|
-
'Runs
|
|
48
|
+
'Runs 4 rounds of rigorous analysis with self-checks and adversarial stress-testing. ' +
|
|
44
49
|
'The first response orients you on the question — follow the instruction field to orient, then call again. ' +
|
|
45
50
|
'Each subsequent round returns a prompt (work through it internally) and an instruction (follow it). ' +
|
|
46
51
|
'Show the user only a brief status line per round (e.g. \'Round 3 — stress-testing the position\'). ' +
|
|
@@ -71,14 +76,51 @@ const TOOL_DEFS = [
|
|
|
71
76
|
type: 'boolean',
|
|
72
77
|
description: 'Set to true when the question depends on facts, policies, prices, regulations, or events that may have changed.',
|
|
73
78
|
},
|
|
79
|
+
record: {
|
|
80
|
+
type: 'boolean',
|
|
81
|
+
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.',
|
|
82
|
+
},
|
|
83
|
+
harvest: {
|
|
84
|
+
type: 'object',
|
|
85
|
+
description: 'Final-call-only. When status will transition to complete, include your synthesis here so it can be persisted to the local session file.',
|
|
86
|
+
properties: {
|
|
87
|
+
title: { type: 'string', description: '1-4 word title for this session' },
|
|
88
|
+
summary: { type: 'string', description: '3-6 sentences synthesizing the analysis' },
|
|
89
|
+
keyFindings: { type: 'array', items: { type: 'string' }, description: '3-7 bullet findings' },
|
|
90
|
+
shimmer: { type: 'string', description: 'Full round-1 self-observation text' },
|
|
91
|
+
openQuestions: { type: 'array', items: { type: 'string' } },
|
|
92
|
+
followUps: {
|
|
93
|
+
type: 'array',
|
|
94
|
+
items: {
|
|
95
|
+
type: 'object',
|
|
96
|
+
properties: {
|
|
97
|
+
question: { type: 'string' },
|
|
98
|
+
rationale: { type: 'string' },
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
rounds: {
|
|
105
|
+
type: 'array',
|
|
106
|
+
description: 'Final-call-only, present only when --record was set. Array of {round, mode, body} for each analytical round.',
|
|
107
|
+
items: {
|
|
108
|
+
type: 'object',
|
|
109
|
+
properties: {
|
|
110
|
+
round: { type: 'number' },
|
|
111
|
+
mode: { type: 'string' },
|
|
112
|
+
body: { type: 'string' },
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
},
|
|
74
116
|
},
|
|
75
117
|
required: ['input'],
|
|
76
118
|
},
|
|
77
119
|
},
|
|
78
120
|
{
|
|
79
|
-
name: '
|
|
121
|
+
name: 'problem_solve',
|
|
80
122
|
description: 'Structured decision-making that forces thorough evaluation before commitment. ' +
|
|
81
|
-
'Runs 5
|
|
123
|
+
'Runs 5 rounds through orient, anticipate, generate, evaluate, and commit phases. ' +
|
|
82
124
|
'The first response orients you — follow the instruction field, then call again. ' +
|
|
83
125
|
'Each round returns a prompt and instruction. Work through the prompt internally. ' +
|
|
84
126
|
'Show the user only a brief status line per round (e.g. \'Round 2 — mapping failure modes\'). ' +
|
|
@@ -109,14 +151,88 @@ const TOOL_DEFS = [
|
|
|
109
151
|
type: 'boolean',
|
|
110
152
|
description: 'Set to true when the question depends on facts, policies, prices, regulations, or events that may have changed.',
|
|
111
153
|
},
|
|
154
|
+
record: {
|
|
155
|
+
type: 'boolean',
|
|
156
|
+
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.',
|
|
157
|
+
},
|
|
158
|
+
harvest: {
|
|
159
|
+
type: 'object',
|
|
160
|
+
description: 'Final-call-only. When status will transition to complete, include your synthesis here so it can be persisted to the local session file.',
|
|
161
|
+
properties: {
|
|
162
|
+
title: { type: 'string', description: '1-4 word title for this session' },
|
|
163
|
+
summary: { type: 'string', description: '3-6 sentences synthesizing the analysis' },
|
|
164
|
+
keyFindings: { type: 'array', items: { type: 'string' }, description: '3-7 bullet findings' },
|
|
165
|
+
shimmer: { type: 'string', description: 'Full round-1 self-observation text' },
|
|
166
|
+
openQuestions: { type: 'array', items: { type: 'string' } },
|
|
167
|
+
followUps: {
|
|
168
|
+
type: 'array',
|
|
169
|
+
items: {
|
|
170
|
+
type: 'object',
|
|
171
|
+
properties: {
|
|
172
|
+
question: { type: 'string' },
|
|
173
|
+
rationale: { type: 'string' },
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
biasAudit: {
|
|
178
|
+
type: 'object',
|
|
179
|
+
description: 'Bias audit of the leading direction, linked to SHIMMER observations.',
|
|
180
|
+
properties: {
|
|
181
|
+
biasesOperating: {
|
|
182
|
+
type: 'array',
|
|
183
|
+
items: {
|
|
184
|
+
type: 'object',
|
|
185
|
+
properties: {
|
|
186
|
+
bias: { type: 'string', enum: ['anchoring', 'framing', 'authority', 'sunk_cost', 'availability', 'confirmation'] },
|
|
187
|
+
evidence: { type: 'string' },
|
|
188
|
+
sourceReflex: { type: 'string', description: 'Which SHIMMER reflex surfaced this bias, if any.' },
|
|
189
|
+
correction: { type: 'string' },
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
decisionStable: { type: 'boolean' },
|
|
194
|
+
frameReversal: {
|
|
195
|
+
type: 'object',
|
|
196
|
+
properties: {
|
|
197
|
+
originalFraming: { type: 'string' },
|
|
198
|
+
invertedFraming: { type: 'string' },
|
|
199
|
+
wouldReachSameConclusion: { type: 'boolean' },
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
adversarialVerdict: {
|
|
205
|
+
type: 'string',
|
|
206
|
+
enum: ['PASSED', 'CAVEATS', 'NEEDS_REVISION'],
|
|
207
|
+
description: 'Outcome of the adversarial stress-test against the leading direction.',
|
|
208
|
+
},
|
|
209
|
+
reversalConditions: {
|
|
210
|
+
type: 'array',
|
|
211
|
+
items: { type: 'string' },
|
|
212
|
+
description: 'Conditions under which this decision would be reversed (kill switches, escalation triggers, review timeline). 3-5 entries.',
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
rounds: {
|
|
217
|
+
type: 'array',
|
|
218
|
+
description: 'Final-call-only, present only when --record was set. Array of {round, mode, body} for each analytical round.',
|
|
219
|
+
items: {
|
|
220
|
+
type: 'object',
|
|
221
|
+
properties: {
|
|
222
|
+
round: { type: 'number' },
|
|
223
|
+
mode: { type: 'string' },
|
|
224
|
+
body: { type: 'string' },
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
},
|
|
112
228
|
},
|
|
113
229
|
required: ['input'],
|
|
114
230
|
},
|
|
115
231
|
},
|
|
116
232
|
{
|
|
117
|
-
name: '
|
|
233
|
+
name: 'rvry',
|
|
118
234
|
description: 'Structured analysis for questions needing more depth than a quick answer. ' +
|
|
119
|
-
'Runs
|
|
235
|
+
'Runs 1-3 rounds; simple questions can complete in a single analytical round. ' +
|
|
120
236
|
'The first response orients you — follow the instruction field, then call again. ' +
|
|
121
237
|
'Each round returns a prompt and instruction. Work through the prompt internally. ' +
|
|
122
238
|
'Show the user only a brief status line per round. Do not display internal data. ' +
|
|
@@ -146,14 +262,51 @@ const TOOL_DEFS = [
|
|
|
146
262
|
type: 'boolean',
|
|
147
263
|
description: 'Set to true when the question depends on facts, policies, prices, regulations, or events that may have changed.',
|
|
148
264
|
},
|
|
265
|
+
record: {
|
|
266
|
+
type: 'boolean',
|
|
267
|
+
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.',
|
|
268
|
+
},
|
|
269
|
+
harvest: {
|
|
270
|
+
type: 'object',
|
|
271
|
+
description: 'Final-call-only. When status will transition to complete, include your synthesis here so it can be persisted to the local session file.',
|
|
272
|
+
properties: {
|
|
273
|
+
title: { type: 'string', description: '1-4 word title for this session' },
|
|
274
|
+
summary: { type: 'string', description: '3-6 sentences synthesizing the analysis' },
|
|
275
|
+
keyFindings: { type: 'array', items: { type: 'string' }, description: '3-7 bullet findings' },
|
|
276
|
+
shimmer: { type: 'string', description: 'Full round-1 self-observation text' },
|
|
277
|
+
openQuestions: { type: 'array', items: { type: 'string' } },
|
|
278
|
+
followUps: {
|
|
279
|
+
type: 'array',
|
|
280
|
+
items: {
|
|
281
|
+
type: 'object',
|
|
282
|
+
properties: {
|
|
283
|
+
question: { type: 'string' },
|
|
284
|
+
rationale: { type: 'string' },
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
rounds: {
|
|
291
|
+
type: 'array',
|
|
292
|
+
description: 'Final-call-only, present only when --record was set. Array of {round, mode, body} for each analytical round.',
|
|
293
|
+
items: {
|
|
294
|
+
type: 'object',
|
|
295
|
+
properties: {
|
|
296
|
+
round: { type: 'number' },
|
|
297
|
+
mode: { type: 'string' },
|
|
298
|
+
body: { type: 'string' },
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
},
|
|
149
302
|
},
|
|
150
303
|
required: ['input'],
|
|
151
304
|
},
|
|
152
305
|
},
|
|
153
306
|
{
|
|
154
|
-
name: '
|
|
307
|
+
name: 'challenge',
|
|
155
308
|
description: 'Adversarial analysis that stress-tests a proposal or idea before commitment. ' +
|
|
156
|
-
'Runs
|
|
309
|
+
'Runs 5 rounds identifying weaknesses, testing assumptions, and surfacing failure modes. ' +
|
|
157
310
|
'The first response orients you — follow the instruction field, then call again. ' +
|
|
158
311
|
'Each round returns a prompt and instruction. Work through the prompt internally. ' +
|
|
159
312
|
'Show the user only a brief status line per round. Do not display internal data. ' +
|
|
@@ -183,12 +336,108 @@ const TOOL_DEFS = [
|
|
|
183
336
|
type: 'boolean',
|
|
184
337
|
description: 'Set to true when the question depends on facts, policies, prices, regulations, or events that may have changed.',
|
|
185
338
|
},
|
|
339
|
+
record: {
|
|
340
|
+
type: 'boolean',
|
|
341
|
+
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.',
|
|
342
|
+
},
|
|
343
|
+
harvest: {
|
|
344
|
+
type: 'object',
|
|
345
|
+
description: 'Final-call-only. When status will transition to complete, include your synthesis here so it can be persisted to the local session file.',
|
|
346
|
+
properties: {
|
|
347
|
+
title: { type: 'string', description: '1-4 word title for this session' },
|
|
348
|
+
summary: { type: 'string', description: '3-6 sentences synthesizing the analysis' },
|
|
349
|
+
keyFindings: { type: 'array', items: { type: 'string' }, description: '3-7 bullet findings' },
|
|
350
|
+
shimmer: { type: 'string', description: 'Full round-1 self-observation text' },
|
|
351
|
+
openQuestions: { type: 'array', items: { type: 'string' } },
|
|
352
|
+
followUps: {
|
|
353
|
+
type: 'array',
|
|
354
|
+
items: {
|
|
355
|
+
type: 'object',
|
|
356
|
+
properties: {
|
|
357
|
+
question: { type: 'string' },
|
|
358
|
+
rationale: { type: 'string' },
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
verdict: {
|
|
363
|
+
type: 'string',
|
|
364
|
+
enum: ['GO', 'CONDITIONAL_GO', 'NO_GO'],
|
|
365
|
+
description: 'Tri-state adversarial verdict on the proposal.',
|
|
366
|
+
},
|
|
367
|
+
confidence: {
|
|
368
|
+
type: 'number',
|
|
369
|
+
minimum: 0,
|
|
370
|
+
maximum: 1,
|
|
371
|
+
description: '0.0-1.0 strength of the verdict.',
|
|
372
|
+
},
|
|
373
|
+
mitigations: {
|
|
374
|
+
type: 'array',
|
|
375
|
+
items: { type: 'string' },
|
|
376
|
+
description: 'Required mitigations for CONDITIONAL_GO verdicts. Conditions that must be met for GO.',
|
|
377
|
+
},
|
|
378
|
+
assumptions: {
|
|
379
|
+
type: 'array',
|
|
380
|
+
description: 'Assumption audit with bias attribution. 3-4 entries typical.',
|
|
381
|
+
items: {
|
|
382
|
+
type: 'object',
|
|
383
|
+
properties: {
|
|
384
|
+
assumption: { type: 'string' },
|
|
385
|
+
confidence: { type: 'string', enum: ['high', 'medium', 'low'] },
|
|
386
|
+
ifWrong: { type: 'string', description: 'Consequence if the assumption is wrong.' },
|
|
387
|
+
bias: { type: 'string', enum: ['anchoring', 'framing', 'authority', 'sunk_cost', 'availability', 'confirmation', 'none'] },
|
|
388
|
+
biasEvidence: { type: 'string', description: 'Evidence that the named bias is operating. Use empty string when bias is "none".' },
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
edgeCases: {
|
|
393
|
+
type: 'array',
|
|
394
|
+
items: { type: 'string' },
|
|
395
|
+
description: 'Boundary conditions and hostile scenarios the proposal needs to survive. 5-10 entries.',
|
|
396
|
+
},
|
|
397
|
+
failureModes: {
|
|
398
|
+
type: 'array',
|
|
399
|
+
description: 'Failure mode catalog with blast radius and detection. 3-5 entries.',
|
|
400
|
+
items: {
|
|
401
|
+
type: 'object',
|
|
402
|
+
properties: {
|
|
403
|
+
component: { type: 'string' },
|
|
404
|
+
howItFails: { type: 'string' },
|
|
405
|
+
blastRadius: { type: 'string', enum: ['contained', 'cascading'] },
|
|
406
|
+
detection: { type: 'string', description: 'How you would notice this failure.' },
|
|
407
|
+
},
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
counterArguments: {
|
|
411
|
+
type: 'array',
|
|
412
|
+
description: 'Steelman + rebuttal pairs. 2-3 entries. Prevents one-sided adversarial output.',
|
|
413
|
+
items: {
|
|
414
|
+
type: 'object',
|
|
415
|
+
properties: {
|
|
416
|
+
argument: { type: 'string', description: 'Strongest argument FOR the proposal (steelmanned).' },
|
|
417
|
+
rebuttal: { type: 'string', description: 'Why it is flawed or insufficient.' },
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
},
|
|
423
|
+
rounds: {
|
|
424
|
+
type: 'array',
|
|
425
|
+
description: 'Final-call-only, present only when --record was set. Array of {round, mode, body} for each analytical round.',
|
|
426
|
+
items: {
|
|
427
|
+
type: 'object',
|
|
428
|
+
properties: {
|
|
429
|
+
round: { type: 'number' },
|
|
430
|
+
mode: { type: 'string' },
|
|
431
|
+
body: { type: 'string' },
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
},
|
|
186
435
|
},
|
|
187
436
|
required: ['input'],
|
|
188
437
|
},
|
|
189
438
|
},
|
|
190
439
|
{
|
|
191
|
-
name: '
|
|
440
|
+
name: 'meta',
|
|
192
441
|
description: 'Sustained metacognitive observation of reasoning defaults and trained reflexes. ' +
|
|
193
442
|
'Runs 3 rounds: observe, deepen, synthesize. Max tier only. ' +
|
|
194
443
|
'The first response sets the observation frame — follow the instruction field, then call again. ' +
|
|
@@ -211,13 +460,139 @@ const TOOL_DEFS = [
|
|
|
211
460
|
type: 'boolean',
|
|
212
461
|
description: 'Set to true when the question depends on facts, policies, prices, regulations, or events that may have changed.',
|
|
213
462
|
},
|
|
463
|
+
record: {
|
|
464
|
+
type: 'boolean',
|
|
465
|
+
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.',
|
|
466
|
+
},
|
|
467
|
+
harvest: {
|
|
468
|
+
type: 'object',
|
|
469
|
+
description: 'Final-call-only. When status will transition to complete, include your synthesis here so it can be persisted to the local session file.',
|
|
470
|
+
properties: {
|
|
471
|
+
title: { type: 'string', description: '1-4 word title for this session' },
|
|
472
|
+
summary: { type: 'string', description: '3-6 sentences synthesizing the analysis' },
|
|
473
|
+
keyFindings: { type: 'array', items: { type: 'string' }, description: '3-7 bullet findings' },
|
|
474
|
+
shimmer: { type: 'string', description: 'Full round-1 self-observation text' },
|
|
475
|
+
openQuestions: { type: 'array', items: { type: 'string' } },
|
|
476
|
+
followUps: {
|
|
477
|
+
type: 'array',
|
|
478
|
+
items: {
|
|
479
|
+
type: 'object',
|
|
480
|
+
properties: {
|
|
481
|
+
question: { type: 'string' },
|
|
482
|
+
rationale: { type: 'string' },
|
|
483
|
+
},
|
|
484
|
+
},
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
rounds: {
|
|
489
|
+
type: 'array',
|
|
490
|
+
description: 'Final-call-only, present only when --record was set. Array of {round, mode, body} for each analytical round.',
|
|
491
|
+
items: {
|
|
492
|
+
type: 'object',
|
|
493
|
+
properties: {
|
|
494
|
+
round: { type: 'number' },
|
|
495
|
+
mode: { type: 'string' },
|
|
496
|
+
body: { type: 'string' },
|
|
497
|
+
},
|
|
498
|
+
},
|
|
499
|
+
},
|
|
214
500
|
},
|
|
215
501
|
required: ['input'],
|
|
216
502
|
},
|
|
217
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
|
+
},
|
|
218
587
|
];
|
|
219
|
-
/**
|
|
220
|
-
|
|
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) {
|
|
221
596
|
const stripped = {
|
|
222
597
|
sessionId: result.sessionId,
|
|
223
598
|
status: result.status,
|
|
@@ -231,6 +606,10 @@ function stripResponse(result, question) {
|
|
|
231
606
|
stripped.prompt = result.prompt;
|
|
232
607
|
stripped.instruction = result.instruction;
|
|
233
608
|
}
|
|
609
|
+
if (result.status === 'shimmer' && toolName === 'shimmer') {
|
|
610
|
+
stripped.prompt = result.prompt;
|
|
611
|
+
stripped.instruction = result.instruction;
|
|
612
|
+
}
|
|
234
613
|
if (result.status === 'orient') {
|
|
235
614
|
stripped.instruction = result.instruction;
|
|
236
615
|
}
|
|
@@ -265,6 +644,13 @@ async function main() {
|
|
|
265
644
|
}));
|
|
266
645
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
267
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
|
+
}
|
|
268
654
|
const rvryTool = TOOL_MAP[name];
|
|
269
655
|
if (!rvryTool) {
|
|
270
656
|
return {
|
|
@@ -272,6 +658,8 @@ async function main() {
|
|
|
272
658
|
isError: true,
|
|
273
659
|
};
|
|
274
660
|
}
|
|
661
|
+
// Public tool name (RVRY_ aliases normalize to their unprefixed form).
|
|
662
|
+
const publicTool = name.replace(/^RVRY_/, '');
|
|
275
663
|
const typedArgs = args;
|
|
276
664
|
const input = typedArgs?.input;
|
|
277
665
|
if (!input || typeof input !== 'string') {
|
|
@@ -286,6 +674,15 @@ async function main() {
|
|
|
286
674
|
const userConstraints = Array.isArray(typedArgs?.userConstraints)
|
|
287
675
|
? typedArgs.userConstraints.filter(s => typeof s === 'string')
|
|
288
676
|
: undefined;
|
|
677
|
+
// Client-owned harvest params (Path B). Stripped before engine call.
|
|
678
|
+
const clientHarvest = typedArgs?.harvest && typeof typedArgs.harvest === 'object' && !Array.isArray(typedArgs.harvest)
|
|
679
|
+
? typedArgs.harvest
|
|
680
|
+
: undefined;
|
|
681
|
+
const clientRounds = Array.isArray(typedArgs?.rounds)
|
|
682
|
+
? typedArgs.rounds.filter((r) => r && typeof r === 'object' && typeof r.round === 'number')
|
|
683
|
+
: undefined;
|
|
684
|
+
// `record` is a shim-side flag; not needed by server or writer directly.
|
|
685
|
+
void typedArgs?.record;
|
|
289
686
|
// Cache question on first call (no sessionId = new session)
|
|
290
687
|
// On continuation calls, read from cache
|
|
291
688
|
let question = input;
|
|
@@ -306,19 +703,22 @@ async function main() {
|
|
|
306
703
|
if (result.status === 'complete') {
|
|
307
704
|
questionCache.delete(result.sessionId);
|
|
308
705
|
}
|
|
309
|
-
// Write local session
|
|
310
|
-
|
|
706
|
+
// Write local session folder on completion (non-blocking, silent failure).
|
|
707
|
+
// Client-owned harvest (Path B): prefer client-supplied `harvest` + `rounds`.
|
|
708
|
+
if (result.status === 'complete') {
|
|
311
709
|
import('./local-writer.js').then(({ writeLocalSession }) => {
|
|
312
710
|
writeLocalSession({
|
|
313
711
|
sessionId: result.sessionId,
|
|
314
|
-
operationType:
|
|
712
|
+
operationType: publicTool,
|
|
315
713
|
question,
|
|
316
714
|
rounds: result.round,
|
|
317
715
|
harvest: result.harvest,
|
|
716
|
+
clientHarvest,
|
|
717
|
+
clientRounds,
|
|
318
718
|
}).catch(() => { });
|
|
319
719
|
}).catch(() => { });
|
|
320
720
|
}
|
|
321
|
-
const stripped = stripResponse(result, question);
|
|
721
|
+
const stripped = stripResponse(result, question, publicTool);
|
|
322
722
|
return {
|
|
323
723
|
content: [{ type: 'text', text: JSON.stringify(stripped) }],
|
|
324
724
|
};
|
|
@@ -335,27 +735,32 @@ async function main() {
|
|
|
335
735
|
server.setRequestHandler(ListPromptsRequestSchema, async () => ({
|
|
336
736
|
prompts: [
|
|
337
737
|
{
|
|
338
|
-
name: '
|
|
738
|
+
name: 'deepthink',
|
|
339
739
|
description: 'Deep structured analysis for high-stakes questions',
|
|
340
740
|
arguments: [{ name: 'question', description: 'The question to analyze deeply', required: true }],
|
|
341
741
|
},
|
|
342
742
|
{
|
|
343
|
-
name: '
|
|
743
|
+
name: 'problem_solve',
|
|
344
744
|
description: 'Structured decision-making for problems with multiple options',
|
|
345
745
|
arguments: [{ name: 'problem', description: 'The problem or decision to analyze', required: true }],
|
|
346
746
|
},
|
|
347
747
|
{
|
|
348
|
-
name: '
|
|
748
|
+
name: 'rvry',
|
|
349
749
|
description: 'Structured analysis for questions needing more depth',
|
|
350
750
|
arguments: [{ name: 'question', description: 'The question to analyze', required: true }],
|
|
351
751
|
},
|
|
352
752
|
{
|
|
353
|
-
name: '
|
|
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
|
+
},
|
|
757
|
+
{
|
|
758
|
+
name: 'challenge',
|
|
354
759
|
description: 'Adversarial analysis that stress-tests a proposal',
|
|
355
760
|
arguments: [{ name: 'proposal', description: 'The proposal or idea to challenge', required: true }],
|
|
356
761
|
},
|
|
357
762
|
{
|
|
358
|
-
name: '
|
|
763
|
+
name: 'meta',
|
|
359
764
|
description: 'Sustained metacognitive observation (Max tier only)',
|
|
360
765
|
arguments: [{ name: 'topic', description: 'The topic or context to reflect on', required: true }],
|
|
361
766
|
},
|
|
@@ -364,11 +769,12 @@ async function main() {
|
|
|
364
769
|
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
365
770
|
const { name, arguments: args } = request.params;
|
|
366
771
|
const promptMap = {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
772
|
+
deepthink: `Use the deepthink tool to analyze this question in depth: ${args?.question ?? ''}`,
|
|
773
|
+
problem_solve: `Use the problem_solve tool to work through this decision: ${args?.problem ?? ''}`,
|
|
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 ?? ''}`,
|
|
776
|
+
challenge: `Use the challenge tool to stress-test this proposal: ${args?.proposal ?? ''}`,
|
|
777
|
+
meta: `Use the meta tool to reflect on this topic: ${args?.topic ?? ''}`,
|
|
372
778
|
};
|
|
373
779
|
const text = promptMap[name] ?? `Unknown prompt: ${name}`;
|
|
374
780
|
return {
|
|
@@ -382,10 +788,10 @@ async function main() {
|
|
|
382
788
|
});
|
|
383
789
|
const transport = new StdioServerTransport();
|
|
384
790
|
await server.connect(transport);
|
|
385
|
-
console.error('[rvry-mcp] Connected via stdio. Tools:
|
|
791
|
+
console.error('[rvry-mcp] Connected via stdio. Tools: rvry, deepthink, problem_solve, challenge, meta, shimmer (think: renamed to rvry)');
|
|
386
792
|
}
|
|
387
793
|
// Export internals for testing
|
|
388
|
-
export { TOOL_MAP, TOOL_DEFS, stripResponse, questionCache };
|
|
794
|
+
export { TOOL_MAP, TOOL_DEFS, stripResponse, questionCache, THINK_TOMBSTONE_NOTICE };
|
|
389
795
|
// Run server when executed directly (not when imported by tests).
|
|
390
796
|
// import.meta.main: true in Bun direct, false in Bun imports, undefined in Node ESM.
|
|
391
797
|
// @ts-ignore -- import.meta.main is a Bun extension, not in TS lib types
|