@unifiedmemory/cli 1.1.0 → 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/.env.example +27 -12
- package/CHANGELOG.md +53 -0
- package/README.md +17 -23
- package/commands/init.js +126 -4
- package/lib/config.js +18 -30
- package/lib/provider-detector.js +22 -4
- package/package.json +1 -1
package/.env.example
CHANGED
|
@@ -1,29 +1,44 @@
|
|
|
1
1
|
# UnifiedMemory CLI Configuration
|
|
2
|
-
#
|
|
2
|
+
#
|
|
3
|
+
# ============================================
|
|
4
|
+
# IMPORTANT: This file is OPTIONAL
|
|
5
|
+
# ============================================
|
|
6
|
+
# The CLI includes production defaults for all values below.
|
|
7
|
+
# This file is only needed if you want to override defaults
|
|
8
|
+
# (e.g., for development, testing, or custom deployments).
|
|
9
|
+
#
|
|
10
|
+
# For normal usage, you can delete this file - the CLI will work without it.
|
|
11
|
+
#
|
|
12
|
+
# To use custom values:
|
|
13
|
+
# 1. Copy this file to .env
|
|
14
|
+
# 2. Uncomment and modify the values you want to override
|
|
15
|
+
# 3. Leave other values commented to use the built-in defaults
|
|
3
16
|
|
|
4
17
|
# ============================================
|
|
5
|
-
#
|
|
18
|
+
# Clerk OAuth Configuration
|
|
6
19
|
# ============================================
|
|
7
|
-
#
|
|
8
|
-
|
|
9
|
-
|
|
20
|
+
# Production defaults are included in the CLI
|
|
21
|
+
# Only override these if using a custom Clerk instance
|
|
22
|
+
# CLERK_CLIENT_ID=custom_clerk_client_id
|
|
23
|
+
# CLERK_DOMAIN=custom-app.clerk.accounts.dev
|
|
10
24
|
|
|
11
25
|
# ============================================
|
|
12
|
-
#
|
|
26
|
+
# API Configuration
|
|
13
27
|
# ============================================
|
|
14
|
-
#
|
|
15
|
-
|
|
28
|
+
# Production default is included in the CLI
|
|
29
|
+
# Only override this for local testing or custom deployments
|
|
30
|
+
# API_ENDPOINT=https://custom-api-gateway.zuplo.dev
|
|
16
31
|
|
|
17
32
|
# ============================================
|
|
18
|
-
#
|
|
33
|
+
# OAuth Flow Configuration
|
|
19
34
|
# ============================================
|
|
20
|
-
#
|
|
21
|
-
#
|
|
35
|
+
# Defaults to localhost:3333 for the OAuth callback server
|
|
36
|
+
# Customize only if you need a different port or URL
|
|
22
37
|
# REDIRECT_URI=http://localhost:3333/callback
|
|
23
38
|
# PORT=3333
|
|
24
39
|
|
|
25
40
|
# ============================================
|
|
26
|
-
#
|
|
41
|
+
# Clerk Client Secret (Optional)
|
|
27
42
|
# ============================================
|
|
28
43
|
# Not required for PKCE flow (recommended)
|
|
29
44
|
# Only set this if specifically instructed
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,59 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **lib/config.js** - Embedded production defaults for zero-configuration installation
|
|
13
|
+
- Added default values for `CLERK_CLIENT_ID`, `CLERK_DOMAIN`, and `API_ENDPOINT`
|
|
14
|
+
- Users no longer need to create `.env` files after `npm install`
|
|
15
|
+
- Environment variables can still override defaults for development/testing
|
|
16
|
+
- Simplified `validateConfig()` to remove "missing environment variables" errors
|
|
17
|
+
- CLI now works immediately after installation with no setup required
|
|
18
|
+
|
|
19
|
+
- **.env.example** - Updated documentation to clarify optional nature
|
|
20
|
+
- Added prominent note that the file is OPTIONAL
|
|
21
|
+
- Explained that production defaults are included in the CLI
|
|
22
|
+
- Commented out all example values to emphasize optional overrides
|
|
23
|
+
- Clarified when overrides might be needed (development, testing, custom deployments)
|
|
24
|
+
|
|
25
|
+
- **README.md** - Improved installation and configuration documentation
|
|
26
|
+
- Added "No configuration required!" note to installation section
|
|
27
|
+
- Renamed "Configuration" to "Advanced Configuration (Optional)"
|
|
28
|
+
- Removed "Missing environment variables" from troubleshooting
|
|
29
|
+
- Emphasized zero-friction installation experience
|
|
30
|
+
|
|
31
|
+
## [1.2.0] - 2026-01-08
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- **commands/init.js** - Smart default project name based on directory detection
|
|
36
|
+
- Project name prompt now defaults to the parent top-level directory name
|
|
37
|
+
- Automatically detects project root by walking up directories looking for markers:
|
|
38
|
+
- `.git` directory (Git repository)
|
|
39
|
+
- `package.json` (Node.js project)
|
|
40
|
+
- `pyproject.toml` (Python project)
|
|
41
|
+
- `Cargo.toml` (Rust project)
|
|
42
|
+
- `.um` directory (already initialized)
|
|
43
|
+
- Works correctly from nested subdirectories (e.g., `/project/src/components/`)
|
|
44
|
+
- Max depth limit of 5 levels prevents walking too far up (e.g., to home directory)
|
|
45
|
+
- Users can press Enter to accept default or type custom name
|
|
46
|
+
- Graceful fallback to current directory name if no markers found within 5 levels
|
|
47
|
+
- New helper functions: `findProjectRoot()` and `getDefaultProjectName()`
|
|
48
|
+
- No new dependencies - uses built-in Node.js `path` and `fs` modules
|
|
49
|
+
|
|
50
|
+
- **commands/init.js, lib/provider-detector.js** - Auto-authorize MCP tools in Claude Code during init
|
|
51
|
+
- Dynamically fetches available MCP tools from the gateway during `um init`
|
|
52
|
+
- Prompts user once to pre-authorize all UnifiedMemory tools (search_notes, create_note, create_topic, etc.)
|
|
53
|
+
- If user agrees, adds tool permissions to `.claude/settings.local.json` in format `mcp__unifiedmemory__<toolname>`
|
|
54
|
+
- Future-proof: Automatically includes new tools as they're added to the MCP server
|
|
55
|
+
- Single yes/no question with clear explanation of what's being authorized
|
|
56
|
+
- Graceful error handling: Skips permission setup if API unavailable, continues with init
|
|
57
|
+
- Idempotent: Won't duplicate existing permissions if run multiple times
|
|
58
|
+
- Preserves existing permissions (e.g., Bash commands) when adding new ones
|
|
59
|
+
- New helper function: `fetchMCPToolPermissions()` in commands/init.js
|
|
60
|
+
- Updated `ClaudeProvider.updateClaudeSettings()` to write permissions array
|
|
61
|
+
- Eliminates need for manual "Allow" clicks on every MCP tool use
|
|
62
|
+
|
|
10
63
|
### Fixed
|
|
11
64
|
|
|
12
65
|
- **commands/init.js** - Enhanced error handling for 401/403/network errors during project fetching
|
package/README.md
CHANGED
|
@@ -171,6 +171,8 @@ npm install -g @unifiedmemory/cli
|
|
|
171
171
|
um --version
|
|
172
172
|
```
|
|
173
173
|
|
|
174
|
+
**No configuration required!** The CLI includes production defaults and works immediately after installation.
|
|
175
|
+
|
|
174
176
|
**Option 2: Use with npx (no installation)**
|
|
175
177
|
```bash
|
|
176
178
|
npx @unifiedmemory/cli init
|
|
@@ -213,43 +215,35 @@ Tokens automatically refresh. If you see auth errors:
|
|
|
213
215
|
um login
|
|
214
216
|
```
|
|
215
217
|
|
|
216
|
-
|
|
217
|
-
If you see "Missing required environment variables" error:
|
|
218
|
-
1. Copy `.env.example` to `.env` in the CLI installation directory
|
|
219
|
-
2. Fill in your Clerk and API credentials
|
|
220
|
-
3. See Configuration section below for details
|
|
218
|
+
## Advanced Configuration (Optional)
|
|
221
219
|
|
|
222
|
-
|
|
220
|
+
**For most users, no configuration is needed!** The CLI includes production defaults and works out of the box.
|
|
223
221
|
|
|
224
|
-
|
|
222
|
+
For development, testing, or custom deployments, you can override defaults by creating a `.env` file:
|
|
225
223
|
|
|
226
|
-
**Step 1: Create `.env` file**
|
|
224
|
+
**Step 1: Create `.env` file** (optional)
|
|
227
225
|
```bash
|
|
228
226
|
# In the um-cli installation directory (find with: npm root -g)
|
|
229
227
|
cp .env.example .env
|
|
230
228
|
```
|
|
231
229
|
|
|
232
|
-
**Step 2:
|
|
230
|
+
**Step 2: Override the values you need** (optional)
|
|
233
231
|
```bash
|
|
234
|
-
#
|
|
235
|
-
CLERK_CLIENT_ID=
|
|
236
|
-
CLERK_DOMAIN=
|
|
237
|
-
|
|
238
|
-
# Required: API Configuration
|
|
239
|
-
API_ENDPOINT=https://your-api-gateway.zuplo.dev
|
|
240
|
-
```
|
|
232
|
+
# Optional: Override production defaults
|
|
233
|
+
CLERK_CLIENT_ID=custom_clerk_client_id
|
|
234
|
+
CLERK_DOMAIN=custom-app.clerk.accounts.dev
|
|
235
|
+
API_ENDPOINT=https://custom-api-gateway.zuplo.dev
|
|
241
236
|
|
|
242
|
-
|
|
243
|
-
- **Clerk credentials**: [Clerk Dashboard](https://dashboard.clerk.com)
|
|
244
|
-
- **API endpoint**: Your UnifiedMemory deployment
|
|
245
|
-
|
|
246
|
-
**Optional configuration**:
|
|
247
|
-
```bash
|
|
248
|
-
# Customize OAuth redirect (defaults shown)
|
|
237
|
+
# Optional: Customize OAuth redirect (defaults to localhost:3333)
|
|
249
238
|
REDIRECT_URI=http://localhost:3333/callback
|
|
250
239
|
PORT=3333
|
|
251
240
|
```
|
|
252
241
|
|
|
242
|
+
**When you might need this**:
|
|
243
|
+
- 🔧 **Development**: Testing with a local API backend
|
|
244
|
+
- 🧪 **Testing**: Using a staging or test Clerk instance
|
|
245
|
+
- 🏢 **Custom Deployment**: Running your own UnifiedMemory instance
|
|
246
|
+
|
|
253
247
|
See `.env.example` for the complete template with documentation.
|
|
254
248
|
|
|
255
249
|
## Privacy & Security
|
package/commands/init.js
CHANGED
|
@@ -8,6 +8,52 @@ import { loadAndRefreshToken } from '../lib/token-validation.js';
|
|
|
8
8
|
import { login } from './login.js';
|
|
9
9
|
import { ProviderDetector } from '../lib/provider-detector.js';
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Find project root directory by looking for common markers
|
|
13
|
+
* @param {string} startDir - Directory to start searching from
|
|
14
|
+
* @returns {string} Project root directory path
|
|
15
|
+
*/
|
|
16
|
+
function findProjectRoot(startDir = process.cwd()) {
|
|
17
|
+
let currentDir = startDir;
|
|
18
|
+
const root = path.parse(currentDir).root;
|
|
19
|
+
let levelsUp = 0;
|
|
20
|
+
const MAX_DEPTH = 5; // Only walk up 5 levels to avoid finding distant markers
|
|
21
|
+
|
|
22
|
+
while (currentDir !== root && levelsUp < MAX_DEPTH) {
|
|
23
|
+
// Check for common project markers
|
|
24
|
+
const markers = [
|
|
25
|
+
path.join(currentDir, '.git'),
|
|
26
|
+
path.join(currentDir, 'package.json'),
|
|
27
|
+
path.join(currentDir, 'pyproject.toml'),
|
|
28
|
+
path.join(currentDir, 'Cargo.toml'),
|
|
29
|
+
path.join(currentDir, '.um'),
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
// If any marker exists, this is the project root
|
|
33
|
+
for (const marker of markers) {
|
|
34
|
+
if (fs.existsSync(marker)) {
|
|
35
|
+
return currentDir;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Move up one directory
|
|
40
|
+
currentDir = path.dirname(currentDir);
|
|
41
|
+
levelsUp++;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Fallback: return the starting directory
|
|
45
|
+
return startDir;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get default project name based on directory
|
|
50
|
+
* @returns {string} Default project name
|
|
51
|
+
*/
|
|
52
|
+
function getDefaultProjectName() {
|
|
53
|
+
const projectRoot = findProjectRoot();
|
|
54
|
+
return path.basename(projectRoot);
|
|
55
|
+
}
|
|
56
|
+
|
|
11
57
|
export async function init(options = {}) {
|
|
12
58
|
console.log(chalk.cyan('\n🚀 UnifiedMemory Initialization\n'));
|
|
13
59
|
|
|
@@ -35,9 +81,15 @@ export async function init(options = {}) {
|
|
|
35
81
|
// Step 3: Save project config
|
|
36
82
|
await saveProjectConfig(authData, projectData);
|
|
37
83
|
|
|
84
|
+
// Step 3.5: Fetch available MCP tools for permissions
|
|
85
|
+
let mcpToolPermissions = null;
|
|
86
|
+
if (!options.skipConfigure) {
|
|
87
|
+
mcpToolPermissions = await fetchMCPToolPermissions(authData, projectData);
|
|
88
|
+
}
|
|
89
|
+
|
|
38
90
|
// Step 4: Configure AI tools
|
|
39
91
|
if (!options.skipConfigure) {
|
|
40
|
-
await configureProviders(authData, projectData);
|
|
92
|
+
await configureProviders(authData, projectData, mcpToolPermissions);
|
|
41
93
|
}
|
|
42
94
|
|
|
43
95
|
console.log(chalk.green('\n✅ Initialization complete!\n'));
|
|
@@ -228,11 +280,14 @@ async function selectOrCreateProject(authData, options) {
|
|
|
228
280
|
}]);
|
|
229
281
|
|
|
230
282
|
if (action === 'create') {
|
|
283
|
+
const defaultName = getDefaultProjectName();
|
|
284
|
+
|
|
231
285
|
const { name, description } = await inquirer.prompt([
|
|
232
286
|
{
|
|
233
287
|
type: 'input',
|
|
234
288
|
name: 'name',
|
|
235
289
|
message: 'Project name:',
|
|
290
|
+
default: defaultName,
|
|
236
291
|
validate: input => input.length > 0 || 'Name is required',
|
|
237
292
|
},
|
|
238
293
|
{
|
|
@@ -246,11 +301,14 @@ async function selectOrCreateProject(authData, options) {
|
|
|
246
301
|
} else {
|
|
247
302
|
if (projects.length === 0) {
|
|
248
303
|
console.log(chalk.yellow('No projects found. Creating first project...'));
|
|
304
|
+
const defaultName = getDefaultProjectName();
|
|
305
|
+
|
|
249
306
|
const { name, description } = await inquirer.prompt([
|
|
250
307
|
{
|
|
251
308
|
type: 'input',
|
|
252
309
|
name: 'name',
|
|
253
310
|
message: 'Project name:',
|
|
311
|
+
default: defaultName,
|
|
254
312
|
validate: input => input.length > 0 || 'Name is required',
|
|
255
313
|
},
|
|
256
314
|
{
|
|
@@ -440,7 +498,66 @@ async function saveProjectConfig(authData, projectData) {
|
|
|
440
498
|
}
|
|
441
499
|
}
|
|
442
500
|
|
|
443
|
-
|
|
501
|
+
/**
|
|
502
|
+
* Fetch MCP tools and prompt user for permission to pre-authorize
|
|
503
|
+
* @param {Object} authData - Auth data with tokens
|
|
504
|
+
* @param {Object} projectData - Project data
|
|
505
|
+
* @returns {Promise<Array<string>|null>} - Array of permission strings or null if declined
|
|
506
|
+
*/
|
|
507
|
+
async function fetchMCPToolPermissions(authData, projectData) {
|
|
508
|
+
try {
|
|
509
|
+
// Build auth headers (similar to lib/mcp-server.js)
|
|
510
|
+
const authHeaders = {
|
|
511
|
+
'Authorization': `Bearer ${authData.access_token}`,
|
|
512
|
+
'X-Org-Id': authData.org_id,
|
|
513
|
+
'X-User-Id': authData.user_id,
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
// Fetch tools from gateway
|
|
517
|
+
const { fetchRemoteMCPTools } = await import('../lib/mcp-proxy.js');
|
|
518
|
+
const projectContext = {
|
|
519
|
+
project_id: projectData.project_id,
|
|
520
|
+
org_id: authData.org_id,
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
const toolsResult = await fetchRemoteMCPTools(authHeaders, projectContext);
|
|
524
|
+
const tools = toolsResult.tools || [];
|
|
525
|
+
|
|
526
|
+
if (tools.length === 0) {
|
|
527
|
+
return null; // No tools available
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// Format tool names for display
|
|
531
|
+
const toolNames = tools.map(t => t.name).join(', ');
|
|
532
|
+
|
|
533
|
+
// Prompt user
|
|
534
|
+
console.log(chalk.cyan('\n🔧 MCP Tool Permissions\n'));
|
|
535
|
+
console.log(chalk.gray(`Found ${tools.length} available tools: ${toolNames}`));
|
|
536
|
+
|
|
537
|
+
const { allowPermissions } = await inquirer.prompt([{
|
|
538
|
+
type: 'confirm',
|
|
539
|
+
name: 'allowPermissions',
|
|
540
|
+
message: 'Pre-authorize these UnifiedMemory tools in Claude Code? (Recommended)',
|
|
541
|
+
default: true,
|
|
542
|
+
}]);
|
|
543
|
+
|
|
544
|
+
if (!allowPermissions) {
|
|
545
|
+
console.log(chalk.yellow('⚠ Tools not pre-authorized. Claude will prompt for permission on first use.'));
|
|
546
|
+
return null;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// Convert tool names to permission format
|
|
550
|
+
const permissions = tools.map(tool => `mcp__unifiedmemory__${tool.name}`);
|
|
551
|
+
return permissions;
|
|
552
|
+
|
|
553
|
+
} catch (error) {
|
|
554
|
+
console.error(chalk.yellow(`⚠ Could not fetch MCP tools: ${error.message}`));
|
|
555
|
+
console.log(chalk.gray('Skipping permission setup. You can manually add permissions later.'));
|
|
556
|
+
return null;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
async function configureProviders(authData, projectData, mcpToolPermissions = null) {
|
|
444
561
|
console.log(chalk.cyan('\n🔧 Configuring AI code assistants...\n'));
|
|
445
562
|
|
|
446
563
|
// Pass current directory for project-level configs (like Claude Code)
|
|
@@ -456,8 +573,8 @@ async function configureProviders(authData, projectData) {
|
|
|
456
573
|
|
|
457
574
|
// NEW APPROACH: Configure local MCP server (no tokens in config files)
|
|
458
575
|
for (const provider of detected) {
|
|
459
|
-
// Configure MCP server
|
|
460
|
-
const mcpSuccess = provider.configureMCP();
|
|
576
|
+
// Configure MCP server (pass permissions for Claude Code)
|
|
577
|
+
const mcpSuccess = provider.configureMCP(mcpToolPermissions);
|
|
461
578
|
|
|
462
579
|
// Configure memory instructions
|
|
463
580
|
const instructionsResult = provider.configureMemoryInstructions?.();
|
|
@@ -465,6 +582,11 @@ async function configureProviders(authData, projectData) {
|
|
|
465
582
|
// Display results
|
|
466
583
|
if (mcpSuccess) {
|
|
467
584
|
console.log(chalk.green(`✓ Configured ${provider.name} MCP server`));
|
|
585
|
+
|
|
586
|
+
// Show permission status for Claude Code
|
|
587
|
+
if (provider.name === 'Claude Code' && mcpToolPermissions && mcpToolPermissions.length > 0) {
|
|
588
|
+
console.log(chalk.green(` ✓ Pre-authorized ${mcpToolPermissions.length} MCP tools`));
|
|
589
|
+
}
|
|
468
590
|
} else {
|
|
469
591
|
console.log(chalk.red(`✗ Failed to configure ${provider.name} MCP`));
|
|
470
592
|
}
|
package/lib/config.js
CHANGED
|
@@ -9,49 +9,37 @@ const __dirname = dirname(__filename);
|
|
|
9
9
|
dotenvConfig({ path: join(__dirname, '..', '.env') });
|
|
10
10
|
|
|
11
11
|
export const config = {
|
|
12
|
-
//
|
|
13
|
-
clerkClientId: process.env.CLERK_CLIENT_ID,
|
|
12
|
+
// Clerk OAuth configuration (production defaults, can be overridden via env vars)
|
|
13
|
+
clerkClientId: process.env.CLERK_CLIENT_ID || 'nULlnomaKB9rRGP2',
|
|
14
14
|
clerkClientSecret: process.env.CLERK_CLIENT_SECRET, // Optional for PKCE flow
|
|
15
|
-
clerkDomain: process.env.CLERK_DOMAIN,
|
|
15
|
+
clerkDomain: process.env.CLERK_DOMAIN || 'clear-caiman-45.clerk.accounts.dev',
|
|
16
16
|
|
|
17
|
-
//
|
|
18
|
-
apiEndpoint: process.env.API_ENDPOINT,
|
|
17
|
+
// API configuration (production default, can be overridden via env var)
|
|
18
|
+
apiEndpoint: process.env.API_ENDPOINT || 'https://rose-asp-main-1c0b114.d2.zuplo.dev',
|
|
19
19
|
|
|
20
|
-
//
|
|
20
|
+
// OAuth flow configuration (localhost defaults for callback server)
|
|
21
21
|
redirectUri: process.env.REDIRECT_URI || 'http://localhost:3333/callback',
|
|
22
22
|
port: parseInt(process.env.PORT || '3333', 10)
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
// Validation function -
|
|
25
|
+
// Validation function - validates configuration values
|
|
26
26
|
export function validateConfig() {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (!config.clerkClientId) {
|
|
30
|
-
missing.push('CLERK_CLIENT_ID');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (!config.clerkDomain) {
|
|
34
|
-
missing.push('CLERK_DOMAIN');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (!config.apiEndpoint) {
|
|
38
|
-
missing.push('API_ENDPOINT');
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (missing.length > 0) {
|
|
42
|
-
throw new Error(
|
|
43
|
-
`Missing required environment variables: ${missing.join(', ')}\n\n` +
|
|
44
|
-
`Please create a .env file in the project root with these values.\n` +
|
|
45
|
-
`See .env.example for a template.`
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Validate URL format for apiEndpoint
|
|
27
|
+
// Validate URL format for apiEndpoint (now guaranteed to exist via defaults)
|
|
50
28
|
try {
|
|
51
29
|
new URL(config.apiEndpoint);
|
|
52
30
|
} catch (e) {
|
|
53
31
|
throw new Error(`API_ENDPOINT must be a valid URL (got: ${config.apiEndpoint})`);
|
|
54
32
|
}
|
|
55
33
|
|
|
34
|
+
// Validate clerkDomain is not empty (basic sanity check)
|
|
35
|
+
if (!config.clerkDomain || config.clerkDomain.trim() === '') {
|
|
36
|
+
throw new Error('CLERK_DOMAIN cannot be empty');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Validate clerkClientId is not empty (basic sanity check)
|
|
40
|
+
if (!config.clerkClientId || config.clerkClientId.trim() === '') {
|
|
41
|
+
throw new Error('CLERK_CLIENT_ID cannot be empty');
|
|
42
|
+
}
|
|
43
|
+
|
|
56
44
|
return true;
|
|
57
45
|
}
|
package/lib/provider-detector.js
CHANGED
|
@@ -59,9 +59,10 @@ class BaseProvider {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
configureMCP() {
|
|
62
|
+
configureMCP(toolPermissions = null) {
|
|
63
63
|
// NEW APPROACH: Configure local server instead of HTTP
|
|
64
64
|
// No parameters needed - local server reads from filesystem
|
|
65
|
+
// toolPermissions parameter for Claude Code compatibility (unused in base class)
|
|
65
66
|
const config = this.readConfig() || { mcpServers: {} };
|
|
66
67
|
|
|
67
68
|
config.mcpServers = config.mcpServers || {};
|
|
@@ -136,19 +137,19 @@ class ClaudeProvider extends BaseProvider {
|
|
|
136
137
|
}
|
|
137
138
|
}
|
|
138
139
|
|
|
139
|
-
configureMCP() {
|
|
140
|
+
configureMCP(toolPermissions = null) {
|
|
140
141
|
// Create .mcp.json at project root with local server config
|
|
141
142
|
const success = super.configureMCP();
|
|
142
143
|
|
|
143
144
|
if (success) {
|
|
144
145
|
// Update .claude/settings.local.json to enable the MCP server
|
|
145
|
-
this.updateClaudeSettings();
|
|
146
|
+
this.updateClaudeSettings(toolPermissions);
|
|
146
147
|
}
|
|
147
148
|
|
|
148
149
|
return success;
|
|
149
150
|
}
|
|
150
151
|
|
|
151
|
-
updateClaudeSettings() {
|
|
152
|
+
updateClaudeSettings(toolPermissions = null) {
|
|
152
153
|
if (!this.settingsPath) return false;
|
|
153
154
|
|
|
154
155
|
try {
|
|
@@ -169,6 +170,23 @@ class ClaudeProvider extends BaseProvider {
|
|
|
169
170
|
settings.enabledMcpjsonServers.push('unifiedmemory');
|
|
170
171
|
}
|
|
171
172
|
|
|
173
|
+
// Add tool permissions if provided
|
|
174
|
+
if (toolPermissions && Array.isArray(toolPermissions) && toolPermissions.length > 0) {
|
|
175
|
+
if (!settings.permissions) {
|
|
176
|
+
settings.permissions = { allow: [] };
|
|
177
|
+
}
|
|
178
|
+
if (!settings.permissions.allow) {
|
|
179
|
+
settings.permissions.allow = [];
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Add new permissions, avoiding duplicates
|
|
183
|
+
toolPermissions.forEach(permission => {
|
|
184
|
+
if (!settings.permissions.allow.includes(permission)) {
|
|
185
|
+
settings.permissions.allow.push(permission);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
172
190
|
// Write settings
|
|
173
191
|
fs.ensureDirSync(this.claudeDir);
|
|
174
192
|
fs.writeJSONSync(this.settingsPath, settings, { spaces: 2 });
|