@kb-labs/mcp-app 2.96.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mcp/auth.ts","../src/mcp/output-capture.ts","../src/mcp/ui.ts","../src/mcp/authz.ts","../src/mcp/tool-builder.ts","../src/mcp/tool-router.ts","../src/mcp/request-handler.ts","../src/observability/collector.ts","../src/server.ts","../src/bootstrap.ts","../src/index.ts"],"names":["noopUI","durationMs","can","McpServer","resolveObservabilityInstanceId"],"mappings":";;;;;;;;;;;;;;;;;;;AAcA,IAAM,cAAA,GAAiB,+BAAA;AAMhB,SAAS,aAAA,GAA2B;AACzC,EAAA,MAAM,MAAA,GAAS,QAAQ,GAAA,CAAI,kBAAA;AAC3B,EAAA,IAAI,CAAC,MAAA,IAAU,OAAA,CAAQ,GAAA,CAAI,aAAa,YAAA,EAAc;AACpD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,yIAAA;AAAA,KAEF;AAAA,EACF;AACA,EAAA,OAAO,EAAE,MAAA,EAAQ,MAAA,IAAU,cAAA,EAAe;AAC5C;AAUO,SAAS,cAAc,MAAA,EAA2C;AACvE,EAAA,IAAI,WAAW,MAAA,IAAa,CAAC,YAAA,CAAa,IAAA,CAAK,MAAM,CAAA,EAAG;AACtD,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,QAAQ,MAAA,CAAO,KAAA,CAAM,QAAA,CAAS,MAAM,EAAE,IAAA,EAAK;AACjD,EAAA,OAAO,KAAA,CAAM,MAAA,GAAS,CAAA,GAAI,KAAA,GAAQ,IAAA;AACpC;AAOA,eAAsB,kBAAA,CACpB,MAAA,EACA,KAAA,EACA,SAAA,EAC6B;AAC7B,EAAA,MAAM,KAAA,GAAQ,cAAc,MAAM,CAAA;AAClC,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAI,WAAA,CAAY,KAAA,EAAO,SAAS,CAAA,CAAE,OAAO,KAAK,CAAA;AACvD;ACxCO,IAAM,UAAA,GAAa,IAAI,iBAAA,EAA4B;ACJ1D,SAAS,eAAe,KAAA,EAA+B;AACrD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,KAAA,CAAM,OAAA;AACnD;AAUO,SAAS,iBAAiB,MAAA,EAA6C;AAC5E,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,MAAM,IAAA,GAAO,CAAC,IAAA,KAAuB;AACnC,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAA,CAAO,IAAI,CAAA;AAAA,IACb,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,IACjB;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,EAAA,GAAe;AAAA,IACnB,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,SAAS,MAAA,CAAO,OAAA;AAAA,IAChB,KAAA,EAAO,CAAC,IAAA,KAAS,IAAA,CAAK,IAAI,CAAA;AAAA,IAC1B,MAAM,CAAC,OAAA,KAAY,IAAA,CAAK,CAAA,OAAA,EAAU,OAAO,CAAA,CAAE,CAAA;AAAA,IAC3C,SAAS,CAAC,OAAA,KAAY,IAAA,CAAK,CAAA,KAAA,EAAQ,OAAO,CAAA,CAAE,CAAA;AAAA,IAC5C,MAAM,CAAC,OAAA,KAAY,IAAA,CAAK,CAAA,OAAA,EAAU,OAAO,CAAA,CAAE,CAAA;AAAA,IAC3C,KAAA,EAAO,CAAC,KAAA,KAAU,IAAA,CAAK,WAAW,cAAA,CAAe,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,IACzD,OAAO,CAAC,OAAA,KAAY,IAAA,CAAK,CAAA,QAAA,EAAW,OAAO,CAAA,CAAE,CAAA;AAAA,IAC7C,OAAA,EAAS,CAAC,OAAA,KAAY;AACpB,MAAA,IAAA,CAAK,CAAA,UAAA,EAAa,OAAO,CAAA,CAAE,CAAA;AAC3B,MAAA,OAAO;AAAA,QACL,QAAQ,CAAC,CAAA,KAAM,IAAA,CAAK,CAAA,UAAA,EAAa,CAAC,CAAA,CAAE,CAAA;AAAA,QACpC,OAAA,EAAS,CAAC,CAAA,KAAM,IAAA,CAAK,QAAQ,CAAA,IAAK,EAAE,CAAA,CAAA,CAAG,OAAA,EAAS,CAAA;AAAA,QAChD,IAAA,EAAM,CAAC,CAAA,KAAM,IAAA,CAAK,UAAU,CAAA,IAAK,EAAE,CAAA,CAAA,CAAG,OAAA,EAAS,CAAA;AAAA,QAC/C,MAAM,MAAM;AAAA,QAAC;AAAA,OACf;AAAA,IACF,CAAA;AAAA,IACA,OAAO,CAAC,IAAA,KAAS,KAAK,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA;AAAA,IAC1C,MAAM,CAAC,IAAA,KAAS,KAAK,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA;AAAA,IACzC,OAAA,EAAS,MAAM,IAAA,CAAK,EAAE,CAAA;AAAA,IACtB,OAAA,EAAS,MAAM,IAAA,CAAK,KAAK,CAAA;AAAA,IACzB,KAAK,CAAC,OAAA,EAAS,UAAU,IAAA,CAAK,KAAA,GAAQ,IAAI,KAAK,CAAA;AAAA,EAAM,OAAO,KAAK,OAAO,CAAA;AAAA,IACxE,OAAA,EAAS,CAAC,OAAA,KAAY;AACpB,MAAA,IAAA,CAAK,CAAA,CAAA,EAAI,OAAA,CAAQ,KAAK,CAAA,CAAA,CAAG,CAAA;AACzB,MAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,QAAA,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,OAAO,CAAC,CAAA;AAAA,MACtC;AAAA,IACF,CAAA;AAAA,IACA,KAAA,EAAO,CAAC,KAAA,KAAU,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,KAAS,IAAA,CAAK,CAAA,OAAA,EAAK,IAAA,CAAK,KAAK,CAAA,CAAE,CAAC,CAAA;AAAA,IACjE,GAAA,EAAK,CAAC,KAAA,KAAU,IAAA,CAAK,CAAA,CAAA,EAAI,MAAM,KAAK,CAAA,EAAA,EAAK,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAAA;AAAA,IAExD,OAAA,EAAS,OAAO,OAAA,EAAS,OAAA,KAAY;AACnC,MAAA,IAAA,CAAK,CAAA,UAAA,EAAa,OAAO,CAAA,CAAE,CAAA;AAC3B,MAAA,OAAO,SAAS,YAAA,IAAgB,IAAA;AAAA,IAClC,CAAA;AAAA,IACA,MAAA,EAAQ,OAAO,OAAA,EAAS,OAAA,KAAY;AAClC,MAAA,IAAA,CAAK,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAC1B,MAAA,OAAO,SAAS,OAAA,IAAW,EAAA;AAAA,IAC7B,CAAA;AAAA,IACA,MAAA,EAAQ,OAAO,OAAA,EAAS,OAAA,KAAY;AAClC,MAAA,IAAA,CAAK,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAC1B,MAAA,OAAO,OAAA,CAAQ,CAAC,CAAA,EAAG,KAAA;AAAA,IACrB,CAAA;AAAA,IACA,WAAA,EAAa,OAAO,OAAA,EAAS,OAAA,KAAY;AACvC,MAAA,IAAA,CAAK,CAAA,cAAA,EAAiB,OAAO,CAAA,CAAE,CAAA;AAC/B,MAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,KAAK,CAAA;AAAA,IAC5D;AAAA,GACF;AAEA,EAAA,OAAO,EAAE,EAAA,EAAI,SAAA,EAAW,MAAM,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,EAAE;AACjD;ACzEO,SAAS,WAAW,IAAA,EAA6B;AACtD,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,CAAK,MAAA,EAAQ,KAAA,EAAO,CAAC,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,IAAI,CAAA,EAAE;AAC5D;AAOO,SAAS,mBAAmB,aAAA,EAA2C;AAC5E,EAAA,OAAO,aAAA,KAAkB,SAAS,UAAA,GAAa,WAAA;AACjD;ACeA,eAAsB,mBAAmB,IAAA,EAIZ;AAC3B,EAAA,OAAO,cAAA,CAAe;AAAA,IACpB,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,cAAc,IAAA,CAAK,YAAA;AAAA,IACnB,OAAO,EAAE,KAAA,EAAO,GAAA,EAAQ,OAAA,EAAS,KAAK,KAAA;AAAM,GAC7C,CAAA;AACH;AAQA,SAAS,iBAAiB,QAAA,EAA0B;AAClD,EAAA,OAAO,QAAA,CACJ,OAAA,CAAQ,IAAA,EAAM,EAAE,CAAA,CAChB,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAClB,OAAA,CAAQ,gBAAA,EAAkB,GAAG,CAAA;AAClC;AAMA,SAAS,QAAA,CAAS,UAAkB,WAAA,EAA6B;AAC/D,EAAA,OAAO,CAAA,EAAG,gBAAA,CAAiB,QAAQ,CAAC,CAAA,EAAA,EAAK,WAAA,CAAY,IAAA,EAAK,CAAE,OAAA,CAAQ,MAAA,EAAQ,GAAG,CAAC,CAAA,CAAA;AAClF;AAOA,SAAS,iBAAA,CACP,MACA,KAAA,EACiB;AACjB,EAAA,MAAM,QAAA,GAAW,KAAK,IAAA,CAAK,IAAA,GAAO,KAAA,CAAM,KAAK,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA;AAC7D,EAAA,OAAO;AAAA,IACL,eAAA,EAAiB,KAAA;AAAA,IACjB,QAAA;AAAA,IACA,EAAA,EAAI,QAAA,CAAS,QAAA,CAAS,MAAA,GAAS,CAAC,CAAA,IAAK,EAAA;AAAA,IACrC,KAAA,EAAO,QAAA,CAAS,CAAC,CAAA,IAAK,EAAA;AAAA,IACtB,UAAU,QAAA,CAAS,MAAA,IAAU,CAAA,GAAI,QAAA,CAAS,CAAC,CAAA,GAAI,MAAA;AAAA,IAC/C,QAAA,EAAU,KAAK,QAAA,IAAY,EAAA;AAAA,IAC3B,iBAAiB,IAAA,CAAK,eAAA;AAAA,IACtB,SAAS,IAAA,CAAK,OAAA;AAAA,IACd,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,eAAe,IAAA,CAAK,aAAA;AAAA,IACpB,SAAS,KAAA,CAAM,QAAA;AAAA,IACf,YAAY,KAAA,CAAM,QAAA;AAAA,IAClB,SAAS,KAAA,CAAM;AAAA,GACjB;AACF;AAOO,SAAS,WAAA,CACd,UACA,OAAA,EACW;AACX,EAAA,MAAM,QAAmB,EAAC;AAC1B,EAAA,KAAA,MAAW,KAAA,IAAS,SAAS,SAAA,EAAW;AACtC,IAAA,KAAA,MAAW,QAAQ,KAAA,CAAM,QAAA,CAAS,GAAA,EAAK,QAAA,IAAY,EAAC,EAAG;AACrD,MAAA,IAAI,CAAC,OAAA,CAAQ,IAAA,CAAK,aAAA,EAAe,KAAA,CAAM,QAAQ,CAAA,EAAG;AAChD,QAAA;AAAA,MACF;AACA,MAAA,KAAA,CAAM,IAAA,CAAK;AAAA,QACT,IAAA,EAAM,QAAA,CAAS,KAAA,CAAM,QAAA,EAAU,KAAK,IAAI,CAAA;AAAA,QACxC,aAAa,IAAA,CAAK,QAAA;AAAA,QAClB,WAAA,EAAa,qBAAA,CAAsB,iBAAA,CAAkB,IAAA,EAAM,KAAK,CAAC,CAAA;AAAA,QACjE,UAAU,KAAA,CAAM,QAAA;AAAA,QAChB,YAAY,KAAA,CAAM,UAAA;AAAA,QAClB,aAAa,IAAA,CAAK,OAAA;AAAA,QAClB,OAAA,EAAS,KAAA,CAAM,QAAA,CAAS,OAAA,IAAW,OAAA;AAAA,QACnC,eAAe,IAAA,CAAK,aAAA;AAAA,QACpB,aAAa,qBAAA,CAAsB,KAAA,CAAM,QAAA,EAAU,KAAA,EAAO,KAAK,IAAI;AAAA,OACpE,CAAA;AAAA,IACH;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT;ACjGA,SAAS,kBAAA,CAAmB,YAAoB,OAAA,EAAyB;AACvE,EAAA,MAAM,WAAW,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,OAAA;AAC1C,EAAA,OAAO,QAAA,CAAS,UAAA,CAAW,OAAO,CAAA,GAC9B,IAAA,CAAK,OAAA,CAAQ,UAAA,EAAY,QAAQ,CAAA,GACjC,IAAA,CAAK,OAAA,CAAQ,UAAA,EAAY,QAAQ,QAAQ,CAAA;AAC/C;AAGA,SAAS,uBAAuB,SAAA,EAAgD;AAC9E,EAAA,OAAO;AAAA,IACL,QAAQ,SAAA,CAAU,MAAA;AAAA,IAClB,KAAK,SAAA,CAAU,GAAA;AAAA,IACf,YAAY,SAAA,CAAU,UAAA;AAAA,IACtB,aAAa,SAAA,CAAU,WAAA;AAAA,IACvB,OAAO,SAAA,CAAU,KAAA;AAAA,IACjB,QAAQ,SAAA,CAAU,MAAA;AAAA,IAClB,SAAS,SAAA,CAAU,OAAA;AAAA,IACnB,WAAW,SAAA,CAAU,SAAA;AAAA,IACrB,UAAU,SAAA,CAAU,QAAA;AAAA,IACpB,QAAQ,SAAA,CAAU,MAAA;AAAA,IAClB,kBAAkB,SAAA,CAAU,gBAAA;AAAA,IAC5B,SAAS,SAAA,CAAU,OAAA;AAAA,IACnB,MAAM,SAAA,CAAU;AAAA,GAClB;AACF;AAWA,eAAsB,QAAA,CACpB,IAAA,EACA,IAAA,EACA,QAAA,EACA,eAAA,EACyB;AACzB,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,MAAM,SAAA,GAAY,gBAAgB,QAAQ,CAAA;AAE1C,EAAA,MAAM,QAAA,GAAW,MAAM,UAAA,CAAW,GAAA;AAAA,IAAI,KAAA;AAAA,IAAO,MAC3C,gBAAA,CAAiB;AAAA,MACf,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,eAAe,IAAA,CAAK,OAAA;AAAA,MACpB,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,WAAA,EAAa,kBAAA,CAAmB,IAAA,CAAK,UAAA,EAAY,KAAK,WAAW,CAAA;AAAA,MACjE,MAAM,EAAC;AAAA,MACP,KAAA,EAAO,IAAA;AAAA,MACP,QAAA;AAAA;AAAA;AAAA,MAGA,EAAA,EAAIA,MAAAA;AAAA,MACJ,QAAA,EAAU,uBAAuB,SAAS,CAAA;AAAA,MAC1C,iBAAA,EAAmB,SAAA;AAAA,MACnB,UAAA,EAAY,UAAU,aAAA,EAAc;AAAA,MACpC,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,MAAA,EAAQ,KAAK,WAAA,EAAa;AAAA,KAC3B;AAAA,GACH;AAEA,EAAA,OAAO,EAAE,SAAS,QAAA,KAAa,CAAA,EAAG,QAAQ,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,EAAG,QAAA,EAAS;AACvE;;;ACpFO,IAAM,kBAAA,GAAqB,GAAA;AAGlC,SAAS,UAAA,CAAW,MAAc,OAAA,EAAkC;AAClE,EAAA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,EAAG,OAAA,EAAQ;AACtD;AAOO,SAAS,cAAc,UAAA,EAA+C;AAC3E,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,OAAO,qBAAA;AAAA,EACT;AACA,EAAA,OAAO,CAAA,UAAA,EAAa,UAAA,CAAW,QAAQ,CAAA,CAAE,MAAA,CAAO,UAAU,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA,CAAA;AACxF;AAuBA,eAAsB,oBAAoB,IAAA,EAAmD;AAC3F,EAAA,MAAM,EAAE,SAAS,UAAA,EAAY,QAAA,EAAU,OAAO,SAAA,EAAW,SAAA,EAAW,QAAA,GAAW,WAAA,EAAY,GACzF,IAAA;AACF,EAAA,MAAM,EAAA,GAAK,KAAK,GAAA,EAAI;AAGpB,EAAA,MAAM,QAAA,GAAW,aAAA,CAAc,OAAA,GAAU,UAAA,GAAa,IAAI,CAAA;AAE1D,EAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,GAAA,CAAe,QAAQ,CAAA,CAAE,KAAA,CAAM,MAAM,IAAI,CAAA;AACpE,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,MAAMC,WAAAA,GAAa,IAAA,CAAK,GAAA,EAAI,GAAI,EAAA;AAChC,IAAA,SAAA,EAAW,QAAA,CAAS,gBAAA,EAAkBA,WAAAA,EAAY,IAAI,CAAA;AACtD,IAAA,SAAA,EAAW,MAAM,gBAAA,EAAkB;AAAA,MACjC,QAAA;AAAA,MACA,WAAW,MAAA,CAAO,MAAA;AAAA,MAClB,MAAA,EAAQ,IAAA;AAAA,MACR,UAAA,EAAAA;AAAA,KACD,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AACjB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,KAAA,GAAQ,UAAU,WAAA,CAAY,QAAA,CAAS,UAAS,EAAG,OAAO,IAAI,EAAC;AACrE,EAAA,MAAM,MAAM,GAAA,CAAI,QAAA,EAAU,OAAO,kBAAkB,CAAA,CAAE,MAAM,MAAM;AAAA,EAAC,CAAC,CAAA;AAEnE,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,EAAI,GAAI,EAAA;AAChC,EAAA,SAAA,EAAW,QAAA,CAAS,gBAAA,EAAkB,UAAA,EAAY,IAAI,CAAA;AACtD,EAAA,SAAA,EAAW,MAAM,gBAAA,EAAkB;AAAA,IACjC,QAAA;AAAA,IACA,WAAW,KAAA,CAAM,MAAA;AAAA,IACjB,MAAA,EAAQ,KAAA;AAAA,IACR;AAAA,GACD,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,EAAC,CAAC,CAAA;AAEjB,EAAA,OAAO,KAAA;AACT;AAuBA,eAAsB,gBAAgB,IAAA,EAAoD;AACxF,EAAA,MAAM,EAAE,MAAM,YAAA,EAAc,OAAA,EAAS,UAAU,eAAA,EAAiB,SAAA,EAAW,WAAU,GAAI,IAAA;AACzF,EAAA,MAAM,EAAA,GAAK,KAAK,GAAA,EAAI;AAEpB,EAAA,MAAM,OAAO,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,IAAI,CAAA;AACrD,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,OAAO,UAAA,CAAW,CAAA,cAAA,EAAiB,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA;AAAA,EACjD;AAKA,EAAA,IAAI,CAAC,WAAW,CAAC,OAAA,CAAQ,KAAK,aAAA,EAAe,IAAA,CAAK,QAAQ,CAAA,EAAG;AAC3D,IAAA,OAAO,UAAA,CAAW,CAAA,gBAAA,EAAmB,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA;AAAA,EACnD;AAEA,EAAA,SAAA,EAAW,MAAM,uBAAA,EAAyB;AAAA,IACxC,QAAA,EAAU,IAAA;AAAA,IACV,QAAA;AAAA,IACA,UAAU,IAAA,CAAK;AAAA,GAChB,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,EAAC,CAAC,CAAA;AAEjB,EAAA,MAAM,SAAS,MAAM,QAAA,CAAS,MAAM,IAAA,CAAK,IAAA,EAAM,UAAU,eAAe,CAAA;AAExE,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,EAAI,GAAI,EAAA;AAChC,EAAA,SAAA,EAAW,QAAA,CAAS,eAAA,EAAiB,UAAA,EAAY,MAAA,CAAO,OAAO,CAAA;AAC/D,EAAA,SAAA,EAAW,MAAM,yBAAA,EAA2B;AAAA,IAC1C,QAAA,EAAU,IAAA;AAAA,IACV,QAAA;AAAA,IACA,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,SAAS,MAAA,CAAO,OAAA;AAAA,IAChB,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,YAAA,EAAc,OAAO,MAAA,CAAO,MAAA;AAAA,IAC5B;AAAA,GACD,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,EAAC,CAAC,CAAA;AAEjB,EAAA,OAAO,UAAA,CAAW,MAAA,CAAO,MAAA,EAAQ,CAAC,OAAO,OAAO,CAAA;AAClD;AC5HO,IAAM,4BAAN,MAAgC;AAAA,EACpB,aAAa,8BAAA,EAA+B;AAAA,EAC5C,SAAA,GAAA,iBAAY,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,EAC5C,cAAA,GAAiB,CAAA;AAAA,EACjB,aAAA,GAAgB,CAAA;AAAA,EAChB,WAAA,GAAc,CAAA;AAAA,EACL,GAAA,GAAM,IAAI,uBAAA,EAAwB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMnD,SAAS,MAAA,EAA+B;AACtC,IAAA,MAAA,CAAO,OAAA,CAAQ,WAAA,EAAa,CAAC,GAAA,EAAK,QAAQ,IAAA,KAAS;AACjD,MAAA,GAAA,CAAI,cAAA,GAAiB,YAAY,GAAA,EAAI;AACrC,MAAA,IAAA,CAAK,cAAA,EAAA;AACL,MAAA,IAAA,EAAK;AAAA,IACP,CAAC,CAAA;AAED,IAAA,MAAA,CAAO,OAAA,CAAQ,YAAA,EAAc,CAAC,GAAA,EAAK,OAAO,IAAA,KAAS;AACjD,MAAA,MAAM,QAAQ,GAAA,CAAI,cAAA;AAClB,MAAA,MAAM,aAAa,KAAA,IAAS,IAAA,GAAO,WAAA,CAAY,GAAA,KAAQ,KAAA,GAAQ,CAAA;AAC/D,MAAA,IAAA,CAAK,iBAAiB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,iBAAiB,CAAC,CAAA;AACzD,MAAA,IAAA,CAAK,aAAA,EAAA;AACL,MAAA,IAAI,KAAA,CAAM,cAAc,GAAA,EAAK;AAAE,QAAA,IAAA,CAAK,WAAA,EAAA;AAAA,MAAe;AAEnD,MAAA,MAAM,KAAA,GAAA,CAAS,IAAI,YAAA,EAAc,GAAA,IAAO,IAAI,GAAA,EAAK,OAAA,CAAQ,WAAW,EAAE,CAAA;AACtE,MAAA,IAAA,CAAK,GAAA,CAAI,eAAA;AAAA,QAAgB,CAAA,KAAA,EAAQ,GAAA,CAAI,MAAM,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA;AAAA,QAAI,UAAA;AAAA,QACtD,KAAA,CAAM,UAAA,IAAc,GAAA,GAAM,OAAA,GAAU;AAAA,OAAI;AAC1C,MAAA,IAAA,EAAK;AAAA,IACP,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAA,CAAS,IAAA,EAAoB,UAAA,EAAoB,EAAA,EAAmB;AAClE,IAAA,IAAA,CAAK,IAAI,eAAA,CAAgB,IAAA,EAAM,UAAA,EAAY,EAAA,GAAK,OAAO,OAAO,CAAA;AAAA,EAChE;AAAA;AAAA,EAIA,aAAA,CAAc,eAAwB,SAAA,EAAmB;AACvD,IAAA,OAAO,kCAAA,CAAmC;AAAA,MACxC,MAAA,EAAQ,oBAAA;AAAA,MACR,eAAA,EAAiB,KAAA;AAAA,MACjB,SAAA,EAAW,YAAA;AAAA,MACX,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,WAAA,EAAa,YAAA;AAAA,MACb,OAAA,EAAS,OAAA,CAAQ,GAAA,CAAI,mBAAA,IAAuB,OAAA;AAAA,MAC5C,WAAA,EAAa,OAAA,CAAQ,GAAA,CAAI,QAAA,IAAY,aAAA;AAAA,MACrC,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,UAAA,EAAY,YAAA;AAAA,MACZ,cAAc,EAAC;AAAA,MACf,eAAA,EAAiB,UAAA;AAAA,MACjB,cAAA,EAAgB,uBAAA;AAAA,MAChB,YAAA,EAAc,CAAC,aAAA,EAAe,kBAAA,EAAoB,gBAAgB,CAAA;AAAA,MAClE,cAAA,EAAgB;AAAA,QACd,mBAAA;AAAA,QACA,yBAAA;AAAA,QACA,2BAAA;AAAA,QACA,qBAAA;AAAA,QACA,mBAAA;AAAA,QACA,yBAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,IAAA,EAAM,EAAE,SAAA,EAAW,aAAA;AAAc,KAClC,CAAA;AAAA,EACH;AAAA,EAEA,WAAA,CAAY,aAAA,EAAwB,SAAA,EAAmB,aAAA,EAAuB;AAC5E,IAAA,MAAM,GAAA,GAAM,QAAQ,WAAA,EAAY;AAChC,IAAA,OAAO,gCAAA,CAAiC;AAAA,MACtC,MAAA,EAAQ,oBAAA;AAAA,MACR,eAAA,EAAiB,KAAA;AAAA,MACjB,SAAA,EAAW,YAAA;AAAA,MACX,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,UAAA,EAAA,iBAAY,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MACnC,MAAA,EAAQ,gBAAiB,SAAA,GAAuB,UAAA;AAAA,MAChD,SAAA,EAAW,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,QAAQ,CAAA;AAAA,MACtC,UAAA,EAAY,YAAA;AAAA,MACZ,eAAA,EAAiB,UAAA;AAAA,MACjB,YAAA,EAAc,CAAC,aAAA,EAAe,kBAAA,EAAoB,gBAAgB,CAAA;AAAA,MAClE,QAAA,EAAU;AAAA,QACR,UAAU,GAAA,CAAI,GAAA;AAAA,QACd,eAAe,GAAA,CAAI,QAAA;AAAA,QACnB,kBAAkB,IAAA,CAAK;AAAA,OACzB;AAAA,MACA,MAAA,EAAQ;AAAA,QACN;AAAA,UACE,EAAA,EAAI,UAAA;AAAA,UACJ,MAAA,EAAS,gBAAgB,IAAA,GAAO,MAAA;AAAA,UAChC,OAAA,EAAS,aAAA,GAAgB,CAAA,EAAG,SAAS,CAAA,aAAA,CAAA,GAAkB;AAAA,SACzD;AAAA,QACA;AAAA,UACE,EAAA,EAAI,WAAA;AAAA,UACJ,MAAA,EAAQ,IAAA;AAAA,UACR,OAAA,EAAS,QAAQ,aAAa,CAAA;AAAA;AAChC,OACF;AAAA,MACA,aAAA,EAAe,IAAA,CAAK,GAAA,CAAI,gBAAA,CAAiB,CAAC;AAAA,KAC3C,CAAA;AAAA,EACH;AAAA,EAEA,wBAAwB,SAAA,EAA2B;AACjD,IAAA,MAAM,GAAA,GAAM,QAAQ,WAAA,EAAY;AAChC,IAAA,MAAM,KAAA,GAAkB;AAAA,MACtB,8CAAA;AAAA,MACA,CAAA,kBAAA,EAAqB,IAAI,GAAG,CAAA,CAAA;AAAA,MAC5B,mDAAA;AAAA,MACA,CAAA,wBAAA,EAA2B,IAAI,QAAQ,CAAA,CAAA;AAAA,MACvC,yDAAA;AAAA,MACA,0BAA0B,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,MAAA,EAAQ,CAAC,CAAA,CAAA;AAAA,MACtD,2EAAA;AAAA,MACA,mBAAmB,SAAS,CAAA,CAAA;AAAA,MAC5B,6DAAA;AAAA,MACA,CAAA,oBAAA,EAAuB,KAAK,aAAa,CAAA,CAAA;AAAA,MACzC,2DAAA;AAAA,MACA,CAAA,kBAAA,EAAqB,KAAK,WAAW,CAAA,CAAA;AAAA,MACrC,gEAAA;AAAA,MACA,CAAA,0BAAA,EAA6B,KAAK,cAAc,CAAA,CAAA;AAAA,MAChD,GAAG,IAAA,CAAK,GAAA,CAAI,cAAA;AAAe,KAC7B;AACA,IAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,EACxB;AACF,CAAA;;;AC5FO,IAAM,kBAAN,MAAsB;AAAA,EACV,IAAA;AAAA,EACA,eAAA;AAAA,EACA,SAAA;AAAA,EACT,GAAA;AAAA,EACA,QAAA;AAAA,EAER,YAAY,IAAA,EAA8B;AACxC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAA,CAAK,eAAA,KAAoB,MAAM,IAAA,CAAK,QAAA,CAAA;AAC3D,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,yBAAA,EAA0B;AAAA,EACjD;AAAA;AAAA,EAGQ,WAAW,QAAA,EAA6B;AAC9C,IAAA,OAAO,CAAC,aAAA,EAAe,QAAA,KACrBC,GAAAA,CAAI,IAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,QAAA,EAAU,kBAAA,CAAmB,aAAa,CAAA,EAAG,QAAQ,CAAA;AAAA,EAC/E;AAAA,EAEA,IAAY,SAAA,GAAoB;AAC9B,IAAA,OACE,IAAA,CAAK,QAAA,EACD,QAAA,EAAS,CACV,UAAU,OAAA,CAAQ,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,GAAA,EAAK,QAAA,IAAY,EAAE,EAAE,MAAA,IAAU,CAAA;AAAA,EAE1E;AAAA,EAEA,MAAM,KAAA,GAAyB;AAE7B,IAAA,IAAA,CAAK,QAAA,GAAW,MAAM,kBAAA,CAAmB;AAAA,MACvC,IAAA,EAAM,KAAK,IAAA,CAAK,WAAA;AAAA,MAChB,YAAA,EAAc,KAAK,IAAA,CAAK,YAAA;AAAA,MACxB,KAAA,EAAO,KAAK,IAAA,CAAK;AAAA,KAClB,CAAA;AAED,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,qBAAA,IAAyB,YAAA;AAItD,IAAA,MAAM,oBAAA,GAAmD;AAAA,MACvD,UAAU,CAAC,MAAA,KAA4B,IAAA,CAAK,SAAA,CAAU,SAAS,MAAM,CAAA;AAAA,MACrE,aAAA,EAAe,MAAM,IAAA,CAAK,SAAA,CAAU,aAAA,CAAc,CAAC,CAAC,IAAA,CAAK,QAAA,EAAU,IAAA,CAAK,SAAS,CAAA;AAAA,MACjF,WAAA,EAAa,MAAM,IAAA,CAAK,SAAA,CAAU,WAAA,CAAY,CAAC,CAAC,IAAA,CAAK,QAAA,EAAU,IAAA,CAAK,SAAA,EAAW,QAAQ,CAAA;AAAA,MACvF,yBAAyB,CAAC,OAAA,KAAoB,KAAK,SAAA,CAAU,uBAAA,CAAwB,KAAK,SAAS;AAAA,KACrG;AAEA,IAAA,IAAA,CAAK,GAAA,GAAM,MAAM,kBAAA,CAAmB;AAAA,MAClC,SAAA,EAAW,YAAA;AAAA,MACX,MAAA,EAAQ,KAAK,IAAA,CAAK,MAAA;AAAA,MAClB,aAAA,EAAe,oBAAA;AAAA,MACf,UAAA,EAAY,OAAO,EAAE,KAAA,EAAO,CAAC,CAAC,IAAA,CAAK,QAAA,EAAU,OAAA,EAAS,YAAA,EAAa,CAAA;AAAA,MACnE,cAAA,EAAgB,OAAO,MAAA,KAAW,IAAA,CAAK,kBAAkB,MAAM;AAAA,KAChE,CAAA;AAED,IAAA,MAAM,gBAAgB,gBAAA,CAAiB,IAAA,CAAK,KAAK,IAAA,EAAM,IAAA,CAAK,KAAK,IAAI,CAAA;AACrE,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,GAAA,CAAI,OAAO,aAAa,CAAA;AAEnD,IAAA,IAAA,CAAK,KAAK,MAAA,CAAO,IAAA,CAAK,sBAAA,EAAwB,EAAE,SAAS,CAAA;AACzD,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEA,MAAM,IAAA,GAAsB;AAC1B,IAAA,MAAM,IAAA,CAAK,KAAK,KAAA,EAAM;AAAA,EACxB;AAAA,EAEA,MAAc,kBAAkB,MAAA,EAAwC;AACtE,IAAA,MAAM,EAAE,KAAA,EAAO,MAAA,EAAQ,SAAA,KAAc,IAAA,CAAK,IAAA;AAO1C,IAAA,MAAA,CAAO,GAAA,CAAI,aAAA,EAAe,OAAO,OAAA,EAAS,KAAA,KAAU;AAClD,MAAA,KAAA,CACG,MAAA,CAAO,6BAAA,EAA+B,GAAG,CAAA,CACzC,MAAA,CAAO,gCAAgC,oBAAoB,CAAA,CAC3D,MAAA,CAAO,8BAAA,EAAgC,6CAA6C,CAAA;AAGvF,MAAA,IAAI,OAAA,CAAQ,WAAW,SAAA,EAAW;AAChC,QAAA,OAAO,KAAA,CAAM,IAAA,CAAK,GAAG,CAAA,CAAE,IAAA,EAAK;AAAA,MAC9B;AAEA,MAAA,MAAM,SAAA,GAAY,QAAQ,QAAA,IAAY,MAAA;AAGtC,MAAA,MAAM,UAAA,GAAa,QAAQ,OAAA,CAAQ,aAAA;AACnC,MAAA,MAAM,UAAU,MAAM,kBAAA,CAAmB,UAAA,EAAY,KAAA,EAAO,SAAS,CAAA,CAAE,KAAA;AAAA,QACrE,MAAM;AAAA,OACR;AACA,MAAA,MAAM,QAAA,GAAW,SAAS,WAAA,IAAe,WAAA;AAIzC,MAAA,MAAM,UAAU,OAAA,GAAU,IAAA,CAAK,WAAW,UAAA,CAAW,OAAO,CAAC,CAAA,GAAI,IAAA;AAIjE,MAAA,MAAM,YAAA,GAAe,MAAM,mBAAA,CAAoB;AAAA,QAC7C,OAAA;AAAA,QACA,UAAA;AAAA,QACA,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,KAAA;AAAA,QACA,SAAA,EAAW,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,SAAA;AAAA,QAC9B,WAAW,IAAA,CAAK,SAAA;AAAA,QAChB;AAAA,OACD,CAAA;AAGD,MAAA,MAAM,MAAM,IAAIC,MAAA;AAAA,QACd,EAAE,IAAA,EAAM,SAAA,EAAW,OAAA,EAAS,OAAA,EAAQ;AAAA,QACpC,EAAE,YAAA,EAAc,EAAE,KAAA,EAAO,IAAG;AAAE,OAChC;AAEA,MAAA,GAAA,CAAI,iBAAA,CAAkB,wBAAwB,aAAa;AAAA,QACzD,KAAA,EAAO,YAAA,CAAa,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,UAC9B,MAAM,CAAA,CAAE,IAAA;AAAA,UACR,aAAa,CAAA,CAAE,WAAA;AAAA,UACf,aAAa,CAAA,CAAE;AAAA,SACjB,CAAE;AAAA,OACJ,CAAE,CAAA;AAEF,MAAA,GAAA,CAAI,iBAAA;AAAA,QAAkB,qBAAA;AAAA,QAAuB,OAAO,EAAE,MAAA,EAAO,KAC3D,eAAA,CAAgB;AAAA,UACd,MAAM,MAAA,CAAO,IAAA;AAAA,UACb,IAAA,EAAO,MAAA,CAAO,SAAA,IAAa,EAAC;AAAA,UAC5B,YAAA;AAAA,UACA,OAAA;AAAA,UACA,QAAA;AAAA,UACA,iBAAiB,IAAA,CAAK,eAAA;AAAA,UACtB,SAAA,EAAW,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,SAAA;AAAA,UAC9B,WAAW,IAAA,CAAK;AAAA,SACjB;AAAA,OACH;AAIA,MAAA,MAAM,YAAY,IAAI,6BAAA,CAA8B,EAAE,kBAAA,EAAoB,QAAW,CAAA;AACrF,MAAA,IAAI;AACF,QAAA,MAAM,GAAA,CAAI,QAAQ,SAAS,CAAA;AAC3B,QAAA,MAAM,UAAU,aAAA,CAAc,OAAA,CAAQ,KAAK,KAAA,CAAM,GAAA,EAAK,QAAQ,IAAI,CAAA;AAAA,MACpE,SAAS,KAAA,EAAO;AACd,QAAA,SAAA,CAAU,KAAA,CAAM,+BAA+B,KAAc,CAAA;AAC7D,QAAA,IAAI,CAAC,KAAA,CAAM,GAAA,CAAI,WAAA,EAAa;AAC1B,UAAA,KAAA,CAAM,KAAK,GAAG,CAAA,CAAE,KAAK,EAAE,KAAA,EAAO,kBAAkB,CAAA;AAAA,QAClD;AAAA,MACF,CAAA,SAAE;AAGA,QAAA,MAAM,GAAA,CAAI,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM;AAAA,QAAC,CAAC,CAAA;AAAA,MAClC;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AACF,CAAA;;;AC9MA,eAAsB,SAAA,GAA2B;AAC/C,EAAA,MAAM,SAAA;AAAA,IACJ;AAAA,MACE,KAAA,EAAO,YAAA;AAAA,MACP,WAAA,EAAa,IAAA;AAAA,MACb,UAAA,EAAY,oBAAA;AAAA,MACZ,WAAA,EAAa,WAAA;AAAA,MACb,UAAA,EAAY,oBAAA;AAAA,MACZ,MAAM,KAAA,CAAM,EAAE,IAAA,EAAM,MAAK,EAAG;AAC1B,QAAA,MAAM,MAAA,GAAS,sBAAA,CAAuB,QAAA,CAAS,MAAA,EAAQ;AAAA,UACrD,SAAA,EAAW,YAAA;AAAA,UACX,YAAYC,8BAAAA,EAA+B;AAAA,UAC3C,UAAA,EAAY,YAAA;AAAA,UACZ,KAAA,EAAO,KAAA;AAAA,UACP,OAAA,EAAS,WAAA;AAAA,UACT,SAAA,EAAW;AAAA,SACZ,CAAA;AAED,QAAA,MAAA,CAAO,KAAK,iCAAiC,CAAA;AAE7C,QAAA,MAAM,WAAA,GAAc,cAAA,EAAe,IAAK,OAAA,CAAQ,GAAA,EAAI;AACpD,QAAA,MAAM,eAAe,eAAA,EAAgB;AAErC,QAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAM,aAAA,CAAc,EAAE,CAAA;AAEzC,QAAA,MAAM,MAAA,GAAS,IAAI,eAAA,CAAgB;AAAA,UACjC,IAAA;AAAA,UACA,IAAA;AAAA,UACA,MAAA;AAAA,UACA,OAAO,QAAA,CAAS,KAAA;AAAA,UAChB,QAAA;AAAA,UACA,iBAAiB,MAAM,QAAA;AAAA,UACvB,WAAA;AAAA,UACA,YAAA;AAAA,UACA,WAAW,aAAA,EAAc;AAAA,UACzB;AAAA,SACD,CAAA;AAED,QAAA,MAAM,OAAO,KAAA,EAAM;AAEnB,QAAA,OAAO,YAAY;AACjB,UAAA,MAAM,OAAO,IAAA,EAAK;AAAA,QACpB,CAAA;AAAA,MACF;AAAA,KACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,OAAO,OAAO,QAAA,KAAa;AACzB,MAAA,MAAM,sBAAA,CAAuB;AAAA,QAC3B,KAAA;AAAA,QACA,QAAA;AAAA,QACA,UAAA,EAAY,CAAC,SAAA,KAAsB;AACjC,UAAA,MAAM,KAAA,GAAQ,WAAW,QAAA,EAAS;AAClC,UAAA,OAAO,KAAA,GAAQ,iBAAiB,CAAC,CAAA,KAAM,MAAM,IAAA,CAAK,CAAC,CAAC,CAAA,CAAE,EAAA,GAAKJ,MAAAA;AAAA,QAC7D,CAAA;AAAA,QACA,cAAc,gBAAA;AAAiB,OAChC,CAAA;AACD,MAAA,OAAO,QAAA;AAAA,IACT;AAAA,GACF;AACF;;;ACtEA,SAAA,EAAU,CAAE,KAAA,CAAM,CAAC,KAAA,KAAU;AAC3B,EAAA,OAAA,CAAQ,KAAA,CAAM,+BAA+B,KAAK,CAAA;AAClD,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB,CAAC,CAAA","file":"index.js","sourcesContent":["/**\n * MCP authentication — Bearer token verification against the shared gateway\n * JWT secret. Authorization (which tools an identity may use) lives in authz.ts,\n * routed through the platform PDP.\n */\n\nimport { AuthService, type JwtConfig } from '@kb-labs/gateway-auth';\nimport type { ICache } from '@kb-labs/core-platform';\nimport type { AuthContext } from '@kb-labs/gateway-contracts';\n\n/**\n * Insecure development fallback. Must never be used in production — loadJwtConfig\n * throws when NODE_ENV=production and no real secret is configured.\n */\nconst DEV_JWT_SECRET = 'dev-insecure-secret-change-me';\n\n/**\n * Load the JWT config from the environment. Uses the same GATEWAY_JWT_SECRET as\n * the gateway so tokens issued by the gateway are accepted by the MCP daemon.\n */\nexport function loadJwtConfig(): JwtConfig {\n const secret = process.env.GATEWAY_JWT_SECRET;\n if (!secret && process.env.NODE_ENV === 'production') {\n throw new Error(\n 'GATEWAY_JWT_SECRET must be set in production. ' +\n 'Generate one with: node -e \"console.log(require(\\'crypto\\').randomBytes(64).toString(\\'hex\\'))\"',\n );\n }\n return { secret: secret ?? DEV_JWT_SECRET };\n}\n\n/**\n * Extract a Bearer token from an Authorization header, or null.\n *\n * Parsing avoids overlapping quantifiers (e.g. `\\s+(.+)`) on the\n * attacker-controlled header: an anchored single-`\\s` scheme check is linear,\n * then the remainder is sliced and trimmed. This sidesteps the polynomial\n * ReDoS that `/^Bearer\\s+(.+)$/` exhibits on `\"Bearer\" + \" \".repeat(n)`.\n */\nexport function extractBearer(header: string | undefined): string | null {\n if (header === undefined || !/^bearer\\s/i.test(header)) {\n return null;\n }\n const token = header.slice('bearer'.length).trim();\n return token.length > 0 ? token : null;\n}\n\n/**\n * Resolve a verified AuthContext from an Authorization header.\n * Returns null for anonymous (no/invalid token) — the caller treats this as\n * \"no tools, no execution\".\n */\nexport async function resolveAuthContext(\n header: string | undefined,\n cache: ICache,\n jwtConfig: JwtConfig,\n): Promise<AuthContext | null> {\n const token = extractBearer(header);\n if (!token) {\n return null;\n }\n return new AuthService(cache, jwtConfig).verify(token);\n}\n","/**\n * AsyncLocalStorage singleton for per-call plugin output capture.\n *\n * bootstrap.ts wires a uiProvider that reads from this store so each\n * callTool() invocation captures plugin UI output into its own isolated\n * buffer — concurrent calls never mix their output.\n *\n * Usage:\n * // producer (callTool):\n * const lines: string[] = [];\n * await callOutput.run(lines, () => executeCommandV3(...));\n * return lines.join('\\n');\n *\n * // consumer (uiProvider in bootstrap):\n * uiProvider: () => {\n * const lines = callOutput.getStore();\n * return lines ? createBufferedUI((s) => lines.push(s)).ui : noopUI;\n * }\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\nexport const callOutput = new AsyncLocalStorage<string[]>();\n","/**\n * BufferedUI — a UIFacade implementation that captures all output into a string\n * buffer instead of writing to a TTY. Used to run plugin commands headlessly and\n * return their textual output as an MCP tool result.\n *\n * Output methods append to the buffer. Interactive methods return safe,\n * non-blocking defaults (mirroring the canonical noopUI) because an MCP tool call\n * is non-interactive — there is no human to answer a prompt.\n */\n\nimport { noopUI } from '@kb-labs/plugin-contracts';\nimport type { UIFacade } from '@kb-labs/plugin-contracts';\n\nexport interface BufferedUI {\n ui: UIFacade;\n getOutput: () => string;\n}\n\nfunction stringifyError(error: Error | string): string {\n return typeof error === 'string' ? error : error.message;\n}\n\n/**\n * Create a buffered UI facade.\n *\n * @param pushFn - Optional external push function. When provided (e.g. from the\n * AsyncLocalStorage-backed uiProvider in bootstrap), output is appended there\n * and `getOutput()` returns an empty string. When omitted, output is stored in\n * an internal array and available via `getOutput()`.\n */\nexport function createBufferedUI(pushFn?: (text: string) => void): BufferedUI {\n const lines: string[] = [];\n const push = (text: string): void => {\n if (pushFn) {\n pushFn(text);\n } else {\n lines.push(text);\n }\n };\n\n const ui: UIFacade = {\n colors: noopUI.colors,\n symbols: noopUI.symbols,\n write: (text) => push(text),\n info: (message) => push(`[info] ${message}`),\n success: (message) => push(`[ok] ${message}`),\n warn: (message) => push(`[warn] ${message}`),\n error: (error) => push(`[error] ${stringifyError(error)}`),\n debug: (message) => push(`[debug] ${message}`),\n spinner: (message) => {\n push(`[spinner] ${message}`);\n return {\n update: (m) => push(`[spinner] ${m}`),\n succeed: (m) => push(`[ok] ${m ?? ''}`.trimEnd()),\n fail: (m) => push(`[fail] ${m ?? ''}`.trimEnd()),\n stop: () => {},\n };\n },\n table: (data) => push(JSON.stringify(data)),\n json: (data) => push(JSON.stringify(data)),\n newline: () => push(''),\n divider: () => push('---'),\n box: (content, title) => push(title ? `[${title}]\\n${content}` : content),\n sideBox: (options) => {\n push(`[${options.title}]`);\n if (options.summary) {\n push(JSON.stringify(options.summary));\n }\n },\n chain: (items) => items.forEach((item) => push(`• ${item.title}`)),\n log: (entry) => push(`[${entry.level}] ${entry.message}`),\n // Non-interactive defaults — same semantics as noopUI.\n confirm: async (message, options) => {\n push(`[confirm] ${message}`);\n return options?.defaultValue ?? true;\n },\n prompt: async (message, options) => {\n push(`[prompt] ${message}`);\n return options?.default ?? '';\n },\n select: async (message, choices) => {\n push(`[select] ${message}`);\n return choices[0]?.value as never;\n },\n multiSelect: async (message, choices) => {\n push(`[multiSelect] ${message}`);\n return choices.filter((c) => c.checked).map((c) => c.value) as never;\n },\n };\n\n return { ui, getOutput: () => lines.join('\\n') };\n}\n","/**\n * MCP authorization — decides which tools an authenticated identity may see and\n * call. Routed through the platform Policy Decision Point (@kb-labs/core-policy).\n *\n * The platform does not yet issue granular per-tool scopes in JWTs, and the PDP\n * is a permit-all stub by default. This module is the single seam where that\n * changes: when the platform resolves a real policy and/or richer identities,\n * only the policy passed to createPermits and the identity mapping here need to\n * evolve — the tool-builder and server code stay unchanged.\n */\n\nimport { can, type Policy, type Identity } from '@kb-labs/core-policy';\nimport type { AuthContext } from '@kb-labs/gateway-contracts';\n\n/**\n * Map a verified AuthContext to a policy Identity. Roles are derived from the\n * token's type and tier — the only identity signals the platform issues today.\n */\nexport function toIdentity(auth: AuthContext): Identity {\n return { user: auth.userId, roles: [auth.type, auth.tier] };\n}\n\n/**\n * Map a command's operationType to a PDP action verb. Read commands require the\n * read action; everything that can mutate or execute requires the write action.\n * Unknown/undefined operation types fail safe to write (the stronger gate).\n */\nexport function actionForOperation(operationType: string | undefined): string {\n return operationType === 'read' ? 'mcp.read' : 'mcp.write';\n}\n\n/** Predicate: may this identity use a command of the given operationType on the given plugin? */\nexport type Permits = (operationType: string | undefined, resource: string) => boolean;\n\n/**\n * Build a permits predicate bound to a resolved policy and identity. This is the\n * authorization seam — the policy is supplied by the daemon (permit-all stub\n * today, platform-resolved later).\n */\nexport function createPermits(policy: Policy, auth: AuthContext): Permits {\n const identity = toIdentity(auth);\n return (operationType, resource) =>\n can(policy, identity, actionForOperation(operationType), resource);\n}\n","/**\n * Tool builder — turns plugin manifests into MCP tool descriptors with ZERO\n * hardcoding. Every CLI command declared in a plugin manifest becomes a callable\n * MCP tool, gated by the authorization predicate (Permits) routed through the PDP.\n *\n * Two responsibilities, two functions:\n * - createToolRegistry(): called ONCE at daemon startup; builds the entity\n * registry whose snapshot is the source of available commands.\n * - filterTools(): pure, cheap, per-request; projects a snapshot down to the\n * tools the calling identity is permitted to use.\n */\n\nimport { createRegistry } from '@kb-labs/core-registry';\nimport { generateCommandSchema } from '@kb-labs/cli-commands';\nimport { getHandlerPermissions } from '@kb-labs/plugin-contracts';\nimport type { ICache } from '@kb-labs/core-platform';\nimport type {\n IEntityRegistry,\n RegistrySnapshot,\n RegistrySnapshotManifestEntry,\n} from '@kb-labs/core-registry';\nimport type { CliCommandDecl, PermissionSpec } from '@kb-labs/plugin-contracts';\nimport type { CommandManifest } from '@kb-labs/cli-commands';\nimport type { Permits } from './authz.js';\n\n/** A single plugin command exposed as an MCP tool, with everything needed to execute it. */\nexport interface McpTool {\n /** Namespaced, MCP-safe name: `${pluginId}__${command_path_with_underscores}`. */\n name: string;\n description: string;\n inputSchema: object;\n pluginId: string;\n pluginRoot: string;\n handlerPath: string;\n version: string;\n operationType: string | undefined;\n /** Handler permissions, propagated to executeCommandV3 for governance. */\n permissions: PermissionSpec;\n}\n\n/**\n * Build and initialize the entity registry. Called ONCE at daemon startup; the\n * returned registry's snapshot() feeds filterTools() on every request.\n */\nexport async function createToolRegistry(opts: {\n root: string;\n platformRoot?: string;\n cache: ICache;\n}): Promise<IEntityRegistry> {\n return createRegistry({\n root: opts.root,\n platformRoot: opts.platformRoot,\n cache: { ttlMs: 60_000, adapter: opts.cache },\n });\n}\n\n/**\n * Make a plugin ID safe for use in MCP tool names.\n * Strips the leading `@` from scoped npm packages and replaces `/` with `-`.\n * Example: \"@kb-labs/policy\" → \"kb-labs-policy\", \"my-plugin\" → \"my-plugin\".\n * Case is preserved because plugin IDs like \"pluginA\" are valid non-scoped names.\n */\nfunction sanitizePluginId(pluginId: string): string {\n return pluginId\n .replace(/^@/, '') // strip leading @\n .replace(/\\//g, '-') // replace / with -\n .replace(/[^a-zA-Z0-9-]/g, '-'); // replace any other unsafe chars\n}\n\n/**\n * Build a collision-safe MCP tool name: `{pluginId}__{command_path}`.\n * The plugin segment is sanitized so npm scope chars (@, /) are removed.\n */\nfunction toolName(pluginId: string, commandPath: string): string {\n return `${sanitizePluginId(pluginId)}__${commandPath.trim().replace(/\\s+/g, '_')}`;\n}\n\n/**\n * Adapt a manifest CLI command declaration into the CommandManifest shape that\n * generateCommandSchema consumes. Only the fields the schema generator reads are\n * meaningful here; loader is intentionally absent (schema generation never runs it).\n */\nfunction toCommandManifest(\n decl: CliCommandDecl,\n entry: RegistrySnapshotManifestEntry,\n): CommandManifest {\n const segments = decl.path.trim().split(/\\s+/).filter(Boolean);\n return {\n manifestVersion: '1.0',\n segments,\n id: segments[segments.length - 1] ?? '',\n group: segments[0] ?? '',\n subgroup: segments.length >= 3 ? segments[1] : undefined,\n describe: decl.describe ?? '',\n longDescription: decl.longDescription,\n aliases: decl.aliases,\n category: decl.category,\n flags: decl.flags,\n examples: decl.examples,\n operationType: decl.operationType,\n package: entry.pluginId,\n manifestV2: entry.manifest,\n pkgRoot: entry.pluginRoot,\n };\n}\n\n/**\n * Project a registry snapshot down to the MCP tools the identity may use.\n * Pure and cheap — safe to call per request. Authorization is delegated entirely\n * to the supplied Permits predicate (PDP seam).\n */\nexport function filterTools(\n snapshot: Pick<RegistrySnapshot, 'manifests'>,\n permits: Permits,\n): McpTool[] {\n const tools: McpTool[] = [];\n for (const entry of snapshot.manifests) {\n for (const decl of entry.manifest.cli?.commands ?? []) {\n if (!permits(decl.operationType, entry.pluginId)) {\n continue;\n }\n tools.push({\n name: toolName(entry.pluginId, decl.path),\n description: decl.describe,\n inputSchema: generateCommandSchema(toCommandManifest(decl, entry)),\n pluginId: entry.pluginId,\n pluginRoot: entry.pluginRoot,\n handlerPath: decl.handler,\n version: entry.manifest.version ?? '0.0.0',\n operationType: decl.operationType,\n permissions: getHandlerPermissions(entry.manifest, 'cli', decl.path),\n });\n }\n }\n return tools;\n}\n","/**\n * Tool router — executes a resolved McpTool by routing through the same V3\n * command pipeline the CLI uses (executeCommandV3). Plugin output is captured\n * via the platform's uiProvider mechanism:\n *\n * bootstrap.ts wires an AsyncLocalStorage-backed uiProvider to the execution\n * backend. callTool() activates the per-call context via callOutput.run();\n * the backend calls uiProvider() → createBufferedUI(push) where push appends\n * to the call-local buffer. Concurrent calls are fully isolated.\n *\n * Multi-tenancy seam: callTool never touches a global platform directly. It\n * resolves the PlatformContainer through `resolvePlatform(tenantId)`. Today that\n * returns the single global container; when the platform gains per-tenant\n * isolation, only the resolver changes — this module stays untouched.\n */\n\nimport path from 'node:path';\nimport { executeCommandV3 } from '@kb-labs/cli-runtime';\nimport { noopUI } from '@kb-labs/plugin-contracts';\nimport type { PlatformContainer } from '@kb-labs/core-runtime';\nimport type { PlatformServices } from '@kb-labs/plugin-contracts';\nimport { callOutput } from './output-capture.js';\nimport type { McpTool } from './tool-builder.js';\n\nexport interface ToolCallResult {\n success: boolean;\n output: string;\n exitCode: number;\n}\n\n/** Tenant → platform container. Default returns the global container; platform overrides for isolation. */\nexport type PlatformResolver = (tenantId: string) => PlatformContainer;\n\n/**\n * Resolve a manifest handler reference (e.g. \"dist/commands/x.js\" or\n * \"commands/x.js#handler\") to an absolute path under the plugin's dist/.\n * Mirrors the CLI plugin-executor so MCP and CLI execution stay identical.\n */\nfunction resolveHandlerPath(pluginRoot: string, handler: string): string {\n const relative = handler.split('#')[0] ?? handler;\n return relative.startsWith('dist/')\n ? path.resolve(pluginRoot, relative)\n : path.resolve(pluginRoot, 'dist', relative);\n}\n\n/** Project a PlatformContainer onto the PlatformServices surface executeCommandV3 consumes. */\nfunction createPlatformServices(container: PlatformContainer): PlatformServices {\n return {\n logger: container.logger,\n llm: container.llm,\n embeddings: container.embeddings,\n vectorStore: container.vectorStore,\n cache: container.cache,\n config: container.config,\n storage: container.storage,\n analytics: container.analytics,\n eventBus: container.eventBus,\n invoke: container.invoke,\n documentDatabase: container.documentDatabase,\n kvStore: container.kvStore,\n logs: container.logs,\n };\n}\n\n/**\n * Execute an MCP tool. tenantId is propagated end-to-end (no loss); the platform\n * container is resolved through the seam so isolation is the platform's concern.\n *\n * Output capture: activates the AsyncLocalStorage context so the execution\n * backend's uiProvider can write into the call-local `lines` buffer. The `ui`\n * param passed to executeCommandV3 is unused by V3 (the backend uses uiProvider),\n * but noopUI is passed explicitly to make the intent clear.\n */\nexport async function callTool(\n tool: McpTool,\n args: Record<string, unknown>,\n tenantId: string,\n resolvePlatform: PlatformResolver,\n): Promise<ToolCallResult> {\n const lines: string[] = [];\n const container = resolvePlatform(tenantId);\n\n const exitCode = await callOutput.run(lines, () =>\n executeCommandV3({\n pluginId: tool.pluginId,\n pluginVersion: tool.version,\n pluginRoot: tool.pluginRoot,\n handlerPath: resolveHandlerPath(tool.pluginRoot, tool.handlerPath),\n argv: [],\n flags: args,\n tenantId,\n // ui is ignored by executeCommandV3 V3 (backend uses uiProvider).\n // noopUI is passed explicitly to document this intent.\n ui: noopUI,\n platform: createPlatformServices(container),\n platformContainer: container,\n socketPath: container.getSocketPath(),\n permissions: tool.permissions,\n quotas: tool.permissions?.quotas,\n }),\n );\n\n return { success: exitCode === 0, output: lines.join('\\n'), exitCode };\n}\n","/**\n * Request handler logic for the MCP endpoint, extracted from the Fastify/MCP-SDK\n * shell so every authorization and caching branch is unit-testable without\n * spinning up an HTTP server or a transport.\n *\n * server.ts wires these pure(ish) functions to the MCP SDK request handlers;\n * the SDK/transport plumbing itself is exercised by the e2e suite.\n */\n\nimport { createHash } from 'node:crypto';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ICache, IAnalytics } from '@kb-labs/core-platform';\nimport type { IEntityRegistry } from '@kb-labs/core-registry';\nimport { filterTools, type McpTool } from './tool-builder.js';\nimport { callTool, type PlatformResolver } from './tool-router.js';\nimport type { Permits } from './authz.js';\nimport type { McpObservabilityCollector } from '../observability/collector.js';\n\n/** How long a per-identity tool listing stays cached. */\nexport const TOOLS_CACHE_TTL_MS = 60_000;\n\n/** Build a text-only MCP tool result (the only content shape this daemon emits). */\nfunction textResult(text: string, isError: boolean): CallToolResult {\n return { content: [{ type: 'text', text }], isError };\n}\n\n/**\n * Cache key for an identity's visible tool list. Authenticated identities are\n * keyed by a hash of their Authorization header (per-token, per-tenant\n * isolation); everything else shares the single anonymous bucket.\n */\nexport function toolsCacheKey(authHeader: string | null | undefined): string {\n if (!authHeader) {\n return 'mcp:tools:anonymous';\n }\n return `mcp:tools:${createHash('sha256').update(authHeader).digest('hex').slice(0, 16)}`;\n}\n\nexport interface ResolveVisibleToolsArgs {\n /** Identity-bound authorization predicate, or null for anonymous callers. */\n permits: Permits | null;\n /** Raw Authorization header — only used to derive the per-token cache key. */\n authHeader: string | null | undefined;\n registry: IEntityRegistry;\n cache: ICache;\n /** Platform analytics — emits mcp.tools.list event. Optional for tests. */\n analytics?: IAnalytics | null;\n /** Observability collector — records mcp.tools.list operation. Optional for tests. */\n collector?: McpObservabilityCollector;\n /** Tenant ID for analytics context. */\n tenantId?: string;\n}\n\n/**\n * Resolve the tools an identity may see. Cached per identity for 60s; the cache\n * is a LISTING optimization only — it is never the authority for execution\n * (executeToolCall re-checks the live policy). Anonymous callers (permits=null)\n * always get an empty list and never touch the registry.\n */\nexport async function resolveVisibleTools(args: ResolveVisibleToolsArgs): Promise<McpTool[]> {\n const { permits, authHeader, registry, cache, analytics, collector, tenantId = 'anonymous' } =\n args;\n const t0 = Date.now();\n\n // Anonymous identities share one bucket regardless of any (invalid) header.\n const cacheKey = toolsCacheKey(permits ? authHeader : null);\n\n const cached = await cache.get<McpTool[]>(cacheKey).catch(() => null);\n if (cached) {\n const durationMs = Date.now() - t0;\n collector?.recordOp('mcp.tools.list', durationMs, true);\n analytics?.track('mcp.tools.list', {\n tenantId,\n toolCount: cached.length,\n cached: true,\n durationMs,\n }).catch(() => {});\n return cached;\n }\n\n const tools = permits ? filterTools(registry.snapshot(), permits) : [];\n await cache.set(cacheKey, tools, TOOLS_CACHE_TTL_MS).catch(() => {});\n\n const durationMs = Date.now() - t0;\n collector?.recordOp('mcp.tools.list', durationMs, true);\n analytics?.track('mcp.tools.list', {\n tenantId,\n toolCount: tools.length,\n cached: false,\n durationMs,\n }).catch(() => {});\n\n return tools;\n}\n\nexport interface ExecuteToolCallArgs {\n name: string;\n args: Record<string, unknown>;\n visibleTools: McpTool[];\n /** Identity-bound predicate, or null for anonymous. */\n permits: Permits | null;\n tenantId: string;\n resolvePlatform: PlatformResolver;\n /** Platform analytics — emits mcp.tool.call events. Optional for tests. */\n analytics?: IAnalytics | null;\n /** Observability collector — records mcp.tool.call operation. Optional for tests. */\n collector?: McpObservabilityCollector;\n}\n\n/**\n * Execute a tool call. Two independent gates protect execution:\n * 1. the tool must be in the caller's visible set, and\n * 2. the LIVE policy must still permit it (re-checked here, not trusted from\n * the possibly-stale cached listing).\n * Only then is the command run via executeCommandV3.\n */\nexport async function executeToolCall(args: ExecuteToolCallArgs): Promise<CallToolResult> {\n const { name, visibleTools, permits, tenantId, resolvePlatform, analytics, collector } = args;\n const t0 = Date.now();\n\n const tool = visibleTools.find((t) => t.name === name);\n if (!tool) {\n return textResult(`Unknown tool: ${name}`, true);\n }\n\n // Authoritative gate — independent of the cached visibility list. When the\n // platform supplies a real policy, a tool that became forbidden after it was\n // cached is rejected here with no server code change.\n if (!permits || !permits(tool.operationType, tool.pluginId)) {\n return textResult(`Not authorized: ${name}`, true);\n }\n\n analytics?.track('mcp.tool.call.started', {\n toolName: name,\n tenantId,\n pluginId: tool.pluginId,\n }).catch(() => {});\n\n const result = await callTool(tool, args.args, tenantId, resolvePlatform);\n\n const durationMs = Date.now() - t0;\n collector?.recordOp('mcp.tool.call', durationMs, result.success);\n analytics?.track('mcp.tool.call.completed', {\n toolName: name,\n tenantId,\n pluginId: tool.pluginId,\n success: result.success,\n exitCode: result.exitCode,\n outputLength: result.output.length,\n durationMs,\n }).catch(() => {});\n\n return textResult(result.output, !result.success);\n}\n","/**\n * MCP Daemon observability collector.\n *\n * Mirrors the GatewayObservabilityCollector pattern: registers Fastify\n * onRequest/onResponse hooks for HTTP-level metrics, tracks domain operations\n * (mcp.tools.list, mcp.tool.call) via OperationMetricsTracker, and builds\n * the three standard observability payloads:\n *\n * /health → buildHealth() (also used for /observability/health)\n * /observability/describe → buildDescribe()\n * /metrics → renderPrometheusMetrics()\n *\n * All payloads are validated against the platform observability contract via\n * createServiceObservabilityDescribe / createServiceObservabilityHealth.\n */\n\nimport { performance } from 'node:perf_hooks';\nimport type { FastifyInstance } from 'fastify';\nimport {\n OperationMetricsTracker,\n createServiceObservabilityDescribe,\n createServiceObservabilityHealth,\n resolveObservabilityInstanceId,\n} from '@kb-labs/shared-http';\nimport type { ObservabilityCapability, CanonicalObservabilityMetric } from '@kb-labs/core-contracts';\n\n/** Domain operations tracked at the MCP level. */\nexport type McpOperation = 'mcp.tools.list' | 'mcp.tool.call';\n\nexport class McpObservabilityCollector {\n private readonly instanceId = resolveObservabilityInstanceId();\n private readonly startedAt = new Date().toISOString();\n private activeRequests = 0;\n private requestsTotal = 0;\n private errorsTotal = 0;\n private readonly ops = new OperationMetricsTracker();\n\n /**\n * Register Fastify hooks that track HTTP-level request counts and duration.\n * Must be called before routes are registered so the hooks apply to all routes.\n */\n register(server: FastifyInstance): void {\n server.addHook('onRequest', (req, _reply, done) => {\n req.kbMetricsStart = performance.now();\n this.activeRequests++;\n done();\n });\n\n server.addHook('onResponse', (req, reply, done) => {\n const start = req.kbMetricsStart;\n const durationMs = start != null ? performance.now() - start : 0;\n this.activeRequests = Math.max(0, this.activeRequests - 1);\n this.requestsTotal++;\n if (reply.statusCode >= 400) { this.errorsTotal++; }\n // Track HTTP ops in operation tracker for /metrics output.\n const route = (req.routeOptions?.url ?? req.url).replace(/[?#].*$/, '');\n this.ops.recordOperation(`http.${req.method} ${route}`, durationMs,\n reply.statusCode >= 400 ? 'error' : 'ok');\n done();\n });\n }\n\n /**\n * Record a completed domain operation. Called from request-handler after\n * each tools/list and tools/call cycle.\n */\n recordOp(name: McpOperation, durationMs: number, ok: boolean): void {\n this.ops.recordOperation(name, durationMs, ok ? 'ok' : 'error');\n }\n\n // ── Observability payload builders ──────────────────────────────────────\n\n buildDescribe(registryReady: boolean, toolCount: number) {\n return createServiceObservabilityDescribe({\n schema: 'kb.observability/1' as const,\n contractVersion: '1.0' as const,\n serviceId: 'mcp-daemon',\n instanceId: this.instanceId,\n serviceType: 'mcp-server',\n version: process.env.npm_package_version ?? '0.0.0',\n environment: process.env.NODE_ENV ?? 'development',\n startedAt: this.startedAt,\n logsSource: 'mcp-daemon',\n dependencies: [],\n metricsEndpoint: '/metrics',\n healthEndpoint: '/observability/health',\n capabilities: ['httpMetrics', 'operationMetrics', 'logCorrelation'] as ObservabilityCapability[],\n metricFamilies: [\n 'process_rss_bytes',\n 'process_heap_used_bytes',\n 'service_active_operations',\n 'http_requests_total',\n 'http_errors_total',\n 'service_operation_total',\n 'service_operation_duration_ms',\n ] as CanonicalObservabilityMetric[],\n meta: { toolCount, registryReady },\n });\n }\n\n buildHealth(registryReady: boolean, toolCount: number, executionMode: string) {\n const mem = process.memoryUsage();\n return createServiceObservabilityHealth({\n schema: 'kb.observability/1' as const,\n contractVersion: '1.0' as const,\n serviceId: 'mcp-daemon',\n instanceId: this.instanceId,\n observedAt: new Date().toISOString(),\n status: registryReady ? ('healthy' as const) : ('degraded' as const),\n uptimeSec: Math.floor(process.uptime()),\n logsSource: 'mcp-daemon',\n metricsEndpoint: '/metrics',\n capabilities: ['httpMetrics', 'operationMetrics', 'logCorrelation'] as ObservabilityCapability[],\n snapshot: {\n rssBytes: mem.rss,\n heapUsedBytes: mem.heapUsed,\n activeOperations: this.activeRequests,\n },\n checks: [\n {\n id: 'registry',\n status: (registryReady ? 'ok' : 'warn') as 'ok' | 'warn' | 'error',\n message: registryReady ? `${toolCount} tools loaded` : 'Registry not yet ready',\n },\n {\n id: 'execution',\n status: 'ok' as const,\n message: `mode=${executionMode}`,\n },\n ],\n topOperations: this.ops.getTopOperations(5),\n });\n }\n\n renderPrometheusMetrics(toolCount: number): string {\n const mem = process.memoryUsage();\n const lines: string[] = [\n '# HELP process_rss_bytes RSS memory in bytes',\n `process_rss_bytes ${mem.rss}`,\n '# HELP process_heap_used_bytes Heap used in bytes',\n `process_heap_used_bytes ${mem.heapUsed}`,\n '# HELP process_uptime_seconds Process uptime in seconds',\n `process_uptime_seconds ${Math.floor(process.uptime())}`,\n '# HELP mcp_tools_total Number of tools registered in the current snapshot',\n `mcp_tools_total ${toolCount}`,\n '# HELP http_requests_total Total MCP HTTP requests received',\n `http_requests_total ${this.requestsTotal}`,\n '# HELP http_errors_total Total MCP HTTP 4xx/5xx responses',\n `http_errors_total ${this.errorsTotal}`,\n '# HELP service_active_operations Currently active MCP requests',\n `service_active_operations ${this.activeRequests}`,\n ...this.ops.getMetricLines(),\n ];\n return lines.join('\\n');\n }\n}\n","/**\n * MCP Daemon HTTP server.\n *\n * Exposes a single JSON-RPC endpoint (`/api/v1/mcp`) speaking the Model Context\n * Protocol over Streamable HTTP, plus the standard platform observability endpoints:\n *\n * GET /health → McpObservabilityCollector.buildHealth()\n * GET /ready → 200/503 based on registry readiness\n * GET /metrics → Prometheus text format\n * GET /observability/describe → service identity + capabilities\n * GET /observability/health → full snapshot with checks and top operations\n *\n * Design notes:\n * - The entity registry is initialized ONCE at start() and reused for every\n * request; only the cheap, pure filterTools() runs per request.\n * - This endpoint sits in front of the gateway's auth scope (the gateway proxies\n * it as a dumb upstream), so the daemon validates the Bearer token itself via\n * the shared GATEWAY_JWT_SECRET — exactly mirroring the gateway's AuthService.\n * - Anonymous callers (no/invalid token) get an empty tool list and can never\n * reach callTool/executeCommandV3.\n * - tenantId flows end-to-end from AuthContext.namespaceId into executeCommandV3\n * via the resolvePlatform seam — ready for per-tenant isolation without code\n * changes here.\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport { Server as McpServer } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { can, type Policy, type Identity } from '@kb-labs/core-policy';\nimport type { ICache, ILogger } from '@kb-labs/core-platform';\nimport type { JwtConfig } from '@kb-labs/gateway-auth';\nimport type { PlatformContainer } from '@kb-labs/core-runtime';\nimport type { IEntityRegistry } from '@kb-labs/core-registry';\nimport { createDaemonServer, getListenOptions, type ObservabilityCollectorLike } from '@kb-labs/shared-http';\nimport { resolveAuthContext } from './mcp/auth.js';\nimport { toIdentity, actionForOperation, type Permits } from './mcp/authz.js';\nimport { createToolRegistry } from './mcp/tool-builder.js';\nimport { type PlatformResolver } from './mcp/tool-router.js';\nimport { resolveVisibleTools, executeToolCall } from './mcp/request-handler.js';\nimport { McpObservabilityCollector } from './observability/collector.js';\n\nexport interface McpDaemonServerOptions {\n port: number;\n host: string;\n logger: ILogger;\n cache: ICache;\n /** Default global platform container — used as the resolvePlatform fallback. */\n platform: PlatformContainer;\n /** Tenant → platform container seam. Defaults to always returning `platform`. */\n resolvePlatform?: PlatformResolver;\n /** Workspace root used to initialize the entity registry. */\n projectRoot: string;\n /** Platform installation root (installed mode); merges platform-level plugins. */\n platformRoot?: string;\n jwtConfig: JwtConfig;\n /** Authorization policy. Permit-all default until the platform supplies a real one. */\n policy: Policy;\n}\n\nexport class McpDaemonServer {\n private readonly opts: McpDaemonServerOptions;\n private readonly resolvePlatform: PlatformResolver;\n private readonly collector: McpObservabilityCollector;\n private app: FastifyInstance | undefined;\n private registry: IEntityRegistry | undefined;\n\n constructor(opts: McpDaemonServerOptions) {\n this.opts = opts;\n this.resolvePlatform = opts.resolvePlatform ?? (() => opts.platform);\n this.collector = new McpObservabilityCollector();\n }\n\n /** Build a per-request permits predicate bound to the identity (PDP seam). */\n private permitsFor(identity: Identity): Permits {\n return (operationType, resource) =>\n can(this.opts.policy, identity, actionForOperation(operationType), resource);\n }\n\n private get toolCount(): number {\n return (\n this.registry\n ?.snapshot()\n .manifests.flatMap((m) => m.manifest.cli?.commands ?? []).length ?? 0\n );\n }\n\n async start(): Promise<string> {\n // Initialize the registry ONCE; snapshot() is reused per request.\n this.registry = await createToolRegistry({\n root: this.opts.projectRoot,\n platformRoot: this.opts.platformRoot,\n cache: this.opts.cache,\n });\n\n const execMode = process.env.KB_MCP_EXECUTION_MODE ?? 'subprocess';\n\n // Adapter: wraps McpObservabilityCollector to match ObservabilityCollectorLike.\n // Arrow functions capture `this` so the live registry/toolCount state is always current.\n const observabilityAdapter: ObservabilityCollectorLike = {\n register: (server: FastifyInstance) => this.collector.register(server),\n buildDescribe: () => this.collector.buildDescribe(!!this.registry, this.toolCount),\n buildHealth: () => this.collector.buildHealth(!!this.registry, this.toolCount, execMode),\n renderPrometheusMetrics: (_status: string) => this.collector.renderPrometheusMetrics(this.toolCount),\n };\n\n this.app = await createDaemonServer({\n serviceId: 'mcp-daemon',\n logger: this.opts.logger,\n observability: observabilityAdapter,\n readyCheck: () => ({ ready: !!this.registry, service: 'mcp-daemon' }),\n registerRoutes: async (server) => this.registerMcpRoutes(server),\n });\n\n const listenOptions = getListenOptions(this.opts.port, this.opts.host);\n const address = await this.app.listen(listenOptions);\n\n this.opts.logger.info('MCP daemon listening', { address });\n return address;\n }\n\n async stop(): Promise<void> {\n await this.app?.close();\n }\n\n private async registerMcpRoutes(server: FastifyInstance): Promise<void> {\n const { cache, logger, jwtConfig } = this.opts;\n\n // ── MCP JSON-RPC endpoint ──────────────────────────────────────────────\n\n // CORS headers for all MCP responses (including preflight OPTIONS).\n // fastify.all() covers every method including OPTIONS, so no separate\n // fastify.options() is needed — that would cause a duplicate-route error.\n server.all('/api/v1/mcp', async (request, reply) => {\n reply\n .header('Access-Control-Allow-Origin', '*')\n .header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')\n .header('Access-Control-Allow-Headers', 'Authorization, Content-Type, Mcp-Session-Id');\n\n // Short-circuit preflight immediately — no auth or MCP processing needed.\n if (request.method === 'OPTIONS') {\n return reply.code(204).send();\n }\n\n const reqLogger = request.kbLogger ?? logger;\n\n // 1. Authenticate. Invalid/absent token → anonymous (no throw, no 401).\n const authHeader = request.headers.authorization;\n const authCtx = await resolveAuthContext(authHeader, cache, jwtConfig).catch(\n () => null,\n );\n const tenantId = authCtx?.namespaceId ?? 'anonymous';\n\n // Bind the authorization predicate to the identity once per request.\n // Anonymous callers get no predicate → they can neither list nor call tools.\n const permits = authCtx ? this.permitsFor(toIdentity(authCtx)) : null;\n\n // 2. Resolve the visible tool list (cached per identity). The cache is a\n // listing optimization ONLY — executeToolCall re-checks the live policy.\n const visibleTools = await resolveVisibleTools({\n permits,\n authHeader,\n registry: this.registry!,\n cache,\n analytics: this.opts.platform.analytics,\n collector: this.collector,\n tenantId,\n });\n\n // 3. Build a stateless per-request MCP server.\n const mcp = new McpServer(\n { name: 'kb-labs', version: '1.0.0' },\n { capabilities: { tools: {} } },\n );\n\n mcp.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: visibleTools.map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema as { type: 'object' },\n })),\n }));\n\n mcp.setRequestHandler(CallToolRequestSchema, async ({ params }) =>\n executeToolCall({\n name: params.name,\n args: (params.arguments ?? {}) as Record<string, unknown>,\n visibleTools,\n permits,\n tenantId,\n resolvePlatform: this.resolvePlatform,\n analytics: this.opts.platform.analytics,\n collector: this.collector,\n }),\n );\n\n // 4. Streamable HTTP transport (stateless). Pass Fastify's parsed body —\n // the raw stream is already consumed, so the SDK must not re-read it.\n const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });\n try {\n await mcp.connect(transport);\n await transport.handleRequest(request.raw, reply.raw, request.body);\n } catch (error) {\n reqLogger.error('MCP request handling failed', error as Error);\n if (!reply.raw.headersSent) {\n reply.code(500).send({ error: 'internal_error' });\n }\n } finally {\n // Closing may reject if the transport is already torn down — swallow it\n // so it can never surface as an unhandled rejection after the response.\n await mcp.close().catch(() => {});\n }\n });\n }\n}\n","import { platform, createServiceBootstrap, getPlatformRoot, getProjectRoot } from '@kb-labs/core-runtime';\nimport { makeAssemblyHook } from '@kb-labs/plugin-runtime';\nimport { resolvePolicy } from '@kb-labs/core-policy';\nimport { createCorrelatedLogger, resolveObservabilityInstanceId } from '@kb-labs/shared-http';\nimport { noopUI } from '@kb-labs/plugin-contracts';\nimport { runDaemon } from '@kb-labs/shared-daemon';\nimport { loadJwtConfig } from './mcp/auth.js';\nimport { callOutput } from './mcp/output-capture.js';\nimport { createBufferedUI } from './mcp/ui.js';\nimport { McpDaemonServer } from './server.js';\n\nexport async function bootstrap(): Promise<void> {\n await runDaemon(\n {\n appId: 'mcp-daemon',\n defaultPort: 7779,\n portEnvVar: 'KB_MCP_DAEMON_PORT',\n defaultHost: 'localhost',\n hostEnvVar: 'KB_MCP_DAEMON_HOST',\n async setup({ port, host }) {\n const logger = createCorrelatedLogger(platform.logger, {\n serviceId: 'mcp-daemon',\n instanceId: resolveObservabilityInstanceId(),\n logsSource: 'mcp-daemon',\n layer: 'mcp',\n service: 'bootstrap',\n operation: 'mcp-daemon.bootstrap',\n });\n\n logger.info('MCP daemon platform initialised');\n\n const projectRoot = getProjectRoot() ?? process.cwd();\n const platformRoot = getPlatformRoot();\n\n const { policy } = await resolvePolicy({});\n\n const server = new McpDaemonServer({\n port,\n host,\n logger,\n cache: platform.cache,\n platform,\n resolvePlatform: () => platform,\n projectRoot,\n platformRoot,\n jwtConfig: loadJwtConfig(),\n policy,\n });\n\n await server.start();\n\n return async () => {\n await server.stop();\n };\n },\n },\n // platformBootstrap: full init with uiProvider for callOutput ALS wiring.\n // uiProvider flows into initPlatform → createExecutionBackend so the backend\n // captures plugin output from the very start. Concurrent tool calls are\n // fully isolated — each gets its own AsyncLocalStorage slot.\n async (appId, repoRoot) => {\n await createServiceBootstrap({\n appId,\n repoRoot,\n uiProvider: (_hostType: string) => {\n const lines = callOutput.getStore();\n return lines ? createBufferedUI((s) => lines.push(s)).ui : noopUI;\n },\n assemblyHook: makeAssemblyHook(),\n });\n return platform;\n },\n );\n}\n","import { bootstrap } from './bootstrap.js';\n\n// runDaemon() (called inside bootstrap) resolves repo root via findRepoRoot().\nbootstrap().catch((error) => {\n console.error('Failed to start MCP daemon:', error);\n process.exit(1);\n});\n"]}
@@ -0,0 +1,5 @@
1
+ import { ServiceManifest } from '@kb-labs/plugin-contracts';
2
+
3
+ declare const manifest: ServiceManifest;
4
+
5
+ export { manifest as default, manifest };
@@ -0,0 +1,24 @@
1
+ // src/manifest.ts
2
+ var manifest = {
3
+ schema: "kb.service/1",
4
+ id: "mcp-daemon",
5
+ name: "MCP Daemon",
6
+ version: "1.0.0",
7
+ description: "MCP server \u2014 exposes plugin commands as tools for external agents",
8
+ runtime: {
9
+ entry: "dist/index.js",
10
+ port: 7779,
11
+ healthCheck: "/health",
12
+ socket: "/tmp/kb-${KB_SOCKET_HASH}/mcp-daemon.sock"
13
+ },
14
+ env: {
15
+ KB_MCP_DAEMON_PORT: { description: "TCP port", default: "7779" },
16
+ KB_MCP_DAEMON_HOST: { description: "Bind host", default: "localhost" },
17
+ GATEWAY_JWT_SECRET: { description: "Shared JWT secret (same value as gateway)" }
18
+ }
19
+ };
20
+ var manifest_default = manifest;
21
+
22
+ export { manifest_default as default, manifest };
23
+ //# sourceMappingURL=manifest.js.map
24
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/manifest.ts"],"names":[],"mappings":";AAEO,IAAM,QAAA,GAA4B;AAAA,EACvC,MAAA,EAAQ,cAAA;AAAA,EACR,EAAA,EAAI,YAAA;AAAA,EACJ,IAAA,EAAM,YAAA;AAAA,EACN,OAAA,EAAS,OAAA;AAAA,EACT,WAAA,EAAa,wEAAA;AAAA,EACb,OAAA,EAAS;AAAA,IACP,KAAA,EAAO,eAAA;AAAA,IACP,IAAA,EAAM,IAAA;AAAA,IACN,WAAA,EAAa,SAAA;AAAA,IACb,MAAA,EAAQ;AAAA,GACV;AAAA,EACA,GAAA,EAAK;AAAA,IACH,kBAAA,EAAoB,EAAE,WAAA,EAAa,UAAA,EAAY,SAAS,MAAA,EAAO;AAAA,IAC/D,kBAAA,EAAoB,EAAE,WAAA,EAAa,WAAA,EAAa,SAAS,WAAA,EAAY;AAAA,IACrE,kBAAA,EAAoB,EAAE,WAAA,EAAa,2CAAA;AAA4C;AAEnF;AAEA,IAAO,gBAAA,GAAQ","file":"manifest.js","sourcesContent":["import type { ServiceManifest } from '@kb-labs/plugin-contracts';\n\nexport const manifest: ServiceManifest = {\n schema: 'kb.service/1',\n id: 'mcp-daemon',\n name: 'MCP Daemon',\n version: '1.0.0',\n description: 'MCP server — exposes plugin commands as tools for external agents',\n runtime: {\n entry: 'dist/index.js',\n port: 7779,\n healthCheck: '/health',\n socket: '/tmp/kb-${KB_SOCKET_HASH}/mcp-daemon.sock',\n },\n env: {\n KB_MCP_DAEMON_PORT: { description: 'TCP port', default: '7779' },\n KB_MCP_DAEMON_HOST: { description: 'Bind host', default: 'localhost' },\n GATEWAY_JWT_SECRET: { description: 'Shared JWT secret (same value as gateway)' },\n },\n};\n\nexport default manifest;\n"]}
@@ -0,0 +1,26 @@
1
+ {
2
+ "schema": "kb.service/1",
3
+ "id": "mcp-daemon",
4
+ "name": "MCP Daemon",
5
+ "version": "1.0.0",
6
+ "description": "MCP server — exposes plugin commands as tools for external agents",
7
+ "runtime": {
8
+ "entry": "dist/index.js",
9
+ "port": 7779,
10
+ "healthCheck": "/health",
11
+ "socket": "/tmp/kb-${KB_SOCKET_HASH}/mcp-daemon.sock"
12
+ },
13
+ "env": {
14
+ "KB_MCP_DAEMON_PORT": {
15
+ "description": "TCP port",
16
+ "default": "7779"
17
+ },
18
+ "KB_MCP_DAEMON_HOST": {
19
+ "description": "Bind host",
20
+ "default": "localhost"
21
+ },
22
+ "GATEWAY_JWT_SECRET": {
23
+ "description": "Shared JWT secret (same value as gateway)"
24
+ }
25
+ }
26
+ }
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@kb-labs/mcp-app",
3
+ "version": "2.96.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "dependencies": {
10
+ "@modelcontextprotocol/sdk": "^1.29.0",
11
+ "fastify": "^5.8.5",
12
+ "@kb-labs/core-contracts": "2.96.0",
13
+ "@kb-labs/cli-commands": "2.96.0",
14
+ "@kb-labs/core-registry": "2.96.0",
15
+ "@kb-labs/core-platform": "2.96.0",
16
+ "@kb-labs/core-runtime": "2.96.0",
17
+ "@kb-labs/cli-runtime": "2.96.0",
18
+ "@kb-labs/plugin-contracts": "2.96.0",
19
+ "@kb-labs/core-sys": "2.96.0",
20
+ "@kb-labs/gateway-auth": "2.96.0",
21
+ "@kb-labs/shared-http": "2.96.0",
22
+ "@kb-labs/gateway-contracts": "2.96.0",
23
+ "@kb-labs/shared-daemon": "2.96.0",
24
+ "@kb-labs/plugin-runtime": "2.96.0",
25
+ "@kb-labs/core-policy": "2.96.0"
26
+ },
27
+ "devDependencies": {
28
+ "eslint": "^9",
29
+ "rimraf": "^6.0.1",
30
+ "tsup": "^8.5.0",
31
+ "tsx": "^4.20.5",
32
+ "typescript": "^5.6.3",
33
+ "vitest": "^3.2.6",
34
+ "@kb-labs/shared-testing-e2e": "2.96.0",
35
+ "@kb-labs/devkit": "2.96.0"
36
+ },
37
+ "kb": {
38
+ "manifest": "./dist/manifest.js"
39
+ },
40
+ "scripts": {
41
+ "build": "tsup",
42
+ "clean": "rimraf dist",
43
+ "dev": "tsx watch src/index.ts",
44
+ "lint": "eslint .",
45
+ "lint:fix": "eslint . --fix",
46
+ "start": "node dist/index.js",
47
+ "test": "vitest run",
48
+ "test:watch": "vitest",
49
+ "type-check": "tsc --noEmit"
50
+ }
51
+ }