Skip to content

fix(docker): point mcp-server at the neo4j service, widen the healthcheck start period - #61

Merged
Irahan2 merged 1 commit into
mainfrom
fix/54-docker-neo4j-uri-and-healthcheck
Sep 1, 2026
Merged

fix(docker): point mcp-server at the neo4j service, widen the healthcheck start period#61
Irahan2 merged 1 commit into
mainfrom
fix/54-docker-neo4j-uri-and-healthcheck

Conversation

@Irahan2

@Irahan2 Irahan2 commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Points 1 and 3 of #54. Point 3 came out differently than the issue describes, and point 2 turned
out to be partly stale plus a bigger gap underneath, so I left it out and put the question at the
bottom.

1. NEO4J_URI

Confirmed. Checked from inside the running container:

neo4j:7687     -> reachable
localhost:7687 -> ConnectionRefusedError

mcp-server only read the value from .env, and .env.example ships
bolt://localhost:7687. Added an environment: override for the service name, same as
topwr-api does for MCP_HOST, so it doesn't depend on what's in someone's .env. Verified the
environment block beats env_file when both set the key.

Left .env.example alone on purpose, bolt://localhost:7687 is the right address for
just mcp-server on the host.

3. Healthcheck start_period

Raised 15s to 180s as asked, but the ~4 minutes didn't reproduce here. I took the whole stack
down and brought it back up cold with the URI fix in place:

container started : 09:51:51.9
port 8005 open    : 09:51:57.4   -> 6.0s
health log        : one failure inside the start period, healthy from the next check

So on this machine the old 15s was already enough. My guess is the 4 minutes you saw was the
first point: with localhost the Neo4j driver retries before giving up, and the server can't
bind until initialize_rag() returns. Worth re-checking on your side after this lands.

I still went with 180s because the cost is one-sided. A successful check ends the start period
immediately, so headroom never slows a healthy container down, it only delays reporting one that
never comes up. If we'd rather detect a dead mcp-server sooner we can bring it down, the
measurement is in the compose comment.

2. Prefect, and a question

I didn't touch this one. Two things I found while checking it:

The version half is already done. Dockerfile.prefect doesn't pin prefect==2.* any more, it
runs uv sync --locked off pyproject.toml + uv.lock, which resolves to prefect 3.6.11.

The part that isn't done is bigger than the issue says. The container never runs the scheduled
deployment at all:

  • the image's CMD is only prefect server start
  • compose.prefect.yml doesn't override it
  • nothing anywhere calls serve_refresh / uv run prefect-refresh

So the cron from #51 only exists when someone runs just refresh-serve on their own machine.
CLAUDE.md also points at docker/prefect-entrypoint.sh ("starts Prefect server then runs
pipeline") and that file isn't in the repo.

And even if we wire the deployment in, compose.prefect.yml is a separate stack with no neo4j
service and no link to mcp_network, so the pipeline has no route to the graph.

That last bit is a deployment decision rather than a fix, so: how do you want the two stacks to
relate? Options I can see are a shared external network, folding prefect into compose.stack.yml,
or keeping them separate and giving the pipeline its own Neo4j address. Happy to do whichever,
just don't want to pick for you.

I did correct the two stale CLAUDE.md claims here since I'd verified them, gotcha 9 now describes
the real gap. Shout if you'd rather that moved to the follow-up PR.

… unhealthy

Two of the three points in #54.

mcp-server only read NEO4J_URI from .env, and .env.example ships
bolt://localhost:7687, which is correct on the host but means the container
itself once it is on mcp_network. Confirmed from inside the container:
neo4j:7687 connects, localhost:7687 is refused. The compose file now overrides
it the same way topwr-api overrides MCP_HOST, so the value no longer depends on
what an operator happened to put in .env. Checked that the environment block
beats env_file when both set the key.

.env.example keeps bolt://localhost:7687 on purpose, since `just mcp-server`
runs on the host where that is the right address.

start_period on the mcp-server healthcheck goes from 15s to 180s. Measured a
genuinely cold stack after this fix and the port was open in 6 seconds, so the
old value was not obviously wrong here, but a first start on freshly built
layers has been reported taking minutes. A successful check ends the start
period immediately, so the headroom only ever delays reporting a container that
never comes up.

Also corrects two stale claims in CLAUDE.md that came up while checking the
third point: Dockerfile.prefect no longer pins prefect 2.x (it installs 3.6.11
from uv.lock), and docker/prefect-entrypoint.sh does not exist. Gotcha 9 now
describes the real gap instead, which is that nothing in the container runs the
scheduled deployment at all.

@Dominik-Galus Dominik-Galus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@Dominik-Galus Dominik-Galus linked an issue Sep 1, 2026 that may be closed by this pull request
@Irahan2
Irahan2 added this pull request to the merge queue Sep 1, 2026
Merged via the queue into main with commit b97c24e Sep 1, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deployment / data hygiene

2 participants