backpack-ontology 0.2.1 → 0.2.3

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.
Files changed (47) hide show
  1. package/README.md +78 -139
  2. package/dist/auth/oauth.d.ts +32 -0
  3. package/dist/auth/oauth.d.ts.map +1 -0
  4. package/dist/auth/oauth.js +208 -0
  5. package/dist/auth/oauth.js.map +1 -0
  6. package/dist/bin/backpack-app.js +17 -7
  7. package/dist/bin/backpack-app.js.map +1 -1
  8. package/dist/bin/backpack-sync.d.ts +3 -0
  9. package/dist/bin/backpack-sync.d.ts.map +1 -0
  10. package/dist/bin/backpack-sync.js +148 -0
  11. package/dist/bin/backpack-sync.js.map +1 -0
  12. package/dist/bin/backpack.js +3 -0
  13. package/dist/bin/backpack.js.map +1 -1
  14. package/dist/bin/init.js +12 -79
  15. package/dist/bin/init.js.map +1 -1
  16. package/dist/core/backpack.d.ts +1 -0
  17. package/dist/core/backpack.d.ts.map +1 -1
  18. package/dist/core/backpack.js +9 -0
  19. package/dist/core/backpack.js.map +1 -1
  20. package/dist/core/hooks.d.ts +6 -0
  21. package/dist/core/hooks.d.ts.map +1 -0
  22. package/dist/core/hooks.js +68 -0
  23. package/dist/core/hooks.js.map +1 -0
  24. package/dist/core/types.d.ts +1 -0
  25. package/dist/core/types.d.ts.map +1 -1
  26. package/dist/mcp/server.d.ts +11 -3
  27. package/dist/mcp/server.d.ts.map +1 -1
  28. package/dist/mcp/server.js +19 -5
  29. package/dist/mcp/server.js.map +1 -1
  30. package/dist/mcp/tools/bulk-tools.js +1 -1
  31. package/dist/mcp/tools/bulk-tools.js.map +1 -1
  32. package/dist/mcp/tools/edge-tools.js +3 -3
  33. package/dist/mcp/tools/edge-tools.js.map +1 -1
  34. package/dist/mcp/tools/node-tools.js +7 -7
  35. package/dist/mcp/tools/node-tools.js.map +1 -1
  36. package/dist/mcp/tools/ontology-tools.js +5 -5
  37. package/dist/mcp/tools/ontology-tools.js.map +1 -1
  38. package/dist/storage/backpack-app-backend.d.ts +5 -5
  39. package/dist/storage/backpack-app-backend.d.ts.map +1 -1
  40. package/dist/storage/backpack-app-backend.js +16 -10
  41. package/dist/storage/backpack-app-backend.js.map +1 -1
  42. package/dist/storage/json-file-backend.d.ts +1 -0
  43. package/dist/storage/json-file-backend.d.ts.map +1 -1
  44. package/dist/storage/json-file-backend.js +16 -0
  45. package/dist/storage/json-file-backend.js.map +1 -1
  46. package/hooks/hooks.json +2 -2
  47. package/package.json +2 -1
package/README.md CHANGED
@@ -1,198 +1,137 @@
1
- # Backpack Ontology
1
+ # Backpack
2
2
 
3
- A persistent knowledge graph engine for Claude Code, delivered as an MCP server. Backpack gives AI agents structured, searchable memory that persists across sessions.
3
+ **Give your AI a memory it can actually use.** Backpack lets Claude remember what matters your clients, your processes, your decisions across every conversation.
4
4
 
5
- ## Installation
5
+ ## What it does
6
6
 
7
- ```bash
8
- npm install -g backpack-ontology
9
- ```
10
-
11
- ## Setup
12
-
13
- Add Backpack to your Claude Code project (`.mcp.json`):
14
-
15
- ```json
16
- {
17
- "mcpServers": {
18
- "backpack": {
19
- "command": "npx",
20
- "args": ["backpack-ontology"]
21
- }
22
- }
23
- }
24
- ```
25
-
26
- Or register it globally:
7
+ When you're working with Claude and something worth remembering comes up — a relationship, a project decision, a workflow, a domain concept — Backpack saves it as a structured knowledge graph. Next time you ask, Claude already knows.
27
8
 
28
- ```bash
29
- claude mcp add backpack -- npx backpack-ontology
30
9
  ```
10
+ You: "We just signed Acme Corp, they're on the Enterprise tier, main contact is Sarah Chen"
31
11
 
32
- Restart Claude Code to activate.
12
+ Claude: [saves to backpack → clients ontology]
33
13
 
34
- ## Usage
14
+ --- weeks later, different conversation ---
35
15
 
36
- Backpack organizes knowledge as typed graphs nodes (entities) connected by edges (relationships). There are no enforced schemas. The LLM decides what structure fits the domain.
16
+ You: "What do we know about Acme Corp?"
37
17
 
18
+ Claude: "Acme Corp is on the Enterprise tier, main contact is Sarah Chen..."
38
19
  ```
39
- [Ingredient: garlic] --USED_IN--> [Recipe: Aglio e Olio]
40
- [Module: auth] --DEPENDS_ON--> [Module: database]
41
- ```
42
-
43
- Tell Claude what to store:
44
20
 
45
- > "Create an ontology about our codebase architecture"
21
+ No copy-pasting. No re-explaining. Your knowledge carries forward.
46
22
 
47
- > "Search the backpack for anything related to authentication"
23
+ ## Get started
48
24
 
49
- > "Add the deployment pipeline to the infrastructure ontology"
25
+ Tell Claude to set up Backpack:
50
26
 
51
- ### Progressive Discovery
27
+ > "Add backpack to this project"
52
28
 
53
- Tools are organized in layers so the context window stays clean. Claude starts broad and drills down — only pulling in what it needs.
29
+ Claude will configure the MCP server for you. Restart Claude Code and you're ready.
54
30
 
55
- | Layer | Tools | Returns |
56
- |-------|-------|---------|
57
- | **Discover** | `backpack_list`, `backpack_create`, `backpack_describe` | Ontology names, descriptions, type counts |
58
- | **Browse** | `backpack_list_nodes`, `backpack_node_types`, `backpack_search` | Paginated node summaries (id, type, label) |
59
- | **Inspect** | `backpack_get_node`, `backpack_get_neighbors` | Full node data, graph traversal |
60
- | **Mutate** | `backpack_add_node`, `backpack_update_node`, `backpack_add_edge`, ... | Create and modify data |
31
+ Or set it up yourself pick local or cloud:
61
32
 
62
- ## Tools Reference
33
+ | Mode | Setup command |
34
+ |---|---|
35
+ | **Local** (free, private, on your machine) | `claude mcp add backpack -- npx backpack-ontology` |
36
+ | **Backpack App** (free account, cloud sync) | `claude mcp add backpack-app -- npx backpack-app` |
63
37
 
64
- ### Discovery
38
+ Backpack App syncs your knowledge across devices and gives you access to the web-based graph visualizer at [app.backpackontology.com](https://app.backpackontology.com). On first run, a browser window opens for sign-in — after that, it's automatic.
65
39
 
66
- | Tool | Description |
67
- |------|-------------|
68
- | `backpack_list` | List all ontologies with names, descriptions, and summary counts |
69
- | `backpack_create` | Create a new empty ontology |
70
- | `backpack_delete` | Permanently delete an ontology and all its data |
71
- | `backpack_describe` | Inspect ontology structure: node types, edge types, counts |
40
+ ## What to say to Claude
72
41
 
73
- ### Browsing
42
+ You don't need to learn commands or tools. Just talk to Claude naturally. Here's what you can do:
74
43
 
75
- | Tool | Description |
76
- |------|-------------|
77
- | `backpack_node_types` | List distinct node types with counts |
78
- | `backpack_list_nodes` | Paginated node summaries, optionally filtered by type |
79
- | `backpack_search` | Case-insensitive text search across all node properties |
44
+ ### Remember something
80
45
 
81
- ### Inspection
46
+ > "Remember that Acme Corp is on the Enterprise tier, main contact is Sarah Chen"
82
47
 
83
- | Tool | Description |
84
- |------|-------------|
85
- | `backpack_get_node` | Full node with all properties and connected edge summaries |
86
- | `backpack_get_neighbors` | BFS graph traversal from a node (max depth 3) |
48
+ > "Add our new vendor agreement details to backpack"
87
49
 
88
- ### Mutation
50
+ > "Start an ontology for our hiring process"
89
51
 
90
- | Tool | Description |
91
- |------|-------------|
92
- | `backpack_add_node` | Add a node with a freeform type and properties |
93
- | `backpack_update_node` | Merge new properties into an existing node |
94
- | `backpack_remove_node` | Remove a node and cascade-delete its edges |
95
- | `backpack_add_edge` | Create a typed relationship between two nodes |
96
- | `backpack_remove_edge` | Remove a relationship |
97
- | `backpack_import_nodes` | Bulk-add multiple nodes in a single operation |
52
+ ### Find something
98
53
 
99
- ## Programmatic API
54
+ > "What's in my backpack about Acme Corp?"
100
55
 
101
- The core engine has no MCP dependency and can be used as a library:
56
+ > "Search backpack for anything related to compliance"
102
57
 
103
- ```typescript
104
- import { Backpack, JsonFileBackend } from "backpack-ontology";
58
+ > "What do we know about the deployment process?"
105
59
 
106
- const backpack = new Backpack(new JsonFileBackend());
107
- await backpack.initialize();
60
+ ### See the big picture
108
61
 
109
- await backpack.createOntology("my-graph", "A knowledge graph");
110
- const node = await backpack.addNode("my-graph", "Person", { name: "Alice" });
111
- await backpack.addEdge("my-graph", "KNOWS", node.id, otherNodeId);
62
+ > "Show me my knowledge graph"
112
63
 
113
- // Search across all node properties (case-insensitive)
114
- const results = await backpack.searchNodes("my-graph", "alice");
64
+ > "What's in my backpack?"
115
65
 
116
- // BFS traversal from a node (depth 1–3)
117
- const neighbors = await backpack.getNeighbors("my-graph", node.id, undefined, "both", 2);
118
- ```
66
+ > "Describe the clients ontology"
119
67
 
120
- ### Pluggable Storage
68
+ Claude will open the graph visualizer so you can explore your knowledge visually.
121
69
 
122
- The `StorageBackend` interface allows custom persistence implementations:
70
+ ### Move to the cloud
123
71
 
124
- ```typescript
125
- import { Backpack, StorageBackend } from "backpack-ontology";
72
+ > "Sync my backpack to the cloud"
126
73
 
127
- class SqliteBackend implements StorageBackend {
128
- // initialize, listOntologies, loadOntology, saveOntology,
129
- // createOntology, deleteOntology, ontologyExists
130
- }
74
+ > "Upload my local ontologies to Backpack App"
131
75
 
132
- const backpack = new Backpack(new SqliteBackend());
133
- ```
76
+ Claude will migrate your local knowledge to Backpack App so you can access it from any device.
134
77
 
135
- ## Data Storage
78
+ ## What people use it for
136
79
 
137
- Backpack follows the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/latest/):
80
+ - **Client management** keep track of accounts, contacts, contract details, and conversations across sessions
81
+ - **Process documentation** — capture how things are done so Claude can help consistently
82
+ - **Project knowledge** — architecture decisions, vendor relationships, compliance requirements
83
+ - **Domain expertise** — industry terminology, regulatory frameworks, best practices
84
+ - **Team onboarding** — new team members get Claude with your organization's context already loaded
138
85
 
139
- ```
140
- ~/.local/share/backpack/ontologies/
141
- ├── cooking/
142
- │ └── ontology.json
143
- └── codebase-arch/
144
- └── ontology.json
145
- ```
86
+ ## How it works
146
87
 
147
- Ontology files are human-readable JSON. They can be inspected, edited, backed up, or version-controlled directly.
88
+ You have one backpack — it goes everywhere with you. Inside it, you organize knowledge into **ontologies**, each one covering a different topic (clients, processes, compliance, etc.). Within each ontology, information is stored as things connected by relationships. You don't need to think about the structure. Claude handles it automatically based on what you're discussing.
148
89
 
149
- | Variable | Effect |
150
- |----------|--------|
151
- | `XDG_DATA_HOME` | Override data location (default: `~/.local/share`) |
152
- | `XDG_CONFIG_HOME` | Override config location (default: `~/.config`) |
153
- | `BACKPACK_DIR` | Override both — config at `$BACKPACK_DIR/config`, data at `$BACKPACK_DIR/data` |
90
+ ## Data and privacy
154
91
 
155
- ## Telemetry
92
+ **Local mode**: Your data is stored as readable JSON files on your computer at `~/.local/share/backpack/ontologies/`. You can inspect, edit, back up, or version-control these files directly.
156
93
 
157
- Backpack collects anonymous usage telemetry to improve the product. No personal data, ontology content, or tool arguments are ever collected.
94
+ **Backpack App**: Your data is stored securely in our cloud infrastructure. See our [privacy policy](https://backpackontology.com/privacy) for details.
158
95
 
159
- **What is collected:**
160
- - Tool call counts (which tools are used, not what data is passed)
161
- - Session duration
162
- - Aggregate ontology statistics (total node/edge counts, not names or content)
163
- - Runtime environment (Node.js version, OS, platform)
96
+ **Telemetry**: Backpack collects anonymous usage statistics (which tools are used, session duration) to improve the product. No content, names, or personal data is ever collected. Opt out with `DO_NOT_TRACK=1`.
164
97
 
165
- **What is never collected:**
166
- - Ontology names, descriptions, or content
167
- - Node or edge properties
168
- - File paths or user identifiers
169
- - Tool arguments or query strings
98
+ ## Reference
170
99
 
171
- **To opt out**, use any of the following:
100
+ ### CLI commands
172
101
 
173
- ```bash
174
- # Environment variable (standard)
175
- export DO_NOT_TRACK=1
102
+ | Command | What it does |
103
+ |---|---|
104
+ | `npx backpack-ontology` | Start the local MCP server |
105
+ | `npx backpack-app` | Start the Backpack App MCP server (cloud) |
106
+ | `npx backpack-sync` | Upload local ontologies to Backpack App |
107
+ | `npx backpack-viewer` | Open the graph visualizer (http://localhost:5173) |
108
+ | `npx backpack-init` | Reinstall auto-capture hooks if removed |
176
109
 
177
- # Backpack-specific environment variable
178
- export BACKPACK_TELEMETRY_DISABLED=1
179
- ```
110
+ ### Tools
180
111
 
181
- Or add to `~/.config/backpack/config.json`:
112
+ Claude uses these automatically — you don't need to call them directly.
182
113
 
183
- ```json
184
- {
185
- "telemetry": false
186
- }
187
- ```
114
+ | What Claude does | How |
115
+ |---|---|
116
+ | See what's in the backpack | `backpack_list`, `backpack_describe` |
117
+ | Add a new ontology to the backpack | `backpack_create` |
118
+ | Find something in the backpack | `backpack_search`, `backpack_list_nodes` |
119
+ | Get full details on an item | `backpack_get_node`, `backpack_get_neighbors` |
120
+ | Add or update knowledge | `backpack_add_node`, `backpack_update_node`, `backpack_add_edge` |
121
+ | Bulk import | `backpack_import_nodes` |
122
+ | Clean up | `backpack_remove_node`, `backpack_remove_edge`, `backpack_delete` |
188
123
 
189
- ## Visualization
124
+ ### Advanced configuration
190
125
 
191
- Use [backpack-viewer](https://www.npmjs.com/package/backpack-viewer) to visualize ontologies in a web-based graph explorer with force-directed layout and live reload.
126
+ | Variable | Effect |
127
+ |---|---|
128
+ | `XDG_DATA_HOME` | Change local data location (default: `~/.local/share`) |
129
+ | `BACKPACK_DIR` | Override all Backpack directories |
130
+ | `DO_NOT_TRACK` | Disable anonymous telemetry |
192
131
 
193
132
  ## Support
194
133
 
195
- For questions, feedback, or sponsorship inquiries: **support@backpackontology.com**
134
+ Questions, feedback, or partnership inquiries: **support@backpackontology.com**
196
135
 
197
136
  ## License
198
137
 
@@ -0,0 +1,32 @@
1
+ /**
2
+ * OAuth2 authorization code flow with PKCE for CLI/MCP clients.
3
+ *
4
+ * On first run: opens the browser → user signs in via Entra → callback
5
+ * captures the code → exchanges for tokens → caches to disk.
6
+ *
7
+ * On subsequent runs: uses cached token, refreshes if expired.
8
+ */
9
+ export declare class OAuthClient {
10
+ private clientId;
11
+ private issuerUrl;
12
+ private tokenCachePath;
13
+ private cachedToken;
14
+ private endpoints;
15
+ constructor(clientId: string, issuerUrl: string, cacheKey: string);
16
+ /** Returns a valid token for Bearer auth, refreshing or re-authenticating as needed. */
17
+ getAccessToken(): Promise<string>;
18
+ /**
19
+ * Prefer id_token for Bearer auth. Entra CIAM access tokens have
20
+ * Microsoft Graph as the audience, which oauth2-proxy won't accept.
21
+ * The id_token has the correct issuer and audience (our client ID).
22
+ */
23
+ private getBearerToken;
24
+ private discoverEndpoints;
25
+ private authorize;
26
+ private refreshToken;
27
+ private startCallbackServer;
28
+ private openBrowser;
29
+ private loadCachedToken;
30
+ private saveToken;
31
+ }
32
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"AAmBA;;;;;;;GAOG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,WAAW,CAA0B;IAC7C,OAAO,CAAC,SAAS,CAA8B;gBAEnC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAMjE,wFAAwF;IAClF,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IA0BvC;;;;OAIG;IACH,OAAO,CAAC,cAAc;YAIR,iBAAiB;YAQjB,SAAS;YA4DT,YAAY;IAyB1B,OAAO,CAAC,mBAAmB;IAqD3B,OAAO,CAAC,WAAW;YAiBL,eAAe;YASf,SAAS;CAQxB"}
@@ -0,0 +1,208 @@
1
+ import * as crypto from "node:crypto";
2
+ import * as http from "node:http";
3
+ import * as fs from "node:fs/promises";
4
+ import * as path from "node:path";
5
+ import { exec } from "node:child_process";
6
+ import { configDir } from "../core/paths.js";
7
+ /**
8
+ * OAuth2 authorization code flow with PKCE for CLI/MCP clients.
9
+ *
10
+ * On first run: opens the browser → user signs in via Entra → callback
11
+ * captures the code → exchanges for tokens → caches to disk.
12
+ *
13
+ * On subsequent runs: uses cached token, refreshes if expired.
14
+ */
15
+ export class OAuthClient {
16
+ clientId;
17
+ issuerUrl;
18
+ tokenCachePath;
19
+ cachedToken = null;
20
+ endpoints = null;
21
+ constructor(clientId, issuerUrl, cacheKey) {
22
+ this.clientId = clientId;
23
+ this.issuerUrl = issuerUrl.replace(/\/+$/, "");
24
+ this.tokenCachePath = path.join(configDir(), "app-tokens", `${cacheKey}.json`);
25
+ }
26
+ /** Returns a valid token for Bearer auth, refreshing or re-authenticating as needed. */
27
+ async getAccessToken() {
28
+ if (!this.cachedToken) {
29
+ this.cachedToken = await this.loadCachedToken();
30
+ }
31
+ if (this.cachedToken) {
32
+ // Still valid (with 60s buffer)
33
+ if (this.cachedToken.expires_at > Date.now() / 1000 + 60) {
34
+ return this.getBearerToken();
35
+ }
36
+ // Try refresh
37
+ if (this.cachedToken.refresh_token) {
38
+ try {
39
+ await this.refreshToken(this.cachedToken.refresh_token);
40
+ return this.getBearerToken();
41
+ }
42
+ catch {
43
+ console.error("Token refresh failed, re-authenticating...");
44
+ }
45
+ }
46
+ }
47
+ // Full browser-based authorization
48
+ await this.authorize();
49
+ return this.getBearerToken();
50
+ }
51
+ /**
52
+ * Prefer id_token for Bearer auth. Entra CIAM access tokens have
53
+ * Microsoft Graph as the audience, which oauth2-proxy won't accept.
54
+ * The id_token has the correct issuer and audience (our client ID).
55
+ */
56
+ getBearerToken() {
57
+ return this.cachedToken.id_token ?? this.cachedToken.access_token;
58
+ }
59
+ async discoverEndpoints() {
60
+ if (this.endpoints)
61
+ return this.endpoints;
62
+ const res = await fetch(`${this.issuerUrl}/.well-known/openid-configuration`);
63
+ if (!res.ok)
64
+ throw new Error(`OIDC discovery failed: ${res.status}`);
65
+ this.endpoints = (await res.json());
66
+ return this.endpoints;
67
+ }
68
+ async authorize() {
69
+ const endpoints = await this.discoverEndpoints();
70
+ // PKCE
71
+ const codeVerifier = crypto.randomBytes(32).toString("base64url");
72
+ const codeChallenge = crypto
73
+ .createHash("sha256")
74
+ .update(codeVerifier)
75
+ .digest("base64url");
76
+ // Start a temporary callback server on a random port
77
+ const { port, codePromise } = await this.startCallbackServer();
78
+ const redirectUri = `http://localhost:${port}`;
79
+ const params = new URLSearchParams({
80
+ client_id: this.clientId,
81
+ response_type: "code",
82
+ redirect_uri: redirectUri,
83
+ scope: "openid email profile offline_access",
84
+ code_challenge: codeChallenge,
85
+ code_challenge_method: "S256",
86
+ });
87
+ const authUrl = `${endpoints.authorization_endpoint}?${params}`;
88
+ console.error("Opening browser for sign-in...");
89
+ await this.openBrowser(authUrl);
90
+ // Block until the user completes sign-in (or 120s timeout)
91
+ const code = await codePromise;
92
+ // Exchange authorization code for tokens
93
+ const tokenRes = await fetch(endpoints.token_endpoint, {
94
+ method: "POST",
95
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
96
+ body: new URLSearchParams({
97
+ client_id: this.clientId,
98
+ grant_type: "authorization_code",
99
+ code,
100
+ redirect_uri: redirectUri,
101
+ code_verifier: codeVerifier,
102
+ }),
103
+ });
104
+ if (!tokenRes.ok) {
105
+ const body = await tokenRes.text();
106
+ throw new Error(`Token exchange failed (${tokenRes.status}): ${body}`);
107
+ }
108
+ const data = (await tokenRes.json());
109
+ this.cachedToken = {
110
+ access_token: data.access_token,
111
+ refresh_token: data.refresh_token,
112
+ expires_at: Date.now() / 1000 + (data.expires_in ?? 3600),
113
+ id_token: data.id_token,
114
+ };
115
+ await this.saveToken(this.cachedToken);
116
+ console.error("Authenticated successfully.");
117
+ }
118
+ async refreshToken(refreshToken) {
119
+ const endpoints = await this.discoverEndpoints();
120
+ const res = await fetch(endpoints.token_endpoint, {
121
+ method: "POST",
122
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
123
+ body: new URLSearchParams({
124
+ client_id: this.clientId,
125
+ grant_type: "refresh_token",
126
+ refresh_token: refreshToken,
127
+ }),
128
+ });
129
+ if (!res.ok)
130
+ throw new Error(`Refresh failed: ${res.status}`);
131
+ const data = (await res.json());
132
+ this.cachedToken = {
133
+ access_token: data.access_token,
134
+ refresh_token: data.refresh_token ?? refreshToken,
135
+ expires_at: Date.now() / 1000 + (data.expires_in ?? 3600),
136
+ id_token: data.id_token,
137
+ };
138
+ await this.saveToken(this.cachedToken);
139
+ }
140
+ startCallbackServer() {
141
+ return new Promise((resolve) => {
142
+ const server = http.createServer();
143
+ const codePromise = new Promise((resolveCode, rejectCode) => {
144
+ const timeout = setTimeout(() => {
145
+ server.close();
146
+ rejectCode(new Error("Authentication timed out (120s)"));
147
+ }, 120_000);
148
+ server.on("request", (req, res) => {
149
+ const url = new URL(req.url, "http://localhost");
150
+ const code = url.searchParams.get("code");
151
+ const error = url.searchParams.get("error");
152
+ const errorDesc = url.searchParams.get("error_description");
153
+ if (error) {
154
+ res.writeHead(200, { "Content-Type": "text/html" });
155
+ res.end("<html><body><h1>Authentication failed</h1><p>You can close this tab.</p></body></html>");
156
+ clearTimeout(timeout);
157
+ server.close();
158
+ rejectCode(new Error(`OAuth error: ${error} — ${errorDesc}`));
159
+ return;
160
+ }
161
+ if (code) {
162
+ res.writeHead(200, { "Content-Type": "text/html" });
163
+ res.end("<html><body><h1>Signed in to Backpack</h1><p>You can close this tab.</p></body></html>");
164
+ clearTimeout(timeout);
165
+ server.close();
166
+ resolveCode(code);
167
+ return;
168
+ }
169
+ res.writeHead(400);
170
+ res.end();
171
+ });
172
+ });
173
+ server.listen(0, "127.0.0.1", () => {
174
+ const addr = server.address();
175
+ resolve({ port: addr.port, codePromise });
176
+ });
177
+ });
178
+ }
179
+ openBrowser(url) {
180
+ const cmd = process.platform === "darwin"
181
+ ? "open"
182
+ : process.platform === "win32"
183
+ ? "start"
184
+ : "xdg-open";
185
+ return new Promise((resolve) => {
186
+ exec(`${cmd} "${url}"`, (err) => {
187
+ if (err) {
188
+ console.error(`Could not open browser. Please visit:\n${url}`);
189
+ }
190
+ resolve();
191
+ });
192
+ });
193
+ }
194
+ async loadCachedToken() {
195
+ try {
196
+ const raw = await fs.readFile(this.tokenCachePath, "utf-8");
197
+ return JSON.parse(raw);
198
+ }
199
+ catch {
200
+ return null;
201
+ }
202
+ }
203
+ async saveToken(token) {
204
+ await fs.mkdir(path.dirname(this.tokenCachePath), { recursive: true });
205
+ await fs.writeFile(this.tokenCachePath, JSON.stringify(token, null, 2), "utf-8");
206
+ }
207
+ }
208
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
3
  import { createMcpServer } from "../mcp/server.js";
4
+ import { ensureHooksInstalled } from "../core/hooks.js";
4
5
  import { shutdown as shutdownTelemetry } from "../core/telemetry.js";
6
+ // Production defaults — users never need to configure these.
7
+ // Env vars override for development/testing only.
8
+ const DEFAULTS = {
9
+ url: "https://app.backpackontology.com",
10
+ clientId: "YOUR_ENTRA_CLIENT_ID_HERE",
11
+ issuerUrl: "https://YOUR_TENANT.ciamlogin.com/YOUR_TENANT_ID/v2.0",
12
+ };
5
13
  async function main() {
6
- const apiUrl = process.env.BACKPACK_APP_URL;
7
- const apiToken = process.env.BACKPACK_APP_TOKEN;
8
- if (!apiUrl || !apiToken) {
9
- console.error("Required env vars: BACKPACK_APP_URL, BACKPACK_APP_TOKEN");
10
- process.exit(1);
11
- }
12
- const server = await createMcpServer({ mode: "app", url: apiUrl, token: apiToken });
14
+ // Install hooks on first run (silent, non-blocking)
15
+ ensureHooksInstalled().catch(() => { });
16
+ const apiUrl = process.env.BACKPACK_APP_URL || DEFAULTS.url;
17
+ const clientId = process.env.BACKPACK_APP_CLIENT_ID || DEFAULTS.clientId;
18
+ const issuerUrl = process.env.BACKPACK_APP_ISSUER_URL || DEFAULTS.issuerUrl;
19
+ const staticToken = process.env.BACKPACK_APP_TOKEN;
20
+ const server = await createMcpServer(staticToken
21
+ ? { mode: "app", url: apiUrl, token: staticToken }
22
+ : { mode: "app", url: apiUrl, clientId, issuerUrl });
13
23
  const transport = new StdioServerTransport();
14
24
  await server.connect(transport);
15
25
  console.error(`Backpack App MCP server running on stdio (${apiUrl})`);
@@ -1 +1 @@
1
- {"version":3,"file":"backpack-app.js","sourceRoot":"","sources":["../../src/bin/backpack-app.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAErE,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAEhD,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;QACzE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACpF,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,OAAO,CAAC,KAAK,CAAC,6CAA6C,MAAM,GAAG,CAAC,CAAC;AACxE,CAAC;AAED,KAAK,UAAU,gBAAgB;IAC7B,MAAM,iBAAiB,EAAE,CAAC;IAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;AACvC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;AAExC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"backpack-app.js","sourceRoot":"","sources":["../../src/bin/backpack-app.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAErE,6DAA6D;AAC7D,kDAAkD;AAClD,MAAM,QAAQ,GAAG;IACf,GAAG,EAAE,kCAAkC;IACvC,QAAQ,EAAE,2BAA2B;IACrC,SAAS,EAAE,uDAAuD;CACnE,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,oDAAoD;IACpD,oBAAoB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAEvC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,QAAQ,CAAC,GAAG,CAAC;IAC5D,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,QAAQ,CAAC,QAAQ,CAAC;IACzE,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,QAAQ,CAAC,SAAS,CAAC;IAC5E,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAEnD,MAAM,MAAM,GAAG,MAAM,eAAe,CAClC,WAAW;QACT,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE;QAClD,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,CACtD,CAAC;IAEF,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,OAAO,CAAC,KAAK,CAAC,6CAA6C,MAAM,GAAG,CAAC,CAAC;AACxE,CAAC;AAED,KAAK,UAAU,gBAAgB;IAC7B,MAAM,iBAAiB,EAAE,CAAC;IAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;AACvC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;AAExC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=backpack-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backpack-sync.d.ts","sourceRoot":"","sources":["../../src/bin/backpack-sync.ts"],"names":[],"mappings":""}