@selfhost.dev/mcp-server 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.
- package/README.md +382 -0
- package/dist/auth.d.ts +18 -0
- package/dist/auth.js +204 -0
- package/dist/auth.js.map +1 -0
- package/dist/client.d.ts +10 -0
- package/dist/client.js +84 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +20 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +71 -0
- package/dist/index.js.map +1 -0
- package/dist/rate-limiter.d.ts +22 -0
- package/dist/rate-limiter.js +124 -0
- package/dist/rate-limiter.js.map +1 -0
- package/dist/session.d.ts +25 -0
- package/dist/session.js +48 -0
- package/dist/session.js.map +1 -0
- package/dist/tools/alerts.d.ts +2 -0
- package/dist/tools/alerts.js +372 -0
- package/dist/tools/alerts.js.map +1 -0
- package/dist/tools/auth.d.ts +2 -0
- package/dist/tools/auth.js +142 -0
- package/dist/tools/auth.js.map +1 -0
- package/dist/tools/backups.d.ts +2 -0
- package/dist/tools/backups.js +294 -0
- package/dist/tools/backups.js.map +1 -0
- package/dist/tools/credentials.d.ts +2 -0
- package/dist/tools/credentials.js +187 -0
- package/dist/tools/credentials.js.map +1 -0
- package/dist/tools/instances.d.ts +2 -0
- package/dist/tools/instances.js +555 -0
- package/dist/tools/instances.js.map +1 -0
- package/dist/tools/networking.d.ts +2 -0
- package/dist/tools/networking.js +240 -0
- package/dist/tools/networking.js.map +1 -0
- package/dist/tools/organizations.d.ts +2 -0
- package/dist/tools/organizations.js +260 -0
- package/dist/tools/organizations.js.map +1 -0
- package/dist/tools/pg-config.d.ts +2 -0
- package/dist/tools/pg-config.js +59 -0
- package/dist/tools/pg-config.js.map +1 -0
- package/dist/types/api.d.ts +20 -0
- package/dist/types/api.js +2 -0
- package/dist/types/api.js.map +1 -0
- package/dist/types/models.d.ts +44 -0
- package/dist/types/models.js +3 -0
- package/dist/types/models.js.map +1 -0
- package/dist/types/tiers.d.ts +15 -0
- package/dist/types/tiers.js +91 -0
- package/dist/types/tiers.js.map +1 -0
- package/dist/utils/formatters.d.ts +1 -0
- package/dist/utils/formatters.js +28 -0
- package/dist/utils/formatters.js.map +1 -0
- package/dist/utils/validators.d.ts +14 -0
- package/dist/utils/validators.js +9 -0
- package/dist/utils/validators.js.map +1 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
# SelfHost MCP Server
|
|
2
|
+
|
|
3
|
+
A full-featured [Model Context Protocol](https://modelcontextprotocol.io/) server that brings [SelfHost's](https://selfhost.dev) database management capabilities directly into AI coding assistants. Provision, monitor, scale, and manage production database infrastructure — all through natural language, without leaving your editor.
|
|
4
|
+
|
|
5
|
+
Works with **Claude Code**, **Cursor**, **Windsurf**, **Cline**, and any MCP-compatible client.
|
|
6
|
+
|
|
7
|
+
> **JIRA Epic:** [SELFHOST-110](https://selfhost.atlassian.net/browse/SELFHOST-110)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
### Prerequisites
|
|
14
|
+
|
|
15
|
+
- A [SelfHost.dev](https://selfhost.dev) account (invite-only — ask an existing user or join the waitlist)
|
|
16
|
+
- **Node.js 18+** or **Bun**
|
|
17
|
+
|
|
18
|
+
### Install
|
|
19
|
+
|
|
20
|
+
**Claude Code:**
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Using npm (Node.js)
|
|
24
|
+
claude mcp add selfhost -- npx @selfhost.dev/mcp-server
|
|
25
|
+
|
|
26
|
+
# Using Bun
|
|
27
|
+
claude mcp add selfhost -- bunx @selfhost.dev/mcp-server
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Cursor / Windsurf / Other MCP clients:**
|
|
31
|
+
|
|
32
|
+
Add to your MCP configuration file:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"mcpServers": {
|
|
37
|
+
"selfhost": {
|
|
38
|
+
"command": "npx",
|
|
39
|
+
"args": ["@selfhost.dev/mcp-server"]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Or with Bun:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"mcpServers": {
|
|
50
|
+
"selfhost": {
|
|
51
|
+
"command": "bunx",
|
|
52
|
+
"args": ["@selfhost.dev/mcp-server"]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
That's it. The server handles authentication, token refresh, and everything else automatically.
|
|
59
|
+
|
|
60
|
+
### First Run
|
|
61
|
+
|
|
62
|
+
On first use, the MCP server opens your browser to sign in via SelfHost's console. After you authorize, credentials are saved locally (`~/.selfhost/credentials.json`) and auto-refreshed — you won't need to sign in again.
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
You: "Show me my databases"
|
|
66
|
+
|
|
67
|
+
Claude: Authenticates → fetches your orgs → selects org → lists instances
|
|
68
|
+
→ Shows you a summary of all your running databases
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## What Can You Do?
|
|
74
|
+
|
|
75
|
+
### Talk to your infrastructure in plain English
|
|
76
|
+
|
|
77
|
+
| You say | What happens |
|
|
78
|
+
|---------|-------------|
|
|
79
|
+
| *"Spin up a Postgres 18 instance in us-east-1"* | Walks you through config, shows cost estimate, provisions it |
|
|
80
|
+
| *"Stop my staging database"* | Finds the instance, confirms with you, stops it |
|
|
81
|
+
| *"Set up a CPU alert at 80% on my prod DB"* | Creates an alert rule with email notification |
|
|
82
|
+
| *"Show me the backups for my main instance"* | Lists all backups with sizes and timestamps |
|
|
83
|
+
| *"Fork my production database for testing"* | Creates an independent clone with a new password |
|
|
84
|
+
| *"What's my estimated monthly cost for an r6i.xlarge with 500GB gp3?"* | Calculates itemized cost breakdown |
|
|
85
|
+
| *"Tune shared_buffers on my instance"* | Previews defaults, applies the override, syncs to replicas |
|
|
86
|
+
|
|
87
|
+
### Safety Built In
|
|
88
|
+
|
|
89
|
+
Destructive operations (delete, stop, reboot) require explicit confirmation. The server will always ask before proceeding — you'll never accidentally delete a production database.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Features
|
|
94
|
+
|
|
95
|
+
### 76 tools across 8 modules
|
|
96
|
+
|
|
97
|
+
Every tool maps to a real API endpoint. No mock data, no shortcuts.
|
|
98
|
+
|
|
99
|
+
#### Authentication & Users
|
|
100
|
+
Automatic browser-based sign-in with Firebase. Tokens refresh transparently.
|
|
101
|
+
|
|
102
|
+
| Tool | Description |
|
|
103
|
+
|------|-------------|
|
|
104
|
+
| `create_or_login_user` | Create account or sign in |
|
|
105
|
+
| `get_current_user` | Your profile, admin status, org membership |
|
|
106
|
+
| `get_my_memberships` | List your orgs and pending invitations |
|
|
107
|
+
| `select_organization` | Switch org context (sets rate limits based on billing plan) |
|
|
108
|
+
| `get_invite_credits` | Check remaining platform invite credits |
|
|
109
|
+
| `send_platform_invite` | Invite someone to join SelfHost |
|
|
110
|
+
| `list_my_platform_invites` | See invitations you've sent |
|
|
111
|
+
| `reauthenticate` | Sign out and sign in again (switch accounts) |
|
|
112
|
+
|
|
113
|
+
#### Organizations & Team Management
|
|
114
|
+
Multi-tenant — everything is scoped to your org.
|
|
115
|
+
|
|
116
|
+
| Tool | Description |
|
|
117
|
+
|------|-------------|
|
|
118
|
+
| `list_organizations` | All orgs you belong to |
|
|
119
|
+
| `create_organization` | Create a new org (you become owner, get 5 invite credits) |
|
|
120
|
+
| `get_organization` | Org details and billing plan |
|
|
121
|
+
| `update_organization` | Change name, description, or IAM role |
|
|
122
|
+
| `delete_organization` | Soft-delete org and all related resources |
|
|
123
|
+
| `list_members` | See team members and their roles |
|
|
124
|
+
| `remove_member` | Remove a member (owner/admin only) |
|
|
125
|
+
| `invite_to_org` | Send org invitation with role assignment |
|
|
126
|
+
| `list_org_invitations` | Pending invitations |
|
|
127
|
+
| `cancel_invitation` | Revoke a pending invitation |
|
|
128
|
+
| `get_my_invitations` | Invitations sent to you |
|
|
129
|
+
| `list_activity_logs` | Audit trail of all actions in the org |
|
|
130
|
+
|
|
131
|
+
#### Cloud Credentials
|
|
132
|
+
Bring your own AWS account (BYOC) or use SelfHost's managed infrastructure.
|
|
133
|
+
|
|
134
|
+
| Tool | Description |
|
|
135
|
+
|------|-------------|
|
|
136
|
+
| `list_credentials` | List cloud credentials (secrets never exposed) |
|
|
137
|
+
| `add_credential` | Add AWS access keys or IAM role |
|
|
138
|
+
| `update_credential` | Rotate keys or update metadata |
|
|
139
|
+
| `delete_credential` | Remove a credential (with confirmation) |
|
|
140
|
+
| `set_default_credential` | Set as default for the org |
|
|
141
|
+
| `get_aws_account_info` | AWS account ID and free tier status |
|
|
142
|
+
|
|
143
|
+
#### Networking
|
|
144
|
+
VPCs, subnets, and security groups. Optional — auto-created during provisioning if not specified.
|
|
145
|
+
|
|
146
|
+
| Tool | Description |
|
|
147
|
+
|------|-------------|
|
|
148
|
+
| `list_vpcs` | List VPCs in a region (grouped by public/private) |
|
|
149
|
+
| `create_vpc` | Create VPC with internet gateway and subnets |
|
|
150
|
+
| `delete_vpc` | Remove VPC and associated resources (with confirmation) |
|
|
151
|
+
| `list_subnets` | List subnets in a region |
|
|
152
|
+
| `create_subnet` | Create subnet in a VPC |
|
|
153
|
+
| `list_security_groups` | List security groups |
|
|
154
|
+
| `create_security_group` | Create SG with inbound rules |
|
|
155
|
+
| `update_security_group` | Replace inbound rules on a security group |
|
|
156
|
+
|
|
157
|
+
#### Database Instances
|
|
158
|
+
The core feature. Full lifecycle management for PostgreSQL, MySQL, and MongoDB.
|
|
159
|
+
|
|
160
|
+
| Tool | Description |
|
|
161
|
+
|------|-------------|
|
|
162
|
+
| `list_regions` | Available AWS regions |
|
|
163
|
+
| `get_instance_types_for_region` | EC2 types with specs and hourly pricing |
|
|
164
|
+
| `list_storage_types` | EBS volume types with pricing |
|
|
165
|
+
| `estimate_instance_cost` | Itemized monthly cost breakdown before provisioning |
|
|
166
|
+
| `create_instance` | Provision a new database (guided flow with cost confirmation) |
|
|
167
|
+
| `list_instances` | All instances grouped by master + replicas |
|
|
168
|
+
| `get_instance` | Detailed instance info with latest metrics |
|
|
169
|
+
| `update_instance` | Change config, resize, toggle multi-AZ, update CIDR ranges |
|
|
170
|
+
| `stop_instance` | Stop instances (with confirmation) |
|
|
171
|
+
| `start_instance` | Start stopped instances |
|
|
172
|
+
| `reboot_instance` | Reboot instances (with confirmation) |
|
|
173
|
+
| `delete_instance` | Delete instances with optional final snapshot (with confirmation) |
|
|
174
|
+
| `fork_instance` | Clone a database into a new independent instance |
|
|
175
|
+
| `refresh_instance_group` | Refresh cached state for a master + replica group |
|
|
176
|
+
|
|
177
|
+
#### PostgreSQL Configuration
|
|
178
|
+
Tune database parameters with calculated defaults per instance type.
|
|
179
|
+
|
|
180
|
+
| Tool | Description |
|
|
181
|
+
|------|-------------|
|
|
182
|
+
| `preview_pg_config` | See calculated defaults for an instance type (before creating) |
|
|
183
|
+
| `get_pg_config` | Current config with defaults, overrides, and effective values |
|
|
184
|
+
| `update_pg_config` | Apply overrides (auto-syncs to replicas, set null to revert) |
|
|
185
|
+
|
|
186
|
+
#### Backups & Snapshots
|
|
187
|
+
Automated backups with DLM policies and manual EBS snapshots.
|
|
188
|
+
|
|
189
|
+
| Tool | Description |
|
|
190
|
+
|------|-------------|
|
|
191
|
+
| `list_backups` | List all backups (syncs with AWS) |
|
|
192
|
+
| `create_backup` | Create S3 file backup or AWS backup job |
|
|
193
|
+
| `delete_backup` | Delete backup and AWS snapshot (with confirmation) |
|
|
194
|
+
| `list_backup_policies` | List DLM lifecycle policies |
|
|
195
|
+
| `create_backup_policy` | Create automated backup schedule |
|
|
196
|
+
| `update_backup_policy` | Enable/disable or modify schedule |
|
|
197
|
+
| `delete_backup_policy` | Remove policy (with confirmation) |
|
|
198
|
+
| `list_snapshots` | List EBS snapshots in a region |
|
|
199
|
+
| `get_snapshot` | Snapshot details |
|
|
200
|
+
| `delete_snapshot` | Delete EBS snapshot (with confirmation) |
|
|
201
|
+
| `create_snapshot` | Create EBS snapshot from instance volume |
|
|
202
|
+
|
|
203
|
+
#### Alerts & Notifications
|
|
204
|
+
Monitor your databases and get notified when things go wrong.
|
|
205
|
+
|
|
206
|
+
| Tool | Description |
|
|
207
|
+
|------|-------------|
|
|
208
|
+
| `list_alert_rules` | Active alert rules |
|
|
209
|
+
| `create_alert_rule` | Create rule (CPU, memory, disk, replication lag, etc.) |
|
|
210
|
+
| `get_alert_rule` | Rule details |
|
|
211
|
+
| `update_alert_rule` | Modify thresholds or notification channels |
|
|
212
|
+
| `delete_alert_rule` | Delete rule and all instances (with confirmation) |
|
|
213
|
+
| `list_alert_instances` | Fired/pending/resolved alerts (paginated) |
|
|
214
|
+
| `get_alert_instance` | Alert instance details |
|
|
215
|
+
| `acknowledge_alert` | Acknowledge a firing alert |
|
|
216
|
+
| `resolve_alert` | Manually resolve an alert |
|
|
217
|
+
| `list_notification_channels` | Email notification endpoints |
|
|
218
|
+
| `create_notification_channel` | Add email channel |
|
|
219
|
+
| `update_notification_channel` | Modify channel config |
|
|
220
|
+
| `delete_notification_channel` | Remove channel (with confirmation) |
|
|
221
|
+
| `test_notification_channel` | Send test notification |
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Common Workflows
|
|
226
|
+
|
|
227
|
+
### Switch AWS Account (BYOC vs Platform-Managed)
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
You: "I want to use my own AWS account"
|
|
231
|
+
|
|
232
|
+
Claude: Lists your credentials → you pick one (or add new keys)
|
|
233
|
+
→ fetches VPCs in your chosen region → you pick a VPC
|
|
234
|
+
→ proceeds with instance creation using your account
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Switch Organization
|
|
238
|
+
|
|
239
|
+
If you belong to multiple orgs:
|
|
240
|
+
|
|
241
|
+
```
|
|
242
|
+
You: "Switch to my other org"
|
|
243
|
+
|
|
244
|
+
Claude: Calls get_my_memberships → shows your orgs
|
|
245
|
+
→ you pick one → calls select_organization
|
|
246
|
+
→ rate limits and context update to the new org
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Re-authenticate (Switch Accounts)
|
|
250
|
+
|
|
251
|
+
If you need to sign in as a different user:
|
|
252
|
+
|
|
253
|
+
```
|
|
254
|
+
You: "Sign in with a different account"
|
|
255
|
+
|
|
256
|
+
Claude: Calls reauthenticate → clears stored credentials
|
|
257
|
+
→ opens browser for new login → saves new tokens
|
|
258
|
+
→ you're now signed in as the other user
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Restore from Backup
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
You: "Restore my prod database from yesterday's snapshot"
|
|
265
|
+
|
|
266
|
+
Claude: Lists snapshots → you pick one
|
|
267
|
+
→ creates a new instance with snapshot_id
|
|
268
|
+
→ shows you the new password (save it!)
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Rate Limiting
|
|
274
|
+
|
|
275
|
+
Rate limits are based on your org's billing plan and enforced per-user:
|
|
276
|
+
|
|
277
|
+
| Plan | Reads/min | Writes/min | Concurrent |
|
|
278
|
+
|------|-----------|------------|------------|
|
|
279
|
+
| Free | ~60 | ~20 | 3 |
|
|
280
|
+
| Starter | ~150 | ~50 | 5 |
|
|
281
|
+
| Pro | ~300 | ~120 | 10 |
|
|
282
|
+
| Enterprise | ~600 | ~300 | Unlimited |
|
|
283
|
+
|
|
284
|
+
Reference data lookups (regions, instance types, storage types) are unlimited.
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Configuration
|
|
289
|
+
|
|
290
|
+
### Environment Variables
|
|
291
|
+
|
|
292
|
+
| Variable | Default | Description |
|
|
293
|
+
|----------|---------|-------------|
|
|
294
|
+
| `API_URL` | `https://api.selfhost.dev` | SelfHost API endpoint |
|
|
295
|
+
| `CONSOLE_URL` | `https://console.selfhost.dev` | SelfHost Console URL (for browser auth) |
|
|
296
|
+
| `TIER` | Auto-detected | Override rate limit tier (`FREE`, `STARTER`, `PRO`, `ENTERPRISE`, `ADMIN`) |
|
|
297
|
+
| `FIREBASE_API_KEY` | — | Skip browser auth (CI/headless) |
|
|
298
|
+
| `FIREBASE_REFRESH_TOKEN` | — | Skip browser auth (CI/headless) |
|
|
299
|
+
|
|
300
|
+
### Local Development
|
|
301
|
+
|
|
302
|
+
Both `API_URL` and `CONSOLE_URL` are optional overrides — they default to the production endpoints when not set.
|
|
303
|
+
|
|
304
|
+
**1. Local Rails API + Local Console**
|
|
305
|
+
|
|
306
|
+
Using npx:
|
|
307
|
+
```json
|
|
308
|
+
{
|
|
309
|
+
"mcpServers": {
|
|
310
|
+
"selfhost": {
|
|
311
|
+
"command": "npx",
|
|
312
|
+
"args": ["tsx", "/path/to/selfhost-mcp/src/index.ts"],
|
|
313
|
+
"env": {
|
|
314
|
+
"API_URL": "http://localhost:3000",
|
|
315
|
+
"CONSOLE_URL": "http://localhost:54588"
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Using bun:
|
|
323
|
+
```json
|
|
324
|
+
{
|
|
325
|
+
"mcpServers": {
|
|
326
|
+
"selfhost": {
|
|
327
|
+
"command": "bun",
|
|
328
|
+
"args": ["run", "/path/to/selfhost-mcp/src/index.ts"],
|
|
329
|
+
"env": {
|
|
330
|
+
"API_URL": "http://localhost:3000",
|
|
331
|
+
"CONSOLE_URL": "http://localhost:54588"
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**2. Local Rails API + Production Console**
|
|
339
|
+
|
|
340
|
+
```json
|
|
341
|
+
{
|
|
342
|
+
"mcpServers": {
|
|
343
|
+
"selfhost": {
|
|
344
|
+
"command": "npx",
|
|
345
|
+
"args": ["tsx", "/path/to/selfhost-mcp/src/index.ts"],
|
|
346
|
+
"env": {
|
|
347
|
+
"API_URL": "http://localhost:3000"
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
**3. Production Rails API + Local Console**
|
|
355
|
+
|
|
356
|
+
```json
|
|
357
|
+
{
|
|
358
|
+
"mcpServers": {
|
|
359
|
+
"selfhost": {
|
|
360
|
+
"command": "npx",
|
|
361
|
+
"args": ["tsx", "/path/to/selfhost-mcp/src/index.ts"],
|
|
362
|
+
"env": {
|
|
363
|
+
"CONSOLE_URL": "http://localhost:54588"
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Headless / CI Mode
|
|
371
|
+
|
|
372
|
+
Set `FIREBASE_API_KEY` and `FIREBASE_REFRESH_TOKEN` environment variables to skip the browser login flow. You can find these values in `~/.selfhost/credentials.json` after your first browser login.
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Security
|
|
377
|
+
|
|
378
|
+
- **Credentials stored locally** at `~/.selfhost/credentials.json` with `chmod 0600` (owner-only read/write)
|
|
379
|
+
- **JWT auto-refresh** — tokens refresh 5 minutes before expiry, refresh tokens are rotated
|
|
380
|
+
- **Sensitive fields stripped** — passwords, AWS keys, tokens, and secrets are redacted from API responses
|
|
381
|
+
- **Destructive operations gated** — delete, stop, and reboot require explicit `confirm: true`
|
|
382
|
+
- **No console.log** — all logging goes to stderr to avoid corrupting the MCP JSON-RPC stream on stdout
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare function wasAuthPrompted(): Promise<boolean>;
|
|
2
|
+
export declare function markAuthPrompted(): Promise<void>;
|
|
3
|
+
/**
|
|
4
|
+
* Returns true if credentials are available (env vars or stored file).
|
|
5
|
+
* No network calls — just a fast file existence check.
|
|
6
|
+
*/
|
|
7
|
+
export declare function hasCredentials(): Promise<boolean>;
|
|
8
|
+
/**
|
|
9
|
+
* Returns a valid Firebase JWT, auto-refreshing if needed.
|
|
10
|
+
* Triggers browser login on first call if no credentials exist.
|
|
11
|
+
* Concurrent callers share the same in-flight auth promise.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getValidToken(): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Deletes stored credentials file, clears cache, then performs fresh browser login.
|
|
16
|
+
* Used by the `reauthenticate` tool to switch accounts or fix bad state.
|
|
17
|
+
*/
|
|
18
|
+
export declare function forceReauth(): Promise<void>;
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
import { access, readFile, writeFile, mkdir, unlink } from "node:fs/promises";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
import { config } from "./config.js";
|
|
5
|
+
const authPromptedPath = `${dirname(config.credentialsPath)}/.auth-prompted`;
|
|
6
|
+
export async function wasAuthPrompted() {
|
|
7
|
+
try {
|
|
8
|
+
await access(authPromptedPath);
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export async function markAuthPrompted() {
|
|
16
|
+
const dir = dirname(config.credentialsPath);
|
|
17
|
+
await mkdir(dir, { recursive: true });
|
|
18
|
+
await writeFile(authPromptedPath, new Date().toISOString(), { mode: 0o600 });
|
|
19
|
+
}
|
|
20
|
+
let cachedJwt = null;
|
|
21
|
+
let jwtExpiresAt = 0;
|
|
22
|
+
async function loadStoredCredentials() {
|
|
23
|
+
try {
|
|
24
|
+
const raw = await readFile(config.credentialsPath, "utf-8");
|
|
25
|
+
return JSON.parse(raw);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function saveCredentials(apiKey, refreshToken) {
|
|
32
|
+
const dir = dirname(config.credentialsPath);
|
|
33
|
+
await mkdir(dir, { recursive: true });
|
|
34
|
+
const data = {
|
|
35
|
+
firebaseApiKey: apiKey,
|
|
36
|
+
firebaseRefreshToken: refreshToken,
|
|
37
|
+
savedAt: new Date().toISOString(),
|
|
38
|
+
};
|
|
39
|
+
await writeFile(config.credentialsPath, JSON.stringify(data, null, 2), { mode: 0o600 });
|
|
40
|
+
// Clear auth-prompted marker since we now have valid credentials
|
|
41
|
+
try {
|
|
42
|
+
await unlink(authPromptedPath);
|
|
43
|
+
}
|
|
44
|
+
catch { /* ok */ }
|
|
45
|
+
}
|
|
46
|
+
async function refreshJwt(apiKey, refreshToken) {
|
|
47
|
+
const url = `https://securetoken.googleapis.com/v1/token?key=${apiKey}`;
|
|
48
|
+
const res = await fetch(url, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
51
|
+
body: `grant_type=refresh_token&refresh_token=${encodeURIComponent(refreshToken)}`,
|
|
52
|
+
});
|
|
53
|
+
if (!res.ok) {
|
|
54
|
+
const body = await res.text();
|
|
55
|
+
throw new Error(`Firebase token refresh failed (${res.status}): ${body}`);
|
|
56
|
+
}
|
|
57
|
+
const data = (await res.json());
|
|
58
|
+
return {
|
|
59
|
+
jwt: data.id_token,
|
|
60
|
+
newRefreshToken: data.refresh_token,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
async function browserLogin() {
|
|
64
|
+
const open = (await import("open")).default;
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
66
|
+
const server = createServer((req, res) => {
|
|
67
|
+
const url = new URL(req.url, `http://localhost`);
|
|
68
|
+
if (url.pathname === "/callback") {
|
|
69
|
+
const refreshToken = url.searchParams.get("refresh_token");
|
|
70
|
+
const apiKey = url.searchParams.get("api_key");
|
|
71
|
+
if (!refreshToken || !apiKey) {
|
|
72
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
73
|
+
res.end("<h1>Missing parameters</h1><p>refresh_token and api_key are required.</p>");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
77
|
+
res.end("<h1>Authorization complete!</h1><p>You can close this tab and return to Claude Code.</p>");
|
|
78
|
+
server.close();
|
|
79
|
+
clearTimeout(timeout);
|
|
80
|
+
resolve({ apiKey, refreshToken });
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
// Find available port
|
|
84
|
+
server.listen(0, "127.0.0.1", () => {
|
|
85
|
+
const addr = server.address();
|
|
86
|
+
if (!addr || typeof addr === "string") {
|
|
87
|
+
reject(new Error("Failed to get server address"));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const port = addr.port;
|
|
91
|
+
const authUrl = `${config.consoleUrl}/mcp-auth?port=${port}`;
|
|
92
|
+
config.log(`Opening browser for authentication: ${authUrl}`);
|
|
93
|
+
open(authUrl);
|
|
94
|
+
});
|
|
95
|
+
// 2 minute timeout
|
|
96
|
+
const timeout = setTimeout(() => {
|
|
97
|
+
server.close();
|
|
98
|
+
reject(new Error("Browser login timed out after 2 minutes. Please try again."));
|
|
99
|
+
}, 120_000);
|
|
100
|
+
server.on("error", (err) => {
|
|
101
|
+
clearTimeout(timeout);
|
|
102
|
+
reject(err);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Ensures credentials exist (from .env, stored file, or browser login).
|
|
108
|
+
* Returns { apiKey, refreshToken }.
|
|
109
|
+
*/
|
|
110
|
+
async function resolveCredentials() {
|
|
111
|
+
// Priority 1: .env vars (headless/CI)
|
|
112
|
+
if (config.firebaseApiKey && config.firebaseRefreshToken) {
|
|
113
|
+
return {
|
|
114
|
+
apiKey: config.firebaseApiKey,
|
|
115
|
+
refreshToken: config.firebaseRefreshToken,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
// Priority 2: Stored credentials file
|
|
119
|
+
const stored = await loadStoredCredentials();
|
|
120
|
+
if (stored) {
|
|
121
|
+
return {
|
|
122
|
+
apiKey: stored.firebaseApiKey,
|
|
123
|
+
refreshToken: stored.firebaseRefreshToken,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
// Priority 3: Browser login
|
|
127
|
+
const creds = await browserLogin();
|
|
128
|
+
await saveCredentials(creds.apiKey, creds.refreshToken);
|
|
129
|
+
return creds;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Returns true if credentials are available (env vars or stored file).
|
|
133
|
+
* No network calls — just a fast file existence check.
|
|
134
|
+
*/
|
|
135
|
+
export async function hasCredentials() {
|
|
136
|
+
if (config.firebaseApiKey && config.firebaseRefreshToken)
|
|
137
|
+
return true;
|
|
138
|
+
return (await loadStoredCredentials()) !== null;
|
|
139
|
+
}
|
|
140
|
+
let authInProgress = null;
|
|
141
|
+
/**
|
|
142
|
+
* Returns a valid Firebase JWT, auto-refreshing if needed.
|
|
143
|
+
* Triggers browser login on first call if no credentials exist.
|
|
144
|
+
* Concurrent callers share the same in-flight auth promise.
|
|
145
|
+
*/
|
|
146
|
+
export async function getValidToken() {
|
|
147
|
+
if (authInProgress)
|
|
148
|
+
return authInProgress;
|
|
149
|
+
authInProgress = _getValidTokenImpl();
|
|
150
|
+
try {
|
|
151
|
+
return await authInProgress;
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
authInProgress = null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async function _getValidTokenImpl() {
|
|
158
|
+
// Return cached JWT if still valid (5 min buffer)
|
|
159
|
+
const now = Date.now();
|
|
160
|
+
if (cachedJwt && jwtExpiresAt - now > 5 * 60 * 1000) {
|
|
161
|
+
return cachedJwt;
|
|
162
|
+
}
|
|
163
|
+
const creds = await resolveCredentials();
|
|
164
|
+
try {
|
|
165
|
+
const { jwt, newRefreshToken } = await refreshJwt(creds.apiKey, creds.refreshToken);
|
|
166
|
+
cachedJwt = jwt;
|
|
167
|
+
jwtExpiresAt = now + 3600 * 1000;
|
|
168
|
+
await saveCredentials(creds.apiKey, newRefreshToken);
|
|
169
|
+
return jwt;
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
// Refresh token expired — re-authenticate via browser
|
|
173
|
+
cachedJwt = null;
|
|
174
|
+
jwtExpiresAt = 0;
|
|
175
|
+
const newCreds = await browserLogin();
|
|
176
|
+
await saveCredentials(newCreds.apiKey, newCreds.refreshToken);
|
|
177
|
+
const { jwt, newRefreshToken } = await refreshJwt(newCreds.apiKey, newCreds.refreshToken);
|
|
178
|
+
cachedJwt = jwt;
|
|
179
|
+
jwtExpiresAt = Date.now() + 3600 * 1000;
|
|
180
|
+
await saveCredentials(newCreds.apiKey, newRefreshToken);
|
|
181
|
+
return jwt;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Deletes stored credentials file, clears cache, then performs fresh browser login.
|
|
186
|
+
* Used by the `reauthenticate` tool to switch accounts or fix bad state.
|
|
187
|
+
*/
|
|
188
|
+
export async function forceReauth() {
|
|
189
|
+
cachedJwt = null;
|
|
190
|
+
jwtExpiresAt = 0;
|
|
191
|
+
try {
|
|
192
|
+
await unlink(config.credentialsPath);
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// File may not exist — that's fine
|
|
196
|
+
}
|
|
197
|
+
const creds = await browserLogin();
|
|
198
|
+
await saveCredentials(creds.apiKey, creds.refreshToken);
|
|
199
|
+
const { jwt, newRefreshToken } = await refreshJwt(creds.apiKey, creds.refreshToken);
|
|
200
|
+
cachedJwt = jwt;
|
|
201
|
+
jwtExpiresAt = Date.now() + 3600 * 1000;
|
|
202
|
+
await saveCredentials(creds.apiKey, newRefreshToken);
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ClientResult, HttpMethod } from "./types/api.js";
|
|
2
|
+
interface RequestOptions {
|
|
3
|
+
method?: HttpMethod;
|
|
4
|
+
body?: Record<string, unknown>;
|
|
5
|
+
query?: Record<string, string | undefined>;
|
|
6
|
+
toolName?: string;
|
|
7
|
+
skipOrgInjection?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function apiRequest<T>(path: string, options?: RequestOptions): Promise<ClientResult<T>>;
|
|
10
|
+
export {};
|