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
package/src/server/scheduler.ts
DELETED
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Memory Journal MCP Server - Scheduler
|
|
3
|
-
*
|
|
4
|
-
* Lightweight in-process scheduler for periodic maintenance jobs.
|
|
5
|
-
* Only meaningful for HTTP/SSE transport (long-lived server processes).
|
|
6
|
-
* Uses setInterval for simplicity — no external dependencies.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { IDatabaseAdapter } from '../database/core/interfaces.js'
|
|
10
|
-
import type { VectorSearchManager } from '../vector/vector-search-manager.js'
|
|
11
|
-
import { logger } from '../utils/logger.js'
|
|
12
|
-
|
|
13
|
-
// ============================================================================
|
|
14
|
-
// Types
|
|
15
|
-
// ============================================================================
|
|
16
|
-
|
|
17
|
-
/** Scheduler configuration options */
|
|
18
|
-
export interface SchedulerOptions {
|
|
19
|
-
/** Automated backup interval in minutes (0 = disabled) */
|
|
20
|
-
backupIntervalMinutes: number
|
|
21
|
-
/** Max backups to retain during automated cleanup */
|
|
22
|
-
keepBackups: number
|
|
23
|
-
/** Database optimize interval in minutes (0 = disabled) */
|
|
24
|
-
vacuumIntervalMinutes: number
|
|
25
|
-
/** Vector index rebuild interval in minutes (0 = disabled) */
|
|
26
|
-
rebuildIndexIntervalMinutes: number
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/** Status of a single scheduled job */
|
|
30
|
-
export interface JobStatus {
|
|
31
|
-
name: string
|
|
32
|
-
enabled: boolean
|
|
33
|
-
intervalMinutes: number
|
|
34
|
-
lastRun: string | null
|
|
35
|
-
lastResult: 'success' | 'error' | null
|
|
36
|
-
lastError: string | null
|
|
37
|
-
nextRun: string | null
|
|
38
|
-
runCount: number
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** Overall scheduler status */
|
|
42
|
-
export interface SchedulerStatus {
|
|
43
|
-
active: boolean
|
|
44
|
-
jobs: JobStatus[]
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** Internal timer tracking for a job */
|
|
48
|
-
interface JobTimer {
|
|
49
|
-
name: string
|
|
50
|
-
intervalMinutes: number
|
|
51
|
-
timer: ReturnType<typeof setInterval>
|
|
52
|
-
lastRun: Date | null
|
|
53
|
-
lastResult: 'success' | 'error' | null
|
|
54
|
-
lastError: string | null
|
|
55
|
-
runCount: number
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// ============================================================================
|
|
59
|
-
// Scheduler
|
|
60
|
-
// ============================================================================
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Scheduler — runs periodic maintenance jobs for long-lived server processes.
|
|
64
|
-
*
|
|
65
|
-
* Jobs:
|
|
66
|
-
* - **backup**: Exports database to timestamped file, then prunes old backups.
|
|
67
|
-
* - **vacuum**: Runs `PRAGMA optimize` and flushes database to disk.
|
|
68
|
-
* - **rebuild-index**: Rebuilds vector search index from all entries.
|
|
69
|
-
*/
|
|
70
|
-
export class Scheduler {
|
|
71
|
-
private readonly options: SchedulerOptions
|
|
72
|
-
private readonly db: IDatabaseAdapter
|
|
73
|
-
private readonly vectorManager: VectorSearchManager | null
|
|
74
|
-
private readonly timers: JobTimer[] = []
|
|
75
|
-
private started = false
|
|
76
|
-
|
|
77
|
-
constructor(
|
|
78
|
-
options: SchedulerOptions,
|
|
79
|
-
db: IDatabaseAdapter,
|
|
80
|
-
vectorManager?: VectorSearchManager
|
|
81
|
-
) {
|
|
82
|
-
this.options = options
|
|
83
|
-
this.db = db
|
|
84
|
-
this.vectorManager = vectorManager ?? null
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Start all enabled scheduled jobs.
|
|
89
|
-
* Each job runs on its own interval and failures are isolated.
|
|
90
|
-
*/
|
|
91
|
-
start(): void {
|
|
92
|
-
if (this.started) {
|
|
93
|
-
logger.warning('Scheduler already started, ignoring duplicate start()', {
|
|
94
|
-
module: 'Scheduler',
|
|
95
|
-
})
|
|
96
|
-
return
|
|
97
|
-
}
|
|
98
|
-
this.started = true
|
|
99
|
-
|
|
100
|
-
const { backupIntervalMinutes, vacuumIntervalMinutes, rebuildIndexIntervalMinutes } =
|
|
101
|
-
this.options
|
|
102
|
-
|
|
103
|
-
if (backupIntervalMinutes > 0) {
|
|
104
|
-
this.scheduleJob('backup', backupIntervalMinutes, () => this.runBackup())
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (vacuumIntervalMinutes > 0) {
|
|
108
|
-
this.scheduleJob('vacuum', vacuumIntervalMinutes, () => {
|
|
109
|
-
this.runVacuumOptimize()
|
|
110
|
-
return Promise.resolve()
|
|
111
|
-
})
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (rebuildIndexIntervalMinutes > 0) {
|
|
115
|
-
if (this.vectorManager) {
|
|
116
|
-
this.scheduleJob('rebuild-index', rebuildIndexIntervalMinutes, () =>
|
|
117
|
-
this.runRebuildIndex()
|
|
118
|
-
)
|
|
119
|
-
} else {
|
|
120
|
-
logger.warning(
|
|
121
|
-
'rebuild-index-interval specified but vector manager not available, skipping',
|
|
122
|
-
{ module: 'Scheduler' }
|
|
123
|
-
)
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (this.timers.length > 0) {
|
|
128
|
-
const summary = this.timers.map(
|
|
129
|
-
(t: JobTimer) => `${t.name} (${String(t.intervalMinutes)}min)`
|
|
130
|
-
)
|
|
131
|
-
logger.info(`Scheduler started: ${summary.join(', ')}`, { module: 'Scheduler' })
|
|
132
|
-
} else {
|
|
133
|
-
logger.info('Scheduler started with no jobs enabled', { module: 'Scheduler' })
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Stop all scheduled jobs and clear timers.
|
|
139
|
-
* Safe to call multiple times.
|
|
140
|
-
*/
|
|
141
|
-
stop(): void {
|
|
142
|
-
for (const job of this.timers) {
|
|
143
|
-
clearInterval(job.timer)
|
|
144
|
-
}
|
|
145
|
-
if (this.timers.length > 0) {
|
|
146
|
-
logger.info(`Scheduler stopped, cleared ${String(this.timers.length)} job(s)`, {
|
|
147
|
-
module: 'Scheduler',
|
|
148
|
-
})
|
|
149
|
-
}
|
|
150
|
-
this.timers.length = 0
|
|
151
|
-
this.started = false
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Get the current status of all scheduled jobs.
|
|
156
|
-
*/
|
|
157
|
-
getStatus(): SchedulerStatus {
|
|
158
|
-
return {
|
|
159
|
-
active: this.started,
|
|
160
|
-
jobs: this.timers.map((t: JobTimer) => ({
|
|
161
|
-
name: t.name,
|
|
162
|
-
enabled: true,
|
|
163
|
-
intervalMinutes: t.intervalMinutes,
|
|
164
|
-
lastRun: t.lastRun?.toISOString() ?? null,
|
|
165
|
-
lastResult: t.lastResult,
|
|
166
|
-
lastError: t.lastError,
|
|
167
|
-
nextRun: t.lastRun
|
|
168
|
-
? new Date(t.lastRun.getTime() + t.intervalMinutes * 60_000).toISOString()
|
|
169
|
-
: new Date(Date.now() + t.intervalMinutes * 60_000).toISOString(),
|
|
170
|
-
runCount: t.runCount,
|
|
171
|
-
})),
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// ========================================================================
|
|
176
|
-
// Private — Job scheduling
|
|
177
|
-
// ========================================================================
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Schedule a recurring job.
|
|
181
|
-
*/
|
|
182
|
-
private scheduleJob(name: string, intervalMinutes: number, fn: () => Promise<void>): void {
|
|
183
|
-
const intervalMs = intervalMinutes * 60_000
|
|
184
|
-
|
|
185
|
-
const jobTimer: JobTimer = {
|
|
186
|
-
name,
|
|
187
|
-
intervalMinutes,
|
|
188
|
-
timer: setInterval(() => {
|
|
189
|
-
void this.executeJob(jobTimer, fn)
|
|
190
|
-
}, intervalMs),
|
|
191
|
-
lastRun: null,
|
|
192
|
-
lastResult: null,
|
|
193
|
-
lastError: null,
|
|
194
|
-
runCount: 0,
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
jobTimer.timer.unref()
|
|
198
|
-
this.timers.push(jobTimer)
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Execute a job with error isolation and status tracking.
|
|
203
|
-
*/
|
|
204
|
-
private async executeJob(job: JobTimer, fn: () => Promise<void>): Promise<void> {
|
|
205
|
-
const startTime = Date.now()
|
|
206
|
-
try {
|
|
207
|
-
await fn()
|
|
208
|
-
job.lastRun = new Date(startTime)
|
|
209
|
-
job.lastResult = 'success'
|
|
210
|
-
job.lastError = null
|
|
211
|
-
job.runCount++
|
|
212
|
-
} catch (error) {
|
|
213
|
-
job.lastRun = new Date(startTime)
|
|
214
|
-
job.lastResult = 'error'
|
|
215
|
-
job.lastError = error instanceof Error ? error.message : String(error)
|
|
216
|
-
job.runCount++
|
|
217
|
-
logger.error(`Scheduled job '${job.name}' failed`, {
|
|
218
|
-
module: 'Scheduler',
|
|
219
|
-
operation: job.name,
|
|
220
|
-
error: job.lastError,
|
|
221
|
-
})
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// ========================================================================
|
|
226
|
-
// Private — Job implementations
|
|
227
|
-
// ========================================================================
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Backup job: export database to file, then cleanup old backups.
|
|
231
|
-
*/
|
|
232
|
-
private async runBackup(): Promise<void> {
|
|
233
|
-
const result = await this.db.exportToFile()
|
|
234
|
-
logger.info('Scheduled backup created', {
|
|
235
|
-
module: 'Scheduler',
|
|
236
|
-
operation: 'backup',
|
|
237
|
-
context: { filename: result.filename, sizeBytes: result.sizeBytes },
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
const cleanup = this.db.deleteOldBackups(this.options.keepBackups)
|
|
241
|
-
if (cleanup.deleted.length > 0) {
|
|
242
|
-
logger.info(
|
|
243
|
-
`Backup cleanup: deleted ${String(cleanup.deleted.length)}, kept ${String(cleanup.kept)}`,
|
|
244
|
-
{
|
|
245
|
-
module: 'Scheduler',
|
|
246
|
-
operation: 'backup-cleanup',
|
|
247
|
-
}
|
|
248
|
-
)
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Vacuum/optimize job: run PRAGMA optimize and flush to disk.
|
|
254
|
-
*
|
|
255
|
-
* PRAGMA optimize updates internal query planner statistics based on
|
|
256
|
-
* recent query patterns. For the native better-sqlite3 driver, disk
|
|
257
|
-
* writes happen automatically via WAL mode.
|
|
258
|
-
*/
|
|
259
|
-
private runVacuumOptimize(): void {
|
|
260
|
-
this.db.pragma('optimize')
|
|
261
|
-
this.db.flushSave()
|
|
262
|
-
logger.info('Scheduled database optimize completed', {
|
|
263
|
-
module: 'Scheduler',
|
|
264
|
-
operation: 'vacuum',
|
|
265
|
-
})
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Rebuild index job: full vector index rebuild from database entries.
|
|
270
|
-
*/
|
|
271
|
-
private async runRebuildIndex(): Promise<void> {
|
|
272
|
-
if (!this.vectorManager) {
|
|
273
|
-
return
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
const { indexed: count } = await this.vectorManager.rebuildIndex(this.db)
|
|
277
|
-
logger.info(`Scheduled vector index rebuild: ${String(count)} entries indexed`, {
|
|
278
|
-
module: 'Scheduler',
|
|
279
|
-
operation: 'rebuild-index',
|
|
280
|
-
context: { entriesIndexed: count },
|
|
281
|
-
})
|
|
282
|
-
}
|
|
283
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* memory-journal-mcp — HTTP Transport Handlers
|
|
3
|
-
*
|
|
4
|
-
* Standalone handler functions for utility endpoints and auth middleware.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { timingSafeEqual } from 'node:crypto'
|
|
8
|
-
import type { Request, Response } from 'express'
|
|
9
|
-
import { logger } from '../../utils/logger.js'
|
|
10
|
-
import { VERSION } from '../../version.js'
|
|
11
|
-
|
|
12
|
-
// =============================================================================
|
|
13
|
-
// Health Check
|
|
14
|
-
// =============================================================================
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Handle the /health endpoint
|
|
18
|
-
*/
|
|
19
|
-
export function handleHealthCheck(_req: Request, res: Response): void {
|
|
20
|
-
res.status(200).json({
|
|
21
|
-
status: 'healthy',
|
|
22
|
-
timestamp: new Date().toISOString(),
|
|
23
|
-
})
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// =============================================================================
|
|
27
|
-
// Root Info
|
|
28
|
-
// =============================================================================
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Handle the / endpoint — helpful for browser visitors and debugging
|
|
32
|
-
*/
|
|
33
|
-
export function handleRootInfo(_req: Request, res: Response): void {
|
|
34
|
-
res.status(200).json({
|
|
35
|
-
name: 'memory-journal-mcp',
|
|
36
|
-
version: VERSION,
|
|
37
|
-
description: 'Project context management for AI-assisted development',
|
|
38
|
-
endpoints: {
|
|
39
|
-
'POST /mcp': 'JSON-RPC requests (Streamable HTTP, MCP 2025-03-26)',
|
|
40
|
-
'GET /mcp': 'SSE stream for server-to-client notifications',
|
|
41
|
-
'DELETE /mcp': 'Session termination',
|
|
42
|
-
'GET /sse': 'Legacy SSE connection (MCP 2024-11-05)',
|
|
43
|
-
'POST /messages': 'Legacy SSE message endpoint',
|
|
44
|
-
'GET /health': 'Health check',
|
|
45
|
-
},
|
|
46
|
-
documentation: 'https://github.com/neverinfamous/memory-journal-mcp',
|
|
47
|
-
})
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// =============================================================================
|
|
51
|
-
// Bearer Token Auth Middleware
|
|
52
|
-
// =============================================================================
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Create a bearer token authentication middleware.
|
|
56
|
-
* Bypasses /health endpoint. Uses timing-safe comparison.
|
|
57
|
-
*/
|
|
58
|
-
export function createAuthMiddleware(
|
|
59
|
-
authToken: string
|
|
60
|
-
): (req: Request, res: Response, next: () => void) => void {
|
|
61
|
-
logger.info('Bearer token authentication enabled', { module: 'HTTP' })
|
|
62
|
-
|
|
63
|
-
return (req: Request, res: Response, next: () => void): void => {
|
|
64
|
-
if (req.path === '/health') {
|
|
65
|
-
next()
|
|
66
|
-
return
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const header = req.headers.authorization
|
|
70
|
-
const expected = Buffer.from(`Bearer ${authToken}`)
|
|
71
|
-
const received = Buffer.from(header ?? '')
|
|
72
|
-
if (expected.length !== received.length || !timingSafeEqual(expected, received)) {
|
|
73
|
-
res.status(401).json({ error: 'Unauthorized' })
|
|
74
|
-
return
|
|
75
|
-
}
|
|
76
|
-
next()
|
|
77
|
-
}
|
|
78
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* memory-journal-mcp — HTTP Transport barrel export
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export { HttpTransport } from './server/index.js'
|
|
6
|
-
export type { HttpTransportConfig } from './types.js'
|
|
7
|
-
export { getClientIp, checkRateLimit } from './security.js'
|
|
8
|
-
export { handleHealthCheck, handleRootInfo } from './handlers.js'
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* memory-journal-mcp — HTTP Transport Security
|
|
3
|
-
*
|
|
4
|
-
* Security utilities: rate limiting, headers, CORS, client IP extraction.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { Request, Response } from 'express'
|
|
8
|
-
import type { HttpTransportConfig, RateLimitEntry } from './types.js'
|
|
9
|
-
import {
|
|
10
|
-
DEFAULT_RATE_LIMIT_WINDOW_MS,
|
|
11
|
-
DEFAULT_RATE_LIMIT_MAX_REQUESTS,
|
|
12
|
-
DEFAULT_HSTS_MAX_AGE,
|
|
13
|
-
CORS_PREFLIGHT_MAX_AGE_SECONDS,
|
|
14
|
-
} from './types.js'
|
|
15
|
-
|
|
16
|
-
// =============================================================================
|
|
17
|
-
// Client IP Extraction
|
|
18
|
-
// =============================================================================
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Extract the client IP address from the request.
|
|
22
|
-
* When trustProxy is enabled, uses the leftmost IP from X-Forwarded-For.
|
|
23
|
-
* Falls back to Express's req.ip then req.socket.remoteAddress.
|
|
24
|
-
*/
|
|
25
|
-
export function getClientIp(req: Request, trustProxy: boolean): string {
|
|
26
|
-
if (trustProxy) {
|
|
27
|
-
const forwarded = req.headers['x-forwarded-for']
|
|
28
|
-
if (typeof forwarded === 'string') {
|
|
29
|
-
const firstIp = forwarded.split(',')[0]?.trim()
|
|
30
|
-
if (firstIp) return firstIp
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return req.ip ?? req.socket.remoteAddress ?? 'unknown'
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// =============================================================================
|
|
37
|
-
// Rate Limiting
|
|
38
|
-
// =============================================================================
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Check rate limit for a request.
|
|
42
|
-
* Returns object with `allowed` flag and optional `retryAfterSeconds`.
|
|
43
|
-
*/
|
|
44
|
-
export function checkRateLimit(
|
|
45
|
-
req: Request,
|
|
46
|
-
config: HttpTransportConfig,
|
|
47
|
-
rateLimitMap: Map<string, RateLimitEntry>
|
|
48
|
-
): { allowed: boolean; retryAfterSeconds?: number } {
|
|
49
|
-
if (config.enableRateLimit === false) {
|
|
50
|
-
return { allowed: true }
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const clientIp = getClientIp(req, config.trustProxy ?? false)
|
|
54
|
-
const now = Date.now()
|
|
55
|
-
const windowMs = config.rateLimitWindowMs ?? DEFAULT_RATE_LIMIT_WINDOW_MS
|
|
56
|
-
const maxRequests =
|
|
57
|
-
config.rateLimitMaxRequests ??
|
|
58
|
-
(process.env['MCP_RATE_LIMIT_MAX']
|
|
59
|
-
? parseInt(process.env['MCP_RATE_LIMIT_MAX'], 10)
|
|
60
|
-
: DEFAULT_RATE_LIMIT_MAX_REQUESTS)
|
|
61
|
-
|
|
62
|
-
const entry = rateLimitMap.get(clientIp)
|
|
63
|
-
|
|
64
|
-
if (!entry || now > entry.resetTime) {
|
|
65
|
-
rateLimitMap.set(clientIp, { count: 1, resetTime: now + windowMs })
|
|
66
|
-
return { allowed: true }
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (entry.count >= maxRequests) {
|
|
70
|
-
const retryAfterSeconds = Math.ceil((entry.resetTime - now) / 1000)
|
|
71
|
-
return { allowed: false, retryAfterSeconds }
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
entry.count++
|
|
75
|
-
return { allowed: true }
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// =============================================================================
|
|
79
|
-
// Security Headers
|
|
80
|
-
// =============================================================================
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Set security headers for all responses.
|
|
84
|
-
*
|
|
85
|
-
* Headers: X-Content-Type-Options, X-Frame-Options, Cache-Control,
|
|
86
|
-
* Content-Security-Policy, Permissions-Policy, Referrer-Policy, HSTS (opt-in).
|
|
87
|
-
*/
|
|
88
|
-
export function setSecurityHeaders(res: Response, config: HttpTransportConfig): void {
|
|
89
|
-
res.setHeader('X-Content-Type-Options', 'nosniff')
|
|
90
|
-
res.setHeader('X-Frame-Options', 'DENY')
|
|
91
|
-
res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate')
|
|
92
|
-
res.setHeader('Content-Security-Policy', "default-src 'none'; frame-ancestors 'none'")
|
|
93
|
-
res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=()')
|
|
94
|
-
res.setHeader('Referrer-Policy', 'no-referrer')
|
|
95
|
-
|
|
96
|
-
if (config.enableHSTS) {
|
|
97
|
-
const maxAge = config.hstsMaxAge ?? DEFAULT_HSTS_MAX_AGE
|
|
98
|
-
res.setHeader('Strict-Transport-Security', `max-age=${String(maxAge)}; includeSubDomains`)
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// =============================================================================
|
|
103
|
-
// CORS
|
|
104
|
-
// =============================================================================
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Set CORS headers based on configuration.
|
|
108
|
-
*
|
|
109
|
-
* Uses the `origin in whitelist` pattern from CodeQL's documented safe example
|
|
110
|
-
* for js/cors-misconfiguration-for-credentials. CodeQL only recognizes specific
|
|
111
|
-
* sanitizer expressions (object property lookup via `in`, `Set.has()`, etc.) —
|
|
112
|
-
* `Array.some()` with a callback is NOT recognized as a sanitizer.
|
|
113
|
-
*
|
|
114
|
-
* Wildcard subdomain patterns (`*.example.com`) are not supported when
|
|
115
|
-
* `corsAllowCredentials` is true. For credentialed CORS, list explicit origins.
|
|
116
|
-
*/
|
|
117
|
-
export function setCorsHeaders(req: Request, res: Response, config: HttpTransportConfig): void {
|
|
118
|
-
const corsOrigins = config.corsOrigins ?? ['*']
|
|
119
|
-
const isWildcard = corsOrigins.includes('*')
|
|
120
|
-
const origin = req.headers.origin
|
|
121
|
-
|
|
122
|
-
if (isWildcard) {
|
|
123
|
-
res.setHeader('Access-Control-Allow-Origin', '*')
|
|
124
|
-
} else if (origin) {
|
|
125
|
-
// Build whitelist record — CodeQL recognizes `origin in whitelist` as a sanitizer
|
|
126
|
-
const whitelist: Record<string, true> = {}
|
|
127
|
-
for (const allowed of corsOrigins) {
|
|
128
|
-
whitelist[allowed] = true
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (origin in whitelist) {
|
|
132
|
-
res.setHeader('Access-Control-Allow-Origin', origin)
|
|
133
|
-
res.setHeader('Vary', 'Origin')
|
|
134
|
-
if (config.corsAllowCredentials) {
|
|
135
|
-
res.setHeader('Access-Control-Allow-Credentials', 'true')
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS')
|
|
141
|
-
res.setHeader(
|
|
142
|
-
'Access-Control-Allow-Headers',
|
|
143
|
-
'Content-Type, Accept, Authorization, mcp-session-id, Last-Event-ID, mcp-protocol-version'
|
|
144
|
-
)
|
|
145
|
-
res.setHeader('Access-Control-Expose-Headers', 'mcp-session-id')
|
|
146
|
-
res.setHeader('Access-Control-Max-Age', String(CORS_PREFLIGHT_MAX_AGE_SECONDS))
|
|
147
|
-
}
|