callman-mcp 0.1.0 → 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.
Files changed (204) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/README.md +45 -16
  3. package/dist/client/api.d.ts +64 -3
  4. package/dist/client/api.d.ts.map +1 -1
  5. package/dist/client/api.js +67 -2
  6. package/dist/client/api.js.map +1 -1
  7. package/dist/client/errors.d.ts.map +1 -1
  8. package/dist/client/errors.js +33 -7
  9. package/dist/client/errors.js.map +1 -1
  10. package/dist/client/types.d.ts +91 -2
  11. package/dist/client/types.d.ts.map +1 -1
  12. package/dist/context.d.ts +2 -0
  13. package/dist/context.d.ts.map +1 -1
  14. package/dist/context.js +7 -2
  15. package/dist/context.js.map +1 -1
  16. package/dist/domain/contracts.d.ts +893 -0
  17. package/dist/domain/contracts.d.ts.map +1 -0
  18. package/dist/domain/contracts.js +90 -0
  19. package/dist/domain/contracts.js.map +1 -0
  20. package/dist/domain/diagram/build.d.ts +520 -18
  21. package/dist/domain/diagram/build.d.ts.map +1 -1
  22. package/dist/domain/diagram/build.js +65 -19
  23. package/dist/domain/diagram/build.js.map +1 -1
  24. package/dist/domain/diagram/patch.d.ts +624 -51
  25. package/dist/domain/diagram/patch.d.ts.map +1 -1
  26. package/dist/domain/diagram/patch.js +180 -40
  27. package/dist/domain/diagram/patch.js.map +1 -1
  28. package/dist/domain/diagram/style.d.ts +315 -0
  29. package/dist/domain/diagram/style.d.ts.map +1 -0
  30. package/dist/domain/diagram/style.js +124 -0
  31. package/dist/domain/diagram/style.js.map +1 -0
  32. package/dist/domain/diagram/summarize.d.ts +8 -0
  33. package/dist/domain/diagram/summarize.d.ts.map +1 -1
  34. package/dist/domain/diagram/summarize.js +28 -13
  35. package/dist/domain/diagram/summarize.js.map +1 -1
  36. package/dist/domain/requestIntegrations.d.ts +719 -0
  37. package/dist/domain/requestIntegrations.d.ts.map +1 -0
  38. package/dist/domain/requestIntegrations.js +222 -0
  39. package/dist/domain/requestIntegrations.js.map +1 -0
  40. package/dist/domain/requestShape.d.ts +1350 -152
  41. package/dist/domain/requestShape.d.ts.map +1 -1
  42. package/dist/domain/requestShape.js +336 -121
  43. package/dist/domain/requestShape.js.map +1 -1
  44. package/dist/domain/resolve.d.ts +2 -1
  45. package/dist/domain/resolve.d.ts.map +1 -1
  46. package/dist/domain/resolve.js +5 -1
  47. package/dist/domain/resolve.js.map +1 -1
  48. package/dist/domain/scenario/build.d.ts +82 -26
  49. package/dist/domain/scenario/build.d.ts.map +1 -1
  50. package/dist/domain/scenario/build.js +196 -65
  51. package/dist/domain/scenario/build.js.map +1 -1
  52. package/dist/domain/scenario/nodeConfig.d.ts +11 -0
  53. package/dist/domain/scenario/nodeConfig.d.ts.map +1 -0
  54. package/dist/domain/scenario/nodeConfig.js +251 -0
  55. package/dist/domain/scenario/nodeConfig.js.map +1 -0
  56. package/dist/domain/scenario/summarize.d.ts +145 -25
  57. package/dist/domain/scenario/summarize.d.ts.map +1 -1
  58. package/dist/domain/scenario/summarize.js +84 -29
  59. package/dist/domain/scenario/summarize.js.map +1 -1
  60. package/dist/lib/mask.d.ts +0 -18
  61. package/dist/lib/mask.d.ts.map +1 -1
  62. package/dist/lib/mask.js +2 -44
  63. package/dist/lib/mask.js.map +1 -1
  64. package/dist/lib/pagination.d.ts +3 -2
  65. package/dist/lib/pagination.d.ts.map +1 -1
  66. package/dist/lib/pagination.js +13 -8
  67. package/dist/lib/pagination.js.map +1 -1
  68. package/dist/lib/redact.d.ts +12 -0
  69. package/dist/lib/redact.d.ts.map +1 -0
  70. package/dist/lib/redact.js +50 -0
  71. package/dist/lib/redact.js.map +1 -0
  72. package/dist/lib/strict.d.ts +4 -0
  73. package/dist/lib/strict.d.ts.map +1 -0
  74. package/dist/lib/strict.js +14 -0
  75. package/dist/lib/strict.js.map +1 -0
  76. package/dist/prompts/index.js +7 -7
  77. package/dist/prompts/index.js.map +1 -1
  78. package/dist/resources/docs/contracts.d.ts +2 -0
  79. package/dist/resources/docs/contracts.d.ts.map +1 -0
  80. package/dist/resources/docs/contracts.js +74 -0
  81. package/dist/resources/docs/contracts.js.map +1 -0
  82. package/dist/resources/docs/diagramSchema.d.ts +1 -1
  83. package/dist/resources/docs/diagramSchema.d.ts.map +1 -1
  84. package/dist/resources/docs/diagramSchema.js +95 -28
  85. package/dist/resources/docs/diagramSchema.js.map +1 -1
  86. package/dist/resources/docs/overview.d.ts +1 -1
  87. package/dist/resources/docs/overview.d.ts.map +1 -1
  88. package/dist/resources/docs/overview.js +29 -7
  89. package/dist/resources/docs/overview.js.map +1 -1
  90. package/dist/resources/docs/requestSchema.d.ts +1 -1
  91. package/dist/resources/docs/requestSchema.d.ts.map +1 -1
  92. package/dist/resources/docs/requestSchema.js +85 -16
  93. package/dist/resources/docs/requestSchema.js.map +1 -1
  94. package/dist/resources/generated/aiPacks.d.ts +1 -1
  95. package/dist/resources/generated/aiPacks.d.ts.map +1 -1
  96. package/dist/resources/generated/aiPacks.js +3 -2
  97. package/dist/resources/generated/aiPacks.js.map +1 -1
  98. package/dist/resources/index.d.ts.map +1 -1
  99. package/dist/resources/index.js +19 -19
  100. package/dist/resources/index.js.map +1 -1
  101. package/dist/run/executeCollection.d.ts +3 -1
  102. package/dist/run/executeCollection.d.ts.map +1 -1
  103. package/dist/run/executeCollection.js +16 -4
  104. package/dist/run/executeCollection.js.map +1 -1
  105. package/dist/run/summarize.d.ts +17 -6
  106. package/dist/run/summarize.d.ts.map +1 -1
  107. package/dist/run/summarize.js +48 -41
  108. package/dist/run/summarize.js.map +1 -1
  109. package/dist/run/types.d.ts +1 -0
  110. package/dist/run/types.d.ts.map +1 -1
  111. package/dist/server.d.ts +1 -1
  112. package/dist/server.d.ts.map +1 -1
  113. package/dist/server.js +1 -1
  114. package/dist/server.js.map +1 -1
  115. package/dist/tools/catalog.d.ts +1 -1
  116. package/dist/tools/catalog.d.ts.map +1 -1
  117. package/dist/tools/catalog.js +18 -0
  118. package/dist/tools/catalog.js.map +1 -1
  119. package/dist/tools/collections.d.ts.map +1 -1
  120. package/dist/tools/collections.js +53 -41
  121. package/dist/tools/collections.js.map +1 -1
  122. package/dist/tools/contracts.d.ts +4 -0
  123. package/dist/tools/contracts.d.ts.map +1 -0
  124. package/dist/tools/contracts.js +201 -0
  125. package/dist/tools/contracts.js.map +1 -0
  126. package/dist/tools/diagrams.d.ts.map +1 -1
  127. package/dist/tools/diagrams.js +19 -10
  128. package/dist/tools/diagrams.js.map +1 -1
  129. package/dist/tools/environments.d.ts.map +1 -1
  130. package/dist/tools/environments.js +184 -64
  131. package/dist/tools/environments.js.map +1 -1
  132. package/dist/tools/import.d.ts.map +1 -1
  133. package/dist/tools/import.js +111 -20
  134. package/dist/tools/import.js.map +1 -1
  135. package/dist/tools/index.d.ts +2 -1
  136. package/dist/tools/index.d.ts.map +1 -1
  137. package/dist/tools/index.js +19 -1
  138. package/dist/tools/index.js.map +1 -1
  139. package/dist/tools/lookups.d.ts +38 -7
  140. package/dist/tools/lookups.d.ts.map +1 -1
  141. package/dist/tools/lookups.js +113 -10
  142. package/dist/tools/lookups.js.map +1 -1
  143. package/dist/tools/meta.d.ts.map +1 -1
  144. package/dist/tools/meta.js +9 -4
  145. package/dist/tools/meta.js.map +1 -1
  146. package/dist/tools/requests.d.ts.map +1 -1
  147. package/dist/tools/requests.js +138 -50
  148. package/dist/tools/requests.js.map +1 -1
  149. package/dist/tools/run.d.ts.map +1 -1
  150. package/dist/tools/run.js +84 -28
  151. package/dist/tools/run.js.map +1 -1
  152. package/dist/tools/scenarios.d.ts.map +1 -1
  153. package/dist/tools/scenarios.js +238 -75
  154. package/dist/tools/scenarios.js.map +1 -1
  155. package/dist/tools/shared.d.ts +1 -0
  156. package/dist/tools/shared.d.ts.map +1 -1
  157. package/dist/tools/shared.js +9 -1
  158. package/dist/tools/shared.js.map +1 -1
  159. package/dist/tools/workspaces.d.ts.map +1 -1
  160. package/dist/tools/workspaces.js +44 -7
  161. package/dist/tools/workspaces.js.map +1 -1
  162. package/dist-cjs/client/api.js +67 -2
  163. package/dist-cjs/client/errors.js +33 -7
  164. package/dist-cjs/context.js +7 -2
  165. package/dist-cjs/domain/contracts.js +93 -0
  166. package/dist-cjs/domain/diagram/build.js +71 -20
  167. package/dist-cjs/domain/diagram/patch.js +179 -39
  168. package/dist-cjs/domain/diagram/style.js +130 -0
  169. package/dist-cjs/domain/diagram/summarize.js +28 -13
  170. package/dist-cjs/domain/requestIntegrations.js +228 -0
  171. package/dist-cjs/domain/requestShape.js +342 -121
  172. package/dist-cjs/domain/resolve.js +5 -1
  173. package/dist-cjs/domain/scenario/build.js +197 -65
  174. package/dist-cjs/domain/scenario/nodeConfig.js +260 -0
  175. package/dist-cjs/domain/scenario/summarize.js +86 -29
  176. package/dist-cjs/lib/mask.js +3 -48
  177. package/dist-cjs/lib/pagination.js +13 -8
  178. package/dist-cjs/lib/redact.js +53 -0
  179. package/dist-cjs/lib/strict.js +18 -0
  180. package/dist-cjs/prompts/index.js +7 -7
  181. package/dist-cjs/resources/docs/contracts.js +76 -0
  182. package/dist-cjs/resources/docs/diagramSchema.js +95 -28
  183. package/dist-cjs/resources/docs/overview.js +29 -7
  184. package/dist-cjs/resources/docs/requestSchema.js +85 -16
  185. package/dist-cjs/resources/generated/aiPacks.js +3 -2
  186. package/dist-cjs/resources/index.js +17 -17
  187. package/dist-cjs/run/executeCollection.js +16 -4
  188. package/dist-cjs/run/summarize.js +48 -41
  189. package/dist-cjs/server.js +1 -1
  190. package/dist-cjs/tools/catalog.js +18 -0
  191. package/dist-cjs/tools/collections.js +52 -40
  192. package/dist-cjs/tools/contracts.js +204 -0
  193. package/dist-cjs/tools/diagrams.js +19 -10
  194. package/dist-cjs/tools/environments.js +182 -62
  195. package/dist-cjs/tools/import.js +107 -16
  196. package/dist-cjs/tools/index.js +21 -2
  197. package/dist-cjs/tools/lookups.js +123 -11
  198. package/dist-cjs/tools/meta.js +9 -4
  199. package/dist-cjs/tools/requests.js +134 -46
  200. package/dist-cjs/tools/run.js +82 -26
  201. package/dist-cjs/tools/scenarios.js +235 -72
  202. package/dist-cjs/tools/shared.js +11 -2
  203. package/dist-cjs/tools/workspaces.js +43 -6
  204. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"requestShape.d.ts","sourceRoot":"","sources":["../../src/domain/requestShape.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"requestShape.d.ts","sourceRoot":"","sources":["../../src/domain/requestShape.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,10 @@
1
- import { inferBodyStateFromRaw, toPersistedRequestBody, } from "callman-core";
1
+ import { extractUrlQueryPairs, inferBodyStateFromRaw, stripUrlQuery, toPersistedRequestBody, } from "callman-core";
2
2
  import { z } from "zod";
3
- import { maskAuth, maskHeaderValue } from "../lib/mask.js";
3
+ import { ToolInputError } from "../client/errors.js";
4
+ import { isMasked, maskHeaderValue, maskSecret } from "../lib/mask.js";
5
+ import { strictObject } from "../lib/strict.js";
4
6
  import { clip, jsonPreview, LIMITS, safeStringify } from "../lib/truncate.js";
7
+ import { hasIntegrations, integrationsInputView, requestIntegrationFields, toIntegrationPayload } from "./requestIntegrations.js";
5
8
  // The COMPACT request form a model writes (name/method/url, key-value lists,
6
9
  // a body that may be a JSON value, a string or a mode object, a small auth
7
10
  // object) and its translation into the backend's `POST /requests` payload —
@@ -9,75 +12,200 @@ import { clip, jsonPreview, LIMITS, safeStringify } from "../lib/truncate.js";
9
12
  // serialisation (`toPersistedRequestBody`) so an imported request opens in
10
13
  // the editor exactly like a hand-made one.
11
14
  export const HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "TRACE"];
12
- export const kvSchema = z.object({
13
- key: z.string().max(100),
15
+ // Key/value rows — the backend's own limits (key 1–100 chars, value ≤ 5000),
16
+ // strict so a stray `description` or `type` is an error, not a silent drop.
17
+ export const kvSchema = strictObject({
18
+ key: z.string().trim().min(1).max(100),
14
19
  value: z.string().max(5000).default(""),
15
- enabled: z.boolean().optional(),
16
- description: z.string().max(500).optional(),
17
- });
18
- export const bodyInputSchema = z.union([
19
- z.object({
20
- mode: z.literal("raw"),
21
- raw: z.string().max(2_000_000),
22
- language: z.enum(["json", "xml", "text", "html"]).optional(),
23
- }),
24
- z.object({
25
- mode: z.enum(["formdata", "urlencoded"]),
26
- entries: z.array(kvSchema).max(200),
27
- }),
28
- z.object({ mode: z.literal("none") }),
29
- z.unknown(),
30
- ]);
20
+ enabled: z.boolean().optional().describe("false keeps the row but does not send it (default true)"),
21
+ }, "row field");
22
+ export const pathVariableSchema = strictObject({
23
+ key: z.string().trim().min(1).max(100).describe("The name after ':' in the URL, without the colon"),
24
+ value: z.string().max(5000).default(""),
25
+ description: z.string().max(5000).optional(),
26
+ }, "path variable field");
27
+ const RAW_LANGUAGES = ["json", "xml", "text", "html"];
28
+ const rawBodySchema = strictObject({
29
+ mode: z.literal("raw"),
30
+ raw: z.string().max(2_000_000).describe("The body text; {{variables}} are resolved when it runs"),
31
+ language: z.enum(RAW_LANGUAGES).optional().describe("Editor language and default Content-Type; sniffed from the text when omitted"),
32
+ rawLanguage: z.enum(RAW_LANGUAGES).optional().describe("Same as language (the stored name)"),
33
+ }, "raw body field");
34
+ const formBodySchema = strictObject({
35
+ mode: z.enum(["formdata", "urlencoded"]),
36
+ entries: z.array(kvSchema).max(200).optional().describe("Text fields; file parts cannot be set through the API"),
37
+ formEntries: z.array(z.object({ key: z.string(), value: z.string().default(""), enabled: z.boolean().optional() }).passthrough()).max(200).optional().describe("Same as entries (the stored name)"),
38
+ }, "form body field");
39
+ const jsonBodySchema = strictObject({ mode: z.literal("json"), json: z.unknown().describe("Any JSON value — use this form when the payload itself has a top-level `mode` key") }, "json body field");
40
+ const noneBodySchema = strictObject({ mode: z.literal("none") }, "body field");
41
+ const BODY_MODES = ["raw", "formdata", "urlencoded", "json", "none"];
42
+ export const bodyInputSchema = z
43
+ .union([
44
+ z.string().max(2_000_000),
45
+ rawBodySchema,
46
+ formBodySchema,
47
+ jsonBodySchema,
48
+ noneBodySchema,
49
+ z.array(z.unknown()),
50
+ z.number(),
51
+ z.boolean(),
52
+ z.record(z.unknown()).refine((value) => !("mode" in value), { message: `A body object with a "mode" key must be one of the modes ${BODY_MODES.join(", ")}` }),
53
+ ], {
54
+ errorMap: (issue, ctx) => issue.code === z.ZodIssueCode.invalid_union
55
+ ? {
56
+ message: `Invalid body. Send a JSON value (object/array), a string, or { mode: "raw", raw, language? } | { mode: "formdata"|"urlencoded", entries: [{ key, value }] } | { mode: "json", json } | { mode: "none" }.`,
57
+ }
58
+ : { message: ctx.defaultError },
59
+ })
60
+ .describe('A JSON object/array (sent as JSON); a string (JSON is parsed, <xml>/<html> sniffed, otherwise text); { mode: "raw", raw, language: json|xml|text|html }; { mode: "formdata"|"urlencoded", entries: [{ key, value }] }; { mode: "json", json } when the payload itself has a top-level "mode" key; { mode: "none" }.');
61
+ const secret = (what) => z.string().max(10_000).describe(`${what}. {{variable}} references are fine`);
31
62
  export const authInputSchema = z.discriminatedUnion("type", [
32
- z.object({ type: z.literal("none") }),
33
- z.object({ type: z.literal("bearer"), token: z.string().max(10_000) }),
34
- z.object({ type: z.literal("basic"), username: z.string().max(5000), password: z.string().max(5000).default("") }),
35
- z.object({
63
+ strictObject({ type: z.literal("none") }, "auth field"),
64
+ strictObject({ type: z.literal("bearer"), token: secret("Bearer token") }, "bearer auth field"),
65
+ strictObject({ type: z.literal("basic"), username: z.string().max(5000), password: z.string().max(5000).default("") }, "basic auth field"),
66
+ strictObject({
36
67
  type: z.literal("apiKey"),
37
- key: z.string().max(5000),
38
- value: z.string().max(10_000),
68
+ key: z.string().max(5000).describe("Header or query parameter name, e.g. X-API-Key"),
69
+ value: secret("API key"),
39
70
  location: z.enum(["header", "query"]).default("header"),
40
- }),
41
- z.object({
71
+ }, "apiKey auth field"),
72
+ strictObject({
42
73
  type: z.literal("oauth2"),
43
74
  grantType: z.enum(["client_credentials", "password", "refresh_token"]).default("client_credentials"),
44
75
  tokenUrl: z.string().max(4096),
45
76
  clientId: z.string().max(5000).default(""),
46
77
  clientSecret: z.string().max(10_000).default(""),
47
78
  scope: z.string().max(5000).default(""),
48
- username: z.string().max(5000).default(""),
49
- password: z.string().max(5000).default(""),
50
- refreshToken: z.string().max(10_000).default(""),
51
- clientAuth: z.enum(["basic", "body"]).default("body"),
79
+ username: z.string().max(5000).default("").describe("password grant"),
80
+ password: z.string().max(5000).default("").describe("password grant"),
81
+ refreshToken: z.string().max(10_000).default("").describe("refresh_token grant"),
82
+ clientAuth: z.enum(["basic", "body"]).default("body").describe("Send client credentials as a Basic header or in the form body"),
52
83
  audience: z.string().max(4096).default(""),
53
- }),
84
+ }, "oauth2 auth field"),
54
85
  ]);
55
- export const requestInputSchema = z.object({
56
- name: z.string().min(1).max(LIMITS.NAME).describe("Display name, e.g. \"GET /users\" or \"Login\""),
86
+ export const requestInputSchema = strictObject({
87
+ name: z.string().trim().min(1).max(LIMITS.NAME).describe("Display name, e.g. \"GET /users\" or \"Login\""),
57
88
  method: z.enum(HTTP_METHODS),
58
89
  url: z
59
90
  .string()
91
+ .trim()
60
92
  .min(1)
61
93
  .max(4096)
62
- .describe("Full URL; use {{variable}} for hosts/tokens (e.g. {{baseUrl}}/users/:id) and :name for path variables"),
94
+ .describe("Full URL; use {{variable}} for hosts/tokens (e.g. {{baseUrl}}/users/:id) and :name for path variables. A ?query in the URL becomes `query` rows (they are the same thing — runs send the rows)"),
63
95
  headers: z.array(kvSchema).max(200).optional(),
64
- query: z.array(kvSchema).max(200).optional(),
65
- pathVariables: z.array(kvSchema).max(200).optional().describe("Values for :name segments in the URL"),
66
- body: bodyInputSchema
67
- .optional()
68
- .describe("A JSON value (stored as JSON), a string (JSON is parsed, otherwise raw text/xml/html by sniffing), or { mode: \"raw\" | \"formdata\" | \"urlencoded\" | \"none\", … }"),
96
+ query: z.array(kvSchema).max(200).optional().describe("Query parameters; when omitted they are taken from the URL's ?query"),
97
+ pathVariables: z.array(pathVariableSchema).max(200).optional().describe("Values for :name segments in the URL"),
98
+ body: bodyInputSchema.optional(),
69
99
  auth: authInputSchema.optional(),
70
- preRequestScript: z.string().max(100_000).optional(),
71
- postResponseScript: z.string().max(100_000).optional().describe("pm.* script run after the response (tests, pm.environment.set …)"),
72
- testsScript: z.string().max(100_000).optional(),
73
- folder: z.string().max(200).optional().describe("Folder id, name or path (\"Auth/Login\") inside the collection"),
74
- folderKey: z.string().max(120).optional().describe("Bulk create only: key of a folder declared in `folders`"),
75
- isEnabledInRunner: z.boolean().optional(),
76
- });
100
+ preRequestScript: z.string().max(100_000).optional().describe("pm.* script run before the request (callman://docs/scripting/pm-api)"),
101
+ postResponseScript: z.string().max(100_000).optional().describe("pm.* script run after the response (pm.test, pm.environment.set …)"),
102
+ testsScript: z.string().max(100_000).optional().describe("pm.test(...) assertions run after the response"),
103
+ folder: z.string().max(300).optional().describe("Folder id, name or path (\"Auth/Login\") inside the collection"),
104
+ folderKey: z.string().max(120).optional().describe("create_requests_bulk with collectionName only: key of a folder declared in `folders`"),
105
+ isEnabledInRunner: z.boolean().optional().describe("false = skipped by collection runs (run_collection, the desktop runner, the CLI); default true"),
106
+ ...requestIntegrationFields,
107
+ }, "request field");
77
108
  export const toRows = (entries) => (entries ?? [])
78
109
  .filter((entry) => entry.key.trim().length > 0)
79
- .map((entry) => ({ key: entry.key.trim(), value: entry.value ?? "", enabled: entry.enabled ?? true }))
80
- .slice(0, 200);
110
+ .map((entry) => ({ key: entry.key.trim(), value: entry.value ?? "", enabled: entry.enabled ?? true }));
111
+ const toPathVariables = (entries) => entries.map((entry) => ({ key: entry.key.trim().replace(/^:/, ""), value: entry.value ?? "", description: entry.description ?? "" }));
112
+ // ── URL ⇄ query rows ───────────────────────────────────────────────────
113
+ // The desktop keeps the URL's ?query and the query rows in sync
114
+ // (request-editor/lib/urlSync.ts), and every runner sends the ROWS — the run
115
+ // bundle strips the URL query. So a query typed into `url` becomes rows, and
116
+ // the stored URL mirrors the enabled rows exactly like the editor does.
117
+ const splitHash = (url) => {
118
+ const index = url.indexOf("#");
119
+ return index === -1 ? { withoutHash: url, hash: "" } : { withoutHash: url.slice(0, index), hash: url.slice(index) };
120
+ };
121
+ export const buildUrlWithQueryRows = (url, rows) => {
122
+ const { withoutHash, hash } = splitHash(url);
123
+ const base = stripUrlQuery(withoutHash);
124
+ const enabled = rows.filter((row) => row.enabled !== false && row.key.trim());
125
+ return enabled.length === 0 ? `${base}${hash}` : `${base}?${enabled.map((row) => `${row.key}=${row.value}`).join("&")}${hash}`;
126
+ };
127
+ export const syncUrlAndQuery = (url, query) => {
128
+ const fromUrl = extractUrlQueryPairs(url).map((pair) => ({ key: pair.key, value: pair.value, enabled: true }));
129
+ if (query === undefined)
130
+ return { url: buildUrlWithQueryRows(url, fromUrl), query: fromUrl, warnings: [] };
131
+ const rows = toRows(query);
132
+ const dropped = fromUrl.filter((pair) => !rows.some((row) => row.key === pair.key));
133
+ return {
134
+ url: buildUrlWithQueryRows(url, rows),
135
+ query: rows,
136
+ warnings: dropped.length > 0 ? [`The URL's query parameter(s) ${dropped.map((pair) => pair.key).join(", ")} were replaced by the \`query\` rows you passed — add them to \`query\` to keep them.`] : [],
137
+ };
138
+ };
139
+ // ── body ───────────────────────────────────────────────────────────────
140
+ const isModeObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && typeof value.mode === "string";
141
+ // Persisted body — the exact rules of the desktop editor's serializeBodyState
142
+ // (guarded in the desktop by persistedBody.drift.test.ts): JSON stays a bare
143
+ // JSON value; raw xml/text/html persists as { mode, raw, rawLanguage };
144
+ // form bodies keep their entries; empty → null.
145
+ export const toBodyPayload = (body, headers) => {
146
+ if (body === undefined || body === null)
147
+ return null;
148
+ if (typeof body === "string") {
149
+ if (isClipped(body))
150
+ throw clippedError("body");
151
+ return toPersistedRequestBody(inferBodyStateFromRaw(body, headers));
152
+ }
153
+ if (isModeObject(body)) {
154
+ const record = body;
155
+ if (record.mode === "none")
156
+ return null;
157
+ if (record.mode === "json")
158
+ return (record.json ?? null);
159
+ if (record.mode === "raw") {
160
+ const raw = typeof record.raw === "string" ? record.raw : "";
161
+ if (isClipped(raw))
162
+ throw clippedError("body.raw");
163
+ const language = (record.language ?? record.rawLanguage);
164
+ if (language)
165
+ return toPersistedRequestBody({ mode: "raw", raw, rawLanguage: language, formEntries: [] });
166
+ return toPersistedRequestBody(inferBodyStateFromRaw(raw, headers));
167
+ }
168
+ if (record.mode === "formdata" || record.mode === "urlencoded") {
169
+ const persisted = Array.isArray(record.formEntries) ? record.formEntries : null;
170
+ if (persisted?.some((entry) => entry.type === "file")) {
171
+ throw new ToolInputError("FORM_FILE_UNSUPPORTED", "File parts of a form body cannot be set through the API — keep them in the desktop app, or send text fields only.");
172
+ }
173
+ const entries = persisted
174
+ ? persisted.map((entry) => ({ key: String(entry.key ?? ""), value: String(entry.value ?? ""), enabled: entry.enabled !== false }))
175
+ : (record.entries ?? []);
176
+ return toPersistedRequestBody({ mode: record.mode, raw: "", formEntries: toRows(entries) });
177
+ }
178
+ }
179
+ // Any other JSON value is stored as-is (the editor shows it on the JSON tab).
180
+ return body;
181
+ };
182
+ // Previews end in "…" (lib/truncate) — writing one back would store the cut.
183
+ const isClipped = (text) => text.endsWith("…") && text.length >= LIMITS.BODY_PREVIEW;
184
+ const clippedError = (field) => new ToolInputError("CLIPPED_VALUE", `${field} looks like a clipped preview (ends with "…"). Read it with get_request full: true, or pass the complete value.`);
185
+ // The backend (express-mongo-sanitize) rewrites JSON keys that start with "$"
186
+ // or contain "." on ordinary writes — { "$schema": … } is stored as "_schema".
187
+ export const sanitizedKeyWarnings = (body) => {
188
+ const found = new Set();
189
+ const walk = (value, depth) => {
190
+ if (depth > 20 || found.size >= 10 || value === null || typeof value !== "object")
191
+ return;
192
+ if (Array.isArray(value)) {
193
+ for (const item of value)
194
+ walk(item, depth + 1);
195
+ return;
196
+ }
197
+ for (const [key, child] of Object.entries(value)) {
198
+ if (key.startsWith("$") || key.includes("."))
199
+ found.add(key);
200
+ walk(child, depth + 1);
201
+ }
202
+ };
203
+ walk(body, 0);
204
+ return found.size > 0
205
+ ? [`The server rewrites JSON keys that start with "$" or contain "." (${[...found].join(", ")} → "_"). Keep such payloads as a raw string body ({ mode: "raw", raw: "…", language: "json" }).`]
206
+ : [];
207
+ };
208
+ // ── auth ───────────────────────────────────────────────────────────────
81
209
  const EMPTY_AUTH = {
82
210
  type: "none",
83
211
  bearerToken: "",
@@ -105,86 +233,141 @@ export const toAuthPayload = (auth) => {
105
233
  return { ...EMPTY_AUTH };
106
234
  }
107
235
  };
108
- const isModeObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && typeof value.mode === "string";
109
- // Persisted body — the exact rules of the desktop editor's serializeBodyState
110
- // (guarded in the desktop by persistedBody.drift.test.ts): JSON stays a bare
111
- // JSON value; raw xml/text/html persists as { mode, raw, rawLanguage };
112
- // form bodies keep their entries; empty → null.
113
- export const toBodyPayload = (body, headers) => {
114
- if (body === undefined || body === null)
115
- return null;
116
- if (typeof body === "string") {
117
- return toPersistedRequestBody(inferBodyStateFromRaw(body, headers));
118
- }
119
- if (isModeObject(body)) {
120
- const record = body;
121
- if (record.mode === "none")
122
- return null;
123
- if (record.mode === "raw") {
124
- const raw = typeof record.raw === "string" ? record.raw : "";
125
- const language = record.language;
126
- if (language) {
127
- return toPersistedRequestBody({ mode: "raw", raw, rawLanguage: language, formEntries: [] });
128
- }
129
- return toPersistedRequestBody(inferBodyStateFromRaw(raw, headers));
236
+ // Stored auth → the SAME shape authInputSchema accepts, so a read can be
237
+ // written straight back. Secrets are masked unless `reveal`.
238
+ export const authInputView = (auth, reveal = false) => {
239
+ const hide = (value) => (value ? (reveal ? value : maskSecret(value)) : "");
240
+ switch (auth?.type) {
241
+ case "bearer":
242
+ return { type: "bearer", token: hide(auth.bearerToken) };
243
+ case "basic":
244
+ return { type: "basic", username: auth.basicUsername ?? "", password: hide(auth.basicPassword) };
245
+ case "apikey":
246
+ return { type: "apiKey", key: auth.apiKeyKey ?? "", value: hide(auth.apiKeyValue), location: auth.apiKeyLocation ?? "header" };
247
+ case "oauth2": {
248
+ const oauth2 = (auth.oauth2 ?? {});
249
+ return {
250
+ type: "oauth2",
251
+ grantType: oauth2.grantType ?? "client_credentials",
252
+ tokenUrl: oauth2.tokenUrl ?? "",
253
+ clientId: oauth2.clientId ?? "",
254
+ clientSecret: hide(oauth2.clientSecret),
255
+ scope: oauth2.scope ?? "",
256
+ username: oauth2.username ?? "",
257
+ password: hide(oauth2.password),
258
+ refreshToken: hide(oauth2.refreshToken),
259
+ clientAuth: oauth2.clientAuth ?? "body",
260
+ audience: oauth2.audience ?? "",
261
+ };
130
262
  }
131
- if (record.mode === "formdata" || record.mode === "urlencoded") {
132
- const entries = Array.isArray(record.entries) ? record.entries : [];
133
- return toPersistedRequestBody({ mode: record.mode, raw: "", formEntries: toRows(entries) });
263
+ default:
264
+ return { type: "none" };
265
+ }
266
+ };
267
+ // ── masked values ──────────────────────────────────────────────────────
268
+ // get_request shows secrets as ••••ab. Writing that back would store the
269
+ // dots as the credential. On update a masked value that matches the stored
270
+ // secret's mask means "keep the stored value"; anything else masked is refused.
271
+ export const resolveMaskedValues = (item, current) => {
272
+ const problems = [];
273
+ const restoreRows = (field, rows) => rows?.map((row) => {
274
+ if (!isMasked(row.value))
275
+ return row;
276
+ const stored = current?.[field]?.find((entry) => entry.key.toLowerCase() === row.key.toLowerCase());
277
+ if (stored && field === "headers" && maskHeaderValue(stored.key, stored.value) === row.value)
278
+ return { ...row, value: stored.value };
279
+ problems.push(`${field}.${row.key}`);
280
+ return row;
281
+ });
282
+ const out = { ...item, headers: restoreRows("headers", item.headers), query: restoreRows("query", item.query) };
283
+ if (item.headers === undefined)
284
+ delete out.headers;
285
+ if (item.query === undefined)
286
+ delete out.query;
287
+ for (const entry of item.pathVariables ?? [])
288
+ if (isMasked(entry.value))
289
+ problems.push(`pathVariables.${entry.key}`);
290
+ if (item.auth) {
291
+ const storedView = authInputView(current?.auth, true);
292
+ const auth = { ...item.auth };
293
+ for (const [key, value] of Object.entries(auth)) {
294
+ if (!isMasked(value))
295
+ continue;
296
+ const stored = storedView.type === auth.type ? storedView[key] : undefined;
297
+ if (typeof stored === "string" && stored && maskSecret(stored) === value)
298
+ auth[key] = stored;
299
+ else
300
+ problems.push(`auth.${key}`);
134
301
  }
302
+ out.auth = auth;
135
303
  }
136
- // Any other JSON value is stored as-is (the editor shows it on the JSON tab).
137
- return body;
304
+ if (problems.length > 0) {
305
+ throw new ToolInputError("MASKED_VALUE", `Masked values (••••) cannot be saved: ${problems.join(", ")}. Pass the real value or a {{variable}}, or leave the field out to keep what is stored (get_request reveal: true shows it).`, { fields: problems });
306
+ }
307
+ return out;
138
308
  };
139
- export const toCreateRequestPayload = (item, target) => {
309
+ const noConnections = (_ref, _type, where) => {
310
+ throw new ToolInputError("CONNECTIONS_UNAVAILABLE", `${where}: connections were not loaded for this call.`);
311
+ };
312
+ export const toCreateRequestPayload = (item, target, resolve = noConnections) => {
140
313
  const headers = toRows(item.headers);
314
+ const { url, query, warnings } = syncUrlAndQuery(item.url.trim(), item.query);
315
+ const body = toBodyPayload(item.body, headers);
141
316
  return {
142
- name: item.name.trim().slice(0, LIMITS.NAME),
143
- method: item.method,
144
- url: item.url.trim(),
145
- headers,
146
- query: toRows(item.query),
147
- pathVariables: (item.pathVariables ?? [])
148
- .filter((entry) => entry.key.trim())
149
- .map((entry) => ({ key: entry.key.trim(), value: entry.value ?? "", description: entry.description ?? "" })),
150
- body: toBodyPayload(item.body, headers),
151
- auth: toAuthPayload(item.auth),
152
- preRequestScript: item.preRequestScript ?? "",
153
- postResponseScript: item.postResponseScript ?? "",
154
- testsScript: item.testsScript ?? "",
155
- collectionId: target.collectionId,
156
- folderId: target.folderId,
317
+ payload: {
318
+ name: item.name.trim().slice(0, LIMITS.NAME),
319
+ method: item.method,
320
+ url,
321
+ headers,
322
+ query,
323
+ pathVariables: toPathVariables(item.pathVariables ?? []),
324
+ body,
325
+ auth: toAuthPayload(item.auth),
326
+ preRequestScript: item.preRequestScript ?? "",
327
+ postResponseScript: item.postResponseScript ?? "",
328
+ testsScript: item.testsScript ?? "",
329
+ ...(hasIntegrations(item) ? toIntegrationPayload(item, resolve) : {}),
330
+ collectionId: target.collectionId,
331
+ folderId: target.folderId,
332
+ },
333
+ warnings: [...warnings, ...sanitizedKeyWarnings(body)],
157
334
  };
158
335
  };
159
336
  // `format: "requests"` bulk import row — same document minus the ids the
160
- // server assigns, plus the payload-local folderKey.
161
- export const toFlatImportRequest = (item) => {
162
- const { collectionId: _c, folderId: _f, ...payload } = toCreateRequestPayload(item, { collectionId: "", folderId: null });
337
+ // server assigns, plus the payload-local folderKey. The import route is not
338
+ // key-sanitized, so no "$" warning here.
339
+ export const toFlatImportRequest = (item, resolve = noConnections) => {
340
+ const { collectionId: _c, folderId: _f, ...payload } = toCreateRequestPayload(item, { collectionId: "", folderId: null }, resolve).payload;
163
341
  return { ...payload, ...(item.folderKey ? { folderKey: item.folderKey } : {}) };
164
342
  };
165
- export const updateRequestInputSchema = requestInputSchema
166
- .partial()
167
- .omit({ folderKey: true })
168
- .extend({ collection: z.string().max(200).optional() });
169
- export const toUpdateRequestPayload = (item, target) => {
343
+ export const updateRequestInputSchema = strictObject({
344
+ ...Object.fromEntries(Object.entries(requestInputSchema.shape).filter(([key]) => key !== "folderKey").map(([key, schema]) => [key, schema.optional()])),
345
+ collection: z.string().max(200).optional().describe("Narrows a request NAME lookup to one collection (it does not move the request — use move_requests)"),
346
+ }, "request field");
347
+ // Only the fields passed change. isEnabledInRunner is NOT part of the PATCH
348
+ // (the backend's update schema strips it) — the caller sends it to the
349
+ // run-toggle endpoint.
350
+ export const toUpdateRequestPayload = (item, current, target, resolve = noConnections) => {
170
351
  const out = {};
352
+ const warnings = [];
171
353
  if (item.name !== undefined)
172
354
  out.name = item.name.trim().slice(0, LIMITS.NAME);
173
355
  if (item.method !== undefined)
174
356
  out.method = item.method;
175
- if (item.url !== undefined)
176
- out.url = item.url.trim();
357
+ if (item.url !== undefined || item.query !== undefined) {
358
+ const synced = syncUrlAndQuery((item.url ?? current.url).trim(), item.query ?? (item.url !== undefined ? undefined : current.query ?? []));
359
+ out.url = synced.url;
360
+ out.query = synced.query;
361
+ warnings.push(...synced.warnings);
362
+ }
177
363
  if (item.headers !== undefined)
178
364
  out.headers = toRows(item.headers);
179
- if (item.query !== undefined)
180
- out.query = toRows(item.query);
181
- if (item.pathVariables !== undefined) {
182
- out.pathVariables = item.pathVariables
183
- .filter((entry) => entry.key.trim())
184
- .map((entry) => ({ key: entry.key.trim(), value: entry.value ?? "", description: entry.description ?? "" }));
365
+ if (item.pathVariables !== undefined)
366
+ out.pathVariables = toPathVariables(item.pathVariables);
367
+ if (item.body !== undefined) {
368
+ out.body = toBodyPayload(item.body, item.headers !== undefined ? toRows(item.headers) : (current.headers ?? []));
369
+ warnings.push(...sanitizedKeyWarnings(out.body));
185
370
  }
186
- if (item.body !== undefined)
187
- out.body = toBodyPayload(item.body, toRows(item.headers));
188
371
  if (item.auth !== undefined)
189
372
  out.auth = toAuthPayload(item.auth);
190
373
  if (item.preRequestScript !== undefined)
@@ -193,13 +376,11 @@ export const toUpdateRequestPayload = (item, target) => {
193
376
  out.postResponseScript = item.postResponseScript;
194
377
  if (item.testsScript !== undefined)
195
378
  out.testsScript = item.testsScript;
196
- if (item.isEnabledInRunner !== undefined)
197
- out.isEnabledInRunner = item.isEnabledInRunner;
198
- if (target.collectionId !== undefined)
199
- out.collectionId = target.collectionId;
379
+ if (hasIntegrations(item))
380
+ Object.assign(out, toIntegrationPayload(item, resolve, current));
200
381
  if (target.folderId !== undefined)
201
382
  out.folderId = target.folderId;
202
- return out;
383
+ return { payload: out, warnings };
203
384
  };
204
385
  // ── outbound views ─────────────────────────────────────────────────────
205
386
  const kvView = (rows, maskHeaders) => (rows ?? []).map((row) => ({
@@ -207,9 +388,35 @@ const kvView = (rows, maskHeaders) => (rows ?? []).map((row) => ({
207
388
  value: maskHeaders ? maskHeaderValue(row.key, row.value) : row.value,
208
389
  ...(row.enabled === false ? { enabled: false } : {}),
209
390
  }));
391
+ // Stored body → the input shape (a bare JSON value stays bare unless it has
392
+ // a top-level "mode", which would read as a mode object).
393
+ export const bodyInputView = (body) => {
394
+ if (body === null || body === undefined)
395
+ return null;
396
+ if (isModeObject(body)) {
397
+ const record = body;
398
+ if (record.mode === "raw" && typeof record.raw === "string")
399
+ return { mode: "raw", raw: record.raw, language: record.rawLanguage ?? "text" };
400
+ if ((record.mode === "formdata" || record.mode === "urlencoded") && Array.isArray(record.formEntries)) {
401
+ return {
402
+ mode: record.mode,
403
+ entries: record.formEntries.map((entry) => ({
404
+ key: String(entry.key ?? ""),
405
+ value: String(entry.value ?? ""),
406
+ ...(entry.enabled === false ? { enabled: false } : {}),
407
+ ...(entry.type === "file" ? { file: true } : {}),
408
+ })),
409
+ };
410
+ }
411
+ return { mode: "json", json: body };
412
+ }
413
+ return body;
414
+ };
210
415
  export const compactRequestView = (request, options = {}) => {
211
- const bodyText = request.body == null ? null : safeStringify(request.body);
416
+ const body = bodyInputView(request.body);
417
+ const bodyText = body === null ? null : safeStringify(body);
212
418
  const bodyTruncated = bodyText !== null && !options.full && bodyText.length > LIMITS.BODY_PREVIEW;
419
+ const integrations = integrationsInputView(request);
213
420
  return {
214
421
  id: request.id,
215
422
  name: request.name,
@@ -220,17 +427,25 @@ export const compactRequestView = (request, options = {}) => {
220
427
  headers: kvView(request.headers, !options.reveal),
221
428
  query: kvView(request.query, false),
222
429
  ...(request.pathVariables && request.pathVariables.length > 0
223
- ? { pathVariables: request.pathVariables.map((entry) => ({ key: entry.key, value: entry.value ?? "" })) }
430
+ ? {
431
+ pathVariables: request.pathVariables.map((entry) => ({
432
+ key: entry.key,
433
+ value: entry.value ?? "",
434
+ ...(entry.description ? { description: entry.description } : {}),
435
+ })),
436
+ }
224
437
  : {}),
225
- body: options.full ? request.body : jsonPreview(request.body),
226
- ...(bodyTruncated ? { bodyTruncated: true } : {}),
227
- auth: options.reveal ? (request.auth ?? { type: "none" }) : maskAuth(request.auth),
438
+ // A clipped body is never returned as `body` — it would validate as a
439
+ // (cut) body if written back.
440
+ ...(bodyTruncated ? { body: null, bodyPreview: jsonPreview(body), bodyTruncated: true } : { body }),
441
+ auth: authInputView(request.auth, options.reveal),
228
442
  scripts: {
229
443
  preRequest: scriptView(request.preRequestScript, options.full),
230
444
  postResponse: scriptView(request.postResponseScript, options.full),
231
445
  tests: scriptView(request.testsScript, options.full),
232
446
  },
233
447
  isEnabledInRunner: request.isEnabledInRunner !== false,
448
+ ...(integrations ?? {}),
234
449
  updatedAt: request.updatedAt ?? null,
235
450
  };
236
451
  };