Files

122 lines
4.6 KiB
Markdown
Raw Permalink Normal View History

2026-05-09 22:18:00 -05:00
# totalmcp
Unified MCP gateway for Jason's ALPHA stack. One Dockerized server, hot-reloadable plugin architecture, three agent clients (Claude Code, Codex, Antigravity) all connecting to one stable endpoint.
- **Port:** `8811`
- **Static IP:** `10.2.0.35` (Unraid `br0`)
- **Registry:** `git.alwisp.com/jason/totalmcp`
- **Spec:** see [`PLAN.md`](PLAN.md) for the full architecture and phased roadmap
- **Service inventory:** see [`SERVICES.md`](SERVICES.md) for the catalog this gateway plugs into
## Quick Start (local dev)
```bash
cp .env.example .env # then fill in tokens
npm install
npm run prisma:generate
npm run dev # starts tsx watch on src/server.ts
```
Verify:
```bash
curl http://localhost:8811/health
# → { "status": "ok", "version": "0.1.0", "plugins": 0, "enabled": [] }
```
## Build & run
```bash
npm run build # tsc → dist/
npm start # node dist/server.js
```
2026-05-09 23:10:59 -05:00
## Docker (local dev)
2026-05-09 22:18:00 -05:00
```bash
docker compose up --build -d
docker compose logs -f totalmcp
```
2026-05-09 23:10:59 -05:00
## Unraid deployment
Step-by-step GUI walkthrough — paths, variables, ports, network — lives in [`INSTALL-UNRAID.md`](INSTALL-UNRAID.md). Covers the full deploy at `10.2.0.35:8811` plus a minimal "Gitea-plugin-only" starter config.
2026-05-09 22:18:00 -05:00
## Endpoints
| Method | Path | Auth | Purpose |
|--------|-------------|----------|--------------------------------------|
| GET | `/health` | none | Liveness — used by Unraid HEALTHCHECK |
| GET | `/plugins` | bearer | Loaded plugin list + tool counts |
| POST | `/mcp` | bearer | Streamable HTTP — primary MCP transport |
| GET | `/mcp` | bearer | Streamable HTTP server-sent stream |
| DELETE | `/mcp` | bearer | Streamable HTTP session close |
| GET | `/sse` | bearer | Legacy SSE (Antigravity) |
| POST | `/message` | bearer | Legacy SSE message channel |
## Authoring a plugin
Drop a directory under `src/plugins/<name>/index.ts` and `export default` an `MCPPlugin`. Tool names must be fully-qualified (`<service>_<action>`) and unique across all loaded plugins.
```typescript
import { z } from "zod";
import type { MCPPlugin } from "../../types/plugin.js";
const plugin: MCPPlugin = {
name: "example",
version: "0.1.0",
description: "Example plugin",
minGatewayVersion: "0.1.0",
tools: [
{
name: "example_ping",
description: "Returns pong",
inputSchema: z.object({}),
handler: async () => ({ result: "pong" }),
},
],
};
export default plugin;
```
Then add `example` to `ENABLED_PLUGINS` in `.env`. In dev (`npm run dev`), chokidar picks up the change in ~2s. In prod, push to Gitea and let CI rebuild the image.
Reference implementations live at [`src/plugins/gitea/`](src/plugins/gitea/index.ts) and [`src/plugins/unraid/`](src/plugins/unraid/index.ts).
## Repo layout
```
totalmcp/
├── src/
│ ├── server.ts # Express bootstrap
│ ├── registry.ts # Plugin loader + hot-reload
│ ├── config.ts # Zod env validation
│ ├── logger.ts # Structured JSON logger
│ ├── types/plugin.ts # MCPPlugin interface
│ ├── auth/bearer.ts # Per-agent token middleware
│ ├── mcp/build.ts # MCP server wiring
│ ├── transport/
│ │ ├── streamable.ts # Streamable HTTP transport
│ │ └── sse.ts # Legacy SSE transport
│ ├── util/http.ts # Shared HTTP helper (timeouts, JSON, errors)
│ └── plugins/
2026-05-09 22:59:43 -05:00
│ ├── gitea/index.ts # Phase 1 — Gitea REST API
│ ├── unraid/index.ts # Phase 1 — Unraid GraphQL API
│ ├── docker/index.ts # Phase 2 — Docker socket (dockerode)
│ ├── openclaw/index.ts # Phase 2 — OpenClaw/NOVA (Ollama-compatible)
│ ├── unifi/index.ts # Phase 3 — UniFi Access (developer REST)
│ ├── codex-mrp/index.ts # Phase 3 — CODEX MRP (direct SQLite)
│ ├── streamvault/index.ts # Phase 3 — StreamVault download manager
│ └── rackmapper/index.ts # Phase 3 — RackMapper datacenter inventory
2026-05-09 22:18:00 -05:00
├── prisma/schema.prisma # Event log schema
├── Dockerfile
├── docker-compose.yml
├── .env.example
└── package.json
```
## Roadmap
See [`PLAN.md`](PLAN.md) for the full phased plan. Phase 0 (this scaffold) is intentionally minimal — empty registry, both transports respond, Docker image builds, container boots clean.