Skip to main content
Glama
File Notes MCP Server

File Notes MCP Server

by UshatJoshi
README.md
# File Notes MCP Server

A beginner-level MCP (Model Context Protocol) server built with Python and FastMCP. It lets any MCP-compatible client create, list, read, search and delete plain-text notes. Notes are stored as `.txt` files in a local `notes/` folder.

## Features

- Five MCP tools for managing notes
- Notes stored as plain `.txt` files (no database)
- Title validation to block empty names, path traversal (`../`) and unsupported characters
- Clear error messages; errors never crash the server

## Tech Stack

| Component | Purpose |
|---|---|
| Python 3.10+ | Programming language |
| FastMCP (official `mcp` Python SDK) | Exposes Python functions as MCP tools |
| `pathlib`, `re` (standard library) | File handling and title validation |
| MCP Inspector | Browser-based client used to test the server |

## Project Structure

```
file-notes-mcp/
├── server.py          # MCP server (entry point)
├── requirements.txt   # Dependencies
├── notes/             # Stored notes (sample data only)
├── screenshots/       # Demo screenshots
└── README.md
```

## Installation

1. Clone the repository and enter the folder:
   ```bash
   git clone <your-repo-url>
   cd file-notes-mcp
   ```
2. (Optional, recommended) Create and activate a virtual environment:
   ```bash
   # Windows
   python -m venv .venv
   .venv\Scripts\activate

   # macOS / Linux
   python3 -m venv .venv
   source .venv/bin/activate
   ```
3. Install dependencies:
   ```bash
   pip install -r requirements.txt
   ```

## Starting the Server

```bash
python server.py
```

The server uses the STDIO transport, so it is normally launched by a client rather than used directly in the terminal.

## Connecting with MCP Inspector

1. Run:
   ```bash
   mcp dev server.py
   ```
   (Alternative: `npx @modelcontextprotocol/inspector python server.py`. This needs Node.js.)
2. Open the local URL printed in the terminal.
3. Set Transport Type to **STDIO**, Command to `python`, Arguments to `server.py`, then click **Connect**.
4. Open the **Tools** tab and click **List Tools**.

## Tools

| Tool | Input | Behavior |
|---|---|---|
| `create_note` | `title`, `content` | Creates a `.txt` note; rejects duplicate titles |
| `list_notes` | none | Returns all note titles, sorted |
| `read_note` | `title` | Returns the note content; clear error if missing |
| `search_notes` | `keyword` | Returns titles of notes matching the keyword, case-insensitive |
| `delete_note` | `title` | Deletes a note; clear error if missing |

> `search_notes` searches note **content**.

## Example Tool Calls

**create_note**
```json
{ "title": "MCP Architecture", "content": "The client connects to the server using JSON-RPC." }
```
Result: `Note 'MCP Architecture' created successfully.`

**list_notes**
```json
{}
```
Result: `["AI", "Internship Assignment", "MCP Architecture"]`

**read_note**
```json
{ "title": "MCP Architecture" }
```
Result: the content of the note.

**search_notes**
```json
{ "keyword": "connects" }
```
Result: `["MCP Architecture"]`

**delete_note**
```json
{ "title": "AI" }
```
Result: `Note 'AI' deleted successfully.`

## Title Validation Rules

- Titles cannot be empty or only spaces
- Only letters, numbers, spaces, underscores (`_`) and hyphens (`-`) are allowed
- Path traversal (`../`) and slashes are rejected
- The resolved file path must stay inside the `notes/` folder

## Error Handling

All errors are returned to the client as clear messages and the server keeps running.

| Case | Example input | Result |
|---|---|---|
| Duplicate title | `create_note` with an existing title | `A note titled '...' already exists.` |
| Unknown title | `read_note` / `delete_note` with a missing title | `Note '...' does not exist.` |
| Unsafe title | `../secret` | `Invalid title. Use only letters, numbers, spaces, underscores, and hyphens.` |
| Empty title | `""` | `Note title cannot be empty.` |

## Demo Sequence

1. Create two notes
2. List notes
3. Read one note
4. Search by a word from its content
5. Delete one note
6. List notes again
7. Test the error cases: duplicate, unknown and unsafe title




## Notes

- The server uses STDIO transport (one client per server process).
- To let multiple clients share one running server, change the last line of `server.py` to `mcp.run(transport="streamable-http")`.
- The `notes/` folder contains sample data only.