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,145 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* E2E Tests: memory://instructions Resource — Tool-Filter Gating
|
|
3
|
-
*
|
|
4
|
-
* The memory://instructions resource always serves full-level instructions
|
|
5
|
-
* but conditions sections on which tool groups are enabled via --tool-filter.
|
|
6
|
-
*
|
|
7
|
-
* Validated section gates (from server-instructions.ts):
|
|
8
|
-
* Code Mode section — present only when `codemode` group enabled
|
|
9
|
-
* GitHub Integration — present only when `github` group enabled
|
|
10
|
-
* Copilot Review — present only when `github` group enabled
|
|
11
|
-
* Semantic search row in Quick Access — `search` group only
|
|
12
|
-
*
|
|
13
|
-
* This exercises the HTTP-transport path for instructions, which is
|
|
14
|
-
* distinct from the stdio path tested in test-filter-instructions.mjs.
|
|
15
|
-
*
|
|
16
|
-
* Uses dedicated server ports 3110, 3111.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
import { test, expect } from '@playwright/test'
|
|
20
|
-
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
|
|
21
|
-
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
|
|
22
|
-
import { startServer, stopServer } from './helpers.js'
|
|
23
|
-
|
|
24
|
-
const CORE_ONLY_PORT = 3110 // --tool-filter core (no codemode, no github, no search)
|
|
25
|
-
const NO_GITHUB_PORT = 3111 // --tool-filter -github (all except github)
|
|
26
|
-
|
|
27
|
-
/** Read memory://instructions text from a client */
|
|
28
|
-
async function readInstructions(client: Client): Promise<string> {
|
|
29
|
-
const response = await client.readResource({ uri: 'memory://instructions' })
|
|
30
|
-
expect(response.contents).toBeDefined()
|
|
31
|
-
expect(response.contents.length).toBeGreaterThan(0)
|
|
32
|
-
return response.contents[0]!.text as string
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// ============================================================================
|
|
36
|
-
// core-only filter: no codemode, no github, no search
|
|
37
|
-
// ============================================================================
|
|
38
|
-
|
|
39
|
-
test.describe('memory://instructions: core-only filter gating', () => {
|
|
40
|
-
let client: Client
|
|
41
|
-
|
|
42
|
-
test.beforeAll(async () => {
|
|
43
|
-
await startServer(CORE_ONLY_PORT, ['--tool-filter', 'core'], 'instr-core-only')
|
|
44
|
-
const transport = new StreamableHTTPClientTransport(
|
|
45
|
-
new URL(`http://localhost:${CORE_ONLY_PORT}/mcp`)
|
|
46
|
-
)
|
|
47
|
-
client = new Client(
|
|
48
|
-
{ name: 'instr-core-only-test', version: '1.0.0' },
|
|
49
|
-
{ capabilities: {} }
|
|
50
|
-
)
|
|
51
|
-
await client.connect(transport)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
test.afterAll(async () => {
|
|
55
|
-
await client.close()
|
|
56
|
-
stopServer(CORE_ONLY_PORT)
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
test('core-only: core section (Rule & Skill Suggestions) is always present', async () => {
|
|
60
|
-
const text = await readInstructions(client)
|
|
61
|
-
expect(text).toContain('Rule & Skill Suggestions')
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
test('core-only: Active Tools section lists only core group', async () => {
|
|
65
|
-
const text = await readInstructions(client)
|
|
66
|
-
// Active Tools section should mention core tools
|
|
67
|
-
expect(text).toContain('## Active Tools')
|
|
68
|
-
expect(text).toContain('core')
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
test('core-only: Code Mode section is absent (codemode group disabled)', async () => {
|
|
72
|
-
const text = await readInstructions(client)
|
|
73
|
-
expect(text).not.toContain('Code Mode (Token-Efficient')
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
test('core-only: GitHub Integration section is absent (github group disabled)', async () => {
|
|
77
|
-
const text = await readInstructions(client)
|
|
78
|
-
expect(text).not.toContain('## GitHub Integration')
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
test('core-only: Copilot Review Patterns section is absent (github group disabled)', async () => {
|
|
82
|
-
const text = await readInstructions(client)
|
|
83
|
-
expect(text).not.toContain('Copilot Review Patterns')
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
test('core-only: semantic_search Quick Access row is absent (search group disabled)', async () => {
|
|
87
|
-
const text = await readInstructions(client)
|
|
88
|
-
expect(text).not.toContain('| Semantic search |')
|
|
89
|
-
})
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
// ============================================================================
|
|
93
|
-
// -github filter: all groups except github
|
|
94
|
-
// ============================================================================
|
|
95
|
-
|
|
96
|
-
test.describe('memory://instructions: -github filter gating', () => {
|
|
97
|
-
let client: Client
|
|
98
|
-
|
|
99
|
-
test.beforeAll(async () => {
|
|
100
|
-
await startServer(NO_GITHUB_PORT, ['--tool-filter', '-github'], 'instr-no-github')
|
|
101
|
-
const transport = new StreamableHTTPClientTransport(
|
|
102
|
-
new URL(`http://localhost:${NO_GITHUB_PORT}/mcp`)
|
|
103
|
-
)
|
|
104
|
-
client = new Client(
|
|
105
|
-
{ name: 'instr-no-github-test', version: '1.0.0' },
|
|
106
|
-
{ capabilities: {} }
|
|
107
|
-
)
|
|
108
|
-
await client.connect(transport)
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
test.afterAll(async () => {
|
|
112
|
-
await client.close()
|
|
113
|
-
stopServer(NO_GITHUB_PORT)
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
test('-github: core section is present', async () => {
|
|
117
|
-
const text = await readInstructions(client)
|
|
118
|
-
expect(text).toContain('Rule & Skill Suggestions')
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
test('-github: Code Mode section is present (codemode group enabled)', async () => {
|
|
122
|
-
const text = await readInstructions(client)
|
|
123
|
-
expect(text).toContain('Code Mode (Token-Efficient')
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
test('-github: GitHub Integration section is absent (github group removed)', async () => {
|
|
127
|
-
const text = await readInstructions(client)
|
|
128
|
-
expect(text).not.toContain('## GitHub Integration')
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
test('-github: Copilot Review Patterns section is absent (github group removed)', async () => {
|
|
132
|
-
const text = await readInstructions(client)
|
|
133
|
-
expect(text).not.toContain('Copilot Review Patterns')
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
test('-github: semantic_search Quick Access row is present (search group enabled)', async () => {
|
|
137
|
-
const text = await readInstructions(client)
|
|
138
|
-
expect(text).toContain('| Semantic search |')
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
test('-github: Active Tools section does not list github tools', async () => {
|
|
142
|
-
const text = await readInstructions(client)
|
|
143
|
-
expect(text).not.toContain('get_github_issues')
|
|
144
|
-
})
|
|
145
|
-
})
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* E2E Tests: Template Resource Reads via SDK Client
|
|
3
|
-
*
|
|
4
|
-
* Validates that all 8 template resources can be fetched by URI
|
|
5
|
-
* without throwing a raw MCP protocol exception. Since the E2E test
|
|
6
|
-
* environment has no GitHub token, GitHub-backed templates will return
|
|
7
|
-
* structured error JSON rather than real data — both outcomes are valid.
|
|
8
|
-
*
|
|
9
|
-
* Also verifies memory://help/{group} returns per-group tool details.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { test, expect } from '@playwright/test'
|
|
13
|
-
import { createClient } from './helpers.js'
|
|
14
|
-
import type { Client } from '@modelcontextprotocol/sdk/client/index.js'
|
|
15
|
-
|
|
16
|
-
test.describe.configure({ mode: 'serial' })
|
|
17
|
-
|
|
18
|
-
test.describe('E2E Resource Reads: Template Resources', () => {
|
|
19
|
-
let client: Client
|
|
20
|
-
|
|
21
|
-
test.beforeAll(async () => {
|
|
22
|
-
client = await createClient()
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
test.afterAll(async () => {
|
|
26
|
-
await client.close()
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Read a template resource URI and assert we get a non-empty text response.
|
|
31
|
-
* MCP protocol exceptions (thrown, not returned) are re-thrown so the test fails.
|
|
32
|
-
* Structured JSON errors (returned as content) count as valid responses.
|
|
33
|
-
*/
|
|
34
|
-
async function readTemplateResource(uri: string): Promise<string> {
|
|
35
|
-
const response = await client.readResource({ uri })
|
|
36
|
-
expect(response.contents).toBeDefined()
|
|
37
|
-
expect(response.contents.length).toBeGreaterThan(0)
|
|
38
|
-
const text = response.contents[0]!.text as string
|
|
39
|
-
expect(typeof text).toBe('string')
|
|
40
|
-
expect(text.length).toBeGreaterThan(0)
|
|
41
|
-
return text
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// --- memory://help/{group} — dynamic per-group tool reference ---
|
|
45
|
-
|
|
46
|
-
test('memory://help/core returns per-group tool list', async () => {
|
|
47
|
-
const text = await readTemplateResource('memory://help/core')
|
|
48
|
-
const parsed = JSON.parse(text)
|
|
49
|
-
expect(parsed).toHaveProperty('group', 'core')
|
|
50
|
-
expect(parsed).toHaveProperty('tools')
|
|
51
|
-
expect(Array.isArray(parsed.tools)).toBe(true)
|
|
52
|
-
expect(parsed.tools.length).toBeGreaterThanOrEqual(5)
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
test('memory://help/search returns search group tools', async () => {
|
|
56
|
-
const text = await readTemplateResource('memory://help/search')
|
|
57
|
-
const parsed = JSON.parse(text)
|
|
58
|
-
expect(parsed).toHaveProperty('group', 'search')
|
|
59
|
-
expect(Array.isArray(parsed.tools)).toBe(true)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
test('memory://help/github returns github group tools', async () => {
|
|
63
|
-
const text = await readTemplateResource('memory://help/github')
|
|
64
|
-
const parsed = JSON.parse(text)
|
|
65
|
-
expect(parsed).toHaveProperty('group', 'github')
|
|
66
|
-
expect(Array.isArray(parsed.tools)).toBe(true)
|
|
67
|
-
expect(parsed.tools.length).toBeGreaterThanOrEqual(16)
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
test('memory://help/team returns team group tools', async () => {
|
|
71
|
-
const text = await readTemplateResource('memory://help/team')
|
|
72
|
-
const parsed = JSON.parse(text)
|
|
73
|
-
expect(parsed).toHaveProperty('group', 'team')
|
|
74
|
-
expect(Array.isArray(parsed.tools)).toBe(true)
|
|
75
|
-
expect(parsed.tools.length).toBeGreaterThanOrEqual(20)
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
test('memory://help/codemode returns codemode group tools', async () => {
|
|
79
|
-
const text = await readTemplateResource('memory://help/codemode')
|
|
80
|
-
const parsed = JSON.parse(text)
|
|
81
|
-
expect(parsed).toHaveProperty('group', 'codemode')
|
|
82
|
-
expect(Array.isArray(parsed.tools)).toBe(true)
|
|
83
|
-
expect(parsed.tools.length).toBeGreaterThanOrEqual(1)
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
// --- GitHub-backed template resources (no token — structured error or data) ---
|
|
87
|
-
|
|
88
|
-
test('memory://projects/1/timeline returns valid response', async () => {
|
|
89
|
-
const text = await readTemplateResource('memory://projects/1/timeline')
|
|
90
|
-
// Either a structured JSON error or a timeline object
|
|
91
|
-
expect(text.length).toBeGreaterThan(0)
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
test('memory://issues/1/entries returns valid response', async () => {
|
|
95
|
-
const text = await readTemplateResource('memory://issues/1/entries')
|
|
96
|
-
expect(text.length).toBeGreaterThan(0)
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
test('memory://prs/1/entries returns valid response', async () => {
|
|
100
|
-
const text = await readTemplateResource('memory://prs/1/entries')
|
|
101
|
-
expect(text.length).toBeGreaterThan(0)
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
test('memory://prs/1/timeline returns valid response', async () => {
|
|
105
|
-
const text = await readTemplateResource('memory://prs/1/timeline')
|
|
106
|
-
expect(text.length).toBeGreaterThan(0)
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
test('memory://kanban/1 returns valid response', async () => {
|
|
110
|
-
const text = await readTemplateResource('memory://kanban/1')
|
|
111
|
-
expect(text.length).toBeGreaterThan(0)
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
test('memory://kanban/1/diagram returns valid response', async () => {
|
|
115
|
-
const text = await readTemplateResource('memory://kanban/1/diagram')
|
|
116
|
-
expect(text.length).toBeGreaterThan(0)
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
test('memory://milestones/1 returns valid response', async () => {
|
|
120
|
-
const text = await readTemplateResource('memory://milestones/1')
|
|
121
|
-
expect(text.length).toBeGreaterThan(0)
|
|
122
|
-
})
|
|
123
|
-
})
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* E2E Tests: MCP Resource Reads via SDK Client
|
|
3
|
-
*
|
|
4
|
-
* Uses the official @modelcontextprotocol/sdk client to connect
|
|
5
|
-
* via Streamable HTTP transport and read resources end-to-end.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { test, expect } from '@playwright/test'
|
|
9
|
-
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
|
|
10
|
-
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
|
|
11
|
-
|
|
12
|
-
test.describe.configure({ mode: 'serial' })
|
|
13
|
-
|
|
14
|
-
test.describe('E2E Resource Reads (via MCP SDK Client)', () => {
|
|
15
|
-
let client: Client
|
|
16
|
-
|
|
17
|
-
test.beforeAll(async () => {
|
|
18
|
-
const transport = new StreamableHTTPClientTransport(new URL('http://localhost:3100/mcp'))
|
|
19
|
-
client = new Client(
|
|
20
|
-
{ name: 'playwright-resource-test', version: '1.0.0' },
|
|
21
|
-
{ capabilities: {} }
|
|
22
|
-
)
|
|
23
|
-
await client.connect(transport)
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
test.afterAll(async () => {
|
|
27
|
-
await client.close()
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
test('should list available resources', async () => {
|
|
31
|
-
const listResponse = await client.listResources()
|
|
32
|
-
|
|
33
|
-
expect(listResponse.resources).toBeDefined()
|
|
34
|
-
expect(Array.isArray(listResponse.resources)).toBe(true)
|
|
35
|
-
expect(listResponse.resources.length).toBeGreaterThan(0)
|
|
36
|
-
|
|
37
|
-
const uris = listResponse.resources.map((r) => r.uri)
|
|
38
|
-
expect(uris).toContain('memory://health')
|
|
39
|
-
expect(uris).toContain('memory://briefing')
|
|
40
|
-
expect(uris).toContain('memory://recent')
|
|
41
|
-
expect(uris).toContain('memory://statistics')
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
test('should read memory://health resource', async () => {
|
|
45
|
-
const response = await client.readResource({ uri: 'memory://health' })
|
|
46
|
-
|
|
47
|
-
expect(response.contents).toBeDefined()
|
|
48
|
-
expect(response.contents.length).toBeGreaterThan(0)
|
|
49
|
-
|
|
50
|
-
const text = response.contents[0]!.text as string
|
|
51
|
-
const parsed = JSON.parse(text)
|
|
52
|
-
expect(parsed).toHaveProperty('database')
|
|
53
|
-
expect(parsed).toHaveProperty('vectorIndex')
|
|
54
|
-
expect(parsed).toHaveProperty('scheduler')
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
test('should read memory://briefing resource', async () => {
|
|
58
|
-
const response = await client.readResource({ uri: 'memory://briefing' })
|
|
59
|
-
|
|
60
|
-
expect(response.contents).toBeDefined()
|
|
61
|
-
expect(response.contents.length).toBeGreaterThan(0)
|
|
62
|
-
|
|
63
|
-
const text = response.contents[0]!.text as string
|
|
64
|
-
const parsed = JSON.parse(text)
|
|
65
|
-
expect(parsed).toHaveProperty('userMessage')
|
|
66
|
-
expect(parsed).toHaveProperty('journal')
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
test('should read memory://recent resource', async () => {
|
|
70
|
-
const response = await client.readResource({ uri: 'memory://recent' })
|
|
71
|
-
|
|
72
|
-
expect(response.contents).toBeDefined()
|
|
73
|
-
expect(response.contents.length).toBeGreaterThan(0)
|
|
74
|
-
|
|
75
|
-
const text = response.contents[0]!.text as string
|
|
76
|
-
const parsed = JSON.parse(text)
|
|
77
|
-
// May be empty if no entries exist, but should be valid JSON
|
|
78
|
-
expect(parsed).toBeDefined()
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
test('should read memory://statistics resource', async () => {
|
|
82
|
-
const response = await client.readResource({ uri: 'memory://statistics' })
|
|
83
|
-
|
|
84
|
-
expect(response.contents).toBeDefined()
|
|
85
|
-
expect(response.contents.length).toBeGreaterThan(0)
|
|
86
|
-
|
|
87
|
-
const text = response.contents[0]!.text as string
|
|
88
|
-
const parsed = JSON.parse(text)
|
|
89
|
-
expect(parsed).toHaveProperty('totalEntries')
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
test('should list resource templates', async () => {
|
|
93
|
-
const response = await client.listResourceTemplates()
|
|
94
|
-
|
|
95
|
-
expect(response.resourceTemplates).toBeDefined()
|
|
96
|
-
expect(Array.isArray(response.resourceTemplates)).toBe(true)
|
|
97
|
-
expect(response.resourceTemplates.length).toBeGreaterThan(0)
|
|
98
|
-
|
|
99
|
-
const uriTemplates = response.resourceTemplates.map((t) => t.uriTemplate)
|
|
100
|
-
expect(uriTemplates).toContain('memory://issues/{issue_number}/entries')
|
|
101
|
-
expect(uriTemplates).toContain('memory://kanban/{project_number}')
|
|
102
|
-
})
|
|
103
|
-
})
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* E2E Tests: Scheduler Activation
|
|
3
|
-
*
|
|
4
|
-
* Verifies that the automated scheduler is active and visible
|
|
5
|
-
* in the memory://health resource when the server is started
|
|
6
|
-
* with scheduler flags (--backup-interval, --vacuum-interval, etc.)
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { test, expect } from '@playwright/test'
|
|
10
|
-
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
|
|
11
|
-
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
|
|
12
|
-
|
|
13
|
-
test.describe('Scheduler Activation (HTTP Only)', () => {
|
|
14
|
-
let client: Client
|
|
15
|
-
|
|
16
|
-
test.beforeAll(async () => {
|
|
17
|
-
const transport = new StreamableHTTPClientTransport(new URL('http://localhost:3100/mcp'))
|
|
18
|
-
client = new Client(
|
|
19
|
-
{ name: 'playwright-scheduler-test', version: '1.0.0' },
|
|
20
|
-
{ capabilities: {} }
|
|
21
|
-
)
|
|
22
|
-
await client.connect(transport)
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
test.afterAll(async () => {
|
|
26
|
-
await client.close()
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
test('memory://health should show scheduler.active as true', async () => {
|
|
30
|
-
const response = await client.readResource({ uri: 'memory://health' })
|
|
31
|
-
|
|
32
|
-
expect(response.contents).toBeDefined()
|
|
33
|
-
expect(response.contents.length).toBeGreaterThan(0)
|
|
34
|
-
|
|
35
|
-
const text = response.contents[0]!.text as string
|
|
36
|
-
const health = JSON.parse(text)
|
|
37
|
-
|
|
38
|
-
expect(health).toHaveProperty('scheduler')
|
|
39
|
-
expect(health.scheduler).toHaveProperty('active', true)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
test('memory://health should show 3 scheduler jobs', async () => {
|
|
43
|
-
const response = await client.readResource({ uri: 'memory://health' })
|
|
44
|
-
const health = JSON.parse(response.contents[0]!.text as string)
|
|
45
|
-
|
|
46
|
-
expect(health.scheduler).toHaveProperty('jobs')
|
|
47
|
-
expect(Array.isArray(health.scheduler.jobs)).toBe(true)
|
|
48
|
-
expect(health.scheduler.jobs.length).toBe(3)
|
|
49
|
-
|
|
50
|
-
const jobNames = health.scheduler.jobs.map((j: { name: string }) => j.name)
|
|
51
|
-
expect(jobNames).toContain('backup')
|
|
52
|
-
expect(jobNames).toContain('vacuum')
|
|
53
|
-
expect(jobNames).toContain('rebuild-index')
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
test('scheduler jobs should have nextRun timestamps', async () => {
|
|
57
|
-
const response = await client.readResource({ uri: 'memory://health' })
|
|
58
|
-
const health = JSON.parse(response.contents[0]!.text as string)
|
|
59
|
-
|
|
60
|
-
for (const job of health.scheduler.jobs) {
|
|
61
|
-
expect(job).toHaveProperty('nextRun')
|
|
62
|
-
// nextRun should be a valid ISO 8601 timestamp
|
|
63
|
-
const nextRun = new Date(job.nextRun)
|
|
64
|
-
expect(nextRun.toISOString()).toBe(job.nextRun)
|
|
65
|
-
// nextRun should be in the future (or very close to now)
|
|
66
|
-
expect(nextRun.getTime()).toBeGreaterThan(Date.now() - 60000)
|
|
67
|
-
}
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
test('scheduler jobs should have run count fields', async () => {
|
|
71
|
-
const response = await client.readResource({ uri: 'memory://health' })
|
|
72
|
-
const health = JSON.parse(response.contents[0]!.text as string)
|
|
73
|
-
|
|
74
|
-
for (const job of health.scheduler.jobs) {
|
|
75
|
-
expect(job).toHaveProperty('runCount')
|
|
76
|
-
expect(typeof job.runCount).toBe('number')
|
|
77
|
-
}
|
|
78
|
-
})
|
|
79
|
-
})
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* E2E Tests: Security & Limits
|
|
3
|
-
*
|
|
4
|
-
* Tests HTTP transport security hardening: security headers,
|
|
5
|
-
* body size limits, 404 handler, CORS, and HSTS.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { test, expect } from '@playwright/test'
|
|
9
|
-
import { startServer, stopServer } from './helpers.js'
|
|
10
|
-
|
|
11
|
-
test.describe('HTTP Transport Security & Limits', () => {
|
|
12
|
-
test('should return 404 Not Found for unknown endpoints', async ({ request }) => {
|
|
13
|
-
const response = await request.get('/non-existent-path')
|
|
14
|
-
expect(response.status()).toBe(404)
|
|
15
|
-
|
|
16
|
-
const body = await response.json()
|
|
17
|
-
expect(body).toHaveProperty('error', 'Not found')
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
test('should return 413 Payload Too Large for excessive POST bodies', async ({ request }) => {
|
|
21
|
-
// Generate a payload over 1 MB (1,048,576 bytes)
|
|
22
|
-
const bulkyData = 'A'.repeat(1024 * 1025) // ~1.025 MB string
|
|
23
|
-
|
|
24
|
-
const response = await request.post('/mcp', {
|
|
25
|
-
headers: {
|
|
26
|
-
Accept: 'application/json, text/event-stream',
|
|
27
|
-
},
|
|
28
|
-
data: {
|
|
29
|
-
jsonrpc: '2.0',
|
|
30
|
-
id: 1,
|
|
31
|
-
method: 'initialize',
|
|
32
|
-
params: { testData: bulkyData },
|
|
33
|
-
},
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
expect(response.status()).toBe(413)
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
test('should inject security headers on responses', async ({ request }) => {
|
|
40
|
-
const response = await request.get('/health')
|
|
41
|
-
expect(response.status()).toBe(200)
|
|
42
|
-
|
|
43
|
-
const headers = response.headers()
|
|
44
|
-
expect(headers['x-content-type-options']).toBe('nosniff')
|
|
45
|
-
expect(headers['x-frame-options']).toBe('DENY')
|
|
46
|
-
expect(headers['cache-control']).toBe('no-store, no-cache, must-revalidate')
|
|
47
|
-
expect(headers['content-security-policy']).toBe(
|
|
48
|
-
"default-src 'none'; frame-ancestors 'none'"
|
|
49
|
-
)
|
|
50
|
-
expect(headers['referrer-policy']).toBe('no-referrer')
|
|
51
|
-
expect(headers['permissions-policy']).toBe('camera=(), microphone=(), geolocation=()')
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
test('should respond with 204 to CORS preflight OPTIONS requests', async ({ request }) => {
|
|
55
|
-
const response = await request.fetch('/mcp', {
|
|
56
|
-
method: 'OPTIONS',
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
expect(response.status()).toBe(204)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
test('should include CORS headers on responses', async ({ request }) => {
|
|
63
|
-
const response = await request.get('/health')
|
|
64
|
-
const headers = response.headers()
|
|
65
|
-
|
|
66
|
-
// Default CORS origin is * (configurable via --cors-origin)
|
|
67
|
-
expect(headers['access-control-allow-origin']).toBe('*')
|
|
68
|
-
expect(headers['access-control-allow-methods']).toContain('POST')
|
|
69
|
-
expect(headers['access-control-allow-methods']).toContain('GET')
|
|
70
|
-
expect(headers['access-control-expose-headers']).toContain('mcp-session-id')
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
test('should NOT include HSTS header without enableHSTS config', async ({ request }) => {
|
|
74
|
-
// HSTS is now config-driven (enableHSTS: true), not header-sniffed.
|
|
75
|
-
// Without explicit config, X-Forwarded-Proto alone should NOT trigger HSTS.
|
|
76
|
-
const response = await request.get('/health', {
|
|
77
|
-
headers: {
|
|
78
|
-
'X-Forwarded-Proto': 'https',
|
|
79
|
-
},
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
expect(response.status()).toBe(200)
|
|
83
|
-
const headers = response.headers()
|
|
84
|
-
expect(headers['strict-transport-security']).toBeUndefined()
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
test('should NOT include HSTS header without X-Forwarded-Proto', async ({ request }) => {
|
|
88
|
-
const response = await request.get('/health')
|
|
89
|
-
expect(response.status()).toBe(200)
|
|
90
|
-
|
|
91
|
-
const headers = response.headers()
|
|
92
|
-
expect(headers['strict-transport-security']).toBeUndefined()
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
test('should include HSTS header when --enable-hsts is configured', async () => {
|
|
96
|
-
const HSTS_PORT = 3106
|
|
97
|
-
|
|
98
|
-
await startServer(HSTS_PORT, ['--enable-hsts'], 'hsts')
|
|
99
|
-
|
|
100
|
-
try {
|
|
101
|
-
const response = await fetch(`http://localhost:${HSTS_PORT}/health`)
|
|
102
|
-
expect(response.status).toBe(200)
|
|
103
|
-
|
|
104
|
-
const hsts = response.headers.get('strict-transport-security')
|
|
105
|
-
expect(hsts).toBeDefined()
|
|
106
|
-
expect(hsts).toContain('max-age=')
|
|
107
|
-
expect(hsts).toContain('includeSubDomains')
|
|
108
|
-
} finally {
|
|
109
|
-
stopServer(HSTS_PORT)
|
|
110
|
-
}
|
|
111
|
-
})
|
|
112
|
-
})
|