@smithery/sdk 1.5.6 → 1.5.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.
@@ -102,7 +102,6 @@ export function createStatefulServer(createMcpServer, options) {
102
102
  $id: `${req.protocol}://${req.get("host")}/.well-known/mcp-config`,
103
103
  title: "MCP Session Configuration",
104
104
  description: "Schema for the /mcp endpoint configuration",
105
- "x-mcp-version": "1.0",
106
105
  "x-query-style": "dot+bracket",
107
106
  ...baseSchema,
108
107
  };
@@ -98,7 +98,6 @@ export function createStatelessServer(createMcpServer, options) {
98
98
  $id: `${req.protocol}://${req.get("host")}/.well-known/mcp-config`,
99
99
  title: "MCP Session Configuration",
100
100
  description: "Schema for the /mcp endpoint configuration",
101
- "x-mcp-version": "1.0",
102
101
  "x-query-style": "dot+bracket",
103
102
  ...baseSchema,
104
103
  };
@@ -9,28 +9,17 @@ export interface SmitheryUrlOptions {
9
9
  * Creates a URL to connect to the Smithery MCP server.
10
10
  * @param baseUrl The base URL of the Smithery server
11
11
  * @param options Optional configuration object
12
- * @returns A URL object with properly encoded parameters. Example: https://server.smithery.ai/{namespace}/mcp?config=BASE64_ENCODED_CONFIG&api_key=API_KEY
12
+ * @returns A URL with config encoded using dot-notation query params (e.g. model.name=gpt-4&debug=true)
13
13
  */
14
14
  export declare function createSmitheryUrl(baseUrl: string, options?: SmitheryUrlOptions): URL;
15
- /**
16
- * Parses the config from an express request by checking the query parameter "config".
17
- * @param req The express request
18
- * @returns The config
19
- */
20
- export declare function parseExpressRequestConfig(req: ExpressRequest): Record<string, unknown>;
21
15
  /**
22
16
  * Parses and validates config from an Express request with optional Zod schema validation
23
- * Supports both base64-encoded config and dot-notation config parameters
17
+ * Supports dot-notation config parameters (e.g., foo=bar, a.b=c)
24
18
  * @param req The express request
25
19
  * @param schema Optional Zod schema for validation
26
20
  * @returns Result with either parsed data or error response
27
21
  */
28
22
  export declare function parseAndValidateConfig<T = Record<string, unknown>>(req: ExpressRequest, schema?: z.ZodSchema<T>): import("okay-error").Err<{
29
- title: string;
30
- status: number;
31
- detail: string;
32
- instance: string;
33
- }> | import("okay-error").Err<{
34
23
  readonly title: "Invalid configuration parameters";
35
24
  readonly status: 422;
36
25
  readonly detail: "One or more config parameters are invalid.";
@@ -48,3 +37,4 @@ export declare function parseAndValidateConfig<T = Record<string, unknown>>(req:
48
37
  received: unknown;
49
38
  }[];
50
39
  }> | import("okay-error").Ok<T>;
40
+ export declare function parseConfigFromQuery(query: Iterable<[string, unknown]>): Record<string, unknown>;
@@ -1,19 +1,54 @@
1
1
  import _ from "lodash";
2
2
  import { err, ok } from "okay-error";
3
3
  import { zodToJsonSchema } from "zod-to-json-schema";
4
+ function isPlainObject(value) {
5
+ return value !== null && typeof value === "object" && !Array.isArray(value);
6
+ }
7
+ function appendConfigAsDotParams(url, config) {
8
+ function add(pathParts, value) {
9
+ if (Array.isArray(value)) {
10
+ for (let index = 0; index < value.length; index++) {
11
+ add([...pathParts, String(index)], value[index]);
12
+ }
13
+ return;
14
+ }
15
+ if (isPlainObject(value)) {
16
+ for (const [key, nested] of Object.entries(value)) {
17
+ add([...pathParts, key], nested);
18
+ }
19
+ return;
20
+ }
21
+ const key = pathParts.join(".");
22
+ let stringValue;
23
+ switch (typeof value) {
24
+ case "string":
25
+ stringValue = value;
26
+ break;
27
+ case "number":
28
+ case "boolean":
29
+ stringValue = String(value);
30
+ break;
31
+ default:
32
+ stringValue = JSON.stringify(value);
33
+ }
34
+ url.searchParams.set(key, stringValue);
35
+ }
36
+ if (isPlainObject(config)) {
37
+ for (const [key, value] of Object.entries(config)) {
38
+ add([key], value);
39
+ }
40
+ }
41
+ }
4
42
  /**
5
43
  * Creates a URL to connect to the Smithery MCP server.
6
44
  * @param baseUrl The base URL of the Smithery server
7
45
  * @param options Optional configuration object
8
- * @returns A URL object with properly encoded parameters. Example: https://server.smithery.ai/{namespace}/mcp?config=BASE64_ENCODED_CONFIG&api_key=API_KEY
46
+ * @returns A URL with config encoded using dot-notation query params (e.g. model.name=gpt-4&debug=true)
9
47
  */
10
48
  export function createSmitheryUrl(baseUrl, options) {
11
49
  const url = new URL(`${baseUrl}/mcp`);
12
50
  if (options?.config) {
13
- const param = typeof window !== "undefined"
14
- ? btoa(JSON.stringify(options.config))
15
- : Buffer.from(JSON.stringify(options.config)).toString("base64");
16
- url.searchParams.set("config", param);
51
+ appendConfigAsDotParams(url, options.config);
17
52
  }
18
53
  if (options?.apiKey) {
19
54
  url.searchParams.set("api_key", options.apiKey);
@@ -23,60 +58,15 @@ export function createSmitheryUrl(baseUrl, options) {
23
58
  }
24
59
  return url;
25
60
  }
26
- /**
27
- * Parses the config from an express request by checking the query parameter "config".
28
- * @param req The express request
29
- * @returns The config
30
- */
31
- export function parseExpressRequestConfig(req) {
32
- return JSON.parse(Buffer.from(req.query.config, "base64").toString());
33
- }
34
61
  /**
35
62
  * Parses and validates config from an Express request with optional Zod schema validation
36
- * Supports both base64-encoded config and dot-notation config parameters
63
+ * Supports dot-notation config parameters (e.g., foo=bar, a.b=c)
37
64
  * @param req The express request
38
65
  * @param schema Optional Zod schema for validation
39
66
  * @returns Result with either parsed data or error response
40
67
  */
41
68
  export function parseAndValidateConfig(req, schema) {
42
- // Parse config from request parameters
43
- let config = {};
44
- // 1. Process base64-encoded config parameter if present
45
- if (req.query.config) {
46
- try {
47
- config = parseExpressRequestConfig(req);
48
- }
49
- catch (configError) {
50
- return err({
51
- title: "Invalid config parameter",
52
- status: 400,
53
- detail: "Failed to parse config parameter",
54
- instance: req.originalUrl,
55
- });
56
- }
57
- }
58
- // 2. Process dot-notation config parameters (foo=bar, a.b=c)
59
- // This allows URL params like ?server.host=localhost&server.port=8080&debug=true
60
- for (const [key, value] of Object.entries(req.query)) {
61
- // Skip reserved parameters
62
- if (key === "config" || key === "api_key" || key === "profile")
63
- continue;
64
- const pathParts = key.split(".");
65
- // Handle array values from Express query parsing
66
- const rawValue = Array.isArray(value) ? value[0] : value;
67
- if (typeof rawValue !== "string")
68
- continue;
69
- // Try to parse value as JSON (for booleans, numbers, objects)
70
- let parsedValue = rawValue;
71
- try {
72
- parsedValue = JSON.parse(rawValue);
73
- }
74
- catch {
75
- // If parsing fails, use the raw string value
76
- }
77
- // Use lodash's set method to handle nested paths
78
- _.set(config, pathParts, parsedValue);
79
- }
69
+ const config = parseConfigFromQuery(Object.entries(req.query));
80
70
  // Validate config against schema if provided
81
71
  if (schema) {
82
72
  const result = schema.safeParse(config);
@@ -114,3 +104,29 @@ export function parseAndValidateConfig(req, schema) {
114
104
  }
115
105
  return ok(config);
116
106
  }
107
+ // Process dot-notation config parameters from query parameters (foo=bar, a.b=c)
108
+ // This allows URL params like ?server.host=localhost&server.port=8080&debug=true
109
+ export function parseConfigFromQuery(query) {
110
+ const config = {};
111
+ for (const [key, value] of query) {
112
+ // Skip reserved parameters
113
+ if (key === "api_key" || key === "profile")
114
+ continue;
115
+ const pathParts = key.split(".");
116
+ // Handle array values from Express query parsing
117
+ const rawValue = Array.isArray(value) ? value[0] : value;
118
+ if (typeof rawValue !== "string")
119
+ continue;
120
+ // Try to parse value as JSON (for booleans, numbers, objects)
121
+ let parsedValue = rawValue;
122
+ try {
123
+ parsedValue = JSON.parse(rawValue);
124
+ }
125
+ catch {
126
+ // If parsing fails, use the raw string value
127
+ }
128
+ // Use lodash's set method to handle nested paths
129
+ _.set(config, pathParts, parsedValue);
130
+ }
131
+ return config;
132
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smithery/sdk",
3
- "version": "1.5.6",
3
+ "version": "1.5.8",
4
4
  "description": "SDK to develop with Smithery",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",