Skip to main content
Glama
README.md
# AWS DevOps Study KB

A self-hosted memo knowledge base for AWS DevOps Engineer Professional exam prep — **you don't
write the notes, your AI agent does.** Ask Claude, OpenWebUI, or any other agent a study question
("what's the baseline performance difference between gp3 and io2, and when would I pick each?"),
and it saves a well-structured, tagged memo here as a side effect of answering — grounded in
official AWS docs if it's also connected to the [AWS Knowledge MCP server](https://github.com/awslabs/mcp).
Ask again next week and the agent finds the memo instead of re-deriving the answer.

No folders, no manual organizing — every memo is flat, tagged, and full-text searchable. The web
UI is read-only by design: agents own all writes.

```
you: "explain EBS volume types, baseline performance, and when to pick each"
agent: [searches this KB — nothing found] [answers, grounded in AWS docs] [saves a memo,
        tagged ebs, storage, exam:resilient-cloud-solutions]

 ...two weeks later...

you: "remind me about EBS gp3 vs io2"
agent: [searches this KB — finds the memo] "Yep, saved this one already — gp3 baseline is
        3,000 IOPS / 125 MiB/s regardless of size..."
```

## How it works

One Node.js/TypeScript service exposes the same memo store three ways, so it works with whatever
your AI client speaks:

- **MCP** (`/mcp`, streamable-HTTP) — for Claude Code, Claude Desktop, OpenWebUI, or any other
  MCP-native client. Tools: `create_memo`, `search_memos`, `get_memo`, `list_tags`, `update_memo`,
  `delete_memo`.
- **REST + OpenAPI** (`/api/v1/*`, spec at `/openapi.json`) — for agent frameworks and bots that
  only do OpenAPI/REST tool-calling (custom GPT Actions, LibreChat, a homegrown Telegram bot, etc.).
- **Web UI** (`/`) — read-only browse/search/tag-filter view for you, gated by a simple
  cookie-session login. No create/edit forms exist at all — that's not an oversight, it's the point.

All three are thin adapters over one SQLite-backed service (search is FTS5 full-text + tag
filtering), so nothing can drift between what an MCP client sees and what a REST client sees — see
[`CLAUDE.md`](CLAUDE.md) for the architecture in more detail.

## Quickstart

```bash
git clone <this-repo-url>
cd aws-devops-study-kb
cp .env.example .env        # fill in API_BEARER_TOKEN and SESSION_COOKIE_SECRET (see below)
npm install
npm run dev                 # http://localhost:8000
```

Generate real secrets rather than leaving the `.env.example` placeholders:

```bash
openssl rand -hex 32   # → API_BEARER_TOKEN
openssl rand -hex 32   # → SESSION_COOKIE_SECRET
```

For a persistent, internet-reachable deployment (so a cloud-hosted agent or a Telegram bot can
reach it too), see [`docs/deployment.md`](docs/deployment.md) — Docker Compose + a Cloudflare
Tunnel, with no inbound ports to open.

## Connect an AI agent

Every consumer needs the bearer token from `.env` (`API_BEARER_TOKEN`) as
`Authorization: Bearer <token>`. Pick whichever path matches your client.

### MCP clients (Claude Code, Claude Desktop, OpenWebUI, …)

**Claude Code**, against a running deployment:
```bash
claude mcp add --transport http aws-devops-study-kb https://<your-host>/mcp \
  --header "Authorization: Bearer <API_BEARER_TOKEN>"
```

**Claude Desktop** or any client configured via a `mcpServers` JSON block:
```json
{
  "mcpServers": {
    "aws-devops-study-kb": {
      "type": "http",
      "url": "https://<your-host>/mcp",
      "headers": { "Authorization": "Bearer <API_BEARER_TOKEN>" }
    }
  }
}
```

**OpenWebUI**: add it as an MCP tool server (Settings → Tools) with the same URL + header, if your
OpenWebUI version has native MCP support.

Once connected, the server's MCP `instructions` field (read automatically by clients that honor
it) already nudges the model to search before answering and save memos unprompted — see
[`docs/agent-persona.md`](docs/agent-persona.md) if you want to make that behavior explicit and
reliable via a system prompt instead of relying on the client picking it up.

### OpenAPI/REST tool-calling clients

For anything that imports an OpenAPI spec rather than speaking MCP (custom GPT Actions, LibreChat,
a custom bot):
- Spec URL: `https://<your-host>/openapi.json` (bearer-token protected — fetch it with the header)
- A static copy is committed at `openapi/generated.json` if your client needs a file instead of a
  live fetch (regenerate with `npm run generate:openapi` after any schema change).
- Every call needs the same `Authorization: Bearer <API_BEARER_TOKEN>` header.

### Tag convention

There are no folders — tags are the only organizing structure, so agents need to use them
consistently. `exam:<domain>` for the 6 AWS DevOps Pro exam domains, plus freeform topic tags
(`ebs`, `s3`, `codepipeline`, …). Full convention, and where it's enforced/documented for agents,
in [`docs/tag-conventions.md`](docs/tag-conventions.md).

## Development

```bash
npm test              # vitest — memoService, REST API, and MCP tool round-trips
npm run typecheck      # tsc --noEmit
npm run build           # compiles to dist/ (used by the Docker image)
```

See [`CLAUDE.md`](CLAUDE.md) for the full architecture writeup (why SQLite+FTS5, why one shared
service layer, the auth model, known gotchas) if you're extending this.

## License

[MIT](LICENSE)