regen-koi-mcp 1.2.1 → 1.3.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 CHANGED
@@ -4,28 +4,69 @@ Access Regen Network's Knowledge Organization Infrastructure (KOI) through Model
4
4
 
5
5
  ## 🚀 Quick Start
6
6
 
7
- ### One-Line Install (Easiest!)
7
+ **Choose your installation method:**
8
+ - **Native CLI commands** (Recommended) - Most transparent and secure
9
+ - **Automated install script** - Convenient for multiple clients at once
10
+ - **Manual configuration** - Full control over your setup
11
+
12
+ ### Recommended: Native CLI Commands
13
+
14
+ The simplest and most secure way to install for supported clients:
15
+
16
+ **Claude Code CLI:**
17
+ ```bash
18
+ claude mcp add regen-koi npx regen-koi-mcp@latest
19
+ ```
20
+
21
+ **Codex:**
22
+ ```bash
23
+ codex mcp add regen-koi npx "-y regen-koi-mcp@latest"
24
+ ```
25
+
26
+ **Warp:**
27
+ ```bash
28
+ /add-mcp regen-koi npx -y regen-koi-mcp@latest
29
+ ```
30
+
31
+ **Amp:**
32
+ ```bash
33
+ amp mcp add regen-koi -- npx -y regen-koi-mcp@latest
34
+ ```
35
+
36
+ **Factory:**
37
+ ```bash
38
+ droid mcp add regen-koi "npx -y regen-koi-mcp@latest"
39
+ ```
40
+
41
+ Then configure the environment variable (see [client-specific sections](#-supported-clients) below for details).
42
+
43
+ ### Alternative: Automated Install Script
44
+
45
+ **⚠️ Security Note:** This script requires bash access and modifies config files. Review the [install script](https://raw.githubusercontent.com/gaiaaiagent/regen-koi-mcp/main/install.sh) before running.
8
46
 
9
47
  ```bash
10
48
  curl -fsSL https://raw.githubusercontent.com/gaiaaiagent/regen-koi-mcp/main/install.sh | bash
11
49
  ```
12
50
 
13
- This automatically configures Claude Desktop and Claude Code CLI. Just restart and you're done! 🎉
51
+ **What this does:**
52
+ - Automatically configures Claude Desktop and Claude Code CLI
53
+ - Sets up environment variables
54
+ - Works for multiple clients at once
14
55
 
15
- **Quick Test:** After restarting, open Claude and ask: _"What repositories are indexed in KOI?"_ to verify the tools are working.
56
+ **Quick Test:** After installation, restart your client and ask: _"What repositories are indexed in KOI?"_ to verify the tools are working.
16
57
 
17
58
  ---
18
59
 
19
- ### Option 1: NPM (Recommended - Auto-Updates)
60
+ ### Manual Configuration (All Clients)
20
61
 
21
- **No installation needed!** Just configure Claude Desktop with:
62
+ **For clients without a CLI command**, manually add this configuration:
22
63
 
23
64
  ```json
24
65
  {
25
66
  "mcpServers": {
26
67
  "regen-koi": {
27
68
  "command": "npx",
28
- "args": ["-y", "regen-koi-mcp@latest"],
69
+ "args": ["regen-koi-mcp@latest"],
29
70
  "env": {
30
71
  "KOI_API_ENDPOINT": "https://regen.gaiaai.xyz/api/koi"
31
72
  }
@@ -55,7 +96,9 @@ Then restart Claude Desktop and you're done! 🎉
55
96
 
56
97
  ### 🔄 Migrating from Git Installation
57
98
 
58
- If you previously installed via `git clone`, switch to npx for automatic updates:
99
+ If you previously installed via `git clone`, switch to npx for automatic updates.
100
+
101
+ ⚠️ **Security Note:** Review the [migrate script](https://raw.githubusercontent.com/gaiaaiagent/regen-koi-mcp/main/migrate.sh) before running.
59
102
 
60
103
  ```bash
61
104
  curl -fsSL https://raw.githubusercontent.com/gaiaaiagent/regen-koi-mcp/main/migrate.sh | bash
@@ -123,20 +166,31 @@ Regen Network team members with `@regen.network` emails can optionally authentic
123
166
  ```
124
167
  User: "Please use the regen_koi_authenticate tool"
125
168
 
126
- MCP: Opening browser for authentication...
127
- [Browser opens to Google OAuth]
169
+ MCP: ## Authentication Required
170
+
171
+ 🌐 Your browser should open automatically. If not, click:
172
+ [Open Activation Page](https://regen.gaiaai.xyz/activate)
173
+
174
+ Enter this code: NWDV-FCFC
128
175
 
129
- User: [Log in with yourname@regen.network]
130
- [Grant permissions: email, profile]
176
+ Sign in with your @regen.network email.
177
+
178
+ After completing, run this tool again to retrieve your session token.
179
+
180
+ User: [Completes authentication in browser]
181
+ "Please use the regen_koi_authenticate tool again"
182
+
183
+ MCP: ✅ Authentication Successful!
184
+ You now have access to internal Regen Network documentation.
131
185
 
132
- MCP: ✅ Authentication successful!
133
186
  Authenticated as: yourname@regen.network
134
187
  ```
135
188
 
136
189
  **After authentication:**
137
190
  - Queries automatically include internal documentation
138
- - Token is saved on the server (not your machine)
139
- - No need to re-authenticate unless token expires (~7 days)
191
+ - Token is saved locally in `~/.koi-auth.json` and cached in memory
192
+ - Session expires after ~1 hour
193
+ - Browser auto-opens to activation page for convenience
140
194
 
141
195
  ### What Permissions Are Requested
142
196
 
@@ -174,10 +228,20 @@ MCP: Found 23 results from multiple sources:
174
228
  ### Token Security
175
229
 
176
230
  Your authentication tokens are:
177
- - 🔒 Stored server-side only (never on your machine)
178
- - 🔒 Encrypted in PostgreSQL database
179
- - 🔒 User-specific (never shared between users)
180
- - 🔒 Automatically refreshed when needed
231
+ - 🔒 **Local Storage**: Saved in `~/.koi-auth.json` with `0o600` permissions (owner read/write only)
232
+ - 🔒 **Database**: SHA-256 hashed when stored in PostgreSQL (no plain tokens stored)
233
+ - 🔒 **User-Specific**: Never shared between users; each session is isolated
234
+ - 🔒 **Short-Lived**: Sessions expire after 1 hour; tokens are revocable
235
+ - 🔒 **Domain Enforcement**: Only `@regen.network` emails are permitted (verified in JWT claims)
236
+ - 🔒 **Phishing Prevention**: RFC 8628 Device Authorization Grant with user-typed codes
237
+ - 🔒 **Rate Limited**: 5 attempts/min on activation, 60 req/min on token endpoint
238
+ - 🔒 **No Secrets in URLs**: All authentication flows use POST requests to prevent logging
239
+ - 🔒 **Hardcoded URLs**: Activation page URL is hardcoded in the client (not from server)
240
+ - 🔒 **JWT Validation**: Google ID tokens validated locally with signature verification
241
+
242
+ **Production-Ready:** This authentication system follows RFC 8628 and industry best practices.
243
+
244
+ See [docs/AUTHENTICATION.md](docs/AUTHENTICATION.md) for complete security documentation and threat model.
181
245
 
182
246
  ### Troubleshooting
183
247
 
@@ -268,8 +332,7 @@ Once you've installed the MCP server, try these queries in Claude to explore wha
268
332
  ### Knowledge Base Search
269
333
  | Tool | Description | Key Inputs |
270
334
  |------|-------------|-----------|
271
- | `search_knowledge` | Hybrid search (vectors + graph with RRF) | `query` (string), `limit` (1–20, default 5), `published_from` (YYYY‑MM‑DD), `published_to` (YYYY‑MM‑DD), `include_undated` (bool, default false) |
272
- | `hybrid_search` | Intelligent search routing (auto-detects entity vs conceptual queries) | `query` (string), `limit` (1–50, default 10) |
335
+ | `search` | Hybrid search (vectors + graph with RRF) | `query` (string), `limit` (1–50, default 10), `published_from` (YYYY‑MM‑DD), `published_to` (YYYY‑MM‑DD), `include_undated` (bool, default false) |
273
336
  | `get_stats` | Knowledge base statistics | `detailed` (boolean) |
274
337
  | `generate_weekly_digest` | Generate weekly digest SUMMARY of Regen Network activity | `start_date` (YYYY-MM-DD, default: 7 days ago), `end_date` (YYYY-MM-DD, default: today), `save_to_file` (bool, default false), `output_path` (string), `format` ('markdown' or 'json', default: 'markdown') |
275
338
  | `get_notebooklm_export` | Get FULL NotebookLM export with complete forum posts, Notion pages, and source material | `save_to_file` (bool, default false), `output_path` (string) |
@@ -322,8 +385,8 @@ This table helps you understand which tool to use for different tasks. Just ask
322
385
  | Get repository overview | "Give me an overview of regen-web" | `get_repo_overview` |
323
386
  | Understand tech stack | "What's the tech stack for regen-ledger?" | `get_tech_stack` |
324
387
  | **Search everything (hybrid)** | | |
325
- | Semantic search across code and docs | "How does credit retirement work?" | `hybrid_search` |
326
- | Advanced filtering by date | "Find discussions about tokens from last week" | `search_knowledge` |
388
+ | Semantic search across code and docs | "How does credit retirement work?" | `search` |
389
+ | Advanced filtering by date | "Find discussions about tokens from last week" | `search` |
327
390
  | **Get activity summaries** | | |
328
391
  | Generate weekly digest summary | "Create a weekly digest of Regen activity" | `generate_weekly_digest` |
329
392
  | Get full content for NotebookLM | "Get the full NotebookLM export with all forum posts" | `get_notebooklm_export` |
@@ -399,18 +462,19 @@ regen-koi-mcp/
399
462
 
400
463
  ### Claude Desktop
401
464
 
402
- **One-line install:**
403
- ```bash
404
- curl -fsSL https://raw.githubusercontent.com/gaiaaiagent/regen-koi-mcp/main/install.sh | bash
405
- ```
465
+ **Recommended: Manual configuration**
466
+
467
+ Add to your config file:
468
+ - **Mac:** `~/Library/Application Support/Claude/claude_desktop_config.json`
469
+ - **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
470
+ - **Linux:** `~/.config/Claude/claude_desktop_config.json`
406
471
 
407
- Or manually add to config (`~/Library/Application Support/Claude/claude_desktop_config.json` on Mac, `~/.config/Claude/claude_desktop_config.json` on Linux):
408
472
  ```json
409
473
  {
410
474
  "mcpServers": {
411
475
  "regen-koi": {
412
476
  "command": "npx",
413
- "args": ["-y", "regen-koi-mcp@latest"],
477
+ "args": ["regen-koi-mcp@latest"],
414
478
  "env": {
415
479
  "KOI_API_ENDPOINT": "https://regen.gaiaai.xyz/api/koi"
416
480
  }
@@ -419,29 +483,34 @@ Or manually add to config (`~/Library/Application Support/Claude/claude_desktop_
419
483
  }
420
484
  ```
421
485
 
422
- ---
486
+ **Alternative: Automated installer**
423
487
 
424
- ### Claude Code CLI
488
+ ⚠️ **Security Note:** Review the [install script](https://raw.githubusercontent.com/gaiaaiagent/regen-koi-mcp/main/install.sh) before running.
425
489
 
426
- **Option 1: Use the automated installer (recommended)**
427
490
  ```bash
428
491
  curl -fsSL https://raw.githubusercontent.com/gaiaaiagent/regen-koi-mcp/main/install.sh | bash
429
492
  ```
430
- This configures both Claude Desktop and Claude Code CLI with the correct environment variables.
431
493
 
432
- **Option 2: Manual installation**
433
- 1. Add the MCP server:
494
+ ---
495
+
496
+ ### Claude Code CLI
497
+
498
+ **Recommended: One-line command**
434
499
  ```bash
435
- claude mcp add regen-koi npx -y regen-koi-mcp@latest
500
+ claude mcp add regen-koi npx regen-koi-mcp@latest
436
501
  ```
437
502
 
438
- 2. Configure the environment variable in your Claude Code settings file (`~/.claude/settings.json` or similar):
503
+ Then manually add the environment variable to your Claude Code settings file:
504
+
505
+ **Mac/Linux:** `~/.config/claude/claude_code_config.json`
506
+ **Windows:** `%APPDATA%\claude\claude_code_config.json`
507
+
439
508
  ```json
440
509
  {
441
510
  "mcpServers": {
442
511
  "regen-koi": {
443
512
  "command": "npx",
444
- "args": ["-y", "regen-koi-mcp@latest"],
513
+ "args": ["regen-koi-mcp@latest"],
445
514
  "env": {
446
515
  "KOI_API_ENDPOINT": "https://regen.gaiaai.xyz/api/koi"
447
516
  }
@@ -450,22 +519,38 @@ claude mcp add regen-koi npx -y regen-koi-mcp@latest
450
519
  }
451
520
  ```
452
521
 
522
+ **Alternative: Use the automated installer**
523
+
524
+ ⚠️ **Security Note:** Review the [install script](https://raw.githubusercontent.com/gaiaaiagent/regen-koi-mcp/main/install.sh) before running.
525
+
526
+ ```bash
527
+ curl -fsSL https://raw.githubusercontent.com/gaiaaiagent/regen-koi-mcp/main/install.sh | bash
528
+ ```
529
+
530
+ This configures both Claude Desktop and Claude Code CLI with the correct environment variables.
531
+
453
532
  **Verification:** After installation, restart Claude Code and ask: "What repositories are indexed?" to verify the tools are working.
454
533
 
455
534
  ---
456
535
 
457
536
  ### VS Code / VS Code Insiders
458
537
 
459
- **One-line install:**
538
+ **Recommended: CLI command**
539
+
540
+ For VS Code:
460
541
  ```bash
461
- code --add-mcp '{"name":"regen-koi","command":"npx","args":["-y","regen-koi-mcp@latest"],"env":{"KOI_API_ENDPOINT":"https://regen.gaiaai.xyz/api/koi"}}'
542
+ code --add-mcp '{"name":"regen-koi","command":"npx","args":["regen-koi-mcp@latest"],"env":{"KOI_API_ENDPOINT":"https://regen.gaiaai.xyz/api/koi"}}'
462
543
  ```
463
544
 
464
- Or for VS Code Insiders:
545
+ For VS Code Insiders:
465
546
  ```bash
466
- code-insiders --add-mcp '{"name":"regen-koi","command":"npx","args":["-y","regen-koi-mcp@latest"],"env":{"KOI_API_ENDPOINT":"https://regen.gaiaai.xyz/api/koi"}}'
547
+ code-insiders --add-mcp '{"name":"regen-koi","command":"npx","args":["regen-koi-mcp@latest"],"env":{"KOI_API_ENDPOINT":"https://regen.gaiaai.xyz/api/koi"}}'
467
548
  ```
468
549
 
550
+ **Alternative: Manual configuration**
551
+
552
+ Add to your VS Code MCP settings with the command, args, and env values shown above.
553
+
469
554
  ---
470
555
 
471
556
  ### Cursor
@@ -477,7 +562,7 @@ code-insiders --add-mcp '{"name":"regen-koi","command":"npx","args":["-y","regen
477
562
  4. Enter:
478
563
  - Name: `regen-koi`
479
564
  - Command: `npx`
480
- - Args: `-y regen-koi-mcp@latest`
565
+ - Args: `regen-koi-mcp@latest`
481
566
  - Env: `KOI_API_ENDPOINT=https://regen.gaiaai.xyz/api/koi`
482
567
 
483
568
  ---
@@ -490,7 +575,7 @@ Add to your Windsurf MCP config:
490
575
  "mcpServers": {
491
576
  "regen-koi": {
492
577
  "command": "npx",
493
- "args": ["-y", "regen-koi-mcp@latest"],
578
+ "args": ["regen-koi-mcp@latest"],
494
579
  "env": {
495
580
  "KOI_API_ENDPOINT": "https://regen.gaiaai.xyz/api/koi"
496
581
  }
@@ -509,7 +594,7 @@ Install [Cline from VS Code Marketplace](https://marketplace.visualstudio.com/it
509
594
  "mcpServers": {
510
595
  "regen-koi": {
511
596
  "command": "npx",
512
- "args": ["-y", "regen-koi-mcp@latest"],
597
+ "args": ["regen-koi-mcp@latest"],
513
598
  "env": {
514
599
  "KOI_API_ENDPOINT": "https://regen.gaiaai.xyz/api/koi"
515
600
  }
@@ -528,7 +613,7 @@ Install [Continue from VS Code Marketplace](https://marketplace.visualstudio.com
528
613
  "mcpServers": {
529
614
  "regen-koi": {
530
615
  "command": "npx",
531
- "args": ["-y", "regen-koi-mcp@latest"],
616
+ "args": ["regen-koi-mcp@latest"],
532
617
  "env": {
533
618
  "KOI_API_ENDPOINT": "https://regen.gaiaai.xyz/api/koi"
534
619
  }
@@ -546,61 +631,77 @@ Install [Continue from VS Code Marketplace](https://marketplace.visualstudio.com
546
631
  2. Go to Extensions
547
632
  3. Add MCP server with:
548
633
  - Command: `npx`
549
- - Args: `-y regen-koi-mcp@latest`
634
+ - Args: `regen-koi-mcp@latest`
550
635
  - Env: `KOI_API_ENDPOINT=https://regen.gaiaai.xyz/api/koi`
551
636
 
552
637
  ---
553
638
 
554
639
  ### Warp
555
640
 
556
- **Via Settings:**
557
- 1. Open Settings → AI → Manage MCP Servers
558
- 2. Add new server
559
-
560
- Or use slash command:
641
+ **Recommended: Slash command**
561
642
  ```bash
562
643
  /add-mcp regen-koi npx -y regen-koi-mcp@latest
563
644
  ```
564
645
 
646
+ Then add the environment variable `KOI_API_ENDPOINT=https://regen.gaiaai.xyz/api/koi` in the server settings.
647
+
648
+ **Alternative: Manual configuration via Settings**
649
+ 1. Open Settings → AI → Manage MCP Servers
650
+ 2. Add new server
651
+ 3. Configure:
652
+ - Command: `npx`
653
+ - Args: `regen-koi-mcp@latest`
654
+ - Env: `KOI_API_ENDPOINT=https://regen.gaiaai.xyz/api/koi`
655
+
565
656
  ---
566
657
 
567
658
  ### Amp
568
659
 
569
- **One-line install:**
660
+ **Recommended: One-line command**
570
661
  ```bash
571
662
  amp mcp add regen-koi -- npx -y regen-koi-mcp@latest
572
663
  ```
573
664
 
665
+ Then manually add the environment variable `KOI_API_ENDPOINT=https://regen.gaiaai.xyz/api/koi` to the server configuration.
666
+
574
667
  ---
575
668
 
576
669
  ### Factory
577
670
 
578
- **One-line install:**
671
+ **Recommended: One-line command**
579
672
  ```bash
580
673
  droid mcp add regen-koi "npx -y regen-koi-mcp@latest"
581
674
  ```
582
675
 
583
- Or use interactive UI with `/mcp` command.
676
+ Then manually add the environment variable `KOI_API_ENDPOINT=https://regen.gaiaai.xyz/api/koi` to the server configuration.
677
+
678
+ **Alternative: Interactive UI**
679
+
680
+ Use the `/mcp` command in Factory to add the server interactively.
584
681
 
585
682
  ---
586
683
 
587
684
  ### Codex
588
685
 
589
- **One-line install:**
686
+ **Recommended: One-line command**
590
687
  ```bash
591
688
  codex mcp add regen-koi npx "-y regen-koi-mcp@latest"
592
689
  ```
593
690
 
594
- Or manually edit `~/.codex/config.toml`:
691
+ Then manually add the environment variable to `~/.codex/config.toml`:
595
692
  ```toml
596
693
  [[mcp.servers]]
597
694
  name = "regen-koi"
598
695
  command = "npx"
599
- args = ["-y", "regen-koi-mcp@latest"]
696
+ args = ["regen-koi-mcp@latest"]
600
697
  [mcp.servers.env]
601
698
  KOI_API_ENDPOINT = "https://regen.gaiaai.xyz/api/koi"
602
699
  ```
603
700
 
701
+ **Alternative: Manual configuration**
702
+
703
+ Edit `~/.codex/config.toml` directly with the complete config above.
704
+
604
705
  ---
605
706
 
606
707
  ### Opencode
@@ -611,7 +712,7 @@ Add to `~/.config/opencode/opencode.json`:
611
712
  "mcpServers": {
612
713
  "regen-koi": {
613
714
  "command": "npx",
614
- "args": ["-y", "regen-koi-mcp@latest"],
715
+ "args": ["regen-koi-mcp@latest"],
615
716
  "env": {
616
717
  "KOI_API_ENDPOINT": "https://regen.gaiaai.xyz/api/koi"
617
718
  }
@@ -630,7 +731,7 @@ Add to `.kiro/settings/mcp.json`:
630
731
  "mcpServers": {
631
732
  "regen-koi": {
632
733
  "command": "npx",
633
- "args": ["-y", "regen-koi-mcp@latest"],
734
+ "args": ["regen-koi-mcp@latest"],
634
735
  "env": {
635
736
  "KOI_API_ENDPOINT": "https://regen.gaiaai.xyz/api/koi"
636
737
  }
@@ -646,7 +747,7 @@ Add to `.kiro/settings/mcp.json`:
646
747
  **Via Settings:**
647
748
  1. Open Program sidebar
648
749
  2. Go to MCP configuration
649
- 3. Add server with npx command: `npx -y regen-koi-mcp@latest`
750
+ 3. Add server with npx command: `npx regen-koi-mcp@latest`
650
751
 
651
752
  ---
652
753
 
@@ -657,7 +758,7 @@ Add to `.kiro/settings/mcp.json`:
657
758
  2. Click "Connect more tools"
658
759
  3. Add MCP server:
659
760
  - Command: `npx`
660
- - Args: `-y regen-koi-mcp@latest`
761
+ - Args: `regen-koi-mcp@latest`
661
762
  - Env: `KOI_API_ENDPOINT=https://regen.gaiaai.xyz/api/koi`
662
763
 
663
764
  ---
@@ -670,7 +771,7 @@ Add to Gemini CLI MCP config:
670
771
  "mcpServers": {
671
772
  "regen-koi": {
672
773
  "command": "npx",
673
- "args": ["-y", "regen-koi-mcp@latest"],
774
+ "args": ["regen-koi-mcp@latest"],
674
775
  "env": {
675
776
  "KOI_API_ENDPOINT": "https://regen.gaiaai.xyz/api/koi"
676
777
  }
@@ -688,7 +789,7 @@ Any MCP-compatible client can use this server with:
688
789
  ```json
689
790
  {
690
791
  "command": "npx",
691
- "args": ["-y", "regen-koi-mcp@latest"],
792
+ "args": ["regen-koi-mcp@latest"],
692
793
  "env": {
693
794
  "KOI_API_ENDPOINT": "https://regen.gaiaai.xyz/api/koi"
694
795
  }
@@ -767,7 +868,7 @@ curl -s http://localhost:8301/api/koi/query \
767
868
  }' | jq '.results[0:3]'
768
869
  ```
769
870
 
770
- Within MCP, the `search_knowledge` tool accepts:
871
+ Within MCP, the `search` tool accepts:
771
872
 
772
873
  - `published_from` / `published_to` (YYYY-MM-DD)
773
874
  - `include_undated` (boolean)
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Auth State Persistence
3
+ *
4
+ * Stores authentication state to .koi-auth.json to enable
5
+ * the "One Tool, Two Calls" pattern (no polling loop).
6
+ *
7
+ * State Flow:
8
+ * 1. No state -> Request device code, save to file
9
+ * 2. Has device_code -> Check status with server
10
+ * 3. Has access_token -> Already authenticated
11
+ */
12
+ export interface AuthState {
13
+ deviceCode?: string;
14
+ userCode?: string;
15
+ verificationUri?: string;
16
+ deviceCodeExpiresAt?: number;
17
+ accessToken?: string;
18
+ accessTokenExpiresAt?: number;
19
+ userEmail?: string;
20
+ }
21
+ /**
22
+ * Load auth state from disk.
23
+ * Returns empty object if file doesn't exist or is invalid.
24
+ */
25
+ export declare function loadAuthState(): AuthState;
26
+ /**
27
+ * Save auth state to disk with secure file permissions.
28
+ * File is set to 0o600 (owner read/write only) for security on shared machines.
29
+ */
30
+ export declare function saveAuthState(state: AuthState): void;
31
+ /**
32
+ * Clear auth state (logout).
33
+ */
34
+ export declare function clearAuthState(): void;
35
+ /**
36
+ * Check if access token is still valid.
37
+ */
38
+ export declare function hasValidAccessToken(state: AuthState): boolean;
39
+ /**
40
+ * Check if device code is still valid.
41
+ */
42
+ export declare function hasValidDeviceCode(state: AuthState): boolean;
43
+ /**
44
+ * Clear device code from state (after successful auth or expiry).
45
+ */
46
+ export declare function clearDeviceCode(state: AuthState): AuthState;
47
+ //# sourceMappingURL=auth-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-store.d.ts","sourceRoot":"","sources":["../src/auth-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH,MAAM,WAAW,SAAS;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,SAAS,CAUzC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CASpD;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAQrC;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAK7D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAK5D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAG3D"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Auth State Persistence
3
+ *
4
+ * Stores authentication state to .koi-auth.json to enable
5
+ * the "One Tool, Two Calls" pattern (no polling loop).
6
+ *
7
+ * State Flow:
8
+ * 1. No state -> Request device code, save to file
9
+ * 2. Has device_code -> Check status with server
10
+ * 3. Has access_token -> Already authenticated
11
+ */
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+ import os from 'os';
15
+ // Store auth state in user's home directory
16
+ const AUTH_FILE = path.join(os.homedir(), '.koi-auth.json');
17
+ /**
18
+ * Load auth state from disk.
19
+ * Returns empty object if file doesn't exist or is invalid.
20
+ */
21
+ export function loadAuthState() {
22
+ try {
23
+ if (fs.existsSync(AUTH_FILE)) {
24
+ const data = fs.readFileSync(AUTH_FILE, 'utf8');
25
+ return JSON.parse(data);
26
+ }
27
+ }
28
+ catch (err) {
29
+ console.error('[Auth] Failed to load auth state:', err);
30
+ }
31
+ return {};
32
+ }
33
+ /**
34
+ * Save auth state to disk with secure file permissions.
35
+ * File is set to 0o600 (owner read/write only) for security on shared machines.
36
+ */
37
+ export function saveAuthState(state) {
38
+ try {
39
+ fs.writeFileSync(AUTH_FILE, JSON.stringify(state, null, 2), {
40
+ encoding: 'utf8',
41
+ mode: 0o600 // Owner read/write only
42
+ });
43
+ }
44
+ catch (err) {
45
+ console.error('[Auth] Failed to save auth state:', err);
46
+ }
47
+ }
48
+ /**
49
+ * Clear auth state (logout).
50
+ */
51
+ export function clearAuthState() {
52
+ try {
53
+ if (fs.existsSync(AUTH_FILE)) {
54
+ fs.unlinkSync(AUTH_FILE);
55
+ }
56
+ }
57
+ catch (err) {
58
+ console.error('[Auth] Failed to clear auth state:', err);
59
+ }
60
+ }
61
+ /**
62
+ * Check if access token is still valid.
63
+ */
64
+ export function hasValidAccessToken(state) {
65
+ if (!state.accessToken || !state.accessTokenExpiresAt) {
66
+ return false;
67
+ }
68
+ return Date.now() < state.accessTokenExpiresAt;
69
+ }
70
+ /**
71
+ * Check if device code is still valid.
72
+ */
73
+ export function hasValidDeviceCode(state) {
74
+ if (!state.deviceCode || !state.deviceCodeExpiresAt) {
75
+ return false;
76
+ }
77
+ return Date.now() < state.deviceCodeExpiresAt;
78
+ }
79
+ /**
80
+ * Clear device code from state (after successful auth or expiry).
81
+ */
82
+ export function clearDeviceCode(state) {
83
+ const { deviceCode, userCode, verificationUri, deviceCodeExpiresAt, ...rest } = state;
84
+ return rest;
85
+ }
86
+ //# sourceMappingURL=auth-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-store.js","sourceRoot":"","sources":["../src/auth-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,4CAA4C;AAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,gBAAgB,CAAC,CAAC;AAY5D;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAChD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAgB;IAC5C,IAAI,CAAC;QACH,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;YAC1D,QAAQ,EAAE,MAAM;YAChB,IAAI,EAAE,KAAK,CAAE,wBAAwB;SACtC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,GAAG,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAgB;IAClD,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,CAAC;QACtD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,oBAAoB,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAgB;IACjD,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,mBAAmB,EAAE,CAAC;QACpD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,mBAAmB,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,KAAgB;IAC9C,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,eAAe,EAAE,mBAAmB,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACtF,OAAO,IAAI,CAAC;AACd,CAAC"}
package/dist/auth.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Authentication Module
3
+ * Manages session tokens for authenticated API calls
4
+ *
5
+ * SECURITY: This module stores session tokens (NOT Google OAuth tokens).
6
+ * Session tokens are generated by our server and only work with our API.
7
+ * They are safe to store locally - even if leaked, they can't be used
8
+ * to access Google APIs or impersonate the user elsewhere.
9
+ */
10
+ export declare const USER_EMAIL: string;
11
+ /**
12
+ * Get the current session token (if any)
13
+ * Returns null if no token is stored or if expired
14
+ */
15
+ export declare function getSessionToken(): string | null;
16
+ export declare const getAccessToken: typeof getSessionToken;
17
+ /**
18
+ * Store session token after successful OAuth
19
+ * @param token - The session token from our server (NOT Google OAuth token)
20
+ * @param expiresAt - Expiry timestamp
21
+ */
22
+ export declare function setSessionToken(token: string, expiresAt?: number): void;
23
+ export declare const setAccessToken: typeof setSessionToken;
24
+ /**
25
+ * Clear session token (called when token is invalid or on logout)
26
+ */
27
+ export declare function clearAuthCache(): void;
28
+ /**
29
+ * Check if we have a valid session token
30
+ */
31
+ export declare function hasSessionToken(): boolean;
32
+ export declare const hasAccessToken: typeof hasSessionToken;
33
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAuBH,eAAO,MAAM,UAAU,QAAuB,CAAC;AAc/C;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAS/C;AAGD,eAAO,MAAM,cAAc,wBAAkB,CAAC;AAE9C;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAQvE;AAGD,eAAO,MAAM,cAAc,wBAAkB,CAAC;AAE9C;;GAEG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAKrC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAGD,eAAO,MAAM,cAAc,wBAAkB,CAAC"}