118 lines
4.3 KiB
Markdown
118 lines
4.3 KiB
Markdown
# 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
|
|
```
|
|
|
|
## Docker
|
|
|
|
```bash
|
|
docker compose up --build -d
|
|
docker compose logs -f totalmcp
|
|
```
|
|
|
|
## 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/
|
|
│ ├── 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
|
|
├── 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.
|