Skip to main content
Glama
tothdani562

nestjs-mcp-server

by tothdani562
README.md
# NestJS + GraphQL + MCP

NestJS alkalmazás, ahol GraphQL API és MCP szerver közös domain rétegen (Prisma + SQLite) keresztül működik. Az MCP toolok ugyanazokat a service-eket hívják, nem a GraphQL-t.

Az iterációs terv: [`iterations.md`](./iterations.md).

## Előfeltételek

- Node.js 20+
- npm

## Beállítás

```bash
npm install
cp .env.example .env
npx prisma migrate dev
```

Az `npm install` a `postinstall` scripttel legenerálja a Prisma Clientet (`src/generated/prisma`).

## Indítás

```bash
# fejlesztés (watch)
npm run start:dev

# build
npm run build

# production
npm run start:prod
```

Alapértelmezett port: `3000` (`PORT` a `.env`-ben).

## Ellenőrzés

- `GET /` → `Hello World!`
- `GET /health` → `{ "status": "ok" }`

```bash
curl http://localhost:3000/health
```

## Adatbázis (Prisma + SQLite)

- Séma: `prisma/schema.prisma`
- Config: `prisma.config.ts`
- SQLite fájl: `prisma/dev.db` (gitignored)
- Nest DI: `PrismaModule` / `PrismaService` (globális)

```bash
npx prisma migrate dev   # migráció fejlesztés közben
npx prisma generate      # client újragenerálása
```

## Notes domain

Tiszta domain réteg (nincs GraphQL/MCP függőség):

- `NotesService`: `findAll`, `findOne`, `create`, `update`, `remove`
- DTO-k: `CreateNoteDto`, `UpdateNoteDto`
- Entitás: `Note` (`id`, `title`, `content`, `createdAt`)

```bash
npm test   # tartalmazza a NotesService egységteszteket
```

## GraphQL API

Code-first Apollo GraphQL a `/graphql` endpointon (Apollo Sandbox böngészőben).

- Queries: `notes`, `note(id)`
- Mutations: `createNote`, `updateNote`, `deleteNote`
- Generált séma: `src/schema.gql`
- A resolverök csak a `NotesService`-t hívják

Példa:

```graphql
mutation {
  createNote(input: { title: "Hello", content: "World" }) {
    id
    title
    content
    createdAt
  }
}

query {
  notes {
    id
    title
  }
}
```

```bash
curl http://localhost:3000/graphql \
  -H "Content-Type: application/json" \
  -H "x-api-key: dev-secret-change-me" \
  -d '{"query":"{ notes { id title } }"}'
```

## MCP server (Streamable HTTP)

`@rekog/mcp-nest` Streamable HTTP transport a `/mcp` endpointon. A toolok közvetlenül a `NotesService`-t hívják (nem GraphQL-t).

| Tool | Leírás |
|------|--------|
| `list_notes` | Összes note listázása |
| `get_note` | Egy note ID alapján |
| `create_note` | Új note (title + content) |
| `update_note` | Note frissítése |
| `delete_note` | Note törlése |

Bootstrap: `McpStrategy` + `StreamableHttpTransport` a `main.ts`-ben (`startAllMicroservices` a `listen` előtt).

## Cursor MCP kliens

A projekt tartalmazza a Cursor HTTP MCP configot: [`.cursor/mcp.json`](./.cursor/mcp.json).

### 1. Indítsd a szervert

```bash
npm run start:dev
```

Ellenőrizd: `http://localhost:3000/health` és hogy a logban megjelenik: `MCP streamable-http transport mounted at /mcp`.

### 2. Engedélyezd a szervert Cursorban

1. Nyisd meg **Cursor Settings → Tools & MCP**
2. A `nestjs-notes` szervernek zölden / connected állapotban kell lennie (a `.cursor/mcp.json` alapján)
3. Ha nem jelenik meg: Reload Window, vagy add hozzá manuálisan:

```json
{
  "mcpServers": {
    "nestjs-notes": {
      "url": "http://localhost:3000/mcp",
      "headers": {
        "x-api-key": "dev-secret-change-me"
      }
    }
  }
}
```

### 3. Manuális ellenőrzés chatből

Agent módban kérd pl.:

> Használd a `create_note` MCP toolt: title `From Cursor`, content `hello`

Majd GraphQL-ben ellenőrizd:

```graphql
query {
  notes {
    id
    title
    content
  }
}
```

vagy:

```bash
curl http://localhost:3000/graphql \
  -H "Content-Type: application/json" \
  -H "x-api-key: dev-secret-change-me" \
  -d "{\"query\":\"{ notes { id title } }\"}"
```

### MCP kliens smoke (CLI)

Szerver futása mellett:

```bash
npm run smoke:mcp
```

Ez initialize → `tools/list` → `create_note` hívást végez a `/mcp` endpointon.

### Opcionális: STDIO transport

Ugyanazok a Notes toolok helyi subprocessként (GraphQL nélkül). Előbb build:

```bash
npm run build
```

Cursor / más kliens példa (projekt gyökérből):

```json
{
  "mcpServers": {
    "nestjs-notes-stdio": {
      "command": "node",
      "args": ["dist/main.stdio.js"]
    }
  }
}
```

Állítsd a Cursor working directory-jét a projekt gyökerére, vagy add meg abszolút `args` útvonalat a `dist/main.stdio.js`-hez.

vagy közvetlenül:

```bash
npm run start:mcp:stdio
```

A STDIO módban a stdout a protokollé — ne kapcsolj be Nest logger t.

## Seed, validáció, smoke (DX)

**DX** = *Developer Experience* — a fejlesztői élmény: gyors seed, smoke script, érthető hibák, logging.

### Seed

```bash
npm run prisma:seed
# vagy: npx prisma db seed
```

Három példa note kerül az adatbázisba (`prisma/seed.ts`).

### Validáció és hibák

- GraphQL: `class-validator` a DTO-kon + globális `ValidationPipe`
- MCP: szigorú Zod sémák (`notes.schemas.ts`) a tool paramétereken
- Domain: `NotesService` is Zod-dal validál (közös szabályok)
- Hiányzó note: GraphQL `NotFoundException`, MCP tool `isError: true` + üzenet

### Smoke

Szerver futása mellett:

```bash
npm run smoke        # auth 401 + GraphQL + MCP
npm run smoke:mcp    # csak MCP kliens smoke (API key-vel)
```

## Auth, rate limit, környezetek

### API key

A `/graphql` és `/mcp` endpointok `x-api-key` headert várnak (`API_KEY` a `.env`-ben). A `/` és `/health` nyilvános.

```bash
curl http://localhost:3000/graphql \
  -H "Content-Type: application/json" \
  -H "x-api-key: dev-secret-change-me" \
  -d '{"query":"{ notes { id title } }"}'
```

Kulcs nélkül → **401**.

### Rate limit + timeout

- HTTP `/graphql` + `/mcp`: IP+path alapú limit (`THROTTLE_LIMIT` / `THROTTLE_TTL_MS`)
- Nest Throttler a GraphQL resolverökön
- Tool/resolver timeout: `MCP_TOOL_TIMEOUT_MS` (alap 10s)

### Környezetek

| Fájl | Cél |
|------|-----|
| `.env.development` | Helyi fejlesztés (lazább limit) |
| `.env.demo` | Demo / szigorúbb limit, külön DB |
| `.env` | Közös / fallback értékek |

```bash
# development (alap)
npm run start:dev

# demo
set APP_ENV=demo
npm run start:dev
```

`ConfigModule` betöltési sorrend: `.env.<APP_ENV>` → `.env`.

### Több MCP kliens példa

- Cursor (projekt): [`.cursor/mcp.json`](./.cursor/mcp.json)
- Cursor + STDIO: [`examples/mcp-clients/cursor.mcp.json`](./examples/mcp-clients/cursor.mcp.json)
- Más HTTP MCP kliens: [`examples/mcp-clients/http-client.mcp.json`](./examples/mcp-clients/http-client.mcp.json)

Cursor config (API key headerrel):

```json
{
  "mcpServers": {
    "nestjs-notes": {
      "url": "http://localhost:3000/mcp",
      "headers": {
        "x-api-key": "dev-secret-change-me"
      }
    }
  }
}
```

A STDIO transport helyi folyamat — HTTP API key nem vonatkozik rá.

## Környezeti változók

| Változó | Leírás | Alapértelmezés |
|---------|--------|----------------|
| `PORT` | HTTP szerver port | `3000` |
| `DATABASE_URL` | SQLite connection string | `file:./prisma/dev.db` |
| `APP_ENV` | `development` / `demo` | `development` |
| `API_KEY` | `x-api-key` a GraphQL/MCP-hez | — (kötelező a védett route-okhoz) |
| `THROTTLE_TTL_MS` | Rate limit ablak | `60000` |
| `THROTTLE_LIMIT` | Max kérések / ablak | `60` |
| `MCP_TOOL_TIMEOUT_MS` | Tool/resolver timeout | `10000` |

Másold a `.env.example` fájlt `.env`-re, és igazítsd a helyi értékeket. A `.env` nincs a gitben.

## Dependency notes

- `overrides.ws` → patched `ws@8.21.3` (Nest GraphQL transitive CVE)
- `.npmrc` `legacy-peer-deps=true` → elnyomja a Nest Apollo / deprecated GraphQL Playground peer konfliktust (Apollo 5 + `playground: false` mellett biztonságos)
- Maradék: `@hono/node-server` moderate (MCP SDK 1.x függőség) — 2.x override eltöri az `@modelcontextprotocol/node`-ot, amíg az upstream frissül