mmt-mcp 1.44.1-pre → 1.44.3-pre

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 (22) hide show
  1. package/dist/examples/basic/05_api_test_suite/README.md +2 -2
  2. package/dist/examples/basic/05_api_test_suite/echo.mmt +0 -2
  3. package/dist/examples/professional/07_mock_server_timeout/README.md +1 -1
  4. package/dist/examples/professional/07_mock_server_timeout/test/slow_timeout_test.mmt +1 -1
  5. package/dist/examples/professional/11_token_resolution/README.md +2 -0
  6. package/dist/examples/professional/11_token_resolution/api/current_xml_body.mmt +0 -1
  7. package/dist/examples/professional/11_token_resolution/api/env_xml_body.mmt +10 -10
  8. package/dist/examples/professional/11_token_resolution/api/input_json_body.mmt +8 -0
  9. package/dist/examples/professional/11_token_resolution/api/input_urlencoded_body.mmt +8 -1
  10. package/dist/examples/professional/11_token_resolution/api/input_xml_body.mmt +28 -0
  11. package/dist/examples/professional/11_token_resolution/api/random_urlencoded_body.mmt +0 -1
  12. package/dist/examples/professional/11_token_resolution/api/random_xml_body.mmt +0 -1
  13. package/dist/examples/professional/11_token_resolution/test/current_xml_body_test.mmt +0 -1
  14. package/dist/examples/professional/11_token_resolution/test/env_xml_body_test.mmt +0 -1
  15. package/dist/examples/professional/11_token_resolution/test/input_json_body_test.mmt +2 -0
  16. package/dist/examples/professional/11_token_resolution/test/input_urlencoded_body_test.mmt +2 -1
  17. package/dist/examples/professional/11_token_resolution/test/input_xml_body_test.mmt +8 -0
  18. package/dist/examples/professional/11_token_resolution/test/random_urlencoded_body_test.mmt +0 -1
  19. package/dist/examples/professional/11_token_resolution/test/random_xml_body_test.mmt +0 -1
  20. package/dist/server.cjs +5 -6
  21. package/dist/server.js +5 -6
  22. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
- # API example `expect` / `require` in a suite
1
+ # API example `expect` in a suite
2
2
 
3
- This example shows a `type: api` file with per-example `expect` / `require`, listed in a suite.
3
+ This example shows a `type: api` file with per-example `expect`, listed in a suite.
4
4
 
5
5
  ```bash
6
6
  npx testlight run suite.mmt
@@ -9,5 +9,3 @@ examples:
9
9
  title: Happy path
10
10
  expect:
11
11
  status_code: 200
12
- require:
13
- status_code: == 200
@@ -23,4 +23,4 @@ This professional example demonstrates a request timeout against a delayed local
23
23
  npx testlight run examples/professional/07_mock_server_timeout/test/slow_timeout_test.mmt
24
24
  ```
25
25
 
26
- This example is expected to fail with a request timeout because the request timeout is shorter than the mock response delay.
26
+ This example should pass: the request times out (`status: -1`) because the request timeout is shorter than the mock response delay.
@@ -11,5 +11,5 @@ steps:
11
11
  - call: slow_request
12
12
  id: timeout_result
13
13
  expect:
14
- status: 200
14
+ status: -1
15
15
  report: all
@@ -22,6 +22,8 @@ Each request also sends the other spellings of one token:
22
22
 
23
23
  A whole-field example expect uses the same token (`e:account_age`, `i:username`, `c:day`, `r:uuid`, including a slice such as `i:city[0:3]`). `e:`, `i:`, and `c:` resolve to the value that was sent. Text formats still match when a number or boolean was sent as text. `r:` is checked as a regex of that generator, because each draw is new. `c:epoch` changes every second, so that expect stays a range. Text wrapped around a token (`asda42`, `asda15`) stays a concrete string or a regex.
24
24
 
25
+ The `i:` examples also send `version` (`"1.0"`) and `price` (`9.5`). `input_xml_body.mmt` puts numeric, boolean, and decimal tokens in XML attributes (`<item number="100" flag="true" …>`). Attribute values are always quoted, so the request stays valid XML.
26
+
25
27
  ## Environment
26
28
 
27
29
  `multimeter.mmt` is loaded as the workspace environment. The active values are:
@@ -16,7 +16,6 @@ outputs:
16
16
  quoted_curly: body.body.quoted_curly
17
17
  curly_whole: body.body.curly_whole
18
18
  text_slice: body.body.text_slice
19
- missing_embed: body.body.missing_embed
20
19
  status_code: status
21
20
  url: https://test.mmt.dev/echo
22
21
  method: post
@@ -18,7 +18,6 @@ outputs:
18
18
  quoted_curly: body.body.quoted_curly
19
19
  curly_whole: body.body.curly_whole
20
20
  text_slice: body.body.text_slice
21
- missing_embed: body.body.missing_embed
22
21
  status_code: status
23
22
  url: https://test.mmt.dev/echo
24
23
  method: post
@@ -33,14 +32,14 @@ body:
33
32
  missing_region: e:region
34
33
  literal_token: "e:account_age"
35
34
  literal_omit: "omit"
36
- angle_whole: <<e:account_age>>
37
- quoted_angle: "<<e:account_age>>"
38
- angle_prefix: "asda<<e:account_age>>"
39
- angle_suffix: "<<e:account_age>>asas"
40
- angle_both: "asda<<e:feature_enabled>>asas"
41
- quoted_curly: "{{e:account_age}}"
42
- curly_whole: {{e:plan_label}}
43
- text_slice: <<e:service_url[0:8]>>
35
+ angle_whole: e:account_age
36
+ quoted_angle: e:account_age
37
+ angle_prefix: asda<<e:account_age>>
38
+ angle_suffix: <<e:account_age>>asas
39
+ angle_both: asda<<e:feature_enabled>>asas
40
+ quoted_curly: e:account_age
41
+ curly_whole: e:plan_label
42
+ text_slice: e:service_url[0:8]
44
43
  examples:
45
44
  - id: defaults
46
45
  title: Check outputs
@@ -62,4 +61,5 @@ examples:
62
61
  quoted_curly: =S <<e:account_age>>
63
62
  curly_whole: e:plan_label
64
63
  text_slice: e:service_url[0:8]
65
-
64
+
65
+
@@ -6,6 +6,8 @@ inputs:
6
6
  age: 100
7
7
  active: true
8
8
  city: Berlin
9
+ version: "1.0"
10
+ price: 9.5
9
11
  outputs:
10
12
  username: body.body.username
11
13
  age: body.body.age
@@ -24,6 +26,8 @@ outputs:
24
26
  curly_whole: body.body.curly_whole
25
27
  text_slice: body.body.text_slice
26
28
  missing_embed: body.body.missing_embed
29
+ version_text: body.body.version
30
+ price_value: body.body.price
27
31
  status_code: status
28
32
  url: https://test.mmt.dev/echo
29
33
  method: post
@@ -46,6 +50,8 @@ body:
46
50
  curly_whole: {{i:city}}
47
51
  text_slice: <<i:city[0:3]>>
48
52
  missing_embed: "x<<i:nickname>>y"
53
+ version: i:version
54
+ price: i:price
49
55
  examples:
50
56
  - id: defaults
51
57
  title: Check outputs
@@ -68,3 +74,5 @@ examples:
68
74
  curly_whole: i:city
69
75
  text_slice: i:city[0:3]
70
76
  missing_embed: "xi:nicknamey"
77
+ version_text: "1.0"
78
+ price_value: 9.5
@@ -6,6 +6,8 @@ inputs:
6
6
  age: 100
7
7
  active: true
8
8
  city: Berlin
9
+ version: "1.0"
10
+ price: 9.5
9
11
  outputs:
10
12
  username: body.body.username
11
13
  age: body.body.age
@@ -22,7 +24,8 @@ outputs:
22
24
  quoted_curly: body.body.quoted_curly
23
25
  curly_whole: body.body.curly_whole
24
26
  text_slice: body.body.text_slice
25
- missing_embed: body.body.missing_embed
27
+ version_text: body.body.version
28
+ price_value: body.body.price
26
29
  status_code: status
27
30
  url: https://test.mmt.dev/echo
28
31
  method: post
@@ -43,6 +46,8 @@ body:
43
46
  quoted_curly: "{{i:username}}"
44
47
  curly_whole: {{i:city}}
45
48
  text_slice: <<i:city[0:3]>>
49
+ version: i:version
50
+ price: i:price
46
51
  examples:
47
52
  - id: defaults
48
53
  title: Check outputs
@@ -63,3 +68,5 @@ examples:
63
68
  quoted_curly: i:username
64
69
  curly_whole: i:city
65
70
  text_slice: i:city[0:3]
71
+ version_text: "1.0"
72
+ price_value: "9.5"
@@ -6,6 +6,8 @@ inputs:
6
6
  age: 100
7
7
  active: true
8
8
  city: Berlin
9
+ version: "1.0"
10
+ price: 9.5
9
11
  outputs:
10
12
  username: body.body.username
11
13
  age: body.body.age
@@ -23,6 +25,14 @@ outputs:
23
25
  curly_whole: body.body.curly_whole
24
26
  text_slice: body.body.text_slice
25
27
  missing_embed: body.body.missing_embed
28
+ attr_number: body.body.item.number
29
+ attr_bool: body.body.item.flag
30
+ attr_text: body.body.item.version
31
+ attr_angle: body.body.item.angle
32
+ attr_embedded: body.body.item.embedded
33
+ attr_literal: body.body.item.literal
34
+ attr_decimal: body.body.item.decimal
35
+ price_text: body.body.price
26
36
  status_code: status
27
37
  url: https://test.mmt.dev/echo
28
38
  method: post
@@ -45,6 +55,16 @@ body:
45
55
  curly_whole: {{i:city}}
46
56
  text_slice: <<i:city[0:3]>>
47
57
  missing_embed: "x<<i:nickname>>y"
58
+ item:
59
+ _attributes:
60
+ number: i:age
61
+ flag: i:active
62
+ version: i:version
63
+ angle: <<i:age>>
64
+ embedded: "n<<i:age>>"
65
+ literal: "1.0"
66
+ decimal: i:price
67
+ price: i:price
48
68
  examples:
49
69
  - id: defaults
50
70
  title: Check outputs
@@ -66,3 +86,11 @@ examples:
66
86
  curly_whole: i:city
67
87
  text_slice: i:city[0:3]
68
88
  missing_embed: "xi:nicknamey"
89
+ attr_number: "100"
90
+ attr_bool: "true"
91
+ attr_text: "1.0"
92
+ attr_angle: "100"
93
+ attr_embedded: "n100"
94
+ attr_literal: "1.0"
95
+ attr_decimal: "9.5"
96
+ price_text: "9.5"
@@ -15,7 +15,6 @@ outputs:
15
15
  angle_both: body.body.angle_both
16
16
  quoted_curly: body.body.quoted_curly
17
17
  curly_whole: body.body.curly_whole
18
- missing_embed: body.body.missing_embed
19
18
  status_code: status
20
19
  url: https://test.mmt.dev/echo
21
20
  method: post
@@ -15,7 +15,6 @@ outputs:
15
15
  angle_both: body.body.angle_both
16
16
  quoted_curly: body.body.quoted_curly
17
17
  curly_whole: body.body.curly_whole
18
- missing_embed: body.body.missing_embed
19
18
  status_code: status
20
19
  url: https://test.mmt.dev/echo
21
20
  method: post
@@ -22,4 +22,3 @@ steps:
22
22
  quoted_curly: c:day
23
23
  curly_whole: "!= null"
24
24
  text_slice: "=# 1"
25
- missing_embed: "xc:not_a_tokeny"
@@ -24,4 +24,3 @@ steps:
24
24
  quoted_curly: "42"
25
25
  curly_whole: "10"
26
26
  text_slice: "https://"
27
- missing_embed: "xe:regiony"
@@ -27,3 +27,5 @@ steps:
27
27
  curly_whole: "Berlin"
28
28
  text_slice: "Ber"
29
29
  missing_embed: "xi:nicknamey"
30
+ version_text: "1.0"
31
+ price_value: 9.5
@@ -25,4 +25,5 @@ steps:
25
25
  quoted_curly: i:username
26
26
  curly_whole: "Berlin"
27
27
  text_slice: "Ber"
28
- missing_embed: "xi:nicknamey"
28
+ version_text: "1.0"
29
+ price_value: "9.5"
@@ -26,3 +26,11 @@ steps:
26
26
  curly_whole: "Berlin"
27
27
  text_slice: "Ber"
28
28
  missing_embed: "xi:nicknamey"
29
+ attr_number: "100"
30
+ attr_bool: "true"
31
+ attr_text: "1.0"
32
+ attr_angle: "100"
33
+ attr_embedded: "n100"
34
+ attr_literal: "1.0"
35
+ attr_decimal: "9.5"
36
+ price_text: "9.5"
@@ -25,4 +25,3 @@ steps:
25
25
  curly_whole:
26
26
  - "!= null"
27
27
  - "!C r:"
28
- missing_embed: "xr:not_a_tokeny"
@@ -25,4 +25,3 @@ steps:
25
25
  curly_whole:
26
26
  - "!= null"
27
27
  - "!C r:"
28
- missing_embed: "xr:not_a_tokeny"
package/dist/server.cjs CHANGED
@@ -15283,6 +15283,9 @@ function formValueToString(value, keepLiteralMarkers = false) {
15283
15283
  return stringifyJsonWithRuntimeTokens(value, false);
15284
15284
  }
15285
15285
  function editorFormValue(value) {
15286
+ if (typeof value === "string" && value !== "") {
15287
+ return isLiteralTokenValue(value) ? unwrapLiteralToken(value) : value;
15288
+ }
15286
15289
  if (value === null || typeof value === "number" || typeof value === "boolean" || typeof value === "string") {
15287
15290
  return yamlValueToInputBox(value);
15288
15291
  }
@@ -15916,18 +15919,14 @@ var apiToJSfunc = async (ctx) => {
15916
15919
  "${JSON.stringify($1)}"
15917
15920
  );
15918
15921
  }
15919
- const entries = Object.entries(ctx.api.inputs ?? {});
15922
+ const entries = reqFormat2 === "json" ? Object.entries(ctx.api.inputs ?? {}) : [];
15920
15923
  for (const [name, value] of entries) {
15921
15924
  const quoted = new RegExp(`"\\$\\{${name}\\}"`, "g");
15922
- if (reqFormat2 === "json" && typeof value !== "string") {
15925
+ if (typeof value !== "string") {
15923
15926
  formattedBody = formattedBody.replace(
15924
15927
  quoted,
15925
15928
  () => "${JSON.stringify(" + name + ")}"
15926
15929
  );
15927
- } else if (typeof value === "string") {
15928
- formattedBody = formattedBody.replace(quoted, '"${' + name + '}"');
15929
- } else {
15930
- formattedBody = formattedBody.replace(quoted, "${" + name + "}");
15931
15930
  }
15932
15931
  }
15933
15932
  if (reqFormat2 === "json") {
package/dist/server.js CHANGED
@@ -15283,6 +15283,9 @@ function formValueToString(value, keepLiteralMarkers = false) {
15283
15283
  return stringifyJsonWithRuntimeTokens(value, false);
15284
15284
  }
15285
15285
  function editorFormValue(value) {
15286
+ if (typeof value === "string" && value !== "") {
15287
+ return isLiteralTokenValue(value) ? unwrapLiteralToken(value) : value;
15288
+ }
15286
15289
  if (value === null || typeof value === "number" || typeof value === "boolean" || typeof value === "string") {
15287
15290
  return yamlValueToInputBox(value);
15288
15291
  }
@@ -15916,18 +15919,14 @@ var apiToJSfunc = async (ctx) => {
15916
15919
  "${JSON.stringify($1)}"
15917
15920
  );
15918
15921
  }
15919
- const entries = Object.entries(ctx.api.inputs ?? {});
15922
+ const entries = reqFormat2 === "json" ? Object.entries(ctx.api.inputs ?? {}) : [];
15920
15923
  for (const [name, value] of entries) {
15921
15924
  const quoted = new RegExp(`"\\$\\{${name}\\}"`, "g");
15922
- if (reqFormat2 === "json" && typeof value !== "string") {
15925
+ if (typeof value !== "string") {
15923
15926
  formattedBody = formattedBody.replace(
15924
15927
  quoted,
15925
15928
  () => "${JSON.stringify(" + name + ")}"
15926
15929
  );
15927
- } else if (typeof value === "string") {
15928
- formattedBody = formattedBody.replace(quoted, '"${' + name + '}"');
15929
- } else {
15930
- formattedBody = formattedBody.replace(quoted, "${" + name + "}");
15931
15930
  }
15932
15931
  }
15933
15932
  if (reqFormat2 === "json") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mmt-mcp",
3
- "version": "1.44.1-pre",
3
+ "version": "1.44.3-pre",
4
4
  "description": "Multimeter MCP server for Cursor, Copilot, and Claude. Scaffold, validate, format, and run YAML .mmt API tests. Do not invent .mmt syntax.",
5
5
  "mcpName": "io.github.mshobeyri/multimeter",
6
6
  "type": "module",