#
tokens: 49940/50000 184/252 files (page 1/8)
lines: off (toggle) GitHub
raw markdown copy
This is page 1 of 8. Use http://codebase.md/jakedismo/master-mcp-server?page={x} to view the full context.

# Directory Structure

```
├── .env.example
├── .eslintignore
├── .eslintrc.cjs
├── .eslintrc.js
├── .gitignore
├── .prettierignore
├── .prettierrc
├── .prettierrc.json
├── CHANGELOG.md
├── config
│   ├── default.json
│   ├── development.json
│   ├── production.json
│   └── schema.json
├── config.json
├── CONTRIBUTING.md
├── debug-stdio.cjs
├── debug-stdio.js
├── deploy
│   ├── cloudflare
│   │   ├── .gitkeep
│   │   ├── README.md
│   │   └── wrangler.toml
│   ├── docker
│   │   ├── .gitkeep
│   │   ├── docker-compose.yml
│   │   ├── Dockerfile
│   │   └── entrypoint.sh
│   ├── koyeb
│   │   ├── .gitkeep
│   │   └── koyeb.yaml
│   └── README.md
├── docker-compose.yml
├── Dockerfile
├── docs
│   ├── .DS_Store
│   ├── .vitepress
│   │   ├── cache
│   │   │   └── deps
│   │   │       ├── _metadata.json
│   │   │       ├── chunk-HVR2FF6M.js
│   │   │       ├── chunk-HVR2FF6M.js.map
│   │   │       ├── chunk-P2XGSYO7.js
│   │   │       ├── chunk-P2XGSYO7.js.map
│   │   │       ├── package.json
│   │   │       ├── vitepress___@vue_devtools-api.js
│   │   │       ├── vitepress___@vue_devtools-api.js.map
│   │   │       ├── vitepress___@vueuse_core.js
│   │   │       ├── vitepress___@vueuse_core.js.map
│   │   │       ├── vitepress___@vueuse_integrations_useFocusTrap.js
│   │   │       ├── vitepress___@vueuse_integrations_useFocusTrap.js.map
│   │   │       ├── vitepress___mark__js_src_vanilla__js.js
│   │   │       ├── vitepress___mark__js_src_vanilla__js.js.map
│   │   │       ├── vitepress___minisearch.js
│   │   │       ├── vitepress___minisearch.js.map
│   │   │       ├── vue.js
│   │   │       └── vue.js.map
│   │   ├── config.ts
│   │   ├── dist
│   │   │   ├── 404.html
│   │   │   ├── advanced
│   │   │   │   ├── extensibility.html
│   │   │   │   ├── index.html
│   │   │   │   ├── monitoring.html
│   │   │   │   ├── performance.html
│   │   │   │   └── security.html
│   │   │   ├── api
│   │   │   │   ├── index.html
│   │   │   │   └── README.html
│   │   │   ├── assets
│   │   │   │   ├── advanced_extensibility.md.TrXUn5w5.js
│   │   │   │   ├── advanced_extensibility.md.TrXUn5w5.lean.js
│   │   │   │   ├── advanced_index.md.CPcpUlw_.js
│   │   │   │   ├── advanced_index.md.CPcpUlw_.lean.js
│   │   │   │   ├── advanced_monitoring.md.DTybdNg-.js
│   │   │   │   ├── advanced_monitoring.md.DTybdNg-.lean.js
│   │   │   │   ├── advanced_performance.md.DKmzK0ia.js
│   │   │   │   ├── advanced_performance.md.DKmzK0ia.lean.js
│   │   │   │   ├── advanced_security.md.B-oBD7IB.js
│   │   │   │   ├── advanced_security.md.B-oBD7IB.lean.js
│   │   │   │   ├── api_index.md.Dl1JB08_.js
│   │   │   │   ├── api_index.md.Dl1JB08_.lean.js
│   │   │   │   ├── chunks
│   │   │   │   │   └── framework.CHl2ywxc.js
│   │   │   │   ├── configuration_environment-variables.md.Ddy3P_Wz.js
│   │   │   │   ├── configuration_environment-variables.md.Ddy3P_Wz.lean.js
│   │   │   │   ├── configuration_environment.md.DxcTQ623.js
│   │   │   │   ├── configuration_environment.md.DxcTQ623.lean.js
│   │   │   │   ├── configuration_overview.md.DIkVDv7V.js
│   │   │   │   ├── configuration_overview.md.DIkVDv7V.lean.js
│   │   │   │   ├── configuration_performance.md.DbJdmLrW.js
│   │   │   │   ├── configuration_performance.md.DbJdmLrW.lean.js
│   │   │   │   ├── configuration_reference.md.27IKWqtk.js
│   │   │   │   ├── configuration_reference.md.27IKWqtk.lean.js
│   │   │   │   ├── configuration_security.md.-OOlkzN4.js
│   │   │   │   ├── configuration_security.md.-OOlkzN4.lean.js
│   │   │   │   ├── contributing_dev-setup.md.Ceqh4w-R.js
│   │   │   │   ├── contributing_dev-setup.md.Ceqh4w-R.lean.js
│   │   │   │   ├── contributing_guidelines.md.ZEAX2yVh.js
│   │   │   │   ├── contributing_guidelines.md.ZEAX2yVh.lean.js
│   │   │   │   ├── contributing_index.md.DYq9R6wr.js
│   │   │   │   ├── contributing_index.md.DYq9R6wr.lean.js
│   │   │   │   ├── contributing_maintenance.md.k2bR0IaR.js
│   │   │   │   ├── contributing_maintenance.md.k2bR0IaR.lean.js
│   │   │   │   ├── deployment_cicd.md.Ci2T0UYC.js
│   │   │   │   ├── deployment_cicd.md.Ci2T0UYC.lean.js
│   │   │   │   ├── deployment_cloudflare-workers.md.D2WHsfep.js
│   │   │   │   ├── deployment_cloudflare-workers.md.D2WHsfep.lean.js
│   │   │   │   ├── deployment_docker.md.B8bQDQTo.js
│   │   │   │   ├── deployment_docker.md.B8bQDQTo.lean.js
│   │   │   │   ├── deployment_index.md.ClYeOkpy.js
│   │   │   │   ├── deployment_index.md.ClYeOkpy.lean.js
│   │   │   │   ├── deployment_koyeb.md.B_wJhvF7.js
│   │   │   │   ├── deployment_koyeb.md.B_wJhvF7.lean.js
│   │   │   │   ├── examples_advanced-routing.md.B3CqhLZ7.js
│   │   │   │   ├── examples_advanced-routing.md.B3CqhLZ7.lean.js
│   │   │   │   ├── examples_basic-node.md.CaDZzGlO.js
│   │   │   │   ├── examples_basic-node.md.CaDZzGlO.lean.js
│   │   │   │   ├── examples_cloudflare-worker.md.DwVSz-c7.js
│   │   │   │   ├── examples_cloudflare-worker.md.DwVSz-c7.lean.js
│   │   │   │   ├── examples_index.md.CBF_BLkl.js
│   │   │   │   ├── examples_index.md.CBF_BLkl.lean.js
│   │   │   │   ├── examples_oauth-delegation.md.1hZxoqDl.js
│   │   │   │   ├── examples_oauth-delegation.md.1hZxoqDl.lean.js
│   │   │   │   ├── examples_overview.md.CZN0JbZ7.js
│   │   │   │   ├── examples_overview.md.CZN0JbZ7.lean.js
│   │   │   │   ├── examples_testing.md.Dek4GpNs.js
│   │   │   │   ├── examples_testing.md.Dek4GpNs.lean.js
│   │   │   │   ├── getting-started_concepts.md.D7ON9iGB.js
│   │   │   │   ├── getting-started_concepts.md.D7ON9iGB.lean.js
│   │   │   │   ├── getting-started_installation.md.BKnVqAGg.js
│   │   │   │   ├── getting-started_installation.md.BKnVqAGg.lean.js
│   │   │   │   ├── getting-started_overview.md.DvJDFL2N.js
│   │   │   │   ├── getting-started_overview.md.DvJDFL2N.lean.js
│   │   │   │   ├── getting-started_quickstart-node.md.GOO4aGas.js
│   │   │   │   ├── getting-started_quickstart-node.md.GOO4aGas.lean.js
│   │   │   │   ├── getting-started_quickstart-workers.md.Cpofh8Mj.js
│   │   │   │   ├── getting-started_quickstart-workers.md.Cpofh8Mj.lean.js
│   │   │   │   ├── getting-started.md.DG9ndneo.js
│   │   │   │   ├── getting-started.md.DG9ndneo.lean.js
│   │   │   │   ├── guides_configuration-management.md.B-jwYMbA.js
│   │   │   │   ├── guides_configuration-management.md.B-jwYMbA.lean.js
│   │   │   │   ├── guides_configuration.md.Ci3zYDFA.js
│   │   │   │   ├── guides_configuration.md.Ci3zYDFA.lean.js
│   │   │   │   ├── guides_index.md.CIlq2fmx.js
│   │   │   │   ├── guides_index.md.CIlq2fmx.lean.js
│   │   │   │   ├── guides_module-loading.md.BkJvuRnQ.js
│   │   │   │   ├── guides_module-loading.md.BkJvuRnQ.lean.js
│   │   │   │   ├── guides_oauth-delegation.md.DEOZ-_G0.js
│   │   │   │   ├── guides_oauth-delegation.md.DEOZ-_G0.lean.js
│   │   │   │   ├── guides_request-routing.md.Bdzf0VLg.js
│   │   │   │   ├── guides_request-routing.md.Bdzf0VLg.lean.js
│   │   │   │   ├── guides_testing.md.kYfHqJLu.js
│   │   │   │   ├── guides_testing.md.kYfHqJLu.lean.js
│   │   │   │   ├── inter-italic-cyrillic-ext.r48I6akx.woff2
│   │   │   │   ├── inter-italic-cyrillic.By2_1cv3.woff2
│   │   │   │   ├── inter-italic-greek-ext.1u6EdAuj.woff2
│   │   │   │   ├── inter-italic-greek.DJ8dCoTZ.woff2
│   │   │   │   ├── inter-italic-latin-ext.CN1xVJS-.woff2
│   │   │   │   ├── inter-italic-latin.C2AdPX0b.woff2
│   │   │   │   ├── inter-italic-vietnamese.BSbpV94h.woff2
│   │   │   │   ├── inter-roman-cyrillic-ext.BBPuwvHQ.woff2
│   │   │   │   ├── inter-roman-cyrillic.C5lxZ8CY.woff2
│   │   │   │   ├── inter-roman-greek-ext.CqjqNYQ-.woff2
│   │   │   │   ├── inter-roman-greek.BBVDIX6e.woff2
│   │   │   │   ├── inter-roman-latin-ext.4ZJIpNVo.woff2
│   │   │   │   ├── inter-roman-latin.Di8DUHzh.woff2
│   │   │   │   ├── inter-roman-vietnamese.BjW4sHH5.woff2
│   │   │   │   ├── README.md.BO5r5M9u.js
│   │   │   │   ├── README.md.BO5r5M9u.lean.js
│   │   │   │   ├── style.BQrfSMzK.css
│   │   │   │   ├── troubleshooting_common-issues.md.CScvzWM1.js
│   │   │   │   ├── troubleshooting_common-issues.md.CScvzWM1.lean.js
│   │   │   │   ├── troubleshooting_deployment.md.DUhpqnLE.js
│   │   │   │   ├── troubleshooting_deployment.md.DUhpqnLE.lean.js
│   │   │   │   ├── troubleshooting_errors.md.BSCsEmGc.js
│   │   │   │   ├── troubleshooting_errors.md.BSCsEmGc.lean.js
│   │   │   │   ├── troubleshooting_oauth.md.Cw60Eka3.js
│   │   │   │   ├── troubleshooting_oauth.md.Cw60Eka3.lean.js
│   │   │   │   ├── troubleshooting_performance.md.DxY6LJcT.js
│   │   │   │   ├── troubleshooting_performance.md.DxY6LJcT.lean.js
│   │   │   │   ├── troubleshooting_routing.md.BHN-MDhs.js
│   │   │   │   ├── troubleshooting_routing.md.BHN-MDhs.lean.js
│   │   │   │   ├── troubleshooting_security-best-practices.md.Yiu8E-zt.js
│   │   │   │   ├── troubleshooting_security-best-practices.md.Yiu8E-zt.lean.js
│   │   │   │   ├── tutorials_beginner-getting-started.md.BXObgobW.js
│   │   │   │   ├── tutorials_beginner-getting-started.md.BXObgobW.lean.js
│   │   │   │   ├── tutorials_cloudflare-workers-tutorial.md.MPHsc0aT.js
│   │   │   │   ├── tutorials_cloudflare-workers-tutorial.md.MPHsc0aT.lean.js
│   │   │   │   ├── tutorials_load-balancing-and-resilience.md.Dv9r9jyW.js
│   │   │   │   ├── tutorials_load-balancing-and-resilience.md.Dv9r9jyW.lean.js
│   │   │   │   ├── tutorials_oauth-delegation-github.md.Nq4glqCe.js
│   │   │   │   └── tutorials_oauth-delegation-github.md.Nq4glqCe.lean.js
│   │   │   ├── configuration
│   │   │   │   ├── environment-variables.html
│   │   │   │   ├── environment.html
│   │   │   │   ├── examples.html
│   │   │   │   ├── overview.html
│   │   │   │   ├── performance.html
│   │   │   │   ├── reference.html
│   │   │   │   └── security.html
│   │   │   ├── contributing
│   │   │   │   ├── dev-setup.html
│   │   │   │   ├── guidelines.html
│   │   │   │   ├── index.html
│   │   │   │   └── maintenance.html
│   │   │   ├── deployment
│   │   │   │   ├── cicd.html
│   │   │   │   ├── cloudflare-workers.html
│   │   │   │   ├── docker.html
│   │   │   │   ├── index.html
│   │   │   │   └── koyeb.html
│   │   │   ├── diagrams
│   │   │   │   └── architecture.svg
│   │   │   ├── examples
│   │   │   │   ├── advanced-routing.html
│   │   │   │   ├── basic-node.html
│   │   │   │   ├── cloudflare-worker.html
│   │   │   │   ├── index.html
│   │   │   │   ├── oauth-delegation.html
│   │   │   │   ├── overview.html
│   │   │   │   └── testing.html
│   │   │   ├── getting-started
│   │   │   │   ├── concepts.html
│   │   │   │   ├── installation.html
│   │   │   │   ├── overview.html
│   │   │   │   ├── quick-start.html
│   │   │   │   ├── quickstart-node.html
│   │   │   │   └── quickstart-workers.html
│   │   │   ├── getting-started.html
│   │   │   ├── guides
│   │   │   │   ├── authentication.html
│   │   │   │   ├── client-integration.html
│   │   │   │   ├── configuration-management.html
│   │   │   │   ├── configuration.html
│   │   │   │   ├── index.html
│   │   │   │   ├── module-loading.html
│   │   │   │   ├── oauth-delegation.html
│   │   │   │   ├── request-routing.html
│   │   │   │   ├── server-management.html
│   │   │   │   ├── server-sharing.html
│   │   │   │   └── testing.html
│   │   │   ├── hashmap.json
│   │   │   ├── index.html
│   │   │   ├── logo.svg
│   │   │   ├── README.html
│   │   │   ├── reports
│   │   │   │   └── mcp-compliance-audit.html
│   │   │   ├── troubleshooting
│   │   │   │   ├── common-issues.html
│   │   │   │   ├── deployment.html
│   │   │   │   ├── errors.html
│   │   │   │   ├── index.html
│   │   │   │   ├── oauth.html
│   │   │   │   ├── performance.html
│   │   │   │   ├── routing.html
│   │   │   │   └── security-best-practices.html
│   │   │   ├── tutorials
│   │   │   │   ├── beginner-getting-started.html
│   │   │   │   ├── cloudflare-workers-tutorial.html
│   │   │   │   ├── load-balancing-and-resilience.html
│   │   │   │   └── oauth-delegation-github.html
│   │   │   └── vp-icons.css
│   │   └── theme
│   │       ├── components
│   │       │   ├── ApiPlayground.vue
│   │       │   ├── AuthFlowDemo.vue
│   │       │   ├── CodeTabs.vue
│   │       │   └── ConfigGenerator.vue
│   │       ├── index.ts
│   │       └── style.css
│   ├── advanced
│   │   ├── extensibility.md
│   │   ├── index.md
│   │   ├── monitoring.md
│   │   ├── performance.md
│   │   └── security.md
│   ├── api
│   │   ├── functions
│   │   │   └── createServer.md
│   │   ├── index.md
│   │   ├── interfaces
│   │   │   └── RunningServer.md
│   │   └── README.md
│   ├── architecture
│   │   └── images
│   │       └── mcp_master_architecture.svg
│   ├── configuration
│   │   ├── environment-variables.md
│   │   ├── environment.md
│   │   ├── examples.md
│   │   ├── overview.md
│   │   ├── performance.md
│   │   ├── reference.md
│   │   └── security.md
│   ├── contributing
│   │   ├── dev-setup.md
│   │   ├── guidelines.md
│   │   ├── index.md
│   │   └── maintenance.md
│   ├── deployment
│   │   ├── cicd.md
│   │   ├── cloudflare-workers.md
│   │   ├── docker.md
│   │   ├── docs-site.md
│   │   ├── index.md
│   │   └── koyeb.md
│   ├── examples
│   │   ├── advanced-routing.md
│   │   ├── basic-node.md
│   │   ├── cloudflare-worker.md
│   │   ├── index.md
│   │   ├── oauth-delegation.md
│   │   ├── overview.md
│   │   └── testing.md
│   ├── getting-started
│   │   ├── concepts.md
│   │   ├── installation.md
│   │   ├── overview.md
│   │   ├── quick-start.md
│   │   ├── quickstart-node.md
│   │   └── quickstart-workers.md
│   ├── getting-started.md
│   ├── guides
│   │   ├── authentication.md
│   │   ├── client-integration.md
│   │   ├── configuration-management.md
│   │   ├── configuration.md
│   │   ├── index.md
│   │   ├── module-loading.md
│   │   ├── oauth-delegation.md
│   │   ├── request-routing.md
│   │   ├── server-management.md
│   │   ├── server-sharing.md
│   │   └── testing.md
│   ├── index.html
│   ├── public
│   │   ├── diagrams
│   │   │   └── architecture.svg
│   │   ├── github-social.png
│   │   │   └── image.png
│   │   ├── logo.png
│   │   └── logo.svg
│   ├── README.md
│   ├── stdio-servers.md
│   ├── testing
│   │   └── phase-9-testing-architecture.md
│   ├── troubleshooting
│   │   ├── common-issues.md
│   │   ├── deployment.md
│   │   ├── errors.md
│   │   ├── index.md
│   │   ├── oauth.md
│   │   ├── performance.md
│   │   ├── routing.md
│   │   └── security-best-practices.md
│   └── tutorials
│       ├── beginner-getting-started.md
│       ├── cloudflare-workers-tutorial.md
│       ├── load-balancing-and-resilience.md
│       └── oauth-delegation-github.md
├── examples
│   ├── advanced-routing
│   │   ├── config.yaml
│   │   └── README.md
│   ├── basic-node
│   │   ├── config.yaml
│   │   ├── README.md
│   │   └── server.ts
│   ├── cloudflare-worker
│   │   ├── README.md
│   │   └── worker.ts
│   ├── custom-auth
│   │   ├── config.yaml
│   │   ├── index.ts
│   │   └── README.md
│   ├── multi-server
│   │   ├── config.yaml
│   │   └── README.md
│   ├── oauth-delegation
│   │   └── README.md
│   ├── oauth-node
│   │   ├── config.yaml
│   │   └── README.md
│   ├── performance
│   │   ├── config.yaml
│   │   └── README.md
│   ├── sample-configs
│   │   ├── basic.yaml
│   │   └── simple-setup.yaml
│   ├── security-hardening
│   │   └── README.md
│   ├── stdio-mcp-server.cjs
│   ├── test-mcp-server.js
│   └── test-stdio-server.js
├── LICENSE
├── master-mcp-definition.md
├── package-lock.json
├── package.json
├── README.md
├── reports
│   └── claude_report_20250815_222153.html
├── scripts
│   └── generate-config-docs.ts
├── src
│   ├── auth
│   │   ├── multi-auth-manager.ts
│   │   ├── oauth-providers.ts
│   │   └── token-manager.ts
│   ├── config
│   │   ├── config-loader.ts
│   │   ├── environment-manager.ts
│   │   ├── schema-validator.ts
│   │   └── secret-manager.ts
│   ├── index.ts
│   ├── mcp-server.ts
│   ├── modules
│   │   ├── capability-aggregator.ts
│   │   ├── module-loader.ts
│   │   ├── request-router.ts
│   │   ├── stdio-capability-discovery.ts
│   │   └── stdio-manager.ts
│   ├── oauth
│   │   ├── callback-handler.ts
│   │   ├── flow-controller.ts
│   │   ├── flow-validator.ts
│   │   ├── pkce-manager.ts
│   │   ├── state-manager.ts
│   │   └── web-interface.ts
│   ├── routing
│   │   ├── circuit-breaker.ts
│   │   ├── load-balancer.ts
│   │   ├── retry-handler.ts
│   │   └── route-registry.ts
│   ├── runtime
│   │   ├── node.ts
│   │   └── worker.ts
│   ├── server
│   │   ├── config-manager.ts
│   │   ├── dependency-container.ts
│   │   ├── master-server.ts
│   │   └── protocol-handler.ts
│   ├── types
│   │   ├── auth.ts
│   │   ├── config.ts
│   │   ├── jose-shim.d.ts
│   │   ├── mcp.ts
│   │   └── server.ts
│   └── utils
│       ├── cache.ts
│       ├── crypto.ts
│       ├── dev.ts
│       ├── errors.ts
│       ├── http.ts
│       ├── logger.ts
│       ├── monitoring.ts
│       ├── string.ts
│       ├── time.ts
│       ├── validation.ts
│       └── validators.ts
├── static
│   └── oauth
│       ├── consent.html
│       ├── error.html
│       ├── script.js
│       ├── style.css
│       └── success.html
├── tests
│   ├── _setup
│   │   ├── miniflare.setup.ts
│   │   └── vitest.setup.ts
│   ├── _utils
│   │   ├── log-capture.ts
│   │   ├── mock-fetch.ts
│   │   └── test-server.ts
│   ├── .gitkeep
│   ├── e2e
│   │   ├── flow-controller.express.test.ts
│   │   └── flow-controller.worker.test.ts
│   ├── factories
│   │   ├── configFactory.ts
│   │   ├── mcpFactory.ts
│   │   └── oauthFactory.ts
│   ├── fixtures
│   │   ├── capabilities.json
│   │   └── stdio-server.js
│   ├── integration
│   │   ├── modules.capability-aggregator.test.ts
│   │   ├── modules.module-loader-health.test.ts
│   │   ├── oauth.callback-handler.test.ts
│   │   └── request-router.test.ts
│   ├── mocks
│   │   ├── mcp
│   │   │   └── fake-backend.ts
│   │   └── oauth
│   │       └── mock-oidc-provider.ts
│   ├── perf
│   │   ├── artillery
│   │   │   └── auth-routing.yaml
│   │   └── perf.auth-and-routing.test.ts
│   ├── security
│   │   └── security.oauth-and-input.test.ts
│   ├── servers
│   │   ├── test-auth-simple.js
│   │   ├── test-debug.js
│   │   ├── test-master-mcp.js
│   │   ├── test-mcp-client.js
│   │   ├── test-streaming-both-complete.js
│   │   ├── test-streaming-both-full.js
│   │   ├── test-streaming-both-simple.js
│   │   ├── test-streaming-both.js
│   │   └── test-streaming.js
│   ├── setup
│   │   └── test-setup.ts
│   ├── unit
│   │   ├── auth.multi-auth-manager.test.ts
│   │   ├── auth.token-manager.test.ts
│   │   ├── config.environment-manager.test.ts
│   │   ├── config.schema-validator.test.ts
│   │   ├── config.secret-manager.test.ts
│   │   ├── modules
│   │   │   ├── stdio-capability-discovery.test.ts
│   │   │   └── stdio-manager.test.ts
│   │   ├── modules.route-registry.test.ts
│   │   ├── oauth.pkce-state.test.ts
│   │   ├── routing
│   │   │   └── circuit-breaker.test.ts
│   │   ├── routing.core.test.ts
│   │   ├── stdio-capability-discovery.test.ts
│   │   ├── utils.crypto.test.ts
│   │   ├── utils.logger.test.ts
│   │   └── utils.monitoring.test.ts
│   └── utils
│       ├── fake-express.ts
│       ├── mock-http.ts
│       ├── oauth-mocks.ts
│       └── token-storages.ts
├── tsconfig.base.json
├── tsconfig.json
├── tsconfig.node.json
├── tsconfig.worker.json
├── typedoc.json
├── vitest.config.ts
└── vitest.worker.config.ts
```

# Files

--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------

```javascript

```

--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------

```

```

--------------------------------------------------------------------------------
/deploy/cloudflare/.gitkeep:
--------------------------------------------------------------------------------

```


```

--------------------------------------------------------------------------------
/deploy/docker/.gitkeep:
--------------------------------------------------------------------------------

```


```

--------------------------------------------------------------------------------
/deploy/koyeb/.gitkeep:
--------------------------------------------------------------------------------

```


```

--------------------------------------------------------------------------------
/tests/.gitkeep:
--------------------------------------------------------------------------------

```


```

--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------

```
dist
node_modules
coverage


```

--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------

```
dist
node_modules
coverage


```

--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------

```json
{
  "singleQuote": true,
  "semi": false,
  "trailingComma": "es5",
  "printWidth": 100
}


```

--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------

```
# Runtime
NODE_ENV=development
LOG_LEVEL=info
LOG_FORMAT=json

# Hosting
# If running behind a PaaS that sets PORT, the config loader will detect it.
PORT=3000
MASTER_HOSTING_PLATFORM=node
MASTER_HOSTING_PORT=3000
MASTER_BASE_URL=http://localhost:3000

# Security
# REQUIRED in production; if missing in dev, an ephemeral key is generated
TOKEN_ENC_KEY=replace-with-32+char-hex-or-random

# OAuth defaults (example values; override per provider)
MASTER_OAUTH_AUTHORIZATION_ENDPOINT=https://example.com/auth
MASTER_OAUTH_TOKEN_ENDPOINT=https://example.com/token
MASTER_OAUTH_CLIENT_ID=placeholder
MASTER_OAUTH_REDIRECT_URI=http://localhost:3000/oauth/callback
MASTER_OAUTH_SCOPES=openid


```

--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------

```
/* eslint-env node */
module.exports = {
  root: true,
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: ['./tsconfig.node.json'],
    tsconfigRootDir: __dirname,
    sourceType: 'module',
    ecmaVersion: 2022
  },
  env: {
    node: true,
    es2022: true
  },
  plugins: ['@typescript-eslint'],
  extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
  rules: {
    'no-console': 'off',
    '@typescript-eslint/no-explicit-any': 'off',
    '@typescript-eslint/no-unused-vars': 'off'
  },
  overrides: [
    {
      files: ['**/*.ts', '**/*.tsx'],
      parser: '@typescript-eslint/parser',
      parserOptions: {
        project: ['./tsconfig.node.json'],
        tsconfigRootDir: __dirname,
        sourceType: 'module',
        ecmaVersion: 2022,
      },
    },
    {
      files: ['src/runtime/worker.ts'],
      parserOptions: {
        project: ['./tsconfig.worker.json'],
      },
    },
  ],
  ignorePatterns: ['dist/**', 'node_modules/**']
}

```

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
# Master MCP Server - Comprehensive .gitignore

# Node.js & npm
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Package manager lock files (keep package-lock.json for reproducible builds)
yarn.lock
pnpm-lock.yaml

# Runtime data
pids/
*.pid
*.seed
*.pid.lock

# Coverage directory used by tools like istanbul
coverage/
*.lcov
.nyc_output/
.coverage/

# Compiled output
dist/
build/
lib/
out/
*.tsbuildinfo

# TypeScript cache
*.tsbuildinfo

# ESLint cache
.eslintcache

# Prettier cache
.prettiercache

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
.env.*.local
.env.production

# Secrets and sensitive configuration
config/secrets.json
config/production-secrets.json
.secrets/
secrets/

# IDE and Editor files
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store
Thumbs.db

# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# Logs
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Runtime and process files
.pm2/
.pid

# Database
*.db
*.sqlite
*.sqlite3

# Cache directories
.cache/
.parcel-cache/
.next/
.nuxt/
.vuepress/dist

# Temporary directories
tmp/
temp/
.tmp/
.temp/

# Test artifacts
test-results/
junit.xml
coverage-final.json

# Documentation build artifacts
docs/.vitepress/dist/
docs/.vitepress/cache/
.typedoc/

# Deployment artifacts
deploy/secrets/
deploy/keys/
deploy/*.key
deploy/*.pem

# Docker
.dockerignore
docker-compose.override.yml

# Cloudflare Workers
.dev.vars
.wrangler/
worker-configuration.d.ts

# Koyeb
.koyeb/

# SSL certificates and keys
*.pem
*.key
*.crt
*.ca-bundle
*.p12
*.pfx

# API keys and tokens
.api-keys
*.token
auth.json

# Ouroboros and Swarm Agent Files
ouroboros-results/
ouroboros-logs/
ouroboros-cache/
ouroboros-data/
swarm-cache/
swarm-logs/
agent-logs/
agent-results/
agent-cache/
.ouroboros/
.swarm/

# Session and memory files
SESSION-MEMORY.md
session-*.md
.session/
memory/

# MCP specific
mcp-logs/
mcp-cache/
server-data/
server-logs/
backend-servers/
loaded-servers/
.mcp/

# OAuth and authentication
oauth-tokens/
oauth-cache/
.oauth/
tokens/
session-store/

# Performance and monitoring
metrics/
traces/
.monitoring/
perf-data/

# Local development
.dev/
dev-data/
local-config/
local-secrets/

# Husky hooks (if needed, can be uncommented)
.husky/

# Backup files
*.backup
*.bak
*~

# Temporary files
*.tmp
*.temp

# Archive files
*.zip
*.tar.gz
*.rar
*.7z

# Binary files (unless specifically needed)
*.exe
*.dll
*.so
*.dylib

# Cloud provider specific
.aws/
.gcp/
.azure/

# Terraform
*.tfstate
*.tfstate.*
.terraform/
.terraform.lock.hcl

# Kubernetes
*.kubeconfig

# Monitoring and observability
jaeger-data/
prometheus-data/
grafana-data/

# Load testing
artillery-output/
k6-results/

# Keep important files (negative patterns)
!.gitkeep
!.env.example
!.env.template
!config/default.json
!config/schema.json
!examples/**/*.yaml
!examples/**/*.json
!docs/**/*
!deploy/docker/Dockerfile
!deploy/cloudflare/wrangler.toml
!deploy/koyeb/koyeb.yaml


# MCP / local tooling
.crush/
.kiro/
.claude/
.ouroboros/
ouroboros-results/

# Keep uv.lock tracked (do not ignore)

# IDEs and Ouroboros
AGENTS.md
CLAUDE.md
CRUSH.md
GEMINI.md
QWEN.md
IMPLEMENTATION_PLAN.md
SESSION-MEMORY.md
task-definition.md

# Documentation application
.vitepress

# Random
.DS_Store
```

--------------------------------------------------------------------------------
/examples/advanced-routing/README.md:
--------------------------------------------------------------------------------

```markdown
# Advanced Routing Example

Demonstrates retry policy, circuit breaker, and load balancing configuration.

Run
- `CONFIG_PATH=examples/advanced-routing/config.yaml npm start`


```

--------------------------------------------------------------------------------
/examples/performance/README.md:
--------------------------------------------------------------------------------

```markdown
# Example: Performance Tuning

Demonstrates routing configuration tuned for high-throughput and resilience.

## Run

```
MASTER_CONFIG_PATH=examples/performance/config.yaml npm run dev
```


```

--------------------------------------------------------------------------------
/examples/multi-server/README.md:
--------------------------------------------------------------------------------

```markdown
# Example: Multi-Server with Resilience

Demonstrates multiple instances of the same service id with load balancing, retries, and circuit breaker.

## Run

```
MASTER_CONFIG_PATH=examples/multi-server/config.yaml npm run dev
```


```

--------------------------------------------------------------------------------
/examples/custom-auth/README.md:
--------------------------------------------------------------------------------

```markdown
# Example: Custom Authentication Strategy

Shows how to attach a custom `MultiAuthManager` that tweaks headers per backend.

## Run

```
MASTER_CONFIG_PATH=examples/custom-auth/config.yaml \
node --loader ts-node/esm examples/custom-auth/index.ts
```


```

--------------------------------------------------------------------------------
/examples/cloudflare-worker/README.md:
--------------------------------------------------------------------------------

```markdown
# Cloudflare Worker Example

Runs the Master MCP Worker handler with Wrangler.

Steps
1. Build worker bundle: `npm run build:worker`
2. Dev: `npx wrangler dev examples/cloudflare-worker/worker.ts`
3. Deploy: configure and run from `/deploy/cloudflare`.


```

--------------------------------------------------------------------------------
/docs/api/README.md:
--------------------------------------------------------------------------------

```markdown
**master-mcp-server**

***

# master-mcp-server

## Interfaces

- [RunningServer](interfaces/RunningServer.md)

## Functions

- [createServer](functions/createServer.md)

## References

### default

Renames and re-exports [createServer](functions/createServer.md)

```

--------------------------------------------------------------------------------
/examples/basic-node/README.md:
--------------------------------------------------------------------------------

```markdown
# Example: Basic Master MCP Server (Node)

This example runs the Node runtime with a single local backend.

## Run

```
MASTER_CONFIG_PATH=examples/basic-node/config.yaml npm run dev
```

Endpoints:

- http://localhost:3000/health
- http://localhost:3000/mcp/tools/list


```

--------------------------------------------------------------------------------
/examples/oauth-delegation/README.md:
--------------------------------------------------------------------------------

```markdown
# OAuth Delegation Example

Enable delegated OAuth for backends and complete flows via the built-in controller.

Run
1. Configure `oauth_delegation.enabled: true` in your config, and set provider entries if desired.
2. Start the server and visit `/oauth` to initiate flows.


```

--------------------------------------------------------------------------------
/examples/oauth-node/README.md:
--------------------------------------------------------------------------------

```markdown
# Example: OAuth Delegation (GitHub)

Demonstrates `delegate_oauth` for a GitHub-protected backend.

## Run

Set secrets:

```
export GITHUB_CLIENT_SECRET=... # from GitHub OAuth app
```

Start:

```
MASTER_CONFIG_PATH=examples/oauth-node/config.yaml npm run dev
```

Then open:

```
http://localhost:3000/oauth/authorize?server_id=github-tools
```


```

--------------------------------------------------------------------------------
/examples/security-hardening/README.md:
--------------------------------------------------------------------------------

```markdown
# Example: Security Hardening

This example outlines recommended environment and config for production.

## Environment

- `NODE_ENV=production`
- `LOG_FORMAT=json`
- `LOG_LEVEL=info`
- `TOKEN_ENC_KEY` set via secret store
- `MASTER_BASE_URL=https://your.domain`

## Config Snippet

```yaml
security:
  audit: true
logging:
  level: info
hosting:
  platform: node
  port: 3000
```

Deploy with Docker/Koyeb using read-only config mounts and non-root users (see Dockerfiles).


```

--------------------------------------------------------------------------------
/deploy/README.md:
--------------------------------------------------------------------------------

```markdown
# Deployment Overview

Artifacts and configs to deploy the Master MCP Server:

- Docker
  - `deploy/docker/Dockerfile`: multi-stage build for Node runtime.
  - `deploy/docker/docker-compose.yml`: local development runner.
- Cloudflare Workers
  - `deploy/cloudflare/wrangler.toml`: Workers config (staging/production envs).
  - `deploy/cloudflare/README.md`: usage notes.
- Koyeb
  - `deploy/koyeb/koyeb.yaml`: Koyeb service and autoscaling settings.

CI/CD pipelines live in `.github/workflows`. See `docs/architecture/phase10-deployment-architecture.md` for full details.


```

--------------------------------------------------------------------------------
/deploy/cloudflare/README.md:
--------------------------------------------------------------------------------

```markdown
# Cloudflare Workers Deployment

## Prerequisites
- Cloudflare account and `CLOUDFLARE_API_TOKEN` with Workers permissions.
- `wrangler` installed locally or use GitHub Action for CI deploys.

## Local Dev
```
wrangler dev
```

## Configure Secrets
```
wrangler secret put TOKEN_ENC_KEY
# Add any OAuth client secrets as needed
```

## Deploy
```
wrangler deploy --env staging
wrangler deploy --env production
```

The worker entry is `src/runtime/worker.ts` which exports a `fetch` handler. Ensure your config values align with Workers (e.g., base URLs for OAuth callbacks).


```

--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------

```markdown
# Master MCP Server Documentation

Welcome to the Master MCP Server docs. This documentation covers architecture, configuration, authentication flows, request routing, deployment, and troubleshooting. It also includes end-to-end tutorials and working examples.

## Contents

- Getting Started: `../docs/getting-started.md`
- Guides:
  - Authentication: `./guides/authentication.md`
  - Configuration Mgmt: `./guides/configuration-management.md`
  - Module Loading & Aggregation: `./guides/module-loading.md`
  - Request Routing & Resilience: `./guides/request-routing.md`
  - Server Management: `./guides/server-management.md`
- Tutorials:
  - Beginner Setup: `./tutorials/beginner-getting-started.md`
  - OAuth Delegation with GitHub: `./tutorials/oauth-delegation-github.md`
  - Cloudflare Workers: `./tutorials/cloudflare-workers-tutorial.md`
  - Load Balancing & Resilience: `./tutorials/load-balancing-and-resilience.md`
- API Reference: `./api/README.md` (generated via TypeDoc)
- Configuration:
  - Schema & Reference: `./configuration/reference.md`
  - Environment Variables: `./configuration/environment-variables.md`
  - Security: `./configuration/security.md`
  - Performance: `./configuration/performance.md`
- Deployment:
  - Docker: `./deployment/docker.md`
  - Cloudflare Workers: `./deployment/cloudflare-workers.md`
  - Koyeb: `./deployment/koyeb.md`
  - CI/CD: `./deployment/cicd.md`
- Troubleshooting:
  - Common Issues: `./troubleshooting/common-issues.md`
  - Error Reference: `./troubleshooting/errors.md`
  - Performance Troubleshooting: `./troubleshooting/performance.md`
  - Security Best Practices: `./troubleshooting/security-best-practices.md`

If you are looking for design notes per phase, see `./architecture/*` and testing strategy in `./testing/phase-9-testing-architecture.md`.


```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# Master MCP Server

Master MCP Server aggregates multiple MCP servers behind a single, secure endpoint. It provides configuration-driven module loading, unified capability discovery, request routing with resilience, and first-class OAuth flows for multi-backend authentication.

## Highlights

- Aggregates multiple MCP servers with tool/resource discovery and namespacing
- OAuth support: master token pass-through, delegated provider flows, proxy refresh
- Config-driven setup with JSON/YAML, schema validation, and secret resolution
- Resilient routing: load-balancing, retries with backoff/jitter, circuit-breakers
- Cross-platform: Node.js server and Cloudflare Workers runtime
- Production-ready deployment: Docker, Cloudflare Workers, Koyeb
- Testing strategy and CI-ready structure

## Quick Start (Node.js)

1) Install dependencies (requires network):

```plaintext
npm ci
```

2) Configure environment (copy and edit):

```plaintext
cp .env.example .env
```

3) Run in dev mode:

```plaintext
npm run dev
```

4) Health and Metrics:

- `GET /health` → `{ ok: true }`
- `GET /metrics` → basic system metrics

5) MCP endpoints (HTTP gateway):

- `POST /mcp/tools/list`
- `POST /mcp/tools/call` with `{ name, arguments }`
- `POST /mcp/resources/list`
- `POST /mcp/resources/read` with `{ uri }`

See `docs/` for full guides and end-to-end examples.

## Documentation

- Docs index: `docs/index.md`
- Getting started: `docs/getting-started/overview.md`
- Guides: `docs/guides/*`
- API reference: generated into `docs/api/reference/` (see below)
- Configuration reference: `docs/configuration/*`
- Deployment: `docs/deployment/*`
- Troubleshooting: `docs/troubleshooting/*`
- Contributing: `docs/contributing/*`

## Generate API Docs

We use TypeDoc (Markdown) to generate API docs from TypeScript.

1) Install (requires network):

```plaintext
npm i -D typedoc typedoc-plugin-markdown
```

2) Generate docs:

```plaintext
npm run docs:api
```

Outputs to `docs/api/`.

## Examples

Working examples live in `examples/`:

- Basic Node: `examples/basic-node`
- Cloudflare Worker: `examples/cloudflare-worker`
- Advanced Routing: `examples/advanced-routing`
- OAuth Delegation: `examples/oauth-delegation`
- Testing Patterns: see `/tests` and `docs/examples/testing.md`

Each example has a README with run instructions.

## Deployment

- Docker: `deploy/docker/*` and top-level `Dockerfile` / `docker-compose.yml`
- Cloudflare Workers: `deploy/cloudflare/*` with `wrangler.toml`
- Koyeb: `deploy/koyeb/koyeb.yaml`
- CI/CD examples: see `docs/deployment/cicd.md`

## Architecture

![MCP Master Architecture](docs/architecture/images/mcp_master_architecture.svg)

## Contributing & Support

- See `docs/contributing/*` for development workflow and guidelines
- See `docs/troubleshooting/index.md` for solutions
- Open an issue or discussion for help and ideas

## License

See `LICENSE`. This repository currently uses UNLICENSED for private/internal use.

```

--------------------------------------------------------------------------------
/docs/advanced/security.md:
--------------------------------------------------------------------------------

```markdown
---
title: Security Hardening
---

# Security Hardening

- Rotate secrets regularly (`security.rotation_days`).
- Use `security.audit` for config change logging.
- Lock down OAuth redirect URIs and audiences.
- Enforce strict TLS and CSP in hosting platform.
- Validate inputs and sanitize logs (see `utils/security` patterns).


```

--------------------------------------------------------------------------------
/docs/configuration/security.md:
--------------------------------------------------------------------------------

```markdown
# Security Configuration & Practices

## Secrets in Config

Use either of the following in your config:

- `env:VARNAME` → value is read from `process.env.VARNAME`
- `enc:gcm:<base64>` → value is decrypted using `MASTER_CONFIG_KEY` (or `MASTER_SECRET_KEY`)

`SecretManager` handles both resolving and redacting sensitive values for logs.

## Token Encryption

`TokenManager` encrypts stored delegated/proxy tokens with `TOKEN_ENC_KEY`. In production this must be set; otherwise startup fails. In development, a warning is logged and an ephemeral key is generated.

## OAuth Best Practices

- Always set `hosting.base_url` correctly for accurate redirect URIs behind proxies.
- Use PKCE (enabled by default) and short-lived state tokens.
- Limit scopes in `servers[].auth_config.scopes` to the minimum required.

## Hardening Tips

- Drop container capabilities and run as non-root (see Dockerfiles)
- Use `LOG_FORMAT=json` in production for structured logs
- Ensure secrets are injected via platform secret stores (KMS, Workers Secrets, Koyeb Secrets)
- Enable `security.audit` to log config changes (redacted)


```

--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------

```markdown
# Contributing Guide

Thanks for your interest in contributing to the Master MCP Server. This guide outlines the development workflow and standards.

## Development Setup

1) Install Node >= 18.17
2) Install dependencies:

```
npm ci
```

3) Useful scripts:

```
npm run typecheck
npm run build
npm run dev
npm run test
npm run lint && npm run format
```

## Docs & API Reference

- Author guides and tutorials in `docs/`
- Generate API docs (requires network): `npm run docs:api`
- Keep examples in `examples/` runnable and minimal

## Coding Standards

- TypeScript strict mode; no `any` without justification
- Prefer small, composable modules and clear interfaces
- Avoid introducing runtime-only dependencies in shared modules (support both Node and Workers)

## Testing

- Unit tests under `tests/unit` and integration under `tests/integration`
- Add targeted tests for new modules and critical paths

## Commit Style

- Use clear, imperative messages (e.g., "Add OAuth state validation")
- Reference issues where applicable

## Security

- Never commit secrets
- Use `SecretManager` patterns for config secrets


```

--------------------------------------------------------------------------------
/docs/.vitepress/cache/deps/package.json:
--------------------------------------------------------------------------------

```json
{
  "type": "module"
}

```

--------------------------------------------------------------------------------
/config/production.json:
--------------------------------------------------------------------------------

```json
{
  "logging": { "level": "info" }
}


```

--------------------------------------------------------------------------------
/config/development.json:
--------------------------------------------------------------------------------

```json
{
  "logging": { "level": "debug" }
}


```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
  "extends": "./tsconfig.node.json"
}


```

--------------------------------------------------------------------------------
/examples/cloudflare-worker/worker.ts:
--------------------------------------------------------------------------------

```typescript
export { default as default } from '../../src/runtime/worker.js'


```

--------------------------------------------------------------------------------
/src/utils/validators.ts:
--------------------------------------------------------------------------------

```typescript
export { isNonEmptyString, isRecord } from './validation.js'
export * as Validation from './validation.js'

```

--------------------------------------------------------------------------------
/docs/advanced/index.md:
--------------------------------------------------------------------------------

```markdown
---
title: Advanced Topics
---

# Advanced Topics

Deep dives into security, performance, monitoring, and extensibility.


```

--------------------------------------------------------------------------------
/tests/fixtures/stdio-server.js:
--------------------------------------------------------------------------------

```javascript
process.stdout.write(JSON.stringify({ type: 'notification', message: 'server ready' }) + '\n');

setInterval(() => {
  // Keep the process alive
}, 1000)
```

--------------------------------------------------------------------------------
/static/oauth/script.js:
--------------------------------------------------------------------------------

```javascript
// Placeholder for future enhancements like telemetry, animations, etc.
// Intentionally minimal to reduce attack surface.
document.documentElement.classList.add('js')


```

--------------------------------------------------------------------------------
/tests/fixtures/capabilities.json:
--------------------------------------------------------------------------------

```json
{
  "tools": [
    { "name": "echo", "description": "Echo input" }
  ],
  "resources": [
    { "uri": "docs.readme", "name": "Readme", "mimeType": "text/plain" }
  ]
}


```

--------------------------------------------------------------------------------
/examples/basic-node/server.ts:
--------------------------------------------------------------------------------

```typescript
import { createServer } from '../../src/index.js'

async function main() {
  await createServer(true)
}

// eslint-disable-next-line @typescript-eslint/no-floating-promises
main()


```

--------------------------------------------------------------------------------
/docs/advanced/extensibility.md:
--------------------------------------------------------------------------------

```markdown
---
title: Extensibility & Plugins
---

# Extensibility & Plugins

- Extend `ModuleLoader` to support new sources.
- Add routing strategies by extending the load balancer.
- Use typed interfaces in `src/types/*` for compatibility.


```

--------------------------------------------------------------------------------
/docs/examples/testing.md:
--------------------------------------------------------------------------------

```markdown
---
title: Testing Patterns
---

# Example: Testing Patterns

Use `/tests` as the primary reference. This example demonstrates configuring Node vs Workers test environments and using utilities in `_utils`.

Run
- `npm run test` or target specific suites.


```

--------------------------------------------------------------------------------
/docs/contributing/index.md:
--------------------------------------------------------------------------------

```markdown
---
title: Contributing
---

# Contributing

We welcome contributions across code, documentation, and examples.

- Read Guidelines for coding and docs conventions
- Use Dev Setup to get your environment ready
- Open PRs with focused changes and include tests/docs


```

--------------------------------------------------------------------------------
/tsconfig.node.json:
--------------------------------------------------------------------------------

```json
{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
    "outDir": "dist/node",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "types": ["node"],
    "lib": ["ES2022"],
    "jsx": "react-jsx"
  },
  "exclude": ["src/runtime/worker.ts"]
}

```

--------------------------------------------------------------------------------
/docs/advanced/performance.md:
--------------------------------------------------------------------------------

```markdown
---
title: Performance & Scalability
---

# Performance & Scalability

- Tune retry/backoff to avoid thundering herd.
- Right-size circuit breaker thresholds per backend latency.
- Use caching (`utils/cache`) where safe.
- Monitor p95/p99 latencies and error rates.


```

--------------------------------------------------------------------------------
/docs/advanced/monitoring.md:
--------------------------------------------------------------------------------

```markdown
---
title: Monitoring & Logging
---

# Monitoring & Logging

- Use `/metrics` endpoint and `collectSystemMetrics()` for basic telemetry.
- Integrate logs with your platform (stdout in Docker/Koyeb, Workers logs).
- Centralize error handling in `utils/errors` and `utils/logger`.


```

--------------------------------------------------------------------------------
/tests/_setup/miniflare.setup.ts:
--------------------------------------------------------------------------------

```typescript
// Miniflare/Vitest setup for Workers-targeted suites
import { Logger } from '../../src/utils/logger.js'

Logger.configure({ level: 'error', json: true })

// Miniflare provides global fetch/Request/Response.
// If we need to start auxiliary Node HTTP stubs, do it within tests.


```

--------------------------------------------------------------------------------
/docs/troubleshooting/deployment.md:
--------------------------------------------------------------------------------

```markdown
---
title: Deployment
---

# Troubleshooting: Deployment

- Docker: ensure env files loaded and ports exposed.
- Workers: align bundling target and avoid Node APIs.
- Koyeb: ensure service listens on the configured port.
- Secrets: verify platform secret injection and `config_key_env`.


```

--------------------------------------------------------------------------------
/docs/examples/oauth-delegation.md:
--------------------------------------------------------------------------------

```markdown
---
title: OAuth Delegation
---

# Example: OAuth Delegation

Folder: `/examples/oauth-delegation`

What it shows
- Enabling `oauth_delegation` and providers
- Using `OAuthFlowController` to complete flows

Run
1. Configure providers and redirect URIs
2. Start Node server and visit `/oauth` UI


```

--------------------------------------------------------------------------------
/docs/examples/cloudflare-worker.md:
--------------------------------------------------------------------------------

```markdown
---
title: Cloudflare Worker
---

# Example: Cloudflare Worker

Folder: `/examples/cloudflare-worker`

What it shows
- Worker `fetch` handler delegating to runtime adapter
- Using `wrangler.toml` from `/deploy/cloudflare`

Run
1. `npm run build:worker`
2. `npx wrangler dev examples/cloudflare-worker/worker.ts`


```

--------------------------------------------------------------------------------
/src/types/jose-shim.d.ts:
--------------------------------------------------------------------------------

```typescript
declare module 'jose' {
  export function createRemoteJWKSet(url: URL): any
  export function jwtVerify(
    jwt: string,
    key: any,
    options?: { issuer?: string | string[]; audience?: string | string[] }
  ): Promise<{ payload: any; protectedHeader: any }>
  export function decodeJwt(jwt: string): any
}


```

--------------------------------------------------------------------------------
/tsconfig.worker.json:
--------------------------------------------------------------------------------

```json
{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
    "outDir": "dist/worker",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "types": [],
    "lib": ["ES2022", "WebWorker"]
  },
  "exclude": [
    "src/runtime/node.ts",
    "src/utils/crypto.ts",
    "src/config/**",
    "src/auth/token-manager.ts"
  ]
}

```

--------------------------------------------------------------------------------
/docs/deployment/index.md:
--------------------------------------------------------------------------------

```markdown
---
title: Deployment Overview
---

# Deployment Overview

Supported targets
- Docker (Node runtime)
- Cloudflare Workers
- Koyeb (Node runtime)

Deployment assets live in `/deploy/*`. Platform-specific guides reference these files and environment variable requirements.

See architecture: `docs/architecture/phase10-deployment-architecture.md`.


```

--------------------------------------------------------------------------------
/deploy/docker/entrypoint.sh:
--------------------------------------------------------------------------------

```bash
#!/bin/sh
set -e

# Map PaaS-provided PORT to MASTER_HOSTING_PORT if not explicitly set.
if [ -n "${PORT}" ] && [ -z "${MASTER_HOSTING_PORT}" ]; then
  export MASTER_HOSTING_PORT="${PORT}"
fi

# Default to json logs in production if not set
if [ "${NODE_ENV}" = "production" ] && [ -z "${LOG_FORMAT}" ]; then
  export LOG_FORMAT=json
fi

exec "$@"


```

--------------------------------------------------------------------------------
/docs/guides/index.md:
--------------------------------------------------------------------------------

```markdown
---
title: Guides
---

# User Guides

Structured, task-based guides for common scenarios across auth, routing, configuration, testing, and operations.

Recommended path by persona
- Developers: Authentication → Module Loading → Request Routing
- DevOps: Configuration → Deployment → Monitoring
- Integrators: OAuth Delegation → Routing policies → Security


```

--------------------------------------------------------------------------------
/docs/examples/advanced-routing.md:
--------------------------------------------------------------------------------

```markdown
---
title: Advanced Routing
---

# Example: Advanced Routing

Folder: `/examples/advanced-routing`

What it shows
- Configure retry policy with backoff/jitter
- Circuit breaker thresholds and recovery
- Load balancer strategies

Run
1. Use `config.yaml` from the example
2. Start the server with `CONFIG_PATH=examples/advanced-routing/config.yaml npm start`


```

--------------------------------------------------------------------------------
/docs/configuration/environment.md:
--------------------------------------------------------------------------------

```markdown
---
title: Environment Variables
---

# Environment Variables

Common variables
- `NODE_ENV`: `development` | `production`
- `PORT`: overrides `hosting.port`
- OAuth secrets: `MASTER_OAUTH_CLIENT_SECRET`, provider secrets
- Encryption: key name from `security.config_key_env`

Use `.env` for local development and set secrets via platform secrets in production.


```

--------------------------------------------------------------------------------
/examples/basic-node/config.yaml:
--------------------------------------------------------------------------------

```yaml
hosting:
  platform: node
  port: 3000

master_oauth:
  authorization_endpoint: https://example.com/oauth/authorize
  token_endpoint: https://example.com/oauth/token
  client_id: master-mcp
  redirect_uri: http://localhost:3000/oauth/callback
  scopes: [openid]

servers:
  - id: tools
    type: local
    auth_strategy: bypass_auth
    config:
      port: 3333


```

--------------------------------------------------------------------------------
/tests/factories/mcpFactory.ts:
--------------------------------------------------------------------------------

```typescript
import type { ToolDefinition, ResourceDefinition } from '../../src/types/mcp.js'

export function makeTools(...names: string[]): ToolDefinition[] {
  return names.map((n) => ({ name: n, description: `${n} tool` }))
}

export function makeResources(...uris: string[]): ResourceDefinition[] {
  return uris.map((u) => ({ uri: u, name: u, mimeType: 'text/plain' }))
}


```

--------------------------------------------------------------------------------
/static/oauth/success.html:
--------------------------------------------------------------------------------

```html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>OAuth Success</title>
  <link rel="stylesheet" href="/static/oauth/style.css" />
</head>
<body>
  <main class="container">
    <h1>Success</h1>
    <p>Authorization completed successfully.</p>
  </main>
</body>
</html>


```

--------------------------------------------------------------------------------
/typedoc.json:
--------------------------------------------------------------------------------

```json
{
  "$schema": "https://typedoc.org/schema.json",
  "entryPoints": [
    "src"
  ],
  "tsconfig": "tsconfig.node.json",
  "plugin": ["typedoc-plugin-markdown"],
  "out": "docs/api",
  "cleanOutputDir": false,
  "categorizeByGroup": false,
  "hideBreadcrumbs": true,
  "excludePrivate": true,
  "excludeProtected": false,
  "excludeInternal": true,
  "readme": "none"
}


```

--------------------------------------------------------------------------------
/docs/troubleshooting/routing.md:
--------------------------------------------------------------------------------

```markdown
---
title: Routing & Modules
---

# Troubleshooting: Routing & Modules

- Missing capabilities: call `discoverAllCapabilities()` after loading servers.
- Unhealthy backend: check health checks and restart via `restartServer(id)`.
- Retry storms: reduce `maxRetries` or increase `baseDelayMs`.
- Circuit breaker open: lower `failureThreshold` or increase recovery timeout.


```

--------------------------------------------------------------------------------
/docs/contributing/dev-setup.md:
--------------------------------------------------------------------------------

```markdown
---
title: Development Setup
---

# Development Setup

Prerequisites
- Node 18.17+
- npm or pnpm

Common commands
- `npm run build` — build Node and Worker bundles
- `npm run dev` — start local server
- `npm run test` — run test suites
- `npm run lint` / `npm run format` — code quality

Docs
- `npm run docs:api` — generate API reference
- `npm run docs:dev` — serve docs locally


```

--------------------------------------------------------------------------------
/examples/sample-configs/basic.yaml:
--------------------------------------------------------------------------------

```yaml
hosting:
  platform: node
  port: 3000

master_oauth:
  authorization_endpoint: https://example.com/auth
  token_endpoint: https://example.com/token
  client_id: demo-client
  redirect_uri: http://localhost:3000/callback
  scopes:
    - openid

servers:
  - id: example
    type: local
    auth_strategy: master_oauth
    config:
      environment: {}
      args: []
      port: 3333


```

--------------------------------------------------------------------------------
/static/oauth/error.html:
--------------------------------------------------------------------------------

```html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>OAuth Error</title>
  <link rel="stylesheet" href="/static/oauth/style.css" />
</head>
<body>
  <main class="container error">
    <h1>Authorization Error</h1>
    <p>Something went wrong during the OAuth flow.</p>
  </main>
</body>
</html>


```

--------------------------------------------------------------------------------
/docs/examples/basic-node.md:
--------------------------------------------------------------------------------

```markdown
---
title: Basic Node Aggregator
---

# Example: Basic Node Aggregator

Folder: `/examples/basic-node`

What it shows
- Load two MCP servers from config
- Expose health, metrics, and MCP endpoints
- Validate configuration with schema

Run
1. `npm run build`
2. `node examples/basic-node/server.ts` (ts-node recommended for dev)

Config
- Copy and adapt `examples/sample-configs/basic.yaml`.


```

--------------------------------------------------------------------------------
/docs/getting-started/quickstart-workers.md:
--------------------------------------------------------------------------------

```markdown
---
title: Quickstart (Workers)
---

# Quickstart (Cloudflare Workers)

Run Master MCP in Cloudflare Workers runtime using `src/runtime/worker.ts`.

Steps
1. Copy `deploy/cloudflare/wrangler.toml` and adjust env vars.
2. Build worker bundle: `npm run build:worker`.
3. Publish with Wrangler: `npx wrangler deploy`.

See also: Deployment → Cloudflare Workers and Examples → Cloudflare Worker.


```

--------------------------------------------------------------------------------
/docs/getting-started/installation.md:
--------------------------------------------------------------------------------

```markdown
---
title: Installation
---

# Installation

Prerequisites
- Node.js >= 18.17
- npm or pnpm

Install
1. Clone the repository and install deps: `npm install`
2. Copy `.env.example` to `.env` and adjust values.
3. Build Node and Worker bundles: `npm run build`

Run (Node)
- Dev: `npm run dev` or `npm run dev:watch`
- Prod: `npm run start:prod`

Next: Quickstart (Node) or Quickstart (Workers)


```

--------------------------------------------------------------------------------
/examples/sample-configs/simple-setup.yaml:
--------------------------------------------------------------------------------

```yaml
hosting:
  platform: node
  port: 3000

master_oauth:
  authorization_endpoint: https://auth.example.com/authorize
  token_endpoint: https://auth.example.com/token
  client_id: master-mcp
  redirect_uri: http://localhost:3000/oauth/callback
  scopes: [openid, profile]

servers:
  - id: local-simple
    type: local
    auth_strategy: bypass_auth
    config:
      port: 4001
      environment: {}


```

--------------------------------------------------------------------------------
/tests/factories/oauthFactory.ts:
--------------------------------------------------------------------------------

```typescript
export function makeToken(overrides?: Partial<{ access_token: string; expires_in: number; scope: string | string[] }>) {
  const scope = overrides?.scope ?? ['openid']
  return {
    access_token: overrides?.access_token ?? `at_${Math.random().toString(36).slice(2)}`,
    token_type: 'bearer',
    expires_in: overrides?.expires_in ?? 3600,
    scope: Array.isArray(scope) ? scope.join(' ') : scope,
  }
}


```

--------------------------------------------------------------------------------
/src/runtime/node.ts:
--------------------------------------------------------------------------------

```typescript
import express from 'express'
import { createServer } from '../index.js'

export async function startNode() {
  const app = express()
  await createServer()
  const port = process.env.PORT ? Number(process.env.PORT) : 3000
  app.get('/health', (_req, res) => res.json({ ok: true }))
  app.listen(port, () => {
    // eslint-disable-next-line no-console
    console.log(`Master MCP (Node) on ${port}`)
  })
}


```

--------------------------------------------------------------------------------
/docs/contributing/guidelines.md:
--------------------------------------------------------------------------------

```markdown
---
title: Coding & Docs Guidelines
---

# Coding & Docs Guidelines

Code
- Follow TypeScript strictness and ESLint rules.
- Prefer TSDoc comments for public APIs with `@example` where useful.
- Keep modules cohesive and avoid unrelated changes.

Docs
- Write in Markdown under `/docs`.
- Add pages to VitePress sidebar via `.vitepress/config.ts`.
- For API docs, rely on TypeDoc output under `/docs/api/reference`.


```

--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# Changelog

All notable changes to this project will be documented in this file.

## 0.1.0 – Phase 11 (Final)

- Complete documentation set (guides, tutorials, configuration, deployment)
- API reference pipeline via TypeDoc
- Working examples for Node, OAuth delegation, multi-server, custom auth, performance, security
- Deployment guides for Docker, Cloudflare Workers, and Koyeb
- Troubleshooting and best practices


```

--------------------------------------------------------------------------------
/docs/contributing/maintenance.md:
--------------------------------------------------------------------------------

```markdown
---
title: Maintenance Procedures
---

# Maintenance & Updates

- After adding/changing public APIs: update TSDoc and run `npm run docs:api`.
- After changing config schema or examples: run `npm run docs:config`.
- Before releases: run `npm run docs:all` and preview with `npm run docs:preview`.
- Keep `.vitepress/config.ts` nav/sidebars in sync with new pages.
- Update examples under `/examples/*` and link from `/docs/examples`.


```

--------------------------------------------------------------------------------
/docs/api/functions/createServer.md:
--------------------------------------------------------------------------------

```markdown
[**master-mcp-server**](../README.md)

***

# Function: createServer()

> **createServer**(`startHttp`): `Promise`\<[`RunningServer`](../interfaces/RunningServer.md)\>

Defined in: [index.ts:18](https://github.com/solita-internal/master-mcp-server/blob/cd13e0009f7a1b7f244de882dc738bbf1f90f2c2/src/index.ts#L18)

## Parameters

### startHttp

`boolean` = `true`

## Returns

`Promise`\<[`RunningServer`](../interfaces/RunningServer.md)\>

```

--------------------------------------------------------------------------------
/docs/troubleshooting/oauth.md:
--------------------------------------------------------------------------------

```markdown
---
title: OAuth & Tokens
---

# Troubleshooting: OAuth & Tokens

- Symptom: `invalid_grant` — Check code exchange timing and redirect URI match.
- Symptom: `invalid_client` — Verify client_id/secret; rotate if leaked.
- Symptom: missing `Authorization` — Ensure client token is passed to router/handler.
- Symptom: provider callback 404 — Mount `OAuthFlowController` endpoints.

Logs
- Increase log level to `debug` to see flow details.


```

--------------------------------------------------------------------------------
/docs/troubleshooting/security-best-practices.md:
--------------------------------------------------------------------------------

```markdown
# Security Best Practices

- Store secrets in environment or platform secret stores; avoid plaintext in config
- Set `TOKEN_ENC_KEY` in production and rotate periodically
- Use minimal OAuth scopes and avoid long-lived tokens when possible
- Prefer `LOG_FORMAT=json` and sanitize logs; `SecretManager.redact` prevents secret leakage in config logs
- Enforce `https` at the edge and set `MASTER_BASE_URL=https://...` to ensure secure redirects


```

--------------------------------------------------------------------------------
/tests/_setup/vitest.setup.ts:
--------------------------------------------------------------------------------

```typescript
// Global test setup for Node-targeted suites
import { Logger } from '../../src/utils/logger.js'

// Reduce log noise; allow tests to opt into capture
Logger.configure({ level: 'error', json: true })

// Node 18 has global fetch; ensure it exists for all tests
if (typeof fetch !== 'function') {
  // eslint-disable-next-line @typescript-eslint/no-var-requires
  const nodeFetch = require('node-fetch')
  // @ts-ignore
  globalThis.fetch = nodeFetch
}


```

--------------------------------------------------------------------------------
/docs/examples/index.md:
--------------------------------------------------------------------------------

```markdown
---
title: Examples
---

# Examples

Real-world usage patterns for Node and Workers with routing, OAuth, and configuration.

- Basic Node Aggregator — minimal end-to-end setup
- Cloudflare Worker — Workers runtime entry
- Advanced Routing — retries, circuit-breaking, load balancing
- OAuth Delegation — per-backend OAuth flows
- Testing Patterns — integrate with the test utilities

Each example has a runnable skeleton under `/examples/*` with a README.


```

--------------------------------------------------------------------------------
/tests/perf/artillery/auth-routing.yaml:
--------------------------------------------------------------------------------

```yaml
config:
  target: "http://127.0.0.1:3000"
  phases:
    - duration: 30
      arrivalRate: 10
    - duration: 60
      arrivalRate: 25
scenarios:
  - name: "Call tool echo"
    flow:
      - post:
          url: "/mcp/tools/call"
          json:
            name: "backend.echo"
            arguments: { msg: "hello" }
      - think: 1
  - name: "Read resource"
    flow:
      - post:
          url: "/mcp/resources/read"
          json:
            uri: "backend.docs.readme"


```

--------------------------------------------------------------------------------
/docs/guides/oauth-delegation.md:
--------------------------------------------------------------------------------

```markdown
---
title: OAuth Delegation
---

# OAuth Delegation Guide

Enable per-server OAuth by delegating authorization flows.

- Configure `oauth_delegation.enabled: true` and optional `providers` map.
- Implement callback base URL and provider-specific overrides.
- Use `FlowController` with Express or Workers runtime to complete flows.

Security
- Use state and PKCE to prevent CSRF and code interception.
- Restrict allowed redirect URIs.

See: `src/oauth/*` and `examples/oauth-delegation/`.


```

--------------------------------------------------------------------------------
/static/oauth/consent.html:
--------------------------------------------------------------------------------

```html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Connect Account</title>
  <link rel="stylesheet" href="/static/oauth/style.css" />
  <script src="/static/oauth/script.js" defer></script>
</head>
<body>
  <main class="container">
    <h1>Connect Your Account</h1>
    <p>This page is a placeholder template. The server may use dynamic pages for provider redirect.</p>
  </main>
</body>
</html>


```

--------------------------------------------------------------------------------
/docs/guides/testing.md:
--------------------------------------------------------------------------------

```markdown
---
title: Testing Strategy
---

# Testing Strategy

Phase 9 established a comprehensive strategy with unit, integration, e2e, perf, and security tests.

- Structure: see `/tests` directories by test type.
- Runtimes: run both Node and Workers (Miniflare) where applicable.
- Utilities: `_utils` helpers for HTTP, logging, and test servers.

Commands
- `npm run test` — run all tests
- `npm run test:unit|integration|e2e|perf|security`

See also: `docs/testing/phase-9-testing-architecture.md`.


```

--------------------------------------------------------------------------------
/docs/deployment/koyeb.md:
--------------------------------------------------------------------------------

```markdown
# Deploy on Koyeb

Use the CI-built image and the service manifest in `deploy/koyeb/koyeb.yaml`.

## Steps

1) Build and push an image to GHCR or Docker Hub
2) In Koyeb, create a new service from container image
3) Set environment variables and secrets:
   - `NODE_ENV=production`
   - `TOKEN_ENC_KEY` (secret)
   - `MASTER_BASE_URL` set to your Koyeb app URL
4) Configure autoscaling (see example manifest)

The platform-provided `PORT` is mapped automatically to `MASTER_HOSTING_PORT` by `deploy/docker/entrypoint.sh`.


```

--------------------------------------------------------------------------------
/docs/getting-started/concepts.md:
--------------------------------------------------------------------------------

```markdown
---
title: Core Concepts
---

# Core Concepts

- Master OAuth: centralized OAuth for aggregated servers.
- Delegated OAuth: per-server OAuth via delegation.
- Module Loader: fetches and manages external MCP servers.
- Request Router: registers routes and dispatches requests, with retries and circuit breaking.
- Runtime Abstraction: Node vs Workers environment differences.
- Config System: schema validation, secrets, and environment.

Architecture references are available under `docs/architecture/phase*-architecture.md`.


```

--------------------------------------------------------------------------------
/docs/getting-started/quickstart-node.md:
--------------------------------------------------------------------------------

```markdown
---
title: Quickstart (Node)
---

# Quickstart (Node)

This minimal example runs Master MCP Server in Node, aggregating two servers.

Steps
1. Create a config file (e.g., `config/master.yaml`) based on `examples/sample-configs/basic.yaml`.
2. Start the server: `npm run start`.
3. Connect your MCP client to the exposed endpoint.

Highlights
- Uses `src/runtime/node.ts` to bootstrap.
- Validates config with `SchemaValidator`.
- Routes requests via `RouteRegistry` and `RequestRouter`.

See also: Examples → Basic Node Aggregator.


```

--------------------------------------------------------------------------------
/docs/configuration/overview.md:
--------------------------------------------------------------------------------

```markdown
---
title: Configuration Overview
---

# Configuration Overview

The Master MCP configuration is validated against a JSON Schema (`SchemaValidator`).

Key Sections
- `master_oauth`: top-level OAuth issuer/client settings
- `hosting`: platform and runtime options
- `logging`, `security`: operational controls
- `routing`: load balancing, retries, circuit breakers
- `servers[]`: aggregated MCP servers with per-entry config

Start with examples in `/examples/sample-configs/*.yaml`.
Generate the full reference with `npm run docs:config`.


```

--------------------------------------------------------------------------------
/docs/guides/configuration.md:
--------------------------------------------------------------------------------

```markdown
---
title: Configuration
---

# Configuration Guide

Centralized configuration with schema validation and secrets.

- Types: `MasterConfig`, `HostingConfig`, `RoutingConfig`, `ServerConfig`, `SecurityConfig`.
- Validation: `SchemaValidator` with built-in default schema.
- Secrets: `SecretManager` decrypts protected values; keys from `SecurityConfig.config_key_env`.
- Environments: `EnvironmentManager` to load/merge env vars.

Commands
- Generate reference from schema: `npm run docs:config`

See: Configuration → Reference for full schema.


```

--------------------------------------------------------------------------------
/tsconfig.base.json:
--------------------------------------------------------------------------------

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "rootDir": "src",
    "strict": true,
    "noImplicitOverride": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "forceConsistentCasingInFileNames": true,
    "skipLibCheck": false,
    "sourceMap": true,
    "declaration": true,
    "declarationMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "moduleResolution": "NodeNext",
    "types": []
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "tests"]
}


```

--------------------------------------------------------------------------------
/docs/.vitepress/theme/index.ts:
--------------------------------------------------------------------------------

```typescript
import DefaultTheme from 'vitepress/theme'
import type { Theme } from 'vitepress'
import CodeTabs from './components/CodeTabs.vue'
import ConfigGenerator from './components/ConfigGenerator.vue'
import AuthFlowDemo from './components/AuthFlowDemo.vue'
import ApiPlayground from './components/ApiPlayground.vue'
import './style.css'

const theme: Theme = {
  ...DefaultTheme,
  enhanceApp({ app }) {
    app.component('CodeTabs', CodeTabs)
    app.component('ConfigGenerator', ConfigGenerator)
    app.component('AuthFlowDemo', AuthFlowDemo)
    app.component('ApiPlayground', ApiPlayground)
  },
}

export default theme


```

--------------------------------------------------------------------------------
/docs/api/index.md:
--------------------------------------------------------------------------------

```markdown
---
title: API Overview
---

# API Overview

The API reference is generated from TypeScript sources using TypeDoc and the `typedoc-plugin-markdown` plugin.

- Generated docs output: `/api/reference/`
- Generation config: `typedoc.json`
- Command: `npm run docs:api`

Key entry points
- `MasterServer` — main orchestration server
- `ModuleLoader`, `RequestRouter`, `CapabilityAggregator` — module and routing
- `MultiAuthManager`, `TokenManager` — authentication core
- `FlowController` and related OAuth utilities — OAuth flows
- `SchemaValidator`, `ConfigLoader` — configuration

See `/api/reference/` for the full API.


```

--------------------------------------------------------------------------------
/docs/deployment/cloudflare-workers.md:
--------------------------------------------------------------------------------

```markdown
# Deploy on Cloudflare Workers

Configuration lives in `deploy/cloudflare/wrangler.toml`.

## Setup

```
wrangler whoami
wrangler login
```

Set secrets:

```
wrangler secret put TOKEN_ENC_KEY
# Optional provider secrets as needed
```

Bind KV for token persistence (optional but recommended):

```
wrangler kv:namespace create TOKENS
# Add binding to wrangler.toml and your environments
```

## Dev and Deploy

```
wrangler dev
wrangler deploy --env staging
wrangler deploy --env production
```

Ensure your config uses `hosting.platform=cloudflare-workers` (auto-detected) and `hosting.base_url` is set for OAuth redirects.


```

--------------------------------------------------------------------------------
/docs/examples/overview.md:
--------------------------------------------------------------------------------

```markdown
# Examples Overview

This directory groups runnable examples demonstrating common scenarios:

- `examples/basic-node` — Minimal Node runtime with a local backend
- `examples/oauth-node` — OAuth delegation using GitHub
- `examples/multi-server` — Multiple instances, load balancing, retries, circuit breaker
- `examples/custom-auth` — Custom `MultiAuthManager` that tweaks backend headers
- `examples/performance` — Tuning routing for throughput and resilience
- `examples/security-hardening` — Production environment configuration tips

Run each by pointing `MASTER_CONFIG_PATH` and using `npm run dev`, unless a custom launcher is provided.


```

--------------------------------------------------------------------------------
/docs/troubleshooting/performance.md:
--------------------------------------------------------------------------------

```markdown
# Performance Troubleshooting

## Symptoms

- Elevated latency on tool calls
- Increased error rates or timeouts

## Checks

- Inspect `/metrics` (Node) and platform dashboards (Workers, Koyeb)
- Verify backends’ `/health` and logs
- Confirm load-balancing strategy is appropriate for your topology

## Tuning

- Increase `retry.maxRetries` and `baseDelayMs` judiciously
- Switch to `health` strategy and feed health scores when available
- Tighten circuit breaker thresholds to fail fast on unhealthy instances

## Environment

- Run Node with adequate CPU/memory; consider horizontal scaling
- Use KV-backed tokens in Workers to reduce token cache misses


```

--------------------------------------------------------------------------------
/examples/oauth-node/config.yaml:
--------------------------------------------------------------------------------

```yaml
hosting:
  platform: node
  port: 3000

master_oauth:
  authorization_endpoint: https://example.com/oauth/authorize
  token_endpoint: https://example.com/oauth/token
  client_id: master-mcp
  redirect_uri: http://localhost:3000/oauth/callback
  scopes: [openid]

servers:
  - id: github-tools
    type: local
    auth_strategy: delegate_oauth
    auth_config:
      provider: github
      authorization_endpoint: https://github.com/login/oauth/authorize
      token_endpoint: https://github.com/login/oauth/access_token
      client_id: ${GITHUB_CLIENT_ID}
      client_secret: env:GITHUB_CLIENT_SECRET
      scopes: [repo, read:user]
    config:
      port: 4100


```

--------------------------------------------------------------------------------
/deploy/cloudflare/wrangler.toml:
--------------------------------------------------------------------------------

```toml
name = "master-mcp-server"
main = "src/runtime/worker.ts"
compatibility_date = "2024-07-01"
workers_dev = true

# Optional: enable Node compat if needed (try to keep off)
# node_compat = false

[vars]
# Non-sensitive defaults; override per-env below or via dashboard
MASTER_HOSTING_PLATFORM = "workers"
LOG_LEVEL = "info"
LOG_FORMAT = "json"

[env.staging]
name = "master-mcp-server-staging"

[env.staging.vars]
LOG_LEVEL = "debug"

[env.production]
name = "master-mcp-server-prod"

[env.production.vars]
LOG_LEVEL = "info"

# Secrets to provision via: wrangler secret put TOKEN_ENC_KEY
# - TOKEN_ENC_KEY
# - Any OAuth client secrets required by configured backends


```

--------------------------------------------------------------------------------
/examples/advanced-routing/config.yaml:
--------------------------------------------------------------------------------

```yaml
master_oauth:
  authorization_endpoint: https://example.com/auth
  token_endpoint: https://example.com/token
  client_id: example
  redirect_uri: http://localhost:3000/oauth/callback
  scopes: [openid, profile]

hosting:
  platform: node
  port: 3000

routing:
  loadBalancer:
    strategy: round_robin
  retry:
    maxRetries: 3
    baseDelayMs: 250
    maxDelayMs: 4000
    backoffFactor: 2
    jitter: full
  circuitBreaker:
    failureThreshold: 5
    successThreshold: 2
    recoveryTimeoutMs: 30000

servers:
  - id: local-a
    type: local
    auth_strategy: bypass_auth
    config: {}
  - id: local-b
    type: local
    auth_strategy: bypass_auth
    config: {}


```

--------------------------------------------------------------------------------
/vitest.config.ts:
--------------------------------------------------------------------------------

```typescript
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    globals: true,
    include: ['tests/**/*.{test,spec}.ts'],
    exclude: ['tests/workers/**/*', 'dist', 'node_modules'],
    setupFiles: ['tests/_setup/vitest.setup.ts'],
    environment: 'node',
    coverage: {
      reporter: ['text', 'lcov', 'cobertura'],
      provider: 'v8',
      reportsDirectory: './coverage/node',
      all: true,
      include: ['src/**/*.ts'],
      exclude: ['src/runtime/worker.ts', 'src/types/**', 'src/**/index.ts'],
      thresholds: {
        lines: 0.85,
        functions: 0.85,
        branches: 0.8,
        statements: 0.85,
      },
    },
  },
})


```

--------------------------------------------------------------------------------
/docs/getting-started/overview.md:
--------------------------------------------------------------------------------

```markdown
---
title: Overview
---

# Overview

Master MCP Server aggregates multiple MCP servers and exposes a unified endpoint with:

- Authentication: Master OAuth, delegated OAuth, token management.
- Module loading: Git, NPM, PyPI, Docker, local.
- Request routing: load balancing, retries, circuit breakers.
- Configuration: schema validation, secrets, environment management.
- Runtimes: Node and Cloudflare Workers.
- Testing and Deployment: comprehensive strategy with CI.

Who is this for?
- Developers integrating MCP into applications.
- DevOps engineers deploying/managing the server.
- System integrators configuring auth and routing.

Continue with Installation and Quickstarts.


```

--------------------------------------------------------------------------------
/docs/troubleshooting/errors.md:
--------------------------------------------------------------------------------

```markdown
# Error Reference

## Configuration validation failed

The config did not conform to the schema. The error lists the path and reason. Fix the offending property and reload.

## CircuitOpenError

The circuit breaker is open for the selected upstream instance. Reduce upstream failures or increase `recoveryTimeoutMs`. Calls will resume after a successful half-open trial.

## OAuthError

An upstream OAuth provider response was invalid. Check client credentials, scopes, and redirect URIs.

## Token decryption failed

Persisted token ciphertext could not be decrypted with `TOKEN_ENC_KEY`. Ensure the key has not changed unexpectedly. Clear token storage if necessary and re-authorize.


```

--------------------------------------------------------------------------------
/docs/tutorials/cloudflare-workers-tutorial.md:
--------------------------------------------------------------------------------

```markdown
# Tutorial: Cloudflare Workers

Run Master MCP Server on Cloudflare Workers with the provided runtime.

## 1) Prerequisites

- Cloudflare account
- `wrangler` CLI

## 2) Configure

Update `deploy/cloudflare/wrangler.toml` as needed. Secrets:

```
wrangler secret put TOKEN_ENC_KEY
```

If you need persistent token storage, bind a KV namespace named `TOKENS` and pass it via environment bindings.

## 3) Dev

```
wrangler dev
```

## 4) Deploy

```
wrangler deploy --env staging
wrangler deploy --env production
```

Ensure `hosting.platform` resolves to `cloudflare-workers` (detected automatically) and that `hosting.base_url` is set appropriately if you rely on absolute redirects for OAuth.


```

--------------------------------------------------------------------------------
/tests/unit/config.secret-manager.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { SecretManager } from '../../src/config/secret-manager.js'

test('SecretManager encrypt/decrypt and resolve env placeholders', () => {
  const sm = new SecretManager({ key: 'k123' })
  const enc = sm.encrypt('s3cr3t')
  assert.ok(sm.isEncrypted(enc))
  assert.equal(sm.decrypt(enc), 's3cr3t')

  process.env.MY_TOKEN = 'abc'
  const cfg = { a: enc, b: 'env:MY_TOKEN', c: { password: 'x' } }
  const resolved = sm.resolveSecrets(cfg)
  assert.equal(resolved.a, 's3cr3t')
  assert.equal(resolved.b, 'abc')
  const redacted = sm.redact(resolved)
  assert.equal(redacted.c.password, '***')
})


```

--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------

```json
{
  "hosting": {
    "platform": "node",
    "port": 3005,
    "base_url": "http://localhost:3005"
  },
  "master_oauth": {
    "authorization_endpoint": "https://github.com/login/oauth/authorize",
    "token_endpoint": "https://github.com/login/oauth/access_token",
    "client_id": "Ov23li2S7w1LYoM4yLJP",
    "client_secret": "9f2cebe77974976e5fe7125eb50edefa81ee5219",
    "redirect_uri": "http://localhost:3005/oauth/callback",
    "scopes": ["read:user", "user:email"]
  },
  "servers": [
    {
      "id": "test-server",
      "type": "local",
      "url": "http://localhost:3006",
      "auth_strategy": "bypass_auth",
      "config": {
        "environment": {},
        "args": []
      }
    }
  ]
}
```

--------------------------------------------------------------------------------
/tests/utils/token-storages.ts:
--------------------------------------------------------------------------------

```typescript
import type { TokenStorage } from '../../src/auth/token-manager.js'

export class MemoryKVStorage implements TokenStorage {
  private kv = new Map<string,string>()
  async set(key: string, value: string) { this.kv.set(key, value) }
  async get(key: string) { return this.kv.get(key) }
  async delete(key: string) { this.kv.delete(key) }
  async *entries() { for (const e of this.kv.entries()) yield e }
}

export class RedisLikeStorage implements TokenStorage {
  private map = new Map<string, string>()
  async set(key: string, value: string) { this.map.set(key, value) }
  async get(key: string) { return this.map.get(key) }
  async delete(key: string) { this.map.delete(key) }
  async *entries() { for (const e of this.map.entries()) yield e }
}


```

--------------------------------------------------------------------------------
/docs/tutorials/beginner-getting-started.md:
--------------------------------------------------------------------------------

```markdown
# Tutorial: Beginner Setup

Goal: Run Master MCP Server with a single local backend and call a tool.

## 1) Install and Start

```
npm ci
cp .env.example .env
npm run dev
```

## 2) Add a Backend

Create `examples/basic-node/config.yaml` (already provided) and run with:

```
MASTER_CONFIG_PATH=examples/basic-node/config.yaml npm run dev
```

## 3) Verify Health and Capabilities

```
curl http://localhost:3000/health
curl -X POST http://localhost:3000/mcp/tools/list -H 'content-type: application/json' -d '{}'
```

## 4) Call a Tool

```
curl -X POST http://localhost:3000/mcp/tools/call \
  -H 'content-type: application/json' \
  -d '{"name":"tools.echo","arguments":{"text":"hello"}}'
```

Replace `tools.echo` with a tool exposed by your backend.


```

--------------------------------------------------------------------------------
/examples/custom-auth/config.yaml:
--------------------------------------------------------------------------------

```yaml
hosting:
  platform: node
  port: 3000

master_oauth:
  authorization_endpoint: https://example.com/oauth/authorize
  token_endpoint: https://example.com/oauth/token
  client_id: master-mcp
  redirect_uri: http://localhost:3000/oauth/callback
  scopes: [openid]

servers:
  - id: public-tools
    type: local
    auth_strategy: bypass_auth
    config:
      port: 4200

  - id: custom-proxy
    type: local
    auth_strategy: proxy_oauth
    auth_config:
      provider: google
      authorization_endpoint: https://accounts.google.com/o/oauth2/v2/auth
      token_endpoint: https://oauth2.googleapis.com/token
      client_id: ${GOOGLE_CLIENT_ID}
      client_secret: env:GOOGLE_CLIENT_SECRET
      scopes: [openid, profile, email]
    config:
      port: 4201


```

--------------------------------------------------------------------------------
/deploy/koyeb/koyeb.yaml:
--------------------------------------------------------------------------------

```yaml
version: v1

services:
  - name: master-mcp
    type: web
    ports:
      - port: 80
        protocol: http
    instance_types:
      - micro
    min_instances: 2
    max_instances: 10
    scaling:
      metric: cpu
      target: 70
      stabilization_window: 60
    health_check:
      path: /health
      interval: 10s
      timeout: 3s
      unhealthy_threshold: 3
      healthy_threshold: 1
    docker:
      image: ghcr.io/OWNER/REPO:latest # replaced by CI/CD
      env:
        - key: NODE_ENV
          value: production
        - key: LOG_FORMAT
          value: json
        - key: LOG_LEVEL
          value: info
        # Koyeb provides PORT; entrypoint maps it to hosting.port
        - key: TOKEN_ENC_KEY
          value: ${TOKEN_ENC_KEY} # set via Koyeb secrets


```

--------------------------------------------------------------------------------
/vitest.worker.config.ts:
--------------------------------------------------------------------------------

```typescript
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    globals: true,
    include: ['tests/workers/**/*.{test,spec}.ts'],
    setupFiles: ['tests/_setup/miniflare.setup.ts'],
    environment: 'miniflare',
    environmentOptions: {
      modules: true,
      script: undefined, // tests import modules directly
      bindings: {},
      kvNamespaces: [],
      durableObjects: {},
    },
    coverage: {
      reporter: ['text', 'lcov'],
      provider: 'v8',
      reportsDirectory: './coverage/workers',
      all: true,
      include: ['src/**/*.ts'],
      exclude: ['src/runtime/node.ts', 'src/types/**'],
      thresholds: {
        lines: 0.8,
        functions: 0.8,
        branches: 0.75,
        statements: 0.8,
      },
    },
  },
})


```

--------------------------------------------------------------------------------
/tests/unit/modules/stdio-capability-discovery.test.ts:
--------------------------------------------------------------------------------

```typescript
import { test } from 'node:test'
import assert from 'node:assert'
import { StdioCapabilityDiscovery } from '../../../src/modules/stdio-capability-discovery.js'
import { StdioManager } from '../../../src/modules/stdio-manager.js'

test('StdioCapabilityDiscovery should instantiate correctly', async () => {
  const manager = new StdioManager()
  const discovery = new StdioCapabilityDiscovery(manager)
  assert.ok(discovery)
})

test('StdioCapabilityDiscovery should have required methods', async () => {
  const manager = new StdioManager()
  const discovery = new StdioCapabilityDiscovery(manager)
  assert.strictEqual(typeof discovery.discoverCapabilities, 'function')
  assert.strictEqual(typeof discovery.callTool, 'function')
  assert.strictEqual(typeof discovery.readResource, 'function')
})
```

--------------------------------------------------------------------------------
/docs/configuration/performance.md:
--------------------------------------------------------------------------------

```markdown
# Performance & Tuning

Tune routing and runtime to handle your workload.

## Routing

- Prefer `health` strategy to route to instances with better health scores (when provided)
- Increase `retry.maxRetries` for flaky networks, but cap `maxDelayMs`
- Use `jitter: full` to avoid thundering herds
- Adjust `circuitBreaker` thresholds based on observed upstream reliability

## Node Runtime

- Use `NODE_ENV=production`
- Run behind a reverse proxy (nginx, Cloudflare) for TLS termination
- Set `LOG_LEVEL=info` or `warn`

## Workers Runtime

- Bind KV storage for token persistence to avoid in-memory losses across isolates
- Avoid large responses; stream when possible

## Observability

- Use `/metrics` to scrape basic system stats in Node
- Add platform logs/metrics (Cloudflare, Koyeb dashboards)


```

--------------------------------------------------------------------------------
/examples/multi-server/config.yaml:
--------------------------------------------------------------------------------

```yaml
hosting:
  platform: node
  port: 3000

master_oauth:
  authorization_endpoint: https://example.com/oauth/authorize
  token_endpoint: https://example.com/oauth/token
  client_id: master-mcp
  redirect_uri: http://localhost:3000/oauth/callback
  scopes: [openid]

routing:
  loadBalancer:
    strategy: health
  circuitBreaker:
    failureThreshold: 3
    successThreshold: 2
    recoveryTimeoutMs: 10000
  retry:
    maxRetries: 3
    baseDelayMs: 200
    maxDelayMs: 3000
    backoffFactor: 2
    jitter: full
    retryOn:
      networkErrors: true
      httpStatuses: [408, 429]
      httpStatusClasses: [5]

servers:
  - id: compute
    type: local
    auth_strategy: bypass_auth
    config:
      port: 4101
  - id: compute
    type: local
    auth_strategy: bypass_auth
    config:
      port: 4102


```

--------------------------------------------------------------------------------
/deploy/docker/docker-compose.yml:
--------------------------------------------------------------------------------

```yaml
version: '3.9'

services:
  master-mcp:
    build:
      context: ../..
      dockerfile: deploy/docker/Dockerfile
      args:
        - NODE_VERSION=20
    image: master-mcp:dev
    environment:
      - NODE_ENV=development
      - LOG_LEVEL=debug
      - MASTER_HOSTING_PLATFORM=node
      - MASTER_BASE_URL=http://localhost:3000
      # TOKEN_ENC_KEY is recommended even in dev to persist tokens across restarts
      - TOKEN_ENC_KEY=dev-dev-dev-dev-dev-dev-dev-dev
    ports:
      - "3000:3000"
    volumes:
      - ../../config:/app/config:ro
    healthcheck:
      test: ["CMD", "node", "-e", "const http=require('http');http.get('http://127.0.0.1:3000/health',r=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))"]
      interval: 5s
      timeout: 3s
      retries: 20
      start_period: 10s


```

--------------------------------------------------------------------------------
/docs/troubleshooting/common-issues.md:
--------------------------------------------------------------------------------

```markdown
# Troubleshooting: Common Issues

## Config validation failed

- Error shows `<path>: <reason>` from `SchemaValidator`
- Verify your file is valid JSON/YAML
- Check required fields under `master_oauth`, `hosting`, `servers`

## Missing TOKEN_ENC_KEY in production

- Set `TOKEN_ENC_KEY` to a strong random string
- In development, an ephemeral key is generated with a warning

## OAuth callback mismatch

- Ensure `master_oauth.redirect_uri` matches your runtime base URL
- If behind a proxy, set `MASTER_BASE_URL` to the external URL

## 401 Unauthorized to backends

- Ensure client token is valid or delegated tokens are stored
- For delegated flows, complete `/oauth/authorize` and `/oauth/callback` first

## Workers runtime odd redirects

- Always set `hosting.base_url` in Workers to generate correct absolute URLs


```

--------------------------------------------------------------------------------
/examples/performance/config.yaml:
--------------------------------------------------------------------------------

```yaml
hosting:
  platform: node
  port: 3000

master_oauth:
  authorization_endpoint: https://example.com/oauth/authorize
  token_endpoint: https://example.com/oauth/token
  client_id: master-mcp
  redirect_uri: http://localhost:3000/oauth/callback
  scopes: [openid]

logging:
  level: info

routing:
  loadBalancer:
    strategy: weighted
  retry:
    maxRetries: 4
    baseDelayMs: 100
    maxDelayMs: 1500
    backoffFactor: 1.8
    jitter: full
    retryOn:
      networkErrors: true
      httpStatuses: [408, 429]
      httpStatusClasses: [5]
  circuitBreaker:
    failureThreshold: 4
    successThreshold: 2
    recoveryTimeoutMs: 8000

servers:
  - id: compute
    type: local
    auth_strategy: bypass_auth
    config:
      port: 4301
  - id: compute
    type: local
    auth_strategy: bypass_auth
    config:
      port: 4302


```

--------------------------------------------------------------------------------
/tests/setup/test-setup.ts:
--------------------------------------------------------------------------------

```typescript
// Global test setup for Node test runner with ts-node ESM
// - Configures logger to reduce noise
// - Provides minimal polyfills and deterministic behavior where helpful

import { Logger } from '../../src/utils/logger.js'

// Quiet logs during tests unless DEBUG is set
Logger.configure({ level: (process.env.DEBUG ? 'debug' : 'error') as any, json: false })

// Ensure process.env defaults for tests
process.env.NODE_ENV = process.env.NODE_ENV || 'test'

// Deterministic Math.random for some tests (can be overridden locally)
const seed = 42
let state = seed
const origRandom = Math.random
globalThis.Math.random = () => {
  if (process.env.TEST_NON_DETERMINISTIC === '1') return origRandom()
  state = (1103515245 * state + 12345) % 0x100000000
  return state / 0x100000000
}

// Export nothing; imported by tests as side-effect
export {}


```

--------------------------------------------------------------------------------
/tests/_utils/log-capture.ts:
--------------------------------------------------------------------------------

```typescript
export class LogCapture {
  private originalLog = console.log
  private originalError = console.error
  private logs: string[] = []
  private errors: string[] = []

  start(): void {
    console.log = (...args: any[]) => {
      try { this.logs.push(args.map(String).join(' ')) } catch {}
      this.originalLog.apply(console, args as any)
    }
    console.error = (...args: any[]) => {
      try { this.errors.push(args.map(String).join(' ')) } catch {}
      this.originalError.apply(console, args as any)
    }
  }

  stop(): void {
    console.log = this.originalLog
    console.error = this.originalError
  }

  find(substr: string): boolean {
    return this.logs.concat(this.errors).some((l) => l.includes(substr))
  }

  dump(): { logs: string[]; errors: string[] } {
    return { logs: [...this.logs], errors: [...this.errors] }
  }
}


```

--------------------------------------------------------------------------------
/src/types/auth.ts:
--------------------------------------------------------------------------------

```typescript
export type AuthHeaders = Record<string, string>

export interface ClientInfo {
  client_id?: string
  redirect_uri?: string
  scopes?: string[]
  metadata?: Record<string, unknown>
}

export interface OAuthDelegation {
  type: 'oauth_delegation'
  auth_endpoint: string
  token_endpoint: string
  client_info: ClientInfo
  required_scopes: string[]
  redirect_after_auth: boolean
}

export interface OAuthToken {
  access_token: string
  refresh_token?: string
  expires_at: number // epoch millis
  scope: string[]
  user_info?: unknown
}

export interface AuthInfo {
  type: 'bearer'
  token: string
}

export interface TokenValidationResult {
  valid: boolean
  expiresAt?: number
  scopes?: string[]
  error?: string
}

export interface UserInfo {
  id: string
  name?: string
  email?: string
  avatarUrl?: string
  [key: string]: unknown
}


```

--------------------------------------------------------------------------------
/static/oauth/style.css:
--------------------------------------------------------------------------------

```css
/* Minimal, responsive styles for OAuth pages */
:root { --bg: #0b0d10; --fg: #e8edf2; --muted: #a9b3bd; --accent: #52b788; }
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0; font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, Noto Sans, "Apple Color Emoji", "Segoe UI Emoji";
  background: var(--bg); color: var(--fg);
  display: grid; place-items: center;
}
.container { width: 100%; max-width: 640px; padding: 24px; }
h1 { font-size: 1.5rem; margin: 0 0 0.5rem; }
p { color: var(--muted); line-height: 1.5; }
.button {
  display: inline-block; background: var(--accent); color: #02120c; font-weight: 600;
  padding: 10px 14px; border-radius: 8px; text-decoration: none; margin-top: 12px;
}
.error h1 { color: #ff8692; }
@media (max-width: 480px) { .container { padding: 16px; } }


```

--------------------------------------------------------------------------------
/tests/servers/test-debug.js:
--------------------------------------------------------------------------------

```javascript
import { MultiAuthManager } from '../../src/auth/multi-auth-manager.js'
import { AuthStrategy } from '../../src/types/config.js'

const masterCfg = {
  authorization_endpoint: 'http://localhost/auth',
  token_endpoint: 'http://localhost/token',
  client_id: 'master',
  redirect_uri: 'http://localhost/cb',
  scopes: ['openid'],
}

try {
  console.log('Creating MultiAuthManager...')
  const mam = new MultiAuthManager(masterCfg)
  console.log('MultiAuthManager created successfully')
  
  console.log('Registering server auth...')
  mam.registerServerAuth('srv1', AuthStrategy.MASTER_OAUTH)
  console.log('Server auth registered')
  
  console.log('Preparing auth for backend...')
  const h = await mam.prepareAuthForBackend('srv1', 'CLIENT')
  console.log('Result:', h)
  
} catch (error) {
  console.error('Error:', error)
  console.error('Stack:', error.stack)
}
```

--------------------------------------------------------------------------------
/tests/utils/oauth-mocks.ts:
--------------------------------------------------------------------------------

```typescript
import { createMockServer, MockServer } from './mock-http.js'

export async function createGitHubMock(): Promise<MockServer> {
  return createMockServer([
    { method: 'GET', path: '/user', handler: () => ({ headers: { 'x-oauth-scopes': 'read:user, repo' }, body: { id: 1, login: 'octocat' } }) },
  ])
}

export async function createGoogleMock(): Promise<MockServer> {
  return createMockServer([
    { method: 'GET', path: '/userinfo', handler: () => ({ body: { sub: '123', name: 'Alice', email: '[email protected]', picture: 'http://x' } }) },
  ])
}

export async function createCustomOIDCMock(): Promise<MockServer> {
  return createMockServer([
    { method: 'POST', path: '/token', handler: () => ({ body: { access_token: 'AT', expires_in: 3600, scope: 'openid' } }) },
    { method: 'GET', path: '/userinfo', handler: () => ({ body: { sub: 'abc', name: 'Bob' } }) },
  ])
}


```

--------------------------------------------------------------------------------
/tests/integration/modules.module-loader-health.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { DefaultModuleLoader } from '../../src/modules/module-loader.js'
import { createMockServer } from '../utils/mock-http.js'

test('DefaultModuleLoader performHealthCheck against /health JSON', async () => {
  const srv = await createMockServer([
    { method: 'GET', path: '/health', handler: () => ({ body: { ok: true } }) },
  ])
  try {
    const loader = new DefaultModuleLoader()
    const ls: any = { id: 'a', type: 'node', endpoint: srv.url, config: {} as any, status: 'starting', lastHealthCheck: 0 }
    const ok = await loader.performHealthCheck(ls)
    assert.equal(ok, true)
    // performHealthCheck doesn't update status, that's done by the load method
    assert(ls.lastHealthCheck > 0, 'lastHealthCheck should be updated')
  } finally {
    await srv.close()
  }
})


```

--------------------------------------------------------------------------------
/docs/deployment/docker.md:
--------------------------------------------------------------------------------

```markdown
# Deploy with Docker

Two Docker setups are provided:

1) Top-level `Dockerfile` (multi-stage) and `docker-compose.yml` for local dev
2) `deploy/docker/Dockerfile` optimized for CI-built images and Koyeb

## Local Development

```
docker compose up --build
```

This uses the dev target with hot reload (`nodemon`) and maps your working directory into the container.

## Production Image (CI)

Build and push an image:

```
docker build -f deploy/docker/Dockerfile -t ghcr.io/OWNER/REPO:latest .
docker push ghcr.io/OWNER/REPO:latest
```

Run:

```
docker run -p 3000:3000 \
  -e NODE_ENV=production \
  -e TOKEN_ENC_KEY=... \
  -e MASTER_BASE_URL=https://your.domain \
  ghcr.io/OWNER/REPO:latest
```

## Environment

- Set `TOKEN_ENC_KEY` in production
- Set `MASTER_BASE_URL` if serving behind a proxy to ensure correct OAuth redirects
- Inject `MASTER_OAUTH_CLIENT_SECRET` and other provider secrets via env


```

--------------------------------------------------------------------------------
/src/types/server.ts:
--------------------------------------------------------------------------------

```typescript
import type { ToolDefinition, ResourceDefinition, PromptDefinition } from './mcp.js'
import type { ServerConfig } from './config.js'

export type ServerType = 'python' | 'node' | 'typescript' | 'stdio' | 'unknown'

export interface ServerProcess {
  pid?: number
  port?: number
  url?: string
  stop: () => Promise<void>
}

export interface ServerCapabilities {
  tools: ToolDefinition[]
  resources: ResourceDefinition[]
  prompts?: PromptDefinition[]
}

export interface LoadedServer {
  id: string
  type: ServerType
  process?: ServerProcess
  endpoint: string
  config: ServerConfig
  capabilities?: ServerCapabilities
  status: 'starting' | 'running' | 'stopped' | 'error'
  lastHealthCheck: number
  // Optional: when a server has multiple deploys/instances
  instances?: ServerInstance[]
}

export interface ServerInstance {
  id: string
  url: string
  weight?: number
  healthScore?: number // 0..100, used by health-based LB
}

```

--------------------------------------------------------------------------------
/docs/guides/module-loading.md:
--------------------------------------------------------------------------------

```markdown
# Module Loading & Capability Aggregation

Master MCP loads backend servers from multiple sources and aggregates their capabilities.

## Sources

- `local`: A locally running server exposing HTTP endpoints
- `git`, `npm`, `pypi`, `docker`: Stubs for different origins; endpoint resolution is config-driven (e.g., `config.port` or `url`).

Example server block:

```yaml
servers:
  - id: search
    type: local
    auth_strategy: master_oauth
    config:
      port: 4100
```

## Health Checks

`DefaultModuleLoader` pings each server’s `/health` endpoint when loading to set an initial status (`running` or `error`).

## Capability Aggregation

`CapabilityAggregator` discovers tools and resources via:

- `GET /capabilities` (optional if provided by backend)
- `POST /mcp/tools/list`
- `POST /mcp/resources/list`

Capabilities can be prefixed by server id (default) to avoid naming conflicts. Use the aggregated names in requests, e.g., `serverId.toolName`.


```

--------------------------------------------------------------------------------
/docs/guides/request-routing.md:
--------------------------------------------------------------------------------

```markdown
# Request Routing & Resilience

Requests are routed by `RequestRouter`, which uses a `RouteRegistry`, `LoadBalancer`, `RetryHandler`, and `CircuitBreaker` to provide resilient upstream calls.

## Endpoints

- Tools: `POST /mcp/tools/call` with `{ name, arguments }`
- Resources: `POST /mcp/resources/read` with `{ uri }`

Names and URIs may be prefixed by server id when aggregated.

## Load Balancing

Configure strategy under `routing.loadBalancer.strategy`:

- `round_robin` (default)
- `weighted`
- `health`

## Retries

`routing.retry` controls attempts with backoff and jitter:

- `maxRetries`, `baseDelayMs`, `maxDelayMs`, `backoffFactor`, `jitter` (`full` or `none`)
- `retryOn.httpStatuses`, `retryOn.httpStatusClasses`, `retryOn.networkErrors`

## Circuit Breaker

`routing.circuitBreaker` manages failure thresholds and recovery:

- `failureThreshold`, `successThreshold`, `recoveryTimeoutMs`

When open, requests fail fast with a retry-after hint.


```

--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------

```yaml
version: "3.9"

services:
  master-mcp:
    build:
      context: .
      target: dev
    image: master-mcp-server:dev
    container_name: master-mcp-dev
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
      - MASTER_ENV=development
      - MASTER_HOSTING_PLATFORM=node
      - MASTER_HOSTING_PORT=3000
      # Uncomment and set for local secrets
      # - MASTER_OAUTH_CLIENT_SECRET=${MASTER_OAUTH_CLIENT_SECRET}
      # - TOKEN_ENC_KEY=${TOKEN_ENC_KEY}
    env_file:
      - .env
    volumes:
      - ./:/app
      - /app/node_modules
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/health"]
      interval: 10s
      timeout: 3s
      retries: 3
      start_period: 20s
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    deploy:
      resources:
        limits:
          cpus: "0.75"
          memory: 768M
        reservations:
          cpus: "0.25"
          memory: 256M


```

--------------------------------------------------------------------------------
/tests/_utils/mock-fetch.ts:
--------------------------------------------------------------------------------

```typescript
// Lightweight Node fetch mocking via Undici MockAgent (Node 18)
// Falls back to no-op if Undici not available.

type RemoveFn = () => void

export function withMockFetch(routes: Array<{ method: string; url: RegExp | string; reply: (body?: any) => any }>): RemoveFn {
  try {
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    const undici = require('undici')
    const agent = new undici.MockAgent()
    agent.disableNetConnect()
    const pool = agent.get('http://localhost')
    for (const r of routes) {
      const method = r.method.toUpperCase()
      const matcher = typeof r.url === 'string' ? new RegExp(r.url.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')) : r.url
      pool.intercept({ path: matcher, method }).reply(200, (_opts: any) => r.reply(_opts?.body))
    }
    undici.setGlobalDispatcher(agent)
    return () => undici.setGlobalDispatcher(new undici.Agent())
  } catch {
    // No undici; do nothing.
    return () => void 0
  }
}


```

--------------------------------------------------------------------------------
/tests/unit/config.environment-manager.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { EnvironmentManager } from '../../src/config/environment-manager.js'

test('EnvironmentManager parseCliArgs dotted keys', () => {
  const orig = process.argv
  process.argv = ['node', 'script', '--hosting.port=4001', '--logging.level=debug', '--config-path=./x.json']
  try {
    const parsed = EnvironmentManager.parseCliArgs()
    assert.equal((parsed as any).hosting.port, 4001)
    assert.equal((parsed as any).logging.level, 'debug')
    assert.equal((parsed as any).configPath, './x.json')
  } finally {
    process.argv = orig
  }
})

test('EnvironmentManager loadEnvOverrides maps vars', () => {
  process.env.MASTER_HOSTING_PORT = '1234'
  process.env.MASTER_OAUTH_SCOPES = 'a,b'
  const ov = EnvironmentManager.loadEnvOverrides()
  // @ts-ignore
  assert.equal(ov.hosting?.port, 1234)
  // @ts-ignore
  assert.deepEqual(ov.master_oauth?.scopes, ['a','b'])
})


```

--------------------------------------------------------------------------------
/tests/integration/modules.capability-aggregator.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { CapabilityAggregator } from '../../src/modules/capability-aggregator.js'
import { createMockServer } from '../utils/mock-http.js'

test('CapabilityAggregator discovers via /capabilities', async () => {
  const caps = {
    tools: [{ name: 't1' }],
    resources: [{ uri: 'r1' }],
  }
  const srv = await createMockServer([
    { method: 'GET', path: '/capabilities', handler: () => ({ body: caps }) },
  ])
  try {
    const servers = new Map<string, any>([[
      's1', { id: 's1', type: 'node', endpoint: srv.url, config: {} as any, status: 'running', lastHealthCheck: 0 }
    ]])
    const ag = new CapabilityAggregator()
    await ag.discoverCapabilities(servers as any)
    const tools = ag.getAllTools(servers as any)
    assert.equal(tools[0].name, 's1.t1')
    const map = ag.getMappingForTool('s1.t1')
    assert.equal(map?.originalName, 't1')
  } finally {
    await srv.close()
  }
})


```

--------------------------------------------------------------------------------
/docs/api/interfaces/RunningServer.md:
--------------------------------------------------------------------------------

```markdown
[**master-mcp-server**](../README.md)

***

# Interface: RunningServer

Defined in: [index.ts:7](https://github.com/solita-internal/master-mcp-server/blob/cd13e0009f7a1b7f244de882dc738bbf1f90f2c2/src/index.ts#L7)

## Properties

### container

> **container**: `DependencyContainer`

Defined in: [index.ts:10](https://github.com/solita-internal/master-mcp-server/blob/cd13e0009f7a1b7f244de882dc738bbf1f90f2c2/src/index.ts#L10)

***

### name

> **name**: `string`

Defined in: [index.ts:8](https://github.com/solita-internal/master-mcp-server/blob/cd13e0009f7a1b7f244de882dc738bbf1f90f2c2/src/index.ts#L8)

***

### stop()

> **stop**: () => `Promise`\<`void`\>

Defined in: [index.ts:11](https://github.com/solita-internal/master-mcp-server/blob/cd13e0009f7a1b7f244de882dc738bbf1f90f2c2/src/index.ts#L11)

#### Returns

`Promise`\<`void`\>

***

### version

> **version**: `string`

Defined in: [index.ts:9](https://github.com/solita-internal/master-mcp-server/blob/cd13e0009f7a1b7f244de882dc738bbf1f90f2c2/src/index.ts#L9)

```

--------------------------------------------------------------------------------
/tests/unit/utils.monitoring.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { MetricRegistry, HealthCheckRegistry, monitorEventLoopLag } from '../../src/utils/monitoring.js'

test('MetricRegistry counters/gauges/histograms', () => {
  const R = new MetricRegistry()
  R.counter('c').inc()
  R.gauge('g').set(5)
  R.histogram('h').observe(0.02)
  const snap = R.list()
  assert.equal(snap.counters.c, 1)
  assert.equal(snap.gauges.g, 5)
  assert.ok(Array.isArray(snap.histograms.h.counts))
})

test('HealthCheckRegistry aggregates ok/degraded', async () => {
  const H = new HealthCheckRegistry()
  H.register('ok', async () => ({ ok: true }))
  H.register('bad', async () => ({ ok: false, info: 'x' }))
  const res = await H.run()
  assert.equal(res.status, 'degraded')
})

test('monitorEventLoopLag provides callback and stopper', async () => {
  let called = 0
  const stop = monitorEventLoopLag(() => { called++ }, 5)
  await new Promise((r) => setTimeout(r, 20))
  stop()
  assert.ok(called >= 1)
})


```

--------------------------------------------------------------------------------
/tests/unit/stdio-capability-discovery.test.ts:
--------------------------------------------------------------------------------

```typescript
import { test } from 'node:test'
import assert from 'node:assert'
import { StdioCapabilityDiscovery } from '../src/modules/stdio-capability-discovery.js'

test('StdioCapabilityDiscovery should discover capabilities from a STDIO server', async () => {
  // This test would require a running STDIO server
  // For now, we'll just test that the class can be instantiated
  const discovery = new StdioCapabilityDiscovery()
  assert.ok(discovery)
})

test('StdioCapabilityDiscovery should have discoverCapabilities method', async () => {
  const discovery = new StdioCapabilityDiscovery()
  assert.strictEqual(typeof discovery.discoverCapabilities, 'function')
})

test('StdioCapabilityDiscovery should have callTool method', async () => {
  const discovery = new StdioCapabilityDiscovery()
  assert.strictEqual(typeof discovery.callTool, 'function')
})

test('StdioCapabilityDiscovery should have readResource method', async () => {
  const discovery = new StdioCapabilityDiscovery()
  assert.strictEqual(typeof discovery.readResource, 'function')
})
```

--------------------------------------------------------------------------------
/tests/unit/modules/stdio-manager.test.ts:
--------------------------------------------------------------------------------

```typescript
import { test } from 'node:test'
import assert from 'node:assert'
import { StdioManager } from '../../../src/modules/stdio-manager.js'
import path from 'node:path'

test('StdioManager should handle notifications', async () => {
  const manager = new StdioManager()
  const serverId = 'test-server'
  const serverPath = path.resolve(process.cwd(), 'tests/fixtures/stdio-server.js')

  let notificationReceived = null
  const notificationPromise = new Promise(resolve => {
    manager.onNotification(serverId, (message) => {
      notificationReceived = message
      resolve(message)
    })
  })

  await manager.startServer(serverId, serverPath)

  // Give the server a moment to start and send a notification
  await new Promise(resolve => setTimeout(resolve, 500))

  // The test server should send a notification on start
  // Let's wait for it
  await notificationPromise

  assert.deepStrictEqual(notificationReceived, { type: 'notification', message: 'server ready' })

  const server = manager['processes'].get(serverId)
  server?.kill()
})
```

--------------------------------------------------------------------------------
/tests/unit/modules.route-registry.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { RouteRegistry } from '../../src/routing/route-registry.js'
import { CircuitBreaker } from '../../src/routing/circuit-breaker.js'
import { LoadBalancer } from '../../src/routing/load-balancer.js'

test('RouteRegistry resolves and caches, bumps health', () => {
  const servers = new Map([
    ['s1', { id: 's1', type: 'node', endpoint: 'http://localhost:1234', config: {} as any, status: 'running', lastHealthCheck: Date.now(), instances: [
      { id: 'i1', url: 'http://localhost:1', healthScore: 50 },
      { id: 'i2', url: 'http://localhost:2', healthScore: 50 },
    ] }]
  ])
  const reg = new RouteRegistry(servers as any, new CircuitBreaker({ failureThreshold: 5, successThreshold: 1, recoveryTimeoutMs: 10 }), new LoadBalancer())
  const r1 = reg.resolve('s1')!
  assert.ok(r1.instance.id === 'i1' || r1.instance.id === 'i2')
  // mark success and failure adjust health without throwing
  reg.markSuccess('s1', r1.instance.id)
  reg.markFailure('s1', r1.instance.id)
})


```

--------------------------------------------------------------------------------
/tests/unit/auth.token-manager.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { TokenManager, InMemoryTokenStorage } from '../../src/auth/token-manager.js'

test('TokenManager stores, retrieves and cleans up', async () => {
  const storage = new InMemoryTokenStorage()
  const tm = new TokenManager({ storage, secret: 'k' })
  const key = 'user::server'
  await tm.storeToken(key, { access_token: 't', expires_at: Date.now() + 50, scope: [] })
  const tok = await tm.getToken(key)
  assert.equal(tok?.access_token, 't')
  await new Promise((r) => setTimeout(r, 60))
  await tm.cleanupExpiredTokens()
  const tok2 = await tm.getToken(key)
  assert.equal(tok2, null)
})

test('TokenManager works with custom KV-like storage', async () => {
  const { MemoryKVStorage } = await import('../utils/token-storages.js')
  const storage = new MemoryKVStorage()
  const tm = new TokenManager({ storage, secret: 'k' })
  await tm.storeToken('k1', { access_token: 'Z', expires_at: Date.now() + 1000, scope: [] })
  const tok = await tm.getToken('k1')
  assert.equal(tok?.access_token, 'Z')
})

```

--------------------------------------------------------------------------------
/docs/.vitepress/theme/components/CodeTabs.vue:
--------------------------------------------------------------------------------

```vue
<template>
  <div class="mcp-tabs" role="tablist" aria-label="Code Tabs">
    <div class="mcp-tabs__nav">
      <button
        v-for="opt in options"
        :key="opt.value"
        class="mcp-tabs__btn"
        role="tab"
        :aria-selected="active === opt.value"
        @click="active = opt.value"
      >
        {{ opt.label }}
      </button>
    </div>
    <div class="mcp-tabs__panel" role="tabpanel">
      <slot :name="active" />
    </div>
  </div>
  <div v-if="note" class="mcp-callout" style="margin-top:8px">{{ note }}</div>
  <div v-if="footnote" style="margin-top:6px;color:var(--vp-c-text-2);font-size:.9rem">{{ footnote }}</div>
</template>

<script setup lang="ts">
import { ref, watchEffect } from 'vue'

interface Option { label: string; value: string }
const props = defineProps<{
  options: Option[]
  modelValue?: string
  note?: string
  footnote?: string
}>()
const active = ref(props.modelValue || (props.options[0]?.value ?? ''))
watchEffect(() => {
  if (!props.options.find(o => o.value === active.value)) {
    active.value = props.options[0]?.value ?? ''
  }
})
</script>


```

--------------------------------------------------------------------------------
/tests/unit/utils.logger.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { Logger } from '../../src/utils/logger.js'

test('Logger emits human log line', () => {
  const lines: string[] = []
  const orig = console.log
  console.log = (s: any) => { lines.push(String(s)) }
  try {
    Logger.configure({ json: false, level: 'debug' })
    Logger.info('hello', { a: 1 })
    assert.ok(lines.length >= 1)
    assert.match(lines[0], /\[INFO\].*hello/)
  } finally {
    console.log = orig
    Logger.configure({ json: false, level: 'error' })
  }
})

test('Logger child with base fields', () => {
  const lines: string[] = []
  const orig = console.log
  console.log = (s: any) => { lines.push(String(s)) }
  try {
    Logger.configure({ json: true, level: 'debug', base: { svc: 'x' } })
    const L = Logger.with({ reqId: 'r1' })
    L.debug('dbg', { extra: 2 })
    assert.ok(lines.length)
    const parsed = JSON.parse(lines[0])
    assert.equal(parsed.svc, 'x')
    assert.equal(parsed.reqId, 'r1')
    assert.equal(parsed.msg, 'dbg')
  } finally {
    console.log = orig
  }
})


```

--------------------------------------------------------------------------------
/docs/getting-started/quick-start.md:
--------------------------------------------------------------------------------

```markdown
---
title: Quick Start
---

# Quick Start

Get from zero to a running Master MCP Server in under 10 minutes.

<CodeTabs
  :options="[
    { label: 'Node.js', value: 'node' },
    { label: 'Docker', value: 'docker' },
    { label: 'Cloudflare Workers', value: 'workers' }
  ]"
  note="Follow one tab end-to-end."
>
  <template #node>

```bash
npm install
cp .env.example .env
npm run build && npm run start
```

Minimal `config/master.yaml`:

```yaml
hosting:
  port: 3000
servers:
  - id: search
    type: local
    auth_strategy: master_oauth
    config:
      port: 4100
```

Verify:

```bash
curl -s http://localhost:3000/health
curl -s http://localhost:3000/mcp/tools/list | jq
```

  </template>
  <template #docker>

```bash
docker compose up --build
```

Production image:

```bash
docker run -p 3000:3000 \
  -e NODE_ENV=production \
  -e TOKEN_ENC_KEY=... \
  ghcr.io/OWNER/REPO:latest
```

  </template>
  <template #workers>

```bash
npm run build:worker
npx wrangler deploy deploy/cloudflare
```

  </template>
</CodeTabs>

## Generate a Config

<ConfigGenerator />

## Test Requests

<ApiPlayground />


```

--------------------------------------------------------------------------------
/src/types/mcp.ts:
--------------------------------------------------------------------------------

```typescript
// Minimal MCP-like types for Phase 1 compilation.
// Replace with @modelcontextprotocol/sdk imports in later phases.

export interface ToolDefinition {
  name: string
  description?: string
  inputSchema?: unknown
}

export interface ResourceDefinition {
  uri: string
  name?: string
  description?: string
  mimeType?: string
}

export interface PromptDefinition {
  name: string
  description?: string
  input?: unknown
}

export interface ListToolsRequest {
  type: 'list_tools'
}

export interface ListToolsResult {
  tools: ToolDefinition[]
}

export interface CallToolRequest {
  name: string
  arguments?: Record<string, unknown> | undefined
}

export interface CallToolResult {
  content: unknown
  isError?: boolean
}

export interface ListResourcesRequest {
  type: 'list_resources'
}

export interface ListResourcesResult {
  resources: ResourceDefinition[]
}

export interface ReadResourceRequest {
  uri: string
}

export interface ReadResourceResult {
  contents: string | Uint8Array
  mimeType?: string
}

export interface SubscribeRequest {
  target: string
}

export interface SubscribeResult {
  ok: boolean
}


```

--------------------------------------------------------------------------------
/tests/factories/configFactory.ts:
--------------------------------------------------------------------------------

```typescript
import type { MasterConfig, ServerConfig, AuthStrategy } from '../../src/types/config.js'

export function makeServerConfig(id: string, endpoint: string, authStrategy: AuthStrategy = 0 as any): ServerConfig {
  return {
    id,
    type: 'local',
    url: endpoint,
    auth_strategy: authStrategy || 'bypass_auth',
    config: { port: new URL(endpoint).port ? Number(new URL(endpoint).port) : undefined },
  }
}

export function makeMasterConfig(params: {
  servers: Array<{ id: string; endpoint: string }>
  hosting?: Partial<MasterConfig['hosting']>
  routing?: MasterConfig['routing']
  master_oauth?: Partial<MasterConfig['master_oauth']>
}): MasterConfig {
  const servers: ServerConfig[] = params.servers.map((s) => makeServerConfig(s.id, s.endpoint))
  return {
    master_oauth: {
      authorization_endpoint: 'http://localhost/authorize',
      token_endpoint: 'http://localhost/token',
      client_id: 'local',
      redirect_uri: 'http://localhost/oauth/callback',
      scopes: ['openid'],
      ...(params.master_oauth ?? {}),
    },
    servers,
    hosting: { platform: 'node', port: 0, ...(params.hosting ?? {}) },
    routing: params.routing,
  }
}


```

--------------------------------------------------------------------------------
/tests/unit/config.schema-validator.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { SchemaValidator } from '../../src/config/schema-validator.js'

test('SchemaValidator accepts minimal valid config', async () => {
  const schema = await SchemaValidator.loadSchema('config/schema.json')
  const cfg = {
    master_oauth: {
      authorization_endpoint: 'https://auth.local/authorize',
      token_endpoint: 'https://auth.local/token',
      client_id: 'x',
      redirect_uri: 'http://localhost/cb',
      scopes: ['openid'],
    },
    hosting: { platform: 'node' },
    servers: [],
  }
  assert.doesNotThrow(() => SchemaValidator.assertValid(cfg, schema!))
})

test('SchemaValidator rejects invalid platform', async () => {
  const schema = await SchemaValidator.loadSchema('config/schema.json')
  const cfg: any = {
    master_oauth: {
      authorization_endpoint: 'https://auth.local/authorize',
      token_endpoint: 'https://auth.local/token',
      client_id: 'x',
      redirect_uri: 'http://localhost/cb',
      scopes: ['openid'],
    },
    hosting: { platform: 'nope' },
    servers: [],
  }
  assert.throws(() => SchemaValidator.assertValid(cfg, schema!))
})


```

--------------------------------------------------------------------------------
/config/default.json:
--------------------------------------------------------------------------------

```json
{
  "master_oauth": {
    "authorization_endpoint": "https://example.com/oauth/authorize",
    "token_endpoint": "https://example.com/oauth/token",
    "client_id": "master-mcp",
    "client_secret": "env:MASTER_OAUTH_CLIENT_SECRET",
    "redirect_uri": "http://localhost:3000/callback",
    "scopes": ["openid", "profile"],
    "audience": "master-mcp"
  },
  "hosting": {
    "platform": "node",
    "port": 3000
  },
  "logging": {
    "level": "info"
  },
  "routing": {
    "loadBalancer": { "strategy": "round_robin" },
    "circuitBreaker": { "failureThreshold": 5, "successThreshold": 2, "recoveryTimeoutMs": 30000 },
    "retry": { "maxRetries": 2, "baseDelayMs": 250, "maxDelayMs": 4000, "backoffFactor": 2, "jitter": "full" }
  },
  "servers": [
    {
      "id": "test-server",
      "type": "local",
      "url": "http://localhost:3006",
      "auth_strategy": "bypass_auth",
      "config": {
        "environment": {},
        "args": []
      }
    },
    {
      "id": "stdio-server",
      "type": "local",
      "url": "file://./examples/stdio-mcp-server.cjs",
      "auth_strategy": "bypass_auth",
      "config": {
        "environment": {},
        "args": []
      }
    }
  ]
}


```

--------------------------------------------------------------------------------
/docs/deployment/docs-site.md:
--------------------------------------------------------------------------------

```markdown
---
title: Deploy the Docs Site
---

# Deploy the Docs Site

The documentation is built with VitePress and lives under `docs/`.

## Build Locally

```bash
npm run docs:build
```

The static site is emitted to `docs/.vitepress/dist`.

## Preview Locally

```bash
npm run docs:preview
```

## GitHub Pages

Setup workflow (example):

```yaml
name: Deploy Docs
on:
  push:
    branches: [ main ]
permissions:
  contents: read
  pages: write
  id-token: write
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - run: npm ci
      - run: npm run docs:build
      - uses: actions/upload-pages-artifact@v3
        with: { path: docs/.vitepress/dist }
  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment: { name: github-pages, url: ${{ steps.deployment.outputs.page_url }} }
    steps:
      - id: deployment
        uses: actions/deploy-pages@v4
```

## Cloudflare Pages

- Framework preset: None
- Build command: `npm run docs:build`
- Build output directory: `docs/.vitepress/dist`

## Netlify

- Build command: `npm run docs:build`
- Publish directory: `docs/.vitepress/dist`


```

--------------------------------------------------------------------------------
/docs/tutorials/load-balancing-and-resilience.md:
--------------------------------------------------------------------------------

```markdown
# Tutorial: Load Balancing & Resilience

Demonstrates multiple backends with load balancing, retries, and circuit breaker tuning.

## Configuration

`examples/multi-server/config.yaml` (provided):

```yaml
hosting:
  platform: node
  port: 3000

master_oauth:
  authorization_endpoint: https://example.com/oauth/authorize
  token_endpoint: https://example.com/oauth/token
  client_id: master-mcp
  redirect_uri: http://localhost:3000/oauth/callback
  scopes: [openid]

routing:
  loadBalancer:
    strategy: health
  circuitBreaker:
    failureThreshold: 3
    successThreshold: 2
    recoveryTimeoutMs: 10000
  retry:
    maxRetries: 3
    baseDelayMs: 200
    maxDelayMs: 3000
    backoffFactor: 2
    jitter: full
    retryOn:
      networkErrors: true
      httpStatuses: [408, 429]
      httpStatusClasses: [5]

servers:
  - id: compute
    type: local
    auth_strategy: bypass_auth
    config:
      port: 4101
  - id: compute
    type: local
    auth_strategy: bypass_auth
    config:
      port: 4102
```

Run master with:

```
MASTER_CONFIG_PATH=examples/multi-server/config.yaml npm run dev
```

The router will choose an instance per call, retry on transient errors, and open the circuit if failures breach the threshold.


```

--------------------------------------------------------------------------------
/docs/deployment/cicd.md:
--------------------------------------------------------------------------------

```markdown
# CI/CD Pipelines

Below are example steps you can adapt for your CI provider.

## Build & Publish Docker Image (GitHub Actions)

```yaml
name: build-and-push
on:
  push:
    branches: [ main ]

jobs:
  docker:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build
        run: |
          docker build -f deploy/docker/Dockerfile -t ghcr.io/${{ github.repository }}:latest .
      - name: Push
        run: docker push ghcr.io/${{ github.repository }}:latest
```

## Deploy to Cloudflare Workers (GitHub Actions)

```yaml
name: deploy-workers
on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          command: deploy --env production
```

## Deploy to Koyeb (CLI from CI)

Use Koyeb’s GitHub Action or the CLI with an API token to update the service image tag after push to GHCR.


```

--------------------------------------------------------------------------------
/src/runtime/worker.ts:
--------------------------------------------------------------------------------

```typescript
// Worker runtime with minimal surface to avoid Node-specific modules
import { ConfigLoader } from '../config/config-loader.js'
import { OAuthFlowController } from '../oauth/flow-controller.js'
import { collectSystemMetrics } from '../utils/monitoring.js'

export default {
  async fetch(_req: Request, env?: Record<string, unknown>): Promise<Response> {
    ;(globalThis as any).__WORKER_ENV = env || (globalThis as any).__WORKER_ENV || {}
    try {
      const url = new URL(_req.url)
      if (url.pathname === '/health') {
        return new Response(JSON.stringify({ ok: true }), { headers: { 'content-type': 'application/json' } })
      }
      if (url.pathname === '/metrics') {
        return new Response(
          JSON.stringify({ ok: true, system: collectSystemMetrics() }),
          { headers: { 'content-type': 'application/json' } }
        )
      }
      if (url.pathname.startsWith('/oauth')) {
        const cfg = await ConfigLoader.loadFromEnv()
        const ctrl = new OAuthFlowController({ getConfig: () => cfg })
        return await ctrl.handleRequest(_req)
      }
      return new Response(JSON.stringify({ ok: true }), {
        headers: { 'content-type': 'application/json' },
      })
    } finally {
      // keep server warm for now; no-op
    }
  },
}

```

--------------------------------------------------------------------------------
/docs/public/diagrams/architecture.svg:
--------------------------------------------------------------------------------

```
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 280">
  <defs>
    <style>
      .box{fill:#fff;stroke:#0ea5e9;stroke-width:2;rx:10;}
      .t{font:16px sans-serif;dominant-baseline:middle;text-anchor:middle;}
    </style>
    <marker id="arrow" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
      <path d="M0,0 L0,6 L6,3 z" fill="#0ea5e9" />
    </marker>
  </defs>
  <rect x="40" y="40" width="160" height="60" class="box"/>
  <text x="120" y="70" class="t">MCP Client(s)</text>

  <rect x="320" y="40" width="180" height="60" class="box"/>
  <text x="410" y="60" class="t">Master MCP Server</text>
  <text x="410" y="80" class="t">Auth • Routing • Config</text>

  <rect x="620" y="20" width="140" height="40" class="box"/>
  <text x="690" y="40" class="t">Server A</text>
  <rect x="620" y="80" width="140" height="40" class="box"/>
  <text x="690" y="100" class="t">Server B</text>
  <rect x="620" y="140" width="140" height="40" class="box"/>
  <text x="690" y="160" class="t">Server C</text>

  <path d="M200,70 L320,70" stroke="#0ea5e9" stroke-width="2" marker-end="url(#arrow)"/>
  <path d="M500,60 L620,40" stroke="#0ea5e9" stroke-width="2" marker-end="url(#arrow)"/>
  <path d="M500,70 L620,100" stroke="#0ea5e9" stroke-width="2" marker-end="url(#arrow)"/>
  <path d="M500,80 L620,160" stroke="#0ea5e9" stroke-width="2" marker-end="url(#arrow)"/>
</svg>


```

--------------------------------------------------------------------------------
/docs/configuration/environment-variables.md:
--------------------------------------------------------------------------------

```markdown
# Environment Variables

Environment variables can override configuration at load time. Key variables:

## Hosting

- `MASTER_HOSTING_PLATFORM` → `hosting.platform`
- `MASTER_HOSTING_PORT` → `hosting.port`
- `MASTER_BASE_URL` → `hosting.base_url`

## Logging

- `MASTER_LOG_LEVEL` → `logging.level`

## Master OAuth

- `MASTER_OAUTH_ISSUER` → `master_oauth.issuer`
- `MASTER_OAUTH_AUTHORIZATION_ENDPOINT` → `master_oauth.authorization_endpoint`
- `MASTER_OAUTH_TOKEN_ENDPOINT` → `master_oauth.token_endpoint`
- `MASTER_OAUTH_JWKS_URI` → `master_oauth.jwks_uri`
- `MASTER_OAUTH_CLIENT_ID` → `master_oauth.client_id`
- `MASTER_OAUTH_CLIENT_SECRET` → `master_oauth.client_secret` (stored as `env:MASTER_OAUTH_CLIENT_SECRET`)
- `MASTER_OAUTH_REDIRECT_URI` → `master_oauth.redirect_uri`
- `MASTER_OAUTH_SCOPES` → comma-separated list → `master_oauth.scopes[]`
- `MASTER_OAUTH_AUDIENCE` → `master_oauth.audience`

## Servers (bulk)

- `MASTER_SERVERS` → JSON array of servers
- `MASTER_SERVERS_YAML` → YAML array of servers

## Config discovery and env

- `MASTER_CONFIG_PATH` → explicit path to YAML/JSON config file
- `MASTER_ENV` / `NODE_ENV` → selects env-specific overrides and affects runtime behavior

## Secrets & Tokens

- `MASTER_CONFIG_KEY` (or `MASTER_SECRET_KEY`) → decrypts `enc:gcm:` config values
- `TOKEN_ENC_KEY` → encrypts stored delegated/proxy tokens (REQUIRED in production)

See `.env.example` for a template.


```

--------------------------------------------------------------------------------
/docs/guides/server-sharing.md:
--------------------------------------------------------------------------------

```markdown
---
title: Server Sharing
---

# Server Sharing

Expose multiple MCP backends through the master server and share a single, consistent endpoint with your team or applications.

## Add Backends

Backends are defined in your master config under `servers`.

```yaml
servers:
  - id: search
    type: local
    auth_strategy: master_oauth
    config: { port: 4100 }
  - id: github-tools
    type: local
    auth_strategy: delegate_oauth
    auth_config:
      provider: github
      authorization_endpoint: https://github.com/login/oauth/authorize
      token_endpoint: https://github.com/login/oauth/access_token
      client_id: ${GITHUB_CLIENT_ID}
      client_secret: env:GITHUB_CLIENT_SECRET
      scopes: [repo, read:user]
    config: { port: 4010 }
```

Name collisions are avoided by prefixing capabilities with the server id (e.g., `search.query`, `github-tools.repo.read`).

## Auth Strategies per Server

Choose one per server: `master_oauth`, `delegate_oauth`, `proxy_oauth`, `bypass_auth`.

<AuthFlowDemo />

## Share the Endpoint

- Local: `http://localhost:<port>`
- Docker: container port mapped to host
- Workers: public URL from your deployment

Distribute the base URL along with any client token requirements.

## Health Monitoring & Logs

- `GET /health` and `GET /metrics`
- Container logs (Docker/Koyeb) or platform logs (Workers)
- Use `performHealthChecks()` from code if embedding the master as a library


```

--------------------------------------------------------------------------------
/docs/tutorials/oauth-delegation-github.md:
--------------------------------------------------------------------------------

```markdown
# Tutorial: OAuth Delegation (GitHub)

Goal: Use delegated OAuth for a backend requiring GitHub OAuth.

## 1) Create a GitHub OAuth App

- Homepage URL: `http://localhost:3000`
- Authorization callback URL: `http://localhost:3000/oauth/callback`

Record `Client ID` and `Client Secret`.

## 2) Configuration

`examples/oauth-node/config.yaml` (provided):

```yaml
hosting:
  platform: node
  port: 3000

master_oauth:
  authorization_endpoint: https://example.com/oauth/authorize
  token_endpoint: https://example.com/oauth/token
  client_id: master-mcp
  redirect_uri: http://localhost:3000/oauth/callback
  scopes: [openid]

servers:
  - id: github-tools
    type: local
    auth_strategy: delegate_oauth
    auth_config:
      provider: github
      authorization_endpoint: https://github.com/login/oauth/authorize
      token_endpoint: https://github.com/login/oauth/access_token
      client_id: ${GITHUB_CLIENT_ID}
      client_secret: env:GITHUB_CLIENT_SECRET
      scopes: [repo, read:user]
    config:
      port: 4100
```

Set environment variable:

```
export GITHUB_CLIENT_SECRET=... # from GitHub app
```

Run with:

```
MASTER_CONFIG_PATH=examples/oauth-node/config.yaml npm run dev
```

## 3) Start the Flow

Navigate to:

```
http://localhost:3000/oauth/authorize?server_id=github-tools
```

Complete the GitHub consent, then you should see a success page. Calls to tools under `github-tools.*` will now include the delegated token.


```

--------------------------------------------------------------------------------
/tests/unit/utils.crypto.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { CryptoUtils } from '../../src/utils/crypto.js'

test('CryptoUtils encrypt/decrypt roundtrip', () => {
  const key = 'super-secret-key'
  const text = 'hello world ' + Date.now()
  const enc = CryptoUtils.encrypt(text, key)
  assert.ok(typeof enc === 'string' && enc.length > 16)
  const dec = CryptoUtils.decrypt(enc, key)
  assert.equal(dec, text)
})

test('CryptoUtils hash/verify', () => {
  const h = CryptoUtils.hash('abc')
  assert.ok(h.length === 64)
  assert.ok(CryptoUtils.verify('abc', h))
  assert.equal(CryptoUtils.verify('abcd', h), false)
})

test('CryptoUtils pbkdf2 and scrypt hashing', () => {
  const p = 'password'
  const pb = CryptoUtils.pbkdf2Hash(p, 10_000, 8)
  assert.ok(pb.startsWith('pbkdf2$sha256$'))
  assert.ok(CryptoUtils.pbkdf2Verify(p, pb))
  assert.equal(CryptoUtils.pbkdf2Verify('nope', pb), false)

  const sc = CryptoUtils.scryptHash(p, { N: 1024, r: 8, p: 1, saltLen: 8, keyLen: 16 })
  assert.ok(sc.startsWith('scrypt$'))
  assert.ok(CryptoUtils.scryptVerify(p, sc))
  assert.equal(CryptoUtils.scryptVerify('nope', sc), false)
})

test('CryptoUtils bcryptHash falls back but verifies', async () => {
  const p = 'topsecret'
  const h = await CryptoUtils.bcryptHash(p)
  assert.ok(typeof h === 'string')
  assert.ok(await CryptoUtils.bcryptVerify(p, h))
  assert.equal(await CryptoUtils.bcryptVerify('nope', h), false)
})


```

--------------------------------------------------------------------------------
/tests/security/security.oauth-and-input.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { CallbackHandler } from '../../src/oauth/callback-handler.js'
import { PKCEManager } from '../../src/oauth/pkce-manager.js'
import { StateManager } from '../../src/oauth/state-manager.js'
import { TokenManager, InMemoryTokenStorage } from '../../src/auth/token-manager.js'

test('CallbackHandler rejects missing/invalid state', async () => {
  const cb = new CallbackHandler({
    config: { master_oauth: { authorization_endpoint: 'http://a', token_endpoint: 'http://t', client_id: 'x', redirect_uri: 'http://l', scopes: ['openid'] }, hosting: { platform: 'node' }, servers: [] } as any,
    stateManager: new StateManager(),
    pkceManager: new PKCEManager(),
    baseUrl: 'http://localhost',
  })
  const res = await cb.handleCallback(new URLSearchParams({ state: 'nope', code: 'x' }), { provider: 'custom', authorization_endpoint: 'http://a', token_endpoint: 'http://t', client_id: 'x' })
  assert.ok(res.error)
})

test('TokenManager decryption failure is handled and entry removed', async () => {
  const storage = new InMemoryTokenStorage()
  const tm1 = new TokenManager({ storage, secret: 'a' })
  const tm2 = new TokenManager({ storage, secret: 'b' })
  const key = 'k'
  await tm1.storeToken(key, { access_token: 'X', expires_at: Date.now() + 1000, scope: [] })
  const before = await tm2.getToken(key)
  assert.equal(before, null) // decryption failed => deleted
})


```

--------------------------------------------------------------------------------
/docs/troubleshooting/index.md:
--------------------------------------------------------------------------------

```markdown
---
title: Common Issues
---

# Troubleshooting: Common Issues

- Invalid configuration: run `npm run docs:config` and compare with schema.
- OAuth callback fails: verify redirect URIs, state/PKCE, and client secrets.
- Workers runtime errors: avoid Node-only APIs; use Web Crypto and Fetch.
- Routing loop or failure: check circuit breaker status and retry limits.
- CORS/Networking: ensure your hosting platform permits required egress.

## FAQ

<details>
<summary>How do I connect a GUI client like Claude Desktop?</summary>

If your version supports remote/HTTP MCP servers, point it at your master base URL and include any required bearer token. Otherwise, run a light stdio→HTTP bridge that forwards MCP requests to the master’s `/mcp/*` endpoints.

</details>

<details>
<summary>Why do I get 401/403 responses?</summary>

The backend server may require a different token than your client token. Configure `delegate_oauth` or `proxy_oauth` on that backend, then complete the OAuth flow via `/oauth/authorize?server_id=<id>`.

</details>

<details>
<summary>Tools or resources are missing in the client.</summary>

Confirm each backend is healthy and exposes capabilities. Check `/capabilities` and `/mcp/tools/list`. Prefix names with the server id (e.g., `serverId.toolName`).

</details>

<details>
<summary>Requests time out under load.</summary>

Tune retries and circuit breaker thresholds in `routing`, and monitor p95/p99 latencies. See Advanced → Performance & Scalability.

</details>


```

--------------------------------------------------------------------------------
/tests/mocks/mcp/fake-backend.ts:
--------------------------------------------------------------------------------

```typescript
import type http from 'node:http'
import { createTestServer } from '../../_utils/test-server.js'

export interface FakeBackendOptions {
  id: string
  tools?: Array<{ name: string; description?: string }>
  resources?: Array<{ uri: string; description?: string; mimeType?: string }>
}

export async function startFakeMcpBackend(opts: FakeBackendOptions): Promise<{ url: string; stop: () => Promise<void> }> {
  const srv = await createTestServer()
  const tools = opts.tools ?? [{ name: 'echo', description: 'Echo input' }]
  const resources = opts.resources ?? []

  srv.register('GET', '/health', () => ({ body: { ok: true } }))
  srv.register('GET', '/capabilities', () => ({ body: { tools, resources } }))
  srv.register('POST', '/mcp/tools/list', () => ({ body: { tools } }))
  srv.register('POST', '/mcp/resources/list', () => ({ body: { resources } }))
  srv.register('POST', '/mcp/tools/call', (_req: http.IncomingMessage, raw) => {
    const body = safeParse(raw)
    if (body?.name === 'echo') return { body: { content: body?.arguments ?? {}, isError: false } }
    return { body: { content: { error: 'unknown tool' }, isError: true } }
  })
  srv.register('POST', '/mcp/resources/read', (_req, raw) => {
    const body = safeParse(raw)
    return { body: { contents: `content:${body?.uri ?? ''}`, mimeType: 'text/plain' } }
  })

  return { url: srv.url, stop: srv.close }
}

function safeParse(raw?: string): any {
  try { return raw ? JSON.parse(raw) : undefined } catch { return undefined }
}


```

--------------------------------------------------------------------------------
/docs/getting-started.md:
--------------------------------------------------------------------------------

```markdown
# Getting Started

This guide walks you through running Master MCP Server locally, configuring backends, and discovering capabilities.

## Prerequisites

- Node.js >= 18.17
- npm
- Network access to install dependencies and reach your OAuth providers/backends

## Install

```
npm ci
```

## Configure

1) Copy env template and edit as needed:

```
cp .env.example .env
```

2) Put your configuration in `config/` or pass a YAML/JSON path via `MASTER_CONFIG_PATH`. The built-in schema lives in `config/schema.json` and is also embedded as a fallback.

Example minimal YAML (single local server):

```yaml
hosting:
  platform: node
  port: 3000

master_oauth:
  authorization_endpoint: https://example.com/oauth/authorize
  token_endpoint: https://example.com/oauth/token
  client_id: master-mcp
  redirect_uri: http://localhost:3000/oauth/callback
  scopes: [openid]

servers:
  - id: tools
    type: local
    auth_strategy: bypass_auth
    config:
      port: 3333
```

## Run Dev Server

```
npm run dev
```

If your config is outside `config/`, set:

```
MASTER_CONFIG_PATH=examples/sample-configs/basic.yaml npm run dev
```

## Verify

- `GET http://localhost:3000/health` → `{ ok: true }`
- `POST http://localhost:3000/mcp/tools/list`
- `POST http://localhost:3000/mcp/resources/list`

When calling tools/resources on protected backends, include `Authorization: Bearer <token>`.

## Next Steps

- Read `docs/guides/authentication.md` for OAuth flows
- See `examples/*` to run end-to-end scenarios
- Deploy using `docs/deployment/*`


```

--------------------------------------------------------------------------------
/tests/unit/auth.multi-auth-manager.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { MultiAuthManager } from '../../src/auth/multi-auth-manager.js'
import { AuthStrategy } from '../../src/types/config.js'

const masterCfg = {
  authorization_endpoint: 'http://localhost/auth',
  token_endpoint: 'http://localhost/token',
  client_id: 'master',
  redirect_uri: 'http://localhost/cb',
  scopes: ['openid'],
}

test('MultiAuthManager pass-through and delegation', async (t) => {
  try {
    const mam = new MultiAuthManager(masterCfg as any)
    mam.registerServerAuth('srv1', AuthStrategy.MASTER_OAUTH)
    const h = await mam.prepareAuthForBackend('srv1', 'CLIENT')
    assert.equal(h.Authorization, 'Bearer CLIENT')

    mam.registerServerAuth('srv2', AuthStrategy.DELEGATE_OAUTH, {
      provider: 'custom', authorization_endpoint: 'http://p/auth', token_endpoint: 'http://p/token', client_id: 'c'
    })
    const d = await mam.prepareAuthForBackend('srv2', 'CLIENT') as any
    assert.equal(d.type, 'oauth_delegation')
  } catch (error) {
    console.error('Test failed:', error)
    throw error
  }
})

test('MultiAuthManager stores delegated server token', async (t) => {
  try {
    const mam = new MultiAuthManager(masterCfg as any)
    await mam.storeDelegatedToken('CLIENT', 'srv', { access_token: 'S', expires_at: Date.now() + 1000, scope: [] })
    const tok = await mam.getStoredServerToken('srv', 'CLIENT')
    assert.equal(tok, 'S')
  } catch (error) {
    console.error('Test failed:', error)
    throw error
  }
})


```

--------------------------------------------------------------------------------
/debug-stdio.js:
--------------------------------------------------------------------------------

```javascript
import { StdioManager } from './src/modules/stdio-manager.js'
import { Logger } from './src/utils/logger.js'

// Set logger to debug level
Logger.configure({ level: 'debug' })

async function testStdio() {
  const stdioManager = new StdioManager()
  const serverId = 'test-stdio-server'
  const filePath = './examples/stdio-mcp-server.cjs'
  
  try {
    console.log('Starting STDIO server...')
    const serverProcess = await stdioManager.startServer(serverId, filePath)
    console.log('STDIO server started successfully:', serverProcess)
    
    // Send a simple request to see if we can communicate
    console.log('Sending initialize request...')
    const initializeRequestId = Date.now()
    const initializeRequest = {
      jsonrpc: "2.0",
      id: initializeRequestId,
      method: "initialize",
      params: {
        protocolVersion: "2025-06-18",
        capabilities: {},
        clientInfo: { 
          name: "debug-script",
          version: "1.0.0"
        }
      }
    }
    
    await stdioManager.sendMessage(serverId, initializeRequest)
    console.log('Initialize request sent')
    
    // Wait for response
    console.log('Waiting for response...')
    const response = await stdioManager.waitForResponse(serverId, initializeRequestId, 5000) // 5 second timeout
    console.log('Received response:', response)
    
    // Stop the server
    console.log('Stopping server...')
    await serverProcess.stop()
    console.log('Server stopped')
  } catch (error) {
    console.error('Error in STDIO test:', error)
  }
}

testStdio()
```

--------------------------------------------------------------------------------
/debug-stdio.cjs:
--------------------------------------------------------------------------------

```
const { StdioManager } = require('./dist/node/modules/stdio-manager.js')
const { Logger } = require('./dist/node/utils/logger.js')

// Set logger to debug level
Logger.configure({ level: 'debug' })

async function testStdio() {
  const stdioManager = new StdioManager()
  const serverId = 'test-stdio-server'
  const filePath = './examples/stdio-mcp-server.cjs'
  
  try {
    console.log('Starting STDIO server...')
    const serverProcess = await stdioManager.startServer(serverId, filePath)
    console.log('STDIO server started successfully:', serverProcess)
    
    // Send a simple request to see if we can communicate
    console.log('Sending initialize request...')
    const initializeRequestId = Date.now()
    const initializeRequest = {
      jsonrpc: "2.0",
      id: initializeRequestId,
      method: "initialize",
      params: {
        protocolVersion: "2025-06-18",
        capabilities: {},
        clientInfo: { 
          name: "debug-script",
          version: "1.0.0"
        }
      }
    }
    
    await stdioManager.sendMessage(serverId, initializeRequest)
    console.log('Initialize request sent')
    
    // Wait for response
    console.log('Waiting for response...')
    const response = await stdioManager.waitForResponse(serverId, initializeRequestId, 5000) // 5 second timeout
    console.log('Received response:', response)
    
    // Stop the server
    console.log('Stopping server...')
    await serverProcess.stop()
    console.log('Server stopped')
  } catch (error) {
    console.error('Error in STDIO test:', error)
  }
}

testStdio()
```

--------------------------------------------------------------------------------
/tests/utils/fake-express.ts:
--------------------------------------------------------------------------------

```typescript
type Handler = (req: any, res: any) => void | Promise<void>

export class FakeExpressApp {
  routes: Record<string, { method: 'GET'|'POST'; handler: Handler }> = {}
  use(_arg: any): void { /* ignore middleware */ }
  get(path: string, handler: Handler): void { this.routes[`GET ${path}`] = { method: 'GET', handler } }
  post(path: string, handler: Handler): void { this.routes[`POST ${path}`] = { method: 'POST', handler } }
  async invoke(method: 'GET'|'POST', path: string, options?: { query?: Record<string,string>, headers?: Record<string,string>, body?: any }) {
    const key = `${method} ${path}`
    const route = this.routes[key]
    if (!route) throw new Error(`Route not found: ${key}`)
    const req = {
      method,
      query: options?.query ?? {},
      headers: options?.headers ?? {},
      body: options?.body ?? undefined,
      protocol: 'http',
      get: (h: string) => (options?.headers?.[h.toLowerCase()] ?? options?.headers?.[h] ?? undefined),
    }
    let statusCode = 200
    let sentHeaders: Record<string,string> = {}
    let payload: any
    const res = {
      set: (k: string, v: string) => { sentHeaders[k.toLowerCase()] = v },
      status: (c: number) => { statusCode = c; return res },
      send: (b: any) => { payload = b },
      json: (b: any) => { sentHeaders['content-type'] = 'application/json'; payload = JSON.stringify(b) },
      redirect: (loc: string) => { statusCode = 302; sentHeaders['location'] = loc; payload = '' },
    }
    await route.handler(req, res)
    return { status: statusCode, headers: sentHeaders, body: payload }
  }
}


```

--------------------------------------------------------------------------------
/docs/.vitepress/cache/deps/_metadata.json:
--------------------------------------------------------------------------------

```json
{
  "hash": "3c026b6f",
  "configHash": "1d5e3756",
  "lockfileHash": "b26962c5",
  "browserHash": "5431331e",
  "optimized": {
    "vue": {
      "src": "../../../../node_modules/vue/dist/vue.runtime.esm-bundler.js",
      "file": "vue.js",
      "fileHash": "7cfbfc66",
      "needsInterop": false
    },
    "vitepress > @vue/devtools-api": {
      "src": "../../../../node_modules/@vue/devtools-api/dist/index.js",
      "file": "vitepress___@vue_devtools-api.js",
      "fileHash": "89ef8781",
      "needsInterop": false
    },
    "vitepress > @vueuse/core": {
      "src": "../../../../node_modules/@vueuse/core/index.mjs",
      "file": "vitepress___@vueuse_core.js",
      "fileHash": "12a4fb0b",
      "needsInterop": false
    },
    "vitepress > @vueuse/integrations/useFocusTrap": {
      "src": "../../../../node_modules/@vueuse/integrations/useFocusTrap.mjs",
      "file": "vitepress___@vueuse_integrations_useFocusTrap.js",
      "fileHash": "b5a95a87",
      "needsInterop": false
    },
    "vitepress > mark.js/src/vanilla.js": {
      "src": "../../../../node_modules/mark.js/src/vanilla.js",
      "file": "vitepress___mark__js_src_vanilla__js.js",
      "fileHash": "38188df1",
      "needsInterop": false
    },
    "vitepress > minisearch": {
      "src": "../../../../node_modules/minisearch/dist/es/index.js",
      "file": "vitepress___minisearch.js",
      "fileHash": "996cffe0",
      "needsInterop": false
    }
  },
  "chunks": {
    "chunk-P2XGSYO7": {
      "file": "chunk-P2XGSYO7.js"
    },
    "chunk-HVR2FF6M": {
      "file": "chunk-HVR2FF6M.js"
    }
  }
}
```

--------------------------------------------------------------------------------
/tests/e2e/flow-controller.worker.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { OAuthFlowController } from '../../src/oauth/flow-controller.js'
import { createMockServer } from '../utils/mock-http.js'

test('OAuthFlowController Worker-style authorize and callback', async () => {
  const tokenSrv = await createMockServer([
    { method: 'POST', path: '/token', handler: () => ({ body: { access_token: 'AT', expires_in: 60, scope: 'openid' } }) },
  ])
  try {
    const cfg = {
      master_oauth: {
        authorization_endpoint: tokenSrv.url + '/authorize',
        token_endpoint: tokenSrv.url + '/token',
        client_id: 'cid',
        redirect_uri: 'http://localhost/oauth/callback',
        scopes: ['openid'],
      },
      hosting: { platform: 'cloudflare-workers', base_url: 'http://localhost' },
      servers: [],
    }
    const ctrl = new OAuthFlowController({ getConfig: () => cfg as any })
    const base = 'http://localhost'
    const authRes = await ctrl.handleRequest(new Request(base + '/oauth/authorize?provider=master', { method: 'GET' }))
    assert.equal(authRes.status, 200)
    const html = await authRes.text()
    const m = html.match(/url=([^"\s]+)/)
    assert.ok(m && m[1])
    const urlStr = m[1].replace(/&amp;/g, '&') // Decode HTML entities
    const state = new URL(urlStr).searchParams.get('state')!
    const cbRes = await ctrl.handleRequest(new Request(base + `/oauth/callback?state=${encodeURIComponent(state)}&code=good&provider=master`, { method: 'GET' }))
    assert.equal(cbRes.status, 200)
  } finally {
    await tokenSrv.close()
  }
})


```

--------------------------------------------------------------------------------
/tests/unit/oauth.pkce-state.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { PKCEManager } from '../../src/oauth/pkce-manager.js'
import { StateManager } from '../../src/oauth/state-manager.js'
import { FlowValidator } from '../../src/oauth/flow-validator.js'

test('PKCEManager generates and verifies', async () => {
  const pkce = new PKCEManager({ ttlMs: 1000 })
  const state = 'abc'
  const { challenge, method, verifier } = await pkce.generate(state)
  assert.ok(challenge.length > 16)
  assert.equal(method, 'S256')
  const v = pkce.getVerifier(state)
  assert.equal(v, verifier)
  // consumed; second time should be undefined
  assert.equal(pkce.getVerifier(state), undefined)
})

test('StateManager create/consume with TTL', async () => {
  const sm = new StateManager({ ttlMs: 10 })
  const s = sm.create({ provider: 'p', issuedAt: 0 } as any)
  const peek = sm.peek(s)
  assert.ok(peek && peek.provider === 'p')
  const used = sm.consume(s)
  assert.ok(used)
  assert.equal(sm.consume(s), null)
})

test('FlowValidator validateReturnTo prevents open redirects', () => {
  const fv = new FlowValidator(() => ({
    master_oauth: {
      authorization_endpoint: 'https://a', token_endpoint: 'https://t', client_id: 'x', redirect_uri: 'http://l', scopes: ['openid']
    }, hosting: { platform: 'node' }, servers: []
  } as any))
  assert.equal(fv.validateReturnTo('http://evil.com', 'http://localhost:3000'), undefined)
  assert.equal(fv.validateReturnTo('http://localhost:3000/path', 'http://localhost:3000'), '/path')
  assert.equal(fv.validateReturnTo('/ok', 'http://x'), '/ok')
})


```

--------------------------------------------------------------------------------
/docs/guides/configuration-management.md:
--------------------------------------------------------------------------------

```markdown
# Configuration Management

Master MCP Server supports JSON or YAML configuration files, environment variable overrides, CLI overrides, schema validation, and secret resolution.

## Files

- Default paths: `config/default.json`, `config/<env>.json`
- Explicit path: set `MASTER_CONFIG_PATH=/path/to/config.yaml`
- Schema: `config/schema.json` (also embedded in code as a fallback)

## Environment Overrides

Environment variables map to config fields. Key ones:

- `MASTER_HOSTING_PLATFORM`, `MASTER_HOSTING_PORT`, `MASTER_BASE_URL`
- `MASTER_LOG_LEVEL`
- `MASTER_OAUTH_*` (ISSUER, AUTHORIZATION_ENDPOINT, TOKEN_ENDPOINT, CLIENT_ID, CLIENT_SECRET, REDIRECT_URI, SCOPES, AUDIENCE)
- `MASTER_SERVERS` (JSON) or `MASTER_SERVERS_YAML` (YAML)

See `docs/configuration/environment-variables.md` and `.env.example`.

## CLI Overrides

You can override nested fields with dotted keys:

```
node dist/node/index.js --hosting.port=4000 --routing.retry.maxRetries=3
```

## Secrets

- `env:VARNAME` → replaced by `process.env.VARNAME` at load time
- `enc:gcm:<base64>` → decrypted using `MASTER_CONFIG_KEY` (or `MASTER_SECRET_KEY`)

Use `SecretManager` to encrypt/decrypt/rotate secrets safely.

## Hot Reload (Node)

When `ConfigManager` is created with `{ watch: true }`, changes to `config/default.json`, `config/<env>.json`, or an explicit path will be validated and emitted. Some changes (e.g., hosting.port) still require a restart.

## Validation

Configs are validated using a lightweight schema validator (`SchemaValidator`) with support for types, enums, required fields, arrays, and formats (`url`, `integer`). On failure, the error lists the exact path and reason.


```

--------------------------------------------------------------------------------
/src/utils/cache.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Simple in-memory TTL cache with optional memoization helpers.
 */

export interface CacheEntry<V> {
  value: V
  expiresAt: number
}

export class TTLCache<K, V> {
  private store = new Map<K, CacheEntry<V>>()
  constructor(private defaultTtlMs = 60_000) {}

  set(key: K, value: V, ttlMs?: number): void {
    const ttl = ttlMs ?? this.defaultTtlMs
    const expiresAt = Date.now() + ttl
    this.store.set(key, { value, expiresAt })
  }

  get(key: K): V | undefined {
    const hit = this.store.get(key)
    if (!hit) return undefined
    if (hit.expiresAt < Date.now()) {
      this.store.delete(key)
      return undefined
    }
    return hit.value
  }

  has(key: K): boolean {
    return this.get(key) !== undefined
  }

  delete(key: K): void {
    this.store.delete(key)
  }

  clear(): void {
    this.store.clear()
  }

  size(): number {
    return this.store.size
  }

  sweep(): void {
    const now = Date.now()
    for (const [k, v] of this.store.entries()) {
      if (v.expiresAt < now) this.store.delete(k)
    }
  }

  async getOrSet(key: K, loader: () => Promise<V>, ttlMs?: number): Promise<V> {
    const existing = this.get(key)
    if (existing !== undefined) return existing
    const v = await loader()
    this.set(key, v, ttlMs)
    return v
  }
}

export function memoizeAsync<A extends unknown[], R>(fn: (...args: A) => Promise<R>, ttlMs = 60_000): (...args: A) => Promise<R> {
  const cache = new TTLCache<string, R>(ttlMs)
  return async (...args: A) => {
    const key = JSON.stringify(args)
    const hit = cache.get(key)
    if (hit !== undefined) return hit
    const res = await fn(...args)
    cache.set(key, res, ttlMs)
    return res
  }
}


```

--------------------------------------------------------------------------------
/docs/.vitepress/theme/style.css:
--------------------------------------------------------------------------------

```css
:root {
  --mcp-accent: #0ea5e9;
  --mcp-accent-600: #0284c7;
  --mcp-bg-soft: color-mix(in oklab, var(--vp-c-bg) 90%, var(--mcp-accent) 10%);
}

.mcp-kicker {
  font-size: .9rem;
  color: var(--vp-c-text-2);
  text-transform: uppercase;
  letter-spacing: .08em;
}

/* Tabs */
.mcp-tabs {
  border: 1px solid var(--vp-c-divider);
  border-radius: 10px;
  overflow: hidden;
  background: var(--vp-c-bg-soft);
}
.mcp-tabs__nav {
  display: flex;
  gap: 6px;
  padding: 8px;
  background: var(--vp-c-bg);
  border-bottom: 1px solid var(--vp-c-divider);
}
.mcp-tabs__btn {
  appearance: none;
  border: 1px solid var(--vp-c-divider);
  padding: 6px 12px;
  border-radius: 8px;
  background: var(--vp-c-bg-soft);
  color: var(--vp-c-text-1);
  cursor: pointer;
  font-weight: 500;
}
.mcp-tabs__btn[aria-selected="true"] {
  background: var(--mcp-accent);
  border-color: var(--mcp-accent);
  color: white;
}
.mcp-tabs__panel {
  padding: 12px 14px;
}

/* Utility blocks */
.mcp-callout {
  border-left: 3px solid var(--mcp-accent);
  padding: 10px 14px;
  margin: 10px 0;
  background: var(--vp-c-bg-soft);
}

.mcp-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 16px;
}
.mcp-col-6 { grid-column: span 6; }
.mcp-col-12 { grid-column: span 12; }
@media (max-width: 960px) {
  .mcp-col-6 { grid-column: span 12; }
}

.mcp-diagram {
  width: 100%;
  border: 1px dashed var(--vp-c-divider);
  border-radius: 10px;
  padding: 12px;
}

.mcp-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--mcp-accent);
  color: white;
  padding: 8px 12px;
  border-radius: 8px;
  text-decoration: none;
}
.mcp-cta:hover { background: var(--mcp-accent-600); }


```

--------------------------------------------------------------------------------
/tests/unit/routing.core.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { CircuitBreaker, CircuitOpenError } from '../../src/routing/circuit-breaker.js'
import { RetryHandler } from '../../src/routing/retry-handler.js'
import { LoadBalancer } from '../../src/routing/load-balancer.js'

test('CircuitBreaker opens and recovers', async () => {
  const cb = new CircuitBreaker({ failureThreshold: 2, successThreshold: 1, recoveryTimeoutMs: 10 })
  const key = 'svc::inst'
  await assert.rejects(cb.execute(key, async () => { throw new Error('fail') }))
  await assert.rejects(cb.execute(key, async () => { throw new Error('fail') }))
  // Now circuit open
  await assert.rejects(cb.execute(key, async () => 'ok'), (e: any) => e instanceof CircuitOpenError)
  // Wait for half-open
  await new Promise((r) => setTimeout(r, 12))
  const res = await cb.execute(key, async () => 'ok')
  assert.equal(res, 'ok')
})

test('RetryHandler retries on 5xx and succeeds', async () => {
  const rh = new RetryHandler({ maxRetries: 2, baseDelayMs: 1, maxDelayMs: 2, jitter: 'none' })
  let n = 0
  const res = await rh.execute(async () => {
    n++
    if (n < 3) { const err: any = new Error('HTTP 500'); err.status = 500; throw err }
    return 'ok'
  })
  assert.equal(res, 'ok')
  assert.equal(n, 3)
})

test('LoadBalancer round-robin selection', () => {
  const lb = new LoadBalancer({ strategy: 'round_robin' })
  const pool = [ { id: 'a' }, { id: 'b' }, { id: 'c' } ] as any
  const chosen = [
    lb.select('svc', pool)!.id,
    lb.select('svc', pool)!.id,
    lb.select('svc', pool)!.id,
    lb.select('svc', pool)!.id,
  ]
  assert.deepEqual(chosen, ['a','b','c','a'])
})


```

--------------------------------------------------------------------------------
/src/utils/time.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Date/time utilities, duration parsing and timezone helpers.
 */

export function now(): number {
  if (typeof performance !== 'undefined' && typeof performance.now === 'function') return performance.now()
  return Date.now()
}

export function sleep(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms))
}

/** Parses durations like "500ms", "2s", "5m", "1h", "1d". */
export function parseDuration(input: string): number {
  const m = String(input).trim().match(/^(\d+(?:\.\d+)?)(ms|s|m|h|d)$/i)
  if (!m) throw new Error('Invalid duration')
  const n = parseFloat(m[1])
  const u = m[2].toLowerCase()
  switch (u) {
    case 'ms':
      return n
    case 's':
      return n * 1000
    case 'm':
      return n * 60_000
    case 'h':
      return n * 3_600_000
    case 'd':
      return n * 86_400_000
    default:
      throw new Error('Invalid duration unit')
  }
}

export function formatDuration(ms: number): string {
  if (ms < 1000) return `${ms}ms`
  if (ms < 60_000) return `${(ms / 1000).toFixed(ms % 1000 === 0 ? 0 : 2)}s`
  if (ms < 3_600_000) return `${(ms / 60_000).toFixed(ms % 60_000 === 0 ? 0 : 2)}m`
  if (ms < 86_400_000) return `${(ms / 3_600_000).toFixed(ms % 3_600_000 === 0 ? 0 : 2)}h`
  return `${(ms / 86_400_000).toFixed(ms % 86_400_000 === 0 ? 0 : 2)}d`
}

export function toUTC(date: Date): string {
  return date.toISOString()
}

export function fromUnix(seconds: number): Date {
  return new Date(seconds * 1000)
}

export function formatInTimeZone(date: Date, timeZone: string, opts?: Intl.DateTimeFormatOptions): string {
  const formatter = new Intl.DateTimeFormat('en-US', { timeZone, ...opts })
  return formatter.format(date)
}


```

--------------------------------------------------------------------------------
/tests/perf/perf.auth-and-routing.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import { performance } from 'node:perf_hooks'
import { MultiAuthManager } from '../../src/auth/multi-auth-manager.js'
import { AuthStrategy } from '../../src/types/config.js'
import { createMockServer } from '../utils/mock-http.js'
import { RequestRouter } from '../../src/modules/request-router.js'
import { CapabilityAggregator } from '../../src/modules/capability-aggregator.js'

test('Perf: validateClientToken and routeCallTool throughput (smoke)', async (t) => {
  const mam = new MultiAuthManager({ authorization_endpoint: 'http://a', token_endpoint: 'http://t', client_id: 'x', redirect_uri: 'http://l', scopes: ['openid'] } as any)
  mam.registerServerAuth('s', AuthStrategy.BYPASS_AUTH)
  const N = 1000
  const t0 = performance.now()
  for (let i = 0; i < N; i++) await mam.validateClientToken('opaque-token')
  const dt = performance.now() - t0
  t.diagnostic(`validateClientToken x${N}: ${Math.round(dt)}ms (${Math.round((N/dt)*1000)} ops/sec)`) // eslint-disable-line

  const upstream = await createMockServer([
    { method: 'POST', path: '/mcp/tools/call', handler: () => ({ body: { content: { ok: true } } }) },
  ])
  const servers = new Map<string, any>([[ 's', { id: 's', type: 'node', endpoint: upstream.url, config: {} as any, status: 'running', lastHealthCheck: 0 } ]])
  const rr = new RequestRouter(servers as any, new CapabilityAggregator())
  const M = 200
  const t1 = performance.now()
  for (let i = 0; i < M; i++) await rr.routeCallTool({ name: 's.ping' })
  const dt2 = performance.now() - t1
  t.diagnostic(`routeCallTool x${M}: ${Math.round(dt2)}ms (${Math.round((M/dt2)*1000)} rps)`) // eslint-disable-line
  await upstream.close()
})


```

--------------------------------------------------------------------------------
/docs/public/logo.svg:
--------------------------------------------------------------------------------

```
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   viewBox="0 0 120 120"
   version="1.1"
   id="svg4"
   sodipodi:docname="logo.svg"
   inkscape:export-filename="logo.png"
   inkscape:export-xdpi="96"
   inkscape:export-ydpi="96"
   inkscape:version="1.4 (e7c3feb1, 2024-10-09)"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
   id="namedview4"
   pagecolor="#ffffff"
   bordercolor="#000000"
   borderopacity="0.25"
   inkscape:showpageshadow="2"
   inkscape:pageopacity="0.0"
   inkscape:pagecheckerboard="0"
   inkscape:deskcolor="#d1d1d1"
   inkscape:zoom="2.9371694"
   inkscape:cx="38.131951"
   inkscape:cy="32.68453"
   inkscape:window-width="1512"
   inkscape:window-height="945"
   inkscape:window-x="0"
   inkscape:window-y="37"
   inkscape:window-maximized="0"
   inkscape:current-layer="svg4" />
<defs
   id="defs2">
  <linearGradient
     id="g"
     x1="0"
     y1="0"
     x2="1"
     y2="1">
    <stop
       offset="0%"
       stop-color="#7C3AED"
       id="stop1" />
    <stop
       offset="100%"
       stop-color="#06B6D4"
       id="stop2" />
  </linearGradient>
</defs>
<circle
   cx="60"
   cy="60"
   r="56"
   fill="url(#g)"
   id="circle2" />
<g
   fill="#fff"
   id="g4">
  <circle
     cx="60"
     cy="60"
     r="10"
     id="circle3" />
  <path
     d="M60 20 a40 40 0 0 1 0 80"
     fill="none"
     stroke="#fff"
     stroke-width="6"
     id="path3" />
  <path
     d="M20 60 a40 40 0 0 1 80 0"
     fill="none"
     stroke="#fff"
     stroke-width="6"
     id="path4" />
</g>

  Sorry, your browser does not support inline SVG.
</svg>

```

--------------------------------------------------------------------------------
/docs/configuration/examples.md:
--------------------------------------------------------------------------------

```markdown
---
title: Configuration Examples
---

# Configuration Examples

Real-world scenarios to use as starting points.

## Minimal Local Aggregation

```yaml
hosting:
  port: 3000
servers:
  - id: search
    type: local
    auth_strategy: master_oauth
    config: { port: 4100 }
```

## Mixed Auth Strategies (GitHub Delegation)

```yaml
hosting:
  port: 3000
  base_url: https://your.domain
servers:
  - id: search
    type: local
    auth_strategy: master_oauth
    config: { port: 4100 }
  - id: github-tools
    type: local
    auth_strategy: delegate_oauth
    auth_config:
      provider: github
      authorization_endpoint: https://github.com/login/oauth/authorize
      token_endpoint: https://github.com/login/oauth/access_token
      client_id: ${GITHUB_CLIENT_ID}
      client_secret: env:GITHUB_CLIENT_SECRET
      scopes: [repo, read:user]
    config: { port: 4010 }
routing:
  retry:
    maxRetries: 2
    baseDelayMs: 200
  circuitBreaker:
    failureThreshold: 5
    successThreshold: 2
    recoveryTimeoutMs: 10000
```

## Dockerized Production

```yaml
hosting:
  port: 3000
servers:
  - id: search
    type: local
    auth_strategy: bypass_auth
    config: { url: http://search:4100 }
```

Run with env:

```bash
TOKEN_ENC_KEY=... MASTER_BASE_URL=https://master.example.com docker compose up -d
```

## Multi-tenant (Advanced)

In multi-tenant deployments, use separate configs per tenant and map them under different base URLs or headers. Keep secrets isolated and rotate regularly.

```yaml
# tenant-a.yaml
hosting: { port: 3001 }
servers: [ { id: search, type: local, auth_strategy: master_oauth, config: { port: 4110 } } ]

# tenant-b.yaml
hosting: { port: 3002 }
servers: [ { id: search, type: local, auth_strategy: master_oauth, config: { port: 4120 } } ]
```


```

--------------------------------------------------------------------------------
/tests/servers/test-auth-simple.js:
--------------------------------------------------------------------------------

```javascript
import { MultiAuthManager } from '../../src/auth/multi-auth-manager.js'
import { AuthStrategy } from '../../src/types/config.js'
import '../setup/test-setup.js'

const masterCfg = {
  authorization_endpoint: 'http://localhost/auth',
  token_endpoint: 'http://localhost/token',
  client_id: 'master',
  redirect_uri: 'http://localhost/cb',
  scopes: ['openid'],
}

async function testAuth() {
  console.log('Testing MultiAuthManager...')
  
  try {
    const mam = new MultiAuthManager(masterCfg)
    mam.registerServerAuth('srv1', AuthStrategy.MASTER_OAUTH)
    const h = await mam.prepareAuthForBackend('srv1', 'CLIENT')
    
    if (h.Authorization === 'Bearer CLIENT') {
      console.log('✅ Test 1 passed: Master OAuth pass-through')
    } else {
      console.log('❌ Test 1 failed:', h)
    }

    // Test delegation
    mam.registerServerAuth('srv2', AuthStrategy.DELEGATE_OAUTH, {
      provider: 'custom', 
      authorization_endpoint: 'http://p/auth', 
      token_endpoint: 'http://p/token', 
      client_id: 'c'
    })
    const d = await mam.prepareAuthForBackend('srv2', 'CLIENT')
    
    if (d.type === 'oauth_delegation') {
      console.log('✅ Test 2 passed: OAuth delegation')
    } else {
      console.log('❌ Test 2 failed:', d)
    }

    // Test storage
    await mam.storeDelegatedToken('CLIENT', 'srv', { access_token: 'S', expires_at: Date.now() + 1000, scope: [] })
    const tok = await mam.getStoredServerToken('srv', 'CLIENT')
    
    if (tok === 'S') {
      console.log('✅ Test 3 passed: Token storage')
    } else {
      console.log('❌ Test 3 failed:', tok)
    }
    
    console.log('All tests completed successfully!')
    
  } catch (error) {
    console.error('Test failed:', error)
    console.error('Stack:', error.stack)
  }
}

testAuth()
```

--------------------------------------------------------------------------------
/tests/e2e/flow-controller.express.test.ts:
--------------------------------------------------------------------------------

```typescript
import '../setup/test-setup.js'
import test from 'node:test'
import assert from 'node:assert/strict'
import { OAuthFlowController } from '../../src/oauth/flow-controller.js'
import { FakeExpressApp } from '../utils/fake-express.js'
import { createMockServer } from '../utils/mock-http.js'

test('OAuthFlowController Express flow: authorize -> token -> callback', async () => {
  const tokenSrv = await createMockServer([
    { method: 'POST', path: '/token', handler: (_req, _body) => ({ body: { access_token: 'AT', expires_in: 60, scope: 'openid' } }) },
  ])
  try {
    const cfg = {
      master_oauth: {
        authorization_endpoint: tokenSrv.url + '/authorize',
        token_endpoint: tokenSrv.url + '/token',
        client_id: 'cid',
        redirect_uri: 'http://localhost/oauth/callback',
        scopes: ['openid'],
      },
      hosting: { platform: 'node', base_url: 'http://localhost' },
      servers: [],
    }
    const ctrl = new OAuthFlowController({ getConfig: () => cfg as any })
    const app = new FakeExpressApp()
    ctrl.registerExpress(app as any)

    const auth = await app.invoke('GET', '/oauth/authorize', { query: { provider: 'master' } })
    assert.equal(auth.status, 200)
    assert.match(String(auth.body), /Redirecting/)
    const m = String(auth.body).match(/url=([^"\s]+)/)
    assert.ok(m && m[1])
    const urlStr = m[1].replace(/&amp;/g, '&') // Decode HTML entities
    const url = new URL(urlStr)
    const state = url.searchParams.get('state')!
    assert.ok(state)

    const cb = await app.invoke('GET', '/oauth/callback', { query: { state, code: 'good', provider: 'master' } })
    assert.equal(cb.status, 200)
    assert.match(String(cb.body), /Authorization complete|You may close this window/)
  } finally {
    await tokenSrv.close()
  }
})


```

--------------------------------------------------------------------------------
/deploy/docker/Dockerfile:
--------------------------------------------------------------------------------

```dockerfile
# syntax=docker/dockerfile:1.7

ARG NODE_VERSION=20
FROM node:${NODE_VERSION}-slim AS base
ENV PNPM_HOME=/usr/local/share/pnpm \
    NODE_ENV=production \
    APP_HOME=/app
WORKDIR ${APP_HOME}

# ---------- Builder ----------
FROM base AS builder
ENV NODE_ENV=development
SHELL ["/bin/sh", "-lc"]
RUN --mount=type=cache,target=/var/cache/apt \
    --mount=type=cache,target=/var/lib/apt/lists \
    apt-get update && apt-get install -y --no-install-recommends git ca-certificates && rm -rf /var/lib/apt/lists/*
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm npm ci
COPY tsconfig*.json ./
COPY src ./src
COPY config ./config
COPY static ./static
RUN npm run build:node

# ---------- Runtime ----------
FROM base AS runtime
SHELL ["/bin/sh", "-lc"]
# Create non-root user
RUN useradd -r -u 10001 -g root nodejs && mkdir -p /app && chown -R nodejs:root /app

# Only production deps
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm npm ci --omit=dev --ignore-scripts && npm cache clean --force

# Copy build artifacts and minimal runtime assets
COPY --from=builder /app/dist/node ./dist/node
COPY --from=builder /app/config ./config
COPY --from=builder /app/static ./static
COPY deploy/docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENV NODE_ENV=production \
    LOG_FORMAT=json \
    PORT=3000 \
    MASTER_HOSTING_PLATFORM=node

EXPOSE 3000
USER nodejs
ENTRYPOINT ["/entrypoint.sh"]
CMD ["node", "dist/node/index.js"]

# Healthcheck without adding curl/wget: use Node's http module
HEALTHCHECK --interval=10s --timeout=3s --start-period=10s --retries=3 \
  CMD node -e "const http=require('http');const p=process.env.PORT||3000;http.get({host:'127.0.0.1',port:p,path:'/health'},r=>{process.exit(r.statusCode===200?0:1)}).on('error',()=>process.exit(1))"


```

--------------------------------------------------------------------------------
/src/utils/dev.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Development and debugging helpers.
 */

export function isDev(): boolean {
  const env = (globalThis as any)?.process?.env
  return env?.NODE_ENV !== 'production'
}

export function debugLog(...args: unknown[]): void {
  if (!isDev()) return
  // eslint-disable-next-line no-console
  console.debug('[DEV]', ...args)
}

export function invariant(condition: unknown, message = 'Invariant failed'): asserts condition {
  if (!condition) throw new Error(message)
}

export function assertNever(x: never, message = 'Unexpected object'): never {
  throw new Error(`${message}: ${String(x)}`)
}

export function pretty(value: unknown): string {
  try {
    const util = (globalThis as any).require ? (globalThis as any).require('node:util') : undefined
    if (util?.inspect) return util.inspect(value, { depth: 4, colors: true })
  } catch {
    // ignore
  }
  try {
    return JSON.stringify(value, null, 2)
  } catch {
    return String(value)
  }
}

export function deprecate(fn: (...args: any[]) => any, message: string): (...args: any[]) => any {
  let warned = false
  return (...args: any[]) => {
    if (!warned) {
      warned = true
      // eslint-disable-next-line no-console
      console.warn(`[DEPRECATED] ${message}`)
    }
    return fn(...args)
  }
}

export function withTiming<T>(name: string, fn: () => T): { result: T; durationMs: number; name: string } {
  const start = typeof performance !== 'undefined' ? performance.now() : Date.now()
  const result = fn()
  const durationMs = (typeof performance !== 'undefined' ? performance.now() : Date.now()) - start
  return { result, durationMs, name }
}

export function sleep(ms: number): Promise<void> {
  return new Promise((res) => setTimeout(res, ms))
}

export function mockRandom(fn: () => number): () => void {
  const original = Math.random
  ;(Math as any).random = fn
  return () => {
    ;(Math as any).random = original
  }
}

```

--------------------------------------------------------------------------------
/tests/servers/test-master-mcp.js:
--------------------------------------------------------------------------------

```javascript
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'

async function runTest() {
  try {
    console.log('Testing Master MCP Server...')
    
    // Create a streamable HTTP transport to connect to our MCP server
    const transport = new StreamableHTTPClientTransport(new URL('http://localhost:3005/mcp'))
    
    // Create the MCP client
    const client = new Client({
      name: 'master-mcp-test-client',
      version: '1.0.0'
    })
    
    // Initialize the client
    await client.connect(transport)
    console.log('✅ Server initialized')
    console.log('Server info:', client.getServerVersion())
    console.log('Protocol version:', client.getServerCapabilities())
    
    // List tools
    console.log('\n--- Testing tools/list ---')
    const toolsResult = await client.listTools({})
    console.log('✅ tools/list successful')
    console.log('Number of tools:', toolsResult.tools.length)
    console.log('Tools:', toolsResult.tools.map(t => t.name))
    
    // List resources
    console.log('\n--- Testing resources/list ---')
    const resourcesResult = await client.listResources({})
    console.log('✅ resources/list successful')
    console.log('Number of resources:', resourcesResult.resources.length)
    console.log('Resources:', resourcesResult.resources.map(r => r.uri))
    
    // Test ping
    console.log('\n--- Testing ping ---')
    const pingResult = await client.ping()
    console.log('✅ ping successful')
    console.log('Ping result:', pingResult)
    
    // Close the connection
    await client.close()
    console.log('\n✅ Disconnected from MCP server')
    console.log('\n🎉 All tests completed successfully!')
    
  } catch (error) {
    console.error('❌ Test failed:', error)
    console.error('Error stack:', error.stack)
  }
}

// Run the test
runTest()
```

--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------

```dockerfile
# syntax=docker/dockerfile:1.7

# Multi-stage build for production and dev with multi-arch support.
# Targets:
# - base: common base image
# - deps: install all dependencies (including dev)
# - build: compile TypeScript to dist
# - prod-deps: install only production deps
# - runner: minimal runtime image
# - dev: development image with hot-reload support

ARG NODE_VERSION=20.14.0
ARG ALPINE_VERSION=3.19

FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION} AS base
ENV NODE_ENV=production \
    APP_HOME=/app \
    PNPM_HOME=/pnpm
WORKDIR ${APP_HOME}
RUN addgroup -g 1001 -S nodejs && adduser -S node -u 1001 -G nodejs

FROM base AS deps
ENV NODE_ENV=development
COPY package*.json ./
# Prefer npm ci for reproducible installs
RUN --mount=type=cache,target=/root/.npm \
    npm ci

FROM deps AS build
COPY tsconfig*.json ./
COPY src ./src
COPY config ./config
COPY static ./static
RUN npm run build

FROM deps AS prod-deps
ENV NODE_ENV=production
RUN --mount=type=cache,target=/root/.npm \
    npm prune --omit=dev

FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION} AS runner
ENV NODE_ENV=production \
    APP_HOME=/app \
    PORT=3000
WORKDIR ${APP_HOME}
# Busybox wget is enough for healthcheck; curl can be used if preferred
RUN apk add --no-cache wget

# Copy built app and production deps
COPY --from=prod-deps ${APP_HOME}/node_modules ./node_modules
COPY --from=build ${APP_HOME}/dist ./dist
COPY package*.json ./
COPY config ./config
COPY static ./static

# Use non-root user
USER 1001

EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --start-period=20s --retries=3 \
  CMD wget -qO- http://127.0.0.1:${PORT}/health || exit 1

# Default start command
CMD ["node", "dist/node/index.js"]

# Development image with hot reloading (nodemon)
FROM deps AS dev
ENV NODE_ENV=development \
    PORT=3000
RUN npm pkg set scripts.dev:watch="nodemon --watch src --ext ts,tsx,json --exec 'node --loader ts-node/esm src/index.ts'" && \
    npm i -D nodemon@^3
CMD ["npm", "run", "dev:watch"]


```

--------------------------------------------------------------------------------
/src/oauth/web-interface.ts:
--------------------------------------------------------------------------------

```typescript
export class WebInterface {
  // Minimal, accessible pages for success and error. CSS served from /static/oauth/style.css
  renderRedirectPage(providerName: string, redirectUrl: string): string {
    const esc = (s: string) => s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
    return `<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Continue to ${esc(providerName)}</title>
  <link rel="stylesheet" href="/static/oauth/style.css" />
  <meta http-equiv="refresh" content="0;url=${esc(redirectUrl)}" />
  <script>location.replace(${JSON.stringify(redirectUrl)})</script>
  </head>
<body>
  <main class="container">
    <h1>Redirecting…</h1>
    <p>Taking you to ${esc(providerName)} to sign in.</p>
    <p><a class="button" href="${esc(redirectUrl)}">Continue</a></p>
  </main>
</body>
</html>`
  }

  renderSuccessPage(message = 'Authorization completed successfully.'): string {
    const esc = (s: string) => s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
    return `<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>OAuth Success</title>
  <link rel="stylesheet" href="/static/oauth/style.css" />
</head>
<body>
  <main class="container">
    <h1>Success</h1>
    <p>${esc(message)}</p>
  </main>
</body>
</html>`
  }

  renderErrorPage(error = 'Authorization failed.'): string {
    const esc = (s: string) => s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
    return `<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>OAuth Error</title>
  <link rel="stylesheet" href="/static/oauth/style.css" />
</head>
<body>
  <main class="container error">
    <h1>Authorization Error</h1>
    <p>${esc(error)}</p>
  </main>
</body>
</html>`
  }
}


```

--------------------------------------------------------------------------------
/tests/servers/test-streaming.js:
--------------------------------------------------------------------------------

```javascript
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'

async function runStreamingTest() {
  try {
    console.log('Testing Master MCP Server with HTTP Streaming...')
    
    // Create a streamable HTTP transport to connect to our MCP server
    const transport = new StreamableHTTPClientTransport(new URL('http://localhost:3005/mcp'))
    
    // Create the MCP client
    const client = new Client({
      name: 'master-mcp-streaming-test-client',
      version: '1.0.0'
    })
    
    // Initialize the client
    await client.connect(transport)
    console.log('✅ Server initialized with streaming transport')
    console.log('Server info:', client.getServerVersion())
    console.log('Server capabilities:', client.getServerCapabilities())
    
    // List tools using streaming
    console.log('\n--- Testing tools/list with streaming ---')
    const toolsResult = await client.listTools({})
    console.log('✅ tools/list successful with streaming')
    console.log('Number of tools:', toolsResult.tools.length)
    
    // List resources using streaming
    console.log('\n--- Testing resources/list with streaming ---')
    const resourcesResult = await client.listResources({})
    console.log('✅ resources/list successful with streaming')
    console.log('Number of resources:', resourcesResult.resources.length)
    
    // Test ping
    console.log('\n--- Testing ping with streaming ---')
    const pingResult = await client.ping()
    console.log('✅ ping successful with streaming')
    console.log('Ping result:', pingResult)
    
    // Close the connection
    await client.close()
    console.log('\n✅ Disconnected from MCP server')
    console.log('\n🎉 All streaming tests completed successfully!')
    
  } catch (error) {
    console.error('❌ Streaming test failed:', error)
    console.error('Error stack:', error.stack)
  }
}

// Run the streaming test
runStreamingTest()
```

--------------------------------------------------------------------------------
/docs/guides/server-management.md:
--------------------------------------------------------------------------------

```markdown
# Server Management

The `MasterServer` orchestrates backend servers and exposes convenience APIs.

## Key APIs

- `startFromConfig(config, clientToken?)`: Load and health-check backends, discover capabilities
- `performHealthChecks(clientToken?)`: Returns `{ [serverId]: boolean }`
- `restartServer(id)`: Restarts a backend (when supported)
- `unloadAll()`: Stops and clears all backends
- `getRouter()`: Access to `RequestRouter`
- `getAggregatedTools()/getAggregatedResources()`: Current aggregated definitions
- `attachAuthManager(multiAuth)`: Injects a `MultiAuthManager`
- `getOAuthFlowController()`: Provides an OAuth controller to mount in your runtime

## Node Runtime

`src/index.ts` creates an Express app exposing health, metrics, OAuth endpoints, and MCP HTTP endpoints. Use `npm run dev` during development.

## Workers Runtime

`src/runtime/worker.ts` exports a `fetch` handler integrating the protocol and OAuth flows. Configure via `deploy/cloudflare/wrangler.toml`.

## Adding Backends by Source

> Note: Some origin types (git/npm/pypi/docker) are treated as config-driven endpoints in the current loader. Provide an explicit `url` or `port` for the running backend.

<CodeTabs :options="[
  { label: 'Local', value: 'local' },
  { label: 'Git', value: 'git' },
  { label: 'NPM', value: 'npm' },
  { label: 'Docker', value: 'docker' }
]">
  <template #local>

```yaml
servers:
  - id: search
    type: local
    auth_strategy: master_oauth
    config: { port: 4100 }
```

  </template>
  <template #git>

```yaml
servers:
  - id: tools-from-git
    type: git
    auth_strategy: bypass_auth
    config:
      url: http://git-tools.internal:4010
```

  </template>
  <template #npm>

```yaml
servers:
  - id: npm-tools
    type: npm
    auth_strategy: proxy_oauth
    config:
      url: http://npm-tools:4020
```

  </template>
  <template #docker>

```yaml
servers:
  - id: containerized
    type: docker
    auth_strategy: master_oauth
    config:
      url: http://containerized:4030
```

  </template>
</CodeTabs>


```

--------------------------------------------------------------------------------
/src/oauth/state-manager.ts:
--------------------------------------------------------------------------------

```typescript
// State Manager for OAuth CSRF protection
// Generates random opaque state tokens and tracks associated payload with TTL

export interface OAuthStatePayload {
  provider?: string
  serverId?: string
  clientToken?: string
  returnTo?: string
  issuedAt: number
}

export interface StateRecord {
  payload: OAuthStatePayload
  expiresAt: number
}

export interface StateManagerOptions {
  ttlMs?: number
}

function getCrypto(): any {
  const g: any = globalThis as any
  if (g.crypto && g.crypto.subtle && g.crypto.getRandomValues) return g.crypto as any
  try {
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    const nodeCrypto = require('node:crypto')
    return nodeCrypto.webcrypto as any
  } catch {
    throw new Error('Secure crypto not available in this environment')
  }
}

function randomId(bytes = 32): string {
  const crypto = getCrypto()
  const arr = new Uint8Array(bytes)
  crypto.getRandomValues(arr)
  let str = ''
  for (let i = 0; i < arr.length; i++) str += arr[i].toString(16).padStart(2, '0')
  return str
}

export class StateManager {
  private readonly store = new Map<string, StateRecord>()
  private readonly ttl: number

  constructor(options?: StateManagerOptions) {
    this.ttl = options?.ttlMs ?? 10 * 60_000
  }

  create(payload: Omit<OAuthStatePayload, 'issuedAt'>): string {
    const state = randomId(32)
    const now = Date.now()
    this.store.set(state, { payload: { ...payload, issuedAt: now }, expiresAt: now + this.ttl })
    return state
  }

  consume(state: string): OAuthStatePayload | null {
    const rec = this.store.get(state)
    if (!rec) return null
    this.store.delete(state)
    if (rec.expiresAt <= Date.now()) return null
    return rec.payload
  }

  peek(state: string): OAuthStatePayload | null {
    const rec = this.store.get(state)
    if (!rec || rec.expiresAt <= Date.now()) return null
    return rec.payload
  }

  cleanup(): void {
    const now = Date.now()
    for (const [k, v] of this.store) if (v.expiresAt <= now) this.store.delete(k)
  }
}

```

--------------------------------------------------------------------------------
/tests/utils/mock-http.ts:
--------------------------------------------------------------------------------

```typescript
import http from 'node:http'

export type Handler = (req: http.IncomingMessage, body: any) => { status?: number; headers?: Record<string, string>; body?: any }

export interface Route {
  method: string
  path: string | RegExp
  handler: Handler
}

export interface MockServer {
  url: string
  port: number
  close: () => Promise<void>
}

export function createMockServer(routes: Route[], opts?: { port?: number }): Promise<MockServer> {
  const server = http.createServer(async (req, res) => {
    const url = new URL(req.url || '/', `http://${req.headers.host}`)
    const chunks: Buffer[] = []
    for await (const c of req) chunks.push(c as Buffer)
    let body: any = Buffer.concat(chunks).toString('utf8')
    const ct = (req.headers['content-type'] || '').toString()
    try {
      if (ct.includes('application/json') && body) body = JSON.parse(body)
      else if (ct.includes('application/x-www-form-urlencoded') && body) body = Object.fromEntries(new URLSearchParams(body))
    } catch {
      // leave as raw string
    }

    const route = routes.find((r) => r.method.toUpperCase() === (req.method || '').toUpperCase() &&
      (typeof r.path === 'string' ? r.path === url.pathname : r.path.test(url.pathname)))

    const result = route ? route.handler(req, body) : { status: 404, body: { error: 'not found' } }
    const status = result.status ?? 200
    const headers = result.headers ?? { 'content-type': 'application/json' }
    const payload = result.body ?? { ok: true }
    res.statusCode = status
    for (const [k, v] of Object.entries(headers)) res.setHeader(k, v)
    res.end(typeof payload === 'string' || Buffer.isBuffer(payload) ? payload : JSON.stringify(payload))
  })

  return new Promise((resolve) => {
    server.listen(opts?.port ?? 0, () => {
      const addr = server.address()
      const port = typeof addr === 'object' && addr ? addr.port : (opts?.port ?? 0)
      resolve({
        url: `http://localhost:${port}`,
        port,
        close: () => new Promise((r) => server.close(() => r())),
      })
    })
  })
}


```

--------------------------------------------------------------------------------
/src/routing/load-balancer.ts:
--------------------------------------------------------------------------------

```typescript
export type LoadBalancingStrategy = 'round_robin' | 'weighted' | 'health'

export interface LoadBalancingInstance {
  id: string
  weight?: number
  healthScore?: number // 0..100; higher is better
}

export interface LoadBalancerOptions {
  strategy: LoadBalancingStrategy
}

export class LoadBalancer {
  private readonly opts: Required<LoadBalancerOptions>
  private rrIndex: Map<string, number> = new Map()

  constructor(options?: Partial<LoadBalancerOptions>) {
    this.opts = { strategy: options?.strategy ?? 'round_robin' }
  }

  select<T extends LoadBalancingInstance>(key: string, instances: T[]): T | undefined {
    if (!instances.length) return undefined
    switch (this.opts.strategy) {
      case 'weighted':
        return this.selectWeighted(instances)
      case 'health':
        return this.selectHealth(instances, key)
      case 'round_robin':
      default:
        return this.selectRoundRobin(key, instances)
    }
  }

  private selectRoundRobin<T extends LoadBalancingInstance>(key: string, instances: T[]): T {
    const idx = this.rrIndex.get(key) ?? 0
    const chosen = instances[idx % instances.length]
    this.rrIndex.set(key, (idx + 1) % instances.length)
    return chosen
  }

  private selectWeighted<T extends LoadBalancingInstance>(instances: T[]): T {
    const weights = instances.map((i) => Math.max(1, Math.floor(i.weight ?? 1)))
    const total = weights.reduce((a, b) => a + b, 0)
    let r = Math.random() * total
    for (let i = 0; i < instances.length; i++) {
      if (r < weights[i]) return instances[i]
      r -= weights[i]
    }
    return instances[0]
  }

  private selectHealth<T extends LoadBalancingInstance>(instances: T[], key: string): T {
    // Choose highest health; tie-break with RR for stability
    const sorted = [...instances].sort((a, b) => (b.healthScore ?? 0) - (a.healthScore ?? 0))
    const topScore = sorted[0].healthScore ?? 0
    const top = sorted.filter((i) => (i.healthScore ?? 0) === topScore)
    if (top.length === 1) return top[0]
    return this.selectRoundRobin(key + '::health', top)
  }
}

```

--------------------------------------------------------------------------------
/tests/_utils/test-server.ts:
--------------------------------------------------------------------------------

```typescript
import http from 'node:http'

export interface RouteHandler {
  (req: http.IncomingMessage, body: string | undefined): { status?: number; headers?: Record<string, string>; body?: any }
}

export interface TestServer {
  url: string
  port: number
  close: () => Promise<void>
  register: (method: string, path: string, handler: RouteHandler) => void
}

export function createTestServer(): Promise<TestServer> {
  const routes = new Map<string, RouteHandler>()
  const server = http.createServer(async (req, res) => {
    try {
      const url = new URL(req.url || '/', 'http://localhost')
      const key = `${(req.method || 'GET').toUpperCase()} ${url.pathname}`
      let body: string | undefined
      if (req.method && ['POST', 'PUT', 'PATCH'].includes(req.method.toUpperCase())) {
        body = await new Promise<string>((resolve) => {
          const chunks: Buffer[] = []
          req.on('data', (c) => chunks.push(Buffer.isBuffer(c) ? c : Buffer.from(String(c))))
          req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')))
        })
      }
      const handler = routes.get(key)
      if (!handler) {
        res.statusCode = 404
        res.end('not found')
        return
      }
      const result = handler(req, body)
      const status = result.status ?? 200
      const headers = { 'content-type': 'application/json', ...(result.headers ?? {}) }
      const payload = typeof result.body === 'string' ? result.body : JSON.stringify(result.body ?? { ok: true })
      res.writeHead(status, headers)
      res.end(payload)
    } catch (err: any) {
      res.writeHead(500, { 'content-type': 'application/json' })
      res.end(JSON.stringify({ error: err?.message ?? 'internal error' }))
    }
  })

  return new Promise((resolve) => {
    server.listen(0, '127.0.0.1', () => {
      const addr = server.address()
      const port = typeof addr === 'object' && addr ? addr.port : 0
      resolve({
        port,
        url: `http://127.0.0.1:${port}`,
        close: () => new Promise<void>((r) => server.close(() => r())),
        register: (method: string, path: string, handler: RouteHandler) => {
          routes.set(`${method.toUpperCase()} ${path}`, handler)
        },
      })
    })
  })
}


```

--------------------------------------------------------------------------------
/src/server/protocol-handler.ts:
--------------------------------------------------------------------------------

```typescript
import type {
  CallToolRequest,
  CallToolResult,
  ListResourcesRequest,
  ListResourcesResult,
  ListToolsRequest,
  ListToolsResult,
  ReadResourceRequest,
  ReadResourceResult,
  SubscribeRequest,
  SubscribeResult,
} from '../types/mcp.js'
import type { CapabilityAggregator } from '../modules/capability-aggregator.js'
import type { RequestRouter } from '../modules/request-router.js'
import { Logger } from '../utils/logger.js'

export interface ProtocolContext {
  aggregator: CapabilityAggregator
  router: RequestRouter
  // Optional client bearer token provided by gateway
  getClientToken?: () => string | undefined
}

export class ProtocolHandler {
  constructor(private readonly ctx: ProtocolContext) {}

  async handleListTools(_req: ListToolsRequest): Promise<ListToolsResult> {
    try {
      const tools = this.ctx.aggregator.getAllTools(this.ctx.router.getServers())
      return { tools }
    } catch (err) {
      Logger.error('handleListTools failed', err)
      return { tools: [] }
    }
  }

  async handleCallTool(req: CallToolRequest): Promise<CallToolResult> {
    try {
      const token = this.ctx.getClientToken?.()
      const res = await this.ctx.router.routeCallTool(req, token)
      return res
    } catch (err) {
      Logger.warn('handleCallTool error', err)
      return { content: { error: String(err) }, isError: true }
    }
  }

  async handleListResources(_req: ListResourcesRequest): Promise<ListResourcesResult> {
    try {
      const resources = this.ctx.aggregator.getAllResources(this.ctx.router.getServers())
      return { resources }
    } catch (err) {
      Logger.error('handleListResources failed', err)
      return { resources: [] }
    }
  }

  async handleReadResource(req: ReadResourceRequest): Promise<ReadResourceResult> {
    try {
      const token = this.ctx.getClientToken?.()
      const res = await this.ctx.router.routeReadResource(req, token)
      return res
    } catch (err) {
      Logger.warn('handleReadResource error', err)
      return { contents: String(err), mimeType: 'text/plain' }
    }
  }

  async handleSubscribe(_req: SubscribeRequest): Promise<SubscribeResult> {
    // Event subscriptions not yet surfaced; return OK for MCP compatibility
    return { ok: true }
  }
}

```
Page 1/8FirstPrevNextLast