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

Private **shared memory** POC for the Silex talk *MCP + second cerveau*: **OKF markdown notes** + **links** (optional human summary). Same brain via **web UI** and **MCP** (read + write).

> **Auth:** shared API key (`Authorization: Bearer …` or `X-API-Key`).  
> Rate limit: **3 adds / min** and **3 modifications / min** per IP.

## What you can share

| Kind | Format | Rules |
|------|--------|--------|
| **Note** | Markdown + [Open Knowledge Format](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md) frontmatter | `type` required; optional `title`, `description`, `resource`, `tags`, `timestamp` |
| **Link** | URL ± title ± tags ± **summary** | Summary is **human-only** (never server-generated). List `needs_summary` to contribute. |

Notes are vectorized (when Workers AI + Vectorize are bound). Links are vectorized **only if** a summary is present.

## Monorepo

```
apps/api          Hono Worker — REST + MCP + D1 + (optional) Vectorize/AI
apps/web          TanStack Router + React Query — private UI R/W
packages/shared   OKF parser/validator + Zod schemas
plugins/demo-mcp  Claude Code plugin (MCP + skills)
.claude-plugin/   Marketplace manifest (install from this repo)
```

## Claude Code plugin

MCP alone = tools. **Plugin = MCP + skills** (when/how to use OKF, no auto-summaries, rate limits).

```bash
claude plugin marketplace add MickaelV0/demo-mcp
claude plugin install demo-mcp@demo-mcp
# prompts for API key (sensitive userConfig)
```

Local:

```bash
claude --plugin-dir ./plugins/demo-mcp
```

See [`plugins/demo-mcp/README.md`](plugins/demo-mcp/README.md).

## Quick start

```bash
bun install

# Local API key — without it every /api/* and /mcp call returns 503
cp apps/api/.dev.vars.example apps/api/.dev.vars

# API (D1 local)
bun run dev:api
# → http://127.0.0.1:8787

# Web (proxies /api + /mcp to 8787)
bun run dev:web
# → http://127.0.0.1:5173
```

Apply local D1 migrations (first run / after schema change):

```bash
bun run db:migrate:local
```

> Examples below use the `.dev.vars.example` key (`dev-local-key`). Every
> `/api/*` and `/mcp` call needs it — `Authorization: Bearer …` or `X-API-Key`.

### Example: publish a note

```bash
curl -s http://127.0.0.1:8787/api/notes \
  -H 'authorization: Bearer dev-local-key' \
  -H 'content-type: text/markdown' \
  --data-binary @- <<'MD'
---
type: Note
title: Hello shared memory
tags: [demo, mcp]
---

Body in markdown. Link [[other]] or [x](./other.md).
MD
```

### Example: link without summary

```bash
curl -s http://127.0.0.1:8787/api/links \
  -H 'authorization: Bearer dev-local-key' \
  -H 'content-type: application/json' \
  -d '{"url":"https://example.com","tags":["reading"]}'
```

### MCP

```bash
claude mcp add demo-mcp --transport http http://127.0.0.1:8787/mcp \
  --header "Authorization: Bearer dev-local-key"
```

`POST /mcp` JSON-RPC: `initialize`, `tools/list`, `tools/call`.

## REST map

| Method | Path | Bucket |
|--------|------|--------|
| GET | `/api/notes`, `/api/notes/:id` | — |
| POST | `/api/notes` (OKF MD) | **add** |
| PUT | `/api/notes/:id` | **mod** |
| POST | `/api/notes/:id/edges` | **add** |
| GET | `/api/links?needs_summary=1` | — |
| POST | `/api/links` | **add** |
| PATCH | `/api/links/:id/summary` | **mod** |
| GET | `/api/search?q=` | — |
| GET | `/api/tags` | — |
| POST | `/mcp` | tools write → same buckets |

## Production

**URL:** https://demo-mcp.roxabi.dev  
(same origin: SPA + `/api/*` + `POST /mcp`)

Deploy (CF credentials in shell only — **never commit `.env`**):

```bash
export CLOUDFLARE_ACCOUNT_ID=b5e90be971920ce406f7b679c4f1cd33

bun install
bun --filter @demo-mcp/web build
bunx wrangler d1 migrations apply demo-mcp --remote --config apps/api/wrangler.toml
# set once (or rotate): do NOT put this in the repo
printf '%s' "$DEMO_MCP_API_KEY" | bunx wrangler secret put API_KEY --config apps/api/wrangler.toml
bunx wrangler deploy --config apps/api/wrangler.toml
```

Public without key: `GET /health` only. All `/api/*` and `/mcp` need the key.

Optional embeddings: create Vectorize index, uncomment `[[vectorize]]` in `apps/api/wrangler.toml`, redeploy.

## Design notes

- **POC auth** — one shared API key (Worker secret `API_KEY`), not full user accounts.
- **No `.env` in repo** — `wrangler.toml` `[vars]` for public config; secrets via `wrangler secret put`.
- **OKF only** for notes — invalid frontmatter → 400.
- **Double surface** — web curation + MCP action, one Hono API.
- Context: Silex talk *MCP, plugins & second cerveau*.

## License

MIT