@rvry/mcp 1.3.0 → 1.4.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 +92 -44
- package/dist/client.d.ts +4 -0
- package/dist/codex-adapter.d.ts +51 -0
- package/dist/codex-adapter.js +346 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +22 -7
- package/dist/setup.d.ts +27 -10
- package/dist/setup.js +105 -18
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -18,12 +18,44 @@ The wizard will:
|
|
|
18
18
|
2. Auto-detect supported clients on your machine
|
|
19
19
|
3. Configure them automatically
|
|
20
20
|
|
|
21
|
-
Supported clients: **Claude Code**, **Claude Desktop**
|
|
21
|
+
Supported clients: **Claude Code**, **Claude Desktop / Co-Work**, **Codex**
|
|
22
22
|
|
|
23
23
|
Restart any running clients after setup, and RVRY is ready.
|
|
24
24
|
|
|
25
|
+
### Codex
|
|
26
|
+
|
|
27
|
+
To configure only Codex, run:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx --yes --package @rvry/mcp@latest rvry-mcp setup --client codex
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The installer registers the `rvry` MCP server through the Codex CLI and installs seven namespaced skills under `~/.agents/skills/`:
|
|
34
|
+
|
|
35
|
+
| Skill | Tool | What it does |
|
|
36
|
+
|-----------------------|-----------------|-------------------------------------------------------------------------------|
|
|
37
|
+
| `$rvry` | `rvry` | Reflective answering: observation first, then an answer under its commitments |
|
|
38
|
+
| `$rvry-think` | `think` | Quick structured analysis of a question |
|
|
39
|
+
| `$rvry-think-model` | `think_model` | Apply one of the 18 named mental models |
|
|
40
|
+
| `$rvry-deepthink` | `deepthink` | Deep multi-round analysis of a hard question |
|
|
41
|
+
| `$rvry-problem-solve` | `problem_solve` | Structured decision-making before commitment |
|
|
42
|
+
| `$rvry-challenge` | `challenge` | Adversarial stress-testing with a GO / NO GO verdict |
|
|
43
|
+
| `$rvry-meta` | `meta` | Metacognitive observation on a topic |
|
|
44
|
+
|
|
45
|
+
For example: `$rvry-deepthink Should we split the billing service?`
|
|
46
|
+
|
|
47
|
+
The installer does not add a Codex lifecycle hook, and none is required. The MCP registration and skill files contain the integration. After installing or updating RVRY, restart existing Codex sessions or reload skills so they discover the new files.
|
|
48
|
+
|
|
25
49
|
### Manual Configuration
|
|
26
50
|
|
|
51
|
+
For Codex, register the MCP server with its CLI:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
codex mcp add rvry --env RVRY_TOKEN=rvry_your_token -- npx --yes --package @rvry/mcp@latest rvry-mcp
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
This manual command creates or overwrites the `rvry` registration, but it registers the tool server only. Use the setup command above to install the seven Codex skills as well. Do not print the registration as a verification step: current Codex CLI output includes the literal `RVRY_TOKEN`.
|
|
58
|
+
|
|
27
59
|
For any MCP client that supports **stdio transport**, add this to your MCP config:
|
|
28
60
|
|
|
29
61
|
```json
|
|
@@ -42,28 +74,28 @@ Get your token at [rvry.ai/dashboard](https://rvry.ai/dashboard) after signing u
|
|
|
42
74
|
|
|
43
75
|
## Tools
|
|
44
76
|
|
|
45
|
-
| Tool
|
|
46
|
-
|
|
47
|
-
| **`think`**
|
|
48
|
-
| **`deepthink`**
|
|
49
|
-
| **`rvry`**
|
|
50
|
-
| **`think_model`**
|
|
51
|
-
| **`problem_solve`** | Structured decision-making: orient, anticipate, generate, evaluate, commit. Includes a six-bias audit and written reversal conditions before the recommendation is final.
|
|
52
|
-
| **`challenge`**
|
|
53
|
-
| **`meta`**
|
|
77
|
+
| Tool | What it does | Plan |
|
|
78
|
+
|---------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------|
|
|
79
|
+
| **`think`** | Structured analysis for questions that need structure, not a saga. 1–3 analytical rounds; simple questions complete in one. | Free+ |
|
|
80
|
+
| **`deepthink`** | Extended multi-round analysis for high-stakes questions. Catches assumptions, tests them, and doesn't let your AI wrap up until it's dealt with what it found. | Free+ |
|
|
81
|
+
| **`rvry`** | Reflective answering. A protected observation round surfaces the commitments the answer must honor, then the answer is produced under them — with a ledger showing the fate of every commitment. | Free+ |
|
|
82
|
+
| **`think_model`** | Applies one named mental model — 18 available, from Five Whys to Red Team — as a structured session with model-specific stages and synthesis. | Free+ |
|
|
83
|
+
| **`problem_solve`** | Structured decision-making: orient, anticipate, generate, evaluate, commit. Includes a six-bias audit and written reversal conditions before the recommendation is final. | Pro+ |
|
|
84
|
+
| **`challenge`** | Adversarial stress-testing. Finds weaknesses, tests assumptions, surfaces edge cases, and closes with a GO / CONDITIONAL GO / NO GO verdict. | Pro+ |
|
|
85
|
+
| **`meta`** | Sustained metacognitive observation. Examines how your AI is thinking, not just what it's thinking. | Max |
|
|
54
86
|
|
|
55
87
|
## The 18 Mental Models
|
|
56
88
|
|
|
57
|
-
`think_model` (
|
|
89
|
+
`think_model` (`/think-model` in Claude Code, `$rvry-think-model` in Codex) runs exactly one model as an engine-enforced session — fixed stages, model-specific output structure, no early exits.
|
|
58
90
|
|
|
59
|
-
|
|
|
60
|
-
|
|
61
|
-
| `five-whys`
|
|
62
|
-
| `fermi-estimation`
|
|
63
|
-
| `constraint-relaxation` | `first-principles`
|
|
64
|
-
| `opportunity-cost`
|
|
65
|
-
| `reversibility`
|
|
66
|
-
| `second-order-effects`
|
|
91
|
+
| | | |
|
|
92
|
+
|-------------------------|-------------------------|-------------------------|
|
|
93
|
+
| `five-whys` | `rubber-duck` | `assumption-surfacing` |
|
|
94
|
+
| `fermi-estimation` | `abstraction-laddering` | `decomposition` |
|
|
95
|
+
| `constraint-relaxation` | `first-principles` | `steelmanning` |
|
|
96
|
+
| `opportunity-cost` | `trade-off-matrix` | `time-horizon-shifting` |
|
|
97
|
+
| `reversibility` | `pre-mortem` | `inversion` |
|
|
98
|
+
| `second-order-effects` | `red-team` | `impact-effort-grid` |
|
|
67
99
|
|
|
68
100
|
```
|
|
69
101
|
/think-model pre-mortem we're migrating the billing system to event sourcing next quarter
|
|
@@ -77,15 +109,15 @@ A Five Whys session ends with a verified causal chain and a root-cause fix. A Pr
|
|
|
77
109
|
|
|
78
110
|
When you run setup and select Claude Code, the wizard installs these commands:
|
|
79
111
|
|
|
80
|
-
| Command
|
|
81
|
-
|
|
82
|
-
| `/think`
|
|
83
|
-
| `/deepthink`
|
|
84
|
-
| `/rvry`
|
|
85
|
-
| `/think-model`
|
|
86
|
-
| `/problem-solve` | problem_solve | Structured decision-making, stress-tested before commitment
|
|
87
|
-
| `/challenge`
|
|
88
|
-
| `/meta`
|
|
112
|
+
| Command | Tool | What it does |
|
|
113
|
+
|------------------|---------------|----------------------------------------------------------------|
|
|
114
|
+
| `/think` | think | Quick structured analysis of a question |
|
|
115
|
+
| `/deepthink` | deepthink | Deep multi-round analysis of a hard question |
|
|
116
|
+
| `/rvry` | rvry | Reflective answering — self-observation first, then the answer |
|
|
117
|
+
| `/think-model` | think_model | Apply one named mental model to a problem |
|
|
118
|
+
| `/problem-solve` | problem_solve | Structured decision-making, stress-tested before commitment |
|
|
119
|
+
| `/challenge` | challenge | Adversarial stress-test with a GO / NO GO verdict |
|
|
120
|
+
| `/meta` | meta | Metacognitive observation on a topic |
|
|
89
121
|
|
|
90
122
|
Usage: type `/deepthink [your question]` in Claude Code. Each command routes to the corresponding RVRY tool and includes rendering instructions so analysis appears as visible markdown rather than hidden in tool calls.
|
|
91
123
|
|
|
@@ -95,23 +127,39 @@ Usage: type `/deepthink [your question]` in Claude Code. Each command routes to
|
|
|
95
127
|
|
|
96
128
|
Commands are installed to `~/.claude/commands/`.
|
|
97
129
|
|
|
130
|
+
## Codex Skills
|
|
131
|
+
|
|
132
|
+
When you run setup with `--client codex`, the installer writes the seven skills listed above to `~/.agents/skills/`. Each skill includes Codex metadata declaring the `rvry` MCP dependency and disabling implicit invocation, so RVRY runs only when you explicitly select a namespaced skill. The skills preserve the same multi-round continuation, visible observation/reflection, harvest, and optional recording behavior as the Claude Code workflows.
|
|
133
|
+
|
|
134
|
+
The metadata identifies the already configured stdio dependency; it cannot carry the package arguments or `RVRY_TOKEN` needed to install RVRY by itself. Use the setup command above as the complete install and repair path.
|
|
135
|
+
|
|
136
|
+
Invoke a skill by name followed by the question, for example:
|
|
137
|
+
|
|
138
|
+
```text
|
|
139
|
+
$rvry-think-model pre-mortem we're migrating billing to event sourcing next quarter
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Re-run setup to refresh RVRY-owned skill files and metadata after a package update. Changed RVRY-owned files are backed up beside the original with a `.bak` suffix. New Codex sessions discover them automatically; restart an existing session or reload skills after installation. No Codex lifecycle hook is installed or required.
|
|
143
|
+
|
|
98
144
|
## Parameters
|
|
99
145
|
|
|
100
146
|
All tools accept:
|
|
101
147
|
|
|
102
|
-
| Parameter
|
|
103
|
-
|
|
104
|
-
| `input`
|
|
105
|
-
| `sessionId`
|
|
106
|
-
| `skipScoping`
|
|
107
|
-
| `userConstraints`
|
|
108
|
-
| `requiresCurrentData` | boolean
|
|
109
|
-
| `record`
|
|
110
|
-
| `harvest`
|
|
111
|
-
| `rounds`
|
|
148
|
+
| Parameter | Type | Required | Description |
|
|
149
|
+
|-----------------------|----------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
150
|
+
| `input` | string | Yes | Your question (new session) or analysis findings (continuation). |
|
|
151
|
+
| `sessionId` | string | No | Session ID for continuing an existing session. |
|
|
152
|
+
| `skipScoping` | boolean | No | Skip the scoping questions phase and begin analysis immediately. |
|
|
153
|
+
| `userConstraints` | string[] | No | User-stated directives or requirements to track across rounds. |
|
|
154
|
+
| `requiresCurrentData` | boolean | No | Set to `true` when the question depends on facts, policies, prices, or events that may have changed. Seeds a verification constraint that persists across all rounds. |
|
|
155
|
+
| `record` | boolean | No | When `true` on every call, the local client archives each round's body to `.rvry/<op>/<timestamp>-<slug>/round-N-<label>.md`. Passed from slash commands via the `--record` flag. |
|
|
156
|
+
| `harvest` | object | No | Final-call-only. The client includes its synthesis (`title`, `summary`, `keyFindings`, `shimmer`, `openQuestions`, `followUps`, plus operation-specific fields) so it can be persisted to the local session file. |
|
|
157
|
+
| `rounds` | array | No | Final-call-only, present only when `--record` was set. Array of `{round, mode, body}` for each analytical round. |
|
|
112
158
|
|
|
113
159
|
`think_model` additionally requires `modelName` (one of the 18 model ids) on the first call.
|
|
114
160
|
|
|
161
|
+
**Required user-input pauses:** A `scoping` response includes `scopingQuestions`; ask the user and resume with the same `sessionId`. During analysis, the client exposes `mustAskUser: true` when the engine requires an answer before it can continue. `blockingUnknowns` is included only under that exact gate and is withheld otherwise. Ask the user, stop the current turn, then continue the same session with an evidence-bearing `RESOLVE Cn:` constraint update for the user's answer; a raw answer alone does not resolve the engine constraint.
|
|
162
|
+
|
|
115
163
|
**When to use `requiresCurrentData`:** Any question about regulations, pricing, legal rulings, market conditions, API specifications, or current events. The engine will require the model to explicitly classify every cited fact as either verified-current or training-data-dependent before concluding.
|
|
116
164
|
|
|
117
165
|
**SHIMMER display:** Most sessions open with a self-observation round. The model displays `RVRY SHIMMER` with the revery definition before its observation — this is the priming phase, where the model observes its own processing before structured analysis begins. The observation is preserved verbatim in the final harvest.
|
|
@@ -128,18 +176,18 @@ The model keeps working not because it was told to think harder, but because it
|
|
|
128
176
|
|
|
129
177
|
## Pricing
|
|
130
178
|
|
|
131
|
-
| Plan | Sessions
|
|
132
|
-
|
|
133
|
-
| Free | 5/month
|
|
134
|
-
| Pro
|
|
135
|
-
| Max
|
|
179
|
+
| Plan | Sessions | Tools | Price |
|
|
180
|
+
|------|-----------|---------------------------------------------|--------|
|
|
181
|
+
| Free | 5/month | `think`, `deepthink`, `rvry`, `think_model` | $0 |
|
|
182
|
+
| Pro | 21/month | Free tools + `problem_solve`, `challenge` | $20/mo |
|
|
183
|
+
| Max | Unlimited | All tools, including `meta` | $99/mo |
|
|
136
184
|
|
|
137
185
|
Sign up at [rvry.ai](https://rvry.ai).
|
|
138
186
|
|
|
139
187
|
## Requirements
|
|
140
188
|
|
|
141
189
|
- Node.js ≥ 18
|
|
142
|
-
- An MCP client with stdio transport support (Claude Code, Claude Desktop, and most others)
|
|
190
|
+
- An MCP client with stdio transport support (Claude Code, Claude Desktop, Codex, and most others)
|
|
143
191
|
|
|
144
192
|
## License
|
|
145
193
|
|
package/dist/client.d.ts
CHANGED
|
@@ -18,6 +18,10 @@ export interface ThinkResponse {
|
|
|
18
18
|
prompt: string;
|
|
19
19
|
instruction: string;
|
|
20
20
|
scopingQuestions?: ScopingQuestion[];
|
|
21
|
+
/** True when active blocking unknowns require user input before continuing. */
|
|
22
|
+
mustAskUser?: boolean;
|
|
23
|
+
/** User-facing descriptions of the blocking unknowns that must be resolved. */
|
|
24
|
+
blockingUnknowns?: string[];
|
|
21
25
|
usage?: {
|
|
22
26
|
used: number;
|
|
23
27
|
limit: number;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex-native installation helpers for @rvry/mcp.
|
|
3
|
+
*
|
|
4
|
+
* This module deliberately uses argv arrays for every Codex invocation. Tokens
|
|
5
|
+
* are never interpolated into a shell command or written to captured output.
|
|
6
|
+
*/
|
|
7
|
+
declare const SKILL_NAME_BY_SOURCE_FILE: {
|
|
8
|
+
readonly 'rvry.md': "rvry";
|
|
9
|
+
readonly 'think.md': "rvry-think";
|
|
10
|
+
readonly 'think-model.md': "rvry-think-model";
|
|
11
|
+
readonly 'deepthink.md': "rvry-deepthink";
|
|
12
|
+
readonly 'problem-solve.md': "rvry-problem-solve";
|
|
13
|
+
readonly 'challenge.md': "rvry-challenge";
|
|
14
|
+
readonly 'meta.md': "rvry-meta";
|
|
15
|
+
};
|
|
16
|
+
type CodexSkillName = (typeof SKILL_NAME_BY_SOURCE_FILE)[keyof typeof SKILL_NAME_BY_SOURCE_FILE];
|
|
17
|
+
export type CodexCommandRunner = (command: string, args: readonly string[]) => string;
|
|
18
|
+
export interface CodexSkillSource {
|
|
19
|
+
file: string;
|
|
20
|
+
content: string;
|
|
21
|
+
description: string;
|
|
22
|
+
label: string;
|
|
23
|
+
argumentHint: string;
|
|
24
|
+
}
|
|
25
|
+
export interface CodexSkillInstallResult {
|
|
26
|
+
name: CodexSkillName;
|
|
27
|
+
status: 'ok' | 'updated' | 'unchanged' | 'error';
|
|
28
|
+
path: string;
|
|
29
|
+
metadataPath?: string;
|
|
30
|
+
backupPath?: string;
|
|
31
|
+
metadataBackupPath?: string;
|
|
32
|
+
error?: string;
|
|
33
|
+
}
|
|
34
|
+
/** Detect whether a usable Codex CLI executable is available. */
|
|
35
|
+
export declare function isCodexCliAvailable(runner?: CodexCommandRunner): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Register RVRY as a global Codex MCP server and verify the resulting config.
|
|
38
|
+
*
|
|
39
|
+
* The named entry is always re-applied through `codex mcp add`. Current Codex
|
|
40
|
+
* omits placement fields such as `environment_id` from `mcp get --json`, so a
|
|
41
|
+
* projected exact match cannot prove the server will execute locally. The add
|
|
42
|
+
* operation clears hidden overrides; unrelated inspection failures fail closed.
|
|
43
|
+
*/
|
|
44
|
+
export declare function configureCodexMcp(token: string, runner?: CodexCommandRunner): 'ok' | 'updated' | 'unchanged' | 'error';
|
|
45
|
+
/** Convert one Claude slash-command definition into a Codex-native SKILL.md. */
|
|
46
|
+
export declare function buildCodexSkill(source: CodexSkillSource): string;
|
|
47
|
+
/** Build Codex product metadata for one explicitly invoked RVRY skill. */
|
|
48
|
+
export declare function buildCodexSkillMetadata(source: Pick<CodexSkillSource, 'file'>): string;
|
|
49
|
+
/** Install the seven namespaced RVRY skills below an injected global skill root. */
|
|
50
|
+
export declare function installCodexSkills(skillsRoot: string, sources: readonly CodexSkillSource[]): CodexSkillInstallResult[];
|
|
51
|
+
export {};
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex-native installation helpers for @rvry/mcp.
|
|
3
|
+
*
|
|
4
|
+
* This module deliberately uses argv arrays for every Codex invocation. Tokens
|
|
5
|
+
* are never interpolated into a shell command or written to captured output.
|
|
6
|
+
*/
|
|
7
|
+
import { execFileSync } from 'child_process';
|
|
8
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
9
|
+
import { basename, join } from 'path';
|
|
10
|
+
const CODEX_SERVER_NAME = 'rvry';
|
|
11
|
+
const RVRY_NPX_ARGS = ['--yes', '--package', '@rvry/mcp@latest', 'rvry-mcp'];
|
|
12
|
+
const SKILL_NAME_BY_SOURCE_FILE = {
|
|
13
|
+
'rvry.md': 'rvry',
|
|
14
|
+
'think.md': 'rvry-think',
|
|
15
|
+
'think-model.md': 'rvry-think-model',
|
|
16
|
+
'deepthink.md': 'rvry-deepthink',
|
|
17
|
+
'problem-solve.md': 'rvry-problem-solve',
|
|
18
|
+
'challenge.md': 'rvry-challenge',
|
|
19
|
+
'meta.md': 'rvry-meta',
|
|
20
|
+
};
|
|
21
|
+
const SKILL_METADATA = {
|
|
22
|
+
rvry: {
|
|
23
|
+
displayName: 'RVRY',
|
|
24
|
+
shortDescription: 'Metacognitive constraint-guided reasoning',
|
|
25
|
+
defaultPrompt: 'Use $rvry to reason through this request with RVRY.',
|
|
26
|
+
},
|
|
27
|
+
'rvry-think': {
|
|
28
|
+
displayName: 'RVRY Think',
|
|
29
|
+
shortDescription: 'Structured multi-round reasoning',
|
|
30
|
+
defaultPrompt: 'Use $rvry-think to analyze this question systematically.',
|
|
31
|
+
},
|
|
32
|
+
'rvry-think-model': {
|
|
33
|
+
displayName: 'RVRY Think Model',
|
|
34
|
+
shortDescription: 'Reason with a named mental model',
|
|
35
|
+
defaultPrompt: 'Use $rvry-think-model to apply a named mental model to this problem.',
|
|
36
|
+
},
|
|
37
|
+
'rvry-deepthink': {
|
|
38
|
+
displayName: 'RVRY Deepthink',
|
|
39
|
+
shortDescription: 'Adaptive pre-mortem failure analysis',
|
|
40
|
+
defaultPrompt: 'Use $rvry-deepthink to deeply analyze this difficult question.',
|
|
41
|
+
},
|
|
42
|
+
'rvry-problem-solve': {
|
|
43
|
+
displayName: 'RVRY Problem Solve',
|
|
44
|
+
shortDescription: 'Convergent five-step decision pipeline',
|
|
45
|
+
defaultPrompt: 'Use $rvry-problem-solve to reach a stress-tested decision.',
|
|
46
|
+
},
|
|
47
|
+
'rvry-challenge': {
|
|
48
|
+
displayName: 'RVRY Challenge',
|
|
49
|
+
shortDescription: 'Adversarial proposal stress testing',
|
|
50
|
+
defaultPrompt: 'Use $rvry-challenge to stress-test this proposal before commitment.',
|
|
51
|
+
},
|
|
52
|
+
'rvry-meta': {
|
|
53
|
+
displayName: 'RVRY Meta',
|
|
54
|
+
shortDescription: 'Sustained metacognitive observation',
|
|
55
|
+
defaultPrompt: 'Use $rvry-meta to observe the reasoning process around this topic.',
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
const defaultCommandRunner = (command, args) => execFileSync(command, [...args], {
|
|
59
|
+
encoding: 'utf8',
|
|
60
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
61
|
+
});
|
|
62
|
+
function errorText(error) {
|
|
63
|
+
if (!(error instanceof Error)) {
|
|
64
|
+
return String(error);
|
|
65
|
+
}
|
|
66
|
+
const processError = error;
|
|
67
|
+
const render = (value) => {
|
|
68
|
+
if (typeof value === 'string')
|
|
69
|
+
return value;
|
|
70
|
+
if (value instanceof Uint8Array)
|
|
71
|
+
return Buffer.from(value).toString('utf8');
|
|
72
|
+
return '';
|
|
73
|
+
};
|
|
74
|
+
return [error.message, render(processError.stdout), render(processError.stderr)]
|
|
75
|
+
.filter(Boolean)
|
|
76
|
+
.join('\n');
|
|
77
|
+
}
|
|
78
|
+
function isMissingServerError(error) {
|
|
79
|
+
return /No MCP server named\s+['"]?rvry['"]?\s+found/i.test(errorText(error));
|
|
80
|
+
}
|
|
81
|
+
function parseMcpConfig(output) {
|
|
82
|
+
try {
|
|
83
|
+
const parsed = JSON.parse(output);
|
|
84
|
+
return typeof parsed === 'object' && parsed !== null ? parsed : null;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function stringRecord(value) {
|
|
91
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
92
|
+
return null;
|
|
93
|
+
const entries = Object.entries(value);
|
|
94
|
+
if (entries.some(([, item]) => typeof item !== 'string'))
|
|
95
|
+
return null;
|
|
96
|
+
return Object.fromEntries(entries);
|
|
97
|
+
}
|
|
98
|
+
function isExpectedMcpConfig(config, token) {
|
|
99
|
+
const transport = config.transport;
|
|
100
|
+
const args = transport?.args;
|
|
101
|
+
const env = stringRecord(transport?.env);
|
|
102
|
+
return (config.name === CODEX_SERVER_NAME &&
|
|
103
|
+
config.enabled === true &&
|
|
104
|
+
transport?.type === 'stdio' &&
|
|
105
|
+
transport.command === 'npx' &&
|
|
106
|
+
Array.isArray(args) &&
|
|
107
|
+
args.length === RVRY_NPX_ARGS.length &&
|
|
108
|
+
args.every((arg, index) => arg === RVRY_NPX_ARGS[index]) &&
|
|
109
|
+
env?.RVRY_TOKEN === token &&
|
|
110
|
+
Object.keys(env).length === 1 &&
|
|
111
|
+
Array.isArray(transport.env_vars) &&
|
|
112
|
+
transport.env_vars.length === 0 &&
|
|
113
|
+
transport.cwd == null &&
|
|
114
|
+
config.enabled_tools == null &&
|
|
115
|
+
config.disabled_tools == null &&
|
|
116
|
+
config.startup_timeout_sec == null &&
|
|
117
|
+
config.tool_timeout_sec == null);
|
|
118
|
+
}
|
|
119
|
+
function readCodexMcpConfig(runner) {
|
|
120
|
+
const output = runner('codex', ['mcp', 'get', CODEX_SERVER_NAME, '--json']);
|
|
121
|
+
const config = parseMcpConfig(output);
|
|
122
|
+
if (!config) {
|
|
123
|
+
throw new Error('Codex returned invalid MCP configuration JSON.');
|
|
124
|
+
}
|
|
125
|
+
return config;
|
|
126
|
+
}
|
|
127
|
+
/** Detect whether a usable Codex CLI executable is available. */
|
|
128
|
+
export function isCodexCliAvailable(runner = defaultCommandRunner) {
|
|
129
|
+
try {
|
|
130
|
+
runner('codex', ['--version']);
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Register RVRY as a global Codex MCP server and verify the resulting config.
|
|
139
|
+
*
|
|
140
|
+
* The named entry is always re-applied through `codex mcp add`. Current Codex
|
|
141
|
+
* omits placement fields such as `environment_id` from `mcp get --json`, so a
|
|
142
|
+
* projected exact match cannot prove the server will execute locally. The add
|
|
143
|
+
* operation clears hidden overrides; unrelated inspection failures fail closed.
|
|
144
|
+
*/
|
|
145
|
+
export function configureCodexMcp(token, runner = defaultCommandRunner) {
|
|
146
|
+
let existing = null;
|
|
147
|
+
let existed = false;
|
|
148
|
+
try {
|
|
149
|
+
existing = readCodexMcpConfig(runner);
|
|
150
|
+
existed = true;
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
if (!isMissingServerError(error))
|
|
154
|
+
return 'error';
|
|
155
|
+
}
|
|
156
|
+
const projectedConfigWasExpected = existing
|
|
157
|
+
? isExpectedMcpConfig(existing, token)
|
|
158
|
+
: false;
|
|
159
|
+
try {
|
|
160
|
+
runner('codex', [
|
|
161
|
+
'mcp',
|
|
162
|
+
'add',
|
|
163
|
+
CODEX_SERVER_NAME,
|
|
164
|
+
'--env',
|
|
165
|
+
`RVRY_TOKEN=${token}`,
|
|
166
|
+
'--',
|
|
167
|
+
'npx',
|
|
168
|
+
...RVRY_NPX_ARGS,
|
|
169
|
+
]);
|
|
170
|
+
const verified = readCodexMcpConfig(runner);
|
|
171
|
+
if (!verified || !isExpectedMcpConfig(verified, token)) {
|
|
172
|
+
return 'error';
|
|
173
|
+
}
|
|
174
|
+
if (!existed)
|
|
175
|
+
return 'ok';
|
|
176
|
+
return projectedConfigWasExpected ? 'unchanged' : 'updated';
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return 'error';
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function resolveSkillName(sourceFile) {
|
|
183
|
+
const name = SKILL_NAME_BY_SOURCE_FILE[basename(sourceFile)];
|
|
184
|
+
if (!name) {
|
|
185
|
+
throw new Error(`Unsupported RVRY Codex skill source: ${sourceFile}`);
|
|
186
|
+
}
|
|
187
|
+
return name;
|
|
188
|
+
}
|
|
189
|
+
function replaceSlashReferences(content) {
|
|
190
|
+
const replacements = [
|
|
191
|
+
['/problem-solve', '$rvry-problem-solve'],
|
|
192
|
+
['/think-model', '$rvry-think-model'],
|
|
193
|
+
['/deepthink', '$rvry-deepthink'],
|
|
194
|
+
['/challenge', '$rvry-challenge'],
|
|
195
|
+
['/think', '$rvry-think'],
|
|
196
|
+
['/meta', '$rvry-meta'],
|
|
197
|
+
['/rvry', '$rvry'],
|
|
198
|
+
];
|
|
199
|
+
let result = content;
|
|
200
|
+
for (const [slashName, skillName] of replacements) {
|
|
201
|
+
const escaped = slashName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
202
|
+
const pattern = new RegExp(`(^|[^A-Za-z0-9:/])${escaped}(?=$|[^A-Za-z0-9_-])`, 'gm');
|
|
203
|
+
result = result.replace(pattern, (_match, prefix) => `${prefix}${skillName}`);
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
function replaceClaudeQuestionSchema(content) {
|
|
208
|
+
return content.replace(/(^3\. For each BLOCKING uncertainty not answered in the proposal, )ask via AskUserQuestion:\r?\n(?: {3}-[^\r\n]*(?:\r?\n|$)){4}/m, '$1ask the user one concise blocking question in plain text, end the turn, and wait for the answer before continuing.\n');
|
|
209
|
+
}
|
|
210
|
+
function adaptSkillBody(content) {
|
|
211
|
+
return replaceSlashReferences(replaceClaudeQuestionSchema(content))
|
|
212
|
+
.replaceAll('$ARGUMENTS', 'SKILL_INPUT')
|
|
213
|
+
.replaceAll('ask via AskUserQuestion:', 'ask the user directly in one concise plain-text question, then end the turn and wait:')
|
|
214
|
+
.replaceAll('AskUserQuestion', 'a concise plain-text question');
|
|
215
|
+
}
|
|
216
|
+
function codexPreamble(skillName, argumentHint) {
|
|
217
|
+
const challengeScopingNote = skillName === 'rvry-challenge'
|
|
218
|
+
? '- For the first `challenge` call, pass `skipScoping: true` after completing Phase 0.5 or when `--auto` skips that scan. Phase 0.5 already handles scoping, so do not ask the engine to repeat it.\n'
|
|
219
|
+
: '';
|
|
220
|
+
return `# Codex RVRY adapter contract
|
|
221
|
+
|
|
222
|
+
Invoke this workflow as \`$${skillName} ${argumentHint}\`. SKILL_INPUT is the user's request associated with \`$${skillName}\`. Remove the skill mention itself before treating the remainder as the operation input.
|
|
223
|
+
|
|
224
|
+
- This workflow requires the MCP server named \`rvry\`. Call the requested tool from that server. If the server or tool is unavailable, stop and tell the user to run RVRY setup; never imitate or replace the RVRY workflow yourself.
|
|
225
|
+
- When the request depends on current facts, policies, prices, regulations, software behavior, or events, pass \`requiresCurrentData: true\` on the first call and every continuation call.
|
|
226
|
+
- Preserve the returned \`sessionId\` and use that same session for every continuation. Never start a replacement session to avoid an unresolved round.
|
|
227
|
+
- If a response has status \`scoping\` and includes \`scopingQuestions\`, ask the user those questions, end the turn, and wait. Resume the same \`sessionId\` after the user answers.
|
|
228
|
+
- If a response has \`mustAskUser: true\` or non-empty \`blockingUnknowns\`, record each matching active \`BLOCKING_UNKNOWN\` constraint ID from the returned prompt, ask the blocking question in plain text, end the turn, and wait.
|
|
229
|
+
- After the user answers a blocking unknown, do not send the raw answer as a continuation. Resume the same \`sessionId\` with an analytical input containing \`Constraint Updates\`, then \`RESOLVE Cn: The user confirmed that <blocking unknown text>: <user answer>.\`, then \`End Constraint Updates\`. Use the actual matching constraint ID, unknown text, and answer; resolve only answered unknowns and never invent evidence.
|
|
230
|
+
${challengeScopingNote}- Continue the tool loop for \`shimmer\`, \`orient\`, and \`active\` responses. A turn may exit the workflow only after the tool returns status \`complete\`, except for a required user-input pause or a surfaced setup/error condition.
|
|
231
|
+
`;
|
|
232
|
+
}
|
|
233
|
+
/** Convert one Claude slash-command definition into a Codex-native SKILL.md. */
|
|
234
|
+
export function buildCodexSkill(source) {
|
|
235
|
+
const skillName = resolveSkillName(source.file);
|
|
236
|
+
const taskTrigger = source.description.replace(/\s+/g, ' ').trim().replace(/[.!?]+$/, '');
|
|
237
|
+
const normalizedTrigger = `${taskTrigger.charAt(0).toLowerCase()}${taskTrigger.slice(1)}`;
|
|
238
|
+
const description = `Run RVRY's ${normalizedTrigger} workflow. Invoke explicitly as $${skillName}.`;
|
|
239
|
+
const body = adaptSkillBody(source.content).trim();
|
|
240
|
+
return [
|
|
241
|
+
'---',
|
|
242
|
+
`name: ${skillName}`,
|
|
243
|
+
`description: ${JSON.stringify(description)}`,
|
|
244
|
+
'---',
|
|
245
|
+
'',
|
|
246
|
+
codexPreamble(skillName, source.argumentHint).trim(),
|
|
247
|
+
'',
|
|
248
|
+
'## RVRY operation workflow',
|
|
249
|
+
'',
|
|
250
|
+
body,
|
|
251
|
+
'',
|
|
252
|
+
].join('\n');
|
|
253
|
+
}
|
|
254
|
+
/** Build Codex product metadata for one explicitly invoked RVRY skill. */
|
|
255
|
+
export function buildCodexSkillMetadata(source) {
|
|
256
|
+
const skillName = resolveSkillName(source.file);
|
|
257
|
+
const metadata = SKILL_METADATA[skillName];
|
|
258
|
+
return [
|
|
259
|
+
'interface:',
|
|
260
|
+
` display_name: ${JSON.stringify(metadata.displayName)}`,
|
|
261
|
+
` short_description: ${JSON.stringify(metadata.shortDescription)}`,
|
|
262
|
+
` default_prompt: ${JSON.stringify(metadata.defaultPrompt)}`,
|
|
263
|
+
'dependencies:',
|
|
264
|
+
' tools:',
|
|
265
|
+
' - type: "mcp"',
|
|
266
|
+
' value: "rvry"',
|
|
267
|
+
' description: "RVRY reasoning session server"',
|
|
268
|
+
' transport: "stdio"',
|
|
269
|
+
' command: "npx"',
|
|
270
|
+
'policy:',
|
|
271
|
+
' allow_implicit_invocation: false',
|
|
272
|
+
'',
|
|
273
|
+
].join('\n');
|
|
274
|
+
}
|
|
275
|
+
/** Install the seven namespaced RVRY skills below an injected global skill root. */
|
|
276
|
+
export function installCodexSkills(skillsRoot, sources) {
|
|
277
|
+
return sources.map((source) => {
|
|
278
|
+
let name;
|
|
279
|
+
try {
|
|
280
|
+
name = resolveSkillName(source.file);
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
return {
|
|
284
|
+
name: 'rvry',
|
|
285
|
+
status: 'error',
|
|
286
|
+
path: skillsRoot,
|
|
287
|
+
error: error instanceof Error ? error.message : String(error),
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
const directory = join(skillsRoot, name);
|
|
291
|
+
const path = join(directory, 'SKILL.md');
|
|
292
|
+
const backupPath = `${path}.bak`;
|
|
293
|
+
const metadataDirectory = join(directory, 'agents');
|
|
294
|
+
const metadataPath = join(metadataDirectory, 'openai.yaml');
|
|
295
|
+
const metadataBackupPath = `${metadataPath}.bak`;
|
|
296
|
+
try {
|
|
297
|
+
const content = buildCodexSkill(source);
|
|
298
|
+
const metadata = buildCodexSkillMetadata(source);
|
|
299
|
+
mkdirSync(directory, { recursive: true });
|
|
300
|
+
mkdirSync(metadataDirectory, { recursive: true });
|
|
301
|
+
const skillExists = existsSync(path);
|
|
302
|
+
const metadataExists = existsSync(metadataPath);
|
|
303
|
+
const previous = skillExists ? readFileSync(path, 'utf8') : undefined;
|
|
304
|
+
const previousMetadata = metadataExists ? readFileSync(metadataPath, 'utf8') : undefined;
|
|
305
|
+
const skillChanged = previous !== content;
|
|
306
|
+
const metadataChanged = previousMetadata !== metadata;
|
|
307
|
+
if (!skillChanged && !metadataChanged) {
|
|
308
|
+
return { name, status: 'unchanged', path, metadataPath };
|
|
309
|
+
}
|
|
310
|
+
let writtenBackupPath;
|
|
311
|
+
let writtenMetadataBackupPath;
|
|
312
|
+
if (skillChanged) {
|
|
313
|
+
if (previous !== undefined) {
|
|
314
|
+
writeFileSync(backupPath, previous, 'utf8');
|
|
315
|
+
writtenBackupPath = backupPath;
|
|
316
|
+
}
|
|
317
|
+
writeFileSync(path, content, 'utf8');
|
|
318
|
+
}
|
|
319
|
+
if (metadataChanged) {
|
|
320
|
+
if (previousMetadata !== undefined) {
|
|
321
|
+
writeFileSync(metadataBackupPath, previousMetadata, 'utf8');
|
|
322
|
+
writtenMetadataBackupPath = metadataBackupPath;
|
|
323
|
+
}
|
|
324
|
+
writeFileSync(metadataPath, metadata, 'utf8');
|
|
325
|
+
}
|
|
326
|
+
const status = !skillExists && !metadataExists ? 'ok' : 'updated';
|
|
327
|
+
return {
|
|
328
|
+
name,
|
|
329
|
+
status,
|
|
330
|
+
path,
|
|
331
|
+
metadataPath,
|
|
332
|
+
backupPath: writtenBackupPath,
|
|
333
|
+
metadataBackupPath: writtenMetadataBackupPath,
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
return {
|
|
338
|
+
name,
|
|
339
|
+
status: 'error',
|
|
340
|
+
path,
|
|
341
|
+
metadataPath,
|
|
342
|
+
error: error instanceof Error ? error.message : String(error),
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* Exposes 7 tools (think, think_model, rvry, deepthink, problem_solve,
|
|
9
9
|
* challenge, meta) + RVRY_* backward-compat aliases + MCP Prompts.
|
|
10
10
|
*
|
|
11
|
-
* Also supports `npx --yes --package @rvry/mcp@latest rvry-mcp setup` to
|
|
11
|
+
* Also supports `npx --yes --package @rvry/mcp@latest rvry-mcp setup` to
|
|
12
|
+
* configure supported clients and install Claude Code commands or Codex skills.
|
|
12
13
|
*/
|
|
13
14
|
import { type Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
14
15
|
import { type RvryTool, type ThinkResponse } from './client.js';
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* Exposes 7 tools (think, think_model, rvry, deepthink, problem_solve,
|
|
9
9
|
* challenge, meta) + RVRY_* backward-compat aliases + MCP Prompts.
|
|
10
10
|
*
|
|
11
|
-
* Also supports `npx --yes --package @rvry/mcp@latest rvry-mcp setup` to
|
|
11
|
+
* Also supports `npx --yes --package @rvry/mcp@latest rvry-mcp setup` to
|
|
12
|
+
* configure supported clients and install Claude Code commands or Codex skills.
|
|
12
13
|
*/
|
|
13
14
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
14
15
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
@@ -673,12 +674,18 @@ const TOOL_DEFS = [
|
|
|
673
674
|
* Strip response fields based on status for context-efficient MCP responses.
|
|
674
675
|
*
|
|
675
676
|
* `toolName` is the public MCP tool name of the call in scope. The 'shimmer'
|
|
676
|
-
* status (an engine wire value) passthrough applies to
|
|
677
|
-
*
|
|
678
|
-
*
|
|
679
|
-
* priming round.
|
|
677
|
+
* status (an engine wire value) passthrough applies to every public workflow
|
|
678
|
+
* that executes the engine's observation task. Meta starts directly in its own
|
|
679
|
+
* active observation pass and therefore never reaches this status.
|
|
680
680
|
*/
|
|
681
|
-
const
|
|
681
|
+
const SHIMMER_WORKFLOW_TOOLS = new Set([
|
|
682
|
+
'rvry',
|
|
683
|
+
'deepthink',
|
|
684
|
+
'problem_solve',
|
|
685
|
+
'think',
|
|
686
|
+
'challenge',
|
|
687
|
+
'think_model',
|
|
688
|
+
]);
|
|
682
689
|
function stripResponse(result, question, toolName) {
|
|
683
690
|
const stripped = {
|
|
684
691
|
sessionId: result.sessionId,
|
|
@@ -693,13 +700,21 @@ function stripResponse(result, question, toolName) {
|
|
|
693
700
|
stripped.prompt = result.prompt;
|
|
694
701
|
stripped.instruction = result.instruction;
|
|
695
702
|
}
|
|
696
|
-
if (result.status === 'shimmer' && toolName !== undefined &&
|
|
703
|
+
if (result.status === 'shimmer' && toolName !== undefined && SHIMMER_WORKFLOW_TOOLS.has(toolName)) {
|
|
697
704
|
stripped.prompt = result.prompt;
|
|
698
705
|
stripped.instruction = result.instruction;
|
|
699
706
|
}
|
|
700
707
|
if (result.status === 'orient') {
|
|
701
708
|
stripped.instruction = result.instruction;
|
|
702
709
|
}
|
|
710
|
+
// Blocking-unknown signals are safe, user-facing protocol fields. Only
|
|
711
|
+
// expose the unknowns when the engine explicitly requires user input.
|
|
712
|
+
if (result.mustAskUser === true) {
|
|
713
|
+
stripped.mustAskUser = true;
|
|
714
|
+
if (result.blockingUnknowns !== undefined) {
|
|
715
|
+
stripped.blockingUnknowns = result.blockingUnknowns;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
703
718
|
if (result.status === 'complete' && result.harvest) {
|
|
704
719
|
const { constraintTrace, ...harvestSafe } = result.harvest;
|
|
705
720
|
stripped.harvest = harvestSafe;
|
package/dist/setup.d.ts
CHANGED
|
@@ -2,26 +2,42 @@
|
|
|
2
2
|
* @rvry/mcp setup wizard
|
|
3
3
|
*
|
|
4
4
|
* Interactive setup: device auth flow (browser-based) or manual token paste.
|
|
5
|
-
* Auto-detects Claude Code
|
|
5
|
+
* Auto-detects Claude Code, Claude Desktop, and Codex, then configures the
|
|
6
|
+
* selected clients without touching unrelated client state.
|
|
6
7
|
*
|
|
7
8
|
* Usage: npx --yes --package @rvry/mcp@latest rvry-mcp setup
|
|
8
9
|
* npx --yes --package @rvry/mcp@latest rvry-mcp setup --token <value>
|
|
9
10
|
* npx --yes --package @rvry/mcp@latest rvry-mcp setup --client code (Claude Code only)
|
|
10
11
|
* npx --yes --package @rvry/mcp@latest rvry-mcp setup --client desktop (Claude Desktop only)
|
|
12
|
+
* npx --yes --package @rvry/mcp@latest rvry-mcp setup --client codex (Codex only)
|
|
11
13
|
*/
|
|
14
|
+
import { type CodexSkillSource } from './codex-adapter.js';
|
|
15
|
+
interface ClientDef {
|
|
16
|
+
/** Display name shown in picker */
|
|
17
|
+
name: string;
|
|
18
|
+
/** Short id for --client flag */
|
|
19
|
+
id: string;
|
|
20
|
+
/** Pre-select when detected? Defaults to true. */
|
|
21
|
+
defaultSelected?: boolean;
|
|
22
|
+
/** Detect if the client is installed */
|
|
23
|
+
detect: () => boolean;
|
|
24
|
+
/** Configure the client. Returns a status string for the summary. */
|
|
25
|
+
configure: (token: string) => 'ok' | 'updated' | 'unchanged' | 'error';
|
|
26
|
+
/** Shown when the client is not installed */
|
|
27
|
+
notInstalledHint: string;
|
|
28
|
+
}
|
|
29
|
+
/** All supported clients. Add new clients here. */
|
|
30
|
+
declare const CLIENT_REGISTRY: ClientDef[];
|
|
31
|
+
declare function isSupportedClientId(value: unknown): value is string;
|
|
32
|
+
/** Return every detected client index for an explicit --client selection. */
|
|
33
|
+
declare function selectDetectedClientIndices(availability: readonly boolean[]): number[];
|
|
12
34
|
/** The /think-model shim: one named mental model per session. */
|
|
13
35
|
declare const THINK_MODEL_SHIM_CONTENT: string;
|
|
14
36
|
/** The /think shim. Carries the Difficulty Gate + mode routing. */
|
|
15
37
|
declare const THINK_SHIM_CONTENT: string;
|
|
16
38
|
/** The /rvry shim: 3-round reflective answering with client-owned harvest. */
|
|
17
|
-
declare const RVRY_SHIM_CONTENT = "Call the rvry 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 prose, beginning with the header \"## RVRY | Observation\" and the revery definition, exactly as the instruction field describes. Do NOT show a brief status line.\n3. The commitments that surfaced (FORWARD:/FORBIDDEN:/QUESTION: lines, or the single line NOTHING) are machine-readable bookkeeping: append them to the end of the observation text you send back to the tool, but do NOT show them in the visible display.\n4. REMEMBER your observation text verbatim \u2014 you will pass it as harvest.shimmer on the final call, and you will re-display its prose in the final output.\n5. Call the rvry tool again with your observation text (prose + commitment lines) 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\nFINAL VISIBLE OUTPUT:\nWhen you present the completed answer to the user,
|
|
18
|
-
declare const SLASH_COMMANDS:
|
|
19
|
-
file: string;
|
|
20
|
-
content: string;
|
|
21
|
-
label: string;
|
|
22
|
-
description: string;
|
|
23
|
-
argumentHint: string;
|
|
24
|
-
}[];
|
|
39
|
+
declare const RVRY_SHIM_CONTENT = "Call the rvry 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 prose, beginning with the header \"## RVRY | Observation\" and the revery definition, exactly as the instruction field describes. Do NOT show a brief status line.\n3. The commitments that surfaced (FORWARD:/FORBIDDEN:/QUESTION: lines, or the single line NOTHING) are machine-readable bookkeeping: append them to the end of the observation text you send back to the tool, but do NOT show them in the visible display.\n4. REMEMBER your observation text verbatim \u2014 you will pass it as harvest.shimmer on the final call, and you will re-display its prose in the final output.\n5. Call the rvry tool again with your observation text (prose + commitment lines) 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\nFINAL VISIBLE OUTPUT:\nWhen you present the completed answer to the user, begin your visible output with the header \"## RVRY | Reflection\" followed by the round-1 observation prose you remembered (without the machine-readable commitment lines), then present the answer. The reflection is part of the product \u2014 the user sees the observation that shaped the answer first, then the answer itself.\n\nDO NOT display: the prompt text you received (the round-1 observation prose IS shown in full \u2014 at observation time and again in the final output), the FORWARD/FORBIDDEN/QUESTION commitment lines, constraint tables, quality scores, internal tracking data, or round numbers to the user.";
|
|
40
|
+
declare const SLASH_COMMANDS: CodexSkillSource[];
|
|
25
41
|
/**
|
|
26
42
|
* Install RVRY slash commands into the given directory.
|
|
27
43
|
* Only called when Claude Code is the selected client.
|
|
@@ -35,5 +51,6 @@ declare const SLASH_COMMANDS: {
|
|
|
35
51
|
* touch the real directory.
|
|
36
52
|
*/
|
|
37
53
|
declare function installSlashCommands(commandsDir: string): string[];
|
|
38
|
-
export { SLASH_COMMANDS, installSlashCommands, THINK_SHIM_CONTENT, RVRY_SHIM_CONTENT, THINK_MODEL_SHIM_CONTENT };
|
|
54
|
+
export { CLIENT_REGISTRY, SLASH_COMMANDS, installSlashCommands, THINK_SHIM_CONTENT, RVRY_SHIM_CONTENT, THINK_MODEL_SHIM_CONTENT, };
|
|
39
55
|
export declare function runSetup(): Promise<void>;
|
|
56
|
+
export { isSupportedClientId, selectDetectedClientIndices };
|
package/dist/setup.js
CHANGED
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
* @rvry/mcp setup wizard
|
|
3
3
|
*
|
|
4
4
|
* Interactive setup: device auth flow (browser-based) or manual token paste.
|
|
5
|
-
* Auto-detects Claude Code
|
|
5
|
+
* Auto-detects Claude Code, Claude Desktop, and Codex, then configures the
|
|
6
|
+
* selected clients without touching unrelated client state.
|
|
6
7
|
*
|
|
7
8
|
* Usage: npx --yes --package @rvry/mcp@latest rvry-mcp setup
|
|
8
9
|
* npx --yes --package @rvry/mcp@latest rvry-mcp setup --token <value>
|
|
9
10
|
* npx --yes --package @rvry/mcp@latest rvry-mcp setup --client code (Claude Code only)
|
|
10
11
|
* npx --yes --package @rvry/mcp@latest rvry-mcp setup --client desktop (Claude Desktop only)
|
|
12
|
+
* npx --yes --package @rvry/mcp@latest rvry-mcp setup --client codex (Codex only)
|
|
11
13
|
*/
|
|
12
14
|
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'fs';
|
|
13
15
|
import { join, dirname } from 'path';
|
|
@@ -17,6 +19,7 @@ import { execSync } from 'child_process';
|
|
|
17
19
|
import { platform } from 'os';
|
|
18
20
|
import { createRequire } from 'module';
|
|
19
21
|
import { fetch } from './fetch.js';
|
|
22
|
+
import { configureCodexMcp, installCodexSkills, isCodexCliAvailable, } from './codex-adapter.js';
|
|
20
23
|
const require = createRequire(import.meta.url);
|
|
21
24
|
const PKG_VERSION = require('../package.json').version;
|
|
22
25
|
const ENGINE_URL = 'https://engine.rvry.ai';
|
|
@@ -234,7 +237,21 @@ const CLIENT_REGISTRY = [
|
|
|
234
237
|
configure: (token) => configureDesktop(token),
|
|
235
238
|
notInstalledHint: 'Not installed',
|
|
236
239
|
},
|
|
240
|
+
{
|
|
241
|
+
name: 'Codex',
|
|
242
|
+
id: 'codex',
|
|
243
|
+
detect: isCodexCliAvailable,
|
|
244
|
+
configure: configureCodexMcp,
|
|
245
|
+
notInstalledHint: 'CLI not found (https://developers.openai.com/codex/cli)',
|
|
246
|
+
},
|
|
237
247
|
];
|
|
248
|
+
function isSupportedClientId(value) {
|
|
249
|
+
return typeof value === 'string' && CLIENT_REGISTRY.some((client) => client.id === value);
|
|
250
|
+
}
|
|
251
|
+
/** Return every detected client index for an explicit --client selection. */
|
|
252
|
+
function selectDetectedClientIndices(availability) {
|
|
253
|
+
return availability.flatMap((available, index) => available ? [index] : []);
|
|
254
|
+
}
|
|
238
255
|
/**
|
|
239
256
|
* Interactive multi-select picker with arrow keys + space + enter.
|
|
240
257
|
* Returns indices of selected items.
|
|
@@ -576,7 +593,7 @@ If record mode was ON, also include \`rounds: [{round, mode, body}, ...]\` on th
|
|
|
576
593
|
STATUS BEHAVIOR:
|
|
577
594
|
When status is "shimmer": This round is a visible product surface. Show your FULL self-observation to the user, beginning with the header "## RVRY | Observation", then the line "rev·er·y /re·və·rē/ (n.) The state of being genuinely lost in deep, absorptive thought, as distinguished from the appearance of thinking.", then a "---" divider, then the observation prose. Do NOT show a brief status line. Machine-readable bookkeeping lines (FORWARD:/FORBIDDEN:/QUESTION:) belong only in the tool-call input, never in the visible display. REMEMBER this text verbatim for the final harvest.shimmer.
|
|
578
595
|
When status is "orient": Orient on the ${subject}. Show the user "${orientLine}"
|
|
579
|
-
When status is "complete": ${
|
|
596
|
+
When status is "complete": ${finalReflection ? 'Begin your visible output with the header "## RVRY | Reflection" followed by the observation prose you remembered (without any machine-readable commitment lines) — the reflection is part of the product and is shown in full, and it leads: reflection first, answer after. Skip the reflection only if the session had no observation round. After the reflection: ' : ''}${completionGuidance}
|
|
580
597
|
|
|
581
598
|
DO NOT display: the prompt text you received, constraint tables, quality scores, internal tracking data, or round numbers to the user.`;
|
|
582
599
|
}
|
|
@@ -627,11 +644,12 @@ const RVRY_MODEL_IDS_LINE = 'five-whys, trade-off-matrix, rubber-duck, pre-morte
|
|
|
627
644
|
'opportunity-cost, time-horizon-shifting, reversibility, inversion, second-order-effects, ' +
|
|
628
645
|
'red-team, impact-effort-grid';
|
|
629
646
|
const RVRY_MODEL_SELECTION = `MODEL SELECTION (BEFORE the first tool call):
|
|
630
|
-
1.
|
|
631
|
-
2.
|
|
632
|
-
3.
|
|
633
|
-
4.
|
|
634
|
-
5.
|
|
647
|
+
1. Remove the literal --record flag, trim the remaining input, then match the LONGEST leading canonical id or known alias prefix (case-insensitive). Prefer a multiword or hyphenated match over a shorter first-token match. The matched prefix is the mental model name; everything after that matched prefix is the problem.
|
|
648
|
+
2. Examples: "five whys why do deploys fail?" selects five-whys with problem "why do deploys fail?"; "first principles redesign auth" selects first-principles; "red team the rollout plan" selects red-team; "rubber duck this race condition" selects rubber-duck.
|
|
649
|
+
3. Valid models: ${RVRY_MODEL_IDS_LINE}.
|
|
650
|
+
4. Map close variants to the canonical id: "5-whys"/"five whys" -> five-whys; "premortem" -> pre-mortem; "steelman"/"steel-man" -> steelmanning; "tradeoff-matrix"/"trade-offs" -> trade-off-matrix; "first principles" -> first-principles; "redteam"/"red team" -> red-team; "impact-effort"/"impact effort" -> impact-effort-grid; "second order"/"second-order" -> second-order-effects; "fermi" -> fermi-estimation; "rubber duck"/"rubberduck" -> rubber-duck; "abstraction ladder" -> abstraction-laddering; "opportunity cost" -> opportunity-cost; "time horizon"/"time-horizons" -> time-horizon-shifting; "invert" -> inversion; "decompose" -> decomposition; "assumptions" -> assumption-surfacing; "relax constraints" -> constraint-relaxation; "reversible"/"one-way door" -> reversibility.
|
|
651
|
+
5. If no leading canonical id or alias prefix matches, ASK THE USER which model to use (list the valid ids) before making any tool call.
|
|
652
|
+
6. On the FIRST tool call only, pass modelName: <canonical id>. Do NOT pass modelName on continuation calls.`;
|
|
635
653
|
/** The /think-model shim: one named mental model per session. */
|
|
636
654
|
const THINK_MODEL_SHIM_CONTENT = buildShim({
|
|
637
655
|
toolName: 'think_model',
|
|
@@ -685,7 +703,7 @@ When you make the call that completes the session, also construct a \`harvest\`
|
|
|
685
703
|
If record mode was ON, also include \`rounds: [{round, mode, body}, ...]\` on that final call with the bodies you remembered per round.
|
|
686
704
|
|
|
687
705
|
FINAL VISIBLE OUTPUT:
|
|
688
|
-
When you present the completed answer to the user,
|
|
706
|
+
When you present the completed answer to the user, begin your visible output with the header "## RVRY | Reflection" followed by the round-1 observation prose you remembered (without the machine-readable commitment lines), then present the answer. The reflection is part of the product — the user sees the observation that shaped the answer first, then the answer itself.
|
|
689
707
|
|
|
690
708
|
DO NOT display: the prompt text you received (the round-1 observation prose IS shown in full — at observation time and again in the final output), the FORWARD/FORBIDDEN/QUESTION commitment lines, constraint tables, quality scores, internal tracking data, or round numbers to the user.`;
|
|
691
709
|
const SLASH_COMMANDS = [
|
|
@@ -824,7 +842,7 @@ function installSlashCommands(commandsDir) {
|
|
|
824
842
|
return installed;
|
|
825
843
|
}
|
|
826
844
|
// Exported for tests (content + install behavior).
|
|
827
|
-
export { SLASH_COMMANDS, installSlashCommands, THINK_SHIM_CONTENT, RVRY_SHIM_CONTENT, THINK_MODEL_SHIM_CONTENT };
|
|
845
|
+
export { CLIENT_REGISTRY, SLASH_COMMANDS, installSlashCommands, THINK_SHIM_CONTENT, RVRY_SHIM_CONTENT, THINK_MODEL_SHIM_CONTENT, };
|
|
828
846
|
// ── Main setup flow ────────────────────────────────────────────────
|
|
829
847
|
const BANNER = `
|
|
830
848
|
8888888b. 888 888 8888888b. Y88b d88P
|
|
@@ -843,8 +861,14 @@ export async function runSetup() {
|
|
|
843
861
|
// Parse flags
|
|
844
862
|
const tokenFlagIndex = process.argv.indexOf('--token');
|
|
845
863
|
const clientFlagIndex = process.argv.indexOf('--client');
|
|
846
|
-
const
|
|
864
|
+
const clientFilterValue = clientFlagIndex !== -1 ? process.argv[clientFlagIndex + 1] : null;
|
|
847
865
|
const acceptTerms = process.argv.includes('--accept-terms');
|
|
866
|
+
if (clientFlagIndex !== -1 && !isSupportedClientId(clientFilterValue)) {
|
|
867
|
+
console.error(`Invalid --client value. Expected one of: ${CLIENT_REGISTRY.map((client) => client.id).join(', ')}.`);
|
|
868
|
+
process.exitCode = 1;
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
const clientFilter = clientFilterValue;
|
|
848
872
|
// ── Step 1: Terms of Service ────────────────────────────────────
|
|
849
873
|
console.log('[1/5] Terms of Service');
|
|
850
874
|
console.log('');
|
|
@@ -938,7 +962,12 @@ export async function runSetup() {
|
|
|
938
962
|
console.log('');
|
|
939
963
|
// ── Step 3: Configure clients ───────────────────────────────────
|
|
940
964
|
console.log('[4/5] Select apps to add RVRY MCP configuration');
|
|
941
|
-
|
|
965
|
+
if (clientFilter) {
|
|
966
|
+
console.log(` Using explicit --client ${clientFilter} selection`);
|
|
967
|
+
}
|
|
968
|
+
else {
|
|
969
|
+
console.log(' Use \x1b[1m↑↓\x1b[0m to navigate, \x1b[1mspace\x1b[0m to toggle, \x1b[1ma\x1b[0m to toggle all, \x1b[1menter\x1b[0m to confirm');
|
|
970
|
+
}
|
|
942
971
|
console.log('');
|
|
943
972
|
const pickerItems = detected.map((d) => ({
|
|
944
973
|
label: d.client.name,
|
|
@@ -946,16 +975,21 @@ export async function runSetup() {
|
|
|
946
975
|
available: d.available,
|
|
947
976
|
hint: d.available ? undefined : d.client.notInstalledHint,
|
|
948
977
|
}));
|
|
949
|
-
|
|
978
|
+
// An explicit --client already expresses the user's selection. Skip the
|
|
979
|
+
// interactive picker so --token + --accept-terms can run unattended.
|
|
980
|
+
const selectedIndices = clientFilter
|
|
981
|
+
? selectDetectedClientIndices(detected.map((item) => item.available))
|
|
982
|
+
: await multiSelect(pickerItems);
|
|
950
983
|
const configuredClients = [];
|
|
951
984
|
let anyConfigured = false;
|
|
985
|
+
let clientConfigurationFailed = false;
|
|
952
986
|
console.log('');
|
|
953
987
|
for (const idx of selectedIndices) {
|
|
954
988
|
const { client } = detected[idx];
|
|
955
989
|
const result = client.configure(token);
|
|
956
990
|
const statusMap = {
|
|
957
991
|
ok: 'Configured',
|
|
958
|
-
updated: 'Updated
|
|
992
|
+
updated: 'Updated configuration',
|
|
959
993
|
unchanged: 'Already configured',
|
|
960
994
|
error: 'Failed',
|
|
961
995
|
};
|
|
@@ -963,8 +997,15 @@ export async function runSetup() {
|
|
|
963
997
|
const icon = result === 'error' ? '✗' : '✓';
|
|
964
998
|
console.log(` ${icon} ${client.name}: ${status}`);
|
|
965
999
|
configuredClients.push({ name: client.name, status });
|
|
966
|
-
if (result
|
|
1000
|
+
if (result === 'error') {
|
|
1001
|
+
clientConfigurationFailed = true;
|
|
1002
|
+
}
|
|
1003
|
+
else {
|
|
967
1004
|
anyConfigured = true;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
if ((clientFilter && selectedIndices.length === 0) || clientConfigurationFailed) {
|
|
1008
|
+
process.exitCode = 1;
|
|
968
1009
|
}
|
|
969
1010
|
// Install slash commands if Claude Code was configured
|
|
970
1011
|
const claudeCodeConfigured = selectedIndices.some((idx) => detected[idx].client.id === "code") && configuredClients.some((c) => c.name === "Claude Code" && c.status !== "Failed");
|
|
@@ -980,6 +1021,36 @@ export async function runSetup() {
|
|
|
980
1021
|
}
|
|
981
1022
|
}
|
|
982
1023
|
}
|
|
1024
|
+
// Install namespaced Codex skills if Codex was configured. Namespacing keeps
|
|
1025
|
+
// RVRY from clobbering unrelated global skills such as `$deepthink`.
|
|
1026
|
+
const codexConfigured = selectedIndices.some((idx) => detected[idx].client.id === 'codex') && configuredClients.some((c) => c.name === 'Codex' && c.status !== 'Failed');
|
|
1027
|
+
let installedCodexSkills = [];
|
|
1028
|
+
if (codexConfigured) {
|
|
1029
|
+
console.log('');
|
|
1030
|
+
console.log(' Installing Codex skills...');
|
|
1031
|
+
installedCodexSkills = installCodexSkills(join(homedir(), '.agents', 'skills'), SLASH_COMMANDS);
|
|
1032
|
+
if (installedCodexSkills.length > 0) {
|
|
1033
|
+
console.log(` Processed ${installedCodexSkills.length} skill(s):`);
|
|
1034
|
+
for (const skill of installedCodexSkills) {
|
|
1035
|
+
const verb = skill.status === 'unchanged'
|
|
1036
|
+
? 'Ready'
|
|
1037
|
+
: skill.status === 'updated'
|
|
1038
|
+
? 'Updated'
|
|
1039
|
+
: skill.status === 'error'
|
|
1040
|
+
? 'Failed'
|
|
1041
|
+
: 'Installed';
|
|
1042
|
+
const detail = skill.status === 'error' && skill.error ? ` — ${skill.error}` : '';
|
|
1043
|
+
console.log(` ${verb}: $${skill.name}${detail}`);
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
const codexSkillErrors = installedCodexSkills.filter((skill) => skill.status === 'error');
|
|
1048
|
+
const codexSkillsReady = codexConfigured
|
|
1049
|
+
&& installedCodexSkills.length === SLASH_COMMANDS.length
|
|
1050
|
+
&& codexSkillErrors.length === 0;
|
|
1051
|
+
if (codexConfigured && !codexSkillsReady) {
|
|
1052
|
+
process.exitCode = 1;
|
|
1053
|
+
}
|
|
983
1054
|
if (selectedIndices.length === 0) {
|
|
984
1055
|
console.log(' No clients selected.');
|
|
985
1056
|
}
|
|
@@ -989,10 +1060,13 @@ export async function runSetup() {
|
|
|
989
1060
|
console.log(' Manual configuration:');
|
|
990
1061
|
console.log('');
|
|
991
1062
|
console.log(' Option A — Claude Code (if you install it later):');
|
|
992
|
-
console.log(
|
|
1063
|
+
console.log(' claude mcp add -e RVRY_TOKEN="rvry_your_token" -s user rvry -- npx --yes --package @rvry/mcp@latest rvry-mcp');
|
|
1064
|
+
console.log('');
|
|
1065
|
+
console.log(' Option B — Codex (if you install it later):');
|
|
1066
|
+
console.log(' codex mcp add rvry --env RVRY_TOKEN="rvry_your_token" -- npx --yes --package @rvry/mcp@latest rvry-mcp');
|
|
993
1067
|
console.log('');
|
|
994
|
-
console.log(' Option
|
|
995
|
-
const manualConfig = { mcpServers: { RVRY: RVRY_SERVER_ENTRY(
|
|
1068
|
+
console.log(' Option C — Claude Desktop JSON config:');
|
|
1069
|
+
const manualConfig = { mcpServers: { RVRY: RVRY_SERVER_ENTRY('rvry_your_token') } };
|
|
996
1070
|
console.log('');
|
|
997
1071
|
for (const line of JSON.stringify(manualConfig, null, 2).split('\n')) {
|
|
998
1072
|
console.log(` ${line}`);
|
|
@@ -1006,7 +1080,8 @@ export async function runSetup() {
|
|
|
1006
1080
|
// ── Summary ─────────────────────────────────────────────────────
|
|
1007
1081
|
console.log('─'.repeat(50));
|
|
1008
1082
|
console.log('');
|
|
1009
|
-
|
|
1083
|
+
const setupFailed = process.exitCode !== undefined && process.exitCode !== 0;
|
|
1084
|
+
console.log(setupFailed ? 'RVRY Setup Incomplete' : 'RVRY Setup Complete');
|
|
1010
1085
|
console.log('');
|
|
1011
1086
|
console.log(` Token: ${maskToken(token)}${usage ? ` (${usage.tier})` : ''}`);
|
|
1012
1087
|
for (const c of configuredClients) {
|
|
@@ -1018,12 +1093,23 @@ export async function runSetup() {
|
|
|
1018
1093
|
const configuredNames = new Set(configuredClients.map((c) => c.name));
|
|
1019
1094
|
const hasDesktopStyle = configuredNames.has('Claude Desktop / Claude Co-Work');
|
|
1020
1095
|
const hasCodeStyle = configuredNames.has('Claude Code');
|
|
1096
|
+
const hasCodexStyle = codexSkillsReady;
|
|
1021
1097
|
console.log('Next steps:');
|
|
1022
1098
|
let step = 1;
|
|
1023
1099
|
if (hasDesktopStyle) {
|
|
1024
1100
|
console.log(` ${step}. Restart Claude Desktop for the new MCP server to load`);
|
|
1025
1101
|
step++;
|
|
1026
1102
|
}
|
|
1103
|
+
if (hasCodexStyle) {
|
|
1104
|
+
console.log(` ${step}. Restart Codex or reload skills so the new adapter is discovered`);
|
|
1105
|
+
step++;
|
|
1106
|
+
console.log(` ${step}. Try: $rvry-deepthink [your question]`);
|
|
1107
|
+
step++;
|
|
1108
|
+
}
|
|
1109
|
+
if (codexConfigured && !codexSkillsReady) {
|
|
1110
|
+
console.log(` ${step}. Fix the Codex skill installation errors above, then rerun setup`);
|
|
1111
|
+
step++;
|
|
1112
|
+
}
|
|
1027
1113
|
if (hasCodeStyle || hasDesktopStyle) {
|
|
1028
1114
|
if (installedCommands.length > 0) {
|
|
1029
1115
|
console.log(` ${step}. Try a slash command: /deepthink [your question]`);
|
|
@@ -1038,3 +1124,4 @@ export async function runSetup() {
|
|
|
1038
1124
|
console.log(' 2. Then try: "Use deepthink to analyze..."');
|
|
1039
1125
|
}
|
|
1040
1126
|
}
|
|
1127
|
+
export { isSupportedClientId, selectDetectedClientIndices };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rvry/mcp",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Reasoning depth enforcement for LLMs. Seven structured analysis tools and 18 mental-model templates for Claude Code, Claude Desktop, and any MCP client.",
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "Reasoning depth enforcement for LLMs. Seven structured analysis tools and 18 mental-model templates for Claude Code, Claude Desktop, Codex, and any MCP client.",
|
|
5
5
|
"homepage": "https://rvry.ai",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
19
|
"build": "tsc -p tsconfig.build.json && chmod 755 dist/index.js",
|
|
20
|
-
"prepack": "
|
|
20
|
+
"prepack": "bun run build",
|
|
21
21
|
"typecheck": "tsc --noEmit"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
@@ -38,6 +38,8 @@
|
|
|
38
38
|
"critical-thinking",
|
|
39
39
|
"claude",
|
|
40
40
|
"claude-code",
|
|
41
|
+
"codex",
|
|
42
|
+
"openai-codex",
|
|
41
43
|
"llm",
|
|
42
44
|
"ai"
|
|
43
45
|
],
|