mcpmake 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/bundle.d.ts +1 -0
- package/dist/commands/bundle.d.ts.map +1 -0
- package/dist/commands/bundle.js +5 -4
- package/dist/commands/bundle.js.map +1 -0
- package/dist/commands/ci.d.ts +1 -0
- package/dist/commands/ci.d.ts.map +1 -0
- package/dist/commands/ci.js +3 -2
- package/dist/commands/ci.js.map +1 -0
- package/dist/commands/deploy.d.ts +1 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +4 -3
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/diff.d.ts +1 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +5 -4
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/from/describe.d.ts +1 -0
- package/dist/commands/from/describe.d.ts.map +1 -0
- package/dist/commands/from/describe.js +11 -10
- package/dist/commands/from/describe.js.map +1 -0
- package/dist/commands/from/har.d.ts +1 -0
- package/dist/commands/from/har.d.ts.map +1 -0
- package/dist/commands/from/har.js +14 -13
- package/dist/commands/from/har.js.map +1 -0
- package/dist/commands/from/openapi.d.ts +1 -0
- package/dist/commands/from/openapi.d.ts.map +1 -0
- package/dist/commands/from/openapi.js +17 -16
- package/dist/commands/from/openapi.js.map +1 -0
- package/dist/commands/from/postman.d.ts +1 -0
- package/dist/commands/from/postman.d.ts.map +1 -0
- package/dist/commands/from/postman.js +13 -12
- package/dist/commands/from/postman.js.map +1 -0
- package/dist/commands/from/stainless.d.ts +110 -0
- package/dist/commands/from/stainless.d.ts.map +1 -0
- package/dist/commands/from/stainless.js +272 -0
- package/dist/commands/from/stainless.js.map +1 -0
- package/dist/commands/from/target-support.d.ts +1 -0
- package/dist/commands/from/target-support.d.ts.map +1 -0
- package/dist/commands/from/target-support.js +2 -1
- package/dist/commands/from/target-support.js.map +1 -0
- package/dist/commands/from/url.d.ts +1 -0
- package/dist/commands/from/url.d.ts.map +1 -0
- package/dist/commands/from/url.js +14 -13
- package/dist/commands/from/url.js.map +1 -0
- package/dist/commands/from/website.d.ts +1 -0
- package/dist/commands/from/website.d.ts.map +1 -0
- package/dist/commands/from/website.js +17 -16
- package/dist/commands/from/website.js.map +1 -0
- package/dist/commands/lint.d.ts +1 -0
- package/dist/commands/lint.d.ts.map +1 -0
- package/dist/commands/lint.js +6 -5
- package/dist/commands/lint.js.map +1 -0
- package/dist/commands/merge.d.ts +1 -0
- package/dist/commands/merge.d.ts.map +1 -0
- package/dist/commands/merge.js +3 -2
- package/dist/commands/merge.js.map +1 -0
- package/dist/commands/publish.d.ts +1 -0
- package/dist/commands/publish.d.ts.map +1 -0
- package/dist/commands/publish.js +4 -3
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/rescan.d.ts +1 -0
- package/dist/commands/rescan.d.ts.map +1 -0
- package/dist/commands/rescan.js +12 -11
- package/dist/commands/rescan.js.map +1 -0
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +10 -9
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/verify.d.ts +1 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +7 -6
- package/dist/commands/verify.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -2
- package/dist/index.js.map +1 -0
- package/dist/registry/official-registry.d.ts +1 -0
- package/dist/registry/official-registry.d.ts.map +1 -0
- package/dist/registry/official-registry.js +1 -0
- package/dist/registry/official-registry.js.map +1 -0
- package/package.json +20 -46
- package/README.md +0 -691
- package/dist/analyzer/auth-detector.d.ts +0 -12
- package/dist/analyzer/auth-detector.js +0 -142
- package/dist/analyzer/dom-parser.d.ts +0 -10
- package/dist/analyzer/dom-parser.js +0 -259
- package/dist/analyzer/goal-crawler.d.ts +0 -25
- package/dist/analyzer/goal-crawler.js +0 -177
- package/dist/analyzer/hybrid-detector.d.ts +0 -28
- package/dist/analyzer/hybrid-detector.js +0 -96
- package/dist/analyzer/index.d.ts +0 -12
- package/dist/analyzer/index.js +0 -8
- package/dist/analyzer/screenshot-capture.d.ts +0 -29
- package/dist/analyzer/screenshot-capture.js +0 -42
- package/dist/analyzer/selector-builder.d.ts +0 -19
- package/dist/analyzer/selector-builder.js +0 -199
- package/dist/analyzer/semantic-analyzer.d.ts +0 -13
- package/dist/analyzer/semantic-analyzer.js +0 -145
- package/dist/analyzer/site-crawler.d.ts +0 -38
- package/dist/analyzer/site-crawler.js +0 -235
- package/dist/cloud/billing/billing-engine.d.ts +0 -44
- package/dist/cloud/billing/billing-engine.js +0 -81
- package/dist/cloud/billing/credit-store.d.ts +0 -64
- package/dist/cloud/billing/credit-store.js +0 -168
- package/dist/cloud/billing/index.d.ts +0 -4
- package/dist/cloud/billing/index.js +0 -2
- package/dist/cloud/billing/usage-store.d.ts +0 -42
- package/dist/cloud/billing/usage-store.js +0 -85
- package/dist/cloud/billing/usage-tracker.d.ts +0 -38
- package/dist/cloud/billing/usage-tracker.js +0 -95
- package/dist/cloud/build-pipeline.d.ts +0 -39
- package/dist/cloud/build-pipeline.js +0 -310
- package/dist/cloud/build-queue.d.ts +0 -30
- package/dist/cloud/build-queue.js +0 -70
- package/dist/cloud/caddy-manager.d.ts +0 -18
- package/dist/cloud/caddy-manager.js +0 -97
- package/dist/cloud/container-backend.d.ts +0 -62
- package/dist/cloud/container-backend.js +0 -59
- package/dist/cloud/container-manager.d.ts +0 -64
- package/dist/cloud/container-manager.js +0 -301
- package/dist/cloud/crypto.d.ts +0 -27
- package/dist/cloud/crypto.js +0 -63
- package/dist/cloud/db/index.d.ts +0 -27
- package/dist/cloud/db/index.js +0 -53
- package/dist/cloud/db/migrations.d.ts +0 -12
- package/dist/cloud/db/migrations.js +0 -329
- package/dist/cloud/db/pg-store.d.ts +0 -45
- package/dist/cloud/db/pg-store.js +0 -336
- package/dist/cloud/failure-tracker.d.ts +0 -51
- package/dist/cloud/failure-tracker.js +0 -102
- package/dist/cloud/idle-monitor.d.ts +0 -30
- package/dist/cloud/idle-monitor.js +0 -70
- package/dist/cloud/mailer.d.ts +0 -21
- package/dist/cloud/mailer.js +0 -193
- package/dist/cloud/mcp-proxy.d.ts +0 -58
- package/dist/cloud/mcp-proxy.js +0 -203
- package/dist/cloud/metric-samples.d.ts +0 -43
- package/dist/cloud/metric-samples.js +0 -85
- package/dist/cloud/metrics.d.ts +0 -26
- package/dist/cloud/metrics.js +0 -59
- package/dist/cloud/multipart.d.ts +0 -26
- package/dist/cloud/multipart.js +0 -132
- package/dist/cloud/observability.d.ts +0 -27
- package/dist/cloud/observability.js +0 -98
- package/dist/cloud/rate-limiter.d.ts +0 -31
- package/dist/cloud/rate-limiter.js +0 -58
- package/dist/cloud/request-security.d.ts +0 -5
- package/dist/cloud/request-security.js +0 -74
- package/dist/cloud/resource-monitor.d.ts +0 -69
- package/dist/cloud/resource-monitor.js +0 -130
- package/dist/cloud/secret-store.d.ts +0 -38
- package/dist/cloud/secret-store.js +0 -103
- package/dist/cloud/security.d.ts +0 -26
- package/dist/cloud/security.js +0 -142
- package/dist/cloud/server.d.ts +0 -21
- package/dist/cloud/server.js +0 -1079
- package/dist/cloud/shared-state.d.ts +0 -72
- package/dist/cloud/shared-state.js +0 -159
- package/dist/cloud/ssrf.d.ts +0 -43
- package/dist/cloud/ssrf.js +0 -150
- package/dist/cloud/store.d.ts +0 -41
- package/dist/cloud/store.js +0 -75
- package/dist/cloud/stripe.d.ts +0 -78
- package/dist/cloud/stripe.js +0 -317
- package/dist/cloud/telemetry-store.d.ts +0 -53
- package/dist/cloud/telemetry-store.js +0 -108
- package/dist/cloud/web/auth.d.ts +0 -225
- package/dist/cloud/web/auth.js +0 -555
- package/dist/cloud/web/charts.d.ts +0 -70
- package/dist/cloud/web/charts.js +0 -178
- package/dist/cloud/web/csrf.d.ts +0 -14
- package/dist/cloud/web/csrf.js +0 -22
- package/dist/cloud/web/docs.d.ts +0 -40
- package/dist/cloud/web/docs.js +0 -174
- package/dist/cloud/web/router.d.ts +0 -25
- package/dist/cloud/web/router.js +0 -1921
- package/dist/cloud/web/static/alpine.min.js +0 -5
- package/dist/cloud/web/static/favicon.svg +0 -4
- package/dist/cloud/web/static/htmx-sse.js +0 -290
- package/dist/cloud/web/static/htmx.min.js +0 -1
- package/dist/cloud/web/static/style.css +0 -2683
- package/dist/cloud/web/static-server.d.ts +0 -13
- package/dist/cloud/web/static-server.js +0 -73
- package/dist/cloud/web/template-engine.d.ts +0 -27
- package/dist/cloud/web/template-engine.js +0 -146
- package/dist/cloud/web/templates/layouts/admin.hbs +0 -57
- package/dist/cloud/web/templates/layouts/auth.hbs +0 -138
- package/dist/cloud/web/templates/layouts/base.hbs +0 -16
- package/dist/cloud/web/templates/layouts/dashboard.hbs +0 -39
- package/dist/cloud/web/templates/layouts/landing.hbs +0 -82
- package/dist/cloud/web/templates/pages/admin/overview.hbs +0 -123
- package/dist/cloud/web/templates/pages/admin/servers.hbs +0 -129
- package/dist/cloud/web/templates/pages/admin/telemetry.hbs +0 -39
- package/dist/cloud/web/templates/pages/admin/user-edit.hbs +0 -91
- package/dist/cloud/web/templates/pages/admin/users.hbs +0 -179
- package/dist/cloud/web/templates/pages/auth/forgot-password.hbs +0 -25
- package/dist/cloud/web/templates/pages/auth/login.hbs +0 -33
- package/dist/cloud/web/templates/pages/auth/register.hbs +0 -32
- package/dist/cloud/web/templates/pages/auth/reset-password.hbs +0 -34
- package/dist/cloud/web/templates/pages/dashboard/billing.hbs +0 -140
- package/dist/cloud/web/templates/pages/dashboard/create.hbs +0 -173
- package/dist/cloud/web/templates/pages/dashboard/index.hbs +0 -8
- package/dist/cloud/web/templates/pages/dashboard/server-detail.hbs +0 -280
- package/dist/cloud/web/templates/pages/dashboard/server-logs.hbs +0 -35
- package/dist/cloud/web/templates/pages/dashboard/server-metrics.hbs +0 -63
- package/dist/cloud/web/templates/pages/dashboard/servers-partial.hbs +0 -21
- package/dist/cloud/web/templates/pages/dashboard/servers.hbs +0 -44
- package/dist/cloud/web/templates/pages/docs/show.hbs +0 -16
- package/dist/cloud/web/templates/pages/errors/404.hbs +0 -9
- package/dist/cloud/web/templates/pages/errors/500.hbs +0 -8
- package/dist/cloud/web/templates/pages/landing/index.hbs +0 -223
- package/dist/cloud/web/templates/pages/legal/privacy.hbs +0 -71
- package/dist/cloud/web/templates/pages/legal/terms.hbs +0 -73
- package/dist/cloud/web/templates/partials/admin-stats.hbs +0 -52
- package/dist/cloud/web/templates/partials/flash-message.hbs +0 -6
- package/dist/cloud/web/templates/partials/pricing-table.hbs +0 -103
- package/dist/cloud/web/templates/partials/server-card.hbs +0 -19
- package/dist/cloud/web/templates/partials/status-badge.hbs +0 -1
- package/dist/config/configurable-command.d.ts +0 -13
- package/dist/config/configurable-command.js +0 -70
- package/dist/config/mcpmake-config.d.ts +0 -68
- package/dist/config/mcpmake-config.js +0 -207
- package/dist/docs/cli.md +0 -400
- package/dist/docs/mcp-2026-07-28-migration.md +0 -78
- package/dist/docs/migrate-from-stainless.md +0 -94
- package/dist/docs/quickstart.md +0 -166
- package/dist/docs/show-hn.md +0 -26
- package/dist/docs/website-servers.md +0 -169
- package/dist/emitter/code-writer.d.ts +0 -8
- package/dist/emitter/code-writer.js +0 -25
- package/dist/emitter/index.d.ts +0 -32
- package/dist/emitter/index.js +0 -280
- package/dist/emitter/mcpb-bundler.d.ts +0 -31
- package/dist/emitter/mcpb-bundler.js +0 -172
- package/dist/emitter/project-scaffolder.d.ts +0 -4
- package/dist/emitter/project-scaffolder.js +0 -89
- package/dist/emitter/python-template-loader.d.ts +0 -4
- package/dist/emitter/python-template-loader.js +0 -30
- package/dist/emitter/python-templates/dockerfile.hbs +0 -14
- package/dist/emitter/python-templates/env.example.hbs +0 -6
- package/dist/emitter/python-templates/requirements.txt.hbs +0 -4
- package/dist/emitter/python-templates/server.py.hbs +0 -77
- package/dist/emitter/site-scaffolder.d.ts +0 -13
- package/dist/emitter/site-scaffolder.js +0 -70
- package/dist/emitter/site-template-loader.d.ts +0 -5
- package/dist/emitter/site-template-loader.js +0 -47
- package/dist/emitter/site-templates/browser-manager.ts.hbs +0 -233
- package/dist/emitter/site-templates/config.ts.hbs +0 -28
- package/dist/emitter/site-templates/dockerfile.hbs +0 -31
- package/dist/emitter/site-templates/env.example.hbs +0 -19
- package/dist/emitter/site-templates/package.json.hbs +0 -26
- package/dist/emitter/site-templates/server-main-http.ts.hbs +0 -108
- package/dist/emitter/site-templates/server-main.ts.hbs +0 -23
- package/dist/emitter/site-templates/tool-handler-action.ts.hbs +0 -86
- package/dist/emitter/site-templates/tool-handler-form.ts.hbs +0 -116
- package/dist/emitter/site-templates/tool-handler-lifecycle.ts.hbs +0 -146
- package/dist/emitter/site-templates/tool-index.ts.hbs +0 -11
- package/dist/emitter/template-loader.d.ts +0 -1
- package/dist/emitter/template-loader.js +0 -27
- package/dist/emitter/templates/auth-provider.ts.hbs +0 -57
- package/dist/emitter/templates/config.ts.hbs +0 -63
- package/dist/emitter/templates/discovery.ts.hbs +0 -301
- package/dist/emitter/templates/dockerfile.hbs +0 -34
- package/dist/emitter/templates/env.example.hbs +0 -28
- package/dist/emitter/templates/gitignore.hbs +0 -5
- package/dist/emitter/templates/http-executor.ts.hbs +0 -117
- package/dist/emitter/templates/oauth.ts.hbs +0 -188
- package/dist/emitter/templates/package.json.hbs +0 -25
- package/dist/emitter/templates/prompts.ts.hbs +0 -22
- package/dist/emitter/templates/readme.md.hbs +0 -123
- package/dist/emitter/templates/resources.ts.hbs +0 -63
- package/dist/emitter/templates/server-main-http.ts.hbs +0 -407
- package/dist/emitter/templates/server-main.ts.hbs +0 -40
- package/dist/emitter/templates/task-handlers.ts.hbs +0 -189
- package/dist/emitter/templates/task-manager.ts.hbs +0 -139
- package/dist/emitter/templates/task-sse.ts.hbs +0 -105
- package/dist/emitter/templates/tool-handler.ts.hbs +0 -124
- package/dist/emitter/templates/tool-index.ts.hbs +0 -11
- package/dist/emitter/templates/tool-test.ts.hbs +0 -57
- package/dist/emitter/templates/trace.ts.hbs +0 -79
- package/dist/emitter/templates/tsconfig.json.hbs +0 -16
- package/dist/emitter/templates/types.ts.hbs +0 -5
- package/dist/emitter/worker-template-loader.d.ts +0 -5
- package/dist/emitter/worker-template-loader.js +0 -33
- package/dist/emitter/worker-templates/config.ts.hbs +0 -54
- package/dist/emitter/worker-templates/dev-vars.example.hbs +0 -10
- package/dist/emitter/worker-templates/gitignore.hbs +0 -6
- package/dist/emitter/worker-templates/package.json.hbs +0 -24
- package/dist/emitter/worker-templates/readme.md.hbs +0 -53
- package/dist/emitter/worker-templates/server.test.ts.hbs +0 -20
- package/dist/emitter/worker-templates/tool-handler.ts.hbs +0 -85
- package/dist/emitter/worker-templates/tool-index.ts.hbs +0 -28
- package/dist/emitter/worker-templates/tsconfig.json.hbs +0 -17
- package/dist/emitter/worker-templates/worker.ts.hbs +0 -242
- package/dist/emitter/worker-templates/wrangler.toml.hbs +0 -19
- package/dist/generator/spec-generator.d.ts +0 -6
- package/dist/generator/spec-generator.js +0 -50
- package/dist/parser/har-filter.d.ts +0 -8
- package/dist/parser/har-filter.js +0 -71
- package/dist/parser/har-loader.d.ts +0 -2
- package/dist/parser/har-loader.js +0 -14
- package/dist/parser/har-normalizer.d.ts +0 -20
- package/dist/parser/har-normalizer.js +0 -78
- package/dist/parser/index.d.ts +0 -10
- package/dist/parser/index.js +0 -6
- package/dist/parser/openapi-loader.d.ts +0 -6
- package/dist/parser/openapi-loader.js +0 -308
- package/dist/parser/operation-extractor.d.ts +0 -13
- package/dist/parser/operation-extractor.js +0 -155
- package/dist/parser/overlay-loader.d.ts +0 -10
- package/dist/parser/overlay-loader.js +0 -184
- package/dist/parser/postman-loader.d.ts +0 -9
- package/dist/parser/postman-loader.js +0 -106
- package/dist/parser/schema-converter.d.ts +0 -12
- package/dist/parser/schema-converter.js +0 -117
- package/dist/plugins/adapter.d.ts +0 -40
- package/dist/plugins/adapter.js +0 -15
- package/dist/plugins/loader.d.ts +0 -25
- package/dist/plugins/loader.js +0 -58
- package/dist/pricing.d.ts +0 -55
- package/dist/pricing.js +0 -133
- package/dist/providers/index.d.ts +0 -15
- package/dist/providers/index.js +0 -56
- package/dist/recorder/browser-recorder.d.ts +0 -22
- package/dist/recorder/browser-recorder.js +0 -205
- package/dist/rescan/diff-engine.d.ts +0 -5
- package/dist/rescan/diff-engine.js +0 -312
- package/dist/rescan/index.d.ts +0 -3
- package/dist/rescan/index.js +0 -2
- package/dist/rescan/rescan-runner.d.ts +0 -42
- package/dist/rescan/rescan-runner.js +0 -69
- package/dist/rescan/rescan-scheduler.d.ts +0 -41
- package/dist/rescan/rescan-scheduler.js +0 -179
- package/dist/site-transformer/browser-tools.d.ts +0 -10
- package/dist/site-transformer/browser-tools.js +0 -59
- package/dist/site-transformer/index.d.ts +0 -2
- package/dist/site-transformer/index.js +0 -2
- package/dist/site-transformer/selector-healer.d.ts +0 -8
- package/dist/site-transformer/selector-healer.js +0 -106
- package/dist/site-transformer/tool-generator.d.ts +0 -13
- package/dist/site-transformer/tool-generator.js +0 -245
- package/dist/transformer/auth-detector.d.ts +0 -13
- package/dist/transformer/auth-detector.js +0 -90
- package/dist/transformer/catalog-builder.d.ts +0 -18
- package/dist/transformer/catalog-builder.js +0 -56
- package/dist/transformer/client-compat.d.ts +0 -6
- package/dist/transformer/client-compat.js +0 -44
- package/dist/transformer/har-clusterer.d.ts +0 -9
- package/dist/transformer/har-clusterer.js +0 -27
- package/dist/transformer/har-dedup.d.ts +0 -10
- package/dist/transformer/har-dedup.js +0 -81
- package/dist/transformer/har-schema-inferrer.d.ts +0 -15
- package/dist/transformer/har-schema-inferrer.js +0 -90
- package/dist/transformer/har-to-operations.d.ts +0 -13
- package/dist/transformer/har-to-operations.js +0 -192
- package/dist/transformer/index.d.ts +0 -8
- package/dist/transformer/index.js +0 -6
- package/dist/transformer/llm-namer.d.ts +0 -6
- package/dist/transformer/llm-namer.js +0 -59
- package/dist/transformer/naming.d.ts +0 -4
- package/dist/transformer/naming.js +0 -30
- package/dist/transformer/operation-filter.d.ts +0 -13
- package/dist/transformer/operation-filter.js +0 -52
- package/dist/transformer/resource-builder.d.ts +0 -12
- package/dist/transformer/resource-builder.js +0 -80
- package/dist/transformer/schema-merger.d.ts +0 -14
- package/dist/transformer/schema-merger.js +0 -65
- package/dist/transformer/tool-builder.d.ts +0 -3
- package/dist/transformer/tool-builder.js +0 -114
- package/dist/types/index.d.ts +0 -131
- package/dist/types/index.js +0 -1
- package/dist/types/site.d.ts +0 -284
- package/dist/types/site.js +0 -8
- package/dist/utils/fail.d.ts +0 -48
- package/dist/utils/fail.js +0 -204
- package/dist/utils/fs.d.ts +0 -5
- package/dist/utils/fs.js +0 -28
- package/dist/utils/interactive.d.ts +0 -6
- package/dist/utils/interactive.js +0 -30
- package/dist/utils/logger.d.ts +0 -1
- package/dist/utils/logger.js +0 -2
- package/dist/utils/sanitize.d.ts +0 -28
- package/dist/utils/sanitize.js +0 -44
- package/dist/utils/watcher.d.ts +0 -11
- package/dist/utils/watcher.js +0 -36
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
|
|
3
|
-
export function registerAllPrompts(server: McpServer): void {
|
|
4
|
-
{{#each prompts}}
|
|
5
|
-
server.prompt(
|
|
6
|
-
'{{name}}',
|
|
7
|
-
`{{{description}}}`,
|
|
8
|
-
() => ({
|
|
9
|
-
messages: [
|
|
10
|
-
{
|
|
11
|
-
role: 'user' as const,
|
|
12
|
-
content: {
|
|
13
|
-
type: 'text' as const,
|
|
14
|
-
text: `{{{template}}}`,
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
],
|
|
18
|
-
}),
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
{{/each}}
|
|
22
|
-
}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
# {{serverName}}
|
|
2
|
-
|
|
3
|
-
MCP server generated by [mcpmake](https://github.com/starkyru/mcpmake).
|
|
4
|
-
|
|
5
|
-
## Setup
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install
|
|
9
|
-
cp .env.example .env # fill in your credentials
|
|
10
|
-
npm run build
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Running
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
# stdio transport (for Claude Desktop)
|
|
17
|
-
npm start
|
|
18
|
-
|
|
19
|
-
# Development mode (auto-reload)
|
|
20
|
-
npm run dev
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
{{#if (eq transport "http")}}
|
|
24
|
-
## HTTP Transport
|
|
25
|
-
|
|
26
|
-
Run the server over HTTP instead of stdio:
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
TRANSPORT=http PORT=3000 npm start
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
The MCP endpoint is available at `http://localhost:3000/mcp`.
|
|
33
|
-
|
|
34
|
-
| Endpoint | Description |
|
|
35
|
-
|----------|-------------|
|
|
36
|
-
| `POST /mcp` | MCP protocol (JSON-RPC) |
|
|
37
|
-
| `GET /health` | Health check (returns 200 OK) |
|
|
38
|
-
| `GET /ready` | Readiness check (503 during startup/shutdown) |
|
|
39
|
-
{{#if hasOAuth}}
|
|
40
|
-
| `GET /.well-known/oauth-authorization-server` | OAuth Authorization Server Metadata (RFC 8414) |
|
|
41
|
-
{{/if}}
|
|
42
|
-
|
|
43
|
-
### Session mode (MCP 2026-07-28)
|
|
44
|
-
|
|
45
|
-
The server is **stateless by default** (no `Mcp-Session-Id`) so any request can
|
|
46
|
-
hit any instance. Set `MCP_STATEFUL=true` to keep per-session mode if a client
|
|
47
|
-
needs resumable streams. A `server/discover` preflight is supported, and the
|
|
48
|
-
`Mcp-Method`/`Mcp-Name` routing headers are accepted (and logged). See
|
|
49
|
-
[the migration notes](https://github.com/starkyru/mcpmake/blob/main/docs/mcp-2026-07-28-migration.md).
|
|
50
|
-
|
|
51
|
-
### Distributed tracing (W3C Trace Context)
|
|
52
|
-
|
|
53
|
-
An inbound [`traceparent`](https://www.w3.org/TR/trace-context/) is continued
|
|
54
|
-
(or a fresh trace started) per request and stamped onto every upstream API call,
|
|
55
|
-
so one trace spans client → MCP server → API. `tracestate` is propagated
|
|
56
|
-
verbatim. Standardized in MCP 2026-07-28.
|
|
57
|
-
|
|
58
|
-
### Docker Deployment
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
docker build -t {{serverName}} .
|
|
62
|
-
docker run --rm -p 3000:3000 --read-only --cap-drop=ALL --security-opt=no-new-privileges --env-file .env {{serverName}}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
The container runs as a non-root user and is compatible with `--read-only` filesystems.
|
|
66
|
-
|
|
67
|
-
{{/if}}
|
|
68
|
-
## Configuration
|
|
69
|
-
|
|
70
|
-
Copy `.env.example` to `.env` and fill in:
|
|
71
|
-
|
|
72
|
-
| Variable | Description | Required |
|
|
73
|
-
|----------|-------------|----------|
|
|
74
|
-
| `BASE_URL` | API base URL | Yes |
|
|
75
|
-
{{#each authEnvVars}}
|
|
76
|
-
| `{{name}}` | {{description}} | {{#if required}}Yes{{else}}No{{/if}} |
|
|
77
|
-
{{/each}}
|
|
78
|
-
| `MAX_RETRIES` | Max retry attempts (default: 3) | No |
|
|
79
|
-
| `REQUEST_INTERVAL_MS` | Min ms between requests (default: 100) | No |
|
|
80
|
-
|
|
81
|
-
## Tools
|
|
82
|
-
|
|
83
|
-
This server exposes {{tools.length}} tools:
|
|
84
|
-
{{#if dynamicDiscovery}}
|
|
85
|
-
|
|
86
|
-
> **Dynamic discovery is enabled.** Instead of registering all {{tools.length}} tools
|
|
87
|
-
> upfront (high token cost), this server exposes meta-tools — `list_tools`,
|
|
88
|
-
> `search_tools`, `get_tool_schema`, and `execute_tool` — so the agent loads only
|
|
89
|
-
> the schemas it needs.
|
|
90
|
-
{{/if}}
|
|
91
|
-
{{#if recommendDiscovery}}
|
|
92
|
-
|
|
93
|
-
> **Tip — large API ({{tools.length}} tools).** Registering this many tools upfront
|
|
94
|
-
> costs the agent a lot of context tokens, the most common reason big MCP servers
|
|
95
|
-
> underperform. Re-run your generate command with `--dynamic-discovery` to expose
|
|
96
|
-
> meta-tools (`list_tools` / `search_tools` / `get_tool_schema` / `execute_tool`)
|
|
97
|
-
> and load tool schemas on demand.
|
|
98
|
-
{{/if}}
|
|
99
|
-
|
|
100
|
-
{{#each tools}}
|
|
101
|
-
### `{{name}}`
|
|
102
|
-
|
|
103
|
-
{{description}}
|
|
104
|
-
|
|
105
|
-
{{/each}}
|
|
106
|
-
|
|
107
|
-
## Claude Desktop Integration
|
|
108
|
-
|
|
109
|
-
Add to your Claude Desktop config (`~/.claude/claude_desktop_config.json`):
|
|
110
|
-
|
|
111
|
-
```json
|
|
112
|
-
{
|
|
113
|
-
"mcpServers": {
|
|
114
|
-
"{{serverName}}": {
|
|
115
|
-
"command": "node",
|
|
116
|
-
"args": ["{{serverName}}/dist/index.js"],
|
|
117
|
-
"env": {
|
|
118
|
-
"BASE_URL": "YOUR_BASE_URL"
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
```
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import { executeRequest } from './http.js';
|
|
3
|
-
import type { AppConfig } from './config.js';
|
|
4
|
-
|
|
5
|
-
export function registerAllResources(server: McpServer, config: AppConfig): void {
|
|
6
|
-
{{#each resources}}
|
|
7
|
-
{{#if isTemplate}}
|
|
8
|
-
server.resource(
|
|
9
|
-
'{{name}}',
|
|
10
|
-
'{{uri}}',
|
|
11
|
-
{
|
|
12
|
-
description: `{{{description}}}`,
|
|
13
|
-
mimeType: 'application/json',
|
|
14
|
-
},
|
|
15
|
-
async (uri) => {
|
|
16
|
-
{{{urlBody}}}
|
|
17
|
-
const response = await executeRequest({
|
|
18
|
-
method: 'get',
|
|
19
|
-
url,
|
|
20
|
-
headers: {},
|
|
21
|
-
config,
|
|
22
|
-
});
|
|
23
|
-
return {
|
|
24
|
-
contents: [
|
|
25
|
-
{
|
|
26
|
-
uri: uri.href,
|
|
27
|
-
mimeType: 'application/json',
|
|
28
|
-
text: JSON.stringify(response.data, null, 2),
|
|
29
|
-
},
|
|
30
|
-
],
|
|
31
|
-
};
|
|
32
|
-
},
|
|
33
|
-
);
|
|
34
|
-
{{else}}
|
|
35
|
-
server.resource(
|
|
36
|
-
'{{name}}',
|
|
37
|
-
'{{uri}}',
|
|
38
|
-
{
|
|
39
|
-
description: `{{{description}}}`,
|
|
40
|
-
mimeType: 'application/json',
|
|
41
|
-
},
|
|
42
|
-
async () => {
|
|
43
|
-
const response = await executeRequest({
|
|
44
|
-
method: 'get',
|
|
45
|
-
url: `${config.baseUrl}{{path}}`,
|
|
46
|
-
headers: {},
|
|
47
|
-
config,
|
|
48
|
-
});
|
|
49
|
-
return {
|
|
50
|
-
contents: [
|
|
51
|
-
{
|
|
52
|
-
uri: '{{uri}}',
|
|
53
|
-
mimeType: 'application/json',
|
|
54
|
-
text: JSON.stringify(response.data, null, 2),
|
|
55
|
-
},
|
|
56
|
-
],
|
|
57
|
-
};
|
|
58
|
-
},
|
|
59
|
-
);
|
|
60
|
-
{{/if}}
|
|
61
|
-
|
|
62
|
-
{{/each}}
|
|
63
|
-
}
|
|
@@ -1,407 +0,0 @@
|
|
|
1
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
-
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
4
|
-
import { registerAllTools } from './tools/index.js';
|
|
5
|
-
{{#if hasResources}}
|
|
6
|
-
import { registerAllResources } from './resources.js';
|
|
7
|
-
{{/if}}
|
|
8
|
-
{{#if hasPrompts}}
|
|
9
|
-
import { registerAllPrompts } from './prompts.js';
|
|
10
|
-
{{/if}}
|
|
11
|
-
import { loadConfig } from './config.js';
|
|
12
|
-
{{#if hasAsyncTools}}
|
|
13
|
-
import { handleTaskRoutes, handleTaskRpc } from './task-handlers.js';
|
|
14
|
-
import { handleTaskSse } from './task-sse.js';
|
|
15
|
-
{{/if}}
|
|
16
|
-
{{#if hasOAuth}}
|
|
17
|
-
import { getAuthServerMetadata } from './oauth.js';
|
|
18
|
-
{{/if}}
|
|
19
|
-
import http from 'node:http';
|
|
20
|
-
import crypto from 'node:crypto';
|
|
21
|
-
import { deriveContext, runWithTrace } from './trace.js';
|
|
22
|
-
|
|
23
|
-
/* ── Structured JSON logger ─────────────────────────────────────────── */
|
|
24
|
-
|
|
25
|
-
function log(level: 'info' | 'error', msg: string, extra?: Record<string, unknown>): void {
|
|
26
|
-
const entry = { ts: new Date().toISOString(), level, msg, ...extra };
|
|
27
|
-
process.stderr.write(JSON.stringify(entry) + '\n');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/* ── MCP 2026-07-28 ─────────────────────────────────────────────────────
|
|
31
|
-
* This server is being migrated toward the 2026-07-28 spec revision (RC).
|
|
32
|
-
* Implemented here (additive, works against the current SDK):
|
|
33
|
-
* - stateless transport by default (set MCP_STATEFUL=true to keep sessions)
|
|
34
|
-
* - server/discover preflight (SEP-2575)
|
|
35
|
-
* - Mcp-Method / Mcp-Name routing headers logged (SEP-2243)
|
|
36
|
-
* - Tasks extension methods tasks/get|update|cancel (tasks/list removed)
|
|
37
|
-
* SDK-gated (lands when @modelcontextprotocol/sdk ships RC support, then the
|
|
38
|
-
* package.json pin is bumped): removal of the initialize/initialized handshake
|
|
39
|
-
* and moving protocolVersion/clientInfo/capabilities into per-request _meta.
|
|
40
|
-
* The 2026-07-28 RC is NOT final — wire shapes marked VERIFY may change. */
|
|
41
|
-
const PROTOCOL_REVISION = '2026-07-28'; // VERIFY against the final spec
|
|
42
|
-
|
|
43
|
-
/* ── Bearer authentication ──────────────────────────────────────────────
|
|
44
|
-
* Constant-time check that the request presents the expected bearer token via
|
|
45
|
-
* the `Authorization: Bearer <token>` header. Returns true when no token is
|
|
46
|
-
* configured (auth disabled). The token is never accepted from the query
|
|
47
|
-
* string — URLs leak through logs, history, and referrers. */
|
|
48
|
-
function isAuthorized(req: http.IncomingMessage, expected: string | undefined): boolean {
|
|
49
|
-
if (!expected) return true; // auth disabled when MCP_AUTH_TOKEN is unset
|
|
50
|
-
|
|
51
|
-
const header = req.headers.authorization;
|
|
52
|
-
if (typeof header !== 'string' || !header.startsWith('Bearer ')) return false;
|
|
53
|
-
const presented = header.slice(7).trim();
|
|
54
|
-
if (!presented) return false;
|
|
55
|
-
|
|
56
|
-
const a = Buffer.from(presented);
|
|
57
|
-
const b = Buffer.from(expected);
|
|
58
|
-
if (a.length !== b.length) return false;
|
|
59
|
-
return crypto.timingSafeEqual(a, b);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/* ── Bounded request-body reader ─────────────────────────────────────────
|
|
63
|
-
* Buffers the body so we can peek JSON-RPC for server/discover + tasks/* and
|
|
64
|
-
* then hand the parsed value to the SDK transport's `parsedBody` argument
|
|
65
|
-
* (so the drained stream is never re-read). Resolves null past the size cap. */
|
|
66
|
-
const MAX_BODY = 4 * 1024 * 1024; // 4 MB
|
|
67
|
-
function readBody(req: http.IncomingMessage): Promise<Buffer | null> {
|
|
68
|
-
return new Promise((resolve) => {
|
|
69
|
-
const chunks: Buffer[] = [];
|
|
70
|
-
let total = 0;
|
|
71
|
-
let settled = false;
|
|
72
|
-
const done = (v: Buffer | null) => {
|
|
73
|
-
if (!settled) {
|
|
74
|
-
settled = true;
|
|
75
|
-
resolve(v);
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
req.on('data', (c: Buffer) => {
|
|
79
|
-
total += c.length;
|
|
80
|
-
if (total > MAX_BODY) {
|
|
81
|
-
done(null);
|
|
82
|
-
req.destroy();
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
chunks.push(c);
|
|
86
|
-
});
|
|
87
|
-
req.on('end', () => done(Buffer.concat(chunks)));
|
|
88
|
-
req.on('error', () => done(null));
|
|
89
|
-
req.on('aborted', () => done(null));
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function sendJson(res: http.ServerResponse, status: number, body: unknown): void {
|
|
94
|
-
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
95
|
-
res.end(JSON.stringify(body));
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/** Narrow a possibly-repeated request header to a single string value. */
|
|
99
|
-
function headerValue(v: string | string[] | undefined): string | undefined {
|
|
100
|
-
return Array.isArray(v) ? v[0] : v;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function rpcError(res: http.ServerResponse, id: unknown, code: number, message: string): void {
|
|
104
|
-
sendJson(res, 200, { jsonrpc: '2.0', id: id ?? null, error: { code, message } });
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/* ── server/discover (SEP-2575) — VERIFY result shape against final spec ── */
|
|
108
|
-
function buildDiscoverResult(id: unknown): Record<string, unknown> {
|
|
109
|
-
return {
|
|
110
|
-
jsonrpc: '2.0',
|
|
111
|
-
id: id ?? null,
|
|
112
|
-
result: {
|
|
113
|
-
server: { name: '{{serverName}}', version: '{{serverVersion}}' },
|
|
114
|
-
protocolRevision: PROTOCOL_REVISION,
|
|
115
|
-
capabilities: {
|
|
116
|
-
tools: { count: {{tools.length}} },
|
|
117
|
-
{{#if hasResources}}
|
|
118
|
-
resources: {},
|
|
119
|
-
{{/if}}
|
|
120
|
-
{{#if hasPrompts}}
|
|
121
|
-
prompts: {},
|
|
122
|
-
{{/if}}
|
|
123
|
-
},
|
|
124
|
-
extensions: [
|
|
125
|
-
{{#if hasAsyncTools}}
|
|
126
|
-
'tasks',
|
|
127
|
-
{{/if}}
|
|
128
|
-
{{#if hasOAuth}}
|
|
129
|
-
'oauth',
|
|
130
|
-
{{/if}}
|
|
131
|
-
],
|
|
132
|
-
cacheTtlSeconds: 300,
|
|
133
|
-
},
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/* ── MCP server factory ──────────────────────────────────────────────────
|
|
138
|
-
* Builds a fully-registered McpServer. In stateless mode a fresh instance is
|
|
139
|
-
* created per request (a single McpServer connected to multiple transports
|
|
140
|
-
* concurrently races on its internal transport reference). */
|
|
141
|
-
function createMcpServer(config: ReturnType<typeof loadConfig>): McpServer {
|
|
142
|
-
const server = new McpServer({
|
|
143
|
-
name: '{{serverName}}',
|
|
144
|
-
version: '{{serverVersion}}',
|
|
145
|
-
});
|
|
146
|
-
registerAllTools(server, config);
|
|
147
|
-
{{#if hasResources}}
|
|
148
|
-
registerAllResources(server, config);
|
|
149
|
-
{{/if}}
|
|
150
|
-
{{#if hasPrompts}}
|
|
151
|
-
registerAllPrompts(server);
|
|
152
|
-
{{/if}}
|
|
153
|
-
return server;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/* ── Bootstrap ───────────────────────────────────────────────────────── */
|
|
157
|
-
|
|
158
|
-
const config = loadConfig();
|
|
159
|
-
const transportMode = process.env.TRANSPORT ?? 'stdio';
|
|
160
|
-
|
|
161
|
-
if (transportMode === 'http') {
|
|
162
|
-
const port = parseInt(process.env.PORT ?? '3000', 10);
|
|
163
|
-
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
164
|
-
log('error', 'Invalid PORT value, must be 1-65535', { PORT: process.env.PORT });
|
|
165
|
-
process.exit(1);
|
|
166
|
-
}
|
|
167
|
-
const allowedOrigin = process.env.ALLOWED_ORIGIN;
|
|
168
|
-
const authToken = process.env.MCP_AUTH_TOKEN;
|
|
169
|
-
/* Stateless by default (2026-07-28). MCP_STATEFUL=true keeps Mcp-Session-Id
|
|
170
|
-
* sessions during the migration / for clients that need resumable streams. */
|
|
171
|
-
const stateful = process.env.MCP_STATEFUL === 'true';
|
|
172
|
-
let isReady = false;
|
|
173
|
-
|
|
174
|
-
// Stateful mode uses one shared server + transport; stateless builds them
|
|
175
|
-
// per request (see createMcpServer + dispatchToTransport).
|
|
176
|
-
const sharedServer = stateful ? createMcpServer(config) : null;
|
|
177
|
-
const sharedTransport = stateful
|
|
178
|
-
? new StreamableHTTPServerTransport({ sessionIdGenerator: () => crypto.randomUUID() })
|
|
179
|
-
: null;
|
|
180
|
-
|
|
181
|
-
async function dispatchToTransport(
|
|
182
|
-
req: http.IncomingMessage,
|
|
183
|
-
res: http.ServerResponse,
|
|
184
|
-
parsedBody?: unknown,
|
|
185
|
-
): Promise<void> {
|
|
186
|
-
/* Bind W3C Trace Context for this request (continuing an inbound trace or
|
|
187
|
-
* starting one) so upstream API calls made inside the tool handlers carry
|
|
188
|
-
* the traceparent and the distributed trace spans the API hop. */
|
|
189
|
-
const trace = deriveContext(
|
|
190
|
-
headerValue(req.headers['traceparent']),
|
|
191
|
-
headerValue(req.headers['tracestate']),
|
|
192
|
-
);
|
|
193
|
-
await runWithTrace(trace, async () => {
|
|
194
|
-
if (stateful && sharedTransport) {
|
|
195
|
-
await sharedTransport.handleRequest(req, res, parsedBody);
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
const reqServer = createMcpServer(config);
|
|
199
|
-
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
|
|
200
|
-
res.on('close', () => {
|
|
201
|
-
void transport.close();
|
|
202
|
-
void reqServer.close();
|
|
203
|
-
});
|
|
204
|
-
await reqServer.connect(transport);
|
|
205
|
-
await transport.handleRequest(req, res, parsedBody);
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const httpServer = http.createServer(async (req, res) => {
|
|
210
|
-
const url = new URL(req.url ?? '/', `http://localhost:${port}`);
|
|
211
|
-
const method = req.method ?? 'GET';
|
|
212
|
-
|
|
213
|
-
/* ── Authentication ─────────────────────────────────────────────
|
|
214
|
-
* Every endpoint except /health, /ready{{#if hasOAuth}}, and the public
|
|
215
|
-
* OAuth metadata{{/if}} requires a valid bearer token when MCP_AUTH_TOKEN
|
|
216
|
-
* is set. This is the in-container line of defense; the hosting backend
|
|
217
|
-
* also validates before proxying. */
|
|
218
|
-
const isPublicPath =
|
|
219
|
-
url.pathname === '/health' ||
|
|
220
|
-
url.pathname === '/ready'{{#if hasOAuth}} ||
|
|
221
|
-
url.pathname === '/.well-known/oauth-authorization-server'{{/if}};
|
|
222
|
-
if (!isPublicPath && !isAuthorized(req, authToken)) {
|
|
223
|
-
log('error', 'Unauthorized request rejected', { path: url.pathname });
|
|
224
|
-
res.writeHead(401, {
|
|
225
|
-
'Content-Type': 'application/json',
|
|
226
|
-
'WWW-Authenticate': 'Bearer',
|
|
227
|
-
});
|
|
228
|
-
res.end(JSON.stringify({ error: 'Unauthorized: missing or invalid bearer token' }));
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/* ── Routing-header observability (SEP-2243, additive) ─────────── */
|
|
233
|
-
const mcpMethod = req.headers['mcp-method'];
|
|
234
|
-
const mcpName = req.headers['mcp-name'];
|
|
235
|
-
if (mcpMethod || mcpName) {
|
|
236
|
-
log('info', 'mcp-meta-headers', { mcpMethod, mcpName, path: url.pathname });
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
{{#if hasOAuth}}
|
|
240
|
-
/* ── OAuth Authorization Server Metadata (RFC 8414) ─────────────
|
|
241
|
-
* Public discovery endpoint (the 2026-07-28 auth changes clarify
|
|
242
|
-
* .well-known discovery; DCR is retained, not replaced). */
|
|
243
|
-
if (url.pathname === '/.well-known/oauth-authorization-server') {
|
|
244
|
-
if (method !== 'GET') {
|
|
245
|
-
res.writeHead(405, { Allow: 'GET' });
|
|
246
|
-
res.end();
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
const authorizationUrl = config.oauth2AuthorizationUrl;
|
|
250
|
-
const tokenUrl = config.oauth2TokenUrl;
|
|
251
|
-
if (!authorizationUrl || !tokenUrl) {
|
|
252
|
-
sendJson(res, 503, { error: 'OAuth is not configured' });
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
const proto = req.headers['x-forwarded-proto'] === 'https' ? 'https' : 'http';
|
|
256
|
-
const issuer = allowedOrigin ?? `${proto}://${req.headers.host ?? 'localhost'}`;
|
|
257
|
-
sendJson(
|
|
258
|
-
res,
|
|
259
|
-
200,
|
|
260
|
-
getAuthServerMetadata(
|
|
261
|
-
{
|
|
262
|
-
clientId: config.oauth2ClientId ?? '',
|
|
263
|
-
clientSecret: config.oauth2ClientSecret,
|
|
264
|
-
authorizationUrl,
|
|
265
|
-
tokenUrl,
|
|
266
|
-
scopes: [],
|
|
267
|
-
redirectUri: config.oauth2RedirectUri ?? '',
|
|
268
|
-
},
|
|
269
|
-
issuer,
|
|
270
|
-
),
|
|
271
|
-
);
|
|
272
|
-
return;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
{{/if}}
|
|
276
|
-
{{#if hasAsyncTools}}
|
|
277
|
-
/* ── Task management REST routes (retained during the grace period) ── */
|
|
278
|
-
if (handleTaskSse(req, res, url)) return;
|
|
279
|
-
if (handleTaskRoutes(req, res, url)) return;
|
|
280
|
-
|
|
281
|
-
{{/if}}
|
|
282
|
-
if (url.pathname === '/mcp') {
|
|
283
|
-
/* Origin validation (DNS-rebinding protection per MCP spec) */
|
|
284
|
-
const origin = req.headers.origin;
|
|
285
|
-
if (allowedOrigin) {
|
|
286
|
-
if (origin && origin !== allowedOrigin) {
|
|
287
|
-
log('error', 'Origin rejected', { origin, allowedOrigin });
|
|
288
|
-
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
289
|
-
res.end(JSON.stringify({ error: 'Forbidden: invalid origin' }));
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
} else if (origin) {
|
|
293
|
-
/* No allowlist configured but Origin header present — reject cross-origin requests */
|
|
294
|
-
log('error', 'Cross-origin request rejected (ALLOWED_ORIGIN not set)', { origin });
|
|
295
|
-
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
296
|
-
res.end(JSON.stringify({ error: 'Forbidden: ALLOWED_ORIGIN not configured' }));
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/* POST carries a JSON-RPC body: peek for server/discover + tasks/* and
|
|
301
|
-
* forward the parsed body to the transport. GET/DELETE (SSE stream /
|
|
302
|
-
* session teardown) pass straight through. */
|
|
303
|
-
if (method === 'POST') {
|
|
304
|
-
const raw = await readBody(req);
|
|
305
|
-
if (raw === null) {
|
|
306
|
-
rpcError(res, null, -32600, 'Request body too large');
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
if (raw.length === 0) {
|
|
310
|
-
rpcError(res, null, -32600, 'Empty request body');
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
let parsed: unknown;
|
|
314
|
-
try {
|
|
315
|
-
parsed = JSON.parse(raw.toString('utf-8'));
|
|
316
|
-
} catch {
|
|
317
|
-
rpcError(res, null, -32700, 'Parse error');
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/* Intercept single-object JSON-RPC extension methods the SDK doesn't
|
|
322
|
-
* dispatch yet. Batches are forwarded untouched. */
|
|
323
|
-
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
324
|
-
const rpcMethod = (parsed as { method?: unknown }).method;
|
|
325
|
-
const rpcId = (parsed as { id?: unknown }).id;
|
|
326
|
-
if (rpcMethod === 'server/discover') {
|
|
327
|
-
sendJson(res, 200, buildDiscoverResult(rpcId));
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
{{#if hasAsyncTools}}
|
|
331
|
-
if (typeof rpcMethod === 'string' && rpcMethod.startsWith('tasks/')) {
|
|
332
|
-
const handled = handleTaskRpc(rpcMethod, (parsed as { params?: unknown }).params, rpcId);
|
|
333
|
-
if (handled) {
|
|
334
|
-
sendJson(res, 200, handled);
|
|
335
|
-
return;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
{{/if}}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
await dispatchToTransport(req, res, parsed);
|
|
342
|
-
return;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
await dispatchToTransport(req, res);
|
|
346
|
-
} else if (url.pathname === '/health') {
|
|
347
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
348
|
-
res.end(JSON.stringify({ status: 'ok' }));
|
|
349
|
-
} else if (url.pathname === '/ready') {
|
|
350
|
-
if (isReady) {
|
|
351
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
352
|
-
res.end(JSON.stringify({ status: 'ready' }));
|
|
353
|
-
} else {
|
|
354
|
-
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
355
|
-
res.end(JSON.stringify({ status: 'not ready' }));
|
|
356
|
-
}
|
|
357
|
-
} else {
|
|
358
|
-
res.writeHead(404);
|
|
359
|
-
res.end('Not found');
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
// Stateful: connect the shared server once before serving (readiness gates on
|
|
364
|
-
// it). Stateless: readiness gates on listen (no persistent connection).
|
|
365
|
-
if (stateful && sharedServer && sharedTransport) {
|
|
366
|
-
await sharedServer.connect(sharedTransport);
|
|
367
|
-
isReady = true;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
httpServer.listen(port, () => {
|
|
371
|
-
if (!stateful) isReady = true;
|
|
372
|
-
log('info', 'MCP server running', {
|
|
373
|
-
name: '{{serverName}}',
|
|
374
|
-
port,
|
|
375
|
-
endpoint: '/mcp',
|
|
376
|
-
mode: stateful ? 'stateful' : 'stateless',
|
|
377
|
-
});
|
|
378
|
-
});
|
|
379
|
-
|
|
380
|
-
/* ── Graceful shutdown ─────────────────────────────────────────────── */
|
|
381
|
-
|
|
382
|
-
process.on('SIGTERM', () => {
|
|
383
|
-
log('info', 'SIGTERM received, shutting down');
|
|
384
|
-
isReady = false;
|
|
385
|
-
|
|
386
|
-
httpServer.close(async () => {
|
|
387
|
-
try {
|
|
388
|
-
if (sharedServer) await sharedServer.close();
|
|
389
|
-
} catch (err) {
|
|
390
|
-
log('error', 'Error closing MCP server', { err: String(err) });
|
|
391
|
-
}
|
|
392
|
-
log('info', 'Server closed');
|
|
393
|
-
process.exit(0);
|
|
394
|
-
});
|
|
395
|
-
|
|
396
|
-
/* Force exit after 5 seconds if in-flight requests don't complete */
|
|
397
|
-
setTimeout(() => {
|
|
398
|
-
log('error', 'Shutdown timed out after 5 s, forcing exit');
|
|
399
|
-
process.exit(1);
|
|
400
|
-
}, 5000).unref();
|
|
401
|
-
});
|
|
402
|
-
} else {
|
|
403
|
-
const server = createMcpServer(config);
|
|
404
|
-
const transport = new StdioServerTransport();
|
|
405
|
-
await server.connect(transport);
|
|
406
|
-
log('info', 'MCP server running on stdio', { name: '{{serverName}}' });
|
|
407
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
-
{{#if hasStaticTools}}
|
|
4
|
-
import { registerAllTools } from './tools/index.js';
|
|
5
|
-
{{/if}}
|
|
6
|
-
{{#if hasDynamicDiscovery}}
|
|
7
|
-
import { registerDiscoveryTools } from './discovery.js';
|
|
8
|
-
{{/if}}
|
|
9
|
-
{{#if hasResources}}
|
|
10
|
-
import { registerAllResources } from './resources.js';
|
|
11
|
-
{{/if}}
|
|
12
|
-
{{#if hasPrompts}}
|
|
13
|
-
import { registerAllPrompts } from './prompts.js';
|
|
14
|
-
{{/if}}
|
|
15
|
-
import { loadConfig } from './config.js';
|
|
16
|
-
|
|
17
|
-
const config = loadConfig();
|
|
18
|
-
|
|
19
|
-
const server = new McpServer({
|
|
20
|
-
name: '{{serverName}}',
|
|
21
|
-
version: '{{serverVersion}}',
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
{{#if hasStaticTools}}
|
|
25
|
-
registerAllTools(server, config);
|
|
26
|
-
{{/if}}
|
|
27
|
-
{{#if hasDynamicDiscovery}}
|
|
28
|
-
registerDiscoveryTools(server, config);
|
|
29
|
-
{{/if}}
|
|
30
|
-
{{#if hasResources}}
|
|
31
|
-
registerAllResources(server, config);
|
|
32
|
-
{{/if}}
|
|
33
|
-
{{#if hasPrompts}}
|
|
34
|
-
registerAllPrompts(server);
|
|
35
|
-
{{/if}}
|
|
36
|
-
|
|
37
|
-
const transport = new StdioServerTransport();
|
|
38
|
-
await server.connect(transport);
|
|
39
|
-
|
|
40
|
-
console.error('{{serverName}} MCP server running on stdio');
|