@frontmcp/testing 0.5.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 (112) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +1358 -0
  3. package/jest-preset.js +61 -0
  4. package/package.json +94 -0
  5. package/src/assertions/index.d.ts +5 -0
  6. package/src/assertions/index.js +18 -0
  7. package/src/assertions/index.js.map +1 -0
  8. package/src/assertions/mcp-assertions.d.ts +81 -0
  9. package/src/assertions/mcp-assertions.js +220 -0
  10. package/src/assertions/mcp-assertions.js.map +1 -0
  11. package/src/auth/auth-headers.d.ts +29 -0
  12. package/src/auth/auth-headers.js +62 -0
  13. package/src/auth/auth-headers.js.map +1 -0
  14. package/src/auth/index.d.ts +9 -0
  15. package/src/auth/index.js +15 -0
  16. package/src/auth/index.js.map +1 -0
  17. package/src/auth/token-factory.d.ts +94 -0
  18. package/src/auth/token-factory.js +181 -0
  19. package/src/auth/token-factory.js.map +1 -0
  20. package/src/auth/user-fixtures.d.ts +26 -0
  21. package/src/auth/user-fixtures.js +92 -0
  22. package/src/auth/user-fixtures.js.map +1 -0
  23. package/src/client/index.d.ts +7 -0
  24. package/src/client/index.js +12 -0
  25. package/src/client/index.js.map +1 -0
  26. package/src/client/mcp-test-client.builder.d.ts +72 -0
  27. package/src/client/mcp-test-client.builder.js +111 -0
  28. package/src/client/mcp-test-client.builder.js.map +1 -0
  29. package/src/client/mcp-test-client.d.ts +360 -0
  30. package/src/client/mcp-test-client.js +929 -0
  31. package/src/client/mcp-test-client.js.map +1 -0
  32. package/src/client/mcp-test-client.types.d.ts +216 -0
  33. package/src/client/mcp-test-client.types.js +7 -0
  34. package/src/client/mcp-test-client.types.js.map +1 -0
  35. package/src/errors/index.d.ts +45 -0
  36. package/src/errors/index.js +85 -0
  37. package/src/errors/index.js.map +1 -0
  38. package/src/expect.d.ts +67 -0
  39. package/src/expect.js +31 -0
  40. package/src/expect.js.map +1 -0
  41. package/src/fixtures/fixture-types.d.ts +166 -0
  42. package/src/fixtures/fixture-types.js +7 -0
  43. package/src/fixtures/fixture-types.js.map +1 -0
  44. package/src/fixtures/index.d.ts +7 -0
  45. package/src/fixtures/index.js +16 -0
  46. package/src/fixtures/index.js.map +1 -0
  47. package/src/fixtures/test-fixture.d.ts +41 -0
  48. package/src/fixtures/test-fixture.js +280 -0
  49. package/src/fixtures/test-fixture.js.map +1 -0
  50. package/src/http-mock/http-mock.d.ts +84 -0
  51. package/src/http-mock/http-mock.js +544 -0
  52. package/src/http-mock/http-mock.js.map +1 -0
  53. package/src/http-mock/http-mock.types.d.ts +124 -0
  54. package/src/http-mock/http-mock.types.js +10 -0
  55. package/src/http-mock/http-mock.types.js.map +1 -0
  56. package/src/http-mock/index.d.ts +6 -0
  57. package/src/http-mock/index.js +11 -0
  58. package/src/http-mock/index.js.map +1 -0
  59. package/src/index.d.ts +65 -0
  60. package/src/index.js +128 -0
  61. package/src/index.js.map +1 -0
  62. package/src/interceptor/index.d.ts +7 -0
  63. package/src/interceptor/index.js +15 -0
  64. package/src/interceptor/index.js.map +1 -0
  65. package/src/interceptor/interceptor-chain.d.ts +77 -0
  66. package/src/interceptor/interceptor-chain.js +207 -0
  67. package/src/interceptor/interceptor-chain.js.map +1 -0
  68. package/src/interceptor/interceptor.types.d.ts +131 -0
  69. package/src/interceptor/interceptor.types.js +7 -0
  70. package/src/interceptor/interceptor.types.js.map +1 -0
  71. package/src/interceptor/mock-registry.d.ts +82 -0
  72. package/src/interceptor/mock-registry.js +189 -0
  73. package/src/interceptor/mock-registry.js.map +1 -0
  74. package/src/matchers/index.d.ts +7 -0
  75. package/src/matchers/index.js +12 -0
  76. package/src/matchers/index.js.map +1 -0
  77. package/src/matchers/matcher-types.d.ts +266 -0
  78. package/src/matchers/matcher-types.js +10 -0
  79. package/src/matchers/matcher-types.js.map +1 -0
  80. package/src/matchers/mcp-matchers.d.ts +47 -0
  81. package/src/matchers/mcp-matchers.js +391 -0
  82. package/src/matchers/mcp-matchers.js.map +1 -0
  83. package/src/playwright/index.d.ts +37 -0
  84. package/src/playwright/index.js +49 -0
  85. package/src/playwright/index.js.map +1 -0
  86. package/src/server/index.d.ts +6 -0
  87. package/src/server/index.js +10 -0
  88. package/src/server/index.js.map +1 -0
  89. package/src/server/test-server.d.ts +99 -0
  90. package/src/server/test-server.js +286 -0
  91. package/src/server/test-server.js.map +1 -0
  92. package/src/setup.d.ts +22 -0
  93. package/src/setup.js +30 -0
  94. package/src/setup.js.map +1 -0
  95. package/src/transport/index.d.ts +6 -0
  96. package/src/transport/index.js +10 -0
  97. package/src/transport/index.js.map +1 -0
  98. package/src/transport/streamable-http.transport.d.ts +65 -0
  99. package/src/transport/streamable-http.transport.js +432 -0
  100. package/src/transport/streamable-http.transport.js.map +1 -0
  101. package/src/transport/transport.interface.d.ts +124 -0
  102. package/src/transport/transport.interface.js +7 -0
  103. package/src/transport/transport.interface.js.map +1 -0
  104. package/src/ui/index.d.ts +17 -0
  105. package/src/ui/index.js +23 -0
  106. package/src/ui/index.js.map +1 -0
  107. package/src/ui/ui-assertions.d.ts +94 -0
  108. package/src/ui/ui-assertions.js +215 -0
  109. package/src/ui/ui-assertions.js.map +1 -0
  110. package/src/ui/ui-matchers.d.ts +39 -0
  111. package/src/ui/ui-matchers.js +275 -0
  112. package/src/ui/ui-matchers.js.map +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-test-client.js","sourceRoot":"","sources":["../../../src/client/mcp-test-client.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AA+BH,uEAAiE;AAEjE,sFAAiF;AAQjF,gDAAuE;AAEvE,sEAAsE;AACtE,YAAY;AACZ,sEAAsE;AAEtE,MAAM,eAAe,GAAG,KAAK,CAAC;AAC9B,MAAM,wBAAwB,GAAG,YAAY,CAAC;AAC9C,MAAM,mBAAmB,GAAG;IAC1B,IAAI,EAAE,mBAAmB;IACzB,OAAO,EAAE,OAAO;CACjB,CAAC;AAEF,sEAAsE;AACtE,oBAAoB;AACpB,sEAAsE;AAEtE,MAAa,aAAa;IACP,MAAM,CAAgC;IAC/C,SAAS,GAAwB,IAAI,CAAC;IACtC,UAAU,GAA4B,IAAI,CAAC;IAC3C,gBAAgB,GAAG,CAAC,CAAC;IACrB,cAAc,GAAoB,CAAC,CAAC;IACpC,UAAU,CAAqB;IAC/B,YAAY,GAAuB,IAAI,CAAC;IACxC,UAAU,GAAc,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAElE,sBAAsB;IACd,KAAK,GAAe,EAAE,CAAC;IACvB,OAAO,GAAmB,EAAE,CAAC;IAC7B,cAAc,GAAwB,EAAE,CAAC;IACzC,gBAAgB,GAAqB,EAAE,CAAC;IAEhD,oBAAoB;IACZ,aAAa,CAAmB;IAExC,sEAAsE;IACtE,wBAAwB;IACxB,sEAAsE;IAEtE,YAAY,MAA2B;QACrC,IAAI,CAAC,MAAM,GAAG;YACZ,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,iBAAiB;YAChD,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;YACvB,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,KAAK;YACtC,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,eAAe;YAC1C,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,KAAK;YAC5B,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,wBAAwB;YACnE,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,mBAAmB;SACrD,CAAC;QAEF,qEAAqE;QACrE,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,IAAI,CAAC,UAAU,GAAG;gBAChB,WAAW,EAAE,IAAI;gBACjB,MAAM,EAAE,EAAE;aACX,CAAC;QACJ,CAAC;aAAM,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;YAC9B,+BAA+B;YAC/B,IAAI,CAAC,UAAU,GAAG;gBAChB,WAAW,EAAE,KAAK;gBAClB,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK;gBACxB,MAAM,EAAE,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;gBACpD,IAAI,EAAE,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;aACjD,CAAC;QACJ,CAAC;QAED,+BAA+B;QAC/B,IAAI,CAAC,aAAa,GAAG,IAAI,qCAAuB,EAAE,CAAC;IACrD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,MAA2B;QACvC,OAAO,IAAI,8CAAoB,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,sEAAsE;IACtE,yBAAyB;IACzB,sEAAsE;IAEtE;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,iBAAiB,IAAI,CAAC,MAAM,CAAC,OAAO,KAAK,CAAC,CAAC;QAE7D,mCAAmC;QACnC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QAExC,oBAAoB;QACpB,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;QAE/B,6BAA6B;QAC7B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QAE7C,IAAI,CAAC,YAAY,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CAAC,wCAAwC,YAAY,CAAC,KAAK,EAAE,OAAO,IAAI,eAAe,EAAE,CAAC,CAAC;QAC5G,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC;QACpC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC;QAChD,IAAI,CAAC,YAAY,GAAG;YAClB,EAAE,EAAE,IAAI,CAAC,UAAU,IAAI,WAAW,IAAI,CAAC,GAAG,EAAE,EAAE;YAC9C,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,cAAc,EAAE,IAAI,IAAI,EAAE;YAC1B,YAAY,EAAE,CAAC;SAChB,CAAC;QAEF,iDAAiD;QACjD,qEAAqE;QACrE,gDAAgD;QAChD,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;YAC1B,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,2BAA2B;SACpC,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,IAAI,IAAI,YAAY,EAAE,CAAC,CAAC;QAErF,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;YAC7B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,8BAA8B,CAAC,CAAC;IACnD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,OAAgC;QAC9C,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QAExB,IAAI,OAAO,EAAE,SAAS,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACzC,qCAAqC;YACrC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;QACtC,CAAC;QAED,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,WAAW;QACT,OAAO,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,KAAK,CAAC;IAChD,CAAC;IAED,sEAAsE;IACtE,4BAA4B;IAC5B,sEAAsE;IAEtE,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;IAC/B,CAAC;IAED,IAAI,OAAO;QACT,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,IAAI;YAChC,EAAE,EAAE,EAAE;YACN,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,cAAc,EAAE,IAAI,IAAI,EAAE;YAC1B,YAAY,EAAE,CAAC;SAChB,CAAC;QAEF,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,KAAK,IAAI,EAAE;gBACjB,uCAAuC;gBACvC,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;gBAC5B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YAC3B,CAAC;SACF,CAAC;IACJ,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY,CAAC,KAAa;QAC9B,IAAI,CAAC,UAAU,GAAG;YAChB,WAAW,EAAE,KAAK;YAClB,KAAK;YACL,MAAM,EAAE,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC;YACxC,IAAI,EAAE,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC;SACrC,CAAC;QAEF,2BAA2B;QAC3B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,wBAAwB,CAAC,CAAC;IAC9C,CAAC;IAED,sEAAsE;IACtE,6BAA6B;IAC7B,sEAAsE;IAEtE,IAAI,UAAU;QACZ,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE;YAC7C,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,IAAI,EAAE;SACpD,CAAC;IACJ,CAAC;IAED,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,UAAU,EAAE,eAAe,IAAI,EAAE,CAAC;IAChD,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,UAAU,EAAE,YAAY,IAAI,EAAE,CAAC;IAC7C,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,UAAU,EAAE,YAAY,IAAI,EAAE,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,IAAgE;QAC5E,OAAO,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,sEAAsE;IACtE,YAAY;IACZ,sEAAsE;IAE7D,KAAK,GAAG;QACf;;WAEG;QACH,IAAI,EAAE,KAAK,IAAqB,EAAE;YAChC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;YACxC,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YACtE,CAAC;YACD,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;QAC7B,CAAC;QAED;;WAEG;QACH,IAAI,EAAE,KAAK,EAAE,IAAY,EAAE,IAA8B,EAA8B,EAAE;YACvF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACjD,OAAO,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QACvC,CAAC;KACF,CAAC;IAEF,sEAAsE;IACtE,gBAAgB;IAChB,sEAAsE;IAE7D,SAAS,GAAG;QACnB;;WAEG;QACH,IAAI,EAAE,KAAK,IAAyB,EAAE;YACpC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;YAC5C,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YAC1E,CAAC;YACD,OAAO,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;QACjC,CAAC;QAED;;WAEG;QACH,aAAa,EAAE,KAAK,IAAiC,EAAE;YACrD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACpD,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,sCAAsC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YACnF,CAAC;YACD,OAAO,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC;QACzC,CAAC;QAED;;WAEG;QACH,IAAI,EAAE,KAAK,EAAE,GAAW,EAAmC,EAAE;YAC3D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;YAC9C,OAAO,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC;QAED;;WAEG;QACH,SAAS,EAAE,KAAK,EAAE,IAAY,EAAiB,EAAE;YAC/C,wCAAwC;YACxC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,2CAA2C,CAAC,CAAC;QAChE,CAAC;QAED;;WAEG;QACH,WAAW,EAAE,KAAK,EAAE,IAAY,EAAiB,EAAE;YACjD,0CAA0C;YAC1C,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,6CAA6C,CAAC,CAAC;QAClE,CAAC;KACF,CAAC;IAEF,sEAAsE;IACtE,cAAc;IACd,sEAAsE;IAE7D,OAAO,GAAG;QACjB;;WAEG;QACH,IAAI,EAAE,KAAK,IAAuB,EAAE;YAClC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;YAC1C,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YACxE,CAAC;YACD,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;QAC/B,CAAC;QAED;;WAEG;QACH,GAAG,EAAE,KAAK,EAAE,IAAY,EAAE,IAA6B,EAAgC,EAAE;YACvF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAClD,OAAO,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QACzC,CAAC;KACF,CAAC;IAEF,sEAAsE;IACtE,sBAAsB;IACtB,sEAAsE;IAE7D,GAAG,GAAG;QACb;;WAEG;QACH,OAAO,EAAE,KAAK,EAAE,OAKf,EAA4B,EAAE;YAC7B,IAAI,CAAC,eAAe,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACxD,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;YAC5F,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED;;WAEG;QACH,MAAM,EAAE,KAAK,EAAE,OAA6E,EAAiB,EAAE;YAC7G,IAAI,CAAC,eAAe,EAAE,CAAC;YACvB,MAAM,IAAI,CAAC,SAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACxC,CAAC;QAED;;WAEG;QACH,OAAO,EAAE,KAAK,EAAE,IAAY,EAA4B,EAAE;YACxD,IAAI,CAAC,eAAe,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,SAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC;KACF,CAAC;IAEF,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,sEAAsE;IACtE,iBAAiB;IACjB,sEAAsE;IAEtE;;OAEG;IACH,IAAI,cAAc;QAUhB,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;YAC3B,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,KAAK;YACzD,eAAe,EAAE,IAAI,CAAC,SAAS,EAAE,kBAAkB,EAAE,EAAE;YACvD,eAAe,EAAE,IAAI,CAAC,SAAS,EAAE,kBAAkB,EAAE,EAAE,IAAI,CAAC;YAC5D,cAAc,EAAE,IAAI,CAAC,SAAS,EAAE,iBAAiB,EAAE,EAAE,IAAI,CAAC;YAC1D,kBAAkB,EAAE,IAAI,CAAC,SAAS,EAAE,qBAAqB,EAAE,EAAE,IAAI,EAAE;YACnE,kBAAkB,EAAE,KAAK,IAAI,EAAE;gBAC7B,MAAM,IAAI,CAAC,SAAS,EAAE,kBAAkB,EAAE,EAAE,CAAC;YAC/C,CAAC;YACD,gBAAgB,EAAE,KAAK,EAAE,SAAiB,EAAE,EAAE;gBAC5C,MAAM,IAAI,CAAC,SAAS,EAAE,gBAAgB,EAAE,CAAC,SAAS,CAAC,CAAC;YACtD,CAAC;SACF,CAAC;IACJ,CAAC;IAED,2BAA2B;IAC3B,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,sEAAsE;IACtE,gBAAgB;IAChB,sEAAsE;IAE7D,aAAa,GAAG;QACvB;;WAEG;QACH,OAAO,EAAE,GAA0B,EAAE;YACnC,OAAO,IAAI,qBAAqB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACxD,CAAC;QAED;;WAEG;QACH,eAAe,EAAE,GAAsB,EAAE;YACvC,OAAO,IAAI,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACtD,CAAC;QAED;;WAEG;QACH,IAAI,EAAE,KAAK,EAAE,MAAc,EAAE,MAAgC,EAAiB,EAAE;YAC9E,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC5D,CAAC;KACF,CAAC;IAEF,sEAAsE;IACtE,sBAAsB;IACtB,sEAAsE;IAE7D,IAAI,GAAG;QACd,GAAG,EAAE,GAAe,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;QAEtC,MAAM,EAAE,CAAC,KAA0C,EAAc,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC;QAE/G,MAAM,EAAE,CAAC,IAAY,EAAc,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAExF,IAAI,EAAE,GAAyB,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QAEnE,KAAK,EAAE,GAAS,EAAE;YAChB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAClB,CAAC;KACF,CAAC;IAEO,KAAK,GAAG;QACf,GAAG,EAAE,GAAmB,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;QAE5C,IAAI,EAAE,GAA6B,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QAE3E,KAAK,EAAE,GAAS,EAAE;YAChB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QACpB,CAAC;KACF,CAAC;IAEF,sEAAsE;IACtE,yBAAyB;IACzB,sEAAsE;IAEtE;;;;;;;;;;;;;;;;;;OAkBG;IACM,IAAI,GAAG;QACd;;WAEG;QACH,GAAG,EAAE,CAAC,IAAoB,EAAc,EAAE;YACxC,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;QAED;;WAEG;QACH,IAAI,EAAE,CAAC,IAAY,EAAE,MAAe,EAAE,OAA4C,EAAc,EAAE;YAChG,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC;gBAClC,MAAM,EAAE,YAAY;gBACpB,MAAM,EAAE,EAAE,IAAI,EAAE;gBAChB,QAAQ,EAAE,0BAAY,CAAC,UAAU,CAAC;oBAChC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;iBACrF,CAAC;gBACF,KAAK,EAAE,OAAO,EAAE,KAAK;gBACrB,KAAK,EAAE,OAAO,EAAE,KAAK;aACtB,CAAC,CAAC;QACL,CAAC;QAED;;WAEG;QACH,SAAS,EAAE,CAAC,IAAY,EAAE,IAAY,EAAE,OAAe,EAAE,OAA4B,EAAc,EAAE;YACnG,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC;gBAClC,MAAM,EAAE,YAAY;gBACpB,MAAM,EAAE,EAAE,IAAI,EAAE;gBAChB,QAAQ,EAAE,0BAAY,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC;gBAC3C,KAAK,EAAE,OAAO,EAAE,KAAK;aACtB,CAAC,CAAC;QACL,CAAC;QAED;;WAEG;QACH,QAAQ,EAAE,CACR,GAAW,EACX,OAAqE,EACrE,OAA4C,EAChC,EAAE;YACd,MAAM,UAAU,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;YAC9F,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC;gBAClC,MAAM,EAAE,gBAAgB;gBACxB,MAAM,EAAE,EAAE,GAAG,EAAE;gBACf,QAAQ,EAAE,0BAAY,CAAC,YAAY,CAAC,CAAC,UAAU,CAAC,CAAC;gBACjD,KAAK,EAAE,OAAO,EAAE,KAAK;gBACrB,KAAK,EAAE,OAAO,EAAE,KAAK;aACtB,CAAC,CAAC;QACL,CAAC;QAED;;WAEG;QACH,aAAa,EAAE,CAAC,GAAW,EAAE,OAA4B,EAAc,EAAE;YACvE,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC;gBAClC,MAAM,EAAE,gBAAgB;gBACxB,MAAM,EAAE,EAAE,GAAG,EAAE;gBACf,QAAQ,EAAE,0BAAY,CAAC,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC;gBACnD,KAAK,EAAE,OAAO,EAAE,KAAK;aACtB,CAAC,CAAC;QACL,CAAC;QAED;;WAEG;QACH,SAAS,EAAE,CACT,KAA2F,EAC3F,OAA4B,EAChB,EAAE;YACd,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC;gBAClC,MAAM,EAAE,YAAY;gBACpB,QAAQ,EAAE,0BAAY,CAAC,SAAS,CAAC,KAAK,CAAC;gBACvC,KAAK,EAAE,OAAO,EAAE,KAAK;aACtB,CAAC,CAAC;QACL,CAAC;QAED;;WAEG;QACH,aAAa,EAAE,CACb,SAAyF,EACzF,OAA4B,EAChB,EAAE;YACd,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC;gBAClC,MAAM,EAAE,gBAAgB;gBACxB,QAAQ,EAAE,0BAAY,CAAC,aAAa,CAAC,SAAS,CAAC;gBAC/C,KAAK,EAAE,OAAO,EAAE,KAAK;aACtB,CAAC,CAAC;QACL,CAAC;QAED;;WAEG;QACH,KAAK,EAAE,GAAS,EAAE;YAChB,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnC,CAAC;QAED;;WAEG;QACH,GAAG,EAAE,GAAqB,EAAE;YAC1B,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAC3C,CAAC;KACF,CAAC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACM,SAAS,GAAG;QACnB;;;WAGG;QACH,OAAO,EAAE,CAAC,WAA+B,EAAgB,EAAE;YACzD,OAAQ,IAAI,CAAC,aAAyC,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC;QAC5F,CAAC;QAED;;;WAGG;QACH,QAAQ,EAAE,CAAC,WAAgC,EAAgB,EAAE;YAC3D,OAAQ,IAAI,CAAC,aAAyC,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC;QAC7F,CAAC;QAED;;;WAGG;QACH,KAAK,EAAE,CAAC,EAAU,EAAgB,EAAE;YAClC,OAAQ,IAAI,CAAC,aAAyC,CAAC,qBAAqB,CAAC,KAAK,IAAI,EAAE;gBACtF,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;gBAC5C,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;YACnC,CAAC,CAAC,CAAC;QACL,CAAC;QAED;;;WAGG;QACH,UAAU,EAAE,CAAC,MAAc,EAAE,KAAc,EAAgB,EAAE;YAC3D,OAAQ,IAAI,CAAC,aAAyC,CAAC,qBAAqB,CAAC,CAAC,GAAG,EAAE,EAAE;gBACnF,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;oBAClC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,KAAK,CAAC,KAAK,IAAI,gBAAgB,MAAM,EAAE,CAAC,EAAE,CAAC;gBAClF,CAAC;gBACD,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;YACnC,CAAC,CAAC,CAAC;QACL,CAAC;QAED;;WAEG;QACH,KAAK,EAAE,GAAS,EAAE;YACf,IAAI,CAAC,aAAyC,CAAC,OAAO,GAAG,EAAE,CAAC;YAC5D,IAAI,CAAC,aAAyC,CAAC,QAAQ,GAAG,EAAE,CAAC;QAChE,CAAC;QAED;;WAEG;QACH,QAAQ,EAAE,GAAS,EAAE;YAClB,IAAI,CAAC,aAAyC,CAAC,KAAK,EAAE,CAAC;QAC1D,CAAC;KACF,CAAC;IAEF,sEAAsE;IACtE,UAAU;IACV,sEAAsE;IAEtE,UAAU,CAAC,EAAU;QACnB,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,0BAA0B;IAC1B,sEAAsE;IAE9D,KAAK,CAAC,UAAU;QACtB,OAAO,IAAI,CAAC,OAAO,CAAmB,YAAY,EAAE;YAClD,eAAe,EAAE,IAAI,CAAC,MAAM,CAAC,eAAe;YAC5C,YAAY,EAAE;gBACZ,QAAQ,EAAE,EAAE;aACb;YACD,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU;SACnC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,SAAS;QACrB,OAAO,IAAI,CAAC,OAAO,CAAkB,YAAY,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,IAAY,EAAE,IAA8B;QACjE,OAAO,IAAI,CAAC,OAAO,CAAiB,YAAY,EAAE;YAChD,IAAI;YACJ,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,aAAa;QACzB,OAAO,IAAI,CAAC,OAAO,CAAsB,gBAAgB,EAAE,EAAE,CAAC,CAAC;IACjE,CAAC;IAEO,KAAK,CAAC,qBAAqB;QACjC,OAAO,IAAI,CAAC,OAAO,CAA8B,0BAA0B,EAAE,EAAE,CAAC,CAAC;IACnF,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,GAAW;QACpC,OAAO,IAAI,CAAC,OAAO,CAAqB,gBAAgB,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IACrE,CAAC;IAEO,KAAK,CAAC,WAAW;QACvB,OAAO,IAAI,CAAC,OAAO,CAAoB,cAAc,EAAE,EAAE,CAAC,CAAC;IAC7D,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,IAAY,EAAE,IAA6B;QACjE,OAAO,IAAI,CAAC,OAAO,CAAkB,aAAa,EAAE;YAClD,IAAI;YACJ,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAC,CAAC;IACL,CAAC;IAED,sEAAsE;IACtE,uCAAuC;IACvC,sEAAsE;IAE9D,eAAe;QACrB,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YAC9B,KAAK,iBAAiB;gBACpB,OAAO,IAAI,mDAAuB,CAAC;oBACjC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;oBAC5B,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;oBAC5B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI;oBACtB,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU;oBAClC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK;oBACxB,YAAY,EAAE,IAAI,CAAC,aAAa;iBACjC,CAAC,CAAC;YACL,KAAK,KAAK;gBACR,gCAAgC;gBAChC,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;YACvD;gBACE,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,OAAO,CAAI,MAAc,EAAE,MAA+B;QACtE,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,gBAAgB,CAAC;QACnC,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEzB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAU,CAAC,OAAO,CAAI;gBAChD,OAAO,EAAE,KAAK;gBACd,EAAE;gBACF,MAAM;gBACN,MAAM;aACP,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;YACtC,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAE7B,IAAI,OAAO,IAAI,QAAQ,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAC1C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAqB,CAAC;gBAC7C,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;gBAC5D,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK;oBACL,UAAU;oBACV,SAAS,EAAE,EAAE;iBACd,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;YAC5D,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,IAAI,EAAE,QAAQ,CAAC,MAAW;gBAC1B,UAAU;gBACV,SAAS,EAAE,EAAE;aACd,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;YACtC,MAAM,KAAK,GAAiB;gBAC1B,IAAI,EAAE,CAAC,KAAK;gBACZ,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;aAC9D,CAAC;YACF,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK;gBACL,UAAU;gBACV,SAAS,EAAE,EAAE;aACd,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,eAAe;QACrB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IAEO,qBAAqB;QAC3B,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,CAAC,YAAY,CAAC,cAAc,GAAG,IAAI,IAAI,EAAE,CAAC;YAC9C,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC;QACnC,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,2BAA2B;IAC3B,sEAAsE;IAE9D,cAAc,CAAC,QAAqC;QAC1D,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAC7C,MAAM,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC;QAE1D,0EAA0E;QAC1E,MAAM,IAAI,GAAG,GAAG,CAAC,KAA4C,CAAC;QAC9D,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC,SAAS,CAAC,KAAK,SAAS,CAAC;QAC9C,MAAM,iBAAiB,GAAI,GAA+B,CAAC,mBAAmB,CAAC,CAAC;QAEhF,OAAO;YACL,GAAG;YACH,SAAS,EAAE,CAAC,OAAO;YACnB,OAAO;YACP,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,IAAI;gBACF,qEAAqE;gBACrE,IAAI,KAAK,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;oBAC7C,OAAO,iBAAsB,CAAC;gBAChC,CAAC;gBACD,oDAAoD;gBACpD,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;gBAChE,IAAI,WAAW,IAAI,MAAM,IAAI,WAAW,EAAE,CAAC;oBACzC,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAM,CAAC;gBAC3C,CAAC;gBACD,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;YACtD,CAAC;YACD,IAAI;gBACF,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;gBAChE,IAAI,WAAW,IAAI,MAAM,IAAI,WAAW,EAAE,CAAC;oBACzC,OAAO,WAAW,CAAC,IAAI,CAAC;gBAC1B,CAAC;gBACD,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,cAAc;gBACZ,OAAO,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC;YAC9D,CAAC;YACD,eAAe;gBACb,OAAO,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,KAAK,CAAC;YAC/D,CAAC;YACD,kBAAkB;gBAChB,OAAO,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI,KAAK,CAAC;YAClE,CAAC;YACD,SAAS;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;SACF,CAAC;IACJ,CAAC;IAEO,mBAAmB,CAAC,QAAyC;QACnE,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;QAClC,MAAM,YAAY,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;QAEvC,OAAO;YACL,GAAG;YACH,SAAS,EAAE,CAAC,OAAO;YACnB,OAAO;YACP,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,IAAI;gBACF,IAAI,YAAY,IAAI,MAAM,IAAI,YAAY,EAAE,CAAC;oBAC3C,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAM,CAAC;gBAC5C,CAAC;gBACD,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;YACtD,CAAC;YACD,IAAI;gBACF,IAAI,YAAY,IAAI,MAAM,IAAI,YAAY,EAAE,CAAC;oBAC3C,OAAO,YAAY,CAAC,IAAI,CAAC;gBAC3B,CAAC;gBACD,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,QAAQ;gBACN,OAAO,YAAY,EAAE,QAAQ,CAAC;YAChC,CAAC;YACD,WAAW,CAAC,IAAY;gBACtB,OAAO,YAAY,EAAE,QAAQ,KAAK,IAAI,CAAC;YACzC,CAAC;SACF,CAAC;IACJ,CAAC;IAEO,gBAAgB,CAAC,QAAsC;QAC7D,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;QAElC,OAAO;YACL,GAAG;YACH,SAAS,EAAE,CAAC,OAAO;YACnB,OAAO;YACP,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE;YAC5B,WAAW,EAAE,GAAG,CAAC,WAAW;SAC7B,CAAC;IACJ,CAAC;IAED,sEAAsE;IACtE,6BAA6B;IAC7B,sEAAsE;IAE9D,GAAG,CAAC,KAA0C,EAAE,OAAe,EAAE,IAAc;QACrF,MAAM,KAAK,GAAa;YACtB,KAAK;YACL,OAAO;YACP,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,IAAI;SACL,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEvB,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,WAAW,EAAE,KAAK,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAEO,YAAY,CAClB,MAAc,EACd,MAAe,EACf,EAAmB,EACnB,QAAyB,EACzB,UAAkB;QAElB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YAChB,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;YAC/B,QAAQ,EAAE;gBACR,MAAM,EAAE,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;gBAC1D,KAAK,EAAE,OAAO,IAAI,QAAQ,CAAC,CAAC,CAAE,QAAQ,CAAC,KAAsB,CAAC,CAAC,CAAC,SAAS;aAC1E;YACD,UAAU;YACV,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAC,CAAC;IACL,CAAC;IAED,sEAAsE;IACtE,yBAAyB;IACzB,sEAAsE;IAE9D,oBAAoB,CAAC,KAAa;QACxC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;YAC7C,IAAI,CAAC,OAAO;gBAAE,OAAO,EAAE,CAAC;YACxB,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;YAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;YACjC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC9B,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;YACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1B,OAAO,MAAkB,CAAC;YAC5B,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAEO,kBAAkB,CAAC,KAAa;QACtC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;YAC7C,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;YAC7B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE,OAAO,SAAS,CAAC;YACtD,OAAO;gBACL,GAAG;gBACH,KAAK,EAAE,OAAO,CAAC,OAAO,CAAuB;gBAC7C,IAAI,EAAE,OAAO,CAAC,MAAM,CAAuB;aAC5C,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAEO,gBAAgB,CAAC,KAAa;QACpC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YACpC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACrE,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;CACF;AA3+BD,sCA2+BC;AAED,sEAAsE;AACtE,0BAA0B;AAC1B,sEAAsE;AAEtE,MAAM,qBAAqB;IACI;IAA7B,YAA6B,aAAkC;QAAlC,kBAAa,GAAb,aAAa,CAAqB;IAAG,CAAC;IAEnE,IAAI,QAAQ;QACV,OAAO,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;IAED,GAAG,CAAC,MAAc;QAChB,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,SAAiB;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QACxC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;YAClE,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAC;YACxB,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,qCAAqC,MAAM,EAAE,CAAC,CAAC;IACjE,CAAC;CACF;AAED,MAAM,iBAAiB;IACQ;IAA7B,YAA6B,OAAyB;QAAzB,YAAO,GAAP,OAAO,CAAkB;IAAG,CAAC;IAE1D,IAAI,GAAG;QACL,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,SAAiB;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QACxC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACnD,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACpE,OAAO;YACT,CAAC;YACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;CACF","sourcesContent":["/**\n * @file mcp-test-client.ts\n * @description Main MCP Test Client implementation for E2E testing\n */\n\nimport type {\n McpTestClientConfig,\n McpResponse,\n TestTransportType,\n TestAuthConfig,\n ToolResultWrapper,\n ResourceContentWrapper,\n PromptResultWrapper,\n LogEntry,\n RequestTrace,\n NotificationEntry,\n ProgressUpdate,\n SessionInfo,\n AuthState,\n McpErrorInfo,\n InitializeResult,\n ListToolsResult,\n CallToolResult,\n ListResourcesResult,\n ReadResourceResult,\n ListResourceTemplatesResult,\n ListPromptsResult,\n GetPromptResult,\n Tool,\n Resource,\n ResourceTemplate,\n Prompt,\n JSONRPCResponse,\n} from './mcp-test-client.types';\nimport { McpTestClientBuilder } from './mcp-test-client.builder';\nimport type { McpTransport } from '../transport/transport.interface';\nimport { StreamableHttpTransport } from '../transport/streamable-http.transport';\nimport type {\n InterceptorChain,\n MockDefinition,\n MockHandle,\n RequestInterceptor,\n ResponseInterceptor,\n} from '../interceptor';\nimport { DefaultInterceptorChain, mockResponse } from '../interceptor';\n\n// ═══════════════════════════════════════════════════════════════════\n// CONSTANTS\n// ═══════════════════════════════════════════════════════════════════\n\nconst DEFAULT_TIMEOUT = 30000;\nconst DEFAULT_PROTOCOL_VERSION = '2025-06-18';\nconst DEFAULT_CLIENT_INFO = {\n name: '@frontmcp/testing',\n version: '0.4.0',\n};\n\n// ═══════════════════════════════════════════════════════════════════\n// MAIN CLIENT CLASS\n// ═══════════════════════════════════════════════════════════════════\n\nexport class McpTestClient {\n private readonly config: Required<McpTestClientConfig>;\n private transport: McpTransport | null = null;\n private initResult: InitializeResult | null = null;\n private requestIdCounter = 0;\n private _lastRequestId: string | number = 0;\n private _sessionId: string | undefined;\n private _sessionInfo: SessionInfo | null = null;\n private _authState: AuthState = { isAnonymous: true, scopes: [] };\n\n // Logging and tracing\n private _logs: LogEntry[] = [];\n private _traces: RequestTrace[] = [];\n private _notifications: NotificationEntry[] = [];\n private _progressUpdates: ProgressUpdate[] = [];\n\n // Interceptor chain\n private _interceptors: InterceptorChain;\n\n // ═══════════════════════════════════════════════════════════════════\n // CONSTRUCTOR & FACTORY\n // ═══════════════════════════════════════════════════════════════════\n\n constructor(config: McpTestClientConfig) {\n this.config = {\n baseUrl: config.baseUrl,\n transport: config.transport ?? 'streamable-http',\n auth: config.auth ?? {},\n publicMode: config.publicMode ?? false,\n timeout: config.timeout ?? DEFAULT_TIMEOUT,\n debug: config.debug ?? false,\n protocolVersion: config.protocolVersion ?? DEFAULT_PROTOCOL_VERSION,\n clientInfo: config.clientInfo ?? DEFAULT_CLIENT_INFO,\n };\n\n // In public mode, user is always anonymous (no token authentication)\n if (config.publicMode) {\n this._authState = {\n isAnonymous: true,\n scopes: [],\n };\n } else if (config.auth?.token) {\n // Parse auth state from config\n this._authState = {\n isAnonymous: false,\n token: config.auth.token,\n scopes: this.parseScopesFromToken(config.auth.token),\n user: this.parseUserFromToken(config.auth.token),\n };\n }\n\n // Initialize interceptor chain\n this._interceptors = new DefaultInterceptorChain();\n }\n\n /**\n * Create a new McpTestClientBuilder for fluent configuration\n */\n static create(config: McpTestClientConfig): McpTestClientBuilder {\n return new McpTestClientBuilder(config);\n }\n\n // ═══════════════════════════════════════════════════════════════════\n // CONNECTION & LIFECYCLE\n // ═══════════════════════════════════════════════════════════════════\n\n /**\n * Connect to the MCP server and perform initialization\n */\n async connect(): Promise<InitializeResult> {\n this.log('debug', `Connecting to ${this.config.baseUrl}...`);\n\n // Create transport based on config\n this.transport = this.createTransport();\n\n // Connect transport\n await this.transport.connect();\n\n // Perform MCP initialization\n const initResponse = await this.initialize();\n\n if (!initResponse.success || !initResponse.data) {\n throw new Error(`Failed to initialize MCP connection: ${initResponse.error?.message ?? 'Unknown error'}`);\n }\n\n this.initResult = initResponse.data;\n this._sessionId = this.transport.getSessionId();\n this._sessionInfo = {\n id: this._sessionId ?? `session-${Date.now()}`,\n createdAt: new Date(),\n lastActivityAt: new Date(),\n requestCount: 1,\n };\n\n // Send initialized notification per MCP protocol\n // This notification MUST be sent after receiving initialize response\n // before the client can make any other requests\n await this.transport.notify({\n jsonrpc: '2.0',\n method: 'notifications/initialized',\n });\n\n this.log('info', `Connected to ${this.initResult.serverInfo?.name ?? 'MCP Server'}`);\n\n return this.initResult;\n }\n\n /**\n * Disconnect from the MCP server\n */\n async disconnect(): Promise<void> {\n if (this.transport) {\n await this.transport.close();\n this.transport = null;\n }\n this.initResult = null;\n this.log('info', 'Disconnected from MCP server');\n }\n\n /**\n * Reconnect to the server, optionally with an existing session ID\n */\n async reconnect(options?: { sessionId?: string }): Promise<void> {\n await this.disconnect();\n\n if (options?.sessionId && this.transport) {\n // Set session ID before reconnecting\n this._sessionId = options.sessionId;\n }\n\n await this.connect();\n }\n\n /**\n * Check if the client is currently connected\n */\n isConnected(): boolean {\n return this.transport?.isConnected() ?? false;\n }\n\n // ═══════════════════════════════════════════════════════════════════\n // SESSION & AUTH PROPERTIES\n // ═══════════════════════════════════════════════════════════════════\n\n get sessionId(): string {\n return this._sessionId ?? '';\n }\n\n get session(): SessionInfo & { expire: () => Promise<void> } {\n const info = this._sessionInfo ?? {\n id: '',\n createdAt: new Date(),\n lastActivityAt: new Date(),\n requestCount: 0,\n };\n\n return {\n ...info,\n expire: async () => {\n // Force session expiration for testing\n this._sessionId = undefined;\n this._sessionInfo = null;\n },\n };\n }\n\n get auth(): AuthState {\n return this._authState;\n }\n\n /**\n * Authenticate with a token\n */\n async authenticate(token: string): Promise<void> {\n this._authState = {\n isAnonymous: false,\n token,\n scopes: this.parseScopesFromToken(token),\n user: this.parseUserFromToken(token),\n };\n\n // Update transport headers\n if (this.transport) {\n this.transport.setAuthToken(token);\n }\n\n this.log('debug', 'Authentication updated');\n }\n\n // ═══════════════════════════════════════════════════════════════════\n // SERVER INFO & CAPABILITIES\n // ═══════════════════════════════════════════════════════════════════\n\n get serverInfo(): { name: string; version: string; title?: string } {\n return {\n name: this.initResult?.serverInfo?.name ?? '',\n version: this.initResult?.serverInfo?.version ?? '',\n };\n }\n\n get protocolVersion(): string {\n return this.initResult?.protocolVersion ?? '';\n }\n\n get instructions(): string {\n return this.initResult?.instructions ?? '';\n }\n\n get capabilities(): InitializeResult['capabilities'] {\n return this.initResult?.capabilities ?? {};\n }\n\n /**\n * Check if server has a specific capability\n */\n hasCapability(name: 'tools' | 'resources' | 'prompts' | 'logging' | 'sampling'): boolean {\n return !!this.capabilities[name];\n }\n\n // ═══════════════════════════════════════════════════════════════════\n // TOOLS API\n // ═══════════════════════════════════════════════════════════════════\n\n readonly tools = {\n /**\n * List all available tools\n */\n list: async (): Promise<Tool[]> => {\n const response = await this.listTools();\n if (!response.success || !response.data) {\n throw new Error(`Failed to list tools: ${response.error?.message}`);\n }\n return response.data.tools;\n },\n\n /**\n * Call a tool by name with arguments\n */\n call: async (name: string, args?: Record<string, unknown>): Promise<ToolResultWrapper> => {\n const response = await this.callTool(name, args);\n return this.wrapToolResult(response);\n },\n };\n\n // ═══════════════════════════════════════════════════════════════════\n // RESOURCES API\n // ═══════════════════════════════════════════════════════════════════\n\n readonly resources = {\n /**\n * List all static resources\n */\n list: async (): Promise<Resource[]> => {\n const response = await this.listResources();\n if (!response.success || !response.data) {\n throw new Error(`Failed to list resources: ${response.error?.message}`);\n }\n return response.data.resources;\n },\n\n /**\n * List all resource templates\n */\n listTemplates: async (): Promise<ResourceTemplate[]> => {\n const response = await this.listResourceTemplates();\n if (!response.success || !response.data) {\n throw new Error(`Failed to list resource templates: ${response.error?.message}`);\n }\n return response.data.resourceTemplates;\n },\n\n /**\n * Read a resource by URI\n */\n read: async (uri: string): Promise<ResourceContentWrapper> => {\n const response = await this.readResource(uri);\n return this.wrapResourceContent(response);\n },\n\n /**\n * Subscribe to resource changes (placeholder for future implementation)\n */\n subscribe: async (_uri: string): Promise<void> => {\n // TODO: Implement resource subscription\n this.log('warn', 'Resource subscription not yet implemented');\n },\n\n /**\n * Unsubscribe from resource changes (placeholder for future implementation)\n */\n unsubscribe: async (_uri: string): Promise<void> => {\n // TODO: Implement resource unsubscription\n this.log('warn', 'Resource unsubscription not yet implemented');\n },\n };\n\n // ═══════════════════════════════════════════════════════════════════\n // PROMPTS API\n // ═══════════════════════════════════════════════════════════════════\n\n readonly prompts = {\n /**\n * List all available prompts\n */\n list: async (): Promise<Prompt[]> => {\n const response = await this.listPrompts();\n if (!response.success || !response.data) {\n throw new Error(`Failed to list prompts: ${response.error?.message}`);\n }\n return response.data.prompts;\n },\n\n /**\n * Get a prompt with arguments\n */\n get: async (name: string, args?: Record<string, string>): Promise<PromptResultWrapper> => {\n const response = await this.getPrompt(name, args);\n return this.wrapPromptResult(response);\n },\n };\n\n // ═══════════════════════════════════════════════════════════════════\n // RAW PROTOCOL ACCESS\n // ═══════════════════════════════════════════════════════════════════\n\n readonly raw = {\n /**\n * Send any JSON-RPC request\n */\n request: async (message: {\n jsonrpc: '2.0';\n id: string | number;\n method: string;\n params?: Record<string, unknown>;\n }): Promise<JSONRPCResponse> => {\n this.ensureConnected();\n const start = Date.now();\n const response = await this.transport!.request(message);\n this.traceRequest(message.method, message.params, message.id, response, Date.now() - start);\n return response;\n },\n\n /**\n * Send a notification (no response expected)\n */\n notify: async (message: { jsonrpc: '2.0'; method: string; params?: Record<string, unknown> }): Promise<void> => {\n this.ensureConnected();\n await this.transport!.notify(message);\n },\n\n /**\n * Send raw string data (for error testing)\n */\n sendRaw: async (data: string): Promise<JSONRPCResponse> => {\n this.ensureConnected();\n return this.transport!.sendRaw(data);\n },\n };\n\n get lastRequestId(): string | number {\n return this._lastRequestId;\n }\n\n // ═══════════════════════════════════════════════════════════════════\n // TRANSPORT INFO\n // ═══════════════════════════════════════════════════════════════════\n\n /**\n * Get transport information and utilities\n */\n get transport_info(): {\n type: TestTransportType;\n isConnected: () => boolean;\n messageEndpoint: string | undefined;\n connectionCount: number;\n reconnectCount: number;\n lastRequestHeaders: Record<string, string>;\n simulateDisconnect: () => Promise<void>;\n waitForReconnect: (timeoutMs: number) => Promise<void>;\n } {\n return {\n type: this.config.transport,\n isConnected: () => this.transport?.isConnected() ?? false,\n messageEndpoint: this.transport?.getMessageEndpoint?.(),\n connectionCount: this.transport?.getConnectionCount?.() ?? 0,\n reconnectCount: this.transport?.getReconnectCount?.() ?? 0,\n lastRequestHeaders: this.transport?.getLastRequestHeaders?.() ?? {},\n simulateDisconnect: async () => {\n await this.transport?.simulateDisconnect?.();\n },\n waitForReconnect: async (timeoutMs: number) => {\n await this.transport?.waitForReconnect?.(timeoutMs);\n },\n };\n }\n\n // Alias for transport info\n get transport_() {\n return this.transport_info;\n }\n\n // ═══════════════════════════════════════════════════════════════════\n // NOTIFICATIONS\n // ═══════════════════════════════════════════════════════════════════\n\n readonly notifications = {\n /**\n * Start collecting server notifications\n */\n collect: (): NotificationCollector => {\n return new NotificationCollector(this._notifications);\n },\n\n /**\n * Collect progress notifications specifically\n */\n collectProgress: (): ProgressCollector => {\n return new ProgressCollector(this._progressUpdates);\n },\n\n /**\n * Send a notification to the server\n */\n send: async (method: string, params?: Record<string, unknown>): Promise<void> => {\n await this.raw.notify({ jsonrpc: '2.0', method, params });\n },\n };\n\n // ═══════════════════════════════════════════════════════════════════\n // LOGGING & DEBUGGING\n // ═══════════════════════════════════════════════════════════════════\n\n readonly logs = {\n all: (): LogEntry[] => [...this._logs],\n\n filter: (level: 'debug' | 'info' | 'warn' | 'error'): LogEntry[] => this._logs.filter((l) => l.level === level),\n\n search: (text: string): LogEntry[] => this._logs.filter((l) => l.message.includes(text)),\n\n last: (): LogEntry | undefined => this._logs[this._logs.length - 1],\n\n clear: (): void => {\n this._logs = [];\n },\n };\n\n readonly trace = {\n all: (): RequestTrace[] => [...this._traces],\n\n last: (): RequestTrace | undefined => this._traces[this._traces.length - 1],\n\n clear: (): void => {\n this._traces = [];\n },\n };\n\n // ═══════════════════════════════════════════════════════════════════\n // MOCKING & INTERCEPTION\n // ═══════════════════════════════════════════════════════════════════\n\n /**\n * API for mocking MCP requests\n *\n * @example\n * ```typescript\n * // Mock a specific tool call\n * const handle = mcp.mock.tool('my-tool', { result: 'mocked!' });\n *\n * // Mock with params matching\n * mcp.mock.add({\n * method: 'tools/call',\n * params: { name: 'my-tool' },\n * response: mockResponse.toolResult([{ type: 'text', text: 'mocked' }]),\n * });\n *\n * // Clear all mocks after test\n * mcp.mock.clear();\n * ```\n */\n readonly mock = {\n /**\n * Add a mock definition\n */\n add: (mock: MockDefinition): MockHandle => {\n return this._interceptors.mocks.add(mock);\n },\n\n /**\n * Mock a tools/call request for a specific tool\n */\n tool: (name: string, result: unknown, options?: { times?: number; delay?: number }): MockHandle => {\n return this._interceptors.mocks.add({\n method: 'tools/call',\n params: { name },\n response: mockResponse.toolResult([\n { type: 'text', text: typeof result === 'string' ? result : JSON.stringify(result) },\n ]),\n times: options?.times,\n delay: options?.delay,\n });\n },\n\n /**\n * Mock a tools/call request to return an error\n */\n toolError: (name: string, code: number, message: string, options?: { times?: number }): MockHandle => {\n return this._interceptors.mocks.add({\n method: 'tools/call',\n params: { name },\n response: mockResponse.error(code, message),\n times: options?.times,\n });\n },\n\n /**\n * Mock a resources/read request\n */\n resource: (\n uri: string,\n content: string | { text?: string; blob?: string; mimeType?: string },\n options?: { times?: number; delay?: number },\n ): MockHandle => {\n const contentObj = typeof content === 'string' ? { uri, text: content } : { uri, ...content };\n return this._interceptors.mocks.add({\n method: 'resources/read',\n params: { uri },\n response: mockResponse.resourceRead([contentObj]),\n times: options?.times,\n delay: options?.delay,\n });\n },\n\n /**\n * Mock a resources/read request to return an error\n */\n resourceError: (uri: string, options?: { times?: number }): MockHandle => {\n return this._interceptors.mocks.add({\n method: 'resources/read',\n params: { uri },\n response: mockResponse.errors.resourceNotFound(uri),\n times: options?.times,\n });\n },\n\n /**\n * Mock the tools/list response\n */\n toolsList: (\n tools: Array<{ name: string; description?: string; inputSchema?: Record<string, unknown> }>,\n options?: { times?: number },\n ): MockHandle => {\n return this._interceptors.mocks.add({\n method: 'tools/list',\n response: mockResponse.toolsList(tools),\n times: options?.times,\n });\n },\n\n /**\n * Mock the resources/list response\n */\n resourcesList: (\n resources: Array<{ uri: string; name?: string; description?: string; mimeType?: string }>,\n options?: { times?: number },\n ): MockHandle => {\n return this._interceptors.mocks.add({\n method: 'resources/list',\n response: mockResponse.resourcesList(resources),\n times: options?.times,\n });\n },\n\n /**\n * Clear all mocks\n */\n clear: (): void => {\n this._interceptors.mocks.clear();\n },\n\n /**\n * Get all active mocks\n */\n all: (): MockDefinition[] => {\n return this._interceptors.mocks.getAll();\n },\n };\n\n /**\n * API for intercepting requests and responses\n *\n * @example\n * ```typescript\n * // Log all requests\n * const remove = mcp.intercept.request((ctx) => {\n * console.log('Request:', ctx.request.method);\n * return { action: 'passthrough' };\n * });\n *\n * // Modify requests\n * mcp.intercept.request((ctx) => {\n * if (ctx.request.method === 'tools/call') {\n * return {\n * action: 'modify',\n * request: { ...ctx.request, params: { ...ctx.request.params, extra: true } },\n * };\n * }\n * return { action: 'passthrough' };\n * });\n *\n * // Add latency to all requests\n * mcp.intercept.delay(100);\n *\n * // Clean up\n * remove();\n * mcp.intercept.clear();\n * ```\n */\n readonly intercept = {\n /**\n * Add a request interceptor\n * @returns Function to remove the interceptor\n */\n request: (interceptor: RequestInterceptor): (() => void) => {\n return (this._interceptors as DefaultInterceptorChain).addRequestInterceptor(interceptor);\n },\n\n /**\n * Add a response interceptor\n * @returns Function to remove the interceptor\n */\n response: (interceptor: ResponseInterceptor): (() => void) => {\n return (this._interceptors as DefaultInterceptorChain).addResponseInterceptor(interceptor);\n },\n\n /**\n * Add latency to all requests\n * @returns Function to remove the interceptor\n */\n delay: (ms: number): (() => void) => {\n return (this._interceptors as DefaultInterceptorChain).addRequestInterceptor(async () => {\n await new Promise((r) => setTimeout(r, ms));\n return { action: 'passthrough' };\n });\n },\n\n /**\n * Fail requests matching a method\n * @returns Function to remove the interceptor\n */\n failMethod: (method: string, error?: string): (() => void) => {\n return (this._interceptors as DefaultInterceptorChain).addRequestInterceptor((ctx) => {\n if (ctx.request.method === method) {\n return { action: 'error', error: new Error(error ?? `Intercepted: ${method}`) };\n }\n return { action: 'passthrough' };\n });\n },\n\n /**\n * Clear all interceptors (but not mocks)\n */\n clear: (): void => {\n (this._interceptors as DefaultInterceptorChain).request = [];\n (this._interceptors as DefaultInterceptorChain).response = [];\n },\n\n /**\n * Clear everything (interceptors and mocks)\n */\n clearAll: (): void => {\n (this._interceptors as DefaultInterceptorChain).clear();\n },\n };\n\n // ═══════════════════════════════════════════════════════════════════\n // TIMEOUT\n // ═══════════════════════════════════════════════════════════════════\n\n setTimeout(ms: number): void {\n this.config.timeout = ms;\n if (this.transport) {\n this.transport.setTimeout(ms);\n }\n }\n\n // ═══════════════════════════════════════════════════════════════════\n // PRIVATE: MCP OPERATIONS\n // ═══════════════════════════════════════════════════════════════════\n\n private async initialize(): Promise<McpResponse<InitializeResult>> {\n return this.request<InitializeResult>('initialize', {\n protocolVersion: this.config.protocolVersion,\n capabilities: {\n sampling: {},\n },\n clientInfo: this.config.clientInfo,\n });\n }\n\n private async listTools(): Promise<McpResponse<ListToolsResult>> {\n return this.request<ListToolsResult>('tools/list', {});\n }\n\n private async callTool(name: string, args?: Record<string, unknown>): Promise<McpResponse<CallToolResult>> {\n return this.request<CallToolResult>('tools/call', {\n name,\n arguments: args ?? {},\n });\n }\n\n private async listResources(): Promise<McpResponse<ListResourcesResult>> {\n return this.request<ListResourcesResult>('resources/list', {});\n }\n\n private async listResourceTemplates(): Promise<McpResponse<ListResourceTemplatesResult>> {\n return this.request<ListResourceTemplatesResult>('resources/templates/list', {});\n }\n\n private async readResource(uri: string): Promise<McpResponse<ReadResourceResult>> {\n return this.request<ReadResourceResult>('resources/read', { uri });\n }\n\n private async listPrompts(): Promise<McpResponse<ListPromptsResult>> {\n return this.request<ListPromptsResult>('prompts/list', {});\n }\n\n private async getPrompt(name: string, args?: Record<string, string>): Promise<McpResponse<GetPromptResult>> {\n return this.request<GetPromptResult>('prompts/get', {\n name,\n arguments: args ?? {},\n });\n }\n\n // ═══════════════════════════════════════════════════════════════════\n // PRIVATE: TRANSPORT & REQUEST HELPERS\n // ═══════════════════════════════════════════════════════════════════\n\n private createTransport(): McpTransport {\n switch (this.config.transport) {\n case 'streamable-http':\n return new StreamableHttpTransport({\n baseUrl: this.config.baseUrl,\n timeout: this.config.timeout,\n auth: this.config.auth,\n publicMode: this.config.publicMode,\n debug: this.config.debug,\n interceptors: this._interceptors,\n });\n case 'sse':\n // TODO: Implement SSE transport\n throw new Error('SSE transport not yet implemented');\n default:\n throw new Error(`Unknown transport type: ${this.config.transport}`);\n }\n }\n\n private async request<T>(method: string, params: Record<string, unknown>): Promise<McpResponse<T>> {\n this.ensureConnected();\n\n const id = ++this.requestIdCounter;\n this._lastRequestId = id;\n const start = Date.now();\n\n try {\n const response = await this.transport!.request<T>({\n jsonrpc: '2.0',\n id,\n method,\n params,\n });\n\n const durationMs = Date.now() - start;\n this.updateSessionActivity();\n\n if ('error' in response && response.error) {\n const error = response.error as McpErrorInfo;\n this.traceRequest(method, params, id, response, durationMs);\n return {\n success: false,\n error,\n durationMs,\n requestId: id,\n };\n }\n\n this.traceRequest(method, params, id, response, durationMs);\n return {\n success: true,\n data: response.result as T,\n durationMs,\n requestId: id,\n };\n } catch (err) {\n const durationMs = Date.now() - start;\n const error: McpErrorInfo = {\n code: -32603,\n message: err instanceof Error ? err.message : 'Unknown error',\n };\n return {\n success: false,\n error,\n durationMs,\n requestId: id,\n };\n }\n }\n\n private ensureConnected(): void {\n if (!this.transport?.isConnected()) {\n throw new Error('Not connected to MCP server. Call connect() first.');\n }\n }\n\n private updateSessionActivity(): void {\n if (this._sessionInfo) {\n this._sessionInfo.lastActivityAt = new Date();\n this._sessionInfo.requestCount++;\n }\n }\n\n // ═══════════════════════════════════════════════════════════════════\n // PRIVATE: RESULT WRAPPERS\n // ═══════════════════════════════════════════════════════════════════\n\n private wrapToolResult(response: McpResponse<CallToolResult>): ToolResultWrapper {\n const raw = response.data ?? { content: [] };\n const isError = !response.success || raw.isError === true;\n\n // Check for Tool UI response - has structuredContent and ui/html in _meta\n const meta = raw._meta as Record<string, unknown> | undefined;\n const hasUI = meta?.['ui/html'] !== undefined;\n const structuredContent = (raw as Record<string, unknown>)['structuredContent'];\n\n return {\n raw,\n isSuccess: !isError,\n isError,\n error: response.error,\n durationMs: response.durationMs,\n json<T>(): T {\n // For Tool UI responses, return structuredContent (the typed output)\n if (hasUI && structuredContent !== undefined) {\n return structuredContent as T;\n }\n // For regular responses, parse text content as JSON\n const textContent = raw.content?.find((c) => c.type === 'text');\n if (textContent && 'text' in textContent) {\n return JSON.parse(textContent.text) as T;\n }\n throw new Error('No text content to parse as JSON');\n },\n text(): string | undefined {\n const textContent = raw.content?.find((c) => c.type === 'text');\n if (textContent && 'text' in textContent) {\n return textContent.text;\n }\n return undefined;\n },\n hasTextContent(): boolean {\n return raw.content?.some((c) => c.type === 'text') ?? false;\n },\n hasImageContent(): boolean {\n return raw.content?.some((c) => c.type === 'image') ?? false;\n },\n hasResourceContent(): boolean {\n return raw.content?.some((c) => c.type === 'resource') ?? false;\n },\n hasToolUI(): boolean {\n return hasUI;\n },\n };\n }\n\n private wrapResourceContent(response: McpResponse<ReadResourceResult>): ResourceContentWrapper {\n const raw = response.data ?? { contents: [] };\n const isError = !response.success;\n const firstContent = raw.contents?.[0];\n\n return {\n raw,\n isSuccess: !isError,\n isError,\n error: response.error,\n durationMs: response.durationMs,\n json<T>(): T {\n if (firstContent && 'text' in firstContent) {\n return JSON.parse(firstContent.text) as T;\n }\n throw new Error('No text content to parse as JSON');\n },\n text(): string | undefined {\n if (firstContent && 'text' in firstContent) {\n return firstContent.text;\n }\n return undefined;\n },\n mimeType(): string | undefined {\n return firstContent?.mimeType;\n },\n hasMimeType(type: string): boolean {\n return firstContent?.mimeType === type;\n },\n };\n }\n\n private wrapPromptResult(response: McpResponse<GetPromptResult>): PromptResultWrapper {\n const raw = response.data ?? { messages: [] };\n const isError = !response.success;\n\n return {\n raw,\n isSuccess: !isError,\n isError,\n error: response.error,\n durationMs: response.durationMs,\n messages: raw.messages ?? [],\n description: raw.description,\n };\n }\n\n // ═══════════════════════════════════════════════════════════════════\n // PRIVATE: LOGGING & TRACING\n // ═══════════════════════════════════════════════════════════════════\n\n private log(level: 'debug' | 'info' | 'warn' | 'error', message: string, data?: unknown): void {\n const entry: LogEntry = {\n level,\n message,\n timestamp: new Date(),\n data,\n };\n this._logs.push(entry);\n\n if (this.config.debug) {\n console.log(`[${level.toUpperCase()}] ${message}`, data ?? '');\n }\n }\n\n private traceRequest(\n method: string,\n params: unknown,\n id: string | number,\n response: JSONRPCResponse,\n durationMs: number,\n ): void {\n this._traces.push({\n request: { method, params, id },\n response: {\n result: 'result' in response ? response.result : undefined,\n error: 'error' in response ? (response.error as McpErrorInfo) : undefined,\n },\n durationMs,\n timestamp: new Date(),\n });\n }\n\n // ═══════════════════════════════════════════════════════════════════\n // PRIVATE: TOKEN PARSING\n // ═══════════════════════════════════════════════════════════════════\n\n private parseScopesFromToken(token: string): string[] {\n try {\n const payload = this.decodeJwtPayload(token);\n if (!payload) return [];\n const scope = payload['scope'];\n const scopes = payload['scopes'];\n if (typeof scope === 'string') {\n return scope.split(' ');\n }\n if (Array.isArray(scopes)) {\n return scopes as string[];\n }\n return [];\n } catch {\n return [];\n }\n }\n\n private parseUserFromToken(token: string): { sub: string; email?: string; name?: string } | undefined {\n try {\n const payload = this.decodeJwtPayload(token);\n const sub = payload?.['sub'];\n if (!sub || typeof sub !== 'string') return undefined;\n return {\n sub,\n email: payload['email'] as string | undefined,\n name: payload['name'] as string | undefined,\n };\n } catch {\n return undefined;\n }\n }\n\n private decodeJwtPayload(token: string): Record<string, unknown> | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n const payload = Buffer.from(parts[1], 'base64url').toString('utf-8');\n return JSON.parse(payload);\n } catch {\n return null;\n }\n }\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// NOTIFICATION COLLECTORS\n// ═══════════════════════════════════════════════════════════════════\n\nclass NotificationCollector {\n constructor(private readonly notifications: NotificationEntry[]) {}\n\n get received(): NotificationEntry[] {\n return [...this.notifications];\n }\n\n has(method: string): boolean {\n return this.notifications.some((n) => n.method === method);\n }\n\n async waitFor(method: string, timeoutMs: number): Promise<NotificationEntry> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n const found = this.notifications.find((n) => n.method === method);\n if (found) return found;\n await new Promise((r) => setTimeout(r, 50));\n }\n throw new Error(`Timeout waiting for notification: ${method}`);\n }\n}\n\nclass ProgressCollector {\n constructor(private readonly updates: ProgressUpdate[]) {}\n\n get all(): ProgressUpdate[] {\n return [...this.updates];\n }\n\n async waitForComplete(timeoutMs: number): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n const last = this.updates[this.updates.length - 1];\n if (last && last.total !== undefined && last.progress >= last.total) {\n return;\n }\n await new Promise((r) => setTimeout(r, 50));\n }\n throw new Error('Timeout waiting for progress to complete');\n }\n}\n"]}
@@ -0,0 +1,216 @@
1
+ /**
2
+ * @file mcp-test-client.types.ts
3
+ * @description Type definitions for the MCP Test Client
4
+ */
5
+ import type { InitializeResult, ListToolsResult, CallToolResult, ListResourcesResult, ReadResourceResult, ListResourceTemplatesResult, ListPromptsResult, GetPromptResult, Tool, Resource, ResourceTemplate, Prompt } from '@modelcontextprotocol/sdk/types.js';
6
+ /**
7
+ * Simplified JSON-RPC request type for testing
8
+ */
9
+ export interface JSONRPCRequest {
10
+ jsonrpc: '2.0';
11
+ id?: string | number;
12
+ method: string;
13
+ params?: Record<string, unknown>;
14
+ }
15
+ /**
16
+ * Simplified JSON-RPC response type for testing
17
+ */
18
+ export interface JSONRPCResponse {
19
+ jsonrpc: '2.0';
20
+ id: string | number | null;
21
+ result?: unknown;
22
+ error?: {
23
+ code: number;
24
+ message: string;
25
+ data?: unknown;
26
+ };
27
+ }
28
+ export type TestTransportType = 'sse' | 'streamable-http';
29
+ export type TransportState = 'disconnected' | 'connecting' | 'connected' | 'error';
30
+ export interface TestAuthConfig {
31
+ /** Bearer token for authentication */
32
+ token?: string;
33
+ /** Additional headers to include in requests */
34
+ headers?: Record<string, string>;
35
+ }
36
+ export interface McpTestClientConfig {
37
+ /** Base URL of the MCP server */
38
+ baseUrl: string;
39
+ /** Transport type to use (default: 'streamable-http') */
40
+ transport?: TestTransportType;
41
+ /** Authentication configuration */
42
+ auth?: TestAuthConfig;
43
+ /**
44
+ * Enable public mode - skip authentication entirely.
45
+ * When true, no Authorization header is sent and anonymous token is not requested.
46
+ * Use this for testing public/unauthenticated endpoints in CI/CD pipelines.
47
+ */
48
+ publicMode?: boolean;
49
+ /** Request timeout in milliseconds (default: 30000) */
50
+ timeout?: number;
51
+ /** Enable debug logging (default: false) */
52
+ debug?: boolean;
53
+ /** MCP protocol version to request (default: '2024-11-05') */
54
+ protocolVersion?: string;
55
+ /** Client info to send during initialization */
56
+ clientInfo?: {
57
+ name: string;
58
+ version: string;
59
+ };
60
+ }
61
+ export interface McpResponse<T> {
62
+ /** Whether the request succeeded */
63
+ success: boolean;
64
+ /** Response data (if successful) */
65
+ data?: T;
66
+ /** Error information (if failed) */
67
+ error?: McpErrorInfo;
68
+ /** Request duration in milliseconds */
69
+ durationMs: number;
70
+ /** Request ID used for this request */
71
+ requestId: string | number;
72
+ }
73
+ export interface McpErrorInfo {
74
+ /** JSON-RPC error code */
75
+ code: number;
76
+ /** Error message */
77
+ message: string;
78
+ /** Additional error data */
79
+ data?: unknown;
80
+ }
81
+ export interface ToolResultWrapper {
82
+ /** Raw CallToolResult from MCP */
83
+ raw: CallToolResult;
84
+ /** Whether the tool call was successful (no isError flag) */
85
+ isSuccess: boolean;
86
+ /** Whether the tool call failed */
87
+ isError: boolean;
88
+ /** Error information if failed */
89
+ error?: McpErrorInfo;
90
+ /** Duration of the tool call in ms */
91
+ durationMs: number;
92
+ /**
93
+ * Parse tool output as JSON
94
+ *
95
+ * For Tool UI responses: returns structuredContent (the typed output)
96
+ * For regular responses: parses text content as JSON
97
+ */
98
+ json<T = unknown>(): T;
99
+ /** Get first text content */
100
+ text(): string | undefined;
101
+ /** Check if response has text content */
102
+ hasTextContent(): boolean;
103
+ /** Check if response has image content */
104
+ hasImageContent(): boolean;
105
+ /** Check if response has resource content */
106
+ hasResourceContent(): boolean;
107
+ /** Check if response has Tool UI metadata (ui/html in _meta) */
108
+ hasToolUI(): boolean;
109
+ }
110
+ export interface ResourceContentWrapper {
111
+ /** Raw ReadResourceResult from MCP */
112
+ raw: ReadResourceResult;
113
+ /** Whether the read was successful */
114
+ isSuccess: boolean;
115
+ /** Whether the read failed */
116
+ isError: boolean;
117
+ /** Error information if failed */
118
+ error?: McpErrorInfo;
119
+ /** Duration in ms */
120
+ durationMs: number;
121
+ /** Parse text content as JSON */
122
+ json<T = unknown>(): T;
123
+ /** Get text content */
124
+ text(): string | undefined;
125
+ /** Get MIME type */
126
+ mimeType(): string | undefined;
127
+ /** Check if has specific MIME type */
128
+ hasMimeType(type: string): boolean;
129
+ }
130
+ export interface PromptResultWrapper {
131
+ /** Raw GetPromptResult from MCP */
132
+ raw: GetPromptResult;
133
+ /** Whether the get was successful */
134
+ isSuccess: boolean;
135
+ /** Whether the get failed */
136
+ isError: boolean;
137
+ /** Error information if failed */
138
+ error?: McpErrorInfo;
139
+ /** Duration in ms */
140
+ durationMs: number;
141
+ /** Messages in the prompt */
142
+ messages: GetPromptResult['messages'];
143
+ /** Description from prompt result */
144
+ description?: string;
145
+ }
146
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
147
+ export interface LogEntry {
148
+ /** Log level */
149
+ level: LogLevel;
150
+ /** Log message */
151
+ message: string;
152
+ /** Timestamp */
153
+ timestamp: Date;
154
+ /** Additional data */
155
+ data?: unknown;
156
+ }
157
+ export interface RequestTrace {
158
+ /** Request that was sent */
159
+ request: {
160
+ method: string;
161
+ params?: unknown;
162
+ id: string | number;
163
+ };
164
+ /** Response that was received */
165
+ response: {
166
+ result?: unknown;
167
+ error?: McpErrorInfo;
168
+ };
169
+ /** Duration in milliseconds */
170
+ durationMs: number;
171
+ /** Timestamp of the request */
172
+ timestamp: Date;
173
+ }
174
+ export interface NotificationEntry {
175
+ /** Notification method */
176
+ method: string;
177
+ /** Notification params */
178
+ params?: unknown;
179
+ /** Timestamp received */
180
+ timestamp: Date;
181
+ }
182
+ export interface ProgressUpdate {
183
+ /** Progress value (0-100 or custom) */
184
+ progress: number;
185
+ /** Total value */
186
+ total?: number;
187
+ /** Progress token */
188
+ progressToken?: string | number;
189
+ /** Timestamp */
190
+ timestamp: Date;
191
+ }
192
+ export interface SessionInfo {
193
+ /** Session ID */
194
+ id: string;
195
+ /** When the session was created */
196
+ createdAt: Date;
197
+ /** When the last request was made */
198
+ lastActivityAt: Date;
199
+ /** Number of requests made in this session */
200
+ requestCount: number;
201
+ }
202
+ export interface AuthState {
203
+ /** Whether the user is anonymous (no token) */
204
+ isAnonymous: boolean;
205
+ /** Current token (if any) */
206
+ token?: string;
207
+ /** Scopes from the token */
208
+ scopes: string[];
209
+ /** User information from token */
210
+ user?: {
211
+ sub: string;
212
+ email?: string;
213
+ name?: string;
214
+ };
215
+ }
216
+ export type { InitializeResult, ListToolsResult, CallToolResult, ListResourcesResult, ReadResourceResult, ListResourceTemplatesResult, ListPromptsResult, GetPromptResult, Tool, Resource, ResourceTemplate, Prompt, };
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * @file mcp-test-client.types.ts
4
+ * @description Type definitions for the MCP Test Client
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ //# sourceMappingURL=mcp-test-client.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-test-client.types.js","sourceRoot":"","sources":["../../../src/client/mcp-test-client.types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * @file mcp-test-client.types.ts\n * @description Type definitions for the MCP Test Client\n */\n\nimport type {\n InitializeResult,\n ListToolsResult,\n CallToolResult,\n ListResourcesResult,\n ReadResourceResult,\n ListResourceTemplatesResult,\n ListPromptsResult,\n GetPromptResult,\n Tool,\n Resource,\n ResourceTemplate,\n Prompt,\n} from '@modelcontextprotocol/sdk/types.js';\n\n// ═══════════════════════════════════════════════════════════════════\n// JSON-RPC TYPES (simplified for testing)\n// ═══════════════════════════════════════════════════════════════════\n\n/**\n * Simplified JSON-RPC request type for testing\n */\nexport interface JSONRPCRequest {\n jsonrpc: '2.0';\n id?: string | number;\n method: string;\n params?: Record<string, unknown>;\n}\n\n/**\n * Simplified JSON-RPC response type for testing\n */\nexport interface JSONRPCResponse {\n jsonrpc: '2.0';\n id: string | number | null;\n result?: unknown;\n error?: {\n code: number;\n message: string;\n data?: unknown;\n };\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// TRANSPORT TYPES\n// ═══════════════════════════════════════════════════════════════════\n\nexport type TestTransportType = 'sse' | 'streamable-http';\n\nexport type TransportState = 'disconnected' | 'connecting' | 'connected' | 'error';\n\n// ═══════════════════════════════════════════════════════════════════\n// AUTH TYPES\n// ═══════════════════════════════════════════════════════════════════\n\nexport interface TestAuthConfig {\n /** Bearer token for authentication */\n token?: string;\n /** Additional headers to include in requests */\n headers?: Record<string, string>;\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// CLIENT CONFIG\n// ═══════════════════════════════════════════════════════════════════\n\nexport interface McpTestClientConfig {\n /** Base URL of the MCP server */\n baseUrl: string;\n /** Transport type to use (default: 'streamable-http') */\n transport?: TestTransportType;\n /** Authentication configuration */\n auth?: TestAuthConfig;\n /**\n * Enable public mode - skip authentication entirely.\n * When true, no Authorization header is sent and anonymous token is not requested.\n * Use this for testing public/unauthenticated endpoints in CI/CD pipelines.\n */\n publicMode?: boolean;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n /** Enable debug logging (default: false) */\n debug?: boolean;\n /** MCP protocol version to request (default: '2024-11-05') */\n protocolVersion?: string;\n /** Client info to send during initialization */\n clientInfo?: {\n name: string;\n version: string;\n };\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// RESPONSE TYPES\n// ═══════════════════════════════════════════════════════════════════\n\nexport interface McpResponse<T> {\n /** Whether the request succeeded */\n success: boolean;\n /** Response data (if successful) */\n data?: T;\n /** Error information (if failed) */\n error?: McpErrorInfo;\n /** Request duration in milliseconds */\n durationMs: number;\n /** Request ID used for this request */\n requestId: string | number;\n}\n\nexport interface McpErrorInfo {\n /** JSON-RPC error code */\n code: number;\n /** Error message */\n message: string;\n /** Additional error data */\n data?: unknown;\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// TOOL RESULT WRAPPER\n// ═══════════════════════════════════════════════════════════════════\n\nexport interface ToolResultWrapper {\n /** Raw CallToolResult from MCP */\n raw: CallToolResult;\n /** Whether the tool call was successful (no isError flag) */\n isSuccess: boolean;\n /** Whether the tool call failed */\n isError: boolean;\n /** Error information if failed */\n error?: McpErrorInfo;\n /** Duration of the tool call in ms */\n durationMs: number;\n /**\n * Parse tool output as JSON\n *\n * For Tool UI responses: returns structuredContent (the typed output)\n * For regular responses: parses text content as JSON\n */\n json<T = unknown>(): T;\n /** Get first text content */\n text(): string | undefined;\n /** Check if response has text content */\n hasTextContent(): boolean;\n /** Check if response has image content */\n hasImageContent(): boolean;\n /** Check if response has resource content */\n hasResourceContent(): boolean;\n /** Check if response has Tool UI metadata (ui/html in _meta) */\n hasToolUI(): boolean;\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// RESOURCE CONTENT WRAPPER\n// ═══════════════════════════════════════════════════════════════════\n\nexport interface ResourceContentWrapper {\n /** Raw ReadResourceResult from MCP */\n raw: ReadResourceResult;\n /** Whether the read was successful */\n isSuccess: boolean;\n /** Whether the read failed */\n isError: boolean;\n /** Error information if failed */\n error?: McpErrorInfo;\n /** Duration in ms */\n durationMs: number;\n /** Parse text content as JSON */\n json<T = unknown>(): T;\n /** Get text content */\n text(): string | undefined;\n /** Get MIME type */\n mimeType(): string | undefined;\n /** Check if has specific MIME type */\n hasMimeType(type: string): boolean;\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// PROMPT RESULT WRAPPER\n// ═══════════════════════════════════════════════════════════════════\n\nexport interface PromptResultWrapper {\n /** Raw GetPromptResult from MCP */\n raw: GetPromptResult;\n /** Whether the get was successful */\n isSuccess: boolean;\n /** Whether the get failed */\n isError: boolean;\n /** Error information if failed */\n error?: McpErrorInfo;\n /** Duration in ms */\n durationMs: number;\n /** Messages in the prompt */\n messages: GetPromptResult['messages'];\n /** Description from prompt result */\n description?: string;\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// LOGGING TYPES\n// ═══════════════════════════════════════════════════════════════════\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nexport interface LogEntry {\n /** Log level */\n level: LogLevel;\n /** Log message */\n message: string;\n /** Timestamp */\n timestamp: Date;\n /** Additional data */\n data?: unknown;\n}\n\nexport interface RequestTrace {\n /** Request that was sent */\n request: {\n method: string;\n params?: unknown;\n id: string | number;\n };\n /** Response that was received */\n response: {\n result?: unknown;\n error?: McpErrorInfo;\n };\n /** Duration in milliseconds */\n durationMs: number;\n /** Timestamp of the request */\n timestamp: Date;\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// NOTIFICATION TYPES\n// ═══════════════════════════════════════════════════════════════════\n\nexport interface NotificationEntry {\n /** Notification method */\n method: string;\n /** Notification params */\n params?: unknown;\n /** Timestamp received */\n timestamp: Date;\n}\n\nexport interface ProgressUpdate {\n /** Progress value (0-100 or custom) */\n progress: number;\n /** Total value */\n total?: number;\n /** Progress token */\n progressToken?: string | number;\n /** Timestamp */\n timestamp: Date;\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// SESSION TYPES\n// ═══════════════════════════════════════════════════════════════════\n\nexport interface SessionInfo {\n /** Session ID */\n id: string;\n /** When the session was created */\n createdAt: Date;\n /** When the last request was made */\n lastActivityAt: Date;\n /** Number of requests made in this session */\n requestCount: number;\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// AUTH STATE\n// ═══════════════════════════════════════════════════════════════════\n\nexport interface AuthState {\n /** Whether the user is anonymous (no token) */\n isAnonymous: boolean;\n /** Current token (if any) */\n token?: string;\n /** Scopes from the token */\n scopes: string[];\n /** User information from token */\n user?: {\n sub: string;\n email?: string;\n name?: string;\n };\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// RE-EXPORTS FROM MCP SDK\n// ═══════════════════════════════════════════════════════════════════\n\nexport type {\n InitializeResult,\n ListToolsResult,\n CallToolResult,\n ListResourcesResult,\n ReadResourceResult,\n ListResourceTemplatesResult,\n ListPromptsResult,\n GetPromptResult,\n Tool,\n Resource,\n ResourceTemplate,\n Prompt,\n};\n"]}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @file errors/index.ts
3
+ * @description Error classes for @frontmcp/testing
4
+ */
5
+ /**
6
+ * Base error class for test client errors
7
+ */
8
+ export declare class TestClientError extends Error {
9
+ constructor(message: string);
10
+ }
11
+ /**
12
+ * Error thrown when connection fails
13
+ */
14
+ export declare class ConnectionError extends TestClientError {
15
+ readonly cause?: Error | undefined;
16
+ constructor(message: string, cause?: Error | undefined);
17
+ }
18
+ /**
19
+ * Error thrown when request times out
20
+ */
21
+ export declare class TimeoutError extends TestClientError {
22
+ readonly timeoutMs: number;
23
+ constructor(message: string, timeoutMs: number);
24
+ }
25
+ /**
26
+ * Error thrown when MCP returns an error response
27
+ */
28
+ export declare class McpProtocolError extends TestClientError {
29
+ readonly code: number;
30
+ readonly data?: unknown | undefined;
31
+ constructor(message: string, code: number, data?: unknown | undefined);
32
+ }
33
+ /**
34
+ * Error thrown when server fails to start
35
+ */
36
+ export declare class ServerStartError extends TestClientError {
37
+ readonly cause?: Error | undefined;
38
+ constructor(message: string, cause?: Error | undefined);
39
+ }
40
+ /**
41
+ * Error thrown when assertion fails
42
+ */
43
+ export declare class AssertionError extends TestClientError {
44
+ constructor(message: string);
45
+ }
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ /**
3
+ * @file errors/index.ts
4
+ * @description Error classes for @frontmcp/testing
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.AssertionError = exports.ServerStartError = exports.McpProtocolError = exports.TimeoutError = exports.ConnectionError = exports.TestClientError = void 0;
8
+ /**
9
+ * Base error class for test client errors
10
+ */
11
+ class TestClientError extends Error {
12
+ constructor(message) {
13
+ super(message);
14
+ this.name = 'TestClientError';
15
+ // Fix prototype chain for proper instanceof checks in transpiled code
16
+ Object.setPrototypeOf(this, new.target.prototype);
17
+ }
18
+ }
19
+ exports.TestClientError = TestClientError;
20
+ /**
21
+ * Error thrown when connection fails
22
+ */
23
+ class ConnectionError extends TestClientError {
24
+ cause;
25
+ constructor(message, cause) {
26
+ super(message);
27
+ this.cause = cause;
28
+ this.name = 'ConnectionError';
29
+ Object.setPrototypeOf(this, new.target.prototype);
30
+ }
31
+ }
32
+ exports.ConnectionError = ConnectionError;
33
+ /**
34
+ * Error thrown when request times out
35
+ */
36
+ class TimeoutError extends TestClientError {
37
+ timeoutMs;
38
+ constructor(message, timeoutMs) {
39
+ super(message);
40
+ this.timeoutMs = timeoutMs;
41
+ this.name = 'TimeoutError';
42
+ Object.setPrototypeOf(this, new.target.prototype);
43
+ }
44
+ }
45
+ exports.TimeoutError = TimeoutError;
46
+ /**
47
+ * Error thrown when MCP returns an error response
48
+ */
49
+ class McpProtocolError extends TestClientError {
50
+ code;
51
+ data;
52
+ constructor(message, code, data) {
53
+ super(message);
54
+ this.code = code;
55
+ this.data = data;
56
+ this.name = 'McpProtocolError';
57
+ Object.setPrototypeOf(this, new.target.prototype);
58
+ }
59
+ }
60
+ exports.McpProtocolError = McpProtocolError;
61
+ /**
62
+ * Error thrown when server fails to start
63
+ */
64
+ class ServerStartError extends TestClientError {
65
+ cause;
66
+ constructor(message, cause) {
67
+ super(message);
68
+ this.cause = cause;
69
+ this.name = 'ServerStartError';
70
+ Object.setPrototypeOf(this, new.target.prototype);
71
+ }
72
+ }
73
+ exports.ServerStartError = ServerStartError;
74
+ /**
75
+ * Error thrown when assertion fails
76
+ */
77
+ class AssertionError extends TestClientError {
78
+ constructor(message) {
79
+ super(message);
80
+ this.name = 'AssertionError';
81
+ Object.setPrototypeOf(this, new.target.prototype);
82
+ }
83
+ }
84
+ exports.AssertionError = AssertionError;
85
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/errors/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH;;GAEG;AACH,MAAa,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,sEAAsE;QACtE,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAPD,0CAOC;AAED;;GAEG;AACH,MAAa,eAAgB,SAAQ,eAAe;IACI;IAAtD,YAAY,OAAe,EAA2B,KAAa;QACjE,KAAK,CAAC,OAAO,CAAC,CAAC;QADqC,UAAK,GAAL,KAAK,CAAQ;QAEjE,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAND,0CAMC;AAED;;GAEG;AACH,MAAa,YAAa,SAAQ,eAAe;IACF;IAA7C,YAAY,OAAe,EAAkB,SAAiB;QAC5D,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,cAAS,GAAT,SAAS,CAAQ;QAE5D,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAND,oCAMC;AAED;;GAEG;AACH,MAAa,gBAAiB,SAAQ,eAAe;IACN;IAA8B;IAA3E,YAAY,OAAe,EAAkB,IAAY,EAAkB,IAAc;QACvF,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,SAAI,GAAJ,IAAI,CAAQ;QAAkB,SAAI,GAAJ,IAAI,CAAU;QAEvF,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAND,4CAMC;AAED;;GAEG;AACH,MAAa,gBAAiB,SAAQ,eAAe;IACG;IAAtD,YAAY,OAAe,EAA2B,KAAa;QACjE,KAAK,CAAC,OAAO,CAAC,CAAC;QADqC,UAAK,GAAL,KAAK,CAAQ;QAEjE,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAND,4CAMC;AAED;;GAEG;AACH,MAAa,cAAe,SAAQ,eAAe;IACjD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAND,wCAMC","sourcesContent":["/**\n * @file errors/index.ts\n * @description Error classes for @frontmcp/testing\n */\n\n/**\n * Base error class for test client errors\n */\nexport class TestClientError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'TestClientError';\n // Fix prototype chain for proper instanceof checks in transpiled code\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when connection fails\n */\nexport class ConnectionError extends TestClientError {\n constructor(message: string, public override readonly cause?: Error) {\n super(message);\n this.name = 'ConnectionError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when request times out\n */\nexport class TimeoutError extends TestClientError {\n constructor(message: string, public readonly timeoutMs: number) {\n super(message);\n this.name = 'TimeoutError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when MCP returns an error response\n */\nexport class McpProtocolError extends TestClientError {\n constructor(message: string, public readonly code: number, public readonly data?: unknown) {\n super(message);\n this.name = 'McpProtocolError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when server fails to start\n */\nexport class ServerStartError extends TestClientError {\n constructor(message: string, public override readonly cause?: Error) {\n super(message);\n this.name = 'ServerStartError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when assertion fails\n */\nexport class AssertionError extends TestClientError {\n constructor(message: string) {\n super(message);\n this.name = 'AssertionError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n"]}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @file expect.ts
3
+ * @description Pre-typed expect export with MCP custom matchers
4
+ *
5
+ * This is the Playwright-style approach - instead of relying on global type
6
+ * augmentation (which can be fragile across monorepos and path mappings),
7
+ * we export a properly typed expect function that includes all MCP matchers.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { test, expect } from '@frontmcp/testing';
12
+ *
13
+ * test('tools are available', async ({ mcp }) => {
14
+ * const tools = await mcp.tools.list();
15
+ * expect(tools).toContainTool('my-tool'); // Properly typed!
16
+ * });
17
+ * ```
18
+ */
19
+ import { expect as jestExpect } from '@jest/globals';
20
+ import type { McpMatchers } from './matchers/matcher-types';
21
+ /**
22
+ * Extended Jest matchers interface that includes MCP matchers
23
+ */
24
+ type McpExpectMatchers<R = void> = jest.Matchers<R> & McpMatchers<R> & {
25
+ /**
26
+ * Inverts the matchers that follow
27
+ */
28
+ not: jest.Matchers<R> & McpMatchers<R>;
29
+ /**
30
+ * Used to access matchers that are resolved asynchronously
31
+ */
32
+ resolves: jest.Matchers<Promise<R>> & McpMatchers<Promise<R>>;
33
+ /**
34
+ * Used to access matchers that are rejected asynchronously
35
+ */
36
+ rejects: jest.Matchers<Promise<R>> & McpMatchers<Promise<R>>;
37
+ };
38
+ /**
39
+ * Extended expect interface with MCP matchers
40
+ */
41
+ interface McpExpect {
42
+ <T = unknown>(actual: T): McpExpectMatchers<T>;
43
+ anything(): ReturnType<typeof jestExpect.anything>;
44
+ any(classType: unknown): ReturnType<typeof jestExpect.any>;
45
+ arrayContaining<E = unknown>(arr: readonly E[]): ReturnType<typeof jestExpect.arrayContaining>;
46
+ objectContaining<E = Record<string, unknown>>(obj: E): ReturnType<typeof jestExpect.objectContaining>;
47
+ stringContaining(str: string): ReturnType<typeof jestExpect.stringContaining>;
48
+ stringMatching(str: string | RegExp): ReturnType<typeof jestExpect.stringMatching>;
49
+ not: {
50
+ arrayContaining<E = unknown>(arr: readonly E[]): ReturnType<typeof jestExpect.not.arrayContaining>;
51
+ objectContaining<E = Record<string, unknown>>(obj: E): ReturnType<typeof jestExpect.not.objectContaining>;
52
+ stringContaining(str: string): ReturnType<typeof jestExpect.not.stringContaining>;
53
+ stringMatching(str: string | RegExp): ReturnType<typeof jestExpect.not.stringMatching>;
54
+ };
55
+ extend(matchers: Record<string, unknown>): void;
56
+ assertions(num: number): void;
57
+ hasAssertions(): void;
58
+ }
59
+ /**
60
+ * Pre-typed expect with MCP custom matchers included
61
+ *
62
+ * This approach (similar to Playwright's) provides type safety without
63
+ * relying on global TypeScript namespace augmentation, which can be
64
+ * problematic in monorepo setups with path mappings.
65
+ */
66
+ export declare const expect: McpExpect;
67
+ export {};
package/src/expect.js ADDED
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ /**
3
+ * @file expect.ts
4
+ * @description Pre-typed expect export with MCP custom matchers
5
+ *
6
+ * This is the Playwright-style approach - instead of relying on global type
7
+ * augmentation (which can be fragile across monorepos and path mappings),
8
+ * we export a properly typed expect function that includes all MCP matchers.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { test, expect } from '@frontmcp/testing';
13
+ *
14
+ * test('tools are available', async ({ mcp }) => {
15
+ * const tools = await mcp.tools.list();
16
+ * expect(tools).toContainTool('my-tool'); // Properly typed!
17
+ * });
18
+ * ```
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.expect = void 0;
22
+ const globals_1 = require("@jest/globals");
23
+ /**
24
+ * Pre-typed expect with MCP custom matchers included
25
+ *
26
+ * This approach (similar to Playwright's) provides type safety without
27
+ * relying on global TypeScript namespace augmentation, which can be
28
+ * problematic in monorepo setups with path mappings.
29
+ */
30
+ exports.expect = globals_1.expect;
31
+ //# sourceMappingURL=expect.js.map