rentbamboo-mcp 0.1.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.
Files changed (3) hide show
  1. package/README.md +73 -0
  2. package/cli.js +87 -0
  3. package/package.json +19 -0
package/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # rentbamboo-mcp
2
+
3
+ A zero-dependency [MCP](https://modelcontextprotocol.io) **stdio bridge** for
4
+ RentBamboo. It connects any local AI agent (Claude Desktop, Cursor, VS Code,
5
+ PI, opm) to the hosted RentBamboo MCP server over Streamable HTTP using your
6
+ API key. The 55 Panda tools it exposes are **read-only** right now.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm install -g rentbamboo-mcp
12
+ ```
13
+
14
+ ## Configure
15
+
16
+ Set your API key (get one in RentBamboo → Settings → MCP → API keys):
17
+
18
+ ```bash
19
+ export RENTBAMBOO_API_KEY=rb_live_...
20
+ ```
21
+
22
+ Optionally point at a non-production endpoint:
23
+
24
+ ```bash
25
+ export RENTBAMBOO_MCP_URL=http://localhost:3000/api/mcp
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ For **Claude Desktop / Cursor / VS Code** (`claude_desktop_config.json`,
31
+ `mcp.json`, etc.):
32
+
33
+ ```json
34
+ {
35
+ "mcpServers": {
36
+ "rentbamboo": {
37
+ "command": "rentbamboo-mcp",
38
+ "env": { "RENTBAMBOO_API_KEY": "rb_live_..." }
39
+ }
40
+ }
41
+ }
42
+ ```
43
+
44
+ For **opm** (`~/.omp/agent/mcp.json`):
45
+
46
+ ```json
47
+ {
48
+ "mcpServers": {
49
+ "rentbamboo": {
50
+ "type": "stdio",
51
+ "command": "rentbamboo-mcp",
52
+ "env": { "RENTBAMBOO_API_KEY": "rb_live_..." }
53
+ }
54
+ }
55
+ }
56
+ ```
57
+
58
+ For **PI**, install the adapter first (`pi install npm:pi-mcp-adapter`), then
59
+ point it at `rentbamboo-mcp` the same way.
60
+
61
+ ## How it works
62
+
63
+ `rentbamboo-mcp` reads JSON-RPC frames from stdin and forwards each one to the
64
+ hosted MCP endpoint (`POST https://rentbamboo.com/api/mcp`) with
65
+ `Authorization: Bearer <key>`, then writes the response back to stdout. It is a
66
+ thin proxy — all tools, permissions, and the read-only gate live server-side.
67
+
68
+ ## Environment
69
+
70
+ | Variable | Required | Default |
71
+ | --------------------- | -------- | -------------------------------- |
72
+ | `RENTBAMBOO_API_KEY` | yes | — |
73
+ | `RENTBAMBOO_MCP_URL` | no | `https://rentbamboo.com/api/mcp` |
package/cli.js ADDED
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * rentbamboo-mcp — stdio↔HTTP MCP bridge for RentBamboo.
4
+ *
5
+ * A zero-dependency bridge: it presents a stdio MCP server to any local AI
6
+ * agent (Claude Desktop, PI, opm, Cursor, VS Code) and forwards every JSON-RPC
7
+ * request to the hosted RentBamboo MCP endpoint (Streamable HTTP) using your
8
+ * API key. The actual tools/tool-execution live on the hosted server; this
9
+ * package just proxies the wire protocol.
10
+ *
11
+ * Env:
12
+ * RENTBAMBOO_API_KEY (required) your rb_live_... / rb_test_... key
13
+ * RENTBAMBOO_MCP_URL (optional) default https://rentbamboo.com/api/mcp
14
+ */
15
+
16
+ import { createInterface } from "node:readline";
17
+
18
+ const DEFAULT_URL = "https://rentbamboo.com/api/mcp";
19
+ const URL = process.env.RENTBAMBOO_MCP_URL || DEFAULT_URL;
20
+ const KEY = process.env.RENTBAMBOO_API_KEY || process.env.RENTBAMBOO_MCP_KEY || "";
21
+
22
+ if (!KEY) {
23
+ console.error(
24
+ "[rentbamboo-mcp] Set RENTBAMBOO_API_KEY to your RentBamboo API key (rb_live_...).",
25
+ );
26
+ process.exit(1);
27
+ }
28
+
29
+ /** Build a JSON-RPC error envelope for an upstream failure. */
30
+ function errorResponse(id, message) {
31
+ return { jsonrpc: "2.0", id: id ?? null, error: { code: -32603, message } };
32
+ }
33
+
34
+ async function forward(message) {
35
+ const id = Array.isArray(message) ? null : message?.id ?? null;
36
+ try {
37
+ const res = await fetch(URL, {
38
+ method: "POST",
39
+ headers: {
40
+ "Content-Type": "application/json",
41
+ Accept: "application/json",
42
+ Authorization: `Bearer ${KEY}`,
43
+ },
44
+ body: typeof message === "string" ? message : JSON.stringify(message),
45
+ signal: AbortSignal.timeout(120_000),
46
+ });
47
+ const text = await res.text();
48
+ if (res.ok) {
49
+ if (!text) return null; // notification (202 empty) — no reply
50
+ try {
51
+ return JSON.parse(text);
52
+ } catch {
53
+ return errorResponse(id, `invalid upstream response (${text.slice(0, 120)})`);
54
+ }
55
+ }
56
+ return errorResponse(id, `upstream ${res.status}: ${text.slice(0, 200)}`);
57
+ } catch (err) {
58
+ return errorResponse(id, `upstream unreachable: ${err?.message ?? "network error"}`);
59
+ }
60
+ }
61
+
62
+ // Serialize forwards so stdout responses stay in request order, and keep the
63
+ // process alive until every in-flight forward has settled (even if stdin
64
+ // closes — otherwise a piped/short-lived input would exit before the reply).
65
+ let pending = Promise.resolve();
66
+
67
+ const rl = createInterface({ input: process.stdin, crlfDelay: Infinity });
68
+ rl.on("line", (line) => {
69
+ const trimmed = line.trim();
70
+ if (!trimmed) return;
71
+ let message;
72
+ try {
73
+ message = JSON.parse(trimmed);
74
+ } catch {
75
+ return; // malformed frame — ignore
76
+ }
77
+ pending = pending.then(async () => {
78
+ const result = await forward(message);
79
+ if (result !== null && result !== undefined) {
80
+ process.stdout.write(JSON.stringify(result) + "\n");
81
+ }
82
+ });
83
+ });
84
+ rl.on("close", async () => {
85
+ await pending;
86
+ process.exit(0);
87
+ });
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "rentbamboo-mcp",
3
+ "version": "0.1.0",
4
+ "description": "Stdio MCP bridge to the RentBamboo MCP server. Exposes the RentBamboo Panda tools (read-only) to any MCP-capable AI agent.",
5
+ "type": "module",
6
+ "bin": {
7
+ "rentbamboo-mcp": "cli.js"
8
+ },
9
+ "main": "cli.js",
10
+ "files": ["cli.js", "README.md"],
11
+ "engines": {
12
+ "node": ">=18"
13
+ },
14
+ "keywords": ["mcp", "rentbamboo", "crm", "pm", "ai", "agent", "panda"],
15
+ "license": "MIT",
16
+ "publishConfig": {
17
+ "access": "public"
18
+ }
19
+ }