indusagi 0.13.6 → 0.13.8

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 (44) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +7 -1
  3. package/dist/cli.js +114 -14
  4. package/dist/index.js +1618 -51
  5. package/dist/llmgateway.js +114 -14
  6. package/dist/mcp.js +812 -3
  7. package/dist/runtime.js +114 -14
  8. package/dist/sarvam-mcp.js +960 -0
  9. package/dist/shell-app.js +116 -14
  10. package/dist/smithy.js +114 -14
  11. package/dist/swarm.js +114 -14
  12. package/dist/tracing.js +37 -0
  13. package/dist/types/connectors-sarvam/connect.d.ts +14 -0
  14. package/dist/types/connectors-sarvam/connectors-sarvam.test.d.ts +14 -0
  15. package/dist/types/connectors-sarvam/index.d.ts +14 -0
  16. package/dist/types/connectors-sarvam/toolbox.d.ts +19 -0
  17. package/dist/types/connectors-sarvam/types.d.ts +49 -0
  18. package/dist/types/connectors-zoho/connect.d.ts +22 -0
  19. package/dist/types/connectors-zoho/connectors-zoho.test.d.ts +10 -0
  20. package/dist/types/connectors-zoho/index.d.ts +13 -0
  21. package/dist/types/connectors-zoho/toolbox.d.ts +19 -0
  22. package/dist/types/connectors-zoho/types.d.ts +56 -0
  23. package/dist/types/facade/mcp-core/client.d.ts +32 -0
  24. package/dist/types/facade/mcp-core/index.d.ts +4 -0
  25. package/dist/types/facade/mcp-core/oauth/flow.d.ts +72 -0
  26. package/dist/types/facade/mcp-core/oauth/index.d.ts +18 -0
  27. package/dist/types/facade/mcp-core/oauth/oauth.test.d.ts +8 -0
  28. package/dist/types/facade/mcp-core/oauth/provider.d.ts +51 -0
  29. package/dist/types/facade/mcp-core/oauth/token-store.d.ts +31 -0
  30. package/dist/types/facade/mcp-core/oauth/types.d.ts +96 -0
  31. package/dist/types/facade/mcp-core/toolbox-bridge.d.ts +46 -0
  32. package/dist/types/facade/mcp-core/toolbox-bridge.test.d.ts +8 -0
  33. package/dist/types/index.d.ts +2 -0
  34. package/dist/types/llmgateway/contract/model-card.d.ts +1 -1
  35. package/dist/types/llmgateway/credentials/secrets.d.ts +2 -0
  36. package/dist/zoho.js +1451 -0
  37. package/package.json +11 -4
  38. package/dist/knowledge/guides/authoring-an-agent.md +0 -53
  39. package/dist/knowledge/guides/choosing-tools.md +0 -49
  40. package/dist/knowledge/guides/model-selection.md +0 -51
  41. package/dist/knowledge/guides/writing-system-prompts.md +0 -53
  42. package/dist/knowledge/index.ts +0 -19
  43. package/dist/knowledge/loader.ts +0 -200
  44. package/dist/knowledge/manifest.json +0 -29
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Public types for the Sarvam MCP integration.
3
+ *
4
+ * The Sarvam DX exposes an MCP server that runs as a stdio subprocess
5
+ * (`uvx sarvam-mcp`). Auth is a single dashboard-issued API key passed via
6
+ * the `SARVAM_API_KEY` environment variable. These types describe how a
7
+ * caller hands that key — plus a few cosmetic knobs — to
8
+ * {@link connectSarvamMcp} and gets back a runtime {@link ToolBox} ready to
9
+ * drop into `createAgent({ tools })`.
10
+ */
11
+ import type { ToolBox } from "../runtime/contract/index.js";
12
+ import type { MCPClient } from "../facade/mcp-core/client.js";
13
+ /** Options for {@link connectSarvamMcp}. */
14
+ export interface ConnectSarvamMcpOptions {
15
+ /** Sarvam dashboard API key. Falls back to process.env.SARVAM_API_KEY. */
16
+ readonly apiKey?: string;
17
+ /** Stable id used for tool-name prefixing (default: "sarvam"). */
18
+ readonly id?: string;
19
+ /** Override Sarvam API base URL. Falls back to SARVAM_API_BASE_URL env, then "https://api.sarvam.ai". */
20
+ readonly baseUrl?: string;
21
+ /** Override where the Sarvam MCP server writes audio/docs files. Falls back to SARVAM_MCP_BASE_PATH env, then "~/Desktop". */
22
+ readonly basePath?: string;
23
+ /** Subprocess command. Default: "uvx". */
24
+ readonly command?: string;
25
+ /** Subprocess args. Default: ["sarvam-mcp"]. */
26
+ readonly args?: readonly string[];
27
+ /** Extra env for the subprocess. SARVAM_API_KEY and the *_BASE_URL/_BASE_PATH vars above are merged on top. */
28
+ readonly env?: Readonly<Record<string, string>>;
29
+ /** Connect timeout in ms (default 60_000 — uvx may download on first run). */
30
+ readonly timeoutMs?: number;
31
+ /** Optional logger for diagnostics. */
32
+ readonly logger?: {
33
+ debug(msg: string): void;
34
+ error(msg: string, err?: unknown): void;
35
+ };
36
+ }
37
+ /** The handle returned by {@link connectSarvamMcp}. */
38
+ export interface SarvamMcpConnection {
39
+ /** Stable id used for tool prefixing. */
40
+ readonly id: string;
41
+ /** Runtime ToolBox ready for `createAgent({ tools: sarvam.toolBox })`. */
42
+ readonly toolBox: ToolBox;
43
+ /** Names of every remote tool (already prefixed). */
44
+ readonly toolNames: readonly string[];
45
+ /** Underlying MCPClient (escape hatch). */
46
+ readonly client: MCPClient;
47
+ /** Disconnect and kill the spawned uvx child. Idempotent. */
48
+ close(): Promise<void>;
49
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Connect to a Zoho MCP server.
3
+ *
4
+ * Validates the URL, builds an HTTP-backed {@link MCPClient} (Streamable HTTP by
5
+ * default, legacy SSE when `useSse: true`), wires an OAuth 2.1 + PKCE auth
6
+ * provider for the transport when `auth` is `"auto"` (default) or `"oauth"`,
7
+ * opens the connection, then bridges the remote tool catalog into a runtime
8
+ * {@link ToolBox} via {@link mcpClientToToolBox} using `options.id` (default
9
+ * `"zoho"`) as the tool-name prefix so two servers can never collide.
10
+ *
11
+ * On 401 from Zoho:
12
+ * 1. SDK discovers the auth server (RFC 9728 / 8414)
13
+ * 2. Browser opens for PKCE login
14
+ * 3. Local callback captures the code
15
+ * 4. `transport.finishAuth(code)` exchanges tokens
16
+ * 5. Reconnect with Bearer token
17
+ *
18
+ * Tokens persist to `~/.config/indusagi/credentials/mcp/<id>.json` (mode 0600).
19
+ */
20
+ import type { ConnectZohoMcpOptions, ZohoMcpConnection } from "./types.js";
21
+ /** Open a Zoho MCP connection and return a ready-to-use toolbox + client. */
22
+ export declare function connectZohoMcp(options: ConnectZohoMcpOptions): Promise<ZohoMcpConnection>;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Tests for {@link connectZohoMcp}.
3
+ *
4
+ * A small `FakeMCPClient` stands in for the SDK-backed client. We use
5
+ * `vi.mock` to redirect the `MCPClient` import in `./connect.js` to a
6
+ * factory that returns our fake — no network, no vendor SDK, no
7
+ * monkey-patching of live modules. The fake records every method call so
8
+ * assertions can pin exactly what the connector did.
9
+ */
10
+ export {};
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Public barrel for the Zoho MCP connector.
3
+ *
4
+ * - {@link connectZohoMcp} — the high-level "give me a working toolbox"
5
+ * entry point that takes a Zoho console URL.
6
+ * - {@link zohoToolBoxFromClient} — the lower-level adapter for callers who
7
+ * already hold a connected {@link MCPClient}.
8
+ * - {@link ConnectZohoMcpOptions} / {@link ZohoMcpConnection} — the public
9
+ * types for those two entry points.
10
+ */
11
+ export { connectZohoMcp } from "./connect.js";
12
+ export { zohoToolBoxFromClient } from "./toolbox.js";
13
+ export type { ConnectZohoMcpOptions, ZohoMcpConnection } from "./types.js";
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Thin re-export wrapper so power users can also import just the toolbox
3
+ * adapter without going through {@link connectZohoMcp}.
4
+ *
5
+ * `zohoToolBoxFromClient` is equivalent to
6
+ * `mcpClientToToolBox(client, { namePrefix: options.id ?? "zoho", ... })`
7
+ * — it just defaults the prefix to the Zoho id.
8
+ */
9
+ import type { McpToToolBoxOptions } from "../facade/mcp-core/toolbox-bridge.js";
10
+ import type { MCPClient } from "../facade/mcp-core/client.js";
11
+ import type { ToolBox } from "../runtime/contract/index.js";
12
+ /**
13
+ * Wrap a connected {@link MCPClient} as a runtime {@link ToolBox} with a
14
+ * Zoho-friendly prefix. Equivalent to
15
+ * `mcpClientToToolBox(client, { namePrefix: options.id ?? "zoho", ... })`.
16
+ */
17
+ export declare function zohoToolBoxFromClient(client: MCPClient, options?: {
18
+ id?: string;
19
+ } & Omit<McpToToolBoxOptions, "namePrefix">): Promise<ToolBox>;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Public types for the Zoho MCP integration.
3
+ *
4
+ * The Zoho DX exposes a remote MCP server URL from the Zoho developer console.
5
+ * These types describe how a caller hands that URL — plus a few cosmetic
6
+ * knobs — to {@link connectZohoMcp} and gets back a runtime
7
+ * {@link ToolBox} ready to drop into `createAgent({ tools })`.
8
+ */
9
+ /** Options for {@link connectZohoMcp}. */
10
+ export interface ConnectZohoMcpOptions {
11
+ /** The MCP server URL from Zoho console → Connect tab. */
12
+ readonly url: string;
13
+ /** Stable id used for tool-name prefixing (default: "zoho"). */
14
+ readonly id?: string;
15
+ /**
16
+ * Auth mode:
17
+ * - "auto" (default): wire OAuth 2.1 + PKCE; let the SDK drive discovery and
18
+ * token refresh on 401. Persists tokens to `~/.config/indusagi/credentials/mcp/<id>.json`.
19
+ * - "oauth": same as "auto", explicit.
20
+ * - "none": no client OAuth; pass the URL through as-is (Zoho may have
21
+ * embedded a token, or you may have set a bearer via `headers`).
22
+ */
23
+ readonly auth?: "auto" | "oauth" | "none";
24
+ /** Optional static headers (e.g. Authorization). Use with care. */
25
+ readonly headers?: Readonly<Record<string, string>>;
26
+ /** Request timeout in ms (default 30_000). */
27
+ readonly timeoutMs?: number;
28
+ /** Use the legacy SSE transport instead of Streamable HTTP. Default: false. */
29
+ readonly useSse?: boolean;
30
+ /** Override the credentials directory (default: `~/.config/indusagi/credentials/mcp/`). */
31
+ readonly tokenStorePath?: string;
32
+ /** Override the OAuth redirect URI (default: `http://127.0.0.1:<random>/callback`). */
33
+ readonly redirectUrl?: string;
34
+ /** Open the browser for the OAuth round (default: true in TTY, false in CI). */
35
+ readonly openBrowser?: boolean;
36
+ /** OAuth scopes to request (default: server-advertised). */
37
+ readonly scopes?: readonly string[];
38
+ /** Optional logger for diagnostics. */
39
+ readonly logger?: {
40
+ debug(msg: string): void;
41
+ error(msg: string, err?: unknown): void;
42
+ };
43
+ }
44
+ /** The handle returned by {@link connectZohoMcp}. */
45
+ export interface ZohoMcpConnection {
46
+ /** Stable id used for tool prefixing. */
47
+ readonly id: string;
48
+ /** Runtime ToolBox ready for `createAgent({ tools: zoho.toolBox })`. */
49
+ readonly toolBox: import("../runtime/contract/index.js").ToolBox;
50
+ /** Names of every remote tool (already prefixed). */
51
+ readonly toolNames: readonly string[];
52
+ /** Underlying MCPClient (escape hatch). */
53
+ readonly client: import("../facade/mcp-core/client.js").MCPClient;
54
+ /** Disconnect from the MCP server. Idempotent. */
55
+ close(): Promise<void>;
56
+ }
@@ -17,6 +17,7 @@
17
17
  * roots/list, sampling, ping), and bounded reconnect on a dropped stream /
18
18
  * expired session — none of which the hand-rolled POST-only transport did.
19
19
  */
20
+ import { type OAuthClientProvider } from "@modelcontextprotocol/sdk/client/auth.js";
20
21
  import type { MCPServerConfig, MCPToolDefinition, MCPResource, MCPPrompt, MCPToolCallResult, MCPLogHandler, MCPProgressHandler, MCPElicitationHandler, MCPRoot } from "./types.js";
21
22
  /**
22
23
  * Options for creating an MCP client.
@@ -36,6 +37,22 @@ export interface MCPClientOptions {
36
37
  enableProgressTracking?: boolean;
37
38
  /** Filesystem roots to expose to the server */
38
39
  roots?: MCPRoot[];
40
+ /**
41
+ * OAuth client provider for the Streamable HTTP / SSE transport. When set,
42
+ * the SDK handles 401 → discover → PKCE → token-exchange → retry, plus
43
+ * mid-session refresh, automatically. Ignored for stdio.
44
+ *
45
+ * For first-time interactive auth the provider should also expose
46
+ * `waitForAuthorizationCode(): Promise<string>` (our
47
+ * {@link import("./oauth/provider.js").McpOAuthClientProvider} does). After
48
+ * the SDK throws UnauthorizedError we await that code, call
49
+ * `transport.finishAuth(code)`, and reconnect — matching the official
50
+ * MCP SDK CLI example.
51
+ */
52
+ authProvider?: OAuthClientProvider & {
53
+ waitForAuthorizationCode?: () => Promise<string>;
54
+ dispose?: () => void;
55
+ };
39
56
  }
40
57
  /**
41
58
  * MCP Client - manages connection to a single MCP server.
@@ -90,6 +107,21 @@ export declare class MCPClient {
90
107
  */
91
108
  connect(): Promise<void>;
92
109
  private doConnect;
110
+ /**
111
+ * If `err` is an OAuth challenge and we have a provider + finishAuth-capable
112
+ * transport, wait for the browser code, exchange tokens, then reconnect on a
113
+ * **fresh** transport (the first transport is already `start()`ed and cannot
114
+ * be reused — see StreamableHTTPClientTransport.start).
115
+ *
116
+ * Matches the official SDK CLI example (`simpleOAuthClient`):
117
+ * finishAuth(code) → new StreamableHTTPClientTransport → client.connect again
118
+ *
119
+ * Client.connect already called `close()` on init failure, so the Client is
120
+ * free to attach a new transport.
121
+ */
122
+ private tryFinishOAuthAndReconnect;
123
+ /** Turn raw SDK / network errors into a clearer MCPError for callers. */
124
+ private wrapConnectError;
93
125
  /**
94
126
  * Build the SDK transport for the configured server.
95
127
  *
@@ -27,6 +27,10 @@
27
27
  import { MCPClientPool } from "./client-pool.js";
28
28
  export { MCPClient, type MCPClientOptions } from "./client.js";
29
29
  export { MCPClientPool, type MCPClientPoolOptions, type MCPServerStatus } from "./client-pool.js";
30
+ export { mcpClientToToolBox } from "./toolbox-bridge.js";
31
+ export type { McpToToolBoxOptions } from "./toolbox-bridge.js";
32
+ export * as oauth from "./oauth/index.js";
33
+ export type { McpOAuthClientProvider } from "./oauth/index.js";
30
34
  export { MCPServer, createMCPServer, type MCPServerOptions } from "./server.js";
31
35
  export { createMCPAgentToolFactory, registerMCPToolsInRegistry, createMCPToolsMap, createMCPToolsRecord, type MCPToolClient, } from "./tool-factory.js";
32
36
  export { jsonSchemaToTypeBox, applyPassthrough, convertMCPInputSchema, convertMCPOutputSchema, } from "./schema-converter.js";
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Local-callback server for MCP OAuth.
3
+ *
4
+ * The MCP SDK OAuth flow for CLIs is:
5
+ * 1. Pre-bind a 127.0.0.1 callback server → known `redirect_uri`
6
+ * 2. Pass that URL as `OAuthClientProvider.redirectUrl`
7
+ * 3. On 401 the SDK opens the browser via `redirectToAuthorization`
8
+ * 4. SDK returns REDIRECT → transport throws UnauthorizedError
9
+ * 5. Caller waits for the browser hit, then `transport.finishAuth(code)`
10
+ * 6. Reconnect
11
+ *
12
+ * This module owns steps 1 and 5's wait half. Browser open lives in
13
+ * {@link openBrowser}; the provider and MCPClient wire the rest.
14
+ */
15
+ /**
16
+ * A pre-bound OAuth callback listener.
17
+ *
18
+ * Bind once before the MCP connect attempt so `redirect_uri` in the authorize
19
+ * request matches a real listening port. Then call {@link OAuthCallbackServer.waitForCode}
20
+ * after the SDK throws UnauthorizedError.
21
+ */
22
+ export interface OAuthCallbackServer {
23
+ /** Absolute redirect URI, e.g. `http://127.0.0.1:54321/callback`. */
24
+ readonly redirectUri: string;
25
+ /** Bound port. */
26
+ readonly port: number;
27
+ /**
28
+ * Wait for the browser to hit the callback with `?code=…`.
29
+ * If `expectedState` is set, a mismatched `state` rejects.
30
+ */
31
+ waitForCode(expectedState?: string): Promise<string>;
32
+ /** Tear down the listener. Idempotent. */
33
+ close(): void;
34
+ }
35
+ /**
36
+ * Bind a one-shot OAuth callback server on 127.0.0.1 (random free port).
37
+ *
38
+ * Important: the 5‑minute wait timer starts only when {@link OAuthCallbackServer.waitForCode}
39
+ * is called (i.e. when the SDK actually needs browser OAuth). If tokens are already
40
+ * on disk and connect succeeds without OAuth, we must NOT arm a timer — otherwise a
41
+ * later orphan rejection crashes the process with:
42
+ * "oauth-callback: timed out after … waiting for browser login"
43
+ */
44
+ export declare function startOAuthCallbackServer(options?: {
45
+ timeoutMs?: number;
46
+ logger?: {
47
+ debug(msg: string): void;
48
+ warn(msg: string): void;
49
+ };
50
+ }): Promise<OAuthCallbackServer>;
51
+ /**
52
+ * Back-compat helper used by older call sites: bind + wait in one shot.
53
+ * Prefer {@link startOAuthCallbackServer} so `redirect_uri` is known before authorize.
54
+ */
55
+ export declare function waitForAuthorizationCode(expectedState: string, options?: {
56
+ timeoutMs?: number;
57
+ logger?: {
58
+ debug(msg: string): void;
59
+ warn(msg: string): void;
60
+ };
61
+ }): Promise<{
62
+ code: string;
63
+ redirectUri: string;
64
+ port: number;
65
+ close(): void;
66
+ }>;
67
+ /**
68
+ * Open the user's browser to the auth URL. Falls back silently if the runtime
69
+ * has no GUI (CI, headless containers). The caller should always log the URL
70
+ * too so the user can open it manually.
71
+ */
72
+ export declare function openBrowser(url: string): Promise<boolean>;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Public barrel for the MCP OAuth submodule.
3
+ *
4
+ * The MCP OAuth flow is large (RFC 9728 discovery, RFC 7636 PKCE, RFC 7591
5
+ * dynamic registration, plus a browser redirect handler), but the
6
+ * indus-rebuild package only contributes the pieces the official
7
+ * `@modelcontextprotocol/sdk` cannot provide itself: a persistent token store
8
+ * and a local-callback HTTP server. The orchestrator (`auth()`) and the
9
+ * PKCE / refresh primitives all come from the SDK — re-export them so a
10
+ * power user can call them directly without reaching into the SDK.
11
+ */
12
+ export { createMcpOAuthProvider, type McpOAuthClientProvider, } from "./provider.js";
13
+ export type { McpClientInfo, McpOAuthConfig, McpOAuthState, McpTokenSet } from "./types.js";
14
+ export { readMcpOAuthState, writeMcpOAuthState, clearMcpOAuthState, resolveCredentialsDir, credentialsPath, } from "./token-store.js";
15
+ export { waitForAuthorizationCode, startOAuthCallbackServer, openBrowser, } from "./flow.js";
16
+ export type { OAuthCallbackServer } from "./flow.js";
17
+ export { auth, discoverOAuthServerInfo, startAuthorization, exchangeAuthorization, refreshAuthorization, registerClient, extractWWWAuthenticateParams, } from "@modelcontextprotocol/sdk/client/auth.js";
18
+ export type { OAuthTokens, OAuthClientMetadata, OAuthClientInformationMixed } from "@modelcontextprotocol/sdk/shared/auth.js";
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Tests for the MCP OAuth submodule.
3
+ *
4
+ * The tests focus on what *we* add (token-store persistence, provider plumbing,
5
+ * URL parsing) rather than re-validating the SDK. Every test uses a temp dir
6
+ * and never reads or writes the real `~/.config/indusagi/credentials/mcp/`.
7
+ */
8
+ export {};
@@ -0,0 +1,51 @@
1
+ /**
2
+ * An `OAuthClientProvider` implementation that persists every state transition
3
+ * to disk and coordinates a local callback server for the browser redirect.
4
+ *
5
+ * Matches the official SDK CLI pattern (`simpleOAuthClient`):
6
+ * - `redirectToAuthorization` only opens the browser (does NOT wait)
7
+ * - the MCP transport throws `UnauthorizedError` after REDIRECT
8
+ * - the caller awaits {@link McpOAuthClientProvider.waitForAuthorizationCode}
9
+ * - then calls `transport.finishAuth(code)` and reconnects
10
+ *
11
+ * The callback server is pre-bound at provider creation so `redirect_uri` is a
12
+ * real `http://127.0.0.1:<port>/callback` before the authorize request is sent.
13
+ */
14
+ import type { OAuthClientInformationMixed, OAuthClientMetadata, OAuthTokens } from "@modelcontextprotocol/sdk/shared/auth.js";
15
+ import type { McpOAuthConfig } from "./types.js";
16
+ /**
17
+ * The provider object returned by {@link createMcpOAuthProvider}.
18
+ *
19
+ * Implements every required method of the SDK's `OAuthClientProvider`.
20
+ */
21
+ export interface McpOAuthClientProvider {
22
+ readonly id: string;
23
+ readonly credentialsDir: string;
24
+ /** Real callback URL (pre-bound). */
25
+ readonly redirectUrl: string;
26
+ readonly clientMetadata: OAuthClientMetadata;
27
+ state(): string;
28
+ clientInformation(): OAuthClientInformationMixed | undefined;
29
+ saveClientInformation(client: OAuthClientInformationMixed): void;
30
+ tokens(): OAuthTokens | undefined;
31
+ saveTokens(tokens: OAuthTokens): void;
32
+ redirectToAuthorization(authorizationUrl: URL): Promise<void>;
33
+ saveCodeVerifier(codeVerifier: string): void;
34
+ codeVerifier(): string;
35
+ invalidateCredentials(scope: "all" | "client" | "tokens" | "verifier" | "discovery"): void;
36
+ /**
37
+ * Wait for the browser OAuth round to complete after UnauthorizedError.
38
+ * Returns the authorization code for `transport.finishAuth(code)`.
39
+ */
40
+ waitForAuthorizationCode(): Promise<string>;
41
+ /** Tear down the local callback listener. Call after connect succeeds or fails. */
42
+ dispose(): void;
43
+ /** Last authorization URL (for logging / manual open). */
44
+ lastAuthorizationUrl(): string | undefined;
45
+ }
46
+ /**
47
+ * Build a persistent `OAuthClientProvider` for one MCP server.
48
+ *
49
+ * Always async: pre-binds the callback port so `redirectUrl` is real.
50
+ */
51
+ export declare function createMcpOAuthProvider(config: McpOAuthConfig): Promise<McpOAuthClientProvider>;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Persistent token store for MCP OAuth state.
3
+ *
4
+ * One JSON file per server id under `<credentialsDir>/<id>.json`. On POSIX we
5
+ * create the file with mode 0600 so only the owning user can read tokens; on
6
+ * other platforms we fall back to the umask default. Tokens and PKCE verifiers
7
+ * are short-lived material that must never leak to a multi-user host.
8
+ *
9
+ * The store is deliberately synchronous — every method is small and the caller
10
+ * is already in an async context, so wrapping in fs.promises would just add
11
+ * microtask overhead for no benefit.
12
+ */
13
+ import type { McpOAuthState } from "./types.js";
14
+ /** Resolve the credentials directory, honoring the override when supplied. */
15
+ export declare function resolveCredentialsDir(override?: string): string;
16
+ /** File path for a given server id. */
17
+ export declare function credentialsPath(credentialsDir: string, id: string): string;
18
+ /**
19
+ * Read the persisted state for `id`, or `undefined` if nothing was stored yet.
20
+ * Returns `undefined` rather than throwing on missing-file so callers can
21
+ * treat the cold start as "needs authorization".
22
+ */
23
+ export declare function readMcpOAuthState(credentialsDir: string, id: string): McpOAuthState | undefined;
24
+ /**
25
+ * Write state atomically: temp file in the same directory + rename, so a
26
+ * crash mid-write cannot leave a half-formed token file. Creates the parent
27
+ * directory if needed.
28
+ */
29
+ export declare function writeMcpOAuthState(credentialsDir: string, state: McpOAuthState): void;
30
+ /** Remove the state file. Idempotent. */
31
+ export declare function clearMcpOAuthState(credentialsDir: string, id: string): void;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Types for the MCP OAuth submodule.
3
+ *
4
+ * The MCP spec delegates OAuth to the official SDK (RFC 9728 Protected Resource
5
+ * Metadata discovery, RFC 7636 PKCE, RFC 7591 Dynamic Client Registration).
6
+ * This submodule supplies only the persistent state and the local-redirect
7
+ * capture the SDK cannot do on its own — the rest of the flow (PKCE challenge
8
+ * generation, discovery, token exchange, refresh) is delegated to
9
+ * `@modelcontextprotocol/sdk/client/auth.js`.
10
+ */
11
+ /**
12
+ * The persistent token set we keep on disk across agent invocations.
13
+ *
14
+ * Aligned with the SDK's `OAuthTokens` shape so we can hand it straight back
15
+ * to the SDK without translation. `client_id` / `client_secret` come from
16
+ * RFC 7591 dynamic registration when the server supports it.
17
+ */
18
+ export interface McpTokenSet {
19
+ /** OAuth access token; sent as `Authorization: Bearer <accessToken>`. */
20
+ readonly access_token: string;
21
+ /** Long-lived refresh token; used to mint new access tokens without a browser. */
22
+ readonly refresh_token?: string;
23
+ /** Optional scope string echoed back from the auth server. */
24
+ readonly scope?: string;
25
+ /** Token type; "Bearer" by default. */
26
+ readonly token_type?: string;
27
+ /** Absolute epoch-ms deadline derived from the server's `expires_in`. */
28
+ readonly expires_at?: number;
29
+ }
30
+ /**
31
+ * RFC 7591 client information persisted after dynamic registration. Many MCP
32
+ * servers do not require pre-registration, but when they do we need to reuse
33
+ * the issued client_id on every subsequent connection.
34
+ */
35
+ export interface McpClientInfo {
36
+ readonly client_id: string;
37
+ readonly client_secret?: string;
38
+ readonly client_id_issued_at?: number;
39
+ readonly client_secret_expires_at?: number;
40
+ }
41
+ /**
42
+ * Per-server state persisted to disk. Keyed by stable server id (defaults to
43
+ * the MCP URL host). One file per id keeps isolation and rotation simple.
44
+ */
45
+ export interface McpOAuthState {
46
+ /** Stable id (typically the MCP server URL host). */
47
+ readonly id: string;
48
+ /** When the state was last written, epoch-ms. */
49
+ readonly updatedAt: number;
50
+ /** Tokens from the last successful auth round. */
51
+ tokens?: McpTokenSet;
52
+ /** Client info from RFC 7591 dynamic registration, if performed. */
53
+ client?: McpClientInfo;
54
+ /** RFC 9728 protected resource metadata, cached to skip re-discovery. */
55
+ resourceMetadata?: unknown;
56
+ /** RFC 8414 authorization server metadata, cached to skip re-discovery. */
57
+ authServerMetadata?: unknown;
58
+ /** PKCE code verifier held between `startAuthorization` and the callback. */
59
+ codeVerifier?: string;
60
+ /** OAuth `state` parameter held between start and callback for CSRF check. */
61
+ state?: string;
62
+ }
63
+ /**
64
+ * Configuration passed when wiring up an OAuth-aware MCP client.
65
+ */
66
+ export interface McpOAuthConfig {
67
+ /** Stable id used for the on-disk file name and the SDK's session. */
68
+ readonly id: string;
69
+ /** Override path to the credentials directory. Default: `~/.config/indusagi/credentials/mcp/`. */
70
+ readonly credentialsDir?: string;
71
+ /** Where to listen for the OAuth callback. Default: `http://127.0.0.1:<random>/callback`. */
72
+ readonly redirectUrl?: string;
73
+ /** Client metadata sent to RFC 7591 dynamic registration. */
74
+ readonly clientMetadata?: {
75
+ readonly client_name?: string;
76
+ readonly client_uri?: string;
77
+ readonly logo_uri?: string;
78
+ readonly contacts?: readonly string[];
79
+ readonly tos_uri?: string;
80
+ readonly policy_uri?: string;
81
+ readonly redirect_uris?: readonly string[];
82
+ readonly token_endpoint_auth_method?: "none" | "client_secret_basic" | "client_secret_post";
83
+ readonly grant_types?: readonly string[];
84
+ readonly response_types?: readonly string[];
85
+ readonly scope?: string;
86
+ };
87
+ /** Open the browser for the user to complete the auth round. Default: true in TTY. */
88
+ readonly openBrowser?: boolean;
89
+ /** Skip opening the browser and print the URL instead. */
90
+ readonly logger?: {
91
+ debug(msg: string): void;
92
+ info(msg: string): void;
93
+ warn(msg: string): void;
94
+ error(msg: string, err?: unknown): void;
95
+ };
96
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Bridge a connected {@link MCPClient} into the runtime's {@link ToolBox} shape.
3
+ *
4
+ * `mcpClientToToolBox` is the entry point most callers want: it asks the
5
+ * connected client for its remote tool catalog, wraps each one with
6
+ * {@link defineTool} so the model sees a normal `ToolDescriptor`, and returns a
7
+ * {@link ToolBox} that drops straight into `createAgent({ tools })`. Every
8
+ * remote tool is registered under `"<prefix>__<name>"` so two MCP servers
9
+ * advertising the same name never collide.
10
+ *
11
+ * The mapping intentionally projects the MCP result into the kernel's
12
+ * {@link ToolContentBlock} vocabulary:
13
+ * - `text` blocks pass through verbatim;
14
+ * - `image` blocks become a one-line text mention (we do not ship raw
15
+ * base64 to the model through this seam; structured payloads travel on
16
+ * `structuredContent` instead);
17
+ * - `resource` blocks become a `[resource <uri>]` mention;
18
+ * - `structuredContent`, if present, is appended as a JSON content block.
19
+ */
20
+ import type { MCPClient } from "./client.js";
21
+ import type { MCPToolDefinition } from "./types.js";
22
+ import type { ToolBox } from "../../runtime/contract/index.js";
23
+ /** Options for {@link mcpClientToToolBox}. */
24
+ export interface McpToToolBoxOptions {
25
+ /**
26
+ * Prefix each tool name with `"<prefix>__"`. Default: `"mcp"`. Two clients
27
+ * bridged in the same agent should use distinct prefixes.
28
+ */
29
+ readonly namePrefix?: string;
30
+ /** Optional filter — return false to skip a tool. */
31
+ readonly filter?: (tool: MCPToolDefinition) => boolean;
32
+ /** Logger for diagnostics. */
33
+ readonly logger?: {
34
+ debug(msg: string): void;
35
+ error(msg: string, err?: unknown): void;
36
+ };
37
+ }
38
+ /**
39
+ * Wrap a connected {@link MCPClient} as a runtime {@link ToolBox}.
40
+ *
41
+ * Each remote tool becomes a prefixed descriptor (`"<prefix>__<name>"`) whose
42
+ * invocation is forwarded to `client.callTool` with the model's input passed
43
+ * through unchanged. Results are projected from MCP content blocks onto the
44
+ * kernel's `ToolContentBlock` vocabulary.
45
+ */
46
+ export declare function mcpClientToToolBox(client: MCPClient, options?: McpToToolBoxOptions): Promise<ToolBox>;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Tests for {@link mcpClientToToolBox}.
3
+ *
4
+ * A small inline `FakeMCPClient` stands in for the real client: it tracks
5
+ * calls and scripts the responses of `listTools` / `callTool`. No network,
6
+ * no vi.mock — the codebase prefers stubbed fakes.
7
+ */
8
+ export {};
@@ -9,6 +9,8 @@ export * as runtime from "./runtime";
9
9
  export * as capabilities from "./capabilities";
10
10
  export * as interop from "./interop";
11
11
  export * as saas from "./connectors-saas";
12
+ export * as zoho from "./connectors-zoho";
13
+ export * as sarvamMcp from "./connectors-sarvam";
12
14
  export * as swarm from "./swarm";
13
15
  export * as smithy from "./smithy";
14
16
  export * as tracing from "./tracing";
@@ -9,7 +9,7 @@
9
9
  * The upstream organization that owns a model. This is the *vendor* identity,
10
10
  * independent of which HTTP dialect we speak to reach it (see {@link ApiKind}).
11
11
  */
12
- export type ProviderId = "anthropic" | "openai" | "google" | "google-vertex" | "amazon" | "azure" | "nvidia" | "kimi" | "ollama" | "mock";
12
+ export type ProviderId = "anthropic" | "openai" | "google" | "google-vertex" | "amazon" | "azure" | "nvidia" | "kimi" | "minimax" | "minimax-cn" | "ollama" | "mock";
13
13
  /**
14
14
  * The concrete request/response wire protocol a connector implements. Several
15
15
  * providers share a dialect (everything OpenAI-compatible speaks
@@ -17,6 +17,8 @@
17
17
  * - Azure OpenAI ..... AZURE_OPENAI_API_KEY, then AZURE_API_KEY
18
18
  * - NVIDIA ........... NVIDIA_API_KEY
19
19
  * - Kimi (Moonshot) .. MOONSHOT_API_KEY, then KIMI_API_KEY
20
+ * - MiniMax .......... MINIMAX_API_KEY (global api.minimax.io)
21
+ * - MiniMax CN ....... MINIMAX_API_KEY, then MINIMAX_CN_API_KEY (api.minimaxi.com)
20
22
  * - Ollama / mock .... (no secret required)
21
23
  */
22
24
  import type { CredentialResolver, ProviderId } from "../contract";