Skip to main content
Glama

Synesthetic MCP

by delk73
README.md8.96 kB
--- version: v0.2.7 owner: delk73 lastReviewed: 2025-09-12 --- # Synesthetic MCP Minimal, deterministic MCP-style adapter exposing schemas, examples, validation, diff, and an optional backend-populate tool. ## System Context ```mermaid flowchart LR MCP["synesthetic-mcp\n(MCP Adapter: discovery, validation, diff, backend proxy)"] BE["sdfk-backend\n(Python API & CRUD store)"] SSOT["synesthetic-schemas\n(SSOT: JSON Schemas + Python bindings)"] MCP --> |"Validates assets (Protobuf/JSON)"| BE MCP --> |"Consumes Python pkg (submodule)"| SSOT BE --> |"Consumes Python pkg (submodule)"| SSOT %% Grayscale theme, MCP slightly lighter to highlight style MCP fill:#555555,stroke:#ffffff,stroke-width:2px,color:#ffffff style BE fill:#333333,stroke:#cccccc,stroke-width:1.5px,color:#ffffff style SSOT fill:#222222,stroke:#cccccc,stroke-width:1.5px,color:#ffffff ``` ## Features - Schema and example discovery - JSON Schema validation (Draft 2020-12) - Batch validation via `validate_many` with `MCP_MAX_BATCH` (default 100) - RFC6902 diff (add/remove/replace only) - Backend population (optional via `SYN_BACKEND_URL`) - Canonical STDIO JSON-RPC loop with optional Unix-domain socket transport (`MCP_ENDPOINT=socket`) and TCP transport (`MCP_ENDPOINT=tcp`, `MCP_HOST`, `MCP_PORT`) - Per-request 1 MiB payload guard enforced before parsing across STDIO, socket, and TCP transports - Deprecated `validate` alias remains available but logs a warning; prefer `validate_asset` - Strict asset contract: top-level `$schema` is required and legacy `schema`/`$schemaRef` keys are rejected (v0.2.8) ## Quickstart 1. Install deps: `pip install -r requirements.txt && pip install -e .` 2. Initialize schemas/examples: `git submodule update --init --recursive`. 3. Serve via Compose: `docker compose up serve` (runs the transport, logs `mcp:ready mode=<endpoint>` with ISO-8601 timestamps, and exposes `/tmp/mcp.ready` for health checks). 4. Or run the helper: `./up.sh` builds the image and starts the serve service in the background; follow with `docker compose logs -f serve` if you want to tail logs. 5. Validate an asset locally: `python -m mcp --validate libs/synesthetic-schemas/examples/SynestheticAsset_Example1.json`. ## Structure ``` README.md requirements.txt docs/ mcp_spec.md mcp/ __init__.py core.py validate.py diff.py backend.py stdio_main.py socket_main.py transport.py tests/ test_validate.py test_diff.py test_backend.py test_env_discovery.py test_stdio.py test_submodule_integration.py ``` ## Development * Python >= 3.11 * Install deps (minimal): `pip install -r requirements.txt` - Minimal deps: `jsonschema`, `httpx`, `pytest` - Optional extras: `referencing` (enhanced JSON Schema refs; import is optional) - Dev (optional): `ruff`, `mypy` * Import check: `python -c "import mcp; print(mcp.__version__)"` * Run tests: `pytest -q` * Runtimes: - `python -m mcp` (STDIO by default; set `MCP_ENDPOINT=socket` for the Unix-domain socket server or `MCP_ENDPOINT=tcp` for TCP. Logs `mcp:ready mode=<endpoint>` with ISO-8601 timestamps on readiness). - `python -m mcp.stdio_main` (invoke the STDIO loop directly when embedding). ## Dependencies - Runtime: `jsonschema`, `httpx` - Tests: `pytest` - Dev (optional): `ruff`, `mypy` - Extras (optional): `referencing` (ref handling performance/behavior) ## Environment | Variable | Default | Behaviour | | - | - | - | | `MCP_ENDPOINT` | `stdio` | Transport selector. `stdio` runs over stdin/stdout; `socket` enables the Unix-domain socket server; `tcp` binds a TCP listener. | | `MCP_READY_FILE` | `/tmp/mcp.ready` | File touched on startup with `<pid> <ISO8601>` and removed on shutdown; Compose health checks test for its presence. Override when sandboxed. | | `MCP_SOCKET_PATH` | `/tmp/mcp.sock` | Socket path when `MCP_ENDPOINT=socket`. The server unlinks the file on shutdown. | | `MCP_SOCKET_MODE` | `0600` | Octal file mode applied to the socket on startup. Increase only when the socket must be shared. | | `MCP_HOST` | `0.0.0.0` | TCP bind address when `MCP_ENDPOINT=tcp`. Use `127.0.0.1` for local development. | | `MCP_PORT` | `7000` | TCP port when `MCP_ENDPOINT=tcp`. Set to `0` to request an ephemeral port (logged on startup). | | `SYN_SCHEMAS_DIR` | `libs/synesthetic-schemas/jsonschema` when present | Overrides schema directory; required when submodule absent. Startup fails if the directory is missing. | | `SYN_EXAMPLES_DIR` | `libs/synesthetic-schemas/examples` when present | Overrides examples directory; discovery falls back to submodule if unset. | | `SYN_BACKEND_URL` | unset | Enables backend POSTs; missing keeps populate disabled (`unsupported`). | | `SYN_BACKEND_ASSETS_PATH` | `/synesthetic-assets/` | Custom path for backend POST requests. | | `MCP_MAX_BATCH` | `100` | Maximum batch size for `validate_many`; oversized batches return `{ok:false, reason:'unsupported'}`. | `.env.example` captures these defaults for quick copying into local shells or Compose. ### Environment Discovery - `SYN_SCHEMAS_DIR` and `SYN_EXAMPLES_DIR` override paths when set. - Otherwise, schemas/examples are loaded from the `libs/synesthetic-schemas` submodule. - If neither is available, listings are empty and get operations return not found (no fixture fallback). ### Submodule (SSOT) Authoritative schemas/examples live at `libs/synesthetic-schemas` (git submodule). Order of discovery used by the adapter: 1) `SYN_SCHEMAS_DIR` and `SYN_EXAMPLES_DIR` if set 2) `libs/synesthetic-schemas/jsonschema` and `libs/synesthetic-schemas/examples` if present 3) If neither exists, listings are empty and get operations return not found Initialize the submodule: ``` git submodule update --init --recursive ``` ### Schema Aliases (Nested Assets) * **`synesthetic-asset`** → canonical schema (flat). * **`nested-synesthetic-asset`** → alias for assets with components inlined. * All component types may be embedded (shader, tone, haptic, control, modulation, rule bundle). * Alias validation loads the canonical `synesthetic-asset` schema. * Examples `SynestheticAsset_Example*.json` are treated as `nested-synesthetic-asset`. * Assets MUST declare their validating schema via top-level `$schema`; legacy `schema` or `$schemaRef` keys are rejected. * Tests use the nested alias; submodule is the single source of truth. ## Error Model - Validation failed: `{ ok:false, reason:'validation_failed', errors:[{ path, msg }] }` - Backend error: `{ ok:false, reason:'backend_error', status, detail }` - Unsupported tool/resource: `{ ok:false, reason:'unsupported', detail }` - Network errors map to backend_error with `status:503` and a brief `detail`. - Payload too large (>1 MiB on STDIO/socket/TCP): `{ ok:false, reason:'validation_failed', errors:[{ path:'', msg:'payload_too_large' }] }` ## CLI Usage ``` $ python -m mcp --validate path/to/asset.json {"ok": true, "errors": [], "schema": "nested-synesthetic-asset"} ``` - Exit code `0`: validation succeeded. - Exit code `1`: validation failed (payload includes `reason: validation_failed`). - Exit code `2`: input errors (file missing, unreadable, or invalid JSON). ### Docker Build and run tests in a container: ``` ./test.sh ``` Notes: - `docker-compose.yml` passes through env if set; there are no defaults to fixtures. The adapter’s own discovery logic picks the right source. - No backend service is started by compose; backend calls are disabled unless `SYN_BACKEND_URL` is set. ### Serving Locally - `docker compose up serve` builds the image, starts `python -m mcp`, waits for `/tmp/mcp.ready`, and keeps logs attached. - `./up.sh` builds the image and starts the `serve` service in detached mode; run `docker compose logs -f serve` to follow output after startup. - STDIO remains the default; set `MCP_ENDPOINT=socket` to listen on the Unix-domain socket path, or `MCP_ENDPOINT=tcp` (optionally with `MCP_HOST`/`MCP_PORT`) to expose a TCP listener. - Requests above 1 MiB (UTF-8 bytes) are rejected before parsing with `payload_too_large` on STDIO, socket, and TCP (see `tests/test_stdio.py`, `tests/test_socket.py`, and `tests/test_tcp.py`). ## Spec See `docs/mcp_spec.md` for deterministic IO contracts and limits. ## Status ✅ Spec pinned in `docs/mcp_spec.md` ✅ Minimal implementation with tests ### Validating it **Quick host check with `nc`:** ```bash nc localhost 8765 ``` Paste this request: ```json {"jsonrpc":"2.0","id":1,"method":"list_schemas"} ``` You should get a JSON response with available schemas. **Labs connection env** (pointing to the MCP container via TCP): ```bash MCP_ENDPOINT=tcp MCP_HOST=localhost # or 'synesthetic-mcp-serve-1' if inside Docker network MCP_PORT=8765 LABS_FAIL_FAST=1 SYN_SCHEMAS_DIR=libs/synesthetic-schemas/jsonschema SYN_EXAMPLES_DIR=libs/synesthetic-schemas/examples ``` **Run Labs against it:** ```bash python -m labs.cli generate --prompt "hello world shader test" ```

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/delk73/synesthetic-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server