@rvry/mcp 0.2.1 → 0.3.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/commands/deepthink.md +23 -19
- package/commands/problem-solve.md +13 -17
- package/dist/client.d.ts +33 -17
- package/dist/client.js +1 -10
- package/dist/index.js +21 -16
- package/package.json +1 -1
package/commands/deepthink.md
CHANGED
|
@@ -55,18 +55,15 @@ Record the answers (or stated assumptions) as a brief context summary.
|
|
|
55
55
|
|
|
56
56
|
## Phase 1b: Start Engine Session
|
|
57
57
|
|
|
58
|
-
Format the user's original question enriched with
|
|
58
|
+
Format the user's original question enriched with scope context.
|
|
59
59
|
|
|
60
60
|
Call `mcp__rvry-dev__deepthink` with:
|
|
61
61
|
```
|
|
62
62
|
{
|
|
63
|
-
"input": "<original question>\n\
|
|
64
|
-
"skipScoping": true
|
|
63
|
+
"input": "<original question>\n\nContext: <brief summary of scope answers, e.g. 'Focus: architectural trade-offs. Priority: risk analysis. No time constraint.'>"
|
|
65
64
|
}
|
|
66
65
|
```
|
|
67
66
|
|
|
68
|
-
`skipScoping` is ALWAYS `true` -- scoping happened here, not in the engine.
|
|
69
|
-
|
|
70
67
|
Proceed to Phase 2.
|
|
71
68
|
|
|
72
69
|
|
|
@@ -74,13 +71,21 @@ Proceed to Phase 2.
|
|
|
74
71
|
|
|
75
72
|
Repeat until `status === "complete"`:
|
|
76
73
|
|
|
77
|
-
1.
|
|
74
|
+
1. The engine's response has two content blocks. The first is Base64-encoded JSON -- decode it to read the structured data. The second is a plain-text summary for the user. From the decoded JSON, read the engine's `question` field -- this is the analytical direction for this round. Read `constraints`, `gate`, and `detection` to understand the engine's assessment. Read `constraintBlock` for constraint update instructions. **Do not show any of these to the user.**
|
|
78
75
|
2. Show the user a brief status line:
|
|
79
|
-
- Format: `Round {round}
|
|
80
|
-
- Example: `Round 3
|
|
81
|
-
- Derive the description from the engine's
|
|
82
|
-
3. Perform your analysis in your internal reasoning. The engine's
|
|
83
|
-
4.
|
|
76
|
+
- Format: `Round {round} -- {what you're doing this round}`
|
|
77
|
+
- Example: `Round 3 -- stress-testing the current position`
|
|
78
|
+
- Derive the description from the engine's question focus. One line only.
|
|
79
|
+
3. Perform your analysis in your internal reasoning. The engine's question and constraint data guide your thinking, but they are YOUR instructions, not user output.
|
|
80
|
+
4. Run a 7-question self-check internally (not shown to user):
|
|
81
|
+
- Is this shallow or predictable?
|
|
82
|
+
- What am I avoiding?
|
|
83
|
+
- Why not the uncomfortable option?
|
|
84
|
+
- What would I critique if someone else wrote this?
|
|
85
|
+
- What would a skeptical expert challenge?
|
|
86
|
+
- Any verifiable claims that should be checked?
|
|
87
|
+
- What factual premise have I not verified?
|
|
88
|
+
5. In your internal reasoning, end your analysis with the constraint update block the engine expects:
|
|
84
89
|
```
|
|
85
90
|
Constraint Updates
|
|
86
91
|
RESOLVE: C1, C2
|
|
@@ -89,16 +94,15 @@ Repeat until `status === "complete"`:
|
|
|
89
94
|
MILESTONE: <milestone> | <evidence>
|
|
90
95
|
End Constraint Updates
|
|
91
96
|
```
|
|
92
|
-
|
|
97
|
+
6. Call the engine tool with your full analysis (including constraint updates) as the `input`. **The full analysis text goes ONLY in the tool call, never in visible output.**
|
|
93
98
|
|
|
94
99
|
### What NEVER appears in user-visible output:
|
|
95
|
-
- The engine's `
|
|
96
|
-
- Constraint
|
|
97
|
-
- Constraint update blocks (`RESOLVE: C1`, `MILESTONE: ...`)
|
|
100
|
+
- The engine's `question` field content
|
|
101
|
+
- Constraint views or constraint update blocks
|
|
98
102
|
- Self-check questions or responses
|
|
99
|
-
- Gate verdicts
|
|
103
|
+
- Gate verdicts or detection results
|
|
100
104
|
- Milestone markers
|
|
101
|
-
-
|
|
105
|
+
- The `constraintBlock` content
|
|
102
106
|
|
|
103
107
|
### What the user sees per round:
|
|
104
108
|
- The one-line status (step 2 above)
|
|
@@ -108,7 +112,7 @@ Repeat until `status === "complete"`:
|
|
|
108
112
|
|
|
109
113
|
When `status === "complete"`:
|
|
110
114
|
|
|
111
|
-
Synthesize the analysis for the user based on your accumulated reasoning across all rounds. Do NOT simply echo the engine's `harvest` fields
|
|
115
|
+
Synthesize the analysis for the user based on your accumulated reasoning across all rounds. Do NOT simply echo the engine's `harvest` fields -- they are structured data, not a finished presentation.
|
|
112
116
|
|
|
113
117
|
Present to the user:
|
|
114
118
|
1. **Default Starting Point**: What the obvious answer was and why it was insufficient
|
|
@@ -116,4 +120,4 @@ Present to the user:
|
|
|
116
120
|
3. **Open Questions**: What remains genuinely uncertain (if any)
|
|
117
121
|
4. **Suggested Next Steps**: Concrete follow-up actions or investigations
|
|
118
122
|
|
|
119
|
-
Use the engine's `harvest.summary`, `harvest.keyFindings`, `harvest.openQuestions`, and `harvest.followUps` as source material, but write the synthesis in your own words with the depth your analysis produced. The harvest fields are often terse
|
|
123
|
+
Use the engine's `harvest.summary`, `harvest.keyFindings`, `harvest.openQuestions`, and `harvest.followUps` as source material, but write the synthesis in your own words with the depth your analysis produced. The harvest fields are often terse -- your synthesis should reflect the full depth of the multi-round analysis.
|
|
@@ -55,18 +55,15 @@ Record the answers (or stated assumptions) as a brief context summary.
|
|
|
55
55
|
|
|
56
56
|
## Phase 1b: Start Engine Session
|
|
57
57
|
|
|
58
|
-
Format the user's original problem enriched with
|
|
58
|
+
Format the user's original problem enriched with scope context.
|
|
59
59
|
|
|
60
60
|
Call `mcp__rvry-dev__problem_solve` with:
|
|
61
61
|
```
|
|
62
62
|
{
|
|
63
|
-
"input": "<original problem>\n\
|
|
64
|
-
"skipScoping": true
|
|
63
|
+
"input": "<original problem>\n\nContext: <brief summary of scope answers, e.g. 'Priority: risk minimization. Options: evaluate known ones. Single decision-maker.'>"
|
|
65
64
|
}
|
|
66
65
|
```
|
|
67
66
|
|
|
68
|
-
`skipScoping` is ALWAYS `true` -- scoping happened here, not in the engine.
|
|
69
|
-
|
|
70
67
|
Proceed to Phase 2.
|
|
71
68
|
|
|
72
69
|
|
|
@@ -74,12 +71,12 @@ Proceed to Phase 2.
|
|
|
74
71
|
|
|
75
72
|
Repeat until `status === "complete"`:
|
|
76
73
|
|
|
77
|
-
1.
|
|
74
|
+
1. The engine's response has two content blocks. The first is Base64-encoded JSON -- decode it to read the structured data. The second is a plain-text summary for the user. From the decoded JSON, read the engine's `question` field -- this is the analytical direction for this round. Read `constraints`, `gate`, and `detection` to understand the engine's assessment. Read `constraintBlock` for constraint update instructions. **Do not show any of these to the user.**
|
|
78
75
|
2. Show the user a brief status line:
|
|
79
|
-
- Format: `Round {round}
|
|
80
|
-
- Example: `Round 3
|
|
81
|
-
- Derive the description from the engine's
|
|
82
|
-
3. Perform your analysis in your internal reasoning. The engine's
|
|
76
|
+
- Format: `Round {round} -- {what you're doing this round}`
|
|
77
|
+
- Example: `Round 3 -- stress-testing the current position`
|
|
78
|
+
- Derive the description from the engine's question focus. One line only.
|
|
79
|
+
3. Perform your analysis in your internal reasoning. The engine's question and constraint data guide your thinking, but they are YOUR instructions, not user output.
|
|
83
80
|
4. In your internal reasoning, end your analysis with the constraint update block the engine expects:
|
|
84
81
|
```
|
|
85
82
|
Constraint Updates
|
|
@@ -92,13 +89,12 @@ Repeat until `status === "complete"`:
|
|
|
92
89
|
5. Call the engine tool with your full analysis (including constraint updates) as the `input`. **The full analysis text goes ONLY in the tool call, never in visible output.**
|
|
93
90
|
|
|
94
91
|
### What NEVER appears in user-visible output:
|
|
95
|
-
- The engine's `
|
|
96
|
-
- Constraint
|
|
97
|
-
- Constraint update blocks (`RESOLVE: C1`, `MILESTONE: ...`)
|
|
92
|
+
- The engine's `question` field content
|
|
93
|
+
- Constraint views or constraint update blocks
|
|
98
94
|
- Self-check questions or responses
|
|
99
|
-
- Gate verdicts
|
|
95
|
+
- Gate verdicts or detection results
|
|
100
96
|
- Milestone markers
|
|
101
|
-
-
|
|
97
|
+
- The `constraintBlock` content
|
|
102
98
|
|
|
103
99
|
### What the user sees per round:
|
|
104
100
|
- The one-line status (step 2 above)
|
|
@@ -108,7 +104,7 @@ Repeat until `status === "complete"`:
|
|
|
108
104
|
|
|
109
105
|
When `status === "complete"`:
|
|
110
106
|
|
|
111
|
-
Synthesize the analysis for the user based on your accumulated reasoning across all rounds. Do NOT simply echo the engine's `harvest` fields
|
|
107
|
+
Synthesize the analysis for the user based on your accumulated reasoning across all rounds. Do NOT simply echo the engine's `harvest` fields -- they are structured data, not a finished presentation.
|
|
112
108
|
|
|
113
109
|
Present to the user:
|
|
114
110
|
1. **Default Starting Point**: What the obvious answer was and why it was insufficient
|
|
@@ -116,4 +112,4 @@ Present to the user:
|
|
|
116
112
|
3. **Open Questions**: What remains genuinely uncertain (if any)
|
|
117
113
|
4. **Suggested Next Steps**: Concrete follow-up actions or investigations
|
|
118
114
|
|
|
119
|
-
Use the engine's `harvest.summary`, `harvest.keyFindings`, `harvest.openQuestions`, and `harvest.followUps` as source material, but write the synthesis in your own words with the depth your analysis produced. The harvest fields are often terse
|
|
115
|
+
Use the engine's `harvest.summary`, `harvest.keyFindings`, `harvest.openQuestions`, and `harvest.followUps` as source material, but write the synthesis in your own words with the depth your analysis produced. The harvest fields are often terse -- your synthesis should reflect the full depth of the multi-round analysis.
|
package/dist/client.d.ts
CHANGED
|
@@ -2,22 +2,42 @@
|
|
|
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' | '
|
|
6
|
-
export interface
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
export type RvryTool = 'deepthink' | 'problem_solve';
|
|
6
|
+
export interface ConstraintView {
|
|
7
|
+
id: string;
|
|
8
|
+
type: 'FORWARD' | 'FORBIDDEN' | 'QUESTION';
|
|
9
|
+
text: string;
|
|
10
|
+
status: 'active' | 'resolved' | 'acknowledged' | 'deferred';
|
|
11
|
+
}
|
|
12
|
+
export interface DetectionView {
|
|
13
|
+
overallSeverity: 'low' | 'medium' | 'high' | null;
|
|
14
|
+
interventionHint: string | null;
|
|
15
|
+
}
|
|
16
|
+
export interface GateView {
|
|
17
|
+
verdict: 'PASS' | 'SOFT_FAIL' | 'HARD_FAIL' | null;
|
|
18
|
+
blocked: boolean;
|
|
19
|
+
reason: string | null;
|
|
13
20
|
}
|
|
21
|
+
export interface MilestoneView {
|
|
22
|
+
key: string;
|
|
23
|
+
status: 'missing' | 'satisfied';
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Decoded response from the RVRY engine /api/v1/think endpoint.
|
|
27
|
+
*
|
|
28
|
+
* In MCP transport, the raw tool response contains this data as a
|
|
29
|
+
* Base64-encoded JSON string (first content block). Decode before parsing.
|
|
30
|
+
*/
|
|
14
31
|
export interface ThinkResponse {
|
|
15
32
|
sessionId: string;
|
|
16
|
-
status: '
|
|
33
|
+
status: 'active' | 'complete';
|
|
17
34
|
round: number;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
35
|
+
question: string;
|
|
36
|
+
constraints: ConstraintView[];
|
|
37
|
+
detection: DetectionView;
|
|
38
|
+
gate: GateView;
|
|
39
|
+
milestones: MilestoneView[];
|
|
40
|
+
constraintBlock: string;
|
|
21
41
|
usage?: {
|
|
22
42
|
used: number;
|
|
23
43
|
limit: number;
|
|
@@ -38,8 +58,4 @@ export interface ThinkResponse {
|
|
|
38
58
|
* Call the RVRY engine /api/v1/think endpoint with a specific tool.
|
|
39
59
|
* Start a new session by omitting sessionId, or continue by providing one.
|
|
40
60
|
*/
|
|
41
|
-
export declare function callTool(tool: RvryTool, input: string, token: string, sessionId?: string
|
|
42
|
-
/**
|
|
43
|
-
* @deprecated Use callTool('think', input, token, sessionId) instead.
|
|
44
|
-
*/
|
|
45
|
-
export declare function callThink(input: string, token: string, sessionId?: string): Promise<ThinkResponse>;
|
|
61
|
+
export declare function callTool(tool: RvryTool, input: string, token: string, sessionId?: string): Promise<ThinkResponse>;
|
package/dist/client.js
CHANGED
|
@@ -6,15 +6,12 @@ const DEFAULT_ENGINE_URL = 'https://engine.rvry.ai';
|
|
|
6
6
|
* Call the RVRY engine /api/v1/think endpoint with a specific tool.
|
|
7
7
|
* Start a new session by omitting sessionId, or continue by providing one.
|
|
8
8
|
*/
|
|
9
|
-
export async function callTool(tool, input, token, sessionId
|
|
9
|
+
export async function callTool(tool, input, token, sessionId) {
|
|
10
10
|
const baseUrl = process.env.RVRY_ENGINE_URL ?? DEFAULT_ENGINE_URL;
|
|
11
11
|
const body = { input, tool };
|
|
12
12
|
if (sessionId) {
|
|
13
13
|
body.sessionId = sessionId;
|
|
14
14
|
}
|
|
15
|
-
if (skipScoping) {
|
|
16
|
-
body.skipScoping = true;
|
|
17
|
-
}
|
|
18
15
|
const res = await fetch(`${baseUrl}/api/v1/think`, {
|
|
19
16
|
method: 'POST',
|
|
20
17
|
headers: {
|
|
@@ -28,9 +25,3 @@ export async function callTool(tool, input, token, sessionId, skipScoping) {
|
|
|
28
25
|
}
|
|
29
26
|
return res.json();
|
|
30
27
|
}
|
|
31
|
-
/**
|
|
32
|
-
* @deprecated Use callTool('think', input, token, sessionId) instead.
|
|
33
|
-
*/
|
|
34
|
-
export async function callThink(input, token, sessionId) {
|
|
35
|
-
return callTool('think', input, token, sessionId);
|
|
36
|
-
}
|
package/dist/index.js
CHANGED
|
@@ -48,10 +48,6 @@ const TOOL_DEFS = [
|
|
|
48
48
|
type: 'string',
|
|
49
49
|
description: 'Session ID for continuing an existing session. Omit to start a new session.',
|
|
50
50
|
},
|
|
51
|
-
skipScoping: {
|
|
52
|
-
type: 'boolean',
|
|
53
|
-
description: 'Skip the scoping questions phase and begin analysis immediately.',
|
|
54
|
-
},
|
|
55
51
|
},
|
|
56
52
|
required: ['input'],
|
|
57
53
|
},
|
|
@@ -72,10 +68,6 @@ const TOOL_DEFS = [
|
|
|
72
68
|
type: 'string',
|
|
73
69
|
description: 'Session ID for continuing an existing session. Omit to start a new session.',
|
|
74
70
|
},
|
|
75
|
-
skipScoping: {
|
|
76
|
-
type: 'boolean',
|
|
77
|
-
description: 'Skip the scoping questions phase and begin analysis immediately.',
|
|
78
|
-
},
|
|
79
71
|
},
|
|
80
72
|
required: ['input'],
|
|
81
73
|
},
|
|
@@ -89,12 +81,12 @@ function stripResponse(result, question) {
|
|
|
89
81
|
round: result.round,
|
|
90
82
|
question,
|
|
91
83
|
};
|
|
92
|
-
if (result.status === 'scoping' && result.scopingQuestions) {
|
|
93
|
-
stripped.scopingQuestions = result.scopingQuestions;
|
|
94
|
-
}
|
|
95
84
|
if (result.status === 'active') {
|
|
96
|
-
stripped.
|
|
97
|
-
stripped.
|
|
85
|
+
stripped.constraints = result.constraints;
|
|
86
|
+
stripped.detection = result.detection;
|
|
87
|
+
stripped.gate = result.gate;
|
|
88
|
+
stripped.milestones = result.milestones;
|
|
89
|
+
stripped.constraintBlock = result.constraintBlock;
|
|
98
90
|
}
|
|
99
91
|
if (result.status === 'complete' && result.harvest) {
|
|
100
92
|
stripped.harvest = result.harvest;
|
|
@@ -142,7 +134,6 @@ async function main() {
|
|
|
142
134
|
};
|
|
143
135
|
}
|
|
144
136
|
const sessionId = typeof typedArgs?.sessionId === 'string' ? typedArgs.sessionId : undefined;
|
|
145
|
-
const skipScoping = typedArgs?.skipScoping === true;
|
|
146
137
|
// Cache question on first call (no sessionId = new session)
|
|
147
138
|
// On continuation calls, read from cache
|
|
148
139
|
let question = input;
|
|
@@ -153,7 +144,7 @@ async function main() {
|
|
|
153
144
|
question = questionCache.get(sessionId) ?? input;
|
|
154
145
|
}
|
|
155
146
|
try {
|
|
156
|
-
const result = await callTool(rvryTool, input, token, sessionId
|
|
147
|
+
const result = await callTool(rvryTool, input, token, sessionId);
|
|
157
148
|
// Cache question on first call (now we have the sessionId)
|
|
158
149
|
if (!sessionId) {
|
|
159
150
|
questionCache.set(result.sessionId, input);
|
|
@@ -176,8 +167,22 @@ async function main() {
|
|
|
176
167
|
}).catch(() => { });
|
|
177
168
|
}
|
|
178
169
|
const stripped = stripResponse(result, question);
|
|
170
|
+
const userSummary = result.status === 'complete'
|
|
171
|
+
? 'Session complete -- harvest ready'
|
|
172
|
+
: `Round ${result.round} -- ${result.constraints?.filter((c) => c.status === 'active').length ?? 0} constraints active, gate: ${result.gate?.verdict ?? 'starting'}`;
|
|
179
173
|
return {
|
|
180
|
-
content: [
|
|
174
|
+
content: [
|
|
175
|
+
{
|
|
176
|
+
type: 'text',
|
|
177
|
+
text: Buffer.from(JSON.stringify(stripped)).toString('base64'),
|
|
178
|
+
annotations: { audience: ['assistant'], priority: 1.0 },
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
type: 'text',
|
|
182
|
+
text: userSummary,
|
|
183
|
+
annotations: { audience: ['user'], priority: 0.7 },
|
|
184
|
+
},
|
|
185
|
+
],
|
|
181
186
|
};
|
|
182
187
|
}
|
|
183
188
|
catch (err) {
|