Skip to main content
Glama
PyaePhyo-Win

mcp-note-app

by PyaePhyo-Win

MCP Note App

A full-stack note-taking application with a React UI, Express/SQLite backend, real-time Server-Sent Events, JWT auth, and AI agent integration through the Model Context Protocol (MCP).

What You Get

  • Create, edit, delete, tag, and search notes in a modern React interface.

  • Live UI refreshes through SSE when notes change through REST or MCP tools.

  • JWT-protected REST note routes with local API-key login.

  • MCP SSE transport for AI clients and a Python Gemini-powered CLI agent.

  • SQLite persistence via a repository layer.

Related MCP server: Bruin

Architecture

┌─────────────────┐     MCP/SSE      ┌──────────────────┐
│  Python Agent   │ ◄──────────────► │                  │
│  (Gemini AI)    │                  │  Node.js Server  │
│                 │     Tools        │  (MCP + REST)    │
└─────────────────┘                  │                  │
                                     │    SQLite DB     │
┌─────────────────┐     REST/SSE     │                  │
│  React Frontend │ ◄──────────────► │                  │
│ (Vite+Tailwind) │                  └──────────────────┘
└─────────────────┘
  • Backend: TypeScript, Express, MCP server, SQLite (better-sqlite3), Zod, JWT.

  • Frontend: React 18, Vite, Tailwind CSS, TanStack React Query, Zustand, SSE.

  • Agent: Python MCP client connected to Google Gemini (gemini-2.5-flash by default).

Prerequisites

  • Node.js 20+ recommended.

  • npm.

  • Python 3.10+ recommended.

  • A Gemini API key for the optional Python agent.

Quick Start

1. Install dependencies

Install everything from the repository root:

npm run install:all

Or install each layer manually:

npm install --prefix server
npm install --prefix client-ui
python3 -m venv agent/.venv
agent/.venv/bin/python -m pip install -r agent/requirements.txt

Install the root orchestration dependency only if needed:

npm install

2. Configure environment

Create server/.env:

PORT=3000
NODE_ENV=development
JWT_SECRET=change-this-to-a-long-random-secret-at-least-32-chars
JWT_EXPIRY=15m
JWT_REFRESH_EXPIRY=7d
DATABASE_PATH=./data/notes.db
CORS_ORIGIN=http://localhost:5173
AUTH_TOKEN=dev-auth-token-change-in-production

Create agent/.env if you plan to use the Gemini agent:

GEMINI_API_KEY=your-gemini-api-key

Optional stdio transport variables for the agent:

MCP_STDIO_CMD=npx
MCP_STDIO_ARGS=tsx,server/src/index.ts

Do not commit .env files, API keys, JWT secrets, or local SQLite database files.

3. Start the app

Start backend and frontend together:

npm run dev

Or run them separately:

npm run dev:server
npm run dev:client

Then open the frontend at http://localhost:5173.

4. Start the AI agent

Make sure the backend is running first, then run:

npm run dev:agent

One-shot example:

agent/.venv/bin/python agent/agent.py --one-shot "Create a note titled Demo with content Hello from Gemini"

Scripts

Run these from the repository root unless noted otherwise.

Command

Description

npm run install:all

Install server, client, and Python agent dependencies.

npm run install:agent

Create agent/.venv and install Python dependencies.

npm run dev

Start backend and frontend concurrently.

npm run dev:server

Start only the Express/MCP server.

npm run dev:client

Start only the Vite frontend.

npm run dev:agent

Start the Python Gemini MCP agent.

npm run build

Build server and client.

npm run build --prefix server

Type-check/build backend.

npm run build --prefix client-ui

Type-check/build frontend.

npm run test --prefix client-ui

Run frontend unit tests with Vitest.

npm run test:e2e --prefix client-ui

Run Playwright end-to-end tests.

Project Structure

mcp-note-app/
├── server/                          # Express REST API, MCP server, SQLite persistence
│   ├── src/
│   │   ├── auth/                    # JWT signing and verification
│   │   ├── config/                  # Environment validation
│   │   ├── db/                      # SQLite connection and schema
│   │   ├── events/                  # Event bus and SSE handlers
│   │   ├── mcp/                     # MCP tool server and transports
│   │   ├── middleware/              # Auth, CORS, error handling
│   │   ├── repositories/            # NoteRepository + SQLite implementation
│   │   ├── routes/                  # Notes REST routes and live updates
│   │   ├── types.ts                 # Zod schemas and shared backend types
│   │   └── index.ts                 # Express entry point
│   └── package.json
├── client-ui/                       # React frontend
│   ├── e2e/                         # Playwright tests
│   ├── src/
│   │   ├── components/              # Presentational and UI components
│   │   ├── hooks/                   # React Query and SSE hooks
│   │   ├── services/                # API client and query client
│   │   ├── stores/                  # Zustand auth/UI state
│   │   ├── test/                    # Vitest setup and component tests
│   │   ├── types/                   # Frontend note types
│   │   ├── App.tsx
│   │   └── main.tsx
│   └── package.json
├── agent/                           # Python MCP + Gemini CLI agent
│   ├── agent.py
│   ├── mcp_gemini_adapter.py
│   └── requirements.txt
├── AGENTS.md                        # Coding-agent project guidance
├── README.md
└── package.json                     # Root orchestration scripts

Environment Variables

Server

Variable

Default

Description

PORT

3000

Express server port.

NODE_ENV

development

Runtime environment.

JWT_SECRET

required

Secret for JWT signing. Must be at least 32 characters.

JWT_EXPIRY

15m

Access token lifetime.

JWT_REFRESH_EXPIRY

7d

Refresh token lifetime.

DATABASE_PATH

./data/notes.db

SQLite database path, relative to server/ when running server scripts.

CORS_ORIGIN

http://localhost:5173

Allowed frontend origin.

AUTH_TOKEN

required

Development API key used by /api/login.

Agent

Variable

Default

Description

GEMINI_API_KEY

required for agent

Google Gemini API key.

MCP_STDIO_CMD

npx

Command used for agent stdio transport.

MCP_STDIO_ARGS

tsx,server/src/index.ts

Comma-separated stdio command args.

API Endpoints

Method

Path

Auth

Description

POST

/api/login

API key

Login with { "apiKey": "..." }; returns access and refresh tokens.

POST

/api/refresh

Refresh token

Body: { "refreshToken": "..." }; returns a new access token.

GET

/api/notes

JWT

List notes. Query params: query, limit, offset.

POST

/api/notes

JWT

Create a note with title, optional content, optional tags.

GET

/api/notes/:id

JWT

Get one note.

PUT

/api/notes/:id

JWT

Update note fields.

DELETE

/api/notes/:id

JWT

Delete a note.

GET

/api/live-updates

none

SSE stream for frontend refresh events.

GET

/sse

none

MCP SSE connection endpoint.

POST

/messages

none

MCP JSON-RPC message endpoint.

GET

/api/health

none

Health check.

Note payloads

Create note:

{
  "title": "Meeting notes",
  "content": "Discuss launch plan",
  "tags": ["work", "planning"]
}

Update note:

{
  "title": "Updated title",
  "content": "Updated content",
  "tags": ["updated"]
}

MCP Tools

The MCP server exposes these tools to AI clients:

Tool

Description

list_notes

List notes with optional search query, limit, and offset.

read_note

Read a single note by ID.

create_note

Create a note with title, optional content, and optional tags.

update_note

Update selected fields on an existing note.

delete_note

Delete a note by ID.

REST and MCP mutations both emit note update events so connected frontends can refresh through SSE.

Agent Usage

Interactive mode:

npm run dev:agent

Direct Python invocation:

agent/.venv/bin/python agent/agent.py --transport sse --url http://localhost:3000/sse

One-shot mode:

agent/.venv/bin/python agent/agent.py --one-shot "List my notes about planning"

Output formats:

# Script-friendly text, the default for --one-shot
agent/.venv/bin/python agent/agent.py --one-shot "List my notes" --format plain

# Rich Markdown, tool status, and note tables
agent/.venv/bin/python agent/agent.py --one-shot "List my notes" --format pretty

# One JSON object for scripts and integrations
agent/.venv/bin/python agent/agent.py --one-shot "List my notes" --format json

Interactive mode uses the rich terminal renderer by default. It supports persistent command history, completion for slash commands, and multiline prompts: press Esc then Enter to insert a newline, and press Enter to submit. Prompts in the same running process share conversation context, including relevant tool calls and results. Use /reset to forget the model context, or /history to inspect a bounded summary. Context is automatically trimmed at complete turn boundaries when it exceeds the memory budget; it is lost when the process exits. Use /help to view available commands.

Note IDs are full UUIDs. For delete, update, or read requests, you can identify a note by title instead of copying an ID: the agent will search with list_notes and use the exact ID from that result. Never use a shortened ID from a manually copied table value.

Options:

--transport sse|stdio   Transport protocol (default: sse)
--url URL               MCP server URL (default: http://localhost:3000/sse)
--model MODEL           Gemini model (default: gemini-2.5-flash)
--api-key KEY           Gemini API key; prefer GEMINI_API_KEY in agent/.env
--one-shot QUERY        Single query mode
--format FORMAT         Output format: plain, pretty, or json
--verbose               Show connection, turn, and tool-result details
--no-color              Disable ANSI color in pretty output
--history-file PATH     Override the interactive prompt history path
--memory-max-chars N    Approximate maximum model context size across turns (default: 24000)

Interactive commands:

/help                   Show command help
/tools                  List available MCP tools
/clear                  Clear the terminal
/reset                  Forget the current model conversation
/history                Show a summary of model conversation memory
/format [FORMAT]        View or set plain, pretty, or json output
/model [MODEL]          View or set the Gemini model for future prompts
/verbose [on|off]       View or set detailed logging
/quit                   Exit the agent

Frontend Notes

  • The Vite dev server runs on http://localhost:5173 and proxies API calls to the backend.

  • The app logs in with the development API key by default for local use.

  • Note operations use React Query and invalidate ['notes'] after mutations.

  • useSSE listens for backend update events and refreshes note queries live.

Validation

Recommended checks before committing application changes:

npm run build
npm run test --prefix client-ui
npm run test:e2e --prefix client-ui

For targeted changes:

npm run build --prefix server
npm run build --prefix client-ui

Troubleshooting

Server fails on startup with environment errors

Check server/.env. JWT_SECRET must be at least 32 characters and AUTH_TOKEN must be set.

Frontend cannot load notes

Make sure the backend is running on http://localhost:3000, the frontend is running through Vite, and CORS_ORIGIN matches http://localhost:5173.

Agent asks for a Gemini key

Create agent/.env with GEMINI_API_KEY=..., or pass --api-key for a one-off run.

Agent cannot connect to MCP

Start the backend first and verify http://localhost:3000/api/health returns {"status":"ok",...}. The default MCP endpoint is http://localhost:3000/sse.

Development Login

Default local API key:

dev-auth-token-change-in-production

Change this in server/.env for any non-local environment.

Related MCP Connectors

Related MCP Servers

  • F
    license
    B
    quality
    D
    maintenance
    A learning-focused MCP server that demonstrates core MCP concepts through a simple notepad application, enabling users to create, update, delete, and search notes while exploring tools, resources, and prompts functionality.
    4
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for AI agents to read, write, and organize notes in a local-first, human-in-the-loop note-taking app.
    0
    2
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    MCP server for a minimal note-taking app with text and images per user, enabling CRUD operations via Claude.
    -