@mcp-z/client 1.0.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.
Files changed (211) hide show
  1. package/AGENTS.md +159 -0
  2. package/LICENSE +21 -0
  3. package/README.md +90 -0
  4. package/dist/cjs/auth/capability-discovery.d.cts +25 -0
  5. package/dist/cjs/auth/capability-discovery.d.ts +25 -0
  6. package/dist/cjs/auth/capability-discovery.js +280 -0
  7. package/dist/cjs/auth/capability-discovery.js.map +1 -0
  8. package/dist/cjs/auth/index.d.cts +9 -0
  9. package/dist/cjs/auth/index.d.ts +9 -0
  10. package/dist/cjs/auth/index.js +28 -0
  11. package/dist/cjs/auth/index.js.map +1 -0
  12. package/dist/cjs/auth/interactive-oauth-flow.d.cts +58 -0
  13. package/dist/cjs/auth/interactive-oauth-flow.d.ts +58 -0
  14. package/dist/cjs/auth/interactive-oauth-flow.js +537 -0
  15. package/dist/cjs/auth/interactive-oauth-flow.js.map +1 -0
  16. package/dist/cjs/auth/oauth-callback-listener.d.cts +56 -0
  17. package/dist/cjs/auth/oauth-callback-listener.d.ts +56 -0
  18. package/dist/cjs/auth/oauth-callback-listener.js +333 -0
  19. package/dist/cjs/auth/oauth-callback-listener.js.map +1 -0
  20. package/dist/cjs/auth/pkce.d.cts +17 -0
  21. package/dist/cjs/auth/pkce.d.ts +17 -0
  22. package/dist/cjs/auth/pkce.js +192 -0
  23. package/dist/cjs/auth/pkce.js.map +1 -0
  24. package/dist/cjs/auth/rfc9728-discovery.d.cts +34 -0
  25. package/dist/cjs/auth/rfc9728-discovery.d.ts +34 -0
  26. package/dist/cjs/auth/rfc9728-discovery.js +436 -0
  27. package/dist/cjs/auth/rfc9728-discovery.js.map +1 -0
  28. package/dist/cjs/auth/types.d.cts +137 -0
  29. package/dist/cjs/auth/types.d.ts +137 -0
  30. package/dist/cjs/auth/types.js +9 -0
  31. package/dist/cjs/auth/types.js.map +1 -0
  32. package/dist/cjs/client-helpers.d.cts +55 -0
  33. package/dist/cjs/client-helpers.d.ts +55 -0
  34. package/dist/cjs/client-helpers.js +128 -0
  35. package/dist/cjs/client-helpers.js.map +1 -0
  36. package/dist/cjs/config/server-loader.d.cts +27 -0
  37. package/dist/cjs/config/server-loader.d.ts +27 -0
  38. package/dist/cjs/config/server-loader.js +111 -0
  39. package/dist/cjs/config/server-loader.js.map +1 -0
  40. package/dist/cjs/config/validate-config.d.cts +15 -0
  41. package/dist/cjs/config/validate-config.d.ts +15 -0
  42. package/dist/cjs/config/validate-config.js +128 -0
  43. package/dist/cjs/config/validate-config.js.map +1 -0
  44. package/dist/cjs/connection/connect-client.d.cts +59 -0
  45. package/dist/cjs/connection/connect-client.d.ts +59 -0
  46. package/dist/cjs/connection/connect-client.js +536 -0
  47. package/dist/cjs/connection/connect-client.js.map +1 -0
  48. package/dist/cjs/connection/existing-process-transport.d.cts +40 -0
  49. package/dist/cjs/connection/existing-process-transport.d.ts +40 -0
  50. package/dist/cjs/connection/existing-process-transport.js +274 -0
  51. package/dist/cjs/connection/existing-process-transport.js.map +1 -0
  52. package/dist/cjs/connection/types.d.cts +61 -0
  53. package/dist/cjs/connection/types.d.ts +61 -0
  54. package/dist/cjs/connection/types.js +53 -0
  55. package/dist/cjs/connection/types.js.map +1 -0
  56. package/dist/cjs/connection/wait-for-http-ready.d.cts +15 -0
  57. package/dist/cjs/connection/wait-for-http-ready.d.ts +15 -0
  58. package/dist/cjs/connection/wait-for-http-ready.js +232 -0
  59. package/dist/cjs/connection/wait-for-http-ready.js.map +1 -0
  60. package/dist/cjs/dcr/dcr-authenticator.d.cts +73 -0
  61. package/dist/cjs/dcr/dcr-authenticator.d.ts +73 -0
  62. package/dist/cjs/dcr/dcr-authenticator.js +655 -0
  63. package/dist/cjs/dcr/dcr-authenticator.js.map +1 -0
  64. package/dist/cjs/dcr/dynamic-client-registrar.d.cts +28 -0
  65. package/dist/cjs/dcr/dynamic-client-registrar.d.ts +28 -0
  66. package/dist/cjs/dcr/dynamic-client-registrar.js +245 -0
  67. package/dist/cjs/dcr/dynamic-client-registrar.js.map +1 -0
  68. package/dist/cjs/dcr/index.d.cts +8 -0
  69. package/dist/cjs/dcr/index.d.ts +8 -0
  70. package/dist/cjs/dcr/index.js +24 -0
  71. package/dist/cjs/dcr/index.js.map +1 -0
  72. package/dist/cjs/index.d.cts +21 -0
  73. package/dist/cjs/index.d.ts +21 -0
  74. package/dist/cjs/index.js +94 -0
  75. package/dist/cjs/index.js.map +1 -0
  76. package/dist/cjs/monkey-patches.d.cts +6 -0
  77. package/dist/cjs/monkey-patches.d.ts +6 -0
  78. package/dist/cjs/monkey-patches.js +236 -0
  79. package/dist/cjs/monkey-patches.js.map +1 -0
  80. package/dist/cjs/package.json +1 -0
  81. package/dist/cjs/response-wrappers.d.cts +41 -0
  82. package/dist/cjs/response-wrappers.d.ts +41 -0
  83. package/dist/cjs/response-wrappers.js +443 -0
  84. package/dist/cjs/response-wrappers.js.map +1 -0
  85. package/dist/cjs/search/index.d.cts +6 -0
  86. package/dist/cjs/search/index.d.ts +6 -0
  87. package/dist/cjs/search/index.js +25 -0
  88. package/dist/cjs/search/index.js.map +1 -0
  89. package/dist/cjs/search/search.d.cts +22 -0
  90. package/dist/cjs/search/search.d.ts +22 -0
  91. package/dist/cjs/search/search.js +630 -0
  92. package/dist/cjs/search/search.js.map +1 -0
  93. package/dist/cjs/search/types.d.cts +122 -0
  94. package/dist/cjs/search/types.d.ts +122 -0
  95. package/dist/cjs/search/types.js +10 -0
  96. package/dist/cjs/search/types.js.map +1 -0
  97. package/dist/cjs/spawn/spawn-server.d.cts +83 -0
  98. package/dist/cjs/spawn/spawn-server.d.ts +83 -0
  99. package/dist/cjs/spawn/spawn-server.js +410 -0
  100. package/dist/cjs/spawn/spawn-server.js.map +1 -0
  101. package/dist/cjs/spawn/spawn-servers.d.cts +151 -0
  102. package/dist/cjs/spawn/spawn-servers.d.ts +151 -0
  103. package/dist/cjs/spawn/spawn-servers.js +911 -0
  104. package/dist/cjs/spawn/spawn-servers.js.map +1 -0
  105. package/dist/cjs/types.d.cts +11 -0
  106. package/dist/cjs/types.d.ts +11 -0
  107. package/dist/cjs/types.js +10 -0
  108. package/dist/cjs/types.js.map +1 -0
  109. package/dist/cjs/utils/logger.d.cts +24 -0
  110. package/dist/cjs/utils/logger.d.ts +24 -0
  111. package/dist/cjs/utils/logger.js +80 -0
  112. package/dist/cjs/utils/logger.js.map +1 -0
  113. package/dist/cjs/utils/path-utils.d.cts +45 -0
  114. package/dist/cjs/utils/path-utils.d.ts +45 -0
  115. package/dist/cjs/utils/path-utils.js +158 -0
  116. package/dist/cjs/utils/path-utils.js.map +1 -0
  117. package/dist/cjs/utils/sanitizer.d.cts +30 -0
  118. package/dist/cjs/utils/sanitizer.d.ts +30 -0
  119. package/dist/cjs/utils/sanitizer.js +124 -0
  120. package/dist/cjs/utils/sanitizer.js.map +1 -0
  121. package/dist/esm/auth/capability-discovery.d.ts +25 -0
  122. package/dist/esm/auth/capability-discovery.js +110 -0
  123. package/dist/esm/auth/capability-discovery.js.map +1 -0
  124. package/dist/esm/auth/index.d.ts +9 -0
  125. package/dist/esm/auth/index.js +6 -0
  126. package/dist/esm/auth/index.js.map +1 -0
  127. package/dist/esm/auth/interactive-oauth-flow.d.ts +58 -0
  128. package/dist/esm/auth/interactive-oauth-flow.js +217 -0
  129. package/dist/esm/auth/interactive-oauth-flow.js.map +1 -0
  130. package/dist/esm/auth/oauth-callback-listener.d.ts +56 -0
  131. package/dist/esm/auth/oauth-callback-listener.js +166 -0
  132. package/dist/esm/auth/oauth-callback-listener.js.map +1 -0
  133. package/dist/esm/auth/pkce.d.ts +17 -0
  134. package/dist/esm/auth/pkce.js +41 -0
  135. package/dist/esm/auth/pkce.js.map +1 -0
  136. package/dist/esm/auth/rfc9728-discovery.d.ts +34 -0
  137. package/dist/esm/auth/rfc9728-discovery.js +157 -0
  138. package/dist/esm/auth/rfc9728-discovery.js.map +1 -0
  139. package/dist/esm/auth/types.d.ts +137 -0
  140. package/dist/esm/auth/types.js +7 -0
  141. package/dist/esm/auth/types.js.map +1 -0
  142. package/dist/esm/client-helpers.d.ts +55 -0
  143. package/dist/esm/client-helpers.js +81 -0
  144. package/dist/esm/client-helpers.js.map +1 -0
  145. package/dist/esm/config/server-loader.d.ts +27 -0
  146. package/dist/esm/config/server-loader.js +49 -0
  147. package/dist/esm/config/server-loader.js.map +1 -0
  148. package/dist/esm/config/validate-config.d.ts +15 -0
  149. package/dist/esm/config/validate-config.js +76 -0
  150. package/dist/esm/config/validate-config.js.map +1 -0
  151. package/dist/esm/connection/connect-client.d.ts +59 -0
  152. package/dist/esm/connection/connect-client.js +272 -0
  153. package/dist/esm/connection/connect-client.js.map +1 -0
  154. package/dist/esm/connection/existing-process-transport.d.ts +40 -0
  155. package/dist/esm/connection/existing-process-transport.js +103 -0
  156. package/dist/esm/connection/existing-process-transport.js.map +1 -0
  157. package/dist/esm/connection/types.d.ts +61 -0
  158. package/dist/esm/connection/types.js +34 -0
  159. package/dist/esm/connection/types.js.map +1 -0
  160. package/dist/esm/connection/wait-for-http-ready.d.ts +15 -0
  161. package/dist/esm/connection/wait-for-http-ready.js +43 -0
  162. package/dist/esm/connection/wait-for-http-ready.js.map +1 -0
  163. package/dist/esm/dcr/dcr-authenticator.d.ts +73 -0
  164. package/dist/esm/dcr/dcr-authenticator.js +235 -0
  165. package/dist/esm/dcr/dcr-authenticator.js.map +1 -0
  166. package/dist/esm/dcr/dynamic-client-registrar.d.ts +28 -0
  167. package/dist/esm/dcr/dynamic-client-registrar.js +66 -0
  168. package/dist/esm/dcr/dynamic-client-registrar.js.map +1 -0
  169. package/dist/esm/dcr/index.d.ts +8 -0
  170. package/dist/esm/dcr/index.js +5 -0
  171. package/dist/esm/dcr/index.js.map +1 -0
  172. package/dist/esm/index.d.ts +21 -0
  173. package/dist/esm/index.js +22 -0
  174. package/dist/esm/index.js.map +1 -0
  175. package/dist/esm/monkey-patches.d.ts +6 -0
  176. package/dist/esm/monkey-patches.js +32 -0
  177. package/dist/esm/monkey-patches.js.map +1 -0
  178. package/dist/esm/package.json +1 -0
  179. package/dist/esm/response-wrappers.d.ts +41 -0
  180. package/dist/esm/response-wrappers.js +201 -0
  181. package/dist/esm/response-wrappers.js.map +1 -0
  182. package/dist/esm/search/index.d.ts +6 -0
  183. package/dist/esm/search/index.js +3 -0
  184. package/dist/esm/search/index.js.map +1 -0
  185. package/dist/esm/search/search.d.ts +22 -0
  186. package/dist/esm/search/search.js +236 -0
  187. package/dist/esm/search/search.js.map +1 -0
  188. package/dist/esm/search/types.d.ts +122 -0
  189. package/dist/esm/search/types.js +8 -0
  190. package/dist/esm/search/types.js.map +1 -0
  191. package/dist/esm/spawn/spawn-server.d.ts +83 -0
  192. package/dist/esm/spawn/spawn-server.js +145 -0
  193. package/dist/esm/spawn/spawn-server.js.map +1 -0
  194. package/dist/esm/spawn/spawn-servers.d.ts +151 -0
  195. package/dist/esm/spawn/spawn-servers.js +406 -0
  196. package/dist/esm/spawn/spawn-servers.js.map +1 -0
  197. package/dist/esm/types.d.ts +11 -0
  198. package/dist/esm/types.js +9 -0
  199. package/dist/esm/types.js.map +1 -0
  200. package/dist/esm/utils/logger.d.ts +24 -0
  201. package/dist/esm/utils/logger.js +59 -0
  202. package/dist/esm/utils/logger.js.map +1 -0
  203. package/dist/esm/utils/path-utils.d.ts +45 -0
  204. package/dist/esm/utils/path-utils.js +89 -0
  205. package/dist/esm/utils/path-utils.js.map +1 -0
  206. package/dist/esm/utils/sanitizer.d.ts +30 -0
  207. package/dist/esm/utils/sanitizer.js +43 -0
  208. package/dist/esm/utils/sanitizer.js.map +1 -0
  209. package/package.json +92 -0
  210. package/schemas/servers.d.ts +90 -0
  211. package/schemas/servers.schema.json +104 -0
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Shared types for OAuth and DCR authentication
3
+ */ /**
4
+ * OAuth callback result from authorization server
5
+ */ /**
6
+ * Options for OAuth authorization flow
7
+ */ export { };
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/libs/client/src/auth/types.ts"],"sourcesContent":["/**\n * Shared types for OAuth and DCR authentication\n */\n\n/**\n * OAuth callback result from authorization server\n */\nexport interface CallbackResult {\n /** Authorization code from OAuth server */\n code: string;\n /** State parameter for CSRF protection */\n state?: string;\n}\n\n/**\n * PKCE (Proof Key for Code Exchange) parameters (RFC 7636)\n * Used to secure OAuth 2.0 authorization code flow for public clients\n */\nexport interface PkceParams {\n /** Code verifier - cryptographically random string (43-128 characters) */\n codeVerifier: string;\n /** Code challenge - derived from code verifier using challenge method */\n codeChallenge: string;\n /** Code challenge method - S256 (SHA-256) or plain */\n codeChallengeMethod: 'S256' | 'plain';\n}\n\n/**\n * OAuth token set with access and refresh tokens\n */\nexport interface TokenSet {\n /** Access token for API requests */\n accessToken: string;\n /** Refresh token for obtaining new access tokens */\n refreshToken: string;\n /** Timestamp when access token expires (milliseconds since epoch) */\n expiresAt: number;\n /** Scopes granted for this token set */\n scopes?: string[];\n /** Client ID used for DCR registration (stored for future use) */\n clientId?: string;\n /** Client secret used for DCR registration (stored for future use) */\n clientSecret?: string;\n}\n\n/**\n * OAuth 2.0 Protected Resource Metadata (RFC 9728)\n * Response from .well-known/oauth-protected-resource endpoint\n */\nexport interface ProtectedResourceMetadata {\n /** The protected resource identifier */\n resource: string;\n /** List of authorization server URLs that can issue tokens for this resource */\n authorization_servers: string[];\n /** Optional list of scopes supported by this resource */\n scopes_supported?: string[];\n /** Optional list of bearer token methods supported (header, query, body) */\n bearer_methods_supported?: string[];\n}\n\n/**\n * OAuth 2.0 Authorization Server Metadata (RFC 8414)\n * Response from .well-known/oauth-authorization-server endpoint\n */\nexport interface AuthorizationServerMetadata {\n /** The authorization server's issuer identifier */\n issuer?: string;\n /** URL of the authorization endpoint */\n authorization_endpoint?: string;\n /** URL of the token endpoint */\n token_endpoint?: string;\n /** URL of the client registration endpoint (DCR - RFC 7591) */\n registration_endpoint?: string;\n /** URL of the token introspection endpoint */\n introspection_endpoint?: string;\n /** List of OAuth scopes supported by the authorization server */\n scopes_supported?: string[];\n /** Response types supported (code, token, etc.) */\n response_types_supported?: string[];\n /** Grant types supported (authorization_code, refresh_token, etc.) */\n grant_types_supported?: string[];\n /** Token endpoint authentication methods supported */\n token_endpoint_auth_methods_supported?: string[];\n}\n\n/**\n * OAuth server capabilities discovered from .well-known endpoint\n */\nexport interface AuthCapabilities {\n /** Whether the server supports Dynamic Client Registration (RFC 7591) */\n supportsDcr: boolean;\n /** DCR client registration endpoint */\n registrationEndpoint?: string;\n /** OAuth authorization endpoint */\n authorizationEndpoint?: string;\n /** OAuth token endpoint */\n tokenEndpoint?: string;\n /** Token introspection endpoint */\n introspectionEndpoint?: string;\n /** Supported OAuth scopes */\n scopes?: string[];\n}\n\n/**\n * Client credentials from DCR registration\n */\nexport interface ClientCredentials {\n /** OAuth client ID */\n clientId: string;\n /** OAuth client secret */\n clientSecret: string;\n /** Timestamp when client was registered */\n issuedAt?: number;\n}\n\n/**\n * Options for DCR client registration\n */\nexport interface DcrRegistrationOptions {\n /** Client name to register */\n clientName?: string;\n /** Redirect URI for OAuth callback */\n redirectUri?: string;\n}\n\n/**\n * Options for OAuth authorization flow\n */\nexport interface OAuthFlowOptions {\n /** Port for OAuth callback listener (required - use get-port to find available port) */\n port: number;\n /** Redirect URI for OAuth callback (optional - will be built from port if not provided) */\n redirectUri?: string;\n /** OAuth scopes to request */\n scopes?: string[];\n /** Resource parameter (RFC 8707) - target resource server identifier */\n resource?: string;\n /** Enable PKCE (RFC 7636) - recommended for all clients, required for public clients */\n pkce?: boolean;\n /** Headless mode (don't open browser) */\n headless?: boolean;\n /** Timeout for callback (milliseconds) */\n timeout?: number;\n /** Optional logger for debug output (defaults to singleton logger) */\n logger?: import('../utils/logger.ts').Logger;\n}\n"],"names":[],"mappings":"AAAA;;CAEC,GAED;;CAEC,GAuHD;;CAEC,GACD,WAiBC"}
@@ -0,0 +1,55 @@
1
+ import type { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import type { RequestOptions } from '@modelcontextprotocol/sdk/shared/protocol.js';
3
+ import type { ToolArguments } from './connection/types.js';
4
+ import { PromptResponseWrapper, ResourceResponseWrapper, ToolResponseWrapper } from './response-wrappers.js';
5
+ export type PromptArguments = Record<string, string>;
6
+ type NativeCallToolParams = Parameters<Client['callTool']>;
7
+ type NativeCallToolReturn = ReturnType<Client['callTool']>;
8
+ /**
9
+ * Fetch-style wrapper returned by `ManagedClient.callTool()`.
10
+ * @public
11
+ */
12
+ export type WrappedCallToolReturn = Promise<ToolResponseWrapper>;
13
+ type NativeGetPromptParams = Parameters<Client['getPrompt']>;
14
+ type NativeGetPromptReturn = ReturnType<Client['getPrompt']>;
15
+ /**
16
+ * Fetch-style wrapper returned by `ManagedClient.getPrompt()`.
17
+ * @public
18
+ */
19
+ export type WrappedGetPromptReturn = Promise<PromptResponseWrapper>;
20
+ type NativeReadResourceParams = Parameters<Client['readResource']>;
21
+ type NativeReadResourceReturn = ReturnType<Client['readResource']>;
22
+ /**
23
+ * Fetch-style wrapper returned by `ManagedClient.readResource()`.
24
+ * @public
25
+ */
26
+ export type WrappedReadResourceReturn = Promise<ResourceResponseWrapper>;
27
+ /**
28
+ * Client returned by registry.connect() with convenience overloads for
29
+ * calling tools, reading resources, and getting prompts using simple arguments.
30
+ */
31
+ export type ManagedClient = Omit<Client, 'callTool' | 'getPrompt' | 'readResource'> & {
32
+ /** Name of the server this client is connected to. */
33
+ readonly serverName: string;
34
+ /** Underlying MCP SDK client for advanced scenarios. */
35
+ readonly nativeClient: Client;
36
+ callTool(toolName: string, args?: ToolArguments, requestOptions?: RequestOptions): WrappedCallToolReturn;
37
+ callTool(invocation: NativeCallToolParams[0], sessionId?: NativeCallToolParams[1], requestOptions?: NativeCallToolParams[2]): WrappedCallToolReturn;
38
+ callToolRaw(toolName: string, args?: ToolArguments, requestOptions?: RequestOptions): NativeCallToolReturn;
39
+ callToolRaw(invocation: NativeCallToolParams[0], sessionId?: NativeCallToolParams[1], requestOptions?: NativeCallToolParams[2]): NativeCallToolReturn;
40
+ getPrompt(name: string, args?: PromptArguments, requestOptions?: NativeGetPromptParams[1]): WrappedGetPromptReturn;
41
+ getPrompt(invocation: NativeGetPromptParams[0], requestOptions?: NativeGetPromptParams[1]): WrappedGetPromptReturn;
42
+ getPromptRaw(name: string, args?: PromptArguments, requestOptions?: NativeGetPromptParams[1]): NativeGetPromptReturn;
43
+ getPromptRaw(invocation: NativeGetPromptParams[0], requestOptions?: NativeGetPromptParams[1]): NativeGetPromptReturn;
44
+ readResource(uri: string, requestOptions?: NativeReadResourceParams[1]): WrappedReadResourceReturn;
45
+ readResource(request: NativeReadResourceParams[0], requestOptions?: NativeReadResourceParams[1]): WrappedReadResourceReturn;
46
+ readResourceRaw(uri: string, requestOptions?: NativeReadResourceParams[1]): NativeReadResourceReturn;
47
+ readResourceRaw(request: NativeReadResourceParams[0], requestOptions?: NativeReadResourceParams[1]): NativeReadResourceReturn;
48
+ };
49
+ /**
50
+ * Enhance an MCP SDK client with convenience overloads.
51
+ */
52
+ export declare function decorateClient(client: Client, metadata: {
53
+ serverName: string;
54
+ }): ManagedClient;
55
+ export {};
@@ -0,0 +1,81 @@
1
+ import { PromptResponseWrapper, ResourceResponseWrapper, ToolResponseWrapper } from './response-wrappers.js';
2
+ /**
3
+ * Enhance an MCP SDK client with convenience overloads.
4
+ */ export function decorateClient(client, metadata) {
5
+ const enhanced = client;
6
+ Object.defineProperty(enhanced, 'serverName', {
7
+ value: metadata.serverName,
8
+ enumerable: true,
9
+ configurable: false,
10
+ writable: false
11
+ });
12
+ Object.defineProperty(enhanced, 'nativeClient', {
13
+ value: client,
14
+ enumerable: false,
15
+ configurable: false,
16
+ writable: false
17
+ });
18
+ const nativeCallTool = client.callTool.bind(client);
19
+ const wrapCallTool = (promise)=>promise.then((payload)=>new ToolResponseWrapper(payload));
20
+ enhanced.callTool = (nameOrInvocation, argsOrSession, requestOptions)=>{
21
+ if (typeof nameOrInvocation === 'string') {
22
+ return wrapCallTool(nativeCallTool({
23
+ name: nameOrInvocation,
24
+ arguments: argsOrSession !== null && argsOrSession !== void 0 ? argsOrSession : {}
25
+ }, undefined, requestOptions));
26
+ }
27
+ return wrapCallTool(nativeCallTool(nameOrInvocation, argsOrSession, requestOptions));
28
+ };
29
+ enhanced.callToolRaw = (nameOrInvocation, argsOrSession, requestOptions)=>{
30
+ if (typeof nameOrInvocation === 'string') {
31
+ return nativeCallTool({
32
+ name: nameOrInvocation,
33
+ arguments: argsOrSession !== null && argsOrSession !== void 0 ? argsOrSession : {}
34
+ }, undefined, requestOptions);
35
+ }
36
+ return nativeCallTool(nameOrInvocation, argsOrSession, requestOptions);
37
+ };
38
+ const nativeGetPrompt = client.getPrompt.bind(client);
39
+ const wrapPrompt = (promise)=>promise.then((payload)=>new PromptResponseWrapper(payload));
40
+ enhanced.getPrompt = (nameOrParams, argsOrOptions, requestOptions)=>{
41
+ if (typeof nameOrParams === 'string') {
42
+ return wrapPrompt(nativeGetPrompt({
43
+ name: nameOrParams,
44
+ ...argsOrOptions ? {
45
+ arguments: argsOrOptions
46
+ } : {}
47
+ }, requestOptions));
48
+ }
49
+ return wrapPrompt(nativeGetPrompt(nameOrParams, argsOrOptions));
50
+ };
51
+ enhanced.getPromptRaw = (nameOrParams, argsOrOptions, requestOptions)=>{
52
+ if (typeof nameOrParams === 'string') {
53
+ return nativeGetPrompt({
54
+ name: nameOrParams,
55
+ ...argsOrOptions ? {
56
+ arguments: argsOrOptions
57
+ } : {}
58
+ }, requestOptions);
59
+ }
60
+ return nativeGetPrompt(nameOrParams, argsOrOptions);
61
+ };
62
+ const nativeReadResource = client.readResource.bind(client);
63
+ const wrapResource = (promise)=>promise.then((payload)=>new ResourceResponseWrapper(payload));
64
+ enhanced.readResource = (uriOrRequest, requestOptions)=>{
65
+ if (typeof uriOrRequest === 'string') {
66
+ return wrapResource(nativeReadResource({
67
+ uri: uriOrRequest
68
+ }, requestOptions));
69
+ }
70
+ return wrapResource(nativeReadResource(uriOrRequest, requestOptions));
71
+ };
72
+ enhanced.readResourceRaw = (uriOrRequest, requestOptions)=>{
73
+ if (typeof uriOrRequest === 'string') {
74
+ return nativeReadResource({
75
+ uri: uriOrRequest
76
+ }, requestOptions);
77
+ }
78
+ return nativeReadResource(uriOrRequest, requestOptions);
79
+ };
80
+ return enhanced;
81
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/libs/client/src/client-helpers.ts"],"sourcesContent":["import type { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport type { RequestOptions } from '@modelcontextprotocol/sdk/shared/protocol.js';\nimport type { ToolArguments } from './connection/types.ts';\nimport { type NativeCallToolResponse, type NativeGetPromptResponse, type NativeReadResourceResponse, PromptResponseWrapper, ResourceResponseWrapper, ToolResponseWrapper } from './response-wrappers.ts';\n\nexport type PromptArguments = Record<string, string>;\n\ntype NativeCallToolParams = Parameters<Client['callTool']>;\ntype NativeCallToolReturn = ReturnType<Client['callTool']>;\n/**\n * Fetch-style wrapper returned by `ManagedClient.callTool()`.\n * @public\n */\nexport type WrappedCallToolReturn = Promise<ToolResponseWrapper>;\n\ntype NativeGetPromptParams = Parameters<Client['getPrompt']>;\ntype NativeGetPromptReturn = ReturnType<Client['getPrompt']>;\n/**\n * Fetch-style wrapper returned by `ManagedClient.getPrompt()`.\n * @public\n */\nexport type WrappedGetPromptReturn = Promise<PromptResponseWrapper>;\n\ntype NativeReadResourceParams = Parameters<Client['readResource']>;\ntype NativeReadResourceReturn = ReturnType<Client['readResource']>;\n/**\n * Fetch-style wrapper returned by `ManagedClient.readResource()`.\n * @public\n */\nexport type WrappedReadResourceReturn = Promise<ResourceResponseWrapper>;\n\n/**\n * Client returned by registry.connect() with convenience overloads for\n * calling tools, reading resources, and getting prompts using simple arguments.\n */\nexport type ManagedClient = Omit<Client, 'callTool' | 'getPrompt' | 'readResource'> & {\n /** Name of the server this client is connected to. */\n readonly serverName: string;\n /** Underlying MCP SDK client for advanced scenarios. */\n readonly nativeClient: Client;\n\n callTool(toolName: string, args?: ToolArguments, requestOptions?: RequestOptions): WrappedCallToolReturn;\n callTool(invocation: NativeCallToolParams[0], sessionId?: NativeCallToolParams[1], requestOptions?: NativeCallToolParams[2]): WrappedCallToolReturn;\n callToolRaw(toolName: string, args?: ToolArguments, requestOptions?: RequestOptions): NativeCallToolReturn;\n callToolRaw(invocation: NativeCallToolParams[0], sessionId?: NativeCallToolParams[1], requestOptions?: NativeCallToolParams[2]): NativeCallToolReturn;\n\n getPrompt(name: string, args?: PromptArguments, requestOptions?: NativeGetPromptParams[1]): WrappedGetPromptReturn;\n getPrompt(invocation: NativeGetPromptParams[0], requestOptions?: NativeGetPromptParams[1]): WrappedGetPromptReturn;\n getPromptRaw(name: string, args?: PromptArguments, requestOptions?: NativeGetPromptParams[1]): NativeGetPromptReturn;\n getPromptRaw(invocation: NativeGetPromptParams[0], requestOptions?: NativeGetPromptParams[1]): NativeGetPromptReturn;\n\n readResource(uri: string, requestOptions?: NativeReadResourceParams[1]): WrappedReadResourceReturn;\n readResource(request: NativeReadResourceParams[0], requestOptions?: NativeReadResourceParams[1]): WrappedReadResourceReturn;\n readResourceRaw(uri: string, requestOptions?: NativeReadResourceParams[1]): NativeReadResourceReturn;\n readResourceRaw(request: NativeReadResourceParams[0], requestOptions?: NativeReadResourceParams[1]): NativeReadResourceReturn;\n};\n\n/**\n * Enhance an MCP SDK client with convenience overloads.\n */\nexport function decorateClient(client: Client, metadata: { serverName: string }): ManagedClient {\n const enhanced = client as unknown as ManagedClient;\n\n Object.defineProperty(enhanced, 'serverName', {\n value: metadata.serverName,\n enumerable: true,\n configurable: false,\n writable: false,\n });\n Object.defineProperty(enhanced, 'nativeClient', {\n value: client,\n enumerable: false,\n configurable: false,\n writable: false,\n });\n\n const nativeCallTool = client.callTool.bind(client);\n const wrapCallTool = (promise: NativeCallToolReturn): WrappedCallToolReturn => promise.then((payload) => new ToolResponseWrapper(payload as NativeCallToolResponse));\n\n enhanced.callTool = ((nameOrInvocation: string | NativeCallToolParams[0], argsOrSession?: ToolArguments | NativeCallToolParams[1], requestOptions?: NativeCallToolParams[2]) => {\n if (typeof nameOrInvocation === 'string') {\n return wrapCallTool(nativeCallTool({ name: nameOrInvocation, arguments: (argsOrSession as ToolArguments) ?? {} }, undefined, requestOptions));\n }\n return wrapCallTool(nativeCallTool(nameOrInvocation, argsOrSession as NativeCallToolParams[1], requestOptions));\n }) as ManagedClient['callTool'];\n\n enhanced.callToolRaw = ((nameOrInvocation: string | NativeCallToolParams[0], argsOrSession?: ToolArguments | NativeCallToolParams[1], requestOptions?: NativeCallToolParams[2]) => {\n if (typeof nameOrInvocation === 'string') {\n return nativeCallTool({ name: nameOrInvocation, arguments: (argsOrSession as ToolArguments) ?? {} }, undefined, requestOptions);\n }\n return nativeCallTool(nameOrInvocation, argsOrSession as NativeCallToolParams[1], requestOptions);\n }) as ManagedClient['callToolRaw'];\n\n const nativeGetPrompt = client.getPrompt.bind(client);\n const wrapPrompt = (promise: NativeGetPromptReturn): WrappedGetPromptReturn => promise.then((payload) => new PromptResponseWrapper(payload as NativeGetPromptResponse));\n\n enhanced.getPrompt = ((nameOrParams: string | NativeGetPromptParams[0], argsOrOptions?: PromptArguments | NativeGetPromptParams[1], requestOptions?: NativeGetPromptParams[1]) => {\n if (typeof nameOrParams === 'string') {\n return wrapPrompt(nativeGetPrompt({ name: nameOrParams, ...(argsOrOptions ? { arguments: argsOrOptions as PromptArguments } : {}) }, requestOptions));\n }\n return wrapPrompt(nativeGetPrompt(nameOrParams, argsOrOptions as NativeGetPromptParams[1]));\n }) as ManagedClient['getPrompt'];\n\n enhanced.getPromptRaw = ((nameOrParams: string | NativeGetPromptParams[0], argsOrOptions?: PromptArguments | NativeGetPromptParams[1], requestOptions?: NativeGetPromptParams[1]) => {\n if (typeof nameOrParams === 'string') {\n return nativeGetPrompt({ name: nameOrParams, ...(argsOrOptions ? { arguments: argsOrOptions as PromptArguments } : {}) }, requestOptions);\n }\n return nativeGetPrompt(nameOrParams, argsOrOptions as NativeGetPromptParams[1]);\n }) as ManagedClient['getPromptRaw'];\n\n const nativeReadResource = client.readResource.bind(client);\n const wrapResource = (promise: NativeReadResourceReturn): WrappedReadResourceReturn => promise.then((payload) => new ResourceResponseWrapper(payload as NativeReadResourceResponse));\n\n enhanced.readResource = ((uriOrRequest: string | NativeReadResourceParams[0], requestOptions?: NativeReadResourceParams[1]) => {\n if (typeof uriOrRequest === 'string') {\n return wrapResource(nativeReadResource({ uri: uriOrRequest }, requestOptions));\n }\n return wrapResource(nativeReadResource(uriOrRequest, requestOptions));\n }) as ManagedClient['readResource'];\n\n enhanced.readResourceRaw = ((uriOrRequest: string | NativeReadResourceParams[0], requestOptions?: NativeReadResourceParams[1]) => {\n if (typeof uriOrRequest === 'string') {\n return nativeReadResource({ uri: uriOrRequest }, requestOptions);\n }\n return nativeReadResource(uriOrRequest, requestOptions);\n }) as ManagedClient['readResourceRaw'];\n\n return enhanced;\n}\n"],"names":["PromptResponseWrapper","ResourceResponseWrapper","ToolResponseWrapper","decorateClient","client","metadata","enhanced","Object","defineProperty","value","serverName","enumerable","configurable","writable","nativeCallTool","callTool","bind","wrapCallTool","promise","then","payload","nameOrInvocation","argsOrSession","requestOptions","name","arguments","undefined","callToolRaw","nativeGetPrompt","getPrompt","wrapPrompt","nameOrParams","argsOrOptions","getPromptRaw","nativeReadResource","readResource","wrapResource","uriOrRequest","uri","readResourceRaw"],"mappings":"AAGA,SAAqGA,qBAAqB,EAAEC,uBAAuB,EAAEC,mBAAmB,QAAQ,yBAAyB;AAsDzM;;CAEC,GACD,OAAO,SAASC,eAAeC,MAAc,EAAEC,QAAgC;IAC7E,MAAMC,WAAWF;IAEjBG,OAAOC,cAAc,CAACF,UAAU,cAAc;QAC5CG,OAAOJ,SAASK,UAAU;QAC1BC,YAAY;QACZC,cAAc;QACdC,UAAU;IACZ;IACAN,OAAOC,cAAc,CAACF,UAAU,gBAAgB;QAC9CG,OAAOL;QACPO,YAAY;QACZC,cAAc;QACdC,UAAU;IACZ;IAEA,MAAMC,iBAAiBV,OAAOW,QAAQ,CAACC,IAAI,CAACZ;IAC5C,MAAMa,eAAe,CAACC,UAAyDA,QAAQC,IAAI,CAAC,CAACC,UAAY,IAAIlB,oBAAoBkB;IAEjId,SAASS,QAAQ,GAAI,CAACM,kBAAoDC,eAAyDC;QACjI,IAAI,OAAOF,qBAAqB,UAAU;YACxC,OAAOJ,aAAaH,eAAe;gBAAEU,MAAMH;gBAAkBI,SAAS,EAAGH,0BAAAA,2BAAAA,gBAAmC,CAAC;YAAE,GAAGI,WAAWH;QAC/H;QACA,OAAON,aAAaH,eAAeO,kBAAkBC,eAA0CC;IACjG;IAEAjB,SAASqB,WAAW,GAAI,CAACN,kBAAoDC,eAAyDC;QACpI,IAAI,OAAOF,qBAAqB,UAAU;YACxC,OAAOP,eAAe;gBAAEU,MAAMH;gBAAkBI,SAAS,EAAGH,0BAAAA,2BAAAA,gBAAmC,CAAC;YAAE,GAAGI,WAAWH;QAClH;QACA,OAAOT,eAAeO,kBAAkBC,eAA0CC;IACpF;IAEA,MAAMK,kBAAkBxB,OAAOyB,SAAS,CAACb,IAAI,CAACZ;IAC9C,MAAM0B,aAAa,CAACZ,UAA2DA,QAAQC,IAAI,CAAC,CAACC,UAAY,IAAIpB,sBAAsBoB;IAEnId,SAASuB,SAAS,GAAI,CAACE,cAAiDC,eAA4DT;QAClI,IAAI,OAAOQ,iBAAiB,UAAU;YACpC,OAAOD,WAAWF,gBAAgB;gBAAEJ,MAAMO;gBAAc,GAAIC,gBAAgB;oBAAEP,WAAWO;gBAAiC,IAAI,CAAC,CAAC;YAAE,GAAGT;QACvI;QACA,OAAOO,WAAWF,gBAAgBG,cAAcC;IAClD;IAEA1B,SAAS2B,YAAY,GAAI,CAACF,cAAiDC,eAA4DT;QACrI,IAAI,OAAOQ,iBAAiB,UAAU;YACpC,OAAOH,gBAAgB;gBAAEJ,MAAMO;gBAAc,GAAIC,gBAAgB;oBAAEP,WAAWO;gBAAiC,IAAI,CAAC,CAAC;YAAE,GAAGT;QAC5H;QACA,OAAOK,gBAAgBG,cAAcC;IACvC;IAEA,MAAME,qBAAqB9B,OAAO+B,YAAY,CAACnB,IAAI,CAACZ;IACpD,MAAMgC,eAAe,CAAClB,UAAiEA,QAAQC,IAAI,CAAC,CAACC,UAAY,IAAInB,wBAAwBmB;IAE7Id,SAAS6B,YAAY,GAAI,CAACE,cAAoDd;QAC5E,IAAI,OAAOc,iBAAiB,UAAU;YACpC,OAAOD,aAAaF,mBAAmB;gBAAEI,KAAKD;YAAa,GAAGd;QAChE;QACA,OAAOa,aAAaF,mBAAmBG,cAAcd;IACvD;IAEAjB,SAASiC,eAAe,GAAI,CAACF,cAAoDd;QAC/E,IAAI,OAAOc,iBAAiB,UAAU;YACpC,OAAOH,mBAAmB;gBAAEI,KAAKD;YAAa,GAAGd;QACnD;QACA,OAAOW,mBAAmBG,cAAcd;IAC1C;IAEA,OAAOjB;AACT"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Load server definitions from .mcp.json (data-driven)
3
+ */
4
+ export interface McpServerConfig {
5
+ command: string;
6
+ args: string[];
7
+ env?: Record<string, string>;
8
+ }
9
+ export interface MCPConfiguration {
10
+ mcpServers: Record<string, McpServerConfig>;
11
+ }
12
+ /**
13
+ * Load available servers from resources/.mcp.json
14
+ */
15
+ export declare function loadAvailableServers(): MCPConfiguration;
16
+ /**
17
+ * Get list of all available server names
18
+ */
19
+ export declare function getAllServerNames(): string[];
20
+ /**
21
+ * Parse comma-separated server list or "all"
22
+ */
23
+ export declare function parseServerList(input: string): string[];
24
+ /**
25
+ * Get server configuration by name
26
+ */
27
+ export declare function getServerConfig(serverName: string): McpServerConfig;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Load server definitions from .mcp.json (data-driven)
3
+ */ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ // Get package root: dist/esm/lib -> ../../../ or dist/cjs/lib -> ../../../
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+ const packageRoot = path.resolve(__dirname, '../../..');
10
+ /**
11
+ * Load available servers from resources/.mcp.json
12
+ */ export function loadAvailableServers() {
13
+ const configPath = path.join(packageRoot, 'resources/.mcp.json');
14
+ if (!fs.existsSync(configPath)) {
15
+ throw new Error(`Server configuration not found: ${configPath}`);
16
+ }
17
+ const content = fs.readFileSync(configPath, 'utf-8');
18
+ return JSON.parse(content);
19
+ }
20
+ /**
21
+ * Get list of all available server names
22
+ */ export function getAllServerNames() {
23
+ const config = loadAvailableServers();
24
+ return Object.keys(config.mcpServers);
25
+ }
26
+ /**
27
+ * Parse comma-separated server list or "all"
28
+ */ export function parseServerList(input) {
29
+ const allServers = getAllServerNames();
30
+ if (input === 'all') {
31
+ return allServers;
32
+ }
33
+ const requested = input.split(',').map((s)=>s.trim());
34
+ const invalid = requested.filter((s)=>!allServers.includes(s));
35
+ if (invalid.length > 0) {
36
+ throw new Error(`Invalid server names: ${invalid.join(', ')}.\nAvailable: ${allServers.join(', ')}`);
37
+ }
38
+ return requested;
39
+ }
40
+ /**
41
+ * Get server configuration by name
42
+ */ export function getServerConfig(serverName) {
43
+ const config = loadAvailableServers();
44
+ const serverConfig = config.mcpServers[serverName];
45
+ if (!serverConfig) {
46
+ throw new Error(`Unknown server: ${serverName}.\nAvailable: ${getAllServerNames().join(', ')}`);
47
+ }
48
+ return serverConfig;
49
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/libs/client/src/config/server-loader.ts"],"sourcesContent":["/**\n * Load server definitions from .mcp.json (data-driven)\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\n\n// Get package root: dist/esm/lib -> ../../../ or dist/cjs/lib -> ../../../\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\nconst packageRoot = path.resolve(__dirname, '../../..');\n\nexport interface McpServerConfig {\n command: string;\n args: string[];\n env?: Record<string, string>;\n}\n\nexport interface MCPConfiguration {\n mcpServers: Record<string, McpServerConfig>;\n}\n\n/**\n * Load available servers from resources/.mcp.json\n */\nexport function loadAvailableServers(): MCPConfiguration {\n const configPath = path.join(packageRoot, 'resources/.mcp.json');\n\n if (!fs.existsSync(configPath)) {\n throw new Error(`Server configuration not found: ${configPath}`);\n }\n\n const content = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(content) as MCPConfiguration;\n}\n\n/**\n * Get list of all available server names\n */\nexport function getAllServerNames(): string[] {\n const config = loadAvailableServers();\n return Object.keys(config.mcpServers);\n}\n\n/**\n * Parse comma-separated server list or \"all\"\n */\nexport function parseServerList(input: string): string[] {\n const allServers = getAllServerNames();\n\n if (input === 'all') {\n return allServers;\n }\n\n const requested = input.split(',').map((s) => s.trim());\n const invalid = requested.filter((s) => !allServers.includes(s));\n\n if (invalid.length > 0) {\n throw new Error(`Invalid server names: ${invalid.join(', ')}.\\nAvailable: ${allServers.join(', ')}`);\n }\n\n return requested;\n}\n\n/**\n * Get server configuration by name\n */\nexport function getServerConfig(serverName: string): McpServerConfig {\n const config = loadAvailableServers();\n const serverConfig = config.mcpServers[serverName];\n\n if (!serverConfig) {\n throw new Error(`Unknown server: ${serverName}.\\nAvailable: ${getAllServerNames().join(', ')}`);\n }\n\n return serverConfig;\n}\n"],"names":["fs","path","fileURLToPath","__filename","url","__dirname","dirname","packageRoot","resolve","loadAvailableServers","configPath","join","existsSync","Error","content","readFileSync","JSON","parse","getAllServerNames","config","Object","keys","mcpServers","parseServerList","input","allServers","requested","split","map","s","trim","invalid","filter","includes","length","getServerConfig","serverName","serverConfig"],"mappings":"AAAA;;CAEC,GAED,YAAYA,QAAQ,KAAK;AACzB,YAAYC,UAAU,OAAO;AAC7B,SAASC,aAAa,QAAQ,MAAM;AAEpC,2EAA2E;AAC3E,MAAMC,aAAaD,cAAc,YAAYE,GAAG;AAChD,MAAMC,YAAYJ,KAAKK,OAAO,CAACH;AAC/B,MAAMI,cAAcN,KAAKO,OAAO,CAACH,WAAW;AAY5C;;CAEC,GACD,OAAO,SAASI;IACd,MAAMC,aAAaT,KAAKU,IAAI,CAACJ,aAAa;IAE1C,IAAI,CAACP,GAAGY,UAAU,CAACF,aAAa;QAC9B,MAAM,IAAIG,MAAM,CAAC,gCAAgC,EAAEH,YAAY;IACjE;IAEA,MAAMI,UAAUd,GAAGe,YAAY,CAACL,YAAY;IAC5C,OAAOM,KAAKC,KAAK,CAACH;AACpB;AAEA;;CAEC,GACD,OAAO,SAASI;IACd,MAAMC,SAASV;IACf,OAAOW,OAAOC,IAAI,CAACF,OAAOG,UAAU;AACtC;AAEA;;CAEC,GACD,OAAO,SAASC,gBAAgBC,KAAa;IAC3C,MAAMC,aAAaP;IAEnB,IAAIM,UAAU,OAAO;QACnB,OAAOC;IACT;IAEA,MAAMC,YAAYF,MAAMG,KAAK,CAAC,KAAKC,GAAG,CAAC,CAACC,IAAMA,EAAEC,IAAI;IACpD,MAAMC,UAAUL,UAAUM,MAAM,CAAC,CAACH,IAAM,CAACJ,WAAWQ,QAAQ,CAACJ;IAE7D,IAAIE,QAAQG,MAAM,GAAG,GAAG;QACtB,MAAM,IAAIrB,MAAM,CAAC,sBAAsB,EAAEkB,QAAQpB,IAAI,CAAC,MAAM,cAAc,EAAEc,WAAWd,IAAI,CAAC,OAAO;IACrG;IAEA,OAAOe;AACT;AAEA;;CAEC,GACD,OAAO,SAASS,gBAAgBC,UAAkB;IAChD,MAAMjB,SAASV;IACf,MAAM4B,eAAelB,OAAOG,UAAU,CAACc,WAAW;IAElD,IAAI,CAACC,cAAc;QACjB,MAAM,IAAIxB,MAAM,CAAC,gBAAgB,EAAEuB,WAAW,cAAc,EAAElB,oBAAoBP,IAAI,CAAC,OAAO;IAChG;IAEA,OAAO0B;AACT"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Validation result for servers configuration
3
+ */
4
+ export interface ValidationResult {
5
+ valid: boolean;
6
+ errors?: string[];
7
+ warnings?: string[];
8
+ }
9
+ /**
10
+ * Validate servers configuration against JSON Schema
11
+ *
12
+ * @param servers - Servers configuration object to validate (map of server names to configs)
13
+ * @returns ValidationResult with valid flag, errors, and warnings
14
+ */
15
+ export declare function validateServers(servers: unknown): ValidationResult;
@@ -0,0 +1,76 @@
1
+ import { Ajv } from 'ajv';
2
+ import * as fs from 'fs';
3
+ import { createRequire } from 'module';
4
+ import moduleRoot from 'module-root-sync';
5
+ import * as path from 'path';
6
+ // Import ajv-formats (CommonJS module - use createRequire for ESM compatibility)
7
+ const require = createRequire(import.meta.url);
8
+ const addFormats = require('ajv-formats');
9
+ const packageRoot = moduleRoot(import.meta.filename);
10
+ // Module-level cache for schema and validator
11
+ let schemaCache = null;
12
+ let validatorCache = null;
13
+ /**
14
+ * Get servers schema (loads once from bundled file, then caches)
15
+ */ function getSchema() {
16
+ if (schemaCache) {
17
+ return schemaCache;
18
+ }
19
+ const schemaPath = path.join(packageRoot, 'schemas/servers.schema.json');
20
+ if (!fs.existsSync(schemaPath)) {
21
+ throw new Error(`Servers schema not found at: ${schemaPath}`);
22
+ }
23
+ schemaCache = JSON.parse(fs.readFileSync(schemaPath, 'utf8'));
24
+ return schemaCache;
25
+ }
26
+ /**
27
+ * Get compiled AJV validator (creates once, then caches)
28
+ */ function getValidator() {
29
+ if (validatorCache) {
30
+ return validatorCache;
31
+ }
32
+ const schema = getSchema();
33
+ const ajv = new Ajv({
34
+ allErrors: true,
35
+ verbose: true,
36
+ strictSchema: false
37
+ });
38
+ // Add format validators (uri, email, etc.)
39
+ addFormats(ajv);
40
+ validatorCache = ajv.compile(schema);
41
+ return validatorCache;
42
+ }
43
+ /**
44
+ * Validate servers configuration against JSON Schema
45
+ *
46
+ * @param servers - Servers configuration object to validate (map of server names to configs)
47
+ * @returns ValidationResult with valid flag, errors, and warnings
48
+ */ export function validateServers(servers) {
49
+ try {
50
+ const validate = getValidator();
51
+ const valid = validate(servers);
52
+ if (!valid) {
53
+ var _validate_errors;
54
+ const errors = ((_validate_errors = validate.errors) === null || _validate_errors === void 0 ? void 0 : _validate_errors.map((e)=>{
55
+ const path = e.instancePath || '(root)';
56
+ return `${path}: ${e.message}`;
57
+ })) || [];
58
+ return {
59
+ valid: false,
60
+ errors
61
+ };
62
+ }
63
+ const warnings = [];
64
+ return {
65
+ valid: true,
66
+ warnings
67
+ };
68
+ } catch (err) {
69
+ return {
70
+ valid: false,
71
+ errors: [
72
+ `Configuration validation failed: ${err.message}`
73
+ ]
74
+ };
75
+ }
76
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/libs/client/src/config/validate-config.ts"],"sourcesContent":["import { Ajv, type ErrorObject } from 'ajv';\nimport * as fs from 'fs';\nimport { createRequire } from 'module';\nimport moduleRoot from 'module-root-sync';\nimport * as path from 'path';\n\n// Import ajv-formats (CommonJS module - use createRequire for ESM compatibility)\nconst require = createRequire(import.meta.url);\nconst addFormats = require('ajv-formats');\nconst packageRoot = moduleRoot(import.meta.filename);\n\n/**\n * Validation result for servers configuration\n */\nexport interface ValidationResult {\n valid: boolean;\n errors?: string[];\n warnings?: string[];\n}\n\n// Module-level cache for schema and validator\nlet schemaCache: object | null = null;\nlet validatorCache: ReturnType<Ajv['compile']> | null = null;\n\n/**\n * Get servers schema (loads once from bundled file, then caches)\n */\nfunction getSchema(): object {\n if (schemaCache) {\n return schemaCache;\n }\n\n const schemaPath = path.join(packageRoot, 'schemas/servers.schema.json');\n if (!fs.existsSync(schemaPath)) {\n throw new Error(`Servers schema not found at: ${schemaPath}`);\n }\n\n schemaCache = JSON.parse(fs.readFileSync(schemaPath, 'utf8')) as object;\n return schemaCache;\n}\n\n/**\n * Get compiled AJV validator (creates once, then caches)\n */\nfunction getValidator(): ReturnType<Ajv['compile']> {\n if (validatorCache) {\n return validatorCache;\n }\n\n const schema = getSchema();\n const ajv = new Ajv({\n allErrors: true,\n verbose: true,\n strictSchema: false, // Allow non-standard keywords like \"example\"\n });\n\n // Add format validators (uri, email, etc.)\n addFormats(ajv);\n\n validatorCache = ajv.compile(schema);\n return validatorCache;\n}\n\n/**\n * Validate servers configuration against JSON Schema\n *\n * @param servers - Servers configuration object to validate (map of server names to configs)\n * @returns ValidationResult with valid flag, errors, and warnings\n */\nexport function validateServers(servers: unknown): ValidationResult {\n try {\n const validate = getValidator();\n const valid = validate(servers);\n\n if (!valid) {\n const errors =\n validate.errors?.map((e: ErrorObject) => {\n const path = e.instancePath || '(root)';\n return `${path}: ${e.message}`;\n }) || [];\n\n return { valid: false, errors };\n }\n\n const warnings: string[] = [];\n return { valid: true, warnings };\n } catch (err) {\n return {\n valid: false,\n errors: [`Configuration validation failed: ${(err as Error).message}`],\n };\n }\n}\n"],"names":["Ajv","fs","createRequire","moduleRoot","path","require","url","addFormats","packageRoot","filename","schemaCache","validatorCache","getSchema","schemaPath","join","existsSync","Error","JSON","parse","readFileSync","getValidator","schema","ajv","allErrors","verbose","strictSchema","compile","validateServers","servers","validate","valid","errors","map","e","instancePath","message","warnings","err"],"mappings":"AAAA,SAASA,GAAG,QAA0B,MAAM;AAC5C,YAAYC,QAAQ,KAAK;AACzB,SAASC,aAAa,QAAQ,SAAS;AACvC,OAAOC,gBAAgB,mBAAmB;AAC1C,YAAYC,UAAU,OAAO;AAE7B,iFAAiF;AACjF,MAAMC,UAAUH,cAAc,YAAYI,GAAG;AAC7C,MAAMC,aAAaF,QAAQ;AAC3B,MAAMG,cAAcL,WAAW,YAAYM,QAAQ;AAWnD,8CAA8C;AAC9C,IAAIC,cAA6B;AACjC,IAAIC,iBAAoD;AAExD;;CAEC,GACD,SAASC;IACP,IAAIF,aAAa;QACf,OAAOA;IACT;IAEA,MAAMG,aAAaT,KAAKU,IAAI,CAACN,aAAa;IAC1C,IAAI,CAACP,GAAGc,UAAU,CAACF,aAAa;QAC9B,MAAM,IAAIG,MAAM,CAAC,6BAA6B,EAAEH,YAAY;IAC9D;IAEAH,cAAcO,KAAKC,KAAK,CAACjB,GAAGkB,YAAY,CAACN,YAAY;IACrD,OAAOH;AACT;AAEA;;CAEC,GACD,SAASU;IACP,IAAIT,gBAAgB;QAClB,OAAOA;IACT;IAEA,MAAMU,SAAST;IACf,MAAMU,MAAM,IAAItB,IAAI;QAClBuB,WAAW;QACXC,SAAS;QACTC,cAAc;IAChB;IAEA,2CAA2C;IAC3ClB,WAAWe;IAEXX,iBAAiBW,IAAII,OAAO,CAACL;IAC7B,OAAOV;AACT;AAEA;;;;;CAKC,GACD,OAAO,SAASgB,gBAAgBC,OAAgB;IAC9C,IAAI;QACF,MAAMC,WAAWT;QACjB,MAAMU,QAAQD,SAASD;QAEvB,IAAI,CAACE,OAAO;gBAERD;YADF,MAAME,SACJF,EAAAA,mBAAAA,SAASE,MAAM,cAAfF,uCAAAA,iBAAiBG,GAAG,CAAC,CAACC;gBACpB,MAAM7B,OAAO6B,EAAEC,YAAY,IAAI;gBAC/B,OAAO,GAAG9B,KAAK,EAAE,EAAE6B,EAAEE,OAAO,EAAE;YAChC,OAAM,EAAE;YAEV,OAAO;gBAAEL,OAAO;gBAAOC;YAAO;QAChC;QAEA,MAAMK,WAAqB,EAAE;QAC7B,OAAO;YAAEN,OAAO;YAAMM;QAAS;IACjC,EAAE,OAAOC,KAAK;QACZ,OAAO;YACLP,OAAO;YACPC,QAAQ;gBAAC,CAAC,iCAAiC,EAAE,AAACM,IAAcF,OAAO,EAAE;aAAC;QACxE;IACF;AACF"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * connect-mcp-client.ts
3
+ *
4
+ * Helper to connect MCP SDK clients to servers with intelligent transport inference.
5
+ * Automatically detects transport type from URL protocol or type field.
6
+ */
7
+ import '../monkey-patches.js';
8
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
9
+ import { type DcrAuthenticatorOptions } from '../dcr/index.js';
10
+ import type { ServerProcess } from '../spawn/spawn-server.js';
11
+ import type { ServersConfig } from '../spawn/spawn-servers.js';
12
+ /**
13
+ * Minimal interface for connecting to servers.
14
+ * Only needs config and servers map for connection logic.
15
+ */
16
+ interface RegistryLike {
17
+ config: ServersConfig;
18
+ servers: Map<string, ServerProcess>;
19
+ }
20
+ import { type Logger } from '../utils/logger.js';
21
+ /**
22
+ * Connect MCP SDK client to server with full readiness handling.
23
+ * @internal - Use registry.connect() instead
24
+ *
25
+ * **Completely handles readiness**: transport availability + MCP protocol handshake.
26
+ *
27
+ * Transport is intelligently inferred and handled:
28
+ * - **Stdio servers**: Direct MCP connect (fast for spawned processes)
29
+ * - **HTTP servers**: Transport polling (/mcp endpoint) + MCP connect
30
+ * - **Registry result**: Handles both spawned and external servers
31
+ *
32
+ * Returns only when server is fully MCP-ready (initialize handshake complete).
33
+ *
34
+ * @param registryOrConfig - Result from createServerRegistry() or servers config object
35
+ * @param serverName - Server name from servers config
36
+ * @returns Connected MCP SDK Client (guaranteed ready)
37
+ *
38
+ * @example
39
+ * // Using registry (recommended)
40
+ * const registry = createServerRegistry({ echo: { command: 'node', args: ['server.ts'] } });
41
+ * const client = await registry.connect('echo');
42
+ * // Server is fully ready - transport available + MCP handshake complete
43
+ *
44
+ * @example
45
+ * // HTTP server readiness (waits for /mcp polling + MCP handshake)
46
+ * const registry = createServerRegistry(
47
+ * { http: { type: 'http', url: 'http://localhost:3000/mcp', start: {...} } },
48
+ * { dialects: ['start'] }
49
+ * );
50
+ * const client = await registry.connect('http');
51
+ * // 1. Waits for HTTP server to respond on /mcp
52
+ * // 2. Performs MCP initialize handshake
53
+ * // 3. Returns ready client
54
+ */
55
+ export declare function connectMcpClient(registryOrConfig: RegistryLike | ServersConfig, serverName: string, options?: {
56
+ dcrAuthenticator?: Partial<DcrAuthenticatorOptions>;
57
+ logger?: Logger;
58
+ }): Promise<Client>;
59
+ export {};