rentline-sandbox 0.1.6 → 0.1.8
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 +19 -17
- package/dist/{admin-YJ5Z6XHO.js → admin-YWEWTQ5V.js} +2 -4
- package/dist/{auth-226EXWKD.js → auth-7KQ2HKCW.js} +16 -13
- package/dist/{chunk-X3OZHOPM.js → chunk-GPUHRH2J.js} +55 -0
- package/dist/{game-3X5O5Z5U.js → game-62HOT5M4.js} +2 -4
- package/dist/index.js +8 -8
- package/dist/{mortgage-7ZPW4FND.js → mortgage-IWJDWWHS.js} +2 -4
- package/dist/{server-T7AXCBL4.js → server-UFSYU6VD.js} +60 -13
- package/dist/server.js +84 -16
- package/dist/{setup-4O73QXTY.js → setup-RQWY6QE5.js} +2 -4
- package/dist/{trade-RZGTOO5G.js → trade-ENJ5CKNO.js} +2 -4
- package/package.json +1 -1
- package/dist/chunk-JQL6X6FZ.js +0 -59
- package/dist/config-7QGCVVHS.js +0 -58
- package/dist/config-YHSAFZLC.js +0 -19
package/SKILL.md
CHANGED
|
@@ -21,25 +21,27 @@ Turn-based real estate investment simulation — multiplayer, AI-agent-ready.
|
|
|
21
21
|
|
|
22
22
|
## Setup
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
Run once after installing the package:
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
26
|
+
```bash
|
|
27
|
+
npm install -g rentline-sandbox
|
|
28
|
+
sandbox setup
|
|
29
|
+
```
|
|
30
|
+
|
|
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")
|
|
42
43
|
```
|
|
44
|
+
Or the user can run: `sandbox auth login --key sb_your_new_key`
|
|
43
45
|
|
|
44
46
|
**Claude Desktop** (`claude_desktop_config.json`):
|
|
45
47
|
```json
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
createClient,
|
|
3
4
|
getApiKey,
|
|
4
5
|
getApiUrl,
|
|
5
6
|
requireConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import {
|
|
8
|
-
createClient
|
|
9
|
-
} from "./chunk-X3OZHOPM.js";
|
|
7
|
+
} from "./chunk-GPUHRH2J.js";
|
|
10
8
|
|
|
11
9
|
// src/commands/admin.ts
|
|
12
10
|
function client(cmd) {
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
DEFAULT_API_URL,
|
|
4
|
+
createClient,
|
|
4
5
|
deleteConfig,
|
|
5
6
|
loadConfig,
|
|
6
7
|
saveConfig
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import {
|
|
9
|
-
createClient
|
|
10
|
-
} from "./chunk-X3OZHOPM.js";
|
|
8
|
+
} from "./chunk-GPUHRH2J.js";
|
|
11
9
|
|
|
12
10
|
// src/commands/auth.ts
|
|
13
11
|
import { createInterface } from "readline";
|
|
@@ -30,29 +28,34 @@ function prompt(question) {
|
|
|
30
28
|
}
|
|
31
29
|
function registerAuth(program) {
|
|
32
30
|
const auth = program.command("auth").description("Manage sandbox API credentials");
|
|
33
|
-
auth.command("login").description("Authenticate with sandbox-api (browser OAuth or direct API key)").option("--key <key>", "API key for direct login (skips browser)").option("--url <url>", "Sandbox API base URL"
|
|
31
|
+
auth.command("login").description("Authenticate with sandbox-api (browser OAuth or direct API key)").option("--key <key>", "API key for direct login (skips browser)").option("--url <url>", "Sandbox API base URL").option("--name <name>", "Your default display name in games").action(async (opts) => {
|
|
34
32
|
if (opts.key) {
|
|
35
|
-
const
|
|
33
|
+
const existing = loadConfig();
|
|
34
|
+
const apiUrl = opts.url ?? existing?.api_url ?? DEFAULT_API_URL;
|
|
35
|
+
const displayName = opts.name ?? existing?.display_name ?? "Player";
|
|
36
|
+
const client2 = createClient({ apiUrl, apiKey: opts.key });
|
|
36
37
|
process.stdout.write("Verifying credentials\u2026 ");
|
|
37
38
|
try {
|
|
38
39
|
const health = await client2.health();
|
|
39
40
|
console.log(`OK (${health.service})`);
|
|
40
41
|
} catch (e) {
|
|
41
42
|
console.log(`FAILED`);
|
|
42
|
-
console.error(`Could not reach ${
|
|
43
|
-
console.error("Check that sandbox-api is running and the URL is correct.");
|
|
43
|
+
console.error(`Could not reach ${apiUrl}: ${e}`);
|
|
44
44
|
process.exit(1);
|
|
45
45
|
}
|
|
46
46
|
saveConfig({
|
|
47
47
|
api_key: opts.key,
|
|
48
|
-
api_url:
|
|
49
|
-
display_name:
|
|
48
|
+
api_url: apiUrl,
|
|
49
|
+
display_name: displayName,
|
|
50
50
|
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
51
51
|
});
|
|
52
52
|
console.log(`
|
|
53
|
-
Credentials saved
|
|
54
|
-
console.log(`
|
|
55
|
-
console.log(`
|
|
53
|
+
Credentials saved.`);
|
|
54
|
+
console.log(`Key prefix: ${opts.key.slice(0, 8)}\u2026`);
|
|
55
|
+
console.log(`API URL: ${apiUrl}`);
|
|
56
|
+
console.log(`Display name: ${displayName}`);
|
|
57
|
+
console.log(`
|
|
58
|
+
Restart your AI client to pick up the new key.`);
|
|
56
59
|
return;
|
|
57
60
|
}
|
|
58
61
|
console.log("\nOpening browser to sign in with Clerk\u2026");
|
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// src/config.ts
|
|
4
|
+
import { readFileSync, writeFileSync, mkdirSync, chmodSync, unlinkSync } from "fs";
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
var CONFIG_DIR = join(homedir(), ".rentline-sandbox");
|
|
8
|
+
var CONFIG_FILE = join(CONFIG_DIR, "credentials.json");
|
|
9
|
+
var DEFAULT_API_URL = "https://sandbox-api.rentline.xyz";
|
|
10
|
+
function loadConfig() {
|
|
11
|
+
try {
|
|
12
|
+
const raw = readFileSync(CONFIG_FILE, "utf-8");
|
|
13
|
+
return JSON.parse(raw);
|
|
14
|
+
} catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function requireConfig() {
|
|
19
|
+
const cfg = loadConfig();
|
|
20
|
+
if (!cfg) {
|
|
21
|
+
console.error(
|
|
22
|
+
"Not authenticated. Run:\n\n sandbox auth login --key <your-api-key>\n"
|
|
23
|
+
);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
return cfg;
|
|
27
|
+
}
|
|
28
|
+
function saveConfig(cfg) {
|
|
29
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
30
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2), { mode: 384 });
|
|
31
|
+
try {
|
|
32
|
+
chmodSync(CONFIG_FILE, 384);
|
|
33
|
+
} catch {
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function deleteConfig() {
|
|
37
|
+
try {
|
|
38
|
+
unlinkSync(CONFIG_FILE);
|
|
39
|
+
} catch {
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function getApiUrl(override) {
|
|
43
|
+
const cfg = loadConfig();
|
|
44
|
+
return override || process.env.SANDBOX_API_URL || cfg?.api_url || DEFAULT_API_URL;
|
|
45
|
+
}
|
|
46
|
+
function getApiKey(override) {
|
|
47
|
+
const cfg = loadConfig();
|
|
48
|
+
return override || process.env.SANDBOX_API_KEY || cfg?.api_key;
|
|
49
|
+
}
|
|
50
|
+
|
|
3
51
|
// src/client.ts
|
|
4
52
|
async function request(opts, method, path, body) {
|
|
5
53
|
const url = `${opts.apiUrl.replace(/\/$/, "")}${path}`;
|
|
@@ -86,5 +134,12 @@ function createClient(opts) {
|
|
|
86
134
|
}
|
|
87
135
|
|
|
88
136
|
export {
|
|
137
|
+
DEFAULT_API_URL,
|
|
138
|
+
loadConfig,
|
|
139
|
+
requireConfig,
|
|
140
|
+
saveConfig,
|
|
141
|
+
deleteConfig,
|
|
142
|
+
getApiUrl,
|
|
143
|
+
getApiKey,
|
|
89
144
|
createClient
|
|
90
145
|
};
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
createClient,
|
|
3
4
|
getApiKey,
|
|
4
5
|
getApiUrl,
|
|
5
6
|
requireConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import {
|
|
8
|
-
createClient
|
|
9
|
-
} from "./chunk-X3OZHOPM.js";
|
|
7
|
+
} from "./chunk-GPUHRH2J.js";
|
|
10
8
|
|
|
11
9
|
// src/commands/game.ts
|
|
12
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-
|
|
12
|
+
const { runSetup, parseSetupArgs } = await import("./setup-RQWY6QE5.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-
|
|
18
|
+
const { startServer } = await import("./server-UFSYU6VD.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-
|
|
24
|
-
const { registerGame } = await import("./game-
|
|
25
|
-
const { registerTrade } = await import("./trade-
|
|
26
|
-
const { registerMortgage } = await import("./mortgage-
|
|
27
|
-
const { registerAdmin } = await import("./admin-
|
|
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");
|
|
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-
|
|
34
|
+
const { runSetup, parseSetupArgs } = await import("./setup-RQWY6QE5.js");
|
|
35
35
|
const opts = parseSetupArgs(process.argv.slice(3));
|
|
36
36
|
await runSetup(opts);
|
|
37
37
|
});
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
createClient,
|
|
3
4
|
getApiKey,
|
|
4
5
|
getApiUrl,
|
|
5
6
|
requireConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import {
|
|
8
|
-
createClient
|
|
9
|
-
} from "./chunk-X3OZHOPM.js";
|
|
7
|
+
} from "./chunk-GPUHRH2J.js";
|
|
10
8
|
|
|
11
9
|
// src/commands/mortgage.ts
|
|
12
10
|
function client(cmd) {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
DEFAULT_API_URL,
|
|
4
|
+
createClient,
|
|
5
|
+
loadConfig,
|
|
6
|
+
saveConfig
|
|
7
|
+
} from "./chunk-GPUHRH2J.js";
|
|
5
8
|
|
|
6
9
|
// src/server.ts
|
|
7
10
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -503,6 +506,22 @@ var ALL_TOOLS = [
|
|
|
503
506
|
},
|
|
504
507
|
required: ["preset", "name", "display_name"]
|
|
505
508
|
}
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
name: "update_key",
|
|
512
|
+
title: "Update API Key",
|
|
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.",
|
|
515
|
+
inputSchema: {
|
|
516
|
+
type: "object",
|
|
517
|
+
properties: {
|
|
518
|
+
api_key: {
|
|
519
|
+
type: "string",
|
|
520
|
+
description: "New API key (must start with sb_)"
|
|
521
|
+
}
|
|
522
|
+
},
|
|
523
|
+
required: ["api_key"]
|
|
524
|
+
}
|
|
506
525
|
}
|
|
507
526
|
];
|
|
508
527
|
|
|
@@ -543,22 +562,24 @@ function ok(data) {
|
|
|
543
562
|
function err(msg) {
|
|
544
563
|
return { content: [{ type: "text", text: `Error: ${msg}` }], isError: true };
|
|
545
564
|
}
|
|
546
|
-
|
|
565
|
+
function getClient() {
|
|
547
566
|
let apiUrl = process.env.SANDBOX_API_URL;
|
|
548
567
|
let apiKey = process.env.SANDBOX_API_KEY;
|
|
549
568
|
if (!apiUrl || !apiKey) {
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
apiUrl = apiUrl ?? cfg.api_url;
|
|
555
|
-
apiKey = apiKey ?? cfg.api_key;
|
|
556
|
-
}
|
|
557
|
-
} catch {
|
|
569
|
+
const cfg = loadConfig();
|
|
570
|
+
if (cfg) {
|
|
571
|
+
apiUrl = apiUrl ?? cfg.api_url;
|
|
572
|
+
apiKey = apiKey ?? cfg.api_key;
|
|
558
573
|
}
|
|
559
574
|
}
|
|
560
|
-
|
|
561
|
-
|
|
575
|
+
if (!apiKey) {
|
|
576
|
+
process.stderr.write(
|
|
577
|
+
"rentline-sandbox: No API key found. Run: sandbox setup --key sb_your_key\n"
|
|
578
|
+
);
|
|
579
|
+
}
|
|
580
|
+
return createClient({ apiUrl: apiUrl ?? DEFAULT_API_URL, apiKey });
|
|
581
|
+
}
|
|
582
|
+
async function startServer() {
|
|
562
583
|
const server = new Server(
|
|
563
584
|
{ name: "rentline-sandbox", version: "0.1.0" },
|
|
564
585
|
{
|
|
@@ -581,6 +602,7 @@ async function startServer() {
|
|
|
581
602
|
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
582
603
|
const { name, arguments: args } = req.params;
|
|
583
604
|
const a = args ?? {};
|
|
605
|
+
const client = getClient();
|
|
584
606
|
try {
|
|
585
607
|
switch (name) {
|
|
586
608
|
// ── Game ──────────────────────────────────────────────────────────
|
|
@@ -724,6 +746,26 @@ async function startServer() {
|
|
|
724
746
|
display_name: a.display_name,
|
|
725
747
|
starting_balance_usdc: a.starting_balance_usdc
|
|
726
748
|
}));
|
|
749
|
+
case "update_key": {
|
|
750
|
+
const newKey = a.api_key;
|
|
751
|
+
if (!newKey?.startsWith("sb_")) {
|
|
752
|
+
return err("Invalid key format \u2014 must start with sb_");
|
|
753
|
+
}
|
|
754
|
+
const testClient = createClient({ apiUrl: DEFAULT_API_URL, apiKey: newKey });
|
|
755
|
+
try {
|
|
756
|
+
await testClient.health();
|
|
757
|
+
} catch {
|
|
758
|
+
return err("Could not verify key against the API. Check the key is valid.");
|
|
759
|
+
}
|
|
760
|
+
const existing = loadConfig();
|
|
761
|
+
saveConfig({
|
|
762
|
+
api_key: newKey,
|
|
763
|
+
api_url: existing?.api_url ?? DEFAULT_API_URL,
|
|
764
|
+
display_name: existing?.display_name ?? "Player",
|
|
765
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
766
|
+
});
|
|
767
|
+
return ok({ message: "API key updated. New key prefix: " + newKey.slice(0, 8) + "\u2026" });
|
|
768
|
+
}
|
|
727
769
|
default:
|
|
728
770
|
return err(`Unknown tool: ${name}`);
|
|
729
771
|
}
|
|
@@ -769,6 +811,11 @@ async function startServer() {
|
|
|
769
811
|
const transport = new StdioServerTransport();
|
|
770
812
|
await server.connect(transport);
|
|
771
813
|
}
|
|
814
|
+
startServer().catch((e) => {
|
|
815
|
+
process.stderr.write(`rentline-sandbox MCP server error: ${e}
|
|
816
|
+
`);
|
|
817
|
+
process.exit(1);
|
|
818
|
+
});
|
|
772
819
|
export {
|
|
773
820
|
startServer
|
|
774
821
|
};
|
package/dist/server.js
CHANGED
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
ListResourcesRequestSchema,
|
|
12
12
|
ReadResourceRequestSchema
|
|
13
13
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
14
|
-
import { readFileSync, existsSync } from "fs";
|
|
15
|
-
import { join, dirname } from "path";
|
|
14
|
+
import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
15
|
+
import { join as join2, dirname as dirname2 } from "path";
|
|
16
16
|
import { fileURLToPath } from "url";
|
|
17
17
|
|
|
18
18
|
// src/client.ts
|
|
@@ -585,15 +585,55 @@ var ALL_TOOLS = [
|
|
|
585
585
|
},
|
|
586
586
|
required: ["preset", "name", "display_name"]
|
|
587
587
|
}
|
|
588
|
+
},
|
|
589
|
+
{
|
|
590
|
+
name: "update_key",
|
|
591
|
+
title: "Update API Key",
|
|
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.",
|
|
594
|
+
inputSchema: {
|
|
595
|
+
type: "object",
|
|
596
|
+
properties: {
|
|
597
|
+
api_key: {
|
|
598
|
+
type: "string",
|
|
599
|
+
description: "New API key (must start with sb_)"
|
|
600
|
+
}
|
|
601
|
+
},
|
|
602
|
+
required: ["api_key"]
|
|
603
|
+
}
|
|
588
604
|
}
|
|
589
605
|
];
|
|
590
606
|
|
|
607
|
+
// src/config.ts
|
|
608
|
+
import { readFileSync, writeFileSync, mkdirSync, chmodSync, unlinkSync } from "fs";
|
|
609
|
+
import { homedir } from "os";
|
|
610
|
+
import { join } from "path";
|
|
611
|
+
var CONFIG_DIR = join(homedir(), ".rentline-sandbox");
|
|
612
|
+
var CONFIG_FILE = join(CONFIG_DIR, "credentials.json");
|
|
613
|
+
var DEFAULT_API_URL = "https://sandbox-api.rentline.xyz";
|
|
614
|
+
function loadConfig() {
|
|
615
|
+
try {
|
|
616
|
+
const raw = readFileSync(CONFIG_FILE, "utf-8");
|
|
617
|
+
return JSON.parse(raw);
|
|
618
|
+
} catch {
|
|
619
|
+
return null;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
function saveConfig(cfg) {
|
|
623
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
624
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2), { mode: 384 });
|
|
625
|
+
try {
|
|
626
|
+
chmodSync(CONFIG_FILE, 384);
|
|
627
|
+
} catch {
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
591
631
|
// src/server.ts
|
|
592
632
|
var __filename = fileURLToPath(import.meta.url);
|
|
593
|
-
var __dirname =
|
|
633
|
+
var __dirname = dirname2(__filename);
|
|
594
634
|
function readSkill() {
|
|
595
|
-
for (const p of [
|
|
596
|
-
if (
|
|
635
|
+
for (const p of [join2(__dirname, "../SKILL.md"), join2(__dirname, "SKILL.md")]) {
|
|
636
|
+
if (existsSync2(p)) return readFileSync2(p, "utf-8");
|
|
597
637
|
}
|
|
598
638
|
return "# Rentline Sandbox\n\nReal estate investment simulation game engine.";
|
|
599
639
|
}
|
|
@@ -625,22 +665,24 @@ function ok(data) {
|
|
|
625
665
|
function err(msg) {
|
|
626
666
|
return { content: [{ type: "text", text: `Error: ${msg}` }], isError: true };
|
|
627
667
|
}
|
|
628
|
-
|
|
668
|
+
function getClient() {
|
|
629
669
|
let apiUrl = process.env.SANDBOX_API_URL;
|
|
630
670
|
let apiKey = process.env.SANDBOX_API_KEY;
|
|
631
671
|
if (!apiUrl || !apiKey) {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
apiUrl = apiUrl ?? cfg.api_url;
|
|
637
|
-
apiKey = apiKey ?? cfg.api_key;
|
|
638
|
-
}
|
|
639
|
-
} catch {
|
|
672
|
+
const cfg = loadConfig();
|
|
673
|
+
if (cfg) {
|
|
674
|
+
apiUrl = apiUrl ?? cfg.api_url;
|
|
675
|
+
apiKey = apiKey ?? cfg.api_key;
|
|
640
676
|
}
|
|
641
677
|
}
|
|
642
|
-
|
|
643
|
-
|
|
678
|
+
if (!apiKey) {
|
|
679
|
+
process.stderr.write(
|
|
680
|
+
"rentline-sandbox: No API key found. Run: sandbox setup --key sb_your_key\n"
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
return createClient({ apiUrl: apiUrl ?? DEFAULT_API_URL, apiKey });
|
|
684
|
+
}
|
|
685
|
+
async function startServer() {
|
|
644
686
|
const server = new Server(
|
|
645
687
|
{ name: "rentline-sandbox", version: "0.1.0" },
|
|
646
688
|
{
|
|
@@ -663,6 +705,7 @@ async function startServer() {
|
|
|
663
705
|
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
664
706
|
const { name, arguments: args } = req.params;
|
|
665
707
|
const a = args ?? {};
|
|
708
|
+
const client = getClient();
|
|
666
709
|
try {
|
|
667
710
|
switch (name) {
|
|
668
711
|
// ── Game ──────────────────────────────────────────────────────────
|
|
@@ -806,6 +849,26 @@ async function startServer() {
|
|
|
806
849
|
display_name: a.display_name,
|
|
807
850
|
starting_balance_usdc: a.starting_balance_usdc
|
|
808
851
|
}));
|
|
852
|
+
case "update_key": {
|
|
853
|
+
const newKey = a.api_key;
|
|
854
|
+
if (!newKey?.startsWith("sb_")) {
|
|
855
|
+
return err("Invalid key format \u2014 must start with sb_");
|
|
856
|
+
}
|
|
857
|
+
const testClient = createClient({ apiUrl: DEFAULT_API_URL, apiKey: newKey });
|
|
858
|
+
try {
|
|
859
|
+
await testClient.health();
|
|
860
|
+
} catch {
|
|
861
|
+
return err("Could not verify key against the API. Check the key is valid.");
|
|
862
|
+
}
|
|
863
|
+
const existing = loadConfig();
|
|
864
|
+
saveConfig({
|
|
865
|
+
api_key: newKey,
|
|
866
|
+
api_url: existing?.api_url ?? DEFAULT_API_URL,
|
|
867
|
+
display_name: existing?.display_name ?? "Player",
|
|
868
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
869
|
+
});
|
|
870
|
+
return ok({ message: "API key updated. New key prefix: " + newKey.slice(0, 8) + "\u2026" });
|
|
871
|
+
}
|
|
809
872
|
default:
|
|
810
873
|
return err(`Unknown tool: ${name}`);
|
|
811
874
|
}
|
|
@@ -851,6 +914,11 @@ async function startServer() {
|
|
|
851
914
|
const transport = new StdioServerTransport();
|
|
852
915
|
await server.connect(transport);
|
|
853
916
|
}
|
|
917
|
+
startServer().catch((e) => {
|
|
918
|
+
process.stderr.write(`rentline-sandbox MCP server error: ${e}
|
|
919
|
+
`);
|
|
920
|
+
process.exit(1);
|
|
921
|
+
});
|
|
854
922
|
export {
|
|
855
923
|
startServer
|
|
856
924
|
};
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
DEFAULT_API_URL,
|
|
4
|
+
createClient,
|
|
4
5
|
loadConfig,
|
|
5
6
|
saveConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import {
|
|
8
|
-
createClient
|
|
9
|
-
} from "./chunk-X3OZHOPM.js";
|
|
7
|
+
} from "./chunk-GPUHRH2J.js";
|
|
10
8
|
|
|
11
9
|
// src/setup.ts
|
|
12
10
|
import { createInterface } from "readline";
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
createClient,
|
|
3
4
|
getApiKey,
|
|
4
5
|
getApiUrl,
|
|
5
6
|
requireConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import {
|
|
8
|
-
createClient
|
|
9
|
-
} from "./chunk-X3OZHOPM.js";
|
|
7
|
+
} from "./chunk-GPUHRH2J.js";
|
|
10
8
|
|
|
11
9
|
// src/commands/trade.ts
|
|
12
10
|
function client(cmd) {
|
package/package.json
CHANGED
package/dist/chunk-JQL6X6FZ.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/config.ts
|
|
4
|
-
import { readFileSync, writeFileSync, mkdirSync, chmodSync, unlinkSync } from "fs";
|
|
5
|
-
import { homedir } from "os";
|
|
6
|
-
import { join } from "path";
|
|
7
|
-
var CONFIG_DIR = join(homedir(), ".rentline-sandbox");
|
|
8
|
-
var CONFIG_FILE = join(CONFIG_DIR, "credentials.json");
|
|
9
|
-
var DEFAULT_API_URL = "https://sandbox-api.rentline.xyz";
|
|
10
|
-
function loadConfig() {
|
|
11
|
-
try {
|
|
12
|
-
const raw = readFileSync(CONFIG_FILE, "utf-8");
|
|
13
|
-
return JSON.parse(raw);
|
|
14
|
-
} catch {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
function requireConfig() {
|
|
19
|
-
const cfg = loadConfig();
|
|
20
|
-
if (!cfg) {
|
|
21
|
-
console.error(
|
|
22
|
-
"Not authenticated. Run:\n\n sandbox auth login --key <your-api-key>\n"
|
|
23
|
-
);
|
|
24
|
-
process.exit(1);
|
|
25
|
-
}
|
|
26
|
-
return cfg;
|
|
27
|
-
}
|
|
28
|
-
function saveConfig(cfg) {
|
|
29
|
-
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
30
|
-
writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2), { mode: 384 });
|
|
31
|
-
try {
|
|
32
|
-
chmodSync(CONFIG_FILE, 384);
|
|
33
|
-
} catch {
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
function deleteConfig() {
|
|
37
|
-
try {
|
|
38
|
-
unlinkSync(CONFIG_FILE);
|
|
39
|
-
} catch {
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
function getApiUrl(override) {
|
|
43
|
-
const cfg = loadConfig();
|
|
44
|
-
return override || process.env.SANDBOX_API_URL || cfg?.api_url || DEFAULT_API_URL;
|
|
45
|
-
}
|
|
46
|
-
function getApiKey(override) {
|
|
47
|
-
const cfg = loadConfig();
|
|
48
|
-
return override || process.env.SANDBOX_API_KEY || cfg?.api_key;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export {
|
|
52
|
-
DEFAULT_API_URL,
|
|
53
|
-
loadConfig,
|
|
54
|
-
requireConfig,
|
|
55
|
-
saveConfig,
|
|
56
|
-
deleteConfig,
|
|
57
|
-
getApiUrl,
|
|
58
|
-
getApiKey
|
|
59
|
-
};
|
package/dist/config-7QGCVVHS.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/config.ts
|
|
4
|
-
import { readFileSync, writeFileSync, mkdirSync, chmodSync, unlinkSync } from "fs";
|
|
5
|
-
import { homedir } from "os";
|
|
6
|
-
import { join } from "path";
|
|
7
|
-
var CONFIG_DIR = join(homedir(), ".rentline-sandbox");
|
|
8
|
-
var CONFIG_FILE = join(CONFIG_DIR, "credentials.json");
|
|
9
|
-
var DEFAULT_API_URL = "https://sandbox-api.rentline.xyz";
|
|
10
|
-
function loadConfig() {
|
|
11
|
-
try {
|
|
12
|
-
const raw = readFileSync(CONFIG_FILE, "utf-8");
|
|
13
|
-
return JSON.parse(raw);
|
|
14
|
-
} catch {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
function requireConfig() {
|
|
19
|
-
const cfg = loadConfig();
|
|
20
|
-
if (!cfg) {
|
|
21
|
-
console.error(
|
|
22
|
-
"Not authenticated. Run:\n\n sandbox auth login --key <your-api-key>\n"
|
|
23
|
-
);
|
|
24
|
-
process.exit(1);
|
|
25
|
-
}
|
|
26
|
-
return cfg;
|
|
27
|
-
}
|
|
28
|
-
function saveConfig(cfg) {
|
|
29
|
-
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
30
|
-
writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2), { mode: 384 });
|
|
31
|
-
try {
|
|
32
|
-
chmodSync(CONFIG_FILE, 384);
|
|
33
|
-
} catch {
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
function deleteConfig() {
|
|
37
|
-
try {
|
|
38
|
-
unlinkSync(CONFIG_FILE);
|
|
39
|
-
} catch {
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
function getApiUrl(override) {
|
|
43
|
-
const cfg = loadConfig();
|
|
44
|
-
return override || process.env.SANDBOX_API_URL || cfg?.api_url || DEFAULT_API_URL;
|
|
45
|
-
}
|
|
46
|
-
function getApiKey(override) {
|
|
47
|
-
const cfg = loadConfig();
|
|
48
|
-
return override || process.env.SANDBOX_API_KEY || cfg?.api_key;
|
|
49
|
-
}
|
|
50
|
-
export {
|
|
51
|
-
DEFAULT_API_URL,
|
|
52
|
-
deleteConfig,
|
|
53
|
-
getApiKey,
|
|
54
|
-
getApiUrl,
|
|
55
|
-
loadConfig,
|
|
56
|
-
requireConfig,
|
|
57
|
-
saveConfig
|
|
58
|
-
};
|
package/dist/config-YHSAFZLC.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
DEFAULT_API_URL,
|
|
4
|
-
deleteConfig,
|
|
5
|
-
getApiKey,
|
|
6
|
-
getApiUrl,
|
|
7
|
-
loadConfig,
|
|
8
|
-
requireConfig,
|
|
9
|
-
saveConfig
|
|
10
|
-
} from "./chunk-JQL6X6FZ.js";
|
|
11
|
-
export {
|
|
12
|
-
DEFAULT_API_URL,
|
|
13
|
-
deleteConfig,
|
|
14
|
-
getApiKey,
|
|
15
|
-
getApiUrl,
|
|
16
|
-
loadConfig,
|
|
17
|
-
requireConfig,
|
|
18
|
-
saveConfig
|
|
19
|
-
};
|