@electric-ax/agents-mcp 0.2.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/LICENSE +177 -0
- package/dist/index.cjs +1169 -0
- package/dist/index.d.cts +515 -0
- package/dist/index.d.ts +515 -0
- package/dist/index.js +1131 -0
- package/package.json +48 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { OAuthClientInformationMixed } from "@modelcontextprotocol/sdk/shared/auth.js";
|
|
3
|
+
import { OAuthClientProvider } from "@modelcontextprotocol/sdk/client/auth.js";
|
|
4
|
+
|
|
5
|
+
//#region src/types.d.ts
|
|
6
|
+
/** Persisted-token shape — surfaces in OAuth callbacks (`onTokensChanged`). */
|
|
7
|
+
/** Persisted-token shape — surfaces in OAuth callbacks (`onTokensChanged`). */
|
|
8
|
+
interface OAuthTokens {
|
|
9
|
+
accessToken: string;
|
|
10
|
+
refreshToken?: string;
|
|
11
|
+
/** Unix seconds. */
|
|
12
|
+
expiresAt?: number;
|
|
13
|
+
tokenType?: string;
|
|
14
|
+
scope?: string;
|
|
15
|
+
}
|
|
16
|
+
/** DCR-registered (or pre-registered) OAuth client — surfaces in `onClientRegistered`. */
|
|
17
|
+
interface OAuthClientInfo {
|
|
18
|
+
clientId: string;
|
|
19
|
+
clientSecret?: string;
|
|
20
|
+
redirectUris?: string[];
|
|
21
|
+
/** Unix seconds. */
|
|
22
|
+
registeredAt?: number;
|
|
23
|
+
}
|
|
24
|
+
type McpAuthMode = `none` | `apiKey` | `clientCredentials` | `authorizationCode`;
|
|
25
|
+
type McpAuthConfig = {
|
|
26
|
+
mode: `none`;
|
|
27
|
+
} | {
|
|
28
|
+
mode: `apiKey`;
|
|
29
|
+
/** Raw secret. Inline at the call site (e.g. `process.env.X_API_KEY`). */
|
|
30
|
+
key: string;
|
|
31
|
+
headerName?: string;
|
|
32
|
+
valuePrefix?: string;
|
|
33
|
+
} | {
|
|
34
|
+
mode: `clientCredentials`;
|
|
35
|
+
tokenUrl: string;
|
|
36
|
+
/** Inline at the call site (e.g. `process.env.X_CLIENT_ID`). */
|
|
37
|
+
clientId: string;
|
|
38
|
+
/** Inline at the call site (e.g. `process.env.X_CLIENT_SECRET`). */
|
|
39
|
+
clientSecret: string;
|
|
40
|
+
scopes?: string[];
|
|
41
|
+
audience?: string;
|
|
42
|
+
resource?: string;
|
|
43
|
+
} | {
|
|
44
|
+
mode: `authorizationCode`;
|
|
45
|
+
scopes?: string[];
|
|
46
|
+
resource?: string;
|
|
47
|
+
/** Override redirect URI; default `${publicUrl}/oauth/callback/<server>`. */
|
|
48
|
+
redirectUri?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Pre-registered OAuth client. When present, RFC 7591 Dynamic Client
|
|
51
|
+
* Registration is skipped. Sourced from the operator's secret system.
|
|
52
|
+
*/
|
|
53
|
+
client?: OAuthClientInfo;
|
|
54
|
+
/**
|
|
55
|
+
* Pre-existing tokens to seed the registry's in-process cache on
|
|
56
|
+
* boot. When present, the OAuth flow is skipped and the SDK uses
|
|
57
|
+
* these directly. Refresh-token rotation still happens transparently.
|
|
58
|
+
*/
|
|
59
|
+
tokens?: OAuthTokens;
|
|
60
|
+
/**
|
|
61
|
+
* Fires after initial-auth and on every refresh-token rotation.
|
|
62
|
+
* Wire to a persistence layer (keychain, file, vault, ...) if you
|
|
63
|
+
* want tokens to survive process restarts. Optional — without it,
|
|
64
|
+
* tokens live only for the lifetime of the registry.
|
|
65
|
+
*/
|
|
66
|
+
onTokensChanged?: (tokens: OAuthTokens) => void | Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Fires once after Dynamic Client Registration completes. Pair
|
|
69
|
+
* with `client` on the next boot to skip DCR.
|
|
70
|
+
*/
|
|
71
|
+
onClientRegistered?: (client: OAuthClientInfo) => void | Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Reference into a per-process map of pre-built OAuthClientProvider
|
|
74
|
+
* instances. Escape hatch for embedders with non-standard requirements
|
|
75
|
+
* (mTLS, OIDC quirks, etc.).
|
|
76
|
+
*/
|
|
77
|
+
oauthProviderRef?: string;
|
|
78
|
+
};
|
|
79
|
+
interface McpHttpServerConfig {
|
|
80
|
+
name: string;
|
|
81
|
+
transport: `http`;
|
|
82
|
+
url: string;
|
|
83
|
+
auth: McpAuthConfig;
|
|
84
|
+
/** Per-server timeout override in ms. Default 30000. */
|
|
85
|
+
timeoutMs?: number;
|
|
86
|
+
}
|
|
87
|
+
interface McpStdioServerConfig {
|
|
88
|
+
name: string;
|
|
89
|
+
transport: `stdio`;
|
|
90
|
+
command: string;
|
|
91
|
+
args?: string[];
|
|
92
|
+
env?: Record<string, string>;
|
|
93
|
+
auth?: McpAuthConfig;
|
|
94
|
+
/** Per-server timeout override in ms. Default 30000. */
|
|
95
|
+
timeoutMs?: number;
|
|
96
|
+
}
|
|
97
|
+
type McpServerConfig = McpHttpServerConfig | McpStdioServerConfig;
|
|
98
|
+
type McpServerStatus = `connecting` | `authenticating` | `ready` | `error` | `disabled`;
|
|
99
|
+
type McpToolErrorKind = `auth_unavailable` | `transport_error` | `timeout` | `server_error` | `tool_not_found`;
|
|
100
|
+
interface McpToolError {
|
|
101
|
+
kind: McpToolErrorKind;
|
|
102
|
+
message: string;
|
|
103
|
+
details?: unknown;
|
|
104
|
+
}
|
|
105
|
+
type AddServerResult = {
|
|
106
|
+
state: `ready`;
|
|
107
|
+
id: string;
|
|
108
|
+
toolCount: number;
|
|
109
|
+
} | {
|
|
110
|
+
state: `authenticating`;
|
|
111
|
+
id: string;
|
|
112
|
+
authUrl: string;
|
|
113
|
+
} | {
|
|
114
|
+
state: `error`;
|
|
115
|
+
id: string;
|
|
116
|
+
error: McpToolError;
|
|
117
|
+
}; //#endregion
|
|
118
|
+
//#region src/tools.d.ts
|
|
119
|
+
declare const MCP_TOOLS_SENTINEL: unique symbol;
|
|
120
|
+
interface McpToolsSentinel {
|
|
121
|
+
[MCP_TOOLS_SENTINEL]: true;
|
|
122
|
+
/** `undefined` means every registered server. */
|
|
123
|
+
allowlist?: string[];
|
|
124
|
+
}
|
|
125
|
+
declare function isMcpToolsSentinel(x: unknown): x is McpToolsSentinel;
|
|
126
|
+
declare const mcp: {
|
|
127
|
+
/**
|
|
128
|
+
* Returns a sentinel array for `tools: [...mcp.tools()]`.
|
|
129
|
+
* Resolution happens at wake time via the runtime's tool-provider
|
|
130
|
+
* hook. Pass an array to restrict to specific servers; omit for
|
|
131
|
+
* every registered server.
|
|
132
|
+
*/
|
|
133
|
+
tools(allowlist?: string[]): McpToolsSentinel[];
|
|
134
|
+
};
|
|
135
|
+
declare function filterByAllowlist(serverNames: string[], allowlist: string[] | undefined): string[];
|
|
136
|
+
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/credentials/auth-store.d.ts
|
|
139
|
+
/**
|
|
140
|
+
* Internal token + client cache used by the registry. Created per-registry,
|
|
141
|
+
* never crossed by the public API. Seeded from `auth.tokens` / `auth.client`
|
|
142
|
+
* on `addServer`; mutated as the SDK refreshes / completes DCR. Calls into
|
|
143
|
+
* the per-server `onTokensChanged` / `onClientRegistered` callbacks declared
|
|
144
|
+
* on the auth config so the operator can persist if they want.
|
|
145
|
+
*/
|
|
146
|
+
interface AuthStore {
|
|
147
|
+
getOAuthTokens(server: string): OAuthTokens | undefined;
|
|
148
|
+
saveOAuthTokens(server: string, tokens: OAuthTokens): Promise<void>;
|
|
149
|
+
getOAuthClientInfo(server: string): OAuthClientInfo | undefined;
|
|
150
|
+
saveOAuthClientInfo(server: string, info: OAuthClientInfo): Promise<void>;
|
|
151
|
+
}
|
|
152
|
+
/** Per-server hooks registered on `addServer` and invoked on cache mutations. */
|
|
153
|
+
interface AuthStoreHooks {
|
|
154
|
+
onTokensChanged?: (tokens: OAuthTokens) => void | Promise<void>;
|
|
155
|
+
onClientRegistered?: (client: OAuthClientInfo) => void | Promise<void>;
|
|
156
|
+
}
|
|
157
|
+
interface InternalAuthStore extends AuthStore {
|
|
158
|
+
/** Pre-seed the cache with tokens read from `auth.tokens`. */
|
|
159
|
+
seedTokens(server: string, tokens: OAuthTokens): void;
|
|
160
|
+
/** Pre-seed the cache with a pre-registered OAuth client. */
|
|
161
|
+
seedClient(server: string, client: OAuthClientInfo): void;
|
|
162
|
+
/** Register per-server hooks declared on the auth config. */
|
|
163
|
+
registerHooks(server: string, hooks: AuthStoreHooks): void;
|
|
164
|
+
/**
|
|
165
|
+
* Drop only the cached tokens + DCR client info for a server. Hooks
|
|
166
|
+
* stay registered, so future `saveOAuthTokens` / `saveOAuthClientInfo`
|
|
167
|
+
* calls still notify the operator's persistence callbacks. Used by
|
|
168
|
+
* `Registry.reauthorize` to force a fresh OAuth flow without losing
|
|
169
|
+
* the persistence wiring.
|
|
170
|
+
*/
|
|
171
|
+
clearCredentials(server: string): void;
|
|
172
|
+
/** Drop everything we know about a server (used by `removeServer`). */
|
|
173
|
+
forget(server: string): void;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region src/transports/types.d.ts
|
|
178
|
+
interface McpTransport {
|
|
179
|
+
client: Client;
|
|
180
|
+
connect(): Promise<void>;
|
|
181
|
+
close(): Promise<void>;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
//#endregion
|
|
185
|
+
//#region src/auth/sdk-provider.d.ts
|
|
186
|
+
/**
|
|
187
|
+
* Adapter that implements the MCP SDK's `OAuthClientProvider` and reads/writes
|
|
188
|
+
* the registry's internal `AuthStore`. The SDK handles PKCE, DCR (RFC 7591),
|
|
189
|
+
* discovery (RFC 9728), token exchange, refresh, and 401-retry; this adapter
|
|
190
|
+
* just plumbs reads and writes. Cross-process persistence (if any) happens
|
|
191
|
+
* via the `onTokensChanged` / `onClientRegistered` hooks the registry wires
|
|
192
|
+
* into the store from the per-server auth config.
|
|
193
|
+
*/
|
|
194
|
+
interface SdkOAuthProvider extends OAuthClientProvider {
|
|
195
|
+
/** Always implemented — persists the DCR response via the internal AuthStore. */
|
|
196
|
+
saveClientInformation(clientInformation: OAuthClientInformationMixed): void | Promise<void>;
|
|
197
|
+
/** Returns the most recent authorize URL captured by redirectToAuthorization. */
|
|
198
|
+
peekAuthUrl(): string | undefined;
|
|
199
|
+
/** Resets the captured authorize URL. */
|
|
200
|
+
clearAuthUrl(): void;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
//#endregion
|
|
204
|
+
//#region src/config/loader.d.ts
|
|
205
|
+
interface McpConfig {
|
|
206
|
+
servers: McpServerConfig[];
|
|
207
|
+
raw: unknown;
|
|
208
|
+
}
|
|
209
|
+
declare function parseConfig(raw: unknown, env?: NodeJS.ProcessEnv): McpConfig;
|
|
210
|
+
declare function loadConfig(path: string, env?: NodeJS.ProcessEnv): Promise<McpConfig>;
|
|
211
|
+
|
|
212
|
+
//#endregion
|
|
213
|
+
//#region src/registry.d.ts
|
|
214
|
+
interface Entry {
|
|
215
|
+
config: McpServerConfig;
|
|
216
|
+
configHash: string;
|
|
217
|
+
status: McpServerStatus;
|
|
218
|
+
error?: McpToolError;
|
|
219
|
+
authUrl?: string;
|
|
220
|
+
transport?: McpTransport;
|
|
221
|
+
tools: Array<{
|
|
222
|
+
name: string;
|
|
223
|
+
description?: string;
|
|
224
|
+
inputSchema: unknown;
|
|
225
|
+
}>;
|
|
226
|
+
capabilities?: unknown;
|
|
227
|
+
provider?: SdkOAuthProvider;
|
|
228
|
+
}
|
|
229
|
+
interface RegistryOpts {
|
|
230
|
+
/** Base URL of this registry process, used to construct OAuth redirect URIs. */
|
|
231
|
+
publicUrl?: string;
|
|
232
|
+
transportFactoryOverride?: (cfg: McpServerConfig, hp?: HeaderProvider, provider?: SdkOAuthProvider) => McpTransport;
|
|
233
|
+
/**
|
|
234
|
+
* Called when an authorizationCode-flow server first needs the user
|
|
235
|
+
* to consent — receives the SDK-generated authorize URL plus the
|
|
236
|
+
* server name. The default implementation logs the URL; the desktop
|
|
237
|
+
* app overrides this to open the URL in a sandboxed BrowserWindow
|
|
238
|
+
* (and intercept the redirect_uri navigation to call `finishAuth`).
|
|
239
|
+
*
|
|
240
|
+
* Headless / non-Electron embedders that want to drive the flow
|
|
241
|
+
* themselves can read the URL from the `authenticating` envelope of
|
|
242
|
+
* `addServer` instead — this hook is purely a convenience for
|
|
243
|
+
* "open this URL right now" callers.
|
|
244
|
+
*/
|
|
245
|
+
openAuthorizeUrl?: (url: string, server: string) => void;
|
|
246
|
+
/**
|
|
247
|
+
* Internal hook used by tests to seed / inspect the registry's private
|
|
248
|
+
* auth store. Not part of the public contract — production callers should
|
|
249
|
+
* use the per-server `auth.tokens` / `auth.client` fields and the
|
|
250
|
+
* `onTokensChanged` / `onClientRegistered` hooks instead.
|
|
251
|
+
* @internal
|
|
252
|
+
*/
|
|
253
|
+
authStore?: InternalAuthStore;
|
|
254
|
+
}
|
|
255
|
+
type HeaderProvider = () => Promise<{
|
|
256
|
+
name: string;
|
|
257
|
+
value: string;
|
|
258
|
+
} | undefined>;
|
|
259
|
+
interface ListedEntry {
|
|
260
|
+
name: string;
|
|
261
|
+
status: McpServerStatus;
|
|
262
|
+
toolCount: number;
|
|
263
|
+
/** `http` or `stdio`. Surfaces in UI for badges + per-status affordances. */
|
|
264
|
+
transport?: string;
|
|
265
|
+
/** `none` | `apiKey` | `clientCredentials` | `authorizationCode`. */
|
|
266
|
+
authMode?: string;
|
|
267
|
+
authUrl?: string;
|
|
268
|
+
error?: McpToolError;
|
|
269
|
+
tools: Entry[`tools`];
|
|
270
|
+
capabilities?: unknown;
|
|
271
|
+
}
|
|
272
|
+
/** State snapshot delivered to subscribers on every registry mutation. */
|
|
273
|
+
interface RegistrySnapshot {
|
|
274
|
+
/** Monotonic per-registry counter; useful for detecting dropped events. */
|
|
275
|
+
seq: number;
|
|
276
|
+
servers: ReadonlyArray<ListedEntry>;
|
|
277
|
+
}
|
|
278
|
+
type RegistrySubscriber = (snapshot: RegistrySnapshot) => void;
|
|
279
|
+
interface Registry {
|
|
280
|
+
addServer(cfg: McpServerConfig): Promise<AddServerResult>;
|
|
281
|
+
applyConfig(cfg: McpConfig): Promise<AddServerResult[]>;
|
|
282
|
+
removeServer(name: string): Promise<void>;
|
|
283
|
+
list(): ReadonlyArray<ListedEntry>;
|
|
284
|
+
get(name: string): Entry | undefined;
|
|
285
|
+
finishAuth(serverName: string, code: string, state?: string): Promise<AddServerResult>;
|
|
286
|
+
disable(name: string): Promise<void>;
|
|
287
|
+
enable(name: string): Promise<AddServerResult>;
|
|
288
|
+
/**
|
|
289
|
+
* Force a fresh OAuth flow for a server. Closes the current transport,
|
|
290
|
+
* forgets cached tokens (and DCR client info) for this server, and
|
|
291
|
+
* rebuilds the transport in place — keeping the entry visible in
|
|
292
|
+
* snapshots throughout, so renderers don't see a brief
|
|
293
|
+
* "server gone, server back" blip the way `removeServer` + `addServer`
|
|
294
|
+
* would. The SDK provider then has nothing to authenticate with on the
|
|
295
|
+
* next connect, and surfaces a fresh authorize URL via the
|
|
296
|
+
* `openAuthorizeUrl` hook.
|
|
297
|
+
*
|
|
298
|
+
* No-op when the server is unknown, not authorizationCode, or
|
|
299
|
+
* disabled.
|
|
300
|
+
*/
|
|
301
|
+
reauthorize(name: string): Promise<void>;
|
|
302
|
+
/**
|
|
303
|
+
* Subscribe to registry state changes. The handler is invoked
|
|
304
|
+
* synchronously with the current snapshot on subscribe (so callers
|
|
305
|
+
* can render an initial UI without a round-trip), and again on every
|
|
306
|
+
* mutation: addServer / removeServer / applyConfig / finishAuth /
|
|
307
|
+
* disable / enable / connection-state transitions.
|
|
308
|
+
*
|
|
309
|
+
* Returns an unsubscribe function.
|
|
310
|
+
*/
|
|
311
|
+
subscribe(handler: RegistrySubscriber): () => void;
|
|
312
|
+
/**
|
|
313
|
+
* Close every transport, clear all entries, and emit a final empty
|
|
314
|
+
* snapshot to subscribers.
|
|
315
|
+
*/
|
|
316
|
+
close(): Promise<void>;
|
|
317
|
+
}
|
|
318
|
+
declare function createRegistry(opts: RegistryOpts): Registry;
|
|
319
|
+
|
|
320
|
+
//#endregion
|
|
321
|
+
//#region src/config/watcher.d.ts
|
|
322
|
+
interface WatchOpts {
|
|
323
|
+
onChange: (cfg: McpConfig) => void;
|
|
324
|
+
onError?: (err: unknown) => void;
|
|
325
|
+
debounceMs?: number;
|
|
326
|
+
env?: NodeJS.ProcessEnv;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Start watching `path` for changes. Each modification triggers
|
|
330
|
+
* `loadConfig(path)` (debounced) and forwards the parsed config to
|
|
331
|
+
* `onChange`, or any error to `onError`. The caller is responsible
|
|
332
|
+
* for performing the initial load — `watchConfig` only sets up the
|
|
333
|
+
* subscription so the caller can fully await its first apply before
|
|
334
|
+
* subsequent change events start firing.
|
|
335
|
+
*/
|
|
336
|
+
declare function watchConfig(path: string, opts: WatchOpts): Promise<() => void>;
|
|
337
|
+
|
|
338
|
+
//#endregion
|
|
339
|
+
//#region src/bridge/tool-bridge.d.ts
|
|
340
|
+
declare function prefixToolName(server: string, tool: string): string;
|
|
341
|
+
/**
|
|
342
|
+
* Coerce an MCP tool's inputSchema into a shape downstream LLM adapters can
|
|
343
|
+
* consume safely. Some servers send `{ type: 'object' }` with no `properties`
|
|
344
|
+
* for no-arg tools; pi-agent-core walks `inputSchema.properties` and crashes on
|
|
345
|
+
* undefined. We default `properties` to `{}` and `required` to `[]` for object
|
|
346
|
+
* schemas; non-object schemas pass through unchanged.
|
|
347
|
+
*/
|
|
348
|
+
|
|
349
|
+
interface BridgeToolOpts {
|
|
350
|
+
server: string;
|
|
351
|
+
tool: {
|
|
352
|
+
name: string;
|
|
353
|
+
description?: string;
|
|
354
|
+
inputSchema: unknown;
|
|
355
|
+
};
|
|
356
|
+
/**
|
|
357
|
+
* Subset of the MCP SDK Client used here.
|
|
358
|
+
*
|
|
359
|
+
* The real signature of Client.callTool in @modelcontextprotocol/sdk ≥ 1.10 is:
|
|
360
|
+
* callTool(params, resultSchema?, options?)
|
|
361
|
+
* where the SECOND argument is a Zod schema (defaults to CallToolResultSchema) and
|
|
362
|
+
* the THIRD argument is a RequestOptions bag that may include { signal, onProgress }.
|
|
363
|
+
*
|
|
364
|
+
* We model this correctly here so that invoke() never passes signal/onProgress as
|
|
365
|
+
* the resultSchema (which would cause "v3Schema.safeParse is not a function").
|
|
366
|
+
*/
|
|
367
|
+
client: {
|
|
368
|
+
callTool: (args: {
|
|
369
|
+
name: string;
|
|
370
|
+
arguments?: unknown;
|
|
371
|
+
}, resultSchema?: unknown, opts?: {
|
|
372
|
+
onProgress?: (p: unknown) => void;
|
|
373
|
+
signal?: AbortSignal;
|
|
374
|
+
}) => Promise<unknown>;
|
|
375
|
+
};
|
|
376
|
+
timeoutMs?: number;
|
|
377
|
+
/** Optional progress notification callback forwarded to the SDK. */
|
|
378
|
+
onProgress?: (p: unknown) => void;
|
|
379
|
+
/** Optional AbortSignal forwarded to the SDK callTool. */
|
|
380
|
+
signal?: AbortSignal;
|
|
381
|
+
}
|
|
382
|
+
interface BridgedTool {
|
|
383
|
+
name: string;
|
|
384
|
+
server: string;
|
|
385
|
+
description?: string;
|
|
386
|
+
/** MCP wire shape — JSON schema. */
|
|
387
|
+
inputSchema: unknown;
|
|
388
|
+
/** pi-ai/pi-agent expects `parameters` (same JSON schema, different field). */
|
|
389
|
+
parameters: unknown;
|
|
390
|
+
/** Display label used by pi-agent UI bridges. */
|
|
391
|
+
label: string;
|
|
392
|
+
/** Direct MCP-style call. */
|
|
393
|
+
call(args: unknown): Promise<unknown>;
|
|
394
|
+
/** pi-agent execute signature. Wraps `call` and returns AgentToolResult-shaped output. */
|
|
395
|
+
execute: (toolCallId: string, params: unknown, signal?: AbortSignal) => Promise<{
|
|
396
|
+
content: Array<{
|
|
397
|
+
type: string;
|
|
398
|
+
text?: string;
|
|
399
|
+
}>;
|
|
400
|
+
details: unknown;
|
|
401
|
+
}>;
|
|
402
|
+
}
|
|
403
|
+
declare function bridgeMcpTool(opts: BridgeToolOpts): BridgedTool;
|
|
404
|
+
|
|
405
|
+
//#endregion
|
|
406
|
+
//#region src/bridge/resource-bridge.d.ts
|
|
407
|
+
interface BuildResourceToolsOpts {
|
|
408
|
+
server: string;
|
|
409
|
+
client: {
|
|
410
|
+
listResources: () => Promise<unknown>;
|
|
411
|
+
readResource: (args: {
|
|
412
|
+
uri: string;
|
|
413
|
+
}) => Promise<unknown>;
|
|
414
|
+
};
|
|
415
|
+
timeoutMs?: number;
|
|
416
|
+
}
|
|
417
|
+
declare function buildResourceTools(opts: BuildResourceToolsOpts): BridgedTool[];
|
|
418
|
+
|
|
419
|
+
//#endregion
|
|
420
|
+
//#region src/bridge/prompt-bridge.d.ts
|
|
421
|
+
interface BuildPromptToolsOpts {
|
|
422
|
+
server: string;
|
|
423
|
+
client: {
|
|
424
|
+
listPrompts: () => Promise<unknown>;
|
|
425
|
+
getPrompt: (args: {
|
|
426
|
+
name: string;
|
|
427
|
+
arguments?: Record<string, unknown>;
|
|
428
|
+
}) => Promise<unknown>;
|
|
429
|
+
};
|
|
430
|
+
timeoutMs?: number;
|
|
431
|
+
}
|
|
432
|
+
declare function buildPromptTools(opts: BuildPromptToolsOpts): BridgedTool[];
|
|
433
|
+
|
|
434
|
+
//#endregion
|
|
435
|
+
//#region src/persistence/keychain.d.ts
|
|
436
|
+
interface KeychainBackend {
|
|
437
|
+
get(service: string, account: string): Promise<string | undefined>;
|
|
438
|
+
set(service: string, account: string, value: string): Promise<void>;
|
|
439
|
+
}
|
|
440
|
+
interface KeychainPersistenceOpts {
|
|
441
|
+
/** Server name; used as the account-id portion of the keychain entry. */
|
|
442
|
+
server: string;
|
|
443
|
+
/** Keychain service identifier. Default `'electric-agents'`. */
|
|
444
|
+
service?: string;
|
|
445
|
+
/** Override for tests — inject a backend instead of shelling out. */
|
|
446
|
+
backend?: KeychainBackend;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Opt-in helper for OAuth-mode `auth` configs. Loads any persisted tokens
|
|
450
|
+
* and DCR client info from the OS keychain on startup, and returns the
|
|
451
|
+
* matching `onTokensChanged` / `onClientRegistered` callbacks so the SDK
|
|
452
|
+
* writes refreshed material back.
|
|
453
|
+
*
|
|
454
|
+
* const honeycomb = await keychainPersistence({ server: 'honeycomb' })
|
|
455
|
+
* await mcpRegistry.addServer({
|
|
456
|
+
* name: 'honeycomb',
|
|
457
|
+
* transport: 'http',
|
|
458
|
+
* url: 'https://mcp.honeycomb.io/mcp',
|
|
459
|
+
* auth: {
|
|
460
|
+
* mode: 'authorizationCode',
|
|
461
|
+
* flow: 'browser',
|
|
462
|
+
* scopes: ['mcp:read'],
|
|
463
|
+
* ...honeycomb,
|
|
464
|
+
* },
|
|
465
|
+
* })
|
|
466
|
+
*
|
|
467
|
+
* Backend is chosen by `process.platform`:
|
|
468
|
+
* - darwin → `/usr/bin/security` (no extra deps)
|
|
469
|
+
* - linux → `secret-tool` from libsecret-tools (apt: libsecret-tools)
|
|
470
|
+
* - win32 → not implemented yet — falls back to no-op callbacks
|
|
471
|
+
*
|
|
472
|
+
* If the chosen CLI isn't installed (e.g. minimal Linux container without
|
|
473
|
+
* libsecret), reads/writes throw on first use; the registry surfaces
|
|
474
|
+
* that as a connect-time error and the OAuth flow continues without
|
|
475
|
+
* persistence.
|
|
476
|
+
*/
|
|
477
|
+
declare function keychainPersistence(opts: KeychainPersistenceOpts): Promise<{
|
|
478
|
+
tokens?: OAuthTokens;
|
|
479
|
+
client?: OAuthClientInfo;
|
|
480
|
+
onTokensChanged: (t: OAuthTokens) => Promise<void>;
|
|
481
|
+
onClientRegistered: (c: OAuthClientInfo) => Promise<void>;
|
|
482
|
+
}>;
|
|
483
|
+
|
|
484
|
+
//#endregion
|
|
485
|
+
//#region src/persistence/file.d.ts
|
|
486
|
+
interface FilePersistenceOpts {
|
|
487
|
+
/** Path on disk; mode-0600 JSON. Created on first write. */
|
|
488
|
+
path: string;
|
|
489
|
+
/** Server name (key inside the file). */
|
|
490
|
+
server: string;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Opt-in helper for OAuth-mode `auth` configs. Mirrors `keychainPersistence`
|
|
494
|
+
* but persists to a JSON file on disk (mode 0600). Right tool when no OS
|
|
495
|
+
* keychain is available — CI runners, minimal Linux containers, etc.
|
|
496
|
+
*
|
|
497
|
+
* const honeycomb = await filePersistence({
|
|
498
|
+
* path: './.electric-agents/credentials.json',
|
|
499
|
+
* server: 'honeycomb',
|
|
500
|
+
* })
|
|
501
|
+
* await mcpRegistry.addServer({ ..., auth: { ..., ...honeycomb } })
|
|
502
|
+
*/
|
|
503
|
+
declare function filePersistence(opts: FilePersistenceOpts): Promise<{
|
|
504
|
+
tokens?: OAuthTokens;
|
|
505
|
+
client?: OAuthClientInfo;
|
|
506
|
+
onTokensChanged: (t: OAuthTokens) => Promise<void>;
|
|
507
|
+
onClientRegistered: (c: OAuthClientInfo) => Promise<void>;
|
|
508
|
+
}>;
|
|
509
|
+
|
|
510
|
+
//#endregion
|
|
511
|
+
//#region src/index.d.ts
|
|
512
|
+
declare const VERSION = "0.1.0";
|
|
513
|
+
|
|
514
|
+
//#endregion
|
|
515
|
+
export { AddServerResult, BridgeToolOpts, BridgedTool, BuildPromptToolsOpts, BuildResourceToolsOpts, FilePersistenceOpts, HeaderProvider, KeychainPersistenceOpts, ListedEntry, MCP_TOOLS_SENTINEL, McpAuthConfig, McpAuthMode, McpConfig, McpHttpServerConfig, McpServerConfig, McpServerStatus, McpStdioServerConfig, McpToolError, McpToolErrorKind, McpToolsSentinel, OAuthClientInfo, OAuthTokens, Registry, RegistryOpts, RegistrySnapshot, RegistrySubscriber, VERSION, WatchOpts, bridgeMcpTool, buildPromptTools, buildResourceTools, createRegistry, filePersistence, filterByAllowlist, isMcpToolsSentinel, keychainPersistence, loadConfig, mcp, parseConfig, prefixToolName, watchConfig };
|