2026-09-18
Six real bugs between us and a working Glama deployment
A record of a real multi-round debugging session against a third party's hosting platform, not a single clean fix — each round produced a different real error, and each is quoted here as it actually appeared.
The start: no explanation, just "cannot be deployed"
Glama is an MCP directory that also offers one-click hosted deployment for any listed server. Spomory's listing showed a greyed-out "Deploy Server" button with a single line underneath: "This server cannot be deployed." No error, no log, no hint about what was missing.
First guess: add a Dockerfile
The obvious first guess was a missing Dockerfile — Glama needs to containerize the server somehow. Spomory's repo didn't have one, so one was added and verified locally: a real `docker build` succeeded, and a real `docker run` with a dummy `LLM_API_KEY` stayed up without crashing. The Dockerfile was correct.
It still made no difference on Glama's side. The button stayed grey. That was the first sign this wasn't going to be a one-line fix — Glama, it turned out, doesn't use a repository's own Dockerfile at all. It synthesizes its own build recipe from a detected language and lets you edit that recipe directly — but only once you've claimed the listing.
Claiming the listing, via glama.json
Claiming requires two things: a `glama.json` file in the repo naming the GitHub maintainer, and then signing in with that GitHub account on Glama's own site to confirm ownership. The file is simple:
{
"$schema": "https://glama.ai/mcp/schemas/server.json",
"maintainers": ["lyf-wxy"]
} Real error #1: a command that doesn't exist where Glama looks for it
Claiming unlocked an editable "Docker Builds" configuration panel — the actual recipe Glama uses, not the repo's own Dockerfile:
The first real test run against this produced an actual crash, quoted verbatim from the instance logs:
could not start the proxy Error: spawn memory-core-mcp ENOENT
at ChildProcess._handle.onexit (node:internal/child_process:287:19)
at onErrorNT (node:internal/child_process:525:16)
at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {
errno: -2,
code: 'ENOENT',
syscall: 'spawn memory-core-mcp',
path: 'memory-core-mcp',
spawnargs: []
} The command name itself was correct — `memory-core-mcp` is a real console script defined in `pyproject.toml`. The actual problem was in the "CMD arguments" field, the literal command Glama spawns to start the server:
["mcp-proxy", "--", "uv", "run", "memory-core-mcp"] Real error #2, caught before it happened: missing optional dependencies
Before re-testing, a check of `pyproject.toml` showed `llm`, `embedding`, and `mcp` are all optional-dependency groups — a bare `uv sync` installs none of them, which would have failed the very next run with a missing-import error instead of the command-not-found one. The build steps needed the extras spelled out explicitly:
["uv sync --extra llm --extra embedding --extra mcp"] Real error #3: the process starts, then Glama kills it anyway
With both fixes in place, the next run got much further — the Python process actually started, and the instance logs show a real embedding model loading to completion:
Loading weights: 100%|██████████| 391/391 [00:00<00:00, 16767.95it/s]
/root/.local/share/uv/python/.../resource_tracker.py:475: UserWarning: resource_tracker: ...
could not start the proxy SdkError: Connection closed No traceback — the process just stopped responding right after the model finished loading. The actual error surfaced one layer up: "Container exited with code 1 before responding to ping." That phrase is the real clue: Glama pings a freshly started container to confirm it's alive, and Spomory's MCP server was loading a multi-hundred-megabyte multilingual embedding model synchronously at startup — blocking the process for several seconds before it could answer anything, including that ping. Glama's health check timed out and killed it.
class SentenceTransformerProvider(EmbeddingProvider):
"""Loads its model lazily, on the first `embed()` call, rather than in
`__init__`: constructing this class runs at MCP server startup, and
eagerly loading a multi-GB multilingual model there blocks the process
for several seconds before it can respond to anything -- including a
health-check ping, which some hosts (e.g. Glama's container deploy)
time out and kill before the server ever comes up."""
def __init__(self, model_name: str | None = None) -> None:
self.model_name = model_name or os.environ.get("EMBEDDING_MODEL", DEFAULT_MODEL_NAME)
self._model = None
def _get_model(self):
if self._model is None:
from sentence_transformers import SentenceTransformer
self._model = SentenceTransformer(self.model_name)
return self._model Model loading moved out of `__init__` and into a private `_get_model()`, called only from `embed()` — the first real search or write, not server startup. The next test run: status `success`, duration 1m 19.2s, and the instance logs showed real JSON-RPC traffic — `tools/list` correctly returning all six tools including `export_memory`'s full schema, `prompts/list` and `resources/list` both answering cleanly. The server was actually working now.
Real error #4: a passing test that still wouldn't turn into a deploy
A passing build test still isn't a deployable release on Glama — there's a separate "Make Release" action tied to a real GitHub Release, matching a line already sitting in the Admin panel: "Auto-Release: builds and publishes a new version on every GitHub release." The `yliuai/spomory` repo had never shipped one. A real GitHub Release, `v0.1.1`, matching the version then published on PyPI, fixed that.
One more real mistake followed almost immediately: the PyPI package was republished as 0.1.2 shortly after, and the natural question was whether the `v0.1.1` tag was now stale. Checking the actual commit SHAs showed the tag and `main`'s HEAD were identical — `pyproject.toml` at that exact commit already said `0.1.2`. The code was never behind; the release was just mislabeled. The fix was to delete `v0.1.1` and recreate the same commit as `v0.1.2` — a naming correction, not a rebuild.
What actually made this five layers deep
None of these five fixes on their own would have looked complicated in isolation. What made this a real six-round debugging session was that each fix only revealed the next failure — a missing Dockerfile hid a missing claim step, which hid a wrong start command, which hid missing extras, which hid an eager model load, which hid a release-labeling step with its own separate bug. Every log quoted above is what Glama actually printed at each stage, not a cleaned-up retelling.
Spomory's live Glama listing →
The v0.1.2 GitHub release referenced above →