Skip to content

fix: harden self-hosted stdio startup validation#83

Merged
ChiragAgg5k merged 1 commit into
mainfrom
fix/stdio-startup-validation
Jul 22, 2026
Merged

fix: harden self-hosted stdio startup validation#83
ChiragAgg5k merged 1 commit into
mainfrom
fix/stdio-startup-validation

Conversation

@ChiragAgg5k

Copy link
Copy Markdown
Member

Summary

Self-hosted stdio MCP was exiting before the MCP handshake when startup validation failed on the first probe (tables_db). Clients such as Cursor only saw an opaque reconnect error (-32000) with no actionable message.

This change:

  • Probes services in VALIDATION_SERVICE_ORDER until one succeeds, so keys without tables_db/databases scopes can still start via users, teams, etc.
  • Normalizes APPWRITE_ENDPOINT (strip trailing slash, append /v1 when the host has no path).
  • Prints a short [appwrite-mcp] ERROR: … line on stderr for config/validation failures instead of relying on a traceback clients never show.
  • Documents troubleshooting for -32000 in docs/self-hosted.md.
  • Uses raise SystemExit(main()) so stdio exits with a proper status code.

Test plan

  • Unit tests: endpoint normalization, validate_services fall-through and aggregated failures, clean stderr on validation failure
  • uv run python -m unittest discover -s tests/unit -v

Probe multiple Appwrite services at startup, normalize endpoints, and surface
clear stderr errors so MCP clients no longer fail with opaque -32000 reconnects
when the first tables_db probe fails or credentials are misconfigured.

Co-authored-by: Cursor <cursoragent@cursor.com>
@greptile-apps

greptile-apps Bot commented Jul 22, 2026

Copy link
Copy Markdown

Greptile Summary

This PR makes self-hosted stdio startup failures easier to diagnose. The main changes are:

  • Tries multiple Appwrite services before failing startup validation.
  • Normalizes bare stdio endpoints by adding /v1.
  • Prints short stderr errors for stdio validation failures.
  • Returns process exit codes through SystemExit.
  • Adds troubleshooting docs and unit coverage.

Confidence Score: 4/5

The endpoint normalization path needs a fix before merging.

  • Stdio startup can accept a bare self-hosted endpoint after adding /v1.
  • Other runtime paths still use the raw endpoint and can call the wrong base URL.
  • The validation fall-through and exit-code changes look consistent with the documented stdio behavior.

src/mcp_server_appwrite/server.py

Important Files Changed

Filename Overview
src/mcp_server_appwrite/server.py Adds endpoint normalization, multi-service startup probing, and clean stdio error handling; endpoint normalization is not shared by every runtime path.
src/mcp_server_appwrite/main.py Propagates the integer result from the package entrypoint as the process exit code.
tests/unit/test_server.py Adds tests for endpoint normalization, validation fall-through, aggregated validation failures, and clean stdio errors.
docs/self-hosted.md Documents how to troubleshoot opaque stdio reconnect failures and clarifies the expected self-hosted API endpoint.

Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
src/mcp_server_appwrite/server.py:179
**Endpoint Paths Diverge By Transport**

When `APPWRITE_ENDPOINT` is set to a bare self-hosted host such as `http://localhost:9501`, this stdio config path now normalizes it to `/v1`, but the HTTP/OAuth paths still read the raw environment value. Stdio startup can pass while OAuth issuer and request clients use the wrong base path, so the same documented endpoint value can fail outside stdio.

Reviews (1): Last reviewed commit: "fix: harden self-hosted stdio startup va..." | Re-trigger Greptile

project_id = os.getenv("APPWRITE_PROJECT_ID")
api_key = os.getenv("APPWRITE_API_KEY")
endpoint = os.getenv("APPWRITE_ENDPOINT", DEFAULT_ENDPOINT)
endpoint = _normalize_endpoint(os.getenv("APPWRITE_ENDPOINT", DEFAULT_ENDPOINT))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Endpoint Paths Diverge By Transport

When APPWRITE_ENDPOINT is set to a bare self-hosted host such as http://localhost:9501, this stdio config path now normalizes it to /v1, but the HTTP/OAuth paths still read the raw environment value. Stdio startup can pass while OAuth issuer and request clients use the wrong base path, so the same documented endpoint value can fail outside stdio.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/mcp_server_appwrite/server.py
Line: 179

Comment:
**Endpoint Paths Diverge By Transport**

When `APPWRITE_ENDPOINT` is set to a bare self-hosted host such as `http://localhost:9501`, this stdio config path now normalizes it to `/v1`, but the HTTP/OAuth paths still read the raw environment value. Stdio startup can pass while OAuth issuer and request clients use the wrong base path, so the same documented endpoint value can fail outside stdio.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code Fix in Codex

@ChiragAgg5k
ChiragAgg5k merged commit 04fc3bd into main Jul 22, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant