Skip to main content
Glama
README.md
# shed-mcp

A small self-hosted MCP gateway between ChatGPT and private shed-* applications. Phase 1 exposes **Shed Life Todos** through seven narrowly scoped tools. Shed Life remains the source of truth; this gateway calls its HTTP API and has no database or copied task store.

```text
ChatGPT → OpenAI Secure MCP Tunnel → tunnel-client → shed-mcp /mcp → Shed Life API
```

Operators are responsible for securing the downstream applications they expose. Run this single-account gateway on a trusted private host. It is not a remote administration interface. No shell, file, SQL, code-execution or arbitrary HTTP tools exist. MIT licensed; version 0.1.0 is pre-release.

## Tools

| Tool          | Behavior                                                                                    | Annotations                            |
| ------------- | ------------------------------------------------------------------------------------------- | -------------------------------------- |
| create_task   | Persist a requested actionable todo; title required, optional description/date/categories   | Write, non-destructive, non-idempotent |
| list_tasks    | Open tasks by default; status, today/overdue/upcoming, category and substring query filters | Read-only, idempotent                  |
| get_task      | One task by stable UUID                                                                     | Read-only, idempotent                  |
| update_task   | Only supplied title/description/due_date/categories; omitted fields unchanged               | Write, destructive, idempotent         |
| complete_task | Mark a known task completed                                                                 | Write, non-destructive, idempotent     |
| reopen_task   | Reopen a completed task                                                                     | Write, non-destructive, idempotent     |
| delete_task   | Permanent deletion, no undo; explicit request and confirm=true required                     | Write, destructive, idempotent         |

All tools set openWorldHint=false because they address one bounded private account. Annotations are hints, not permissions. IDs come from task results; clients should search and clarify ambiguous matches before writes. Categories are existing names resolved to backend IDs; they are never implicitly created.

`due_date` is a real date-only `YYYY-MM-DD`. `TIMEZONE` determines the reference date for list filters, not a timestamp conversion; explicit `today` overrides it. Today equals that date, overdue is before it, upcoming after it. Undated tasks match none. Filters combine with AND. Set status=all to include completed tasks. PATCH null clears due date; empty description clears notes; empty categories clears membership.

“Add buy milk for tomorrow” should create a task after resolving the date. “How should I organize my todo list?” should stay conversational. See [evaluation prompts](docs/EVALUATIONS.md).

## Local development

Install stable Rust (edition 2024) and Node.js 24+ for development tools, then:

```sh
npm ci
cp .env.example .env
# Edit the backend origin and timezone for your deployment.
npm run check
set -a
. ./.env
set +a
cargo run --locked
```

The gateway reads its environment; the example shell loads your trusted local .env. Systemd reads its private EnvironmentFile directly. Required backend configuration is validated at startup. Basic tests use a mock downstream and require no credentials. The production server uses the official Rust MCP SDK; [architecture and SDK choice](docs/ARCHITECTURE.md) records maturity and current protocol support. Node.js is needed only for tests and Inspector, not to run the gateway. Build a production executable with `cargo build --release --locked`.

## Configuration

| Environment variable | Default / requirement                                                                         |
| -------------------- | --------------------------------------------------------------------------------------------- |
| SHED_LIFE_BASE_URL   | Required HTTP(S) origin, e.g. http://127.0.0.1:8080; no path/query/credentials                |
| MCP_BIND_ADDRESS     | 127.0.0.1; explicit IPv4/IPv6 address                                                         |
| MCP_PORT             | 4317                                                                                          |
| REQUEST_TIMEOUT_MS   | 5000; 1–120000                                                                                |
| TIMEZONE             | UTC; IANA timezone, e.g. Europe/London                                                        |
| LOG_LEVEL            | info; error or silent also supported                                                          |
| MCP_ALLOWED_HOSTS    | localhost/loopback by default; comma-separated URL hostnames, required for non-loopback binds |

The stable Streamable HTTP endpoint is `/mcp`. `/healthz` reports gateway process health, not backend readiness. Success/failure tool logs include name, safe error code and latency without task payloads. Backend outages are reported on tool invocation.

## Compatible Shed Life API

Run your own compatible Shed Life service and configure its origin. Its v0.1.0 API must provide task GET/POST/PATCH/DELETE routes, completion/reopening, and category GET as described in [architecture](docs/ARCHITECTURE.md). Its documented default port is 8092; the generic .env.example origin is a placeholder. Never point this gateway at a database file.

Run the optional live lifecycle test only against a trusted gateway backed by a deployment you are authorized to modify:

```sh
MCP_TEST_URL=http://127.0.0.1:4317/mcp npm run verify:live
```

It creates one uniquely named temporary task, exercises all seven tools, deletes it, and verifies absence. It prints no personal task list. See [verification](docs/VERIFICATION.md).

## MCP Inspector

With the gateway running:

```sh
npx @modelcontextprotocol/inspector --web
# Select Streamable HTTP and http://127.0.0.1:4317/mcp through the Inspector proxy.
npx @modelcontextprotocol/inspector --cli http://127.0.0.1:4317/mcp --transport http --method tools/list
npm run verify:inspector
```

The automated Inspector verification creates a mock backend and temporary loopback gateway, discovers schemas/descriptions/annotations, invokes every tool and checks malformed input. The browser UI must use Inspector's local proxy because gateway Origin requests are rejected. Initialization and both modern discovery and legacy protocol behavior are SDK responsibilities; transport tests exercise them.

## Private deployment and ChatGPT

For a dedicated system service, adapt [the generic unit](examples/systemd/shed-mcp.service), create a dedicated service user, install the release executable as `/opt/shed-mcp/shed-mcp`, and keep a mode-0600 environment file under `/etc/shed-mcp/environment`. Keep the listener private, preferably loopback beside the tunnel client.

For a user service, run `cargo build --release --locked` first and create a private environment file outside tracked content:

```sh
chmod 600 /path/to/private/environment
python3 scripts/install-user-service.py --environment /path/to/private/environment
systemctl --user status shed-mcp.service
```

This installer writes the actual paths into the user's systemd configuration outside Git. It enables boot startup and restart-on-failure. User services need lingering to start without login; check `loginctl show-user "$USER" -p Linger` and arrange it with your administrator if necessary. No firewall or networking changes are required. See [deployment and Secure MCP Tunnel](docs/DEPLOYMENT.md) for current OpenAI UI steps, runtime credentials, doctor checks and persistent supervision.

OpenAI's [Secure MCP Tunnel guide](https://developers.openai.com/api/docs/guides/secure-mcp-tunnels) documents outbound-only connectivity. Provision a tunnel associated with your intended ChatGPT workspace, run the official tunnel client beside this gateway, then add a custom MCP server in ChatGPT with Connection → Tunnel. [NEEDS_USER.md](NEEDS_USER.md) lists steps requiring account access. A public source repository does not require a public MCP endpoint or public plugin submission.

## Security and limitations

Read [SECURITY.md](SECURITY.md) before deployment. This version has no OAuth, per-user account isolation, or internet-facing abuse protection. Loopback trusts local processes; tunnel access must be tightly scoped. Shared deployment requires MCP-compatible authentication and authorization at a private proxy. Do not expose the listener publicly.

Creation is not idempotent in the compatible backend. Writes are never automatically retried; after an uncertain outcome inspect state before retrying. Concurrent writes are last-write-wins. Lists are bounded by a 2 MB response limit and have no pagination until supported by the backend. Future inbox/habit/reminder/calendar/note or other app domains are intentionally unimplemented.

Keep real environment files, keys, tunnel identities, personal URLs, logs and task data outside Git. [CONTRIBUTING.md](CONTRIBUTING.md) describes checks; [PROJECT_STATUS.md](PROJECT_STATUS.md) records validation and release readiness. Do not publish until history and staged content have been audited.

Maintenance

ActivityMaintained
ResponsivenessNo issues