memory-journal-mcp 6.1.2 → 6.2.1
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/README.md +44 -28
- package/dist/{chunk-X4SWFATC.js → chunk-BI4ZNSKA.js} +38 -24
- package/dist/{chunk-HCEWINSB.js → chunk-N6EBIDN7.js} +99 -102
- package/dist/cli.js +2 -2
- package/dist/index.js +2 -2
- package/dist/tools-WPRY5MJ6.js +2 -0
- package/package.json +10 -1
- package/skills/github-commander/SKILL.md +151 -0
- package/skills/github-commander/config/project-config.example.md +125 -0
- package/skills/github-commander/workflows/code-quality-audit.md +80 -0
- package/skills/github-commander/workflows/full-audit.md +134 -0
- package/skills/github-commander/workflows/issue-triage.md +239 -0
- package/skills/github-commander/workflows/milestone-sprint.md +81 -0
- package/skills/github-commander/workflows/perf-audit.md +142 -0
- package/skills/github-commander/workflows/pr-review.md +123 -0
- package/skills/github-commander/workflows/security-audit.md +170 -0
- package/skills/github-commander/workflows/update-deps.md +109 -0
- package/.dockerignore +0 -139
- package/.gitattributes +0 -20
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -95
- package/.github/ISSUE_TEMPLATE/config.yml +0 -11
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -110
- package/.github/ISSUE_TEMPLATE/question.md +0 -78
- package/.github/aw/actions-lock.json +0 -14
- package/.github/copilot-instructions.md +0 -122
- package/.github/dependabot.yml +0 -93
- package/.github/pull_request_template.md +0 -135
- package/.github/workflows/README.md +0 -133
- package/.github/workflows/agentics-maintenance.yml +0 -141
- package/.github/workflows/auto-release.yml +0 -68
- package/.github/workflows/ci-health-monitor.lock.yml +0 -1121
- package/.github/workflows/ci-health-monitor.md +0 -87
- package/.github/workflows/codeql.yml +0 -41
- package/.github/workflows/dependabot-auto-merge.yml +0 -42
- package/.github/workflows/dependency-maintenance.lock.yml +0 -1182
- package/.github/workflows/dependency-maintenance.md +0 -147
- package/.github/workflows/docker-publish.yml +0 -254
- package/.github/workflows/docs-drift-detector.lock.yml +0 -1142
- package/.github/workflows/docs-drift-detector.md +0 -115
- package/.github/workflows/lint-and-test.yml +0 -60
- package/.github/workflows/publish-npm.yml +0 -85
- package/.github/workflows/secrets-scanning.yml +0 -32
- package/.github/workflows/security-update.yml +0 -127
- package/.gitleaks.toml +0 -9
- package/.prettierignore +0 -21
- package/.prettierrc +0 -33
- package/.scout-ignore +0 -12
- package/.trivyignore +0 -21
- package/CHANGELOG.md +0 -1814
- package/CODE_OF_CONDUCT.md +0 -133
- package/CONTRIBUTING.md +0 -263
- package/DOCKER_README.md +0 -331
- package/Dockerfile +0 -128
- package/SECURITY.md +0 -227
- package/UNRELEASED.md +0 -1
- package/dist/tools-T4U5A3X4.js +0 -2
- package/docker-compose.yml +0 -71
- package/docs/README.md +0 -18
- package/docs/agentic-journal-synergy.md +0 -175
- package/docs/copilot-setup.md +0 -72
- package/eslint.config.js +0 -110
- package/mcp-config-example.json +0 -21
- package/playwright.config.ts +0 -35
- package/releases/v2.1.0.md +0 -220
- package/releases/v2.2.0.md +0 -168
- package/releases/v3.0.0.md +0 -237
- package/releases/v3.1.0.md +0 -104
- package/releases/v3.1.1.md +0 -42
- package/releases/v3.1.2.md +0 -40
- package/releases/v3.1.3.md +0 -64
- package/releases/v3.1.4.md +0 -32
- package/releases/v3.1.5.md +0 -44
- package/releases/v4.0.0.md +0 -71
- package/releases/v4.1.0.md +0 -88
- package/releases/v4.2.0.md +0 -90
- package/releases/v4.3.0.md +0 -92
- package/releases/v4.3.1.md +0 -69
- package/releases/v4.4.0.md +0 -120
- package/releases/v4.4.1.md +0 -33
- package/releases/v4.4.2.md +0 -31
- package/releases/v4.5.0.md +0 -116
- package/releases/v5.0.0.md +0 -105
- package/releases/v5.0.1.md +0 -25
- package/releases/v5.1.0.md +0 -83
- package/releases/v5.1.1.md +0 -10
- package/releases/v6.0.0.md +0 -48
- package/releases/v6.0.1.md +0 -36
- package/releases/v6.1.0.md +0 -68
- package/releases/v6.1.1.md +0 -30
- package/releases/v6.1.2.md +0 -23
- package/scripts/generate-server-instructions.ts +0 -306
- package/scripts/server-instructions-function-body.ts +0 -107
- package/scripts/server-instructions-gotchas.ts +0 -45
- package/server.json +0 -42
- package/social-preview.png +0 -0
- package/src/auth/auth-context.ts +0 -78
- package/src/auth/authorization-server-discovery.ts +0 -263
- package/src/auth/errors.ts +0 -215
- package/src/auth/index.ts +0 -58
- package/src/auth/middleware.ts +0 -392
- package/src/auth/oauth-resource-server.ts +0 -170
- package/src/auth/scope-map.ts +0 -46
- package/src/auth/scopes.ts +0 -256
- package/src/auth/token-validator.ts +0 -293
- package/src/auth/transport-agnostic.ts +0 -164
- package/src/auth/types.ts +0 -372
- package/src/cli.ts +0 -279
- package/src/codemode/api-constants.ts +0 -263
- package/src/codemode/api.ts +0 -302
- package/src/codemode/auto-return.ts +0 -65
- package/src/codemode/index.ts +0 -47
- package/src/codemode/sandbox-factory.ts +0 -144
- package/src/codemode/sandbox.ts +0 -220
- package/src/codemode/security.ts +0 -155
- package/src/codemode/types.ts +0 -228
- package/src/codemode/worker-sandbox.ts +0 -277
- package/src/codemode/worker-script.ts +0 -239
- package/src/constants/icons.ts +0 -183
- package/src/constants/server-instructions.md +0 -166
- package/src/constants/server-instructions.ts +0 -514
- package/src/database/adapter-factory.ts +0 -16
- package/src/database/core/entry-columns.ts +0 -10
- package/src/database/core/interfaces.ts +0 -188
- package/src/database/core/schema.ts +0 -152
- package/src/database/sqlite-adapter/backup.ts +0 -167
- package/src/database/sqlite-adapter/entries/crud.ts +0 -233
- package/src/database/sqlite-adapter/entries/importance.ts +0 -76
- package/src/database/sqlite-adapter/entries/index.ts +0 -142
- package/src/database/sqlite-adapter/entries/search.ts +0 -294
- package/src/database/sqlite-adapter/entries/shared.ts +0 -102
- package/src/database/sqlite-adapter/entries/statistics.ts +0 -162
- package/src/database/sqlite-adapter/index.ts +0 -265
- package/src/database/sqlite-adapter/native-connection.ts +0 -301
- package/src/database/sqlite-adapter/relationships.ts +0 -70
- package/src/database/sqlite-adapter/tags.ts +0 -182
- package/src/filtering/tool-filter.ts +0 -312
- package/src/github/github-integration/client.ts +0 -114
- package/src/github/github-integration/index.ts +0 -297
- package/src/github/github-integration/insights.ts +0 -155
- package/src/github/github-integration/issues.ts +0 -213
- package/src/github/github-integration/milestones.ts +0 -262
- package/src/github/github-integration/projects.ts +0 -414
- package/src/github/github-integration/pull-requests.ts +0 -235
- package/src/github/github-integration/repository.ts +0 -110
- package/src/github/github-integration/types.ts +0 -43
- package/src/handlers/prompts/github.ts +0 -210
- package/src/handlers/prompts/index.ts +0 -97
- package/src/handlers/prompts/workflow.ts +0 -361
- package/src/handlers/resources/core/briefing/context-section.ts +0 -182
- package/src/handlers/resources/core/briefing/github-section.ts +0 -354
- package/src/handlers/resources/core/briefing/index.ts +0 -106
- package/src/handlers/resources/core/briefing/user-message.ts +0 -114
- package/src/handlers/resources/core/health.ts +0 -75
- package/src/handlers/resources/core/index.ts +0 -31
- package/src/handlers/resources/core/instructions.ts +0 -45
- package/src/handlers/resources/core/utilities.ts +0 -310
- package/src/handlers/resources/github.ts +0 -340
- package/src/handlers/resources/graph.ts +0 -218
- package/src/handlers/resources/help.ts +0 -410
- package/src/handlers/resources/index.ts +0 -143
- package/src/handlers/resources/shared.ts +0 -219
- package/src/handlers/resources/team.ts +0 -134
- package/src/handlers/resources/templates.ts +0 -334
- package/src/handlers/tools/admin.ts +0 -351
- package/src/handlers/tools/analytics.ts +0 -346
- package/src/handlers/tools/backup.ts +0 -272
- package/src/handlers/tools/codemode.ts +0 -188
- package/src/handlers/tools/core.ts +0 -359
- package/src/handlers/tools/error-fields-mixin.ts +0 -10
- package/src/handlers/tools/export.ts +0 -150
- package/src/handlers/tools/github/copilot-tools.ts +0 -72
- package/src/handlers/tools/github/helpers.ts +0 -125
- package/src/handlers/tools/github/insights-tools.ts +0 -112
- package/src/handlers/tools/github/issue-tools.ts +0 -442
- package/src/handlers/tools/github/kanban-tools.ts +0 -153
- package/src/handlers/tools/github/milestone-tools.ts +0 -371
- package/src/handlers/tools/github/mutation-tools.ts +0 -17
- package/src/handlers/tools/github/read-tools.ts +0 -302
- package/src/handlers/tools/github/schemas.ts +0 -435
- package/src/handlers/tools/github.ts +0 -39
- package/src/handlers/tools/index.ts +0 -255
- package/src/handlers/tools/relationships.ts +0 -390
- package/src/handlers/tools/schemas.ts +0 -165
- package/src/handlers/tools/search.ts +0 -448
- package/src/handlers/tools/team/admin-tools.ts +0 -164
- package/src/handlers/tools/team/analytics-tools.ts +0 -233
- package/src/handlers/tools/team/backup-tools.ts +0 -83
- package/src/handlers/tools/team/core-tools.ts +0 -197
- package/src/handlers/tools/team/export-tools.ts +0 -130
- package/src/handlers/tools/team/helpers.ts +0 -66
- package/src/handlers/tools/team/index.ts +0 -45
- package/src/handlers/tools/team/relationship-tools.ts +0 -219
- package/src/handlers/tools/team/schemas.ts +0 -558
- package/src/handlers/tools/team/search-tools.ts +0 -145
- package/src/handlers/tools/team/vector-tools.ts +0 -261
- package/src/index.ts +0 -57
- package/src/server/mcp-server.ts +0 -446
- package/src/server/registration.ts +0 -141
- package/src/server/scheduler.ts +0 -283
- package/src/transports/http/handlers.ts +0 -78
- package/src/transports/http/index.ts +0 -8
- package/src/transports/http/security.ts +0 -147
- package/src/transports/http/server/index.ts +0 -397
- package/src/transports/http/server/legacy-sse.ts +0 -87
- package/src/transports/http/server/stateful.ts +0 -222
- package/src/transports/http/server/stateless.ts +0 -42
- package/src/transports/http/types.ts +0 -132
- package/src/types/entities.ts +0 -145
- package/src/types/error-types.ts +0 -92
- package/src/types/errors.ts +0 -200
- package/src/types/filtering.ts +0 -55
- package/src/types/github.ts +0 -216
- package/src/types/index.ts +0 -348
- package/src/utils/error-helpers.ts +0 -78
- package/src/utils/errors/error-response-fields.ts +0 -29
- package/src/utils/errors/suggestions.ts +0 -94
- package/src/utils/github-helpers.ts +0 -33
- package/src/utils/logger.ts +0 -107
- package/src/utils/mcp-logger.ts +0 -155
- package/src/utils/progress-utils.ts +0 -100
- package/src/utils/query-helpers.ts +0 -78
- package/src/utils/resource-annotations.ts +0 -75
- package/src/utils/security-utils.ts +0 -198
- package/src/utils/vector-index-helpers.ts +0 -24
- package/src/vector/vector-search-manager.ts +0 -409
- package/src/version.ts +0 -15
- package/test-server/README.md +0 -193
- package/test-server/code-map.md +0 -399
- package/test-server/test-agent-experience.md +0 -213
- package/test-server/test-filter-instructions.mjs +0 -295
- package/test-server/test-instruction-levels.mjs +0 -102
- package/test-server/test-preflight.md +0 -55
- package/test-server/test-prompts.mjs +0 -185
- package/test-server/test-scheduler.mjs +0 -174
- package/test-server/test-tool-annotations.mjs +0 -115
- package/test-server/test-tools-codemode.md +0 -632
- package/test-server/test-tools-codemode2.md +0 -1218
- package/test-server/test-tools-team.md +0 -215
- package/test-server/test-tools.md +0 -429
- package/test-server/test-tools2.md +0 -361
- package/test-server/test-tools3.md +0 -396
- package/test-server/tool-reference.md +0 -231
- package/tests/README.md +0 -54
- package/tests/auth/auth-context.test.ts +0 -162
- package/tests/auth/authorization-server-discovery.test.ts +0 -265
- package/tests/auth/errors.test.ts +0 -170
- package/tests/auth/middleware.test.ts +0 -585
- package/tests/auth/oauth-resource-server.test.ts +0 -173
- package/tests/auth/scope-map.test.ts +0 -66
- package/tests/auth/scopes.test.ts +0 -347
- package/tests/auth/token-validator.test.ts +0 -271
- package/tests/codemode/api.test.ts +0 -396
- package/tests/codemode/auto-return.test.ts +0 -167
- package/tests/codemode/codemode-tool-handlers.test.ts +0 -197
- package/tests/codemode/sandbox-factory.test.ts +0 -152
- package/tests/codemode/sandbox.test.ts +0 -190
- package/tests/codemode/security.test.ts +0 -242
- package/tests/codemode/worker-sandbox.test.ts +0 -106
- package/tests/constants/icons.test.ts +0 -101
- package/tests/constants/server-instructions.test.ts +0 -514
- package/tests/database/crud-workflow-branches.test.ts +0 -418
- package/tests/database/database-branches.test.ts +0 -132
- package/tests/database/entries-auth-branches.test.ts +0 -390
- package/tests/database/native-connection.test.ts +0 -249
- package/tests/database/shared-helpers.test.ts +0 -103
- package/tests/database/sqlite-adapter.bench.ts +0 -63
- package/tests/database/sqlite-adapter.test.ts +0 -690
- package/tests/database/tags.test.ts +0 -134
- package/tests/e2e/README.md +0 -39
- package/tests/e2e/auth.spec.ts +0 -106
- package/tests/e2e/codemode-abuse.spec.ts +0 -75
- package/tests/e2e/health.spec.ts +0 -63
- package/tests/e2e/helpers.ts +0 -139
- package/tests/e2e/oauth-discovery.spec.ts +0 -102
- package/tests/e2e/oauth-scopes.spec.ts +0 -222
- package/tests/e2e/payloads-admin.spec.ts +0 -76
- package/tests/e2e/payloads-analytics.spec.ts +0 -37
- package/tests/e2e/payloads-backup-restore.spec.ts +0 -102
- package/tests/e2e/payloads-backup.spec.ts +0 -44
- package/tests/e2e/payloads-codemode-api.spec.ts +0 -131
- package/tests/e2e/payloads-codemode-readonly.spec.ts +0 -116
- package/tests/e2e/payloads-codemode.spec.ts +0 -116
- package/tests/e2e/payloads-core.spec.ts +0 -82
- package/tests/e2e/payloads-error-contracts.spec.ts +0 -159
- package/tests/e2e/payloads-export.spec.ts +0 -46
- package/tests/e2e/payloads-github-degradation.spec.ts +0 -73
- package/tests/e2e/payloads-github.spec.ts +0 -176
- package/tests/e2e/payloads-relationships.spec.ts +0 -56
- package/tests/e2e/payloads-search.spec.ts +0 -64
- package/tests/e2e/payloads-team-happy.spec.ts +0 -231
- package/tests/e2e/payloads-team.spec.ts +0 -174
- package/tests/e2e/prompts-expanded.spec.ts +0 -137
- package/tests/e2e/prompts.spec.ts +0 -62
- package/tests/e2e/protocols.spec.ts +0 -134
- package/tests/e2e/rate-limiting.spec.ts +0 -291
- package/tests/e2e/resources-briefing-env.spec.ts +0 -106
- package/tests/e2e/resources-complete.spec.ts +0 -180
- package/tests/e2e/resources-expanded.spec.ts +0 -83
- package/tests/e2e/resources-instructions-levels.spec.ts +0 -145
- package/tests/e2e/resources-templates.spec.ts +0 -123
- package/tests/e2e/resources.spec.ts +0 -103
- package/tests/e2e/scheduler.spec.ts +0 -79
- package/tests/e2e/security.spec.ts +0 -112
- package/tests/e2e/session-advanced.spec.ts +0 -152
- package/tests/e2e/sessions.spec.ts +0 -95
- package/tests/e2e/stateless.spec.ts +0 -79
- package/tests/e2e/streaming.spec.ts +0 -176
- package/tests/e2e/tool-filtering-presets.spec.ts +0 -192
- package/tests/e2e/tool-filtering.spec.ts +0 -77
- package/tests/e2e/tools.spec.ts +0 -111
- package/tests/filtering/tool-filter.test.ts +0 -314
- package/tests/github/client-issues-errors.test.ts +0 -433
- package/tests/github/github-integration-branches.test.ts +0 -490
- package/tests/github/github-integration.test.ts +0 -1015
- package/tests/github/github-managers-branches.test.ts +0 -907
- package/tests/github/pull-requests.test.ts +0 -334
- package/tests/handlers/analytics-branches.test.ts +0 -222
- package/tests/handlers/backup-branches.test.ts +0 -270
- package/tests/handlers/briefing-context-section.test.ts +0 -388
- package/tests/handlers/briefing-github-section.test.ts +0 -392
- package/tests/handlers/briefing-user-message.test.ts +0 -405
- package/tests/handlers/codemode-tools.test.ts +0 -85
- package/tests/handlers/copilot-tools.test.ts +0 -126
- package/tests/handlers/error-path-coverage.test.ts +0 -324
- package/tests/handlers/export-tools.test.ts +0 -203
- package/tests/handlers/github-resource-handlers.test.ts +0 -929
- package/tests/handlers/github-tool-handlers.test.ts +0 -1452
- package/tests/handlers/handler-error-branches.test.ts +0 -346
- package/tests/handlers/help-resource.test.ts +0 -92
- package/tests/handlers/prompt-handler-coverage.test.ts +0 -108
- package/tests/handlers/prompt-handlers.test.ts +0 -131
- package/tests/handlers/resource-handler-coverage.test.ts +0 -281
- package/tests/handlers/resource-handlers.test.ts +0 -357
- package/tests/handlers/resource-prompt-branches.test.ts +0 -495
- package/tests/handlers/search-tool-handlers.test.ts +0 -379
- package/tests/handlers/targeted-gap-closure.test.ts +0 -387
- package/tests/handlers/team-admin.test.ts +0 -291
- package/tests/handlers/team-analytics.test.ts +0 -220
- package/tests/handlers/team-core.test.ts +0 -148
- package/tests/handlers/team-data.test.ts +0 -198
- package/tests/handlers/team-relationships.test.ts +0 -271
- package/tests/handlers/team-resource-handlers.test.ts +0 -161
- package/tests/handlers/team-search.test.ts +0 -134
- package/tests/handlers/team-tool-handlers.test.ts +0 -301
- package/tests/handlers/team-vector.test.ts +0 -213
- package/tests/handlers/template-github-branches.test.ts +0 -676
- package/tests/handlers/tool-annotations.test.ts +0 -90
- package/tests/handlers/tool-handler-coverage.test.ts +0 -514
- package/tests/handlers/tool-handlers.test.ts +0 -510
- package/tests/handlers/tool-output-schemas.test.ts +0 -116
- package/tests/handlers/vector-tool-handlers.test.ts +0 -238
- package/tests/security/sql-injection.test.ts +0 -284
- package/tests/server/mcp-server.bench.ts +0 -55
- package/tests/server/mcp-server.test.ts +0 -1326
- package/tests/server/scheduler.test.ts +0 -400
- package/tests/transports/http-legacy-sse.test.ts +0 -275
- package/tests/transports/http-security.test.ts +0 -322
- package/tests/transports/http-stateful.test.ts +0 -487
- package/tests/transports/http-transport-server.test.ts +0 -301
- package/tests/transports/http-transport.test.ts +0 -771
- package/tests/utils/github-helpers.test.ts +0 -58
- package/tests/utils/logger.test.ts +0 -180
- package/tests/utils/mcp-logger.test.ts +0 -211
- package/tests/utils/progress-utils.test.ts +0 -156
- package/tests/utils/query-helpers.test.ts +0 -80
- package/tests/utils/security-utils.test.ts +0 -82
- package/tests/vector/vector-search-branches.test.ts +0 -111
- package/tests/vector/vector-search-manager.test.ts +0 -375
- package/tests/vector/vector-search.bench.ts +0 -48
- package/tsconfig.json +0 -42
- package/tsup.config.ts +0 -19
- package/vitest.config.ts +0 -25
|
@@ -1,397 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* memory-journal-mcp — HTTP Transport Server
|
|
3
|
-
*
|
|
4
|
-
* Dual-protocol HTTP transport:
|
|
5
|
-
* - `/mcp` — Streamable HTTP transport (MCP 2025-03-26)
|
|
6
|
-
* - `/sse` + `/messages` — Legacy SSE transport (MCP 2024-11-05)
|
|
7
|
-
*
|
|
8
|
-
* Modes:
|
|
9
|
-
* - Stateful (default): Multi-session management with SSE streaming
|
|
10
|
-
* - Stateless (opt-in): Lightweight serverless-compatible mode
|
|
11
|
-
*
|
|
12
|
-
* Security utilities and handlers in ./security.ts and ./handlers.ts.
|
|
13
|
-
* Config types and constants in ./types.ts.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import type { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'
|
|
17
|
-
import type { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'
|
|
18
|
-
|
|
19
|
-
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
20
|
-
import express from 'express'
|
|
21
|
-
import type { Express, Request, Response, RequestHandler } from 'express'
|
|
22
|
-
import { logger } from '../../../utils/logger.js'
|
|
23
|
-
import type { Scheduler } from '../../../server/scheduler.js'
|
|
24
|
-
import type { HttpTransportConfig, RateLimitEntry } from '../types.js'
|
|
25
|
-
import {
|
|
26
|
-
DEFAULT_MAX_BODY_BYTES,
|
|
27
|
-
HTTP_REQUEST_TIMEOUT_MS,
|
|
28
|
-
HTTP_KEEP_ALIVE_TIMEOUT_MS,
|
|
29
|
-
HTTP_HEADERS_TIMEOUT_MS,
|
|
30
|
-
} from '../types.js'
|
|
31
|
-
import { setSecurityHeaders, setCorsHeaders, checkRateLimit } from '../security.js'
|
|
32
|
-
import { handleHealthCheck, handleRootInfo, createAuthMiddleware } from '../handlers.js'
|
|
33
|
-
import {
|
|
34
|
-
createTokenValidator,
|
|
35
|
-
createOAuthResourceServer,
|
|
36
|
-
createAuthMiddleware as createOAuthMiddleware,
|
|
37
|
-
oauthErrorHandler,
|
|
38
|
-
InsufficientScopeError,
|
|
39
|
-
SUPPORTED_SCOPES,
|
|
40
|
-
} from '../../../auth/index.js'
|
|
41
|
-
import { getRequiredScope } from '../../../auth/scope-map.js'
|
|
42
|
-
import { hasScope } from '../../../auth/scopes.js'
|
|
43
|
-
import {
|
|
44
|
-
hostHeaderValidation,
|
|
45
|
-
localhostHostValidation,
|
|
46
|
-
} from '@modelcontextprotocol/sdk/server/middleware/hostHeaderValidation.js'
|
|
47
|
-
import { setupStateless } from './stateless.js'
|
|
48
|
-
import { setupStateful } from './stateful.js'
|
|
49
|
-
import { setupLegacySSE } from './legacy-sse.js'
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* HTTP Transport for Memory Journal MCP Server
|
|
53
|
-
*
|
|
54
|
-
* Supports two transport protocols simultaneously:
|
|
55
|
-
* 1. Streamable HTTP (MCP 2025-03-26) via `/mcp` — preferred for modern clients
|
|
56
|
-
* 2. Legacy SSE (MCP 2024-11-05) via `/sse` + `/messages` — backward compatibility
|
|
57
|
-
*/
|
|
58
|
-
export class HttpTransport {
|
|
59
|
-
private readonly app: Express
|
|
60
|
-
private readonly config: HttpTransportConfig
|
|
61
|
-
public readonly transports = new Map<string, StreamableHTTPServerTransport>()
|
|
62
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated -- backward compat for MCP 2024-11-05 clients
|
|
63
|
-
public readonly sseTransports = new Map<string, SSEServerTransport>()
|
|
64
|
-
public readonly sessionLastActivity = new Map<string, number>()
|
|
65
|
-
/** Tracks whether server.connect() has been called (close-before-reconnect pattern) */
|
|
66
|
-
public serverConnected = false
|
|
67
|
-
private httpServer: ReturnType<Express['listen']> | null = null
|
|
68
|
-
private sessionSweepTimer: ReturnType<typeof setInterval> | null = null
|
|
69
|
-
|
|
70
|
-
// Rate limiting state
|
|
71
|
-
private readonly rateLimitMap = new Map<string, RateLimitEntry>()
|
|
72
|
-
private rateLimitCleanupTimer: ReturnType<typeof setInterval> | null = null
|
|
73
|
-
|
|
74
|
-
constructor(config: HttpTransportConfig) {
|
|
75
|
-
this.config = {
|
|
76
|
-
...config,
|
|
77
|
-
enableRateLimit: config.enableRateLimit ?? true,
|
|
78
|
-
}
|
|
79
|
-
this.app = express()
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Initialize and start the HTTP transport
|
|
84
|
-
*/
|
|
85
|
-
async start(server: McpServer, scheduler: Scheduler | null): Promise<void> {
|
|
86
|
-
const { port, host, authToken, corsOrigins } = this.config
|
|
87
|
-
|
|
88
|
-
if (!corsOrigins || corsOrigins.includes('*')) {
|
|
89
|
-
logger.warning(
|
|
90
|
-
'CORS origin is set to "*" (all origins). ' +
|
|
91
|
-
'Set --cors-origin or MCP_CORS_ORIGIN for production deployments.',
|
|
92
|
-
{ module: 'HTTP' }
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (!authToken) {
|
|
97
|
-
logger.warning(
|
|
98
|
-
'No authentication configured for HTTP transport. ' +
|
|
99
|
-
'Set --auth-token or MCP_AUTH_TOKEN for production deployments.',
|
|
100
|
-
{ module: 'HTTP' }
|
|
101
|
-
)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// DNS rebinding protection (CVE-2025-66414)
|
|
105
|
-
// Applied when no auth is configured — defense-in-depth for local HTTP servers.
|
|
106
|
-
// When OAuth or bearer auth is active, auth already prevents unauthorized access.
|
|
107
|
-
if (!this.config.oauthEnabled && !authToken) {
|
|
108
|
-
const isLocalhost = host === 'localhost' || host === '127.0.0.1' || host === '::1'
|
|
109
|
-
this.app.use(
|
|
110
|
-
isLocalhost
|
|
111
|
-
? localhostHostValidation()
|
|
112
|
-
: hostHeaderValidation([host, 'localhost', '127.0.0.1', '[::1]'])
|
|
113
|
-
)
|
|
114
|
-
logger.info('DNS rebinding protection enabled (host header validation)', {
|
|
115
|
-
module: 'HTTP',
|
|
116
|
-
allowedHosts: isLocalhost ? ['localhost', '127.0.0.1', '[::1]'] : [host],
|
|
117
|
-
})
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Security headers middleware
|
|
121
|
-
this.app.use((req: Request, res: Response, next: () => void) => {
|
|
122
|
-
setSecurityHeaders(res, this.config)
|
|
123
|
-
setCorsHeaders(req, res, this.config)
|
|
124
|
-
next()
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
// Handle OPTIONS preflight
|
|
128
|
-
this.app.use((req: Request, res: Response, next: () => void) => {
|
|
129
|
-
if (req.method === 'OPTIONS') {
|
|
130
|
-
res.status(204).end()
|
|
131
|
-
return
|
|
132
|
-
}
|
|
133
|
-
next()
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
// JSON body parser with size limit (DoS prevention)
|
|
137
|
-
const maxBody = this.config.maxBodySize ?? DEFAULT_MAX_BODY_BYTES
|
|
138
|
-
this.app.use(express.json({ limit: maxBody }) as RequestHandler)
|
|
139
|
-
|
|
140
|
-
// Built-in rate limiting (replaces express-rate-limit)
|
|
141
|
-
if (this.config.enableRateLimit !== false) {
|
|
142
|
-
this.app.use((req: Request, res: Response, next: () => void) => {
|
|
143
|
-
// Health check bypasses rate limiting
|
|
144
|
-
if (req.path === '/health') {
|
|
145
|
-
next()
|
|
146
|
-
return
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const result = checkRateLimit(req, this.config, this.rateLimitMap)
|
|
150
|
-
if (!result.allowed) {
|
|
151
|
-
if (result.retryAfterSeconds !== undefined) {
|
|
152
|
-
res.setHeader('Retry-After', String(result.retryAfterSeconds))
|
|
153
|
-
}
|
|
154
|
-
res.status(429).json({
|
|
155
|
-
error: 'Too Many Requests',
|
|
156
|
-
retryAfter: result.retryAfterSeconds,
|
|
157
|
-
})
|
|
158
|
-
return
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
next()
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
// Periodic cleanup of expired entries
|
|
165
|
-
this.rateLimitCleanupTimer = setInterval(() => {
|
|
166
|
-
const now = Date.now()
|
|
167
|
-
for (const [ip, entry] of this.rateLimitMap) {
|
|
168
|
-
if (now > entry.resetTime) {
|
|
169
|
-
this.rateLimitMap.delete(ip)
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}, 60_000)
|
|
173
|
-
// Don't block process exit
|
|
174
|
-
this.rateLimitCleanupTimer.unref()
|
|
175
|
-
|
|
176
|
-
logger.info('Rate limiting enabled: 100 requests/minute per IP', {
|
|
177
|
-
module: 'HTTP',
|
|
178
|
-
})
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Authentication middleware
|
|
182
|
-
if (this.config.oauthEnabled && this.config.oauthIssuer && this.config.oauthAudience) {
|
|
183
|
-
// OAuth 2.1 authentication
|
|
184
|
-
const jwksUri =
|
|
185
|
-
this.config.oauthJwksUri ?? `${this.config.oauthIssuer}/.well-known/jwks.json`
|
|
186
|
-
|
|
187
|
-
const tokenValidator = createTokenValidator({
|
|
188
|
-
jwksUri,
|
|
189
|
-
issuer: this.config.oauthIssuer,
|
|
190
|
-
audience: this.config.oauthAudience,
|
|
191
|
-
clockTolerance: this.config.oauthClockTolerance ?? 60,
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
const resourceServer = createOAuthResourceServer({
|
|
195
|
-
resource: `http://${host}:${String(port)}`,
|
|
196
|
-
authorizationServers: [this.config.oauthIssuer],
|
|
197
|
-
scopesSupported: [...SUPPORTED_SCOPES],
|
|
198
|
-
})
|
|
199
|
-
|
|
200
|
-
// Register RFC 9728 metadata endpoint
|
|
201
|
-
this.app.get(resourceServer.getWellKnownPath(), resourceServer.getMetadataHandler())
|
|
202
|
-
|
|
203
|
-
// Apply OAuth middleware
|
|
204
|
-
this.app.use(
|
|
205
|
-
createOAuthMiddleware({
|
|
206
|
-
tokenValidator,
|
|
207
|
-
resourceServer,
|
|
208
|
-
publicPaths: ['/health', '/', '/.well-known/*'],
|
|
209
|
-
})
|
|
210
|
-
)
|
|
211
|
-
|
|
212
|
-
// OAuth error handler
|
|
213
|
-
this.app.use(oauthErrorHandler)
|
|
214
|
-
|
|
215
|
-
// Per-tool scope enforcement for tools/call requests
|
|
216
|
-
// Applied after auth middleware so req.auth is already populated.
|
|
217
|
-
this.app.use((req: Request, res: Response, next: () => void): void => {
|
|
218
|
-
interface JsonRpcBody {
|
|
219
|
-
method?: string
|
|
220
|
-
params?: { name?: string }
|
|
221
|
-
}
|
|
222
|
-
const body = req.body as JsonRpcBody | null | undefined
|
|
223
|
-
if (req.method !== 'POST' || body?.method !== 'tools/call') {
|
|
224
|
-
next()
|
|
225
|
-
return
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const toolName = body.params?.name
|
|
229
|
-
if (!toolName) {
|
|
230
|
-
next()
|
|
231
|
-
return
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const auth = req.auth
|
|
235
|
-
if (!auth) {
|
|
236
|
-
// Auth middleware should have rejected already; defensive guard
|
|
237
|
-
res.status(401).json({
|
|
238
|
-
error: 'unauthorized',
|
|
239
|
-
error_description: 'Authentication required',
|
|
240
|
-
})
|
|
241
|
-
return
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const requiredScope = getRequiredScope(toolName)
|
|
245
|
-
const granted = hasScope(auth.scopes, requiredScope)
|
|
246
|
-
|
|
247
|
-
if (!granted) {
|
|
248
|
-
const err = new InsufficientScopeError(`Tool access: ${toolName}`, auth.scopes)
|
|
249
|
-
logger.warning(`Insufficient scope for tool: ${toolName}`, {
|
|
250
|
-
module: 'AUTH',
|
|
251
|
-
operation: 'scope-check',
|
|
252
|
-
entityId: toolName,
|
|
253
|
-
})
|
|
254
|
-
res.status(err.httpStatus)
|
|
255
|
-
if (err.wwwAuthenticate) {
|
|
256
|
-
res.setHeader('WWW-Authenticate', err.wwwAuthenticate)
|
|
257
|
-
}
|
|
258
|
-
res.json({
|
|
259
|
-
error: 'insufficient_scope',
|
|
260
|
-
error_description: `Access to tool '${toolName}' denied`,
|
|
261
|
-
tool: toolName,
|
|
262
|
-
})
|
|
263
|
-
return
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
next()
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
logger.info('OAuth 2.1 authentication enabled', {
|
|
270
|
-
module: 'HTTP',
|
|
271
|
-
issuer: this.config.oauthIssuer,
|
|
272
|
-
audience: this.config.oauthAudience,
|
|
273
|
-
})
|
|
274
|
-
} else if (authToken) {
|
|
275
|
-
// Simple bearer token authentication (non-OAuth)
|
|
276
|
-
this.app.use(createAuthMiddleware(authToken))
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Health check endpoint
|
|
280
|
-
this.app.get('/health', handleHealthCheck)
|
|
281
|
-
|
|
282
|
-
// Root info endpoint
|
|
283
|
-
this.app.get('/', handleRootInfo)
|
|
284
|
-
|
|
285
|
-
// Set up MCP endpoints based on mode
|
|
286
|
-
if (this.config.stateless) {
|
|
287
|
-
await setupStateless(this.app, server)
|
|
288
|
-
} else {
|
|
289
|
-
this.sessionSweepTimer = setupStateful(this, this.app, server)
|
|
290
|
-
setupLegacySSE(this, this.app, server)
|
|
291
|
-
}
|
|
292
|
-
// 404 handler — must be after all routes
|
|
293
|
-
this.app.use((_req: Request, res: Response): void => {
|
|
294
|
-
res.status(404).json({ error: 'Not found' })
|
|
295
|
-
})
|
|
296
|
-
|
|
297
|
-
// Start HTTP server
|
|
298
|
-
this.httpServer = this.app.listen(port, host, () => {
|
|
299
|
-
// Set HTTP server timeouts to prevent slowloris-style DoS attacks
|
|
300
|
-
if (this.httpServer) {
|
|
301
|
-
this.httpServer.setTimeout(HTTP_REQUEST_TIMEOUT_MS)
|
|
302
|
-
this.httpServer.keepAliveTimeout = HTTP_KEEP_ALIVE_TIMEOUT_MS
|
|
303
|
-
this.httpServer.headersTimeout = HTTP_HEADERS_TIMEOUT_MS
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
logger.info(
|
|
307
|
-
`MCP server started on HTTP (${this.config.stateless ? 'stateless' : 'stateful'})`,
|
|
308
|
-
{
|
|
309
|
-
module: 'HTTP',
|
|
310
|
-
port,
|
|
311
|
-
host,
|
|
312
|
-
endpoint: `http://${host}:${String(port)}/mcp`,
|
|
313
|
-
}
|
|
314
|
-
)
|
|
315
|
-
})
|
|
316
|
-
|
|
317
|
-
// Start scheduler after HTTP server is listening
|
|
318
|
-
scheduler?.start()
|
|
319
|
-
|
|
320
|
-
this.httpServer.on('close', () => {
|
|
321
|
-
logger.info('HTTP server closed', { module: 'HTTP' })
|
|
322
|
-
})
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* Graceful shutdown
|
|
327
|
-
*/
|
|
328
|
-
async stop(scheduler: Scheduler | null): Promise<void> {
|
|
329
|
-
logger.info('Shutting down HTTP server...', { module: 'HTTP' })
|
|
330
|
-
|
|
331
|
-
scheduler?.stop()
|
|
332
|
-
|
|
333
|
-
// Stop rate limit cleanup timer
|
|
334
|
-
if (this.rateLimitCleanupTimer) {
|
|
335
|
-
clearInterval(this.rateLimitCleanupTimer)
|
|
336
|
-
this.rateLimitCleanupTimer = null
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
// Close all Streamable HTTP transports
|
|
340
|
-
for (const [sessionId, transport] of this.transports) {
|
|
341
|
-
try {
|
|
342
|
-
logger.debug('Closing Streamable HTTP transport', {
|
|
343
|
-
module: 'HTTP',
|
|
344
|
-
sessionId,
|
|
345
|
-
})
|
|
346
|
-
await transport.close()
|
|
347
|
-
} catch (error) {
|
|
348
|
-
logger.error('Error closing transport', {
|
|
349
|
-
module: 'HTTP',
|
|
350
|
-
sessionId,
|
|
351
|
-
error: error instanceof Error ? error.message : String(error),
|
|
352
|
-
})
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
this.transports.clear()
|
|
356
|
-
|
|
357
|
-
// Close all Legacy SSE transports
|
|
358
|
-
for (const [sessionId, transport] of this.sseTransports) {
|
|
359
|
-
try {
|
|
360
|
-
logger.debug('Closing Legacy SSE transport', {
|
|
361
|
-
module: 'HTTP',
|
|
362
|
-
sessionId,
|
|
363
|
-
})
|
|
364
|
-
await transport.close()
|
|
365
|
-
} catch (error) {
|
|
366
|
-
logger.error('Error closing SSE transport', {
|
|
367
|
-
module: 'HTTP',
|
|
368
|
-
sessionId,
|
|
369
|
-
error: error instanceof Error ? error.message : String(error),
|
|
370
|
-
})
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
this.sseTransports.clear()
|
|
374
|
-
|
|
375
|
-
this.sessionLastActivity.clear()
|
|
376
|
-
if (this.sessionSweepTimer !== null) {
|
|
377
|
-
clearInterval(this.sessionSweepTimer)
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
if (this.httpServer !== null) {
|
|
381
|
-
this.httpServer.close()
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
logger.info('Shutdown complete', { module: 'HTTP' })
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// =========================================================================
|
|
388
|
-
// Session Activity Tracking
|
|
389
|
-
// =========================================================================
|
|
390
|
-
|
|
391
|
-
/** Update the last-activity timestamp for a session */
|
|
392
|
-
public touchSession(sid: string): void {
|
|
393
|
-
this.sessionLastActivity.set(sid, Date.now())
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
// =========================================================================
|
|
397
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'
|
|
2
|
-
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
3
|
-
import type { Request, Response, Express } from 'express'
|
|
4
|
-
import type { IncomingMessage, ServerResponse } from 'node:http'
|
|
5
|
-
import { logger } from '../../../utils/logger.js'
|
|
6
|
-
import type { StatefulContext } from './stateful.js'
|
|
7
|
-
import { JSONRPC_SERVER_ERROR } from '../types.js'
|
|
8
|
-
|
|
9
|
-
export function setupLegacySSE(ctx: StatefulContext, app: Express, server: McpServer): void {
|
|
10
|
-
app.get('/sse', (req: Request, res: Response): void => {
|
|
11
|
-
logger.info('Legacy SSE connection requested', { module: 'HTTP' })
|
|
12
|
-
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated -- backward compat for MCP 2024-11-05 clients
|
|
14
|
-
const sseTransport = new SSEServerTransport('/messages', res as ServerResponse)
|
|
15
|
-
|
|
16
|
-
// Store transport by session ID after start
|
|
17
|
-
sseTransport.onclose = () => {
|
|
18
|
-
logger.info('Legacy SSE transport closed', {
|
|
19
|
-
module: 'HTTP',
|
|
20
|
-
sessionId: sseTransport.sessionId,
|
|
21
|
-
})
|
|
22
|
-
ctx.sseTransports.delete(sseTransport.sessionId)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
void (async () => {
|
|
26
|
-
try {
|
|
27
|
-
// Connect SSE transport to server
|
|
28
|
-
// SDK requires close() before reconnecting to a new transport.
|
|
29
|
-
if (ctx.serverConnected) {
|
|
30
|
-
await server.close()
|
|
31
|
-
}
|
|
32
|
-
await server.connect(sseTransport as Parameters<typeof server.connect>[0])
|
|
33
|
-
ctx.serverConnected = true
|
|
34
|
-
ctx.sseTransports.set(sseTransport.sessionId, sseTransport)
|
|
35
|
-
ctx.touchSession(sseTransport.sessionId)
|
|
36
|
-
logger.info('Legacy SSE connection established', {
|
|
37
|
-
module: 'HTTP',
|
|
38
|
-
sessionId: sseTransport.sessionId,
|
|
39
|
-
})
|
|
40
|
-
} catch (error) {
|
|
41
|
-
logger.error('Error starting SSE transport', {
|
|
42
|
-
module: 'HTTP',
|
|
43
|
-
error: error instanceof Error ? error.message : String(error),
|
|
44
|
-
})
|
|
45
|
-
if (!res.headersSent) {
|
|
46
|
-
res.status(500).end()
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
})()
|
|
50
|
-
|
|
51
|
-
// Clean up when client disconnects
|
|
52
|
-
req.on('close', () => {
|
|
53
|
-
ctx.sseTransports.delete(sseTransport.sessionId)
|
|
54
|
-
ctx.sessionLastActivity.delete(sseTransport.sessionId)
|
|
55
|
-
})
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
// POST /messages?sessionId=<id> — Route messages to Legacy SSE transport
|
|
59
|
-
app.post('/messages', (req: Request, res: Response): void => {
|
|
60
|
-
const sessionId =
|
|
61
|
-
typeof req.query['sessionId'] === 'string' ? req.query['sessionId'] : undefined
|
|
62
|
-
|
|
63
|
-
if (sessionId === undefined) {
|
|
64
|
-
res.status(400).json({
|
|
65
|
-
jsonrpc: '2.0',
|
|
66
|
-
error: { code: JSONRPC_SERVER_ERROR, message: 'Missing sessionId parameter' },
|
|
67
|
-
id: null,
|
|
68
|
-
})
|
|
69
|
-
return
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const transport = ctx.sseTransports.get(sessionId)
|
|
73
|
-
if (transport === undefined) {
|
|
74
|
-
res.status(404).json({
|
|
75
|
-
jsonrpc: '2.0',
|
|
76
|
-
error: { code: JSONRPC_SERVER_ERROR, message: 'Session not found' },
|
|
77
|
-
id: null,
|
|
78
|
-
})
|
|
79
|
-
return
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Refresh session activity on message receipt
|
|
83
|
-
ctx.touchSession(sessionId)
|
|
84
|
-
|
|
85
|
-
void transport.handlePostMessage(req as IncomingMessage, res as ServerResponse, req.body)
|
|
86
|
-
})
|
|
87
|
-
}
|