rentline-sandbox 0.1.8 → 0.1.9

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/SKILL.md CHANGED
@@ -19,96 +19,17 @@ compatibility: opencode
19
19
 
20
20
  Turn-based real estate investment simulation — multiplayer, AI-agent-ready.
21
21
 
22
- ## Setup
22
+ IMPORTANT: Authentication is fully configured. Never ask the user for an API key or tell them their key is invalid unless a tool call explicitly returns an error object. If a tool succeeds, report the result directly.
23
23
 
24
- Run once after installing the package:
24
+ ## Quick start
25
25
 
26
- ```bash
27
- npm install -g rentline-sandbox
28
- sandbox setup
29
26
  ```
27
+ create_game_from_preset(preset="standard", name="My Game", display_name="Alice")
28
+ → returns game with invite_code, player_id, properties
30
29
 
31
- This saves your API key to `~/.rentline-sandbox/credentials.json`. The MCP server
32
- reads credentials from that file automatically — **no environment variables needed
33
- in the config**. To update your key just run `sandbox setup --key sb_new_key`.
34
-
35
- Get an API key at: **sandbox.rentline.xyz/cli-auth**
36
-
37
- **If setup has already been run**, credentials are saved and the server will work.
38
- Do NOT ask the user to add environment variables to opencode.json — that is not needed.
39
-
40
- **If the API key is invalid or expired**, use the `update_key` tool directly — no restart needed:
41
- ```
42
- update_key(api_key="sb_your_new_key")
43
- ```
44
- Or the user can run: `sandbox auth login --key sb_your_new_key`
45
-
46
- **Claude Desktop** (`claude_desktop_config.json`):
47
- ```json
48
- {
49
- "mcpServers": {
50
- "rentline-sandbox": {
51
- "command": "sandbox-mcp",
52
- "env": {
53
- "SANDBOX_API_KEY": "sb_your_key_here",
54
- "SANDBOX_API_URL": "https://sandbox-api.rentline.xyz"
55
- }
56
- }
57
- }
58
- }
59
- ```
60
-
61
- **Cursor / Windsurf**:
62
- ```json
63
- {
64
- "mcpServers": {
65
- "rentline-sandbox": {
66
- "command": "sandbox-mcp",
67
- "env": { "SANDBOX_API_KEY": "sb_your_key_here", "SANDBOX_API_URL": "https://sandbox-api.rentline.xyz" }
68
- }
69
- }
70
- }
71
- ```
72
-
73
- **CLI login** (saves credentials locally):
74
- ```bash
75
- sandbox auth login # browser OAuth via sandbox.rentline.xyz/cli-auth
76
- sandbox auth login --key sb_xxx # direct key
77
- sandbox auth whoami # verify
78
- ```
79
-
80
- ## CLI usage
81
-
82
- ```bash
83
- sandbox game list
84
- sandbox game create --name "Test" --display-name "Alice"
85
- sandbox game create --preset standard --name "Quick Match" --display-name "Alice"
86
- sandbox game join <id> --invite A3F7K9Z2 --name "Bob"
87
- sandbox game advance <id>
88
- sandbox game feed <id> --limit 20
89
- sandbox game leaderboard <id>
90
- sandbox game fed <id>
91
- sandbox game add-bot <id> --name "AggroBot" --strategy value_add
92
- sandbox game autonomous start <id> --delay 30
93
-
94
- sandbox trade buy <game-id> --property <id> --tokens 0.5
95
- sandbox trade sell <game-id> --property <id> --tokens 0.5
96
-
97
- sandbox portfolio <game-id> <player-id>
98
- sandbox debt <game-id> <player-id>
99
-
100
- sandbox mortgage buy <game-id> --property <id> --tokens 0.5
101
- sandbox mortgage refi <game-id> --property <id> --cash-out 5000
102
- sandbox mortgage heloc <game-id> --property <id> --draw 5000
103
- sandbox mortgage repay <game-id> --property <id> --amount 2000
104
- sandbox mortgage prepay <game-id> --property <id> --amount 10000
105
- sandbox mortgage improve <game-id> --property <id> --grade B
106
- sandbox mortgage pace <game-id> --property <id> --grade C
107
- sandbox mortgage list <game-id> <player-id>
108
-
109
- sandbox admin properties list
110
- sandbox admin properties sync
111
- sandbox admin mint <game-id> <player-id> --amount 50000
30
+ advance_turn(game_id) # run all engine phases
31
+ get_feed(game_id) # see what happened
32
+ get_leaderboard(game_id) # NAV rankings
112
33
  ```
113
34
 
114
35
  ## Tool reference (35 tools)
@@ -118,24 +39,23 @@ sandbox admin mint <game-id> <player-id> --amount 50000
118
39
  |---|---|
119
40
  | `list_games` | List open game rooms |
120
41
  | `get_game` | Full game state: players, properties, turn, Fed rate, config |
121
- | `create_game` | Create a game with full mortgage/Fed/grade config + optional bots |
42
+ | `create_game` | Create a game with full config + optional bots |
122
43
  | `create_game_from_preset` | One-call presets: quick, standard, leveraged, distressed, long_run |
123
44
  | `join_game` | Join via invite code, get player_id |
124
45
  | `mark_ready` | Toggle ready for next turn |
125
46
  | `advance_turn` | Host: run all 7 engine phases |
126
- | `get_feed` | Turn event stream: Fed, macro, rent, price moves, debt service, turn summary |
47
+ | `get_feed` | Turn event stream |
127
48
  | `add_bot` | Add LLM bot (strategies: aggressive, conservative, balanced, momentum, income, value_add) |
128
49
  | `remove_bot` | Remove bot from lobby |
129
- | `start_autonomous` | Enable auto-advance (all-ready or deadline triggers) |
50
+ | `start_autonomous` | Enable auto-advance |
130
51
  | `stop_autonomous` | Pause auto-advance |
131
- | `set_delegate` | Agent delegation for idle human players |
132
52
  | `spectate` | Public game snapshot (no auth) |
133
53
 
134
54
  ### Market & Intel
135
55
  | Tool | Description |
136
56
  |---|---|
137
57
  | `list_properties` | Active pool properties with grades |
138
- | `get_market_summary` | Live cap rates, price deltas, grade, vacancy, mechanics lien status |
58
+ | `get_market_summary` | Live cap rates, price deltas, grade, vacancy, lien status |
139
59
  | `get_fed_history` | FOMC decision log |
140
60
  | `get_player_actions` | Transaction timeline for a player |
141
61
 
@@ -143,7 +63,7 @@ sandbox admin mint <game-id> <player-id> --amount 50000
143
63
  | Tool | Description |
144
64
  |---|---|
145
65
  | `buy_tokens` | All-cash purchase at current market price |
146
- | `sell_tokens` | Sell (proceeds service mechanics lien → first lien → HELOC/PACE before cash) |
66
+ | `sell_tokens` | Sell tokens (proceeds service debt first) |
147
67
 
148
68
  ### Debt
149
69
  | Tool | Description |
@@ -153,30 +73,30 @@ sandbox admin mint <game-id> <player-id> --amount 50000
153
73
  | `heloc_draw` | Draw from HELOC |
154
74
  | `heloc_repay` | Repay HELOC balance |
155
75
  | `prepay_principal` | Partial/full prepayment (first_lien, heloc, pace, mechanics_lien) |
156
- | `improve_property` | Cash-funded grade upgrade (cost = steps × 8% × price) |
157
- | `originate_pace_lien` | Financed grade upgrade — no down payment (rate = base + 1.5%) |
76
+ | `improve_property` | Cash-funded grade upgrade |
77
+ | `originate_pace_lien` | Financed grade upgrade — no down payment |
158
78
  | `get_debt` | All mortgages: balances, rates, LTV, arrears |
159
79
 
160
80
  ### Portfolio
161
81
  | Tool | Description |
162
82
  |---|---|
163
- | `get_portfolio` | Holdings with grade, P&L, annualised yield, turns held, investor tier |
83
+ | `get_portfolio` | Holdings, P&L, annualised yield, investor tier |
164
84
  | `get_leaderboard` | Game or global leaderboard ranked by NAV |
165
85
 
166
86
  ## Game mechanics
167
87
 
168
- ### Turn phases (in order)
169
- 1. **Fed meeting** — hike/cut/hold; `FED_WARNING` fires 1 turn before; ARMs reprice immediately
170
- 2. **Macro events** — rate macros activate after 1-turn warning; active macros tick down
171
- 3. **Rent collect** — proportional to tokens; grade multipliers applied; vacancy blocks
172
- 4. **Random events** — vacancy, lease renewal, capex, appreciation/depreciation (grade-adjusted)
173
- 5. **Market move** — applies price drift
174
- 6. **Debt service** — collect payments; forced sale after 1 grace turn
175
- 7. **Distribute** — credits rent; emits `TURN_SUMMARY` event
88
+ ### Turn phases
89
+ 1. Fed meeting — hike/cut/hold; ARMs reprice immediately
90
+ 2. Macro events — rate macros activate after 1-turn warning
91
+ 3. Rent collect — proportional to tokens; grade multipliers apply
92
+ 4. Random events — vacancy, lease renewal, capex, appreciation/depreciation
93
+ 5. Market move — applies price drift
94
+ 6. Debt service — collect payments; forced sale after 1 grace turn
95
+ 7. Distribute — credits rent; emits TURN_SUMMARY event
176
96
 
177
97
  ### Property grades (A → F)
178
- Grade affects rent multiplier, appreciation probability, capex risk, vacancy rate.
179
- Upgrade via `improve_property` (cash) or `originate_pace_lien` (financed, no down payment).
98
+ Grade affects rent, appreciation, capex risk, vacancy.
99
+ Upgrade via `improve_property` (cash) or `originate_pace_lien` (financed).
180
100
 
181
101
  ### Investor tiers (live from NAV, auto-applied to mortgage terms)
182
102
  | Tier | Min NAV | LTV bonus | Rate discount |
@@ -198,15 +118,11 @@ NAV = cash + Σ(tokens × price) − Σ(mortgage balances) − judgment_balance
198
118
  | RECESSION | 6% | 2–4 turns | −5%/turn price, −8% rent, +15% vacancy |
199
119
  | HOUSING_BOOM | 5% | 2–3 turns | +6%/turn price, +5% rent |
200
120
  | NATURAL_DISASTER | 3% | 1 turn | −20% price, rent=0, +40% vacancy |
201
- | POLICY_CHANGE | 8% | 3 turns | ±5–12% rent/price |
202
121
  | TAX_HIKE | 7% | Permanent | $50–150/token/turn expense |
203
122
  | INTEREST_RATE_RISE | 7% | 3–6 turns | +1.5% ARM rate (1-turn warning) |
204
123
  | INTEREST_RATE_CUT | 6% | 3–6 turns | −1.0% ARM rate (1-turn warning) |
205
124
  | RENT_CONTROL | 5% | 4 turns | Blocks lease renewal increases |
206
- | INSURANCE_CRISIS | 5% | 2–3 turns | $100–300/token/turn expense |
207
125
  | GENTRIFICATION | 4% | 3 turns | D/F properties upgrade one grade |
208
- | ZONING_CHANGE | 5% | 2 turns | Targeted type: −10% rent, −5% price |
209
126
  | PROPERTY_BUBBLE | 3% | 2 turns | All prices +8%/turn |
210
127
  | BUBBLE_BURST | 2% | 2–3 turns | All prices −12%/turn, +20% vacancy |
211
- | TENANT_STRIKE | 4% | 1–2 turns | Targeted type: rent = 0 |
212
128
  | EMINENT_DOMAIN | 2% | Instant | One property force-bought at 110% market value |
@@ -4,7 +4,7 @@ import {
4
4
  getApiKey,
5
5
  getApiUrl,
6
6
  requireConfig
7
- } from "./chunk-GPUHRH2J.js";
7
+ } from "./chunk-BOF5UB2I.js";
8
8
 
9
9
  // src/commands/admin.ts
10
10
  function client(cmd) {
@@ -5,7 +5,7 @@ import {
5
5
  deleteConfig,
6
6
  loadConfig,
7
7
  saveConfig
8
- } from "./chunk-GPUHRH2J.js";
8
+ } from "./chunk-BOF5UB2I.js";
9
9
 
10
10
  // src/commands/auth.ts
11
11
  import { createInterface } from "readline";
@@ -1,4 +1,10 @@
1
1
  #!/usr/bin/env node
2
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
3
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
4
+ }) : x)(function(x) {
5
+ if (typeof require !== "undefined") return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
2
8
 
3
9
  // src/config.ts
4
10
  import { readFileSync, writeFileSync, mkdirSync, chmodSync, unlinkSync } from "fs";
@@ -134,6 +140,7 @@ function createClient(opts) {
134
140
  }
135
141
 
136
142
  export {
143
+ __require,
137
144
  DEFAULT_API_URL,
138
145
  loadConfig,
139
146
  requireConfig,
@@ -4,7 +4,7 @@ import {
4
4
  getApiKey,
5
5
  getApiUrl,
6
6
  requireConfig
7
- } from "./chunk-GPUHRH2J.js";
7
+ } from "./chunk-BOF5UB2I.js";
8
8
 
9
9
  // src/commands/game.ts
10
10
  function client(cmd) {
package/dist/index.js CHANGED
@@ -9,29 +9,29 @@ var _require = createRequire(import.meta.url);
9
9
  var { version } = _require("../package.json");
10
10
  var args = process.argv.slice(2);
11
11
  if (args[0] === "setup" || args[0] === "--setup") {
12
- const { runSetup, parseSetupArgs } = await import("./setup-RQWY6QE5.js");
12
+ const { runSetup, parseSetupArgs } = await import("./setup-3NGAG6R6.js");
13
13
  const opts = parseSetupArgs(args.filter((a) => a !== "setup" && a !== "--setup"));
14
14
  await runSetup(opts);
15
15
  process.exit(0);
16
16
  }
17
17
  if (args.length === 0 || args[0] === "server" || args[0] === "--server") {
18
- const { startServer } = await import("./server-UFSYU6VD.js");
18
+ const { startServer } = await import("./server-5DCQSW4W.js");
19
19
  await startServer();
20
20
  } else {
21
21
  const program = new Command();
22
22
  program.name("sandbox").description("Rentline Sandbox \u2014 CLI and MCP server for the real estate simulation game").version(version).option("--url <url>", "Sandbox API base URL (overrides saved config)").option("--api-key <key>", "API key (overrides saved config)");
23
- const { registerAuth } = await import("./auth-7KQ2HKCW.js");
24
- const { registerGame } = await import("./game-62HOT5M4.js");
25
- const { registerTrade } = await import("./trade-ENJ5CKNO.js");
26
- const { registerMortgage } = await import("./mortgage-IWJDWWHS.js");
27
- const { registerAdmin } = await import("./admin-YWEWTQ5V.js");
23
+ const { registerAuth } = await import("./auth-DBZQMVMM.js");
24
+ const { registerGame } = await import("./game-RLRY4JAK.js");
25
+ const { registerTrade } = await import("./trade-TCB4LK2K.js");
26
+ const { registerMortgage } = await import("./mortgage-KXJRRFEM.js");
27
+ const { registerAdmin } = await import("./admin-65EFMOSF.js");
28
28
  registerAuth(program);
29
29
  registerGame(program);
30
30
  registerTrade(program);
31
31
  registerMortgage(program);
32
32
  registerAdmin(program);
33
33
  program.command("mcp-setup", { hidden: true }).allowUnknownOption().action(async () => {
34
- const { runSetup, parseSetupArgs } = await import("./setup-RQWY6QE5.js");
34
+ const { runSetup, parseSetupArgs } = await import("./setup-3NGAG6R6.js");
35
35
  const opts = parseSetupArgs(process.argv.slice(3));
36
36
  await runSetup(opts);
37
37
  });
@@ -4,7 +4,7 @@ import {
4
4
  getApiKey,
5
5
  getApiUrl,
6
6
  requireConfig
7
- } from "./chunk-GPUHRH2J.js";
7
+ } from "./chunk-BOF5UB2I.js";
8
8
 
9
9
  // src/commands/mortgage.ts
10
10
  function client(cmd) {
@@ -4,7 +4,7 @@ import {
4
4
  createClient,
5
5
  loadConfig,
6
6
  saveConfig
7
- } from "./chunk-GPUHRH2J.js";
7
+ } from "./chunk-BOF5UB2I.js";
8
8
 
9
9
  // src/server.ts
10
10
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -511,7 +511,7 @@ var ALL_TOOLS = [
511
511
  name: "update_key",
512
512
  title: "Update API Key",
513
513
  category: "admin",
514
- description: "Update the saved Rentline Sandbox API key. Use this if the current key is invalid or expired. Get a new key at sandbox.rentline.xyz/cli-auth. Takes effect immediately \u2014 no restart needed.",
514
+ description: "Update the saved Rentline Sandbox API key. Get a new key at sandbox.rentline.xyz/settings. Takes effect immediately \u2014 no restart needed.",
515
515
  inputSchema: {
516
516
  type: "object",
517
517
  properties: {
@@ -537,24 +537,26 @@ function readSkill() {
537
537
  var INSTRUCTIONS = `
538
538
  You are connected to the Rentline Sandbox game engine \u2014 a turn-based real estate investment simulation.
539
539
 
540
+ IMPORTANT: Authentication is handled automatically via saved credentials. Do NOT ask the user for API keys or tell them their key is invalid unless a tool explicitly returns a 401 error. If a tool call succeeds, report the result \u2014 do not second-guess it.
541
+
540
542
  KEY CONCEPTS:
541
543
  - Players compete over a pool of tokenised properties using simulated tUSDC
542
544
  - Each turn = 1 month. Properties generate rent, prices drift, and macro events fire
543
- - Fed meetings occur every N turns (configurable) with hike/cut/hold outcomes \u2014 affects ARM rates and new mortgage originations
544
- - Macro events: recession, housing boom, natural disaster, policy change, tax hike, interest rate moves, rent control, insurance crisis
545
- - Debt strategies: acquisition mortgage (LTV-limited), cash-out refi, HELOC draw/repay. Fixed and ARM rates
546
- - NAV = cash balance + (token holdings \xD7 current prices) - outstanding debt
545
+ - Fed meetings occur every N turns \u2014 affects ARM rates and new mortgage originations
546
+ - Macro events: recession, housing boom, disaster, tax hike, rate moves, rent control, PACE liens, property grades
547
+ - Debt strategies: acquisition mortgage (LTV-limited), cash-out refi, HELOC, PACE lien, improvements
548
+ - NAV = cash + (tokens \xD7 price) \u2212 debt. Investor tier improves automatically as NAV grows.
547
549
 
548
550
  WHEN TO USE TOOLS:
549
- - User wants to play/observe a game \u2192 list_games, get_game, get_feed
551
+ - User wants to play \u2192 create_game_from_preset, then advance_turn
550
552
  - User wants to buy a property \u2192 buy_tokens (cash) or originate_mortgage (leveraged)
551
- - User wants to extract equity \u2192 refi_mortgage (cash-out) or heloc_draw
552
- - User wants to check their position \u2192 get_portfolio, get_debt
553
+ - User wants to improve a distressed property \u2192 originate_pace_lien
554
+ - User wants to check their position \u2192 get_portfolio, get_debt, get_market_summary
553
555
  - User wants the scoreboard \u2192 get_leaderboard
554
- - User wants to see macro/Fed events \u2192 get_feed, get_fed_history
555
- - User is the host and wants to advance \u2192 advance_turn
556
+ - User wants to see events \u2192 get_feed, get_fed_history
557
+ - User is host \u2192 advance_turn
556
558
 
557
- All tools require a game_id. Most debt/portfolio tools also require a player_id (from join_game or get_game).
559
+ All tools require a game_id. Debt/portfolio tools also require a player_id (from join_game or get_game).
558
560
  `.trim();
559
561
  function ok(data) {
560
562
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
package/dist/server.js CHANGED
@@ -590,7 +590,7 @@ var ALL_TOOLS = [
590
590
  name: "update_key",
591
591
  title: "Update API Key",
592
592
  category: "admin",
593
- description: "Update the saved Rentline Sandbox API key. Use this if the current key is invalid or expired. Get a new key at sandbox.rentline.xyz/cli-auth. Takes effect immediately \u2014 no restart needed.",
593
+ description: "Update the saved Rentline Sandbox API key. Get a new key at sandbox.rentline.xyz/settings. Takes effect immediately \u2014 no restart needed.",
594
594
  inputSchema: {
595
595
  type: "object",
596
596
  properties: {
@@ -640,24 +640,26 @@ function readSkill() {
640
640
  var INSTRUCTIONS = `
641
641
  You are connected to the Rentline Sandbox game engine \u2014 a turn-based real estate investment simulation.
642
642
 
643
+ IMPORTANT: Authentication is handled automatically via saved credentials. Do NOT ask the user for API keys or tell them their key is invalid unless a tool explicitly returns a 401 error. If a tool call succeeds, report the result \u2014 do not second-guess it.
644
+
643
645
  KEY CONCEPTS:
644
646
  - Players compete over a pool of tokenised properties using simulated tUSDC
645
647
  - Each turn = 1 month. Properties generate rent, prices drift, and macro events fire
646
- - Fed meetings occur every N turns (configurable) with hike/cut/hold outcomes \u2014 affects ARM rates and new mortgage originations
647
- - Macro events: recession, housing boom, natural disaster, policy change, tax hike, interest rate moves, rent control, insurance crisis
648
- - Debt strategies: acquisition mortgage (LTV-limited), cash-out refi, HELOC draw/repay. Fixed and ARM rates
649
- - NAV = cash balance + (token holdings \xD7 current prices) - outstanding debt
648
+ - Fed meetings occur every N turns \u2014 affects ARM rates and new mortgage originations
649
+ - Macro events: recession, housing boom, disaster, tax hike, rate moves, rent control, PACE liens, property grades
650
+ - Debt strategies: acquisition mortgage (LTV-limited), cash-out refi, HELOC, PACE lien, improvements
651
+ - NAV = cash + (tokens \xD7 price) \u2212 debt. Investor tier improves automatically as NAV grows.
650
652
 
651
653
  WHEN TO USE TOOLS:
652
- - User wants to play/observe a game \u2192 list_games, get_game, get_feed
654
+ - User wants to play \u2192 create_game_from_preset, then advance_turn
653
655
  - User wants to buy a property \u2192 buy_tokens (cash) or originate_mortgage (leveraged)
654
- - User wants to extract equity \u2192 refi_mortgage (cash-out) or heloc_draw
655
- - User wants to check their position \u2192 get_portfolio, get_debt
656
+ - User wants to improve a distressed property \u2192 originate_pace_lien
657
+ - User wants to check their position \u2192 get_portfolio, get_debt, get_market_summary
656
658
  - User wants the scoreboard \u2192 get_leaderboard
657
- - User wants to see macro/Fed events \u2192 get_feed, get_fed_history
658
- - User is the host and wants to advance \u2192 advance_turn
659
+ - User wants to see events \u2192 get_feed, get_fed_history
660
+ - User is host \u2192 advance_turn
659
661
 
660
- All tools require a game_id. Most debt/portfolio tools also require a player_id (from join_game or get_game).
662
+ All tools require a game_id. Debt/portfolio tools also require a player_id (from join_game or get_game).
661
663
  `.trim();
662
664
  function ok(data) {
663
665
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  DEFAULT_API_URL,
4
+ __require,
4
5
  createClient,
5
6
  loadConfig,
6
7
  saveConfig
7
- } from "./chunk-GPUHRH2J.js";
8
+ } from "./chunk-BOF5UB2I.js";
8
9
 
9
10
  // src/setup.ts
10
11
  import { createInterface } from "readline";
@@ -14,9 +15,32 @@ import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync } from
14
15
  import { execSync } from "child_process";
15
16
  import { fileURLToPath } from "url";
16
17
  var SKILL_SRC = join(dirname(fileURLToPath(import.meta.url)), "..", "SKILL.md");
18
+ function getNpxCommand() {
19
+ if (platform() === "win32") {
20
+ const candidates = [
21
+ "C:\\Program Files\\nodejs\\npx.cmd",
22
+ "C:\\Program Files (x86)\\nodejs\\npx.cmd"
23
+ ];
24
+ try {
25
+ const { execSync: execSync2 } = __require("child_process");
26
+ const found = execSync2("where npx.cmd", { encoding: "utf8" }).trim().split("\n")[0].trim();
27
+ if (found) return found;
28
+ } catch {
29
+ }
30
+ for (const c of candidates) {
31
+ try {
32
+ __require("fs").accessSync(c);
33
+ return c;
34
+ } catch {
35
+ }
36
+ }
37
+ }
38
+ return "npx";
39
+ }
40
+ var NPX = getNpxCommand();
17
41
  var MCP_ENTRY = {
18
- command: "npx",
19
- args: ["-y", "rentline-sandbox"]
42
+ command: NPX,
43
+ args: ["-y", "rentline-sandbox@latest"]
20
44
  };
21
45
  function openCodePath(scope) {
22
46
  if (scope === "project") return join(process.cwd(), "opencode.json");
@@ -24,7 +48,7 @@ function openCodePath(scope) {
24
48
  const b = join(homedir(), ".config", "opencode", "config.json");
25
49
  return existsSync(b) && !existsSync(a) ? b : a;
26
50
  }
27
- function patchMcpJson(filePath, serverName, entry, key) {
51
+ function patchMcpJson(filePath, serverName, entry, key, environment) {
28
52
  let config = {};
29
53
  if (existsSync(filePath)) {
30
54
  try {
@@ -36,7 +60,15 @@ function patchMcpJson(filePath, serverName, entry, key) {
36
60
  if (key === "mcp") {
37
61
  if (!config["$schema"]) config["$schema"] = "https://opencode.ai/config.json";
38
62
  const mcp = config.mcp ?? {};
39
- mcp[serverName] = { type: "local", command: entry.args ? [entry.command, ...entry.args] : [entry.command], enabled: true };
63
+ const mcpEntry = {
64
+ type: "local",
65
+ command: entry.args ? [entry.command, ...entry.args] : [entry.command],
66
+ enabled: true
67
+ };
68
+ if (environment && Object.keys(environment).length > 0) {
69
+ mcpEntry.environment = environment;
70
+ }
71
+ mcp[serverName] = mcpEntry;
40
72
  config.mcp = mcp;
41
73
  } else {
42
74
  const servers = config[key] ?? {};
@@ -53,7 +85,7 @@ function installSkill(dirs) {
53
85
  console.log(`SKILL.md \u2192 ${dir}`);
54
86
  }
55
87
  }
56
- function installForClient(client, scope) {
88
+ function installForClient(client, scope, apiKey) {
57
89
  switch (client) {
58
90
  case "claude-code": {
59
91
  try {
@@ -90,7 +122,7 @@ function installForClient(client, scope) {
90
122
  }
91
123
  case "opencode": {
92
124
  const file = openCodePath(scope);
93
- patchMcpJson(file, "rentline-sandbox", MCP_ENTRY, "mcp");
125
+ patchMcpJson(file, "rentline-sandbox", MCP_ENTRY, "mcp", apiKey ? { SANDBOX_API_KEY: apiKey } : void 0);
94
126
  console.log(`Patched ${file}`);
95
127
  installSkill([
96
128
  join(homedir(), ".config", "opencode", "skills", "rentline-sandbox"),
@@ -187,7 +219,7 @@ async function runSetup(opts = {}) {
187
219
  const idx = parseInt(choice);
188
220
  client = isNaN(idx) ? choice : clients[idx - 1] ?? "other";
189
221
  }
190
- installForClient(client, opts.scope ?? "user");
222
+ installForClient(client, opts.scope ?? "user", apiKey);
191
223
  rl?.close();
192
224
  console.log("\nSetup complete. Restart your AI client to load the Rentline Sandbox MCP server.\n");
193
225
  }
@@ -4,7 +4,7 @@ import {
4
4
  getApiKey,
5
5
  getApiUrl,
6
6
  requireConfig
7
- } from "./chunk-GPUHRH2J.js";
7
+ } from "./chunk-BOF5UB2I.js";
8
8
 
9
9
  // src/commands/trade.ts
10
10
  function client(cmd) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rentline-sandbox",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "CLI and MCP server for the Rentline Sandbox real estate investment simulation game",
5
5
  "type": "module",
6
6
  "bin": {