mcp-home-server
by mgreenspan17
README.md
# mcp-home-server
Single, stable Model Context Protocol (MCP) "door" server that runs on your
home machine and exposes a **dynamic set of tools** to every connected AI
client (desktop, phone, future agents). Tools can be added, edited, or removed
at runtime — no restart needed.
Behind the door:
- **Dynamic tool loader** watches `src/tools/` and hot-reloads each module via
chokidar + the MCP SDK's `list_changed` notification.
- **JSON manifest** is regenerated automatically and served at `GET /manifest`.
- **URLTracker** ingests "AI usage" events, hashes them, and emits a
`url_tracker:new_ai` event the first time a URL is seen.
- **Onboarding agent** listens to those events and writes per-AI onboarding
payloads (`manifests/onboarding/<hash>.json`) so new clients can instantly
configure themselves to use this MCP host.
- **Scouting worker** periodically scans configured roots (`SCOUT_ROOTS`) for
scripts/modules that look like MCP tool candidates; proposals are written to
`manifests/pending/` for human review (no auto-promotion).
- **Dedupe worker** compares registered tools and writes overlap reports to
`docs/dedupe/` to surface merges/refactors.
## Quick start
```bash
git clone https://github.com/manniegreenspan/mcp-home-server.git
cd mcp-home-server
npm install
npm run dev
# Server binds 127.0.0.1 on the first free port in 7000-7999.
# Check console for the actual URL, e.g.: http://127.0.0.1:7432/mcp
```
Test it with the MCP Inspector:
```bash
npx @modelcontextprotocol/inspector@latest
# Paste the MCP endpoint URL into the inspector.
```
## Endpoints
| Path | Method | Purpose |
| ------------------- | ------ | ------------------------------------------------ |
| `/mcp` | POST/GET | MCP Streamable HTTP endpoint (JSON-RPC) |
| `/manifest` | GET | JSON manifest of currently registered tools |
| `/url-track` | POST | URLTracker ingestion: `{ "url": "...", "source": "..." }` |
| `/health` | GET | Liveness + last chokidar refresh |
## Adding a tool
Drop a file in `src/tools/`:
```ts
// src/tools/hello-world.ts
import { z } from "zod";
import type { ToolModule } from "../lib/types";
export default {
name: "hello_world",
description: "Says hello to a name",
inputSchema: { name: z.string().describe("Name to greet") },
handler: async ({ name }) => ({
content: [{ type: "text", text: `Hello, ${name}!` }]
})
} satisfies ToolModule;
```
The loader picks it up immediately, registers it with the MCP server, and
sends the `notifications/tools/list_changed` notification. Connected clients
(Inspector, Claude Desktop, etc.) refresh their tool list automatically.
Delete the file → tool unregistered. Edit the file → tool re-registered.
## Cloudflare deployment
See [`docs/DEPLOYMENT.md`](docs/DEPLOYMENT.md). v1 recommends **Cloudflare
Tunnel** fronting the local Express server. A pure-Cloudflare-Worker rewrite
is in the ROADMAP (Workers can't do dynamic `import()` of `src/tools/*.ts`).
## Project layout
```
mcp-home-server/
├── src/
│ ├── server.ts # main entry: Express + McpServer + transports
│ ├── ports.ts # port scan 7000-7999
│ ├── manifest.ts # generate/serve JSON manifest
│ ├── logger.ts # pino instance
│ ├── event-bus.ts # shared EventEmitter
│ ├── tools/ # dynamic tool modules (one file per tool)
│ ├── workers/ # onboarding-agent, scouting-worker, dedupe-worker
│ ├── url-tracker/ # ingestion + detector + hash store
│ └── lib/ # types, hashing
├── manifests/
│ ├── current.json # auto-regenerated manifest
│ ├── pending/ # scout proposals (manual review)
│ └── onboarding/ # onboarding payloads written by agent
├── docs/
│ ├── DEPLOYMENT.md
│ ├── ARCHITECTURE.md
│ └── dedupe/ # dedupe-worker reports
├── tests/
└── logs/
```
## License
MIT — see [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues