@coffeerunhobby/mcp-ha-connect 2.2.1 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +1 -1
- package/README.md +24 -2
- package/dist/omadaClient/accessControl.d.ts +290 -0
- package/dist/omadaClient/accessControl.js +509 -0
- package/dist/omadaClient/accessControl.js.map +1 -0
- package/dist/omadaClient/client.d.ts +6 -1
- package/dist/omadaClient/client.js +12 -1
- package/dist/omadaClient/client.js.map +1 -1
- package/dist/omadaClient/diagnose.d.ts +68 -0
- package/dist/omadaClient/diagnose.js +164 -0
- package/dist/omadaClient/diagnose.js.map +1 -0
- package/dist/omadaClient/index.d.ts +9 -0
- package/dist/omadaClient/index.js +19 -0
- package/dist/omadaClient/index.js.map +1 -1
- package/dist/omadaClient/macGroups.d.ts +58 -0
- package/dist/omadaClient/macGroups.js +110 -0
- package/dist/omadaClient/macGroups.js.map +1 -0
- package/dist/omadaClient/serialize.d.ts +13 -0
- package/dist/omadaClient/serialize.js +29 -0
- package/dist/omadaClient/serialize.js.map +1 -0
- package/dist/omadaClient/timeRange.d.ts +41 -0
- package/dist/omadaClient/timeRange.js +109 -0
- package/dist/omadaClient/timeRange.js.map +1 -0
- package/dist/tools/infra/actions.d.ts +1 -1
- package/dist/tools/infra/actions.js +1 -1
- package/dist/tools/omada/accessControl.d.ts +151 -0
- package/dist/tools/omada/accessControl.js +158 -0
- package/dist/tools/omada/accessControl.js.map +1 -0
- package/dist/tools/omada/index.js +9 -0
- package/dist/tools/omada/index.js.map +1 -1
- package/dist/tools/omada/macGroups.d.ts +19 -0
- package/dist/tools/omada/macGroups.js +77 -0
- package/dist/tools/omada/macGroups.js.map +1 -0
- package/dist/tools/omada/namespace.js +16 -0
- package/dist/tools/omada/namespace.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -1
- package/.codex/review-rules.md +0 -16
- package/.dockerignore +0 -8
- package/.gitattributes +0 -30
- package/.github/workflows/ci.yml +0 -193
- package/AGENTS.md +0 -389
- package/Dockerfile +0 -50
- package/docker-compose.yml +0 -23
- package/docs/CHANGELOG.md +0 -341
- package/docs/COVERAGE.md +0 -219
- package/docs/QUICK_START.md +0 -240
- package/eslint.config.js +0 -33
- package/n8n/ai-agent-safety-monitor.json +0 -355
- package/openapi.json +0 -1259
- package/scripts/check-version-sync.mjs +0 -69
- package/scripts/generate-jwt.ts +0 -121
- package/src/config.ts +0 -440
- package/src/haClient/automations.ts +0 -261
- package/src/haClient/calendars.ts +0 -94
- package/src/haClient/config.ts +0 -52
- package/src/haClient/devices.ts +0 -653
- package/src/haClient/entities.ts +0 -128
- package/src/haClient/events.ts +0 -689
- package/src/haClient/history.ts +0 -73
- package/src/haClient/index.ts +0 -336
- package/src/haClient/request.ts +0 -142
- package/src/haClient/services.ts +0 -45
- package/src/haClient/states.ts +0 -60
- package/src/haClient/updates.ts +0 -58
- package/src/haClient/wsCommand.ts +0 -44
- package/src/index.ts +0 -164
- package/src/localAI/index.ts +0 -88
- package/src/localAI/prompts.ts +0 -50
- package/src/localAI/providers/base.ts +0 -120
- package/src/localAI/providers/ollama.ts +0 -78
- package/src/localAI/providers/openai.ts +0 -86
- package/src/localAI/types.ts +0 -67
- package/src/omadaClient/auth.ts +0 -178
- package/src/omadaClient/client.ts +0 -337
- package/src/omadaClient/device.ts +0 -118
- package/src/omadaClient/index.ts +0 -310
- package/src/omadaClient/network.ts +0 -284
- package/src/omadaClient/request.ts +0 -365
- package/src/omadaClient/security.ts +0 -51
- package/src/omadaClient/site.ts +0 -344
- package/src/ownerQuestions/service.ts +0 -536
- package/src/permissions/index.ts +0 -143
- package/src/resources/index.ts +0 -213
- package/src/server/auth.ts +0 -175
- package/src/server/chatFace.ts +0 -789
- package/src/server/chatSlice.ts +0 -57
- package/src/server/common.ts +0 -170
- package/src/server/eventSubscription.ts +0 -343
- package/src/server/http.ts +0 -626
- package/src/server/instructions.ts +0 -97
- package/src/server/rateLimiter.ts +0 -227
- package/src/server/stdio.ts +0 -41
- package/src/server/stream.ts +0 -205
- package/src/tools/ai/analyzeSensors.ts +0 -33
- package/src/tools/ai/index.ts +0 -20
- package/src/tools/common.ts +0 -442
- package/src/tools/homeassistant/askOwner.ts +0 -133
- package/src/tools/homeassistant/automationControls.ts +0 -66
- package/src/tools/homeassistant/calendar.ts +0 -97
- package/src/tools/homeassistant/callService.ts +0 -25
- package/src/tools/homeassistant/controlClimate.ts +0 -68
- package/src/tools/homeassistant/controlCover.ts +0 -48
- package/src/tools/homeassistant/controlFan.ts +0 -44
- package/src/tools/homeassistant/controlLight.ts +0 -38
- package/src/tools/homeassistant/controlMediaPlayer.ts +0 -50
- package/src/tools/homeassistant/createAutomation.ts +0 -35
- package/src/tools/homeassistant/deleteAutomation.ts +0 -24
- package/src/tools/homeassistant/entityAction.ts +0 -35
- package/src/tools/homeassistant/entityGuard.ts +0 -28
- package/src/tools/homeassistant/getAllSensors.ts +0 -46
- package/src/tools/homeassistant/getAutomationTrace.ts +0 -30
- package/src/tools/homeassistant/getDomainSummary.ts +0 -29
- package/src/tools/homeassistant/getEntitiesByDomain.ts +0 -56
- package/src/tools/homeassistant/getHistory.ts +0 -24
- package/src/tools/homeassistant/getState.ts +0 -24
- package/src/tools/homeassistant/getStates.ts +0 -46
- package/src/tools/homeassistant/getVersion.ts +0 -21
- package/src/tools/homeassistant/index.ts +0 -121
- package/src/tools/homeassistant/listAutomations.ts +0 -35
- package/src/tools/homeassistant/listEntities.ts +0 -44
- package/src/tools/homeassistant/listPersons.ts +0 -46
- package/src/tools/homeassistant/sceneAndScript.ts +0 -53
- package/src/tools/homeassistant/searchEntities.ts +0 -58
- package/src/tools/homeassistant/sendNotification.ts +0 -179
- package/src/tools/homeassistant/systemTools.ts +0 -52
- package/src/tools/homeassistant/triggerAutomation.ts +0 -24
- package/src/tools/index.ts +0 -78
- package/src/tools/infra/actions.ts +0 -95
- package/src/tools/infra/index.ts +0 -138
- package/src/tools/omada/blockClient.ts +0 -28
- package/src/tools/omada/cyclePoePort.ts +0 -32
- package/src/tools/omada/deleteClient.ts +0 -27
- package/src/tools/omada/disableClientRateLimit.ts +0 -23
- package/src/tools/omada/getClient.ts +0 -14
- package/src/tools/omada/getDevice.ts +0 -14
- package/src/tools/omada/getFirewallSetting.ts +0 -14
- package/src/tools/omada/getInternetInfo.ts +0 -14
- package/src/tools/omada/getLanNetworkList.ts +0 -14
- package/src/tools/omada/getLanProfileList.ts +0 -14
- package/src/tools/omada/getPortForwardingStatus.ts +0 -26
- package/src/tools/omada/getRateLimitProfiles.ts +0 -14
- package/src/tools/omada/getSiteNtpStatus.ts +0 -14
- package/src/tools/omada/getSsidDetail.ts +0 -22
- package/src/tools/omada/getSsidList.ts +0 -21
- package/src/tools/omada/getSwitchStackDetail.ts +0 -14
- package/src/tools/omada/getThreatList.ts +0 -42
- package/src/tools/omada/getWlanGroupList.ts +0 -14
- package/src/tools/omada/graph.ts +0 -187
- package/src/tools/omada/index.ts +0 -153
- package/src/tools/omada/listBlockedClients.ts +0 -17
- package/src/tools/omada/listClients.ts +0 -14
- package/src/tools/omada/listClientsActivity.ts +0 -25
- package/src/tools/omada/listClientsPastConnections.ts +0 -44
- package/src/tools/omada/listDevices.ts +0 -14
- package/src/tools/omada/listDevicesStats.ts +0 -41
- package/src/tools/omada/listMostActiveClients.ts +0 -14
- package/src/tools/omada/listSites.ts +0 -18
- package/src/tools/omada/namespace.ts +0 -1164
- package/src/tools/omada/searchDevices.ts +0 -20
- package/src/tools/omada/setClientRateLimit.ts +0 -26
- package/src/tools/omada/setClientRateLimitProfile.ts +0 -25
- package/src/tools/omada/setSiteNtpServers.ts +0 -36
- package/src/tools/omada/setSsidEnabled.ts +0 -38
- package/src/tools/omada/unblockClient.ts +0 -26
- package/src/tools/types.ts +0 -11
- package/src/tools/utils/pagination-schema.ts +0 -27
- package/src/types/ai/index.ts +0 -11
- package/src/types/ai/types.ts +0 -67
- package/src/types/homeassistant/automations.ts +0 -43
- package/src/types/homeassistant/calendars.ts +0 -26
- package/src/types/homeassistant/config.ts +0 -14
- package/src/types/homeassistant/entities.ts +0 -14
- package/src/types/homeassistant/errors.ts +0 -33
- package/src/types/homeassistant/haConfig.ts +0 -7
- package/src/types/homeassistant/history.ts +0 -13
- package/src/types/homeassistant/index.ts +0 -46
- package/src/types/homeassistant/request.ts +0 -6
- package/src/types/homeassistant/serviceCall.ts +0 -18
- package/src/types/homeassistant/states.ts +0 -58
- package/src/types/homeassistant/updates.ts +0 -28
- package/src/types/index.ts +0 -12
- package/src/types/omada/activeClientInfo.ts +0 -17
- package/src/types/omada/clientActivity.ts +0 -32
- package/src/types/omada/clientBlockStatus.ts +0 -11
- package/src/types/omada/clientPastConnection.ts +0 -82
- package/src/types/omada/index.ts +0 -14
- package/src/types/omada/omadaApiResponse.ts +0 -5
- package/src/types/omada/omadaClientInfo.ts +0 -11
- package/src/types/omada/omadaDeviceInfo.ts +0 -11
- package/src/types/omada/omadaDeviceStats.ts +0 -31
- package/src/types/omada/omadaSiteSummary.ts +0 -5
- package/src/types/omada/oswStackDetail.ts +0 -11
- package/src/types/omada/paginatedResult.ts +0 -6
- package/src/types/omada/rateLimitProfile.ts +0 -58
- package/src/types/omada/threatInfo.ts +0 -38
- package/src/types/omada/tokenResult.ts +0 -6
- package/src/types.ts +0 -2
- package/src/utils/config-validations.ts +0 -68
- package/src/utils/jwt.ts +0 -112
- package/src/utils/logger.ts +0 -121
- package/src/utils/plainText.ts +0 -48
- package/src/utils/redact.ts +0 -59
- package/src/utils/sanitizeError.ts +0 -18
- package/src/utils/tlsDispatcher.ts +0 -69
- package/src/version.ts +0 -5
- package/tests/bdd/automation-creation.spec.ts +0 -214
- package/tests/bdd/automation-management.spec.ts +0 -267
- package/tests/bdd/calendar.spec.ts +0 -190
- package/tests/bdd/configuration.spec.ts +0 -283
- package/tests/bdd/device-control.spec.ts +0 -344
- package/tests/bdd/entity-listing.spec.ts +0 -208
- package/tests/bdd/entity-search.spec.ts +0 -183
- package/tests/bdd/history-retrieval.spec.ts +0 -195
- package/tests/bdd/notifications.spec.ts +0 -238
- package/tests/bdd/service-calls.spec.ts +0 -144
- package/tests/bdd/state-retrieval.spec.ts +0 -204
- package/tests/bench/hotpaths.bench.ts +0 -68
- package/tests/config.test.ts +0 -355
- package/tests/features/automation-creation.feature +0 -36
- package/tests/features/automation-management.feature +0 -54
- package/tests/features/calendar.feature +0 -37
- package/tests/features/configuration.feature +0 -70
- package/tests/features/device-control.feature +0 -100
- package/tests/features/entity-listing.feature +0 -51
- package/tests/features/entity-search.feature +0 -44
- package/tests/features/history-retrieval.feature +0 -38
- package/tests/features/notifications.feature +0 -37
- package/tests/features/service-calls.feature +0 -35
- package/tests/features/state-retrieval.feature +0 -37
- package/tests/fixtures/openapi-default-slice.json +0 -290
- package/tests/haClient/automationTrace.test.ts +0 -59
- package/tests/haClient/automations.test.ts +0 -149
- package/tests/haClient/config.test.ts +0 -117
- package/tests/haClient/entities.test.ts +0 -188
- package/tests/haClient/events.test.ts +0 -455
- package/tests/haClient/eventsTls.test.ts +0 -52
- package/tests/haClient/history.test.ts +0 -228
- package/tests/haClient/index.test.ts +0 -243
- package/tests/haClient/request.test.ts +0 -217
- package/tests/haClient/services.test.ts +0 -120
- package/tests/haClient/states.test.ts +0 -119
- package/tests/haClient/updates.test.ts +0 -193
- package/tests/index.test.ts +0 -160
- package/tests/integration/homeassistant.test.ts +0 -144
- package/tests/integration/omada.test.ts +0 -167
- package/tests/integration/server.test.ts +0 -151
- package/tests/localAI/index.test.ts +0 -177
- package/tests/localAI/ollama.test.ts +0 -187
- package/tests/localAI/openai.test.ts +0 -257
- package/tests/omadaClient/actions.test.ts +0 -161
- package/tests/omadaClient/clientBlocks.test.ts +0 -170
- package/tests/omadaClient/ntp.test.ts +0 -381
- package/tests/omadaClient/site.test.ts +0 -37
- package/tests/ownerQuestions/service.test.ts +0 -499
- package/tests/ownerQuestions/tools.test.ts +0 -186
- package/tests/permissions/index.test.ts +0 -217
- package/tests/resources/index.test.ts +0 -288
- package/tests/scripts/generateJwt.test.ts +0 -44
- package/tests/security/accessControl.test.ts +0 -223
- package/tests/security/authentication.test.ts +0 -117
- package/tests/security/configuration.test.ts +0 -170
- package/tests/security/cryptoTransport.test.ts +0 -172
- package/tests/security/dependencies.test.ts +0 -152
- package/tests/security/injection.test.ts +0 -117
- package/tests/security/insecureDesign.test.ts +0 -121
- package/tests/security/logging.test.ts +0 -131
- package/tests/security/resourceConsumption.test.ts +0 -142
- package/tests/server/auth.test.ts +0 -249
- package/tests/server/chatFace.test.ts +0 -320
- package/tests/server/common.test.ts +0 -84
- package/tests/server/http.test.ts +0 -561
- package/tests/server/instructions.test.ts +0 -152
- package/tests/server/memoizeJsonSchema.test.ts +0 -71
- package/tests/server/stdio.test.ts +0 -99
- package/tests/server/stream.test.ts +0 -285
- package/tests/server/toolVisibility.http.test.ts +0 -111
- package/tests/server/toolVisibility.test.ts +0 -129
- package/tests/tools/ai/analyzeSensors.test.ts +0 -227
- package/tests/tools/common.test.ts +0 -123
- package/tests/tools/homeassistant/handlers.test.ts +0 -872
- package/tests/tools/infra/invokeAction.test.ts +0 -280
- package/tests/tools/omada/graph.test.ts +0 -385
- package/tests/tools/omada/handlers.test.ts +0 -897
- package/tests/tools/omada/namespace.test.ts +0 -483
- package/tests/tools/registry.test.ts +0 -168
- package/tests/utils/config-validations.test.ts +0 -352
- package/tests/utils/jwt.test.ts +0 -115
- package/tests/utils/logger.test.ts +0 -327
- package/tests/utils/redact.test.ts +0 -105
- package/tsconfig.json +0 -24
- package/vitest.config.ts +0 -38
package/AGENTS.md
DELETED
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
# mcp-ha-connect -- Codex Agent
|
|
2
|
-
|
|
3
|
-
## Identity & Scope
|
|
4
|
-
|
|
5
|
-
This agent owns the **mcp-ha-connect MCP server** — a Model Context Protocol server for
|
|
6
|
-
Home Assistant, TP-Link Omada, and Local AI integration.
|
|
7
|
-
|
|
8
|
-
**Repo:** `github.com/coffeerunhobby/mcp-ha-connect`
|
|
9
|
-
**npm:** `@coffeerunhobby/mcp-ha-connect`
|
|
10
|
-
**Docker:** `ghcr.io/coffeerunhobby/mcp-ha-connect`
|
|
11
|
-
**Live endpoint:** Cloudflare domain → NAS Docker port 3000 (domain in NAS `.env`)
|
|
12
|
-
|
|
13
|
-
**Working directory:** `C:\workspace\mcp` — this is the canonical copy.
|
|
14
|
-
`W:\mcp-homeassistant` is a stale export at v0.8.0 — ignore it.
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## Stack
|
|
19
|
-
|
|
20
|
-
- **Runtime:** Node.js 20+ (dev machine uses nvm)
|
|
21
|
-
- **Language:** TypeScript, compiled to `dist/` via `tsc`
|
|
22
|
-
- **MCP SDK:** v2 split packages — `@modelcontextprotocol/server` + `@modelcontextprotocol/node` (Node HTTP transport); `@modelcontextprotocol/client` is dev-only (tests)
|
|
23
|
-
- **Transport:** Streamable HTTP (port 3000, path `/mcp`)
|
|
24
|
-
- **Auth:** JWT bearer tokens with RBAC permission system
|
|
25
|
-
- **Plugins:** Home Assistant · TP-Link Omada SDN · Local AI (Ollama/OpenAI-compat)
|
|
26
|
-
- **Tests:** Vitest (1064 unit tests) + integration tests in `tests/integration/`
|
|
27
|
-
- **Container:** Alpine Node image, deployed on Synology NAS via Docker Compose
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## Infrastructure
|
|
32
|
-
|
|
33
|
-
| Resource | Address | Notes |
|
|
34
|
-
|---|---|---|
|
|
35
|
-
| **MCP server** | `mcpserver.10.0.0.18.nip.io:3000` | NAS Docker container |
|
|
36
|
-
| **Home Assistant** | `homeassistant.10.0.0.19.nip.io:8123` | |
|
|
37
|
-
| **Omada controller** | `omada.10.0.0.18.nip.io:8043` | HTTPS, self-signed cert |
|
|
38
|
-
| **Ollama** | `ollama.10.0.0.17.nip.io:11434` | model `phi4:14b` |
|
|
39
|
-
| **n8n** | `n8n.10.0.0.18.nip.io:5678` | also exposed via Cloudflare |
|
|
40
|
-
| **NAS Docker path** | `/volume1/docker/mcp-ha-connect/` | compose.yaml + .env |
|
|
41
|
-
| **Cloudflare** | proxies public domain → NAS port 3000 | domain stored in `.env` |
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## Secrets & Credentials
|
|
46
|
-
|
|
47
|
-
Server secrets live in the NAS `.env` file. The one release secret — the GHCR push token
|
|
48
|
-
(a GitHub classic PAT with `write:packages`, used for the Docker push in step 5) — lives only
|
|
49
|
-
in the maintainer's password manager. Never store it as an environment variable, in a file, in
|
|
50
|
-
a commit, in chat, or in this file; fetch it at push time and pipe it to `docker login
|
|
51
|
-
--password-stdin`.
|
|
52
|
-
|
|
53
|
-
### npm publishing needs no token
|
|
54
|
-
|
|
55
|
-
npm publish is done by CI via **OIDC trusted publishing** (see Release Process step 4) —
|
|
56
|
-
there is no npm token to store, rotate, or revoke. Publishing is configured at
|
|
57
|
-
npmjs.com → package Settings → **Trusted Publisher** → GitHub Actions (this repo +
|
|
58
|
-
`ci.yml`), not via a token.
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## Release Process
|
|
63
|
-
|
|
64
|
-
### 1. Pre-flight
|
|
65
|
-
|
|
66
|
-
```powershell
|
|
67
|
-
cd C:\workspace\mcp
|
|
68
|
-
npm test # all tests must pass
|
|
69
|
-
npm run build # must compile clean
|
|
70
|
-
npm run lint # ZERO errors AND zero warnings (see Code Quality policy)
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### 2. Version bump
|
|
74
|
-
|
|
75
|
-
Update **both** files to the new version:
|
|
76
|
-
- `package.json` → `"version": "X.Y.Z"`
|
|
77
|
-
- `src/version.ts` → `export const VERSION = 'X.Y.Z';`
|
|
78
|
-
|
|
79
|
-
Update `docs/CHANGELOG.md` with the new version section.
|
|
80
|
-
|
|
81
|
-
### 3. Commit & tag
|
|
82
|
-
|
|
83
|
-
```powershell
|
|
84
|
-
git add .
|
|
85
|
-
git commit -m "vX.Y.Z - <short description>"
|
|
86
|
-
git tag vX.Y.Z
|
|
87
|
-
git push origin main
|
|
88
|
-
git push origin vX.Y.Z
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
Create the GitHub Release at:
|
|
92
|
-
`https://github.com/coffeerunhobby/mcp-ha-connect/releases/new?tag=vX.Y.Z`
|
|
93
|
-
|
|
94
|
-
### 4. npm publish — AUTOMATED by CI (do NOT publish by hand)
|
|
95
|
-
|
|
96
|
-
**The `v*` tag you pushed in step 3 already publishes npm.** `.github/workflows/ci.yml`
|
|
97
|
-
has a `publish-npm` job that fires on `refs/tags/v*` and publishes via **OIDC trusted
|
|
98
|
-
publishing** — tokenless, `--provenance`, no `npm login`. It is **idempotent** (skips if
|
|
99
|
-
`pkg@version` is already on the registry) and it re-runs `npm ci && npm run build`
|
|
100
|
-
because `dist/` is gitignored. The same tag also runs a `release` job that auto-creates
|
|
101
|
-
the GitHub Release (idempotent — a manual `gh release create` just no-ops).
|
|
102
|
-
|
|
103
|
-
> Agent rule: **do NOT run `npm publish`/`npm login`.** Just push the tag, then verify:
|
|
104
|
-
> ```powershell
|
|
105
|
-
> gh run list --limit 3 # publish-npm + release jobs green on the v tag
|
|
106
|
-
> npm view @coffeerunhobby/mcp-ha-connect version # shows the new version
|
|
107
|
-
> ```
|
|
108
|
-
> `npm whoami` from the agent returns 401 (no session) — expected, not a failure.
|
|
109
|
-
|
|
110
|
-
### 5. Docker build & push — via WSL (NO Docker Desktop)
|
|
111
|
-
|
|
112
|
-
**Docker Desktop is not used on this box.** The working engine is **Docker CE inside
|
|
113
|
-
WSL2 Ubuntu-24.04**. CI's `docker-smoke` job only *boot-tests* the image — it does
|
|
114
|
-
**not** push to GHCR, so this push is the one genuinely manual release leg.
|
|
115
|
-
|
|
116
|
-
```powershell
|
|
117
|
-
# GHCR login — token fetched from the maintainer's password manager at push time and piped
|
|
118
|
-
# over stdin (never a command-line arg or env var). WSL keeps the login for the push below.
|
|
119
|
-
<token from password manager> | wsl -d Ubuntu-24.04 -- bash -lc "docker login ghcr.io -u coffeerunhobby --password-stdin"
|
|
120
|
-
|
|
121
|
-
# Build (repo is /mnt/c/workspace/mcp inside WSL) + push both tags
|
|
122
|
-
wsl -d Ubuntu-24.04 -- bash -lc "cd /mnt/c/workspace/mcp && docker build --no-cache -t ghcr.io/coffeerunhobby/mcp-ha-connect:X.Y.Z -t ghcr.io/coffeerunhobby/mcp-ha-connect:latest ."
|
|
123
|
-
wsl -d Ubuntu-24.04 -- bash -lc "docker push ghcr.io/coffeerunhobby/mcp-ha-connect:X.Y.Z && docker push ghcr.io/coffeerunhobby/mcp-ha-connect:latest"
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
WSL2 is amd64 = the NAS arch, so a plain `docker build` (not `buildx --platform`)
|
|
127
|
-
produces the correct image.
|
|
128
|
-
|
|
129
|
-
### 6. Deploy to NAS
|
|
130
|
-
|
|
131
|
-
The compose file pulls `ghcr.io/coffeerunhobby/mcp-ha-connect:latest`. On the NAS:
|
|
132
|
-
|
|
133
|
-
```bash
|
|
134
|
-
cd /volume1/docker/mcp-ha-connect
|
|
135
|
-
docker compose pull mcp-ha-connect && docker compose up -d mcp-ha-connect
|
|
136
|
-
docker compose logs --tail=30
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
Verify: `curl https://<cloudflare-domain>/openapi.json` → `info.version` is the new
|
|
140
|
-
version, and `curl https://<cloudflare-domain>/health` → `{"status":"healthy"}`.
|
|
141
|
-
|
|
142
|
-
---
|
|
143
|
-
|
|
144
|
-
## NAS `.env` — critical settings
|
|
145
|
-
|
|
146
|
-
```env
|
|
147
|
-
MCP_HTTP_BIND_ADDR=0.0.0.0
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
Must be `0.0.0.0`, not `127.0.0.1`. Docker port mapping requires the server to listen on
|
|
151
|
-
all interfaces inside the container — loopback only means Cloudflare gets a 502.
|
|
152
|
-
|
|
153
|
-
```env
|
|
154
|
-
MCP_HTTP_ALLOWED_ORIGINS=...,<cloudflare-domain>,https://<cloudflare-domain>
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
Must include both the bare hostname AND the `https://` form of the Cloudflare domain.
|
|
158
|
-
The MCP SDK checks the `host` header (no protocol) for DNS rebinding protection AND
|
|
159
|
-
the `origin` header (with protocol) for CORS.
|
|
160
|
-
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
## Omada SDN — known issues
|
|
164
|
-
|
|
165
|
-
**After upgrading the Omada controller version**, the `OMADA_OMADAC_ID` changes.
|
|
166
|
-
Error code `-44106` is returned for BOTH wrong credentials AND wrong `OMADA_OMADAC_ID` —
|
|
167
|
-
the API does not distinguish between them.
|
|
168
|
-
|
|
169
|
-
**To get the new Omada ID:**
|
|
170
|
-
Omada web UI → Settings → Open API → click the eye icon → copy **Omada ID**.
|
|
171
|
-
|
|
172
|
-
```bash
|
|
173
|
-
sed -i 's/OMADA_OMADAC_ID=.*/OMADA_OMADAC_ID=<new-id>/' /volume1/docker/mcp-ha-connect/.env
|
|
174
|
-
docker compose up -d
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
If Omada is unreachable or credentials are wrong, the server **gracefully degrades** —
|
|
178
|
-
Omada tools are disabled but HA and AI keep working. Set `OMADA_PLUGIN_ENABLED=false`
|
|
179
|
-
to disable Omada entirely while troubleshooting.
|
|
180
|
-
|
|
181
|
-
**`OMADA_SITE_ID` is validated at startup against the live site list** (the controller is
|
|
182
|
-
the source of truth; the env var is only a selector). If `OMADA_SITE_ID` is set but **not**
|
|
183
|
-
present on the controller — a site id can drift after a controller migration, exactly like
|
|
184
|
-
`OMADA_OMADAC_ID` — the **Omada plugin is disabled** at boot with a `logger.error` that
|
|
185
|
-
names the bad value and lists the valid sites (HA + AI stay up). This turns the old failure
|
|
186
|
-
mode (a silent default scoping every read to a dead site → later "user does not have
|
|
187
|
-
permissions to access this site") into a loud, self-diagnosing startup error. Fix by setting
|
|
188
|
-
`OMADA_SITE_ID` to one of the listed ids. Validation lives in `checkConfiguredSite()`
|
|
189
|
-
(`src/omadaClient/site.ts`); a *valid* default still auto-resolves, so site-scoped reads need
|
|
190
|
-
no explicit `siteId`.
|
|
191
|
-
|
|
192
|
-
---
|
|
193
|
-
|
|
194
|
-
## Code Quality — fix every error and warning
|
|
195
|
-
|
|
196
|
-
**Always fix errors AND warnings. Never label something "pre-existing debt" and move on.**
|
|
197
|
-
|
|
198
|
-
- `npm run lint`, `npm run build`, and `npm test` must all be **completely clean** —
|
|
199
|
-
zero errors, zero warnings — before a change is considered done.
|
|
200
|
-
- If you touch a file (or a release surfaces lint output) and find existing errors or
|
|
201
|
-
warnings, they are now yours to fix. "It was already broken" is not an acceptable
|
|
202
|
-
reason to leave it.
|
|
203
|
-
- **Exception — release timing:** do not cut a patch release *solely* to clean up lint.
|
|
204
|
-
If quality issues are found right after a release has shipped, fold the fixes into the
|
|
205
|
-
**next feature's** commit rather than churning a `vX.Y.(Z+1)`. Outstanding cleanup of
|
|
206
|
-
this kind is tracked in `.Codex/NEXT-SESSION.md` so it isn't forgotten.
|
|
207
|
-
|
|
208
|
-
> No lint cleanup currently outstanding. (The former `Function`-type warnings in the
|
|
209
|
-
> test mock helpers were resolved — `npm run lint --max-warnings=0` is clean as of v1.5.0.)
|
|
210
|
-
|
|
211
|
-
---
|
|
212
|
-
|
|
213
|
-
## Development
|
|
214
|
-
|
|
215
|
-
```powershell
|
|
216
|
-
cd C:\workspace\mcp
|
|
217
|
-
npm run dev # tsx watch with .env
|
|
218
|
-
npm test # vitest (excludes integration)
|
|
219
|
-
npm run test:watch # watch mode
|
|
220
|
-
npm run lint # eslint
|
|
221
|
-
npm run build # tsc compile to dist/
|
|
222
|
-
npm run generate:jwt # generate a test JWT token
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### Integration tests (requires live .env)
|
|
226
|
-
|
|
227
|
-
```powershell
|
|
228
|
-
npm run test:integration
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
---
|
|
232
|
-
|
|
233
|
-
## Live testing against the running server
|
|
234
|
-
|
|
235
|
-
The dev machine can exercise the deployed MCP server two ways:
|
|
236
|
-
|
|
237
|
-
1. **Connected `homeassistant` MCP in Codex Desktop** — this agent has the live server
|
|
238
|
-
wired in as an MCP connection, so HA/Omada tools can be invoked directly (no curl, no
|
|
239
|
-
manual token; the configured bearer is used). **Caveat:** the MCP client caches the tool
|
|
240
|
-
list at *connection time*. After flipping `MCP_TOOL_REGISTRATION_MODE` (eager ⇄ graph)
|
|
241
|
-
and redeploying, that cached list is **stale** — Codex Desktop must reconnect (restart)
|
|
242
|
-
before the new tool surface (`omada_browse`/`omada_read`, or the typed getters) shows up.
|
|
243
|
-
Until it reconnects, calling a tool the live server no longer registers will fail.
|
|
244
|
-
|
|
245
|
-
2. **Direct `/mcp` curl** — generate a token with
|
|
246
|
-
`npm run generate:jwt -- --sub <user> --exp 1h` (signs with the local `.env`
|
|
247
|
-
`MCP_AUTH_SECRET`, which currently matches the NAS), then POST JSON-RPC to the server's
|
|
248
|
-
`/mcp` with headers `Authorization: Bearer <tok>`, `Content-Type: application/json`,
|
|
249
|
-
`Accept: application/json, text/event-stream`. Responses come back as SSE
|
|
250
|
-
(`data: {...}` lines). `tools/list` and `tools/call` work **without** an initialize
|
|
251
|
-
handshake in stateless mode. The reachable server address lives in
|
|
252
|
-
`.Codex/NEXT-SESSION.md` (gitignored — never put the real IP/domain here).
|
|
253
|
-
|
|
254
|
-
Permissions are resolved **server-side** from the token's `sub` via `MCP_PERMISSIONS_CONFIG`
|
|
255
|
-
(they are NOT carried in the token). Pick a `sub` whose mapped role has the bit you need —
|
|
256
|
-
e.g. the ADMIN-gated `/security/threats` node needs a `sub` mapped to an ADMIN role. The NAS
|
|
257
|
-
role map differs from the local `.env`, so don't assume `sub=admin` is actually ADMIN there.
|
|
258
|
-
|
|
259
|
-
---
|
|
260
|
-
|
|
261
|
-
## Never assume. Always verify.
|
|
262
|
-
|
|
263
|
-
- **Cloudflare 502**: check the container is running (`docker compose ps`) and
|
|
264
|
-
`MCP_HTTP_BIND_ADDR=0.0.0.0` is set.
|
|
265
|
-
- **MCP client connects but tools fail**: check `MCP_HTTP_ALLOWED_ORIGINS` includes
|
|
266
|
-
the Cloudflare domain in both bare and `https://` form.
|
|
267
|
-
- **Codex Desktop shows "Server disconnected" but `/health` is 200**: the client's
|
|
268
|
-
mcp-remote auth header is malformed. A `"Authorization: Bearer ${MCP_AUTH_TOKEN}"`
|
|
269
|
-
placeholder does NOT expand on Windows (`cmd /c` uses `%VAR%`, mcp-remote doesn't
|
|
270
|
-
substitute `${VAR}`) → literal text is sent → server 401 → mcp-remote drops into a
|
|
271
|
-
failing OAuth flow. Fix: inline the literal JWT in `claude_desktop_config.json`'s
|
|
272
|
-
`--header` arg, and add `-y` to `npx` so first run doesn't hang. Verify the server
|
|
273
|
-
side first with a direct `curl` POST to `/mcp` carrying the token.
|
|
274
|
-
- **npm version not updating after a tag push**: check the `publish-npm` CI job on the
|
|
275
|
-
tag (`gh run list`) — publishing is OIDC via CI, never manual (see Release step 4).
|
|
276
|
-
- **Omada auth error -44106**: check `OMADA_OMADAC_ID` first, not just credentials —
|
|
277
|
-
this error code covers both cases.
|
|
278
|
-
- **Before a release**: always run `npm test` and `npm run build` clean.
|
|
279
|
-
- **On release, bump the version everywhere**: `package.json`, `src/version.ts`,
|
|
280
|
-
`docs/CHANGELOG.md`, AND `openapi.json` (`info.version`) — the last one drifts easily.
|
|
281
|
-
|
|
282
|
-
---
|
|
283
|
-
|
|
284
|
-
## Tool registration modes (`MCP_TOOL_REGISTRATION_MODE`)
|
|
285
|
-
|
|
286
|
-
Implemented as a **resource-graph** mode for the Omada plugin (config parses the var;
|
|
287
|
-
`config.toolRegistrationMode` threads through `createServer` → `registerAllTools` →
|
|
288
|
-
`registerOmadaTools`). Values:
|
|
289
|
-
|
|
290
|
-
- **`eager`** (default) — register every typed tool (~26 Omada tools). Today's behavior;
|
|
291
|
-
fully backwards-compatible.
|
|
292
|
-
- **`graph`** — register only `omada_browse` + `omada_read` + the 5 typed write/action
|
|
293
|
-
tools. Reads collapse into a discoverable resource graph (`src/tools/omada/namespace.ts`
|
|
294
|
-
manifest + `src/tools/omada/graph.ts`), shrinking the tool-schema budget for low-context
|
|
295
|
-
models while still exposing every read endpoint.
|
|
296
|
-
|
|
297
|
-
Design invariants (don't regress these):
|
|
298
|
-
- **browse returns TYPES, not instances** — `omada_browse(path)` lists permission-filtered
|
|
299
|
-
child resource types + metadata (kind, permission, pagination, params). It never
|
|
300
|
-
enumerates MACs or calls the controller.
|
|
301
|
-
- **read is per-path RBAC, fail-closed** — `omada_read` declares NO static tool permission;
|
|
302
|
-
each manifest node declares its own bit (most reads = QUERY; the `/security/*` subtree =
|
|
303
|
-
ADMIN). Unknown / container / under-privileged / missing-required-param paths all return a
|
|
304
|
-
clean error and never fetch.
|
|
305
|
-
- **single-page pagination** — paginated nodes forward one page/pageSize to a single GET via
|
|
306
|
-
`OmadaClient.readResource()`; they never walk every page.
|
|
307
|
-
- **graph is a complete superset of eager reads** — every eager read getter has a graph node,
|
|
308
|
-
including the ADMIN-gated IDS/IPS threat-management log at `/security/threats`. Its mandatory
|
|
309
|
-
epoch time-window is enforced via required `params.startTime`/`params.endTime` (epoch seconds),
|
|
310
|
-
validated by `omada_read` before any controller call.
|
|
311
|
-
|
|
312
|
-
HA and AI plugins are unaffected (still eager). Writes stay typed + individually gated in
|
|
313
|
-
both modes — generic write verbs were deliberately rejected (prompt-injection / hallucination
|
|
314
|
-
surface).
|
|
315
|
-
|
|
316
|
-
---
|
|
317
|
-
|
|
318
|
-
## Security
|
|
319
|
-
|
|
320
|
-
This server controls real devices (HA, Omada) and is exposed publicly via Cloudflare, so
|
|
321
|
-
treat it as security-sensitive. A full audit (2026-06-07) with file/line findings is in
|
|
322
|
-
`.Codex/NEXT-SESSION.md`; this section is the **durable policy** distilled from it.
|
|
323
|
-
|
|
324
|
-
### Dependencies — update, don't rewrite
|
|
325
|
-
|
|
326
|
-
- Runtime deps are intentionally tiny: `@modelcontextprotocol/server`, `@modelcontextprotocol/node`,
|
|
327
|
-
`undici`, `ws`, `zod` (^4.2 — SDK v2 requires it). Since v2.0.0 (SDK v2) the whole production tree
|
|
328
|
-
is **8 packages** (was 95 with SDK v1, which dragged in Express/cors/cross-spawn/ajv).
|
|
329
|
-
**Do not hand-roll replacements** for these (or for transitive libs like `hono`). A homegrown version loses community review and adds more
|
|
330
|
-
bugs than it removes. Zod and the MCP SDK earn their keep.
|
|
331
|
-
- Transitive advisories now can only come from `hono`/`@hono/node-server` (via
|
|
332
|
-
`@modelcontextprotocol/node`) or `@modelcontextprotocol/core`. **Bumping the SDK packages
|
|
333
|
-
fixes most of them.** `ws` and `undici` are direct deps to bump on their own.
|
|
334
|
-
- Triage with `npm audit --omit=dev` — dev-only vulns (vitest/esbuild/tsx) don't ship.
|
|
335
|
-
The question is *reachability in production*, not the raw count.
|
|
336
|
-
- Remediate on a branch: `npm install @modelcontextprotocol/server@latest @modelcontextprotocol/node@latest ws@latest undici@latest`, then
|
|
337
|
-
`npm test && npm run build && npm audit --omit=dev`. Commit `package-lock.json`;
|
|
338
|
-
CI/Docker use `npm ci`, not `npm install`. Widen version ranges only intentionally.
|
|
339
|
-
|
|
340
|
-
### MCP transport invariant (the SDK "cross-client data leak" advisory)
|
|
341
|
-
|
|
342
|
-
GHSA-345p-7cg4-v4c7 is about **sharing one `McpServer`/transport instance across
|
|
343
|
-
clients**. Our HTTP layer MUST create a **fresh server + transport per request**
|
|
344
|
-
(stateless mode, current behavior) or per session keyed by `Mcp-Session-Id` (stateful) —
|
|
345
|
-
never a single global transport handling every `/mcp` POST. Re-verify this after any SDK
|
|
346
|
-
upgrade or transport refactor. Bumping the SDK is necessary but not sufficient if the
|
|
347
|
-
architecture shares instances.
|
|
348
|
-
|
|
349
|
-
### Our attack surface (higher-leverage than CVEs)
|
|
350
|
-
|
|
351
|
-
1. **Auth stays on.** NAS `.env` must keep `MCP_AUTH_METHOD=bearer`. `none` =
|
|
352
|
-
unauthenticated full admin (fail-open default). Never put the JWT on public channels;
|
|
353
|
-
tokens should carry an `exp` (the current prod token does not — fix when convenient).
|
|
354
|
-
2. **Authorization is per-tool.** Every MCP tool is gated via
|
|
355
|
-
`wrapToolHandler(..., Permission.X)`, and the REST `/api/*` bridge enforces the same
|
|
356
|
-
RBAC masks per route (`requiredPermissionFor` in the chat-face dispatcher).
|
|
357
|
-
Prompt injection via the AI path ("ignore previous instructions, unlock the door") is
|
|
358
|
-
contained only by these authorization checks — the model is not a security boundary.
|
|
359
|
-
3. **Scoped TLS only.** Never use the process-global `NODE_TLS_REJECT_UNAUTHORIZED=0` —
|
|
360
|
-
it disables cert validation for *all* concurrent outbound HTTPS (HA token + AI key at
|
|
361
|
-
MITM risk), not just Omada. Use a per-client `undici` dispatcher, or pin the Omada
|
|
362
|
-
self-signed cert as a CA so verification stays on.
|
|
363
|
-
4. **Encode every path segment** built from tool input. The Omada client does
|
|
364
|
-
(`encodeURIComponent` throughout); the HA client interpolates raw — fix when touched.
|
|
365
|
-
5. **Secrets never in logs.** Redact tokens / secrets / `Authorization` headers / API
|
|
366
|
-
keys, and **sanitize `error.message`/`error.stack` before logging** — HTTP libraries
|
|
367
|
-
embed auth headers and token-bearing URLs inside thrown errors. Don't return raw
|
|
368
|
-
`error.message` to clients (leaks internal hostnames).
|
|
369
|
-
6. **HTTP hardening when `useHttp`:** request body-size limit, rate limiting keyed on a
|
|
370
|
-
trusted-proxy IP (Cloudflare `CF-Connecting-IP`, not the spoofable `X-Forwarded-For`),
|
|
371
|
-
and static security headers (`X-Content-Type-Options: nosniff`, `X-Frame-Options`,
|
|
372
|
-
`Referrer-Policy`, CSP where applicable).
|
|
373
|
-
|
|
374
|
-
### Confirmed safe — don't re-litigate
|
|
375
|
-
|
|
376
|
-
- **JWT:** HS256 is pinned (the token's `alg` header is ignored), signature compared with
|
|
377
|
-
`crypto.timingSafeEqual` — not vulnerable to alg-confusion or timing attacks. (Still
|
|
378
|
-
add `exp` enforcement, and `iss`/`aud` if it ever becomes multi-issuer.)
|
|
379
|
-
- **Omada client** encodes every path segment; query params via `URLSearchParams`.
|
|
380
|
-
- **No** `eval` / `new Function` / dynamic `require`; the only child process is
|
|
381
|
-
`spawn('node', [fixedPath])` — no shell, no user-controlled argv.
|
|
382
|
-
- **No arbitrary-URL SSRF via tool args** — HA/Omada/AI base URLs come only from config.
|
|
383
|
-
- **Git hygiene clean** — `.env` is never tracked; no hardcoded real secrets in src/tests.
|
|
384
|
-
|
|
385
|
-
### Insecure defaults to flip when next touched
|
|
386
|
-
|
|
387
|
-
`config.ts` defaults `MCP_AUTH_METHOD=none`; `.env.example` ships `none` +
|
|
388
|
-
`HA_STRICT_SSL=false`; `docker-compose.yml` hardcodes `MCP_HTTP_ALLOWED_ORIGINS=*`.
|
|
389
|
-
None of these reflect the (secure) live deployment — make the secure values the defaults.
|
package/Dockerfile
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# syntax=docker/dockerfile:1.7
|
|
2
|
-
|
|
3
|
-
FROM node:24-alpine AS deps
|
|
4
|
-
WORKDIR /app
|
|
5
|
-
COPY package*.json ./
|
|
6
|
-
# npm ci installs exactly from the committed package-lock.json (reproducible) and
|
|
7
|
-
# fails if package.json and the lockfile have drifted. The `package*.json` COPY
|
|
8
|
-
# above pulls in package-lock.json, so the lockfile is present in this stage.
|
|
9
|
-
RUN npm ci
|
|
10
|
-
|
|
11
|
-
FROM node:24-alpine AS build
|
|
12
|
-
WORKDIR /app
|
|
13
|
-
COPY --from=deps /app/node_modules ./node_modules
|
|
14
|
-
COPY . .
|
|
15
|
-
RUN npm run build
|
|
16
|
-
|
|
17
|
-
FROM node:24-alpine AS runtime
|
|
18
|
-
|
|
19
|
-
# OCI metadata labels
|
|
20
|
-
LABEL org.opencontainers.image.title="MCP-HA-Connect"
|
|
21
|
-
LABEL org.opencontainers.image.description="MCP server for Home Assistant + TP-Link Omada + Local AI integration"
|
|
22
|
-
LABEL org.opencontainers.image.authors="Coffee Run Hobby"
|
|
23
|
-
LABEL org.opencontainers.image.url="https://github.com/coffeerunhobby/mcp-ha-connect"
|
|
24
|
-
LABEL org.opencontainers.image.source="https://github.com/coffeerunhobby/mcp-ha-connect"
|
|
25
|
-
LABEL org.opencontainers.image.documentation="https://github.com/coffeerunhobby/mcp-ha-connect#readme"
|
|
26
|
-
LABEL org.opencontainers.image.licenses="MIT"
|
|
27
|
-
|
|
28
|
-
WORKDIR /app
|
|
29
|
-
ENV NODE_ENV=production
|
|
30
|
-
# apk upgrade: pick up Alpine security patches even when the node base tag lags
|
|
31
|
-
# (the 2026-07 Trivy scan's 24 libssl/libcrypto CVEs were exactly this rot).
|
|
32
|
-
RUN apk upgrade --no-cache && apk add --no-cache curl
|
|
33
|
-
COPY package*.json ./
|
|
34
|
-
# Reproducible prod-only install from the lockfile (drops devDependencies), then
|
|
35
|
-
# strip the package managers from the runtime image: nothing invokes npm/yarn after
|
|
36
|
-
# this line, and the npm CLI's vendored deps were the only Trivy findings left on
|
|
37
|
-
# v1.5.5 (undici 6.26.0 inside /usr/local/lib/node_modules/npm).
|
|
38
|
-
RUN npm ci --omit=dev && \
|
|
39
|
-
rm -rf /usr/local/lib/node_modules /usr/local/bin/npm /usr/local/bin/npx \
|
|
40
|
-
/usr/local/bin/corepack /opt/yarn* /usr/local/bin/yarn /usr/local/bin/yarnpkg \
|
|
41
|
-
/root/.npm
|
|
42
|
-
COPY --from=build /app/dist ./dist
|
|
43
|
-
|
|
44
|
-
# M10: drop root. The official node image ships a non-root `node` user (uid 1000).
|
|
45
|
-
# Built artifacts under /app are world-readable, so no chown is required; the
|
|
46
|
-
# server listens on 3000 (>1024) which needs no privileged capability.
|
|
47
|
-
USER node
|
|
48
|
-
# --experimental-quic was dropped 2026-07-10: nothing in src/ uses QUIC, and the
|
|
49
|
-
# flag tied the image to a specific Node major (25, now EOL) for no benefit.
|
|
50
|
-
CMD ["node", "dist/index.js"]
|
package/docker-compose.yml
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
services:
|
|
2
|
-
mcp-ha-connect:
|
|
3
|
-
build: .
|
|
4
|
-
container_name: mcp-ha-connect
|
|
5
|
-
restart: unless-stopped
|
|
6
|
-
ports:
|
|
7
|
-
- "3000:3000"
|
|
8
|
-
extra_hosts:
|
|
9
|
-
- "host.docker.internal:host-gateway"
|
|
10
|
-
env_file:
|
|
11
|
-
- .env
|
|
12
|
-
environment:
|
|
13
|
-
# Bind all interfaces inside the container so Docker's port map works.
|
|
14
|
-
- MCP_HTTP_BIND_ADDR=0.0.0.0
|
|
15
|
-
# M1: do NOT hard-code a wildcard origin here. Set MCP_HTTP_ALLOWED_ORIGINS
|
|
16
|
-
# in .env to the exact public origin(s) — e.g. your Cloudflare domain in
|
|
17
|
-
# both bare-host and https:// form — so DNS-rebinding/CORS protection works.
|
|
18
|
-
healthcheck:
|
|
19
|
-
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3000/health"]
|
|
20
|
-
interval: 30s
|
|
21
|
-
timeout: 10s
|
|
22
|
-
retries: 3
|
|
23
|
-
start_period: 10s
|