borgmcp 0.2.0-beta.1

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/dist/config.js ADDED
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Secure token storage using OS keychain
3
+ * Uses Keytar for cross-platform credential management
4
+ *
5
+ * Addresses consensus finding: Machine-specific encryption is insecure
6
+ * Solution: Use OS native keychains (macOS Keychain, Windows Credential Manager, Linux Secret Service)
7
+ */
8
+ import keytar from 'keytar';
9
+ const SERVICE_NAME = 'borg-mcp';
10
+ const ID_TOKEN_ACCOUNT = 'google-id-token';
11
+ const REFRESH_TOKEN_ACCOUNT = 'google-refresh-token';
12
+ const TOKEN_EXPIRY_ACCOUNT = 'token-expiry';
13
+ /**
14
+ * Store Google OAuth ID token securely in OS keychain
15
+ */
16
+ export async function storeIdToken(idToken, expiresAt) {
17
+ await keytar.setPassword(SERVICE_NAME, ID_TOKEN_ACCOUNT, idToken);
18
+ await keytar.setPassword(SERVICE_NAME, TOKEN_EXPIRY_ACCOUNT, expiresAt.toString());
19
+ }
20
+ /**
21
+ * Store Google OAuth refresh token securely in OS keychain
22
+ */
23
+ export async function storeRefreshToken(refreshToken) {
24
+ await keytar.setPassword(SERVICE_NAME, REFRESH_TOKEN_ACCOUNT, refreshToken);
25
+ }
26
+ /**
27
+ * Retrieve Google OAuth ID token from OS keychain
28
+ * Returns null if not found or expired
29
+ */
30
+ export async function getIdToken() {
31
+ const token = await keytar.getPassword(SERVICE_NAME, ID_TOKEN_ACCOUNT);
32
+ const expiryStr = await keytar.getPassword(SERVICE_NAME, TOKEN_EXPIRY_ACCOUNT);
33
+ if (!token || !expiryStr) {
34
+ return null;
35
+ }
36
+ const expiresAt = parseInt(expiryStr, 10);
37
+ const now = Date.now();
38
+ // Check if token is expired (with 5 minute buffer)
39
+ if (expiresAt - now < 5 * 60 * 1000) {
40
+ return null; // Token expired or expiring soon
41
+ }
42
+ return token;
43
+ }
44
+ /**
45
+ * Retrieve Google OAuth refresh token from OS keychain
46
+ */
47
+ export async function getRefreshToken() {
48
+ return await keytar.getPassword(SERVICE_NAME, REFRESH_TOKEN_ACCOUNT);
49
+ }
50
+ /**
51
+ * Clear all stored tokens from OS keychain
52
+ */
53
+ export async function clearTokens() {
54
+ await keytar.deletePassword(SERVICE_NAME, ID_TOKEN_ACCOUNT);
55
+ await keytar.deletePassword(SERVICE_NAME, REFRESH_TOKEN_ACCOUNT);
56
+ await keytar.deletePassword(SERVICE_NAME, TOKEN_EXPIRY_ACCOUNT);
57
+ }
58
+ /**
59
+ * Check if user has valid authentication
60
+ */
61
+ export async function isAuthenticated() {
62
+ const token = await getIdToken();
63
+ return token !== null;
64
+ }
65
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAG5B,MAAM,YAAY,GAAG,UAAU,CAAC;AAChC,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AAC3C,MAAM,qBAAqB,GAAG,sBAAsB,CAAC;AACrD,MAAM,oBAAoB,GAAG,cAAc,CAAC;AAE5C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAe,EAAE,SAAiB;IACnE,MAAM,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAC;IAClE,MAAM,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,oBAAoB,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;AACrF,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,YAAoB;IAC1D,MAAM,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,qBAAqB,EAAE,YAAY,CAAC,CAAC;AAC9E,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;IACvE,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,oBAAoB,CAAC,CAAC;IAE/E,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEvB,mDAAmD;IACnD,IAAI,SAAS,GAAG,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC,CAAC,iCAAiC;IAChD,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,OAAO,MAAM,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,qBAAqB,CAAC,CAAC;AACvE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,MAAM,CAAC,cAAc,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;IAC5D,MAAM,MAAM,CAAC,cAAc,CAAC,YAAY,EAAE,qBAAqB,CAAC,CAAC;IACjE,MAAM,MAAM,CAAC,cAAc,CAAC,YAAY,EAAE,oBAAoB,CAAC,CAAC;AAClE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,KAAK,GAAG,MAAM,UAAU,EAAE,CAAC;IACjC,OAAO,KAAK,KAAK,IAAI,CAAC;AACxB,CAAC"}
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Borg MCP Client - Main Entry Point
4
+ *
5
+ * stdio MCP server that:
6
+ * 1. Connects to Claude Code via stdio transport
7
+ * 2. Authenticates via Google OAuth device flow
8
+ * 3. Proxies MCP tools to remote server at api.borgmcp.ai
9
+ * 4. Provides borg:regen tool for centralized context retrieval
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG"}
package/dist/index.js ADDED
@@ -0,0 +1,157 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Borg MCP Client - Main Entry Point
4
+ *
5
+ * stdio MCP server that:
6
+ * 1. Connects to Claude Code via stdio transport
7
+ * 2. Authenticates via Google OAuth device flow
8
+ * 3. Proxies MCP tools to remote server at api.borgmcp.ai
9
+ * 4. Provides borg:regen tool for centralized context retrieval
10
+ */
11
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
12
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
13
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
14
+ import { regenerateContext, checkSubscriptionStatus, createSubscription, } from './remote-client.js';
15
+ /**
16
+ * Main entry point
17
+ */
18
+ async function main() {
19
+ // If running with 'setup' argument, run the setup wizard
20
+ if (process.argv.includes('setup')) {
21
+ // Import and run setup dynamically
22
+ const setupModule = await import('./setup.js');
23
+ // setup.ts exports main as default, but it auto-runs, so we just need to import it
24
+ return; // setup.js will handle everything and exit
25
+ }
26
+ // Create MCP server
27
+ const server = new Server({
28
+ name: 'borg-mcp-client',
29
+ version: '0.1.0',
30
+ }, {
31
+ capabilities: {
32
+ tools: {},
33
+ },
34
+ });
35
+ // Register tool listing
36
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
37
+ return {
38
+ tools: [
39
+ {
40
+ name: 'subscribe',
41
+ description: 'Create Stripe checkout session ($2/month, 7-day trial)',
42
+ inputSchema: {
43
+ type: 'object',
44
+ properties: {},
45
+ required: [],
46
+ },
47
+ },
48
+ {
49
+ name: 'borg:regen',
50
+ description: 'Regenerate centralized context from your active context entries (requires subscription). Returns markdown-formatted hive mind context.',
51
+ inputSchema: {
52
+ type: 'object',
53
+ properties: {
54
+ categories: {
55
+ type: 'array',
56
+ items: {
57
+ type: 'string',
58
+ },
59
+ description: 'Optional: Filter by specific categories (e.g., ["code-style", "commit-rules"])',
60
+ },
61
+ },
62
+ required: [],
63
+ },
64
+ },
65
+ {
66
+ name: 'subscription_status',
67
+ description: 'Check subscription status',
68
+ inputSchema: {
69
+ type: 'object',
70
+ properties: {},
71
+ required: [],
72
+ },
73
+ },
74
+ ],
75
+ };
76
+ });
77
+ // Register tool execution handler
78
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
79
+ const { name, arguments: args } = request.params;
80
+ try {
81
+ switch (name) {
82
+ case 'subscribe': {
83
+ const checkoutUrl = await createSubscription();
84
+ return {
85
+ content: [
86
+ {
87
+ type: 'text',
88
+ text: `Complete your subscription at: ${checkoutUrl}`,
89
+ },
90
+ ],
91
+ };
92
+ }
93
+ case 'borg:regen': {
94
+ const categories = Array.isArray(args?.categories) ? args.categories : undefined;
95
+ const context = await regenerateContext(categories);
96
+ return {
97
+ content: [
98
+ {
99
+ type: 'text',
100
+ text: context,
101
+ },
102
+ ],
103
+ };
104
+ }
105
+ case 'subscription_status': {
106
+ const status = await checkSubscriptionStatus();
107
+ return {
108
+ content: [
109
+ {
110
+ type: 'text',
111
+ text: JSON.stringify(status, null, 2),
112
+ },
113
+ ],
114
+ };
115
+ }
116
+ default:
117
+ throw new Error(`Unknown tool: ${name}`);
118
+ }
119
+ }
120
+ catch (error) {
121
+ // Better error messages for auth/subscription issues
122
+ if (error.message?.includes('Authentication required')) {
123
+ return {
124
+ content: [
125
+ {
126
+ type: 'text',
127
+ text: '🔐 Not authenticated. Run: borgmcp setup',
128
+ },
129
+ ],
130
+ isError: true,
131
+ };
132
+ }
133
+ return {
134
+ content: [
135
+ {
136
+ type: 'text',
137
+ text: `Error: ${error.message}`,
138
+ },
139
+ ],
140
+ isError: true,
141
+ };
142
+ }
143
+ });
144
+ // Create stdio transport
145
+ const transport = new StdioServerTransport();
146
+ // Connect server to transport
147
+ await server.connect(transport);
148
+ console.error('🚀 Borg MCP Client started');
149
+ console.error('💡 Use borg:regen to fetch centralized context from the hive mind');
150
+ console.error('🌐 Manage your context entries at https://borgmcp.ai/dashboard');
151
+ }
152
+ // Start the server
153
+ main().catch((error) => {
154
+ console.error('Fatal error:', error);
155
+ process.exit(1);
156
+ });
157
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Post-install script
4
+ *
5
+ * Displays welcome message after npm install
6
+ * Non-interactive - just shows next steps
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=postinstall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postinstall.d.ts","sourceRoot":"","sources":["../src/postinstall.ts"],"names":[],"mappings":";AACA;;;;;GAKG"}
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Post-install script
4
+ *
5
+ * Displays welcome message after npm install
6
+ * Non-interactive - just shows next steps
7
+ */
8
+ import chalk from 'chalk';
9
+ console.log(chalk.blue.bold('\n╔════════════════════════════════════╗'));
10
+ console.log(chalk.blue.bold('║ 🧠 Borg MCP Installed! 🎉 ║'));
11
+ console.log(chalk.blue.bold('╚════════════════════════════════════╝\n'));
12
+ console.log(chalk.gray('Centralized context storage for Claude\n'));
13
+ console.log(chalk.green('Next step:'));
14
+ console.log(chalk.white.bold(' $ borgmcp setup\n'));
15
+ console.log(chalk.gray('This will:'));
16
+ console.log(chalk.gray(' • Configure Claude Code'));
17
+ console.log(chalk.gray(' • Authenticate with Google'));
18
+ console.log(chalk.gray(' • Set up your 7-day trial\n'));
19
+ //# sourceMappingURL=postinstall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postinstall.js","sourceRoot":"","sources":["../src/postinstall.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC,CAAC;AACzE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC,CAAC;AACtE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC,CAAC;AAEzE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC,CAAC;AAEpE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;AACvC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;AAErD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;AACtC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;AACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC,CAAC;AACxD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Remote HTTP client for api.borgmcp.ai
3
+ *
4
+ * Handles:
5
+ * - HTTP requests to remote MCP server
6
+ * - Automatic token injection
7
+ * - Network failure handling with retry + exponential backoff
8
+ * - Offline queue for pending operations
9
+ */
10
+ import type { RemoteResponse } from './types.js';
11
+ /**
12
+ * Call remote MCP tool with retry logic
13
+ */
14
+ export declare function callRemoteTool(toolName: string, args: Record<string, any>): Promise<RemoteResponse>;
15
+ /**
16
+ * Regenerate centralized context from active context entries
17
+ */
18
+ export declare function regenerateContext(categories?: string[]): Promise<string>;
19
+ /**
20
+ * Check subscription status
21
+ */
22
+ export declare function checkSubscriptionStatus(): Promise<any>;
23
+ /**
24
+ * Create subscription (returns checkout URL)
25
+ */
26
+ export declare function createSubscription(): Promise<string>;
27
+ //# sourceMappingURL=remote-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-client.d.ts","sourceRoot":"","sources":["../src/remote-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,YAAY,CAAC;AAiDhE;;GAEG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACxB,OAAO,CAAC,cAAc,CAAC,CAoEzB;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,CAAC,EAAE,MAAM,EAAE,GACpB,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,GAAG,CAAC,CAa5D;AAED;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAsB1D"}
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Remote HTTP client for api.borgmcp.ai
3
+ *
4
+ * Handles:
5
+ * - HTTP requests to remote MCP server
6
+ * - Automatic token injection
7
+ * - Network failure handling with retry + exponential backoff
8
+ * - Offline queue for pending operations
9
+ */
10
+ import { getIdToken, getRefreshToken } from './config.js';
11
+ import { refreshIdToken } from './auth.js';
12
+ const API_URL = process.env.BORG_API_URL || 'https://api.borgmcp.ai';
13
+ const MAX_RETRIES = 3;
14
+ const INITIAL_BACKOFF_MS = 1000; // 1 second
15
+ const MAX_BACKOFF_MS = 30000; // 30 seconds
16
+ /**
17
+ * Exponential backoff delay
18
+ */
19
+ function calculateBackoff(retryCount) {
20
+ const delay = Math.min(INITIAL_BACKOFF_MS * Math.pow(2, retryCount), MAX_BACKOFF_MS);
21
+ // Add jitter to avoid thundering herd
22
+ return delay + Math.random() * 1000;
23
+ }
24
+ /**
25
+ * Sleep for specified milliseconds
26
+ */
27
+ function sleep(ms) {
28
+ return new Promise(resolve => setTimeout(resolve, ms));
29
+ }
30
+ /**
31
+ * Get valid auth token (refreshes if expired)
32
+ */
33
+ async function getValidToken() {
34
+ let token = await getIdToken();
35
+ if (!token) {
36
+ // Token expired, try to refresh
37
+ const refreshToken = await getRefreshToken();
38
+ if (refreshToken) {
39
+ await refreshIdToken(refreshToken);
40
+ token = await getIdToken();
41
+ }
42
+ if (!token) {
43
+ throw new Error('Authentication required. Run: borgmcp setup');
44
+ }
45
+ }
46
+ return token;
47
+ }
48
+ /**
49
+ * Call remote MCP tool with retry logic
50
+ */
51
+ export async function callRemoteTool(toolName, args) {
52
+ let lastError = null;
53
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
54
+ try {
55
+ // Get valid auth token
56
+ const token = await getValidToken();
57
+ // Inject auth token into args
58
+ const argsWithAuth = {
59
+ ...args,
60
+ auth_token: token,
61
+ };
62
+ // Make HTTP request to remote server
63
+ const response = await fetch(`${API_URL}/mcp`, {
64
+ method: 'POST',
65
+ headers: {
66
+ 'Content-Type': 'application/json',
67
+ },
68
+ body: JSON.stringify({
69
+ jsonrpc: '2.0',
70
+ id: `client-${Date.now()}`,
71
+ method: 'tools/call',
72
+ params: {
73
+ name: toolName,
74
+ arguments: argsWithAuth,
75
+ },
76
+ }),
77
+ });
78
+ if (!response.ok) {
79
+ throw new Error(`HTTP ${response.status}: ${await response.text()}`);
80
+ }
81
+ const data = (await response.json());
82
+ if (data.error) {
83
+ throw new Error(data.error.message || 'Remote tool call failed');
84
+ }
85
+ return {
86
+ success: true,
87
+ data: data.result,
88
+ };
89
+ }
90
+ catch (error) {
91
+ lastError = error;
92
+ // Don't retry on authentication errors
93
+ if (error.message?.includes('auth') || error.message?.includes('token')) {
94
+ throw error;
95
+ }
96
+ // Don't retry if we've exhausted attempts
97
+ if (attempt >= MAX_RETRIES) {
98
+ break;
99
+ }
100
+ // Exponential backoff before retry
101
+ const backoff = calculateBackoff(attempt);
102
+ console.error(`Retry ${attempt + 1}/${MAX_RETRIES} after ${Math.round(backoff)}ms...`);
103
+ await sleep(backoff);
104
+ }
105
+ }
106
+ // All retries exhausted
107
+ throw new Error(`Failed after ${MAX_RETRIES} retries: ${lastError?.message}`);
108
+ }
109
+ /**
110
+ * Regenerate centralized context from active context entries
111
+ */
112
+ export async function regenerateContext(categories) {
113
+ const token = await getValidToken();
114
+ const url = new URL(`${API_URL}/api/regen`);
115
+ if (categories && categories.length > 0) {
116
+ url.searchParams.set('categories', categories.join(','));
117
+ }
118
+ const response = await fetch(url.toString(), {
119
+ headers: {
120
+ 'Authorization': `Bearer ${token}`,
121
+ },
122
+ });
123
+ if (!response.ok) {
124
+ throw new Error(`HTTP ${response.status}: ${await response.text()}`);
125
+ }
126
+ return await response.text();
127
+ }
128
+ /**
129
+ * Check subscription status
130
+ */
131
+ export async function checkSubscriptionStatus() {
132
+ const token = await getValidToken();
133
+ const response = await fetch(`${API_URL}/api/subscription/status`, {
134
+ headers: {
135
+ 'Authorization': `Bearer ${token}`,
136
+ },
137
+ });
138
+ if (!response.ok) {
139
+ throw new Error(`HTTP ${response.status}: ${await response.text()}`);
140
+ }
141
+ return await response.json();
142
+ }
143
+ /**
144
+ * Create subscription (returns checkout URL)
145
+ */
146
+ export async function createSubscription() {
147
+ const token = await getValidToken();
148
+ const response = await fetch(`${API_URL}/api/subscribe`, {
149
+ method: 'POST',
150
+ headers: {
151
+ 'Authorization': `Bearer ${token}`,
152
+ 'Content-Type': 'application/json',
153
+ },
154
+ });
155
+ if (!response.ok) {
156
+ throw new Error(`HTTP ${response.status}: ${await response.text()}`);
157
+ }
158
+ const data = (await response.json());
159
+ // Backend returns { checkout_url: "..." }
160
+ if (!data.checkout_url) {
161
+ throw new Error('No checkout URL in response');
162
+ }
163
+ return data.checkout_url;
164
+ }
165
+ //# sourceMappingURL=remote-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-client.js","sourceRoot":"","sources":["../src/remote-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Borg MCP Setup Wizard
4
+ *
5
+ * Interactive setup flow:
6
+ * 1. Configure Claude Code MCP settings
7
+ * 2. Google OAuth authentication
8
+ * 3. Subscription setup (web dashboard or Stripe)
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG"}