@qodalis/mcp-cli 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/LICENSE +21 -0
  3. package/README.md +384 -2
  4. package/dist/src/cli.d.ts +3 -0
  5. package/dist/src/cli.d.ts.map +1 -0
  6. package/dist/src/cli.js +102 -0
  7. package/dist/src/cli.js.map +1 -0
  8. package/dist/src/config.d.ts +60 -0
  9. package/dist/src/config.d.ts.map +1 -0
  10. package/dist/src/config.js +149 -0
  11. package/dist/src/config.js.map +1 -0
  12. package/dist/src/dev/api.d.ts +94 -0
  13. package/dist/src/dev/api.d.ts.map +1 -0
  14. package/dist/src/dev/api.js +425 -0
  15. package/dist/src/dev/api.js.map +1 -0
  16. package/dist/src/dev/docs.d.ts +93 -0
  17. package/dist/src/dev/docs.d.ts.map +1 -0
  18. package/dist/src/dev/docs.js +275 -0
  19. package/dist/src/dev/docs.js.map +1 -0
  20. package/dist/src/dev/prompts.d.ts +11 -0
  21. package/dist/src/dev/prompts.d.ts.map +1 -0
  22. package/dist/src/dev/prompts.js +141 -0
  23. package/dist/src/dev/prompts.js.map +1 -0
  24. package/dist/src/dev/scaffold.d.ts +55 -0
  25. package/dist/src/dev/scaffold.d.ts.map +1 -0
  26. package/dist/src/dev/scaffold.js +213 -0
  27. package/dist/src/dev/scaffold.js.map +1 -0
  28. package/dist/src/dev/tools.d.ts +170 -0
  29. package/dist/src/dev/tools.d.ts.map +1 -0
  30. package/dist/src/dev/tools.js +258 -0
  31. package/dist/src/dev/tools.js.map +1 -0
  32. package/dist/src/env-file.d.ts +9 -0
  33. package/dist/src/env-file.d.ts.map +1 -0
  34. package/dist/src/env-file.js +54 -0
  35. package/dist/src/env-file.js.map +1 -0
  36. package/dist/src/errors.d.ts +22 -0
  37. package/dist/src/errors.d.ts.map +1 -0
  38. package/dist/src/errors.js +115 -0
  39. package/dist/src/errors.js.map +1 -0
  40. package/dist/src/filters.d.ts +13 -0
  41. package/dist/src/filters.d.ts.map +1 -0
  42. package/dist/src/filters.js +16 -0
  43. package/dist/src/filters.js.map +1 -0
  44. package/dist/src/index.d.ts +12 -0
  45. package/dist/src/index.d.ts.map +1 -0
  46. package/dist/src/index.js +12 -0
  47. package/dist/src/index.js.map +1 -0
  48. package/dist/src/remote.d.ts +64 -0
  49. package/dist/src/remote.d.ts.map +1 -0
  50. package/dist/src/remote.js +242 -0
  51. package/dist/src/remote.js.map +1 -0
  52. package/dist/src/server.d.ts +22 -0
  53. package/dist/src/server.d.ts.map +1 -0
  54. package/dist/src/server.js +156 -0
  55. package/dist/src/server.js.map +1 -0
  56. package/docs/llms-full.txt +1740 -0
  57. package/package.json +70 -5
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/dev/tools.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EACH,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,oBAAoB,GAEvB,MAAM,UAAU,CAAC;AAClB,OAAO,EACH,UAAU,EACV,UAAU,EACV,QAAQ,EACR,UAAU,GAGb,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,SAAS,EAAE,OAAO,EAAsB,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAe,MAAM,eAAe,CAAC;AAE1E,MAAM,CAAC,MAAM,oBAAoB,GAAG,cAAc,CAAC;AAEnD,+EAA+E;AAC/E,MAAM,CAAC,MAAM,SAAS,GAAW;IAC7B;QACI,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,wBAAwB,EAAE;QACzF,WAAW,EACP,wNAAwN;QAC5N,WAAW,EAAE;YACT,UAAU,EAAE;gBACR,KAAK,EAAE;oBACH,WAAW,EAAE,kDAAkD;oBAC/D,OAAO,EAAE,EAAE;oBACX,OAAO,EAAE,CAAC;oBACV,IAAI,EAAE,SAAS;iBAClB;gBACD,KAAK,EAAE;oBACH,WAAW,EACP,6EAA6E;oBACjF,IAAI,EAAE,QAAQ;iBACjB;aACJ;YACD,QAAQ,EAAE,CAAC,OAAO,CAAC;YACnB,IAAI,EAAE,QAAQ;SACjB;QACD,IAAI,EAAE,kBAAkB;KAC3B;IACD;QACI,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,0BAA0B,EAAE;QAC3F,WAAW,EACP,sSAAsS;QAC1S,WAAW,EAAE;YACT,UAAU,EAAE;gBACR,KAAK,EAAE;oBACH,WAAW,EAAE,qDAAqD;oBAClE,IAAI,EAAE,QAAQ;iBACjB;aACJ;YACD,QAAQ,EAAE,CAAC,OAAO,CAAC;YACnB,IAAI,EAAE,QAAQ;SACjB;QACD,IAAI,EAAE,gBAAgB;KACzB;IACD;QACI,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,uBAAuB,EAAE;QACxF,WAAW,EACP,8VAA8V;QAClW,WAAW,EAAE;YACT,UAAU,EAAE;gBACR,OAAO,EAAE;oBACL,WAAW,EACP,uIAAuI;oBAC3I,IAAI,EAAE,QAAQ;iBACjB;gBACD,MAAM,EAAE,EAAE,WAAW,EAAE,+BAA+B,EAAE,IAAI,EAAE,QAAQ,EAAE;aAC3E;YACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;YACpB,IAAI,EAAE,QAAQ;SACjB;QACD,IAAI,EAAE,UAAU;KACnB;IACD;QACI,WAAW,EAAE;YACT,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,KAAK;YACrB,aAAa,EAAE,IAAI;YACnB,YAAY,EAAE,KAAK;YACnB,KAAK,EAAE,+BAA+B;SACzC;QACD,WAAW,EACP,6SAA6S;QACjT,WAAW,EAAE;YACT,UAAU,EAAE;gBACR,WAAW,EAAE,EAAE,WAAW,EAAE,oCAAoC,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAClF,SAAS,EAAE;oBACP,WAAW,EACP,gFAAgF;oBACpF,IAAI,EAAE,QAAQ;iBACjB;gBACD,IAAI,EAAE;oBACF,WAAW,EACP,2GAA2G;oBAC/G,IAAI,EAAE,QAAQ;iBACjB;gBACD,aAAa,EAAE;oBACX,WAAW,EACP,iGAAiG;oBACrG,IAAI,EAAE,QAAQ;iBACjB;aACJ;YACD,QAAQ,EAAE,CAAC,MAAM,CAAC;YAClB,IAAI,EAAE,QAAQ;SACjB;QACD,IAAI,EAAE,sBAAsB;KAC/B;CACJ,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAWpE,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,OAAO,GAAG,KAAK,EAAkB,EAAE,CAAC,CAAC;IAC9D,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACxC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;CACxC,CAAC,CAAC;AAEH,MAAM,SAAS,GAAG,CACd,IAA6B,EAC7B,IAAY,EACZ,QAAQ,GAAG,KAAK,EACE,EAAE;IACpB,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACxD,IAAI,QAAQ,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,8BAA8B,IAAI,IAAI,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,aAAa,IAAI,qBAAqB,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC;AAEF,gGAAgG;AAChG,MAAM,OAAO,QAAQ;IAKI;IACA;IALZ,IAAI,CAAa;IACjB,GAAG,CAAY;IAExB,YACqB,MAAc,EACd,UAA2B,EAAE;QAD7B,WAAM,GAAN,MAAM,CAAQ;QACd,YAAO,GAAP,OAAO,CAAsB;QAE9C,IAAI,CAAC,IAAI,GAAG,IAAI,UAAU,CAAC;YACvB,GAAG,EAAE,MAAM,CAAC,OAAO;YACnB,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5C,GAAG,OAAO,CAAC,IAAI;SAClB,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,GAAG,IAAI,SAAS,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,0EAA0E;IAC1E,KAAK;QACD,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,GAAG,CAAC,IAAY;QACZ,OAAO,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,mEAAmE;IACnE,YAAY,CAAC,IAAY;QACrB,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI,IAAI,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5C,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC,WAAW,EAAE,YAAY,KAAK,IAAI;YAClE,CAAC,CAAC,QAAQ,IAAI,gEAAgE;YAC9E,CAAC,CAAC,QAAQ,IAAI,2DAA2D,CAAC;IAClF,CAAC;IAED,KAAK,CAAC,IAAI,CACN,IAAY,EACZ,IAA6B,EAC7B,MAAoB;QAEpB,IAAI,CAAC;YACD,QAAQ,IAAI,EAAE,CAAC;gBACX,KAAK,kBAAkB;oBACnB,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACnC,KAAK,gBAAgB;oBACjB,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACjC,KAAK,UAAU;oBACX,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACnC,KAAK,sBAAsB;oBACvB,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC7C;oBACI,OAAO,IAAI,CAAC,iBAAiB,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;YACnD,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QAC9E,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,IAA6B;QAC9C,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/B,MAAM,KAAK,GACP,OAAO,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;YACrD,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;YACjD,CAAC,CAAC,CAAC,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QAC5C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpB,OAAO,IAAI,CACP,qBAAqB,KAAK,2BAA2B,IAAI,CAAC,MAAM,SAAS,UAAU,CAAC,IAAI,CAAC,EAAE,CAC9F,CAAC;QACN,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAClB,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CACP,GAAG,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,OAAO,MAAM,GAAG,CAAC,KAAK,CAAC,KAAK,aAAa,GAAG,CAAC,KAAK,SAAS,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAChM,CAAC;QACF,OAAO,IAAI,CACP,GAAG,IAAI,CAAC,MAAM,kBAAkB,KAAK,cAAc,IAAI,CAAC,MAAM,iEAAiE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACpJ,CAAC;IACN,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,IAA6B;QAC5C,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAE,CAAC;QAC9C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACrC,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3B,OAAO,IAAI,CACP,MAAM,CAAC,MAAM;iBACR,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACP,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;gBACpB,CAAC,CAAC,QAAQ,CAAC,CAAC,OAAO,MAAM,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,OAAO,EAAE;gBACpD,CAAC,CAAC,CAAC,CAAC,OAAO,CAClB;iBACA,IAAI,CAAC,aAAa,CAAC,CAC3B,CAAC;QACN,CAAC;QACD,OAAO,IAAI,CACP,wBAAwB,KAAK,mBAAmB,IAAI,CAAC,MAAM,2BAA2B,UAAU,CAAC,IAAI,CAAC,EAAE,EACxG,IAAI,CACP,CAAC;IACN,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,IAA6B;QAC9C,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAE,CAAC,IAAI,EAAE,CAAC;QACvD,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACrC,OAAO,IAAI,CAAC,IAAI,MAAM,qDAAqD,EAAE,IAAI,CAAC,CAAC;QACvF,CAAC;QACD,MAAM,GAAG,GAAG,oBAAoB,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;QAC7D,IAAI,KAAK,CAAC;QACV,IAAI,CAAC;YACD,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,IAAI,CACP,sCAAsC,GAAG,KAAM,KAAe,CAAC,OAAO,qDAAqD,GAAG,oBAAoB,EAClJ,IAAI,CACP,CAAC;QACN,CAAC;QACD,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC3C,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;IAChF,CAAC;IAEO,KAAK,CAAC,QAAQ,CAClB,IAA6B,EAC7B,MAAoB;QAEpB,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,sBAAsB,CAAC,CAAC;QACzD,IAAI,MAAM,EAAE,CAAC;YACT,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC9B,CAAC;QACD,MAAM,IAAI,GAAG,YAAY,CAAC;YACtB,WAAW,EAAE,SAAS,CAAC,IAAI,EAAE,aAAa,CAAC;YAC3C,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE,WAAW,CAAC;YACvC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAE;YACpC,aAAa,EAAE,SAAS,CAAC,IAAI,EAAE,eAAe,CAAC;SAClD,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,iBAAiB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAC1E,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE;YACtC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB;gBAC9B,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE;gBAC/C,CAAC,CAAC,EAAE,CAAC;YACT,MAAM;SACT,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED,uEAAuE;IAEvE,OAAO;QACH,OAAO,OAAO,CAAC;IACnB,CAAC;IAED,SAAS,CAAC,IAAY,EAAE,IAAwC;QAC5D,MAAM,GAAG,GAAkB,EAAE,WAAW,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,sBAAsB,CAAC,EAAE,CAAC;QACvF,OAAO,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IACtC,CAAC;IAED,yEAAyE;IAEzE,KAAK,CAAC,SAAS;QACX,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3B,WAAW,EAAE,CAAC,CAAC,OAAO;YACtB,QAAQ,EAAE,eAAe;YACzB,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,MAAM,CAAC,CAAC,KAAK,EAAE;YACjC,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,GAAG,EAAE,GAAG,oBAAoB,GAAG,CAAC,CAAC,GAAG,EAAE;SACzC,CAAC,CAAC,CAAC;IACR,CAAC;IAED,gFAAgF;IAChF,KAAK,CAAC,YAAY,CAAC,GAAW;QAC1B,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACxC,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,MAAM,IAAI,GAAS,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,EAAE,OAAO,CAAC;IAC5D,CAAC;CACJ"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * A small `.env` parser (no dependency): `KEY=value`, optional `export`,
3
+ * `#` comments, single/double quotes with `\n`/`\t`/`\\`/`\"` escapes inside
4
+ * double quotes, and inline comments after unquoted values.
5
+ */
6
+ export declare const parseEnvFile: (content: string) => Record<string, string>;
7
+ /** Loads a .env file into `env` without overriding keys that are already set. */
8
+ export declare const applyEnvFile: (path: string, env: Record<string, string | undefined>) => void;
9
+ //# sourceMappingURL=env-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-file.d.ts","sourceRoot":"","sources":["../../src/env-file.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAgBnE,CAAC;AAmBF,iFAAiF;AACjF,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,EAAE,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KAAG,IAapF,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { readFileSync } from 'node:fs';
2
+ /**
3
+ * A small `.env` parser (no dependency): `KEY=value`, optional `export`,
4
+ * `#` comments, single/double quotes with `\n`/`\t`/`\\`/`\"` escapes inside
5
+ * double quotes, and inline comments after unquoted values.
6
+ */
7
+ export const parseEnvFile = (content) => {
8
+ const result = {};
9
+ for (const rawLine of content.split(/\r?\n/)) {
10
+ const line = rawLine.trim();
11
+ const isSkippable = line.length === 0 || line.startsWith('#');
12
+ if (isSkippable) {
13
+ continue;
14
+ }
15
+ const match = /^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(line);
16
+ if (!match) {
17
+ continue;
18
+ }
19
+ const key = match[1] ?? '';
20
+ result[key] = parseValue(match[2] ?? '');
21
+ }
22
+ return result;
23
+ };
24
+ const parseValue = (raw) => {
25
+ const value = raw.trim();
26
+ if (value.startsWith('"')) {
27
+ const end = value.indexOf('"', 1);
28
+ const body = end === -1 ? value.slice(1) : value.slice(1, end);
29
+ return body.replace(/\\(n|t|r|\\|")/g, (_m, ch) => ch === 'n' ? '\n' : ch === 't' ? '\t' : ch === 'r' ? '\r' : ch);
30
+ }
31
+ if (value.startsWith("'")) {
32
+ const end = value.indexOf("'", 1);
33
+ return end === -1 ? value.slice(1) : value.slice(1, end);
34
+ }
35
+ const commentStart = value.search(/\s#/);
36
+ return (commentStart === -1 ? value : value.slice(0, commentStart)).trim();
37
+ };
38
+ /** Loads a .env file into `env` without overriding keys that are already set. */
39
+ export const applyEnvFile = (path, env) => {
40
+ let content;
41
+ try {
42
+ content = readFileSync(path, 'utf8');
43
+ }
44
+ catch (error) {
45
+ const reason = error instanceof Error ? error.message : String(error);
46
+ throw new Error(`Could not read env file "${path}": ${reason}`);
47
+ }
48
+ for (const [key, value] of Object.entries(parseEnvFile(content))) {
49
+ if (env[key] === undefined) {
50
+ env[key] = value;
51
+ }
52
+ }
53
+ };
54
+ //# sourceMappingURL=env-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-file.js","sourceRoot":"","sources":["../../src/env-file.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { AuthConfig } from './config.js';
2
+ export type FailureKind = 'auth' | 'forbidden' | 'http' | 'login' | 'not-enabled' | 'timeout' | 'unreachable';
3
+ /** A remote failure turned into one sentence that tells the user what to do. */
4
+ export declare class RemoteError extends Error {
5
+ readonly kind: FailureKind;
6
+ constructor(kind: FailureKind, message: string, options?: ErrorOptions);
7
+ }
8
+ /** The first `code` found on the error, its `cause` chain or an AggregateError's members. */
9
+ export declare const networkCode: (error: unknown, depth?: number) => string | undefined;
10
+ /** Connection refused/reset, DNS failure, socket closed: safe to retry once on a fresh connection. */
11
+ export declare const isRetryableNetworkError: (error: unknown) => boolean;
12
+ /** HTTP status of an SDK HTTP error (`SdkHttpError.status`) or a plain `{ status }`. */
13
+ export declare const httpStatus: (error: unknown) => number | undefined;
14
+ export type ClassifyContext = {
15
+ auth: AuthConfig['kind'];
16
+ requestTimeoutMs: number;
17
+ connectionTimeoutMs: number;
18
+ url: string;
19
+ };
20
+ /** Map a transport / HTTP failure to a {@link RemoteError} with an actionable message. */
21
+ export declare const classify: (error: unknown, ctx: ClassifyContext) => RemoteError;
22
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,MAAM,WAAW,GACnB,MAAM,GAAG,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,GAAG,SAAS,GAAG,aAAa,CAAC;AAExF,gFAAgF;AAChF,qBAAa,WAAY,SAAQ,KAAK;IAE9B,QAAQ,CAAC,IAAI,EAAE,WAAW;gBAAjB,IAAI,EAAE,WAAW,EAC1B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY;CAK7B;AAkBD,6FAA6F;AAC7F,eAAO,MAAM,WAAW,GAAI,OAAO,OAAO,EAAE,cAAS,KAAG,MAAM,GAAG,SAmBhE,CAAC;AAEF,sGAAsG;AACtG,eAAO,MAAM,uBAAuB,GAAI,OAAO,OAAO,KAAG,OAGxD,CAAC;AAgBF,wFAAwF;AACxF,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAGpD,CAAC;AAgBF,MAAM,MAAM,eAAe,GAAG;IAC1B,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,0FAA0F;AAC1F,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,EAAE,KAAK,eAAe,KAAG,WAqE/D,CAAC"}
@@ -0,0 +1,115 @@
1
+ /** A remote failure turned into one sentence that tells the user what to do. */
2
+ export class RemoteError extends Error {
3
+ kind;
4
+ constructor(kind, message, options) {
5
+ super(message, options);
6
+ this.kind = kind;
7
+ this.name = 'RemoteError';
8
+ }
9
+ }
10
+ /** Connection-level error codes: the request never reached (or never left) the server. */
11
+ const RETRYABLE_CODES = new Set([
12
+ 'ECONNREFUSED',
13
+ 'ECONNRESET',
14
+ 'EPIPE',
15
+ 'ENOTFOUND',
16
+ 'EAI_AGAIN',
17
+ 'EHOSTUNREACH',
18
+ 'ENETUNREACH',
19
+ 'ENETDOWN',
20
+ 'UND_ERR_SOCKET',
21
+ 'UND_ERR_CLOSED',
22
+ ]);
23
+ /** Not retried: the host did not answer within QCLI_CONNECTION_TIMEOUT, retrying doubles the wait. */
24
+ const CONNECT_TIMEOUT_CODES = new Set(['UND_ERR_CONNECT_TIMEOUT', 'ETIMEDOUT']);
25
+ /** The first `code` found on the error, its `cause` chain or an AggregateError's members. */
26
+ export const networkCode = (error, depth = 0) => {
27
+ if (!error || typeof error !== 'object' || depth > 5) {
28
+ return undefined;
29
+ }
30
+ const code = error.code;
31
+ if (typeof code === 'string' &&
32
+ (RETRYABLE_CODES.has(code) || CONNECT_TIMEOUT_CODES.has(code))) {
33
+ return code;
34
+ }
35
+ const nested = error.errors;
36
+ for (const inner of Array.isArray(nested) ? nested : []) {
37
+ const found = networkCode(inner, depth + 1);
38
+ if (found) {
39
+ return found;
40
+ }
41
+ }
42
+ return networkCode(error.cause, depth + 1);
43
+ };
44
+ /** Connection refused/reset, DNS failure, socket closed: safe to retry once on a fresh connection. */
45
+ export const isRetryableNetworkError = (error) => {
46
+ const code = networkCode(error);
47
+ return code !== undefined && RETRYABLE_CODES.has(code);
48
+ };
49
+ const isNetworkError = (error) => networkCode(error) !== undefined ||
50
+ (error instanceof TypeError && /fetch failed|network/i.test(error.message));
51
+ const isTimeout = (error) => {
52
+ const name = error?.name;
53
+ const code = error?.code;
54
+ return (name === 'TimeoutError' ||
55
+ code === 'REQUEST_TIMEOUT' ||
56
+ /timed? ?out/i.test(String(error?.message)));
57
+ };
58
+ /** HTTP status of an SDK HTTP error (`SdkHttpError.status`) or a plain `{ status }`. */
59
+ export const httpStatus = (error) => {
60
+ const status = error?.status;
61
+ return typeof status === 'number' && status >= 400 ? status : undefined;
62
+ };
63
+ /** `{"error":"…"}` (or detail/message) from the HTTP body the SDK attached. */
64
+ const serverDetail = (error) => {
65
+ const data = error?.data;
66
+ const text = typeof data?.text === 'string' ? data.text : error?.message;
67
+ const json = typeof text === 'string' ? text.slice(Math.max(0, text.indexOf('{'))) : '';
68
+ try {
69
+ const body = JSON.parse(json);
70
+ const detail = body['error'] ?? body['detail'] ?? body['message'];
71
+ return typeof detail === 'string' ? detail.slice(0, 300) : undefined;
72
+ }
73
+ catch {
74
+ return undefined;
75
+ }
76
+ };
77
+ /** Map a transport / HTTP failure to a {@link RemoteError} with an actionable message. */
78
+ export const classify = (error, ctx) => {
79
+ if (error instanceof RemoteError) {
80
+ return error;
81
+ }
82
+ const status = httpStatus(error);
83
+ const detail = serverDetail(error);
84
+ const options = { cause: error };
85
+ if (status === 401) {
86
+ const advice = ctx.auth === 'token'
87
+ ? 'QCLI_TOKEN is wrong, expired or revoked. Create a new token (`token create claude` in the web CLI) and update QCLI_TOKEN.'
88
+ : ctx.auth === 'password'
89
+ ? 'the session was rejected even after signing in again. Check that the account is enabled.'
90
+ : 'the server requires authentication. Set QCLI_TOKEN, or QCLI_USER and QCLI_PASSWORD.';
91
+ return new RemoteError('auth', `${ctx.url} answered 401 (not authenticated): ${advice}`, options);
92
+ }
93
+ if (status === 403) {
94
+ return new RemoteError('forbidden', `${ctx.url} answered 403${detail ? ` (${detail})` : ''}: the account needs the commands:execute permission, or the server rejected the request origin.`, options);
95
+ }
96
+ if (status === 404 || status === 405) {
97
+ return new RemoteError('not-enabled', `MCP is not enabled on this server (enable the mcp option): ${status} from ${ctx.url}/api/qcli/mcp.`, options);
98
+ }
99
+ if (status !== undefined) {
100
+ return new RemoteError('http', `${ctx.url} answered ${status}${detail ? `: ${detail}` : ''}.`, options);
101
+ }
102
+ const code = networkCode(error);
103
+ if (code && CONNECT_TIMEOUT_CODES.has(code)) {
104
+ return new RemoteError('unreachable', `Cannot reach ${ctx.url} (no answer within ${ctx.connectionTimeoutMs} ms). Check QCLI_URL / VPN.`, options);
105
+ }
106
+ if (isNetworkError(error)) {
107
+ const reason = code ?? error.message;
108
+ return new RemoteError('unreachable', `Cannot reach ${ctx.url} (${reason}). Check QCLI_URL / VPN.`, options);
109
+ }
110
+ if (isTimeout(error)) {
111
+ return new RemoteError('timeout', `${ctx.url} did not answer within ${ctx.requestTimeoutMs} ms (QCLI_REQUEST_TIMEOUT).`, options);
112
+ }
113
+ return new RemoteError('http', `${ctx.url}: ${error?.message ?? String(error)}`, options);
114
+ };
115
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { Tool } from '@modelcontextprotocol/server';
2
+ import type { Config } from './config.js';
3
+ /** A tool exactly as the remote server lists it. */
4
+ export type RemoteTool = Tool;
5
+ /** `fs_*` matches every name starting with `fs_`; anything else must match exactly. */
6
+ export declare const matchesPattern: (name: string, pattern: string) => boolean;
7
+ export type FilterConfig = Pick<Config, 'exclude' | 'readOnly' | 'tools'>;
8
+ /**
9
+ * Whether the proxy exposes (and forwards calls to) a tool: read-only mode keeps only
10
+ * tools annotated `readOnlyHint: true`, then the allow-list and deny-list apply.
11
+ */
12
+ export declare const isToolAllowed: (tool: RemoteTool, config: FilterConfig) => boolean;
13
+ //# sourceMappingURL=filters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../../src/filters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,oDAAoD;AACpD,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC;AAE9B,uFAAuF;AACvF,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,SAAS,MAAM,KAAG,OACqB,CAAC;AAErF,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC,CAAC;AAE1E;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,UAAU,EAAE,QAAQ,YAAY,KAAG,OAQtE,CAAC"}
@@ -0,0 +1,16 @@
1
+ /** `fs_*` matches every name starting with `fs_`; anything else must match exactly. */
2
+ export const matchesPattern = (name, pattern) => pattern.endsWith('*') ? name.startsWith(pattern.slice(0, -1)) : name === pattern;
3
+ /**
4
+ * Whether the proxy exposes (and forwards calls to) a tool: read-only mode keeps only
5
+ * tools annotated `readOnlyHint: true`, then the allow-list and deny-list apply.
6
+ */
7
+ export const isToolAllowed = (tool, config) => {
8
+ if (config.readOnly && tool.annotations?.readOnlyHint !== true) {
9
+ return false;
10
+ }
11
+ if (config.tools.length > 0 && !config.tools.some((p) => matchesPattern(tool.name, p))) {
12
+ return false;
13
+ }
14
+ return !config.exclude.some((p) => matchesPattern(tool.name, p));
15
+ };
16
+ //# sourceMappingURL=filters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters.js","sourceRoot":"","sources":["../../src/filters.ts"],"names":[],"mappings":"AAMA,uFAAuF;AACvF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,IAAY,EAAE,OAAe,EAAW,EAAE,CACrE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC;AAIrF;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAgB,EAAE,MAAoB,EAAW,EAAE;IAC7E,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC,WAAW,EAAE,YAAY,KAAK,IAAI,EAAE,CAAC;QAC7D,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrF,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ export { ConfigError, createEnvReader, DEFAULT_DOCS_URL, describeConfig, ENV_FILE_VARIABLES, loadConfig, names, normalizeUrl, type AuthConfig, type Config, type Env, } from './config.js';
2
+ export { ApiSource, extractDeclarations, formatLookup, lookupSymbol, normalizePackageName, type ApiLookup, type ApiSourceOptions, type TypeFiles, } from './dev/api.js';
3
+ export { DocsSource, parseDocs, readDocs, searchDocs, type Docs, type DocSection, type DocTopic, type SearchHit, } from './dev/docs.js';
4
+ export { getPrompt, PROMPTS } from './dev/prompts.js';
5
+ export { planScaffold, scaffoldPlugin, ScaffoldError, type ScaffoldPlan } from './dev/scaffold.js';
6
+ export { DEV_TOOLS, DevTools, type DevToolsOptions } from './dev/tools.js';
7
+ export { applyEnvFile, parseEnvFile } from './env-file.js';
8
+ export { classify, RemoteError, type FailureKind } from './errors.js';
9
+ export { isToolAllowed, matchesPattern, type RemoteTool } from './filters.js';
10
+ export { createFetch, MCP_PATH, RemoteServer, TOOLS_TTL_MS, type RemoteOptions } from './remote.js';
11
+ export { buildInstructions, createProxyServer, SERVER_NAME, type ProxyServerOptions, SERVER_VERSION, WEBSITE_URL, } from './server.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,KAAK,EACL,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,MAAM,EACX,KAAK,GAAG,GACX,MAAM,aAAa,CAAC;AACrB,OAAO,EACH,SAAS,EACT,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,oBAAoB,EACpB,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,SAAS,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACH,UAAU,EACV,SAAS,EACT,QAAQ,EACR,UAAU,EACV,KAAK,IAAI,EACT,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,SAAS,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACnG,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACpG,OAAO,EACH,iBAAiB,EACjB,iBAAiB,EACjB,WAAW,EACX,KAAK,kBAAkB,EACvB,cAAc,EACd,WAAW,GACd,MAAM,aAAa,CAAC"}
@@ -0,0 +1,12 @@
1
+ export { ConfigError, createEnvReader, DEFAULT_DOCS_URL, describeConfig, ENV_FILE_VARIABLES, loadConfig, names, normalizeUrl, } from './config.js';
2
+ export { ApiSource, extractDeclarations, formatLookup, lookupSymbol, normalizePackageName, } from './dev/api.js';
3
+ export { DocsSource, parseDocs, readDocs, searchDocs, } from './dev/docs.js';
4
+ export { getPrompt, PROMPTS } from './dev/prompts.js';
5
+ export { planScaffold, scaffoldPlugin, ScaffoldError } from './dev/scaffold.js';
6
+ export { DEV_TOOLS, DevTools } from './dev/tools.js';
7
+ export { applyEnvFile, parseEnvFile } from './env-file.js';
8
+ export { classify, RemoteError } from './errors.js';
9
+ export { isToolAllowed, matchesPattern } from './filters.js';
10
+ export { createFetch, MCP_PATH, RemoteServer, TOOLS_TTL_MS } from './remote.js';
11
+ export { buildInstructions, createProxyServer, SERVER_NAME, SERVER_VERSION, WEBSITE_URL, } from './server.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,KAAK,EACL,YAAY,GAIf,MAAM,aAAa,CAAC;AACrB,OAAO,EACH,SAAS,EACT,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,oBAAoB,GAIvB,MAAM,cAAc,CAAC;AACtB,OAAO,EACH,UAAU,EACV,SAAS,EACT,QAAQ,EACR,UAAU,GAKb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAqB,MAAM,mBAAmB,CAAC;AACnG,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAwB,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAoB,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAmB,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAsB,MAAM,aAAa,CAAC;AACpG,OAAO,EACH,iBAAiB,EACjB,iBAAiB,EACjB,WAAW,EAEX,cAAc,EACd,WAAW,GACd,MAAM,aAAa,CAAC"}
@@ -0,0 +1,64 @@
1
+ import { type CallToolRequestParams, type CallToolResult, type FetchLike } from '@modelcontextprotocol/client';
2
+ import { type Config } from './config.js';
3
+ import type { RemoteTool } from './filters.js';
4
+ export declare const MCP_PATH = "/api/qcli/mcp";
5
+ export declare const SESSIONS_PATH = "/api/v1/qcli/sessions";
6
+ /** How long a fetched tool list is reused before `tools/list` asks the server again. */
7
+ export declare const TOOLS_TTL_MS = 60000;
8
+ export type RemoteOptions = {
9
+ /** Client name/version announced to the server */
10
+ clientInfo: {
11
+ name: string;
12
+ version: string;
13
+ };
14
+ /** Overrides the HTTP client (tests) */
15
+ fetch?: FetchLike;
16
+ log?: (message: string) => void;
17
+ now?: () => number;
18
+ toolsTtlMs?: number;
19
+ };
20
+ /** HTTP client honouring QCLI_CONNECTION_TIMEOUT, QCLI_REQUEST_TIMEOUT and QCLI_TRUST_CERT. */
21
+ export declare const createFetch: (config: Config) => {
22
+ close: () => Promise<void>;
23
+ fetch: FetchLike;
24
+ };
25
+ /**
26
+ * Connection to the Qodalis CLI server's MCP endpoint.
27
+ *
28
+ * - Connects on first use; a failed connect is never cached.
29
+ * - A connection-level error (refused, reset, DNS) drops the client and retries once.
30
+ * - With QCLI_USER / QCLI_PASSWORD it signs in, and signs in again after a 401.
31
+ * - The tool list is cached for {@link TOOLS_TTL_MS}.
32
+ */
33
+ export declare class RemoteServer {
34
+ private readonly config;
35
+ private readonly options;
36
+ private client;
37
+ private connecting;
38
+ private sessionToken;
39
+ private toolsCache;
40
+ private readonly fetchFn;
41
+ private readonly closeFetch;
42
+ private readonly log;
43
+ private readonly now;
44
+ /** `config.url`, required to talk to a server */
45
+ private readonly url;
46
+ constructor(config: Config, options: RemoteOptions);
47
+ /** Remote tools (unfiltered), from the cache unless it is older than the TTL or `refresh`. */
48
+ listTools(refresh?: boolean): Promise<RemoteTool[]>;
49
+ /** Find a tool, asking the server again when it is not in the cached list. */
50
+ findTool(name: string): Promise<RemoteTool | undefined>;
51
+ /** Forward `tools/call`; remote JSON-RPC errors are rethrown unchanged. */
52
+ callTool(params: CallToolRequestParams, signal?: AbortSignal): Promise<CallToolResult>;
53
+ close(): Promise<void>;
54
+ /** Run an operation with a connected client: one retry on connection loss, one re-login on 401. */
55
+ private run;
56
+ private connect;
57
+ private open;
58
+ private dropClient;
59
+ private bearerToken;
60
+ /** POST /api/v1/qcli/sessions with QCLI_USER / QCLI_PASSWORD. */
61
+ private signIn;
62
+ private classifyContext;
63
+ }
64
+ //# sourceMappingURL=remote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../../src/remote.ts"],"names":[],"mappings":"AAAA,OAAO,EAIH,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,KAAK,SAAS,EACjB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAe,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAQvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,eAAO,MAAM,QAAQ,kBAAkB,CAAC;AACxC,eAAO,MAAM,aAAa,0BAA0B,CAAC;AACrD,wFAAwF;AACxF,eAAO,MAAM,YAAY,QAAS,CAAC;AAEnC,MAAM,MAAM,aAAa,GAAG;IACxB,kDAAkD;IAClD,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,wCAAwC;IACxC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,+FAA+F;AAC/F,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,KAAG;IAAE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAc1F,CAAC;AAEF;;;;;;;GAOG;AACH,qBAAa,YAAY;IAajB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAb5B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,UAAU,CAA8B;IAChD,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,UAAU,CAAkD;IACpE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAY;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA4B;IAChD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,iDAAiD;IACjD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;gBAGR,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa;IAkB3C,8FAA8F;IACxF,SAAS,CAAC,OAAO,UAAQ,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAsBvD,8EAA8E;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAK7D,2EAA2E;IACrE,QAAQ,CAAC,MAAM,EAAE,qBAAqB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;IAkBtF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB5B,mGAAmG;YACrF,GAAG;IAgCjB,OAAO,CAAC,OAAO;YAWD,IAAI;YAmBJ,UAAU;YAMV,WAAW;IAYzB,iEAAiE;YACnD,MAAM;IAuCpB,OAAO,CAAC,eAAe;CAQ1B"}
@@ -0,0 +1,242 @@
1
+ import { Client, ProtocolError, StreamableHTTPClientTransport, } from '@modelcontextprotocol/client';
2
+ import { Agent, fetch as undiciFetch } from 'undici';
3
+ import { ConfigError } from './config.js';
4
+ import { classify, httpStatus, isRetryableNetworkError, networkCode, RemoteError, } from './errors.js';
5
+ export const MCP_PATH = '/api/qcli/mcp';
6
+ export const SESSIONS_PATH = '/api/v1/qcli/sessions';
7
+ /** How long a fetched tool list is reused before `tools/list` asks the server again. */
8
+ export const TOOLS_TTL_MS = 60_000;
9
+ /** HTTP client honouring QCLI_CONNECTION_TIMEOUT, QCLI_REQUEST_TIMEOUT and QCLI_TRUST_CERT. */
10
+ export const createFetch = (config) => {
11
+ const agent = new Agent({
12
+ connect: { rejectUnauthorized: !config.trustCert, timeout: config.connectionTimeoutMs },
13
+ });
14
+ const fetchFn = (url, init) => {
15
+ const timeout = AbortSignal.timeout(config.requestTimeoutMs);
16
+ const signal = init?.signal ? AbortSignal.any([init.signal, timeout]) : timeout;
17
+ return undiciFetch(url, {
18
+ ...init,
19
+ dispatcher: agent,
20
+ signal,
21
+ });
22
+ };
23
+ return { close: () => agent.close(), fetch: fetchFn };
24
+ };
25
+ /**
26
+ * Connection to the Qodalis CLI server's MCP endpoint.
27
+ *
28
+ * - Connects on first use; a failed connect is never cached.
29
+ * - A connection-level error (refused, reset, DNS) drops the client and retries once.
30
+ * - With QCLI_USER / QCLI_PASSWORD it signs in, and signs in again after a 401.
31
+ * - The tool list is cached for {@link TOOLS_TTL_MS}.
32
+ */
33
+ export class RemoteServer {
34
+ config;
35
+ options;
36
+ client;
37
+ connecting;
38
+ sessionToken;
39
+ toolsCache;
40
+ fetchFn;
41
+ closeFetch;
42
+ log;
43
+ now;
44
+ /** `config.url`, required to talk to a server */
45
+ url;
46
+ constructor(config, options) {
47
+ this.config = config;
48
+ this.options = options;
49
+ if (!config.url) {
50
+ throw new ConfigError('QCLI_URL is required to connect to a Qodalis CLI server.');
51
+ }
52
+ this.url = config.url;
53
+ if (options.fetch) {
54
+ this.fetchFn = options.fetch;
55
+ this.closeFetch = async () => undefined;
56
+ }
57
+ else {
58
+ const created = createFetch(config);
59
+ this.fetchFn = created.fetch;
60
+ this.closeFetch = created.close;
61
+ }
62
+ this.log = options.log ?? (() => undefined);
63
+ this.now = options.now ?? Date.now;
64
+ }
65
+ /** Remote tools (unfiltered), from the cache unless it is older than the TTL or `refresh`. */
66
+ async listTools(refresh = false) {
67
+ const ttl = this.options.toolsTtlMs ?? TOOLS_TTL_MS;
68
+ const cached = this.toolsCache;
69
+ if (!refresh && cached && this.now() - cached.at < ttl) {
70
+ return cached.tools;
71
+ }
72
+ const tools = await this.run(async (client) => {
73
+ const all = [];
74
+ let cursor;
75
+ do {
76
+ const page = await client.listTools(cursor ? { cursor } : {}, {
77
+ timeout: this.config.requestTimeoutMs,
78
+ });
79
+ all.push(...page.tools);
80
+ cursor = page.nextCursor;
81
+ } while (cursor);
82
+ return all;
83
+ }, true);
84
+ this.toolsCache = { at: this.now(), tools };
85
+ return tools;
86
+ }
87
+ /** Find a tool, asking the server again when it is not in the cached list. */
88
+ async findTool(name) {
89
+ const cached = (await this.listTools()).find((t) => t.name === name);
90
+ return cached ?? (await this.listTools(true)).find((t) => t.name === name);
91
+ }
92
+ /** Forward `tools/call`; remote JSON-RPC errors are rethrown unchanged. */
93
+ async callTool(params, signal) {
94
+ try {
95
+ return (await this.run((client) => client.callTool(params, {
96
+ timeout: this.config.requestTimeoutMs,
97
+ ...(signal ? { signal } : {}),
98
+ }), true));
99
+ }
100
+ catch (error) {
101
+ if (error instanceof ProtocolError && /unknown tool/i.test(error.message)) {
102
+ this.toolsCache = undefined; // the server's commands changed
103
+ }
104
+ throw error;
105
+ }
106
+ }
107
+ async close() {
108
+ const client = this.client;
109
+ this.client = undefined;
110
+ await client?.close().catch(() => undefined);
111
+ if (this.sessionToken) {
112
+ // End the password session we opened (best effort)
113
+ await this.fetchFn(`${this.url}${SESSIONS_PATH}/current`, {
114
+ headers: { Authorization: `Bearer ${this.sessionToken}` },
115
+ method: 'DELETE',
116
+ signal: AbortSignal.timeout(2000),
117
+ }).catch(() => undefined);
118
+ this.sessionToken = undefined;
119
+ }
120
+ await this.closeFetch().catch(() => undefined);
121
+ }
122
+ /** Run an operation with a connected client: one retry on connection loss, one re-login on 401. */
123
+ async run(operation, retryNetwork) {
124
+ let signedInAgain = false;
125
+ let retried = false;
126
+ for (;;) {
127
+ try {
128
+ const client = await this.connect();
129
+ return await operation(client);
130
+ }
131
+ catch (error) {
132
+ if (error instanceof ProtocolError || error instanceof RemoteError) {
133
+ throw error;
134
+ }
135
+ await this.dropClient();
136
+ const status = httpStatus(error);
137
+ if (status === 401 && this.config.auth.kind === 'password' && !signedInAgain) {
138
+ signedInAgain = true;
139
+ this.sessionToken = undefined;
140
+ this.log('session rejected (401); signing in again');
141
+ continue;
142
+ }
143
+ if (retryNetwork && !retried && isRetryableNetworkError(error)) {
144
+ retried = true;
145
+ this.log(`connection lost (${networkCode(error)}); retrying once`);
146
+ continue;
147
+ }
148
+ throw classify(error, this.classifyContext());
149
+ }
150
+ }
151
+ }
152
+ connect() {
153
+ if (this.client) {
154
+ return Promise.resolve(this.client);
155
+ }
156
+ // Concurrent first calls share one connect; a failure is not cached
157
+ this.connecting ??= this.open().finally(() => {
158
+ this.connecting = undefined;
159
+ });
160
+ return this.connecting;
161
+ }
162
+ async open() {
163
+ const token = await this.bearerToken();
164
+ const transport = new StreamableHTTPClientTransport(new URL(`${this.url}${MCP_PATH}`), {
165
+ fetch: this.fetchFn,
166
+ requestInit: { headers: token ? { Authorization: `Bearer ${token}` } : {} },
167
+ });
168
+ const client = new Client(this.options.clientInfo);
169
+ try {
170
+ await client.connect(transport, { timeout: this.config.connectionTimeoutMs });
171
+ }
172
+ catch (error) {
173
+ await client.close().catch(() => undefined);
174
+ throw error;
175
+ }
176
+ const info = client.getServerVersion();
177
+ this.log(`connected to ${this.url}${info ? ` (${info.name} ${info.version})` : ''}`);
178
+ this.client = client;
179
+ return client;
180
+ }
181
+ async dropClient() {
182
+ const client = this.client;
183
+ this.client = undefined;
184
+ await client?.close().catch(() => undefined);
185
+ }
186
+ async bearerToken() {
187
+ const auth = this.config.auth;
188
+ if (auth.kind === 'token') {
189
+ return auth.token;
190
+ }
191
+ if (auth.kind === 'none') {
192
+ return undefined;
193
+ }
194
+ this.sessionToken ??= await this.signIn(auth.user, auth.password);
195
+ return this.sessionToken;
196
+ }
197
+ /** POST /api/v1/qcli/sessions with QCLI_USER / QCLI_PASSWORD. */
198
+ async signIn(user, password) {
199
+ const response = await this.fetchFn(`${this.url}${SESSIONS_PATH}`, {
200
+ body: JSON.stringify({ password, username: user }),
201
+ headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
202
+ method: 'POST',
203
+ });
204
+ const text = await response.text();
205
+ if (response.status === 401 || response.status === 400 || response.status === 403) {
206
+ throw new RemoteError('login', `${this.url} rejected QCLI_USER / QCLI_PASSWORD for "${user}" (${response.status}${errorText(text)}).`);
207
+ }
208
+ if (response.status === 404) {
209
+ throw new RemoteError('login', `${this.url} has no users plugin (404 on ${SESSIONS_PATH}): use QCLI_TOKEN with the server's mcp token instead of QCLI_USER / QCLI_PASSWORD.`);
210
+ }
211
+ if (response.status === 429) {
212
+ throw new RemoteError('login', `${this.url}: too many failed sign-ins for "${user}"; try again later.`);
213
+ }
214
+ if (!response.ok) {
215
+ throw classify(Object.assign(new Error(text), { status: response.status, data: { text } }), this.classifyContext());
216
+ }
217
+ const token = JSON.parse(text).token;
218
+ if (typeof token !== 'string' || !token) {
219
+ throw new RemoteError('login', `${this.url} did not return a session token.`);
220
+ }
221
+ this.log(`signed in to ${this.url} as ${user}`);
222
+ return token;
223
+ }
224
+ classifyContext() {
225
+ return {
226
+ auth: this.config.auth.kind,
227
+ connectionTimeoutMs: this.config.connectionTimeoutMs,
228
+ requestTimeoutMs: this.config.requestTimeoutMs,
229
+ url: this.url,
230
+ };
231
+ }
232
+ }
233
+ const errorText = (text) => {
234
+ try {
235
+ const body = JSON.parse(text);
236
+ return typeof body.error === 'string' ? `: ${body.error.slice(0, 200)}` : '';
237
+ }
238
+ catch {
239
+ return '';
240
+ }
241
+ };
242
+ //# sourceMappingURL=remote.js.map