actual-mcp-server 0.6.52 → 0.6.55
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 +16 -12
- package/dist/package.json +6 -3
- package/dist/src/lib/config-registry.js +102 -0
- package/dist/src/lib/constants.js +3 -0
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -121,13 +121,13 @@ git clone https://github.com/agigante80/actual-mcp-server.git
|
|
|
121
121
|
cd actual-mcp-server
|
|
122
122
|
cp .env.example .env # fill in ACTUAL_SERVER_URL, ACTUAL_PASSWORD, ACTUAL_BUDGET_SYNC_ID
|
|
123
123
|
|
|
124
|
-
docker compose --profile production up -d #
|
|
124
|
+
docker compose --profile production up -d # production: MCP server listens on :3600
|
|
125
125
|
# or
|
|
126
126
|
docker compose --profile dev up -d # dev mode with hot-reload
|
|
127
|
-
# or
|
|
128
|
-
docker compose --profile fullstack up -d # includes Actual Budget server on :5006
|
|
129
127
|
```
|
|
130
128
|
|
|
129
|
+
> The compose file defines only the `dev` and `production` profiles. The MCP server listens on `:3600` directly: there is no bundled reverse proxy and no bundled Actual Budget server, so point `ACTUAL_SERVER_URL` at your own Actual instance. For TLS, enable native HTTPS with `MCP_ENABLE_HTTPS=true` (plus `MCP_HTTPS_CERT` and `MCP_HTTPS_KEY`), or front the server with your own reverse proxy.
|
|
130
|
+
|
|
131
131
|
### Option C: npm (HTTP server)
|
|
132
132
|
|
|
133
133
|
```bash
|
|
@@ -424,10 +424,11 @@ All configuration is via environment variables. Copy `.env.example` to `.env` to
|
|
|
424
424
|
| Variable | Default | Required | Description |
|
|
425
425
|
|----------|---------|----------|-------------|
|
|
426
426
|
| **Actual Budget Connection** ||||
|
|
427
|
-
| `ACTUAL_SERVER_URL` |
|
|
427
|
+
| `ACTUAL_SERVER_URL` | _(none)_ | Yes | URL of your Actual Budget server. Use the same URL you type in your browser: `http://localhost:5006` (local), `http://192.168.1.x:5006` (network), `https://actual.yourdomain.com` (domain), or `http://actual:5006` (container name if on the same Docker network) |
|
|
428
428
|
| `ACTUAL_PASSWORD` | _(none)_ | Yes | Password for Actual Budget server |
|
|
429
429
|
| `ACTUAL_BUDGET_SYNC_ID` | _(none)_ | Yes | Budget Sync ID from Actual (Settings then Sync ID) |
|
|
430
430
|
| `ACTUAL_BUDGET_PASSWORD` | _(none)_ | No | Optional encryption password for encrypted budgets |
|
|
431
|
+
| `ALLOW_INSECURE_UPSTREAM` | `false` | No | Allow an `http://` upstream even when `ACTUAL_BUDGET_PASSWORD` is set (#161). Off by default so a plaintext upstream plus an encryption password is refused |
|
|
431
432
|
| **MCP Server Settings** ||||
|
|
432
433
|
| `MCP_BRIDGE_PORT` | `3600` | No | Port for MCP server to listen on |
|
|
433
434
|
| `MCP_BRIDGE_BIND_HOST` | `0.0.0.0` | No | Host address to bind server to (`0.0.0.0` = all interfaces) |
|
|
@@ -436,13 +437,14 @@ All configuration is via environment variables. Copy `.env.example` to `.env` to
|
|
|
436
437
|
| `MCP_BRIDGE_PUBLIC_SCHEME` | auto-detected | No | Public scheme (`http` or `https`) |
|
|
437
438
|
| `MCP_BRIDGE_USE_TLS` | `false` | No | Set to `true` to advertise `https://` in the server URL (for reverse-proxy setups where TLS is terminated upstream) |
|
|
438
439
|
| **Transport Configuration** ||||
|
|
439
|
-
| `MCP_TRANSPORT_MODE` | `--http` | No | Transport mode
|
|
440
|
+
| `MCP_TRANSPORT_MODE` | `--http` | No | Transport mode. Only `--http` is a valid value; stdio is selected via the `--stdio` CLI flag, not this var |
|
|
440
441
|
| `MCP_HTTP_PATH` | `/http` | No | HTTP endpoint routing path |
|
|
441
442
|
| `MCP_BRIDGE_HTTP_PATH` | same as `MCP_HTTP_PATH` | No | Advertised HTTP path shown to clients (set when a reverse proxy rewrites the path) |
|
|
443
|
+
| `MCP_HTTP_BODY_LIMIT` | `512kb` | No | Maximum accepted JSON-RPC request body size (e.g. `512kb`, `1mb`) |
|
|
442
444
|
| **Session Management** ||||
|
|
443
445
|
| `USE_CONNECTION_POOL` | `true` | No | Enable session-based connection pooling |
|
|
444
446
|
| `MAX_CONCURRENT_SESSIONS` | `15` | No | Maximum concurrent MCP sessions allowed |
|
|
445
|
-
| `SESSION_IDLE_TIMEOUT_MINUTES` | `5`
|
|
447
|
+
| `SESSION_IDLE_TIMEOUT_MINUTES` | `5` | No | Minutes before idle session cleanup |
|
|
446
448
|
| **Security & Authentication** ||||
|
|
447
449
|
| `AUTH_PROVIDER` | `none` | No | Auth mode: `none` (static Bearer) or `oidc` (JWKS-validated JWT) |
|
|
448
450
|
| `MCP_SSE_AUTHORIZATION` | _(none)_ | No | Static Bearer token (`AUTH_PROVIDER=none`; highly recommended in production) |
|
|
@@ -455,19 +457,21 @@ All configuration is via environment variables. Copy `.env.example` to `.env` to
|
|
|
455
457
|
| `MCP_HTTPS_KEY` | _(none)_ | No | Path to PEM private key file (required when `MCP_ENABLE_HTTPS=true`) |
|
|
456
458
|
| **Logging Configuration** ||||
|
|
457
459
|
| `MCP_BRIDGE_STORE_LOGS` | `false` | No | Enable file logging (vs console only) |
|
|
458
|
-
| `MCP_BRIDGE_LOG_DIR` |
|
|
459
|
-
| `MCP_BRIDGE_LOG_LEVEL` | `debug` | No | Log level: `error`, `warn`, `info`, `debug` |
|
|
460
|
+
| `MCP_BRIDGE_LOG_DIR` | `app/logs` (beside the install) | No | Directory for log files (if `STORE_LOGS=true`). `.env.example` and Docker set it explicitly (e.g. `./logs`, `/app/logs`) |
|
|
461
|
+
| `MCP_BRIDGE_LOG_LEVEL` | `debug` (dev) / `info` (prod) | No | Log level: `error`, `warn`, `info`, `debug` |
|
|
462
|
+
| `LOG_FORMAT` | auto | No | Log output format: `json` or `pretty`. Precedence: explicit `LOG_FORMAT` wins, else `NODE_ENV=production` selects `json`, else `pretty` |
|
|
463
|
+
| `MCP_SERVICE_NAME` | `actual-mcp-server` | No | Service name stamped on every structured (json) log record |
|
|
460
464
|
| **Log Rotation** (when `MCP_BRIDGE_STORE_LOGS=true`) ||||
|
|
461
465
|
| `MCP_BRIDGE_MAX_FILES` | `14d` | No | Keep rotated logs for N days (e.g., `14d`, `30d`) |
|
|
462
466
|
| `MCP_BRIDGE_MAX_LOG_SIZE` | `20m` | No | Rotate when file reaches size (e.g., `20m`, `100m`) |
|
|
463
467
|
| `MCP_BRIDGE_ROTATE_DATEPATTERN` | `YYYY-MM-DD` | No | Date pattern for rotated log filenames |
|
|
464
468
|
| **Development & Debugging** ||||
|
|
465
|
-
| `DEBUG` |
|
|
466
|
-
| `LOG_LEVEL` |
|
|
469
|
+
| `DEBUG` | _(none)_ | No | Enable debug mode (verbose logging) when set to any truthy value |
|
|
470
|
+
| `LOG_LEVEL` | _(none)_ | No | Debug-detection toggle: set to `debug` to enable extra transport debug output. Distinct from `MCP_BRIDGE_LOG_LEVEL` (the winston level); has no default and is not itself a log level |
|
|
467
471
|
| `MCP_BRIDGE_DEBUG_TRANSPORT` | `false` | No | Enable transport-level debug logging |
|
|
468
472
|
| **Advanced/Internal** ||||
|
|
469
473
|
| `ACTUAL_API_CONCURRENCY` | `5` | No | Max concurrent Actual API operations |
|
|
470
|
-
| `NODE_ENV` | `production` | No | Node environment; `production
|
|
474
|
+
| `NODE_ENV` | _(none)_ / `production` | No | Node environment. No app default; the Docker image sets `production`, which selects json logs and hides stack traces in error responses |
|
|
471
475
|
| `VERSION` | auto-detected | No | Server version (auto-set by build/Docker) |
|
|
472
476
|
| `TZ` | `UTC` | No | Timezone for timestamps (e.g., `America/New_York`) |
|
|
473
477
|
|
|
@@ -751,4 +755,4 @@ The software is provided **as-is**, without warranty of any kind. The author acc
|
|
|
751
755
|
|
|
752
756
|
---
|
|
753
757
|
|
|
754
|
-
**Version:** 0.6.
|
|
758
|
+
**Version:** 0.6.55 | **Tool Count:** 71 (verified LibreChat-compatible)
|
package/dist/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "actual-mcp-server",
|
|
3
3
|
"displayName": "Actual MCP Server",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.55",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.0.0",
|
|
7
7
|
"npm": ">=10.0.0"
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"verify-tools": "npm run build && node scripts/verify-tools.js",
|
|
31
31
|
"check:coverage": "node scripts/list-actual-api-methods.mjs",
|
|
32
32
|
"direct-sync": "node scripts/direct-sync/bank-sync-direct.mjs",
|
|
33
|
-
"test:unit-js": "node tests/unit/transactions_create.test.js && node tests/unit/generated_tools.smoke.test.js && node tests/unit/schema_validation.test.js && node tests/unit/config_https_validation.test.js && node tests/unit/config_data_dir.test.js && node tests/unit/port_alignment.test.js && node tests/unit/dockerfile_data_dir_alignment.test.js && node tests/unit/config_insecure_upstream.test.js && node tests/unit/auth-acl.test.js && node tests/unit/bug76.test.js && node tests/unit/budgets_setAmount.test.js && node tests/unit/budgets_transfer.test.js && node tests/unit/transactions_uncategorized.test.js && node tests/unit/httpServer_session_init.test.js && node tests/unit/httpServer_session_not_found.test.js && node tests/unit/manual_mcp_client_retry.test.js && node tests/unit/manual_mcp_client_session.test.js && node tests/unit/manual_mcp_client_circuit.test.js && node tests/unit/manual_runner_killswitch.test.js && node tests/unit/adapter_auth_rate_limit.test.js && node tests/unit/adapter_session_reuse.test.js && node tests/unit/retry_classifier.test.js && node tests/unit/adapter_module_surface.test.js && node tests/unit/adapter_nonidempotent_no_retry.test.js && node tests/unit/pool_liveness.test.js && node tests/unit/pool_shutdown_all.test.js && node tests/unit/query_where_operators.test.js && node tests/unit/query_run_validation.test.js && node tests/unit/adapter_with_write_session.test.js && node tests/unit/category_groups_delete.test.js && node tests/unit/rules_delete.test.js && node tests/unit/schedules_delete.test.js && node tests/unit/payees_delete.test.js && node tests/unit/rules_create_or_update.test.js && node tests/unit/unhandled-rejection.test.js && node tests/unit/rejection-allowlist-purity.test.js && node tests/unit/httpServer_bearer_auth.test.js && node tests/unit/httpServer_oidc_audience.test.js && node tests/unit/httpServer_oidc_auth_verification.test.js && node tests/unit/httpServer_body_limit.test.js && node tests/unit/adapter_write_pool_cooperation.test.js && node tests/unit/budget_acl_enforcement.test.js && node tests/unit/budget_preference_store.test.js && node tests/unit/budget_preference_restore.test.js && node tests/unit/tags_list.test.js && node tests/unit/tags_create.test.js && node tests/unit/tags_update.test.js && node tests/unit/tags_delete.test.js && node tests/unit/notes_get.test.js && node tests/unit/notes_update.test.js && node tests/unit/payees_common_list.test.js && node tests/unit/transactions_update_guard.test.js && node tests/unit/entities_search.test.js && node tests/unit/transactions_import_schema.test.js && node tests/unit/tool_schema_shape.test.js && node tests/unit/zod_error_format.test.js && node tests/unit/tool_count_sync.test.js && node tests/unit/stdio_transport.test.js && node tests/unit/logger_structured.test.js && node tests/unit/logger_redaction.test.js && node tests/unit/logger_correlation.test.js && node tests/unit/check_coverage.test.js",
|
|
33
|
+
"test:unit-js": "node tests/unit/transactions_create.test.js && node tests/unit/generated_tools.smoke.test.js && node tests/unit/schema_validation.test.js && node tests/unit/config_https_validation.test.js && node tests/unit/config_data_dir.test.js && node tests/unit/config_drift.test.js && node tests/unit/port_alignment.test.js && node tests/unit/dockerfile_data_dir_alignment.test.js && node tests/unit/compose_profile_sync.test.js && node tests/unit/advertised_tools_sync.test.js && node tests/unit/knip_config.test.js && node tests/unit/config_insecure_upstream.test.js && node tests/unit/auth-acl.test.js && node tests/unit/bug76.test.js && node tests/unit/budgets_setAmount.test.js && node tests/unit/budgets_transfer.test.js && node tests/unit/transactions_uncategorized.test.js && node tests/unit/httpServer_session_init.test.js && node tests/unit/httpServer_session_not_found.test.js && node tests/unit/manual_mcp_client_retry.test.js && node tests/unit/manual_mcp_client_session.test.js && node tests/unit/manual_mcp_client_circuit.test.js && node tests/unit/manual_runner_killswitch.test.js && node tests/unit/adapter_auth_rate_limit.test.js && node tests/unit/adapter_session_reuse.test.js && node tests/unit/retry_classifier.test.js && node tests/unit/adapter_module_surface.test.js && node tests/unit/adapter_nonidempotent_no_retry.test.js && node tests/unit/pool_liveness.test.js && node tests/unit/pool_shutdown_all.test.js && node tests/unit/query_where_operators.test.js && node tests/unit/query_run_validation.test.js && node tests/unit/adapter_with_write_session.test.js && node tests/unit/category_groups_delete.test.js && node tests/unit/rules_delete.test.js && node tests/unit/schedules_delete.test.js && node tests/unit/payees_delete.test.js && node tests/unit/rules_create_or_update.test.js && node tests/unit/unhandled-rejection.test.js && node tests/unit/rejection-allowlist-purity.test.js && node tests/unit/httpServer_bearer_auth.test.js && node tests/unit/httpServer_oidc_audience.test.js && node tests/unit/httpServer_oidc_auth_verification.test.js && node tests/unit/httpServer_body_limit.test.js && node tests/unit/adapter_write_pool_cooperation.test.js && node tests/unit/budget_acl_enforcement.test.js && node tests/unit/budget_preference_store.test.js && node tests/unit/budget_preference_restore.test.js && node tests/unit/tags_list.test.js && node tests/unit/tags_create.test.js && node tests/unit/tags_update.test.js && node tests/unit/tags_delete.test.js && node tests/unit/notes_get.test.js && node tests/unit/notes_update.test.js && node tests/unit/payees_common_list.test.js && node tests/unit/transactions_update_guard.test.js && node tests/unit/entities_search.test.js && node tests/unit/transactions_import_schema.test.js && node tests/unit/tool_schema_shape.test.js && node tests/unit/zod_error_format.test.js && node tests/unit/tool_count_sync.test.js && node tests/unit/stdio_transport.test.js && node tests/unit/logger_structured.test.js && node tests/unit/logger_redaction.test.js && node tests/unit/logger_correlation.test.js && node tests/unit/check_coverage.test.js",
|
|
34
34
|
"test:adapter": "npm run build && node dist/src/tests_adapter_runner.js",
|
|
35
35
|
"test:e2e": "npx playwright test",
|
|
36
36
|
"test:e2e:docker": "./tests/e2e/run-docker-e2e.sh",
|
|
@@ -55,7 +55,9 @@
|
|
|
55
55
|
"release:major": "npm run version:bump -- major",
|
|
56
56
|
"release:minor": "npm run version:bump -- minor",
|
|
57
57
|
"release:patch": "npm run version:bump -- patch",
|
|
58
|
-
"tool-count": "node scripts/tool-count.mjs"
|
|
58
|
+
"tool-count": "node scripts/tool-count.mjs",
|
|
59
|
+
"config-drift": "npm run build && node scripts/config-drift.mjs",
|
|
60
|
+
"knip": "knip --no-exit-code"
|
|
59
61
|
},
|
|
60
62
|
"dependencies": {
|
|
61
63
|
"@actual-app/api": "^26.6.0",
|
|
@@ -77,6 +79,7 @@
|
|
|
77
79
|
"@playwright/test": "^1.60.0",
|
|
78
80
|
"@types/express": "^5.0.3",
|
|
79
81
|
"@types/node": "^25.9.2",
|
|
82
|
+
"knip": "^6.16.1",
|
|
80
83
|
"node-fetch": "^3.3.2",
|
|
81
84
|
"tsconfig-paths": "^4.2.0",
|
|
82
85
|
"typescript": "^6.0.3"
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// src/lib/config-registry.ts (#231)
|
|
2
|
+
//
|
|
3
|
+
// The single in-code record of every configuration variable that is NOT a Zod
|
|
4
|
+
// schema key in src/config.ts but is still read from process.env somewhere in
|
|
5
|
+
// src/. Together with `Object.keys(configSchema.shape)`, this allowlist is the
|
|
6
|
+
// canonical set of configuration variables the server understands.
|
|
7
|
+
//
|
|
8
|
+
// Why an allowlist instead of promoting everything into the schema: most of these
|
|
9
|
+
// are read before src/config.ts loads (src/logger.ts, see logger.ts:53) or in the
|
|
10
|
+
// deferred-config entry src/index.ts (which reads process.env directly to keep the
|
|
11
|
+
// fast `--help` exit, the decision recorded for #230). Promoting them risks a
|
|
12
|
+
// load-order regression, so they stay raw but DOCUMENTED here, with a reason and
|
|
13
|
+
// read site. Migrating any raw read into the validated config object is deliberately
|
|
14
|
+
// out of scope for #231 (a separate, behaviour-sensitive change).
|
|
15
|
+
//
|
|
16
|
+
// This file is data only. It imports nothing from src/config.ts so it carries no
|
|
17
|
+
// process.env requirement and can be imported by the drift guard and its unit test.
|
|
18
|
+
/**
|
|
19
|
+
* Variables read from process.env in src/ that are NOT configSchema keys.
|
|
20
|
+
* Grouped by reason in the comments; the array is the machine-readable source.
|
|
21
|
+
*/
|
|
22
|
+
export const RAW_ENV_ALLOWLIST = [
|
|
23
|
+
// Logger bootstrap: read in src/logger.ts before src/config.ts loads.
|
|
24
|
+
{ name: 'MCP_BRIDGE_STORE_LOGS', reason: 'logger bootstrap (before config loads)', readSite: 'logger.ts:14' },
|
|
25
|
+
{ name: 'MCP_BRIDGE_LOG_DIR', reason: 'logger bootstrap (before config loads)', readSite: 'logger.ts:15' },
|
|
26
|
+
{ name: 'MCP_BRIDGE_ROTATE_DATEPATTERN', reason: 'logger bootstrap (before config loads)', readSite: 'logger.ts:21' },
|
|
27
|
+
{ name: 'MCP_BRIDGE_MAX_LOG_SIZE', reason: 'logger bootstrap (before config loads)', readSite: 'logger.ts:22' },
|
|
28
|
+
{ name: 'MCP_BRIDGE_MAX_FILES', reason: 'logger bootstrap (before config loads)', readSite: 'logger.ts:23' },
|
|
29
|
+
{ name: 'LOG_FORMAT', reason: 'logger bootstrap, read via resolveLogConfig(env)', readSite: 'logger.ts:74' },
|
|
30
|
+
{ name: 'MCP_BRIDGE_LOG_LEVEL', reason: 'logger bootstrap, read via resolveLogConfig(env)', readSite: 'logger.ts:77' },
|
|
31
|
+
{ name: 'MCP_SERVICE_NAME', reason: 'logger bootstrap, read via resolveLogConfig(env)', readSite: 'logger.ts:78' },
|
|
32
|
+
{ name: 'MCP_STDIO_MODE', reason: 'mirrors the --stdio CLI flag, set in-process before the logger import; not a .env knob', readSite: 'logger.ts:345, index.ts', documented: false },
|
|
33
|
+
// Deferred-config entry: read in src/index.ts to preserve the fast --help exit (#230).
|
|
34
|
+
{ name: 'MCP_BRIDGE_BIND_HOST', reason: 'deferred-config entry (index.ts reads process.env directly, #230)', readSite: 'index.ts' },
|
|
35
|
+
{ name: 'MCP_HTTP_PATH', reason: 'deferred-config entry; the path the server LISTENS on', readSite: 'index.ts:195' },
|
|
36
|
+
{ name: 'MCP_BRIDGE_HTTP_PATH', reason: 'deferred-config entry; the path ADVERTISED to clients, falls back to MCP_HTTP_PATH', readSite: 'index.ts:281' },
|
|
37
|
+
{ name: 'MCP_BRIDGE_PUBLIC_HOST', reason: 'deferred-config entry; advertised public host', readSite: 'index.ts:269, httpServer.ts:581' },
|
|
38
|
+
{ name: 'MCP_BRIDGE_PUBLIC_SCHEME', reason: 'deferred-config entry; advertised scheme override', readSite: 'index.ts' },
|
|
39
|
+
{ name: 'MCP_BRIDGE_USE_TLS', reason: 'deprecated alias of MCP_ENABLE_HTTPS; affects only advertised-scheme detection', readSite: 'index.ts:277' },
|
|
40
|
+
{ name: 'MCP_BRIDGE_DEBUG_TRANSPORT', reason: 'transport debug flag, read pre-config', readSite: 'index.ts, utils.ts' },
|
|
41
|
+
// Framework / internal: not user-facing config knobs.
|
|
42
|
+
{ name: 'NODE_ENV', reason: 'framework var; selects prod log format and prod behaviours', readSite: 'httpServer.ts, logger.ts (resolveLogConfig)' },
|
|
43
|
+
{ name: 'DEBUG', reason: 'framework debug toggle', readSite: 'utils.ts, index.ts, httpServer_testing.ts' },
|
|
44
|
+
{ name: 'LOG_LEVEL', reason: 'debug-detection toggle (distinct from MCP_BRIDGE_LOG_LEVEL, the winston level)', readSite: 'utils.ts' },
|
|
45
|
+
{ name: 'DOTENV_CONFIG_QUIET', reason: 'dotenv internal flag, not an operator knob', readSite: 'index.ts', documented: false },
|
|
46
|
+
{ name: 'VERSION', reason: 'build-time version arg, injected by the Docker build, not an operator knob', readSite: 'index.ts, server_info.ts', documented: false },
|
|
47
|
+
// Domain-time: read after config loads; future candidates for schema promotion.
|
|
48
|
+
{ name: 'ACTUAL_API_CONCURRENCY', reason: 'adapter concurrency tuning; future schema-promotion candidate', readSite: 'lib/actual-adapter/concurrency.ts' },
|
|
49
|
+
{ name: 'SESSION_IDLE_TIMEOUT_MINUTES', reason: 'pool idle timeout; future schema-promotion candidate', readSite: 'lib/ActualConnectionPool.ts' },
|
|
50
|
+
{ name: 'USE_CONNECTION_POOL', reason: 'pool toggle; future schema-promotion candidate', readSite: 'actualConnection.ts' },
|
|
51
|
+
];
|
|
52
|
+
/**
|
|
53
|
+
* Schema keys that are ALSO read directly from process.env at a second site. These
|
|
54
|
+
* are validated by configSchema (so they are canonical via schema membership), but
|
|
55
|
+
* the matrix records their raw read site for completeness. Migrating these reads to
|
|
56
|
+
* config.X is the out-of-scope follow-up.
|
|
57
|
+
*/
|
|
58
|
+
export const SCHEMA_VARS_ALSO_READ_RAW = [
|
|
59
|
+
{ name: 'MCP_BRIDGE_PORT', readSite: 'index.ts:194' },
|
|
60
|
+
{ name: 'MCP_ENABLE_HTTPS', readSite: 'index.ts:277,286' },
|
|
61
|
+
{ name: 'MCP_HTTPS_CERT', readSite: 'index.ts:287' },
|
|
62
|
+
{ name: 'MCP_HTTPS_KEY', readSite: 'index.ts:288' },
|
|
63
|
+
{ name: 'MAX_CONCURRENT_SESSIONS', readSite: 'ActualConnectionPool.ts:60' },
|
|
64
|
+
{ name: 'ACTUAL_BUDGET_PASSWORD', readSite: 'actualConnection.ts:33, ActualConnectionPool.ts:255,338' },
|
|
65
|
+
];
|
|
66
|
+
/**
|
|
67
|
+
* Prefixes of dynamic variable families enumerated at runtime, not declared one by
|
|
68
|
+
* one. `.env.example` documents example members (BUDGET_1_*, BUDGET_2_*, ...); the
|
|
69
|
+
* drift guard collapses any name starting with one of these to the family.
|
|
70
|
+
*/
|
|
71
|
+
export const DYNAMIC_ENV_FAMILIES = ['BUDGET_'];
|
|
72
|
+
/**
|
|
73
|
+
* Variables documented for the operator (e.g. in Docker) but read by the OS or
|
|
74
|
+
* runtime, not by the app. The drift guard allows these in docs without requiring a
|
|
75
|
+
* schema/allowlist entry.
|
|
76
|
+
*/
|
|
77
|
+
export const OS_LEVEL_ENV = ['TZ'];
|
|
78
|
+
/**
|
|
79
|
+
* The canonical set of configuration variable names the server understands:
|
|
80
|
+
* every Zod schema key united with every raw-read allowlist name. Pass the schema
|
|
81
|
+
* keys in (e.g. `Object.keys(configSchema.shape)`) so this module stays free of any
|
|
82
|
+
* import from src/config.ts and its process.env requirement.
|
|
83
|
+
*/
|
|
84
|
+
export function canonicalConfigVars(schemaKeys) {
|
|
85
|
+
return new Set([...schemaKeys, ...RAW_ENV_ALLOWLIST.map((v) => v.name)]);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The subset of canonical vars that MUST appear in the user-facing docs
|
|
89
|
+
* (.env.example and the README env table): every schema key, plus every allowlist
|
|
90
|
+
* entry not flagged `documented: false`. Internal vars (build arg, dotenv flag,
|
|
91
|
+
* CLI-flag mirror) are accounted for by the enumeration but exempt from the docs.
|
|
92
|
+
*/
|
|
93
|
+
export function documentedConfigVars(schemaKeys) {
|
|
94
|
+
return new Set([
|
|
95
|
+
...schemaKeys,
|
|
96
|
+
...RAW_ENV_ALLOWLIST.filter((v) => v.documented !== false).map((v) => v.name),
|
|
97
|
+
]);
|
|
98
|
+
}
|
|
99
|
+
/** True if `name` belongs to a dynamic family (e.g. BUDGET_2_NAME). */
|
|
100
|
+
export function isDynamicFamilyVar(name) {
|
|
101
|
+
return DYNAMIC_ENV_FAMILIES.some((prefix) => name.startsWith(prefix));
|
|
102
|
+
}
|
|
@@ -65,6 +65,9 @@ export const DEFAULT_BIND_HOST = 'localhost';
|
|
|
65
65
|
* Default HTTP port for MCP server. Canonical default is 3600 (#230): it matches
|
|
66
66
|
* the listen-port fallback in src/index.ts, the Dockerfile EXPOSE/HEALTHCHECK, the
|
|
67
67
|
* published image, .env.example, and every deployment guide.
|
|
68
|
+
*
|
|
69
|
+
* @public Consumed by the text-parsing port_alignment guard (tests/unit/port_alignment.test.js),
|
|
70
|
+
* not by a runtime import, so Knip cannot see the usage. Alive: removing it breaks the guard.
|
|
68
71
|
*/
|
|
69
72
|
export const DEFAULT_HTTP_PORT = 3600;
|
|
70
73
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "actual-mcp-server",
|
|
3
3
|
"displayName": "Actual MCP Server",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.55",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.0.0",
|
|
7
7
|
"npm": ">=10.0.0"
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"verify-tools": "npm run build && node scripts/verify-tools.js",
|
|
31
31
|
"check:coverage": "node scripts/list-actual-api-methods.mjs",
|
|
32
32
|
"direct-sync": "node scripts/direct-sync/bank-sync-direct.mjs",
|
|
33
|
-
"test:unit-js": "node tests/unit/transactions_create.test.js && node tests/unit/generated_tools.smoke.test.js && node tests/unit/schema_validation.test.js && node tests/unit/config_https_validation.test.js && node tests/unit/config_data_dir.test.js && node tests/unit/port_alignment.test.js && node tests/unit/dockerfile_data_dir_alignment.test.js && node tests/unit/config_insecure_upstream.test.js && node tests/unit/auth-acl.test.js && node tests/unit/bug76.test.js && node tests/unit/budgets_setAmount.test.js && node tests/unit/budgets_transfer.test.js && node tests/unit/transactions_uncategorized.test.js && node tests/unit/httpServer_session_init.test.js && node tests/unit/httpServer_session_not_found.test.js && node tests/unit/manual_mcp_client_retry.test.js && node tests/unit/manual_mcp_client_session.test.js && node tests/unit/manual_mcp_client_circuit.test.js && node tests/unit/manual_runner_killswitch.test.js && node tests/unit/adapter_auth_rate_limit.test.js && node tests/unit/adapter_session_reuse.test.js && node tests/unit/retry_classifier.test.js && node tests/unit/adapter_module_surface.test.js && node tests/unit/adapter_nonidempotent_no_retry.test.js && node tests/unit/pool_liveness.test.js && node tests/unit/pool_shutdown_all.test.js && node tests/unit/query_where_operators.test.js && node tests/unit/query_run_validation.test.js && node tests/unit/adapter_with_write_session.test.js && node tests/unit/category_groups_delete.test.js && node tests/unit/rules_delete.test.js && node tests/unit/schedules_delete.test.js && node tests/unit/payees_delete.test.js && node tests/unit/rules_create_or_update.test.js && node tests/unit/unhandled-rejection.test.js && node tests/unit/rejection-allowlist-purity.test.js && node tests/unit/httpServer_bearer_auth.test.js && node tests/unit/httpServer_oidc_audience.test.js && node tests/unit/httpServer_oidc_auth_verification.test.js && node tests/unit/httpServer_body_limit.test.js && node tests/unit/adapter_write_pool_cooperation.test.js && node tests/unit/budget_acl_enforcement.test.js && node tests/unit/budget_preference_store.test.js && node tests/unit/budget_preference_restore.test.js && node tests/unit/tags_list.test.js && node tests/unit/tags_create.test.js && node tests/unit/tags_update.test.js && node tests/unit/tags_delete.test.js && node tests/unit/notes_get.test.js && node tests/unit/notes_update.test.js && node tests/unit/payees_common_list.test.js && node tests/unit/transactions_update_guard.test.js && node tests/unit/entities_search.test.js && node tests/unit/transactions_import_schema.test.js && node tests/unit/tool_schema_shape.test.js && node tests/unit/zod_error_format.test.js && node tests/unit/tool_count_sync.test.js && node tests/unit/stdio_transport.test.js && node tests/unit/logger_structured.test.js && node tests/unit/logger_redaction.test.js && node tests/unit/logger_correlation.test.js && node tests/unit/check_coverage.test.js",
|
|
33
|
+
"test:unit-js": "node tests/unit/transactions_create.test.js && node tests/unit/generated_tools.smoke.test.js && node tests/unit/schema_validation.test.js && node tests/unit/config_https_validation.test.js && node tests/unit/config_data_dir.test.js && node tests/unit/config_drift.test.js && node tests/unit/port_alignment.test.js && node tests/unit/dockerfile_data_dir_alignment.test.js && node tests/unit/compose_profile_sync.test.js && node tests/unit/advertised_tools_sync.test.js && node tests/unit/knip_config.test.js && node tests/unit/config_insecure_upstream.test.js && node tests/unit/auth-acl.test.js && node tests/unit/bug76.test.js && node tests/unit/budgets_setAmount.test.js && node tests/unit/budgets_transfer.test.js && node tests/unit/transactions_uncategorized.test.js && node tests/unit/httpServer_session_init.test.js && node tests/unit/httpServer_session_not_found.test.js && node tests/unit/manual_mcp_client_retry.test.js && node tests/unit/manual_mcp_client_session.test.js && node tests/unit/manual_mcp_client_circuit.test.js && node tests/unit/manual_runner_killswitch.test.js && node tests/unit/adapter_auth_rate_limit.test.js && node tests/unit/adapter_session_reuse.test.js && node tests/unit/retry_classifier.test.js && node tests/unit/adapter_module_surface.test.js && node tests/unit/adapter_nonidempotent_no_retry.test.js && node tests/unit/pool_liveness.test.js && node tests/unit/pool_shutdown_all.test.js && node tests/unit/query_where_operators.test.js && node tests/unit/query_run_validation.test.js && node tests/unit/adapter_with_write_session.test.js && node tests/unit/category_groups_delete.test.js && node tests/unit/rules_delete.test.js && node tests/unit/schedules_delete.test.js && node tests/unit/payees_delete.test.js && node tests/unit/rules_create_or_update.test.js && node tests/unit/unhandled-rejection.test.js && node tests/unit/rejection-allowlist-purity.test.js && node tests/unit/httpServer_bearer_auth.test.js && node tests/unit/httpServer_oidc_audience.test.js && node tests/unit/httpServer_oidc_auth_verification.test.js && node tests/unit/httpServer_body_limit.test.js && node tests/unit/adapter_write_pool_cooperation.test.js && node tests/unit/budget_acl_enforcement.test.js && node tests/unit/budget_preference_store.test.js && node tests/unit/budget_preference_restore.test.js && node tests/unit/tags_list.test.js && node tests/unit/tags_create.test.js && node tests/unit/tags_update.test.js && node tests/unit/tags_delete.test.js && node tests/unit/notes_get.test.js && node tests/unit/notes_update.test.js && node tests/unit/payees_common_list.test.js && node tests/unit/transactions_update_guard.test.js && node tests/unit/entities_search.test.js && node tests/unit/transactions_import_schema.test.js && node tests/unit/tool_schema_shape.test.js && node tests/unit/zod_error_format.test.js && node tests/unit/tool_count_sync.test.js && node tests/unit/stdio_transport.test.js && node tests/unit/logger_structured.test.js && node tests/unit/logger_redaction.test.js && node tests/unit/logger_correlation.test.js && node tests/unit/check_coverage.test.js",
|
|
34
34
|
"test:adapter": "npm run build && node dist/src/tests_adapter_runner.js",
|
|
35
35
|
"test:e2e": "npx playwright test",
|
|
36
36
|
"test:e2e:docker": "./tests/e2e/run-docker-e2e.sh",
|
|
@@ -55,7 +55,9 @@
|
|
|
55
55
|
"release:major": "npm run version:bump -- major",
|
|
56
56
|
"release:minor": "npm run version:bump -- minor",
|
|
57
57
|
"release:patch": "npm run version:bump -- patch",
|
|
58
|
-
"tool-count": "node scripts/tool-count.mjs"
|
|
58
|
+
"tool-count": "node scripts/tool-count.mjs",
|
|
59
|
+
"config-drift": "npm run build && node scripts/config-drift.mjs",
|
|
60
|
+
"knip": "knip --no-exit-code"
|
|
59
61
|
},
|
|
60
62
|
"dependencies": {
|
|
61
63
|
"@actual-app/api": "^26.6.0",
|
|
@@ -77,6 +79,7 @@
|
|
|
77
79
|
"@playwright/test": "^1.60.0",
|
|
78
80
|
"@types/express": "^5.0.3",
|
|
79
81
|
"@types/node": "^25.9.2",
|
|
82
|
+
"knip": "^6.16.1",
|
|
80
83
|
"node-fetch": "^3.3.2",
|
|
81
84
|
"tsconfig-paths": "^4.2.0",
|
|
82
85
|
"typescript": "^6.0.3"
|