Synology NAS Connector
by sammkoo
README.md
# Synology NAS Connector for ChatGPT
Independent, MIT-licensed **v0.1 developer preview**. A read-only MCP server for selected NAS folders, a portable Node.js core, a DSM dashboard, and a reproducible DSM `.spk` builder. No OpenAI API key, DSM password, file upload, outbound relay, telemetry or inference calls are required.
**Implemented:** folder listing, filename search, metadata, bounded UTF-8 document reads; MCP stdio and stateless Streamable HTTP; bearer-token development authentication; DSM package lifecycle. Build 0002 adds an authenticated management bridge, graphical share selection and live policy revocation, pending real DSM CGI validation.
**Planned:** production MCP OAuth, account pairing, Sign in with ChatGPT, public plugin distribution and an optional outbound relay. These features are visibly disabled. A `.spk` build is not proof of installation compatibility; real DSM testing remains a release gate.
## Quick start
Use Node.js 22 (Node.js 24 is also covered by CI) and Python 3 for packaging.
```sh
npm ci
npm run init
```
Edit `.local/config.json`; new configurations have **no roots**. Add only specific folders:
```json
"roots": [{"id": "documents", "label": "Documents", "path": "/absolute/path/to/selected/folder"}]
```
Keep the token file private, owned by the service user, with mode `0600`. The generated configuration binds to `127.0.0.1` and permits only the two local dashboard origins.
```sh
npm run check
npm run build
node dist/server.cjs --config .local/config.json
```
Open `http://127.0.0.1:8787`. Enter the locally generated token from `.local/token` to see service status and allowed folder aliases. Copy it locally; never commit it. The dashboard stores no credentials. Root access is configured by editing the private config and restarting, rather than granting file permissions from a browser.
## Local MCP clients
Use an absolute server and config path in a client that supports stdio:
```json
{
"mcpServers": {
"synology-nas": {
"command": "node",
"args": ["/absolute/path/to/dist/server.cjs", "--stdio", "--config", "/absolute/path/to/.local/config.json"]
}
}
}
```
Stdio trusts the local spawning process and OS identity; it does not require a bearer token. It uses the same root policy and core as HTTP and DSM. This configuration example is for clients that accept this format; it is not a claimed ChatGPT desktop configuration.
HTTP clients use `POST /mcp` with `Authorization: Bearer <local-token>` and MCP transport headers. There is no legacy SSE transport. Static tokens are for local/self-hosted development, not a completed public ChatGPT authentication flow.
| Tool | Inputs | Result |
| --- | --- | --- |
| `list_roots` | none | allowed root IDs and labels |
| `list_directory` | `rootId`, relative `path`, `limit`, `offset` | entries, `nextOffset`, partial-coverage indicators |
| `search_files` | `rootId`, filename `query`, `limit` | matching files, partial-coverage indicators |
| `get_metadata` | `rootId`, relative `path` | type, bytes, modification time |
| `read_text` | `rootId`, relative `path`, `startLine`, `maxLines` | text, line range, trust marker |
Text support: `.txt`, `.md`, `.csv`, `.tsv`, `.json`, `.xml`, `.yaml`, `.yml`, `.log`, `.rst`, strictly UTF-8. PDF, DOCX, spreadsheets, OCR and archives are outside v0.1. Search matches filenames only and does not index file contents. Default directory scans stop at 5,000 examined entries; tool output is capped at 200 entries. Use `nextOffset` for another directory page. `scanTruncated` means the scan budget stopped discovery; further pages cannot recover unscanned entries. Pagination is not a snapshot if the directory changes. There is no persistent search index.
## Docker
After generating `.local`, set `http.host` to `0.0.0.0` **inside the container config**, and use `/data/documents` as the root path. Keep `tokenFile` as `token`, allowed hosts as `127.0.0.1`/`localhost`, and the local dashboard origins. Compose publishes only on the host loopback interface and mounts both config and documents read-only.
```sh
NAS_UID=$(id -u) NAS_GID=$(id -g) docker compose up --build
```
The selected UID/GID must own `.local/token` and be able to traverse the mounted directories. Linux Docker uses descriptor-relative file access. The image runs without root, capabilities or a writable root filesystem. No Docker daemon is required for native local development.
## DSM package
```sh
npm run build
npm run spk
npm run test:spk
```
Output: `artifacts/SynologyNASConnector-0.1.0-0002-noarch.spk` and its SHA-256 checksum. See [DSM management preview](docs/dsm-management.md) for the new setup flow and device-validation limits. The [original installation guide](docs/installation.md) also documents manual/local diagnostics.
## Project layout
```text
packages/core/ filesystem policy, limits, config; no DSM or MCP dependency
packages/auth/ local-token authentication and future OAuth adapter contract
packages/management/ signed bridge, share catalog and private configuration service
apps/server/ MCP tool definitions, HTTP transport, stdio CLI
apps/dsm-ui/ static dashboard served locally and packaged for DSM
apps/dsm-bridge/ authenticated DSM CGI bridge; no DSM credentials forwarded
packaging/synology/ INFO, privilege policy, lifecycle scripts and DSM launcher
scripts/ portable bundle, SPK builder, package and Docker verification
tests/ policy, authentication and real MCP SDK client tests
docs/ architecture, installation, integration evidence, threat model
```
GitHub Actions tests on Linux with Node.js 22/24, builds and verifies `.spk`, uploads package artifacts, audits production dependencies, and builds/smoke-tests Docker. Source is published at [sammkoo/synology-nas-connector](https://github.com/sammkoo/synology-nas-connector). No release is published automatically; production promotion requires the [product acceptance evidence](docs/product-plan.md).
See [architecture](docs/architecture.md), [verified OpenAI integration points](docs/openai-integration.md), [security](SECURITY.md), [verification record](docs/verification.md), and [contributing](CONTRIBUTING.md).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues