moeba-claude-channel 0.0.5 → 0.0.7
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 +98 -0
- package/dist/moeba-channel.js +40 -4
- package/package.json +3 -2
package/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# moeba-claude-channel
|
|
2
|
+
|
|
3
|
+
Claude Code channel for [Moeba](https://moeba.co.za) — chat with Claude Code from the Moeba mobile app.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
Bridges your Claude Code session to the Moeba app. Send messages from your phone, Claude Code processes them and replies back.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Moeba App → Moeba Server → SSE → Local MCP Channel → Claude Code
|
|
11
|
+
← HTTP reply ← moeba_reply tool ←
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g moeba-claude-channel
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Setup
|
|
21
|
+
|
|
22
|
+
Add to `~/.claude.json`:
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"mcpServers": {
|
|
27
|
+
"moeba": {
|
|
28
|
+
"command": "moeba-claude-channel",
|
|
29
|
+
"args": ["--login"],
|
|
30
|
+
"autoApprove": ["moeba_reply", "moeba_progress"]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### First run
|
|
37
|
+
|
|
38
|
+
1. Start Claude Code — the channel starts automatically
|
|
39
|
+
2. Browser opens for Google/Apple sign-in (same account as your Moeba app)
|
|
40
|
+
3. Credentials cached at `~/.moeba/channel-<project>.json`
|
|
41
|
+
4. A **"Claude Code — \<project\>"** agent appears in your Moeba app
|
|
42
|
+
|
|
43
|
+
### Headless mode (SSH, CI, or setting up for another user)
|
|
44
|
+
|
|
45
|
+
No browser needed — pass an API key and email via env vars:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"mcpServers": {
|
|
50
|
+
"moeba": {
|
|
51
|
+
"command": "moeba-claude-channel",
|
|
52
|
+
"args": ["--login"],
|
|
53
|
+
"env": {
|
|
54
|
+
"MOEBA_API_KEY": "mba_your_key_here",
|
|
55
|
+
"MOEBA_EMAIL": "user@example.com"
|
|
56
|
+
},
|
|
57
|
+
"autoApprove": ["moeba_reply", "moeba_progress"]
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Multi-project support
|
|
64
|
+
|
|
65
|
+
Each project directory gets its own agent in the Moeba app:
|
|
66
|
+
|
|
67
|
+
- `Claude Code — kepler`
|
|
68
|
+
- `Claude Code — moeba`
|
|
69
|
+
- `Claude Code — roxy`
|
|
70
|
+
|
|
71
|
+
The project name is detected from the git repo. Override with `MOEBA_PROJECT` env var.
|
|
72
|
+
|
|
73
|
+
## Tools
|
|
74
|
+
|
|
75
|
+
| Tool | Description |
|
|
76
|
+
|------|-------------|
|
|
77
|
+
| `moeba_reply` | Send a reply back to the Moeba user |
|
|
78
|
+
| `moeba_progress` | Show a typing indicator while working |
|
|
79
|
+
|
|
80
|
+
## Channel notifications
|
|
81
|
+
|
|
82
|
+
To enable Claude Code to auto-respond to incoming messages:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
claude --dangerously-load-development-channels server:moeba
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Requirements
|
|
89
|
+
|
|
90
|
+
- [Claude Code](https://claude.ai/code) v2.1.80+
|
|
91
|
+
- [Moeba](https://moeba.co.za) account (free)
|
|
92
|
+
- Node.js 20+
|
|
93
|
+
|
|
94
|
+
## Links
|
|
95
|
+
|
|
96
|
+
- [Moeba App (iOS)](https://apps.apple.com/za/app/moeba/id6758993423)
|
|
97
|
+
- [Moeba App (Android)](https://play.google.com/store/apps/details?id=za.co.moeba.app)
|
|
98
|
+
- [Moeba Web](https://web.moeba.co.za)
|
package/dist/moeba-channel.js
CHANGED
|
@@ -237,11 +237,47 @@ function connectSSE(c, mcp) {
|
|
|
237
237
|
// Main — authenticate first, then connect MCP
|
|
238
238
|
// ---------------------------------------------------------------------------
|
|
239
239
|
async function main() {
|
|
240
|
-
// 1.
|
|
241
|
-
//
|
|
240
|
+
// 1. Authenticate — three modes:
|
|
241
|
+
// a. Cached credentials (fastest, no network)
|
|
242
|
+
// b. API key + email env vars (headless — SSH, CI, inviting others)
|
|
243
|
+
// c. Browser OAuth (--login flag)
|
|
242
244
|
const loginMode = process.argv.includes('--login');
|
|
245
|
+
const envApiKey = process.env.MOEBA_API_KEY;
|
|
246
|
+
const envEmail = process.env.MOEBA_EMAIL;
|
|
243
247
|
let creds = loadCredentials();
|
|
244
|
-
if (!creds &&
|
|
248
|
+
if (!creds && envApiKey && envEmail) {
|
|
249
|
+
// Mode B: headless auth via API key + email
|
|
250
|
+
console.error(`Authenticating as ${envEmail} via API key...`);
|
|
251
|
+
try {
|
|
252
|
+
const response = await fetch(`${MOEBA_API_URL}/channel/auth`, {
|
|
253
|
+
method: 'POST',
|
|
254
|
+
headers: { 'Content-Type': 'application/json' },
|
|
255
|
+
body: JSON.stringify({ apiKey: envApiKey, email: envEmail, projectName: PROJECT_NAME }),
|
|
256
|
+
});
|
|
257
|
+
if (!response.ok) {
|
|
258
|
+
const err = await response.text();
|
|
259
|
+
console.error(`API key auth failed: ${err}`);
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
const data = (await response.json());
|
|
263
|
+
creds = {
|
|
264
|
+
token: data.token,
|
|
265
|
+
email: data.email,
|
|
266
|
+
businessId: data.businessId,
|
|
267
|
+
agentId: data.agentId,
|
|
268
|
+
connectionId: data.connectionId,
|
|
269
|
+
agentApiKey: data.agentApiKey,
|
|
270
|
+
projectName: PROJECT_NAME,
|
|
271
|
+
};
|
|
272
|
+
saveCredentials(creds);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
catch (err) {
|
|
276
|
+
console.error(`API key auth error: ${err.message}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
else if (!creds && loginMode) {
|
|
280
|
+
// Mode C: browser OAuth
|
|
245
281
|
console.error('No Moeba credentials found — opening browser to sign in...');
|
|
246
282
|
creds = await authenticate();
|
|
247
283
|
}
|
|
@@ -249,7 +285,7 @@ async function main() {
|
|
|
249
285
|
console.error(`Authenticated as ${creds.email} (project: ${PROJECT_NAME})`);
|
|
250
286
|
}
|
|
251
287
|
else {
|
|
252
|
-
console.error(`Moeba channel: no credentials for project "${PROJECT_NAME}" — run with --login
|
|
288
|
+
console.error(`Moeba channel: no credentials for project "${PROJECT_NAME}" — run with --login or set MOEBA_API_KEY + MOEBA_EMAIL`);
|
|
253
289
|
}
|
|
254
290
|
// 2. Create MCP channel server
|
|
255
291
|
const mcp = new Server({ name: 'moeba', version: '0.0.1' }, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "moeba-claude-channel",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "Claude Code channel for Moeba — chat with Claude Code from the Moeba app",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/moeba-channel.js",
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
"moeba-claude-channel": "dist/moeba-channel.js"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
|
-
"dist"
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
12
13
|
],
|
|
13
14
|
"scripts": {
|
|
14
15
|
"build": "tsc",
|