@datagrout/conduit 0.7.0 → 0.8.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/README.md CHANGED
@@ -5,7 +5,7 @@ Production-ready MCP client with mTLS identity, OAuth 2.1, semantic discovery, a
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install @datagrout/conduit@0.5.0
8
+ npm install @datagrout/conduit@0.8.1
9
9
  ```
10
10
 
11
11
  ## Quick Start
@@ -49,6 +49,61 @@ const client = new Client({
49
49
 
50
50
  The SDK automatically fetches, caches, and refreshes JWTs before they expire.
51
51
 
52
+ ### OAuth 2.1 (authorization code + PKCE)
53
+
54
+ `client_credentials` authenticates a *machine*, with a secret issued out of
55
+ band. To authenticate a *person* — and to reach
56
+ `https://gateway.datagrout.ai/connect`, where the server binding is chosen at
57
+ consent time and lives in the token rather than the URL — run the
58
+ browser-consent flow once and persist the grant:
59
+
60
+ ```typescript
61
+ import { AuthCodeFlow, LoopbackListener } from '@datagrout/conduit';
62
+
63
+ const listener = await LoopbackListener.bind(); // 127.0.0.1, OS-chosen port
64
+ const flow = await AuthCodeFlow.discover('https://gateway.datagrout.ai/connect');
65
+ const registered = await flow.register('My App', listener.redirectUri);
66
+
67
+ const { url, pending } = flow.authorizeUrl();
68
+ console.log(`Open this to sign in:\n${url}`); // the SDK never opens a browser
69
+
70
+ const redirect = await listener.wait(300_000);
71
+ const grant = await flow.exchange(pending, redirect.code, redirect.state);
72
+
73
+ // Persist BOTH: a client id without its redirect URI cannot be reused, because
74
+ // the authorization server matches redirect URIs exactly.
75
+ saveSomewhere({ registered, grant });
76
+ ```
77
+
78
+ On later runs, skip straight to the grant:
79
+
80
+ ```typescript
81
+ const client = new Client({
82
+ url: 'https://gateway.datagrout.ai/connect',
83
+ auth: { authorizationCode: grant },
84
+ });
85
+ ```
86
+
87
+ DataGrout **rotates refresh tokens**, so a grant that is refreshed and not
88
+ written back leaves a consumed token on disk. Own the provider when you care:
89
+
90
+ ```typescript
91
+ import { AuthCodeProvider } from '@datagrout/conduit';
92
+
93
+ const provider = new AuthCodeProvider(grant);
94
+ const client = new Client({ url, auth: { authorizationCode: provider } });
95
+
96
+ setInterval(() => {
97
+ const rotated = provider.takeIfDirty();
98
+ if (rotated) saveSomewhere({ registered, grant: rotated });
99
+ }, 30_000);
100
+ ```
101
+
102
+ Where the grant lives is your decision — a keychain, a config file, a vault.
103
+ The SDK owns its shape and its refresh, and deliberately picks no location.
104
+ The shape is identical across every conduit SDK, so a grant written by the
105
+ Python client is readable by this one.
106
+
52
107
  ### mTLS (Mutual TLS)
53
108
 
54
109
  After bootstrapping, the client certificate handles authentication at the TLS layer — no tokens needed.
@@ -217,7 +272,12 @@ Supported topics:
217
272
  ```typescript
218
273
  new Client(options: {
219
274
  url: string;
220
- auth?: { bearer?: string; apiKey?: string; clientCredentials?: {...} };
275
+ auth?: {
276
+ bearer?: string;
277
+ apiKey?: string;
278
+ clientCredentials?: {...};
279
+ authorizationCode?: Grant | AuthCodeProvider;
280
+ };
221
281
  transport?: 'mcp' | 'jsonrpc' | 'websocket';
222
282
  useIntelligentInterface?: boolean;
223
283
  identity?: ConduitIdentity;
@@ -255,7 +315,7 @@ new Client(options: {
255
315
 
256
316
  ## Requirements
257
317
 
258
- - Node.js 18+
318
+ - Node.js 22.12+ (the oldest line still receiving security patches; tested on 22 and 24)
259
319
  - TypeScript 5.0+ (for TypeScript users)
260
320
 
261
321
  ## License