Hillnote MCP Server
Official Model Context Protocol (MCP) server for Hillnote, enabling AI assistants to interact with your document workspaces programmatically.
Platform Support: Supports macOS, Windows, and Linux.
Features
- 📁 Multi-Workspace Support - Manage multiple document workspaces
- 📝 Document Management - Full CRUD operations for documents
- 🔍 Smart Search - Fuzzy search with intelligent ranking across titles, tags, and content
- ✏️ Content Manipulation - Advanced content editing with validation and preview
- 🎯 AI Recipes - Manage and execute AI prompt recipes
- 🛠️ HTML Tools - Create interactive HTML-based utilities
- 📋 Database & Task Management - Create databases with rows, columns, views, and kanban boards for task tracking
- 🎨 Slide Presentations - Two-phase slide creation with storytelling guides and visual design tools
- 🎨 Canvas Drawings - Create and edit Excalidraw canvas drawings with shapes, text, arrows, and more
- 🏷️ Metadata Support - Rich document metadata with tags, emojis, and descriptions
Requirements
- macOS, Windows, or Linux
- Hillnote Desktop App
- Node.js >= 18.0.0
- MCP-compatible client (Claude Desktop, Cursor, VS Code, etc.)
Installation
Option 1: Install from NPM (Recommended)
# Install globally (IMPORTANT: Use -g flag!)
npm install -g @hillnote/mcp-server
# Verify installation worked
npm list -g @hillnote/mcp-server
# If using Homebrew Node.js, the files will be in:
# /opt/homebrew/lib/node_modules/@hillnote/mcp-server/
⚠️ Important: The -g flag is required for global installation. Without it, the package installs locally and won't work with the Claude Desktop configuration.
Option 2: Install from Source
# Clone the repository
git clone https://github.com/HillnoteApp/hillnote-mcp-server.git
cd hillnote-mcp-server
# Install dependencies (NO -g flag needed here)
npm install
Updating to Latest Version
NPM Installation
# Update to the latest version
npm update -g @hillnote/mcp-server
# Or reinstall to force latest version
npm install -g @hillnote/mcp-server@latest
# Check current version
npm list -g @hillnote/mcp-server
# After updating, restart your MCP client (Claude Desktop, Cursor, etc.)
Source Installation
# Navigate to your cloned repository
cd /path/to/hillnote-mcp-server
# Pull latest changes
git pull origin main
# Reinstall dependencies
npm install
# After updating, restart your MCP client
Version Check
To see what version you're currently running:
# For NPM installation
npm list -g @hillnote/mcp-server
# For source installation
cd /path/to/hillnote-mcp-server
cat package.json | grep version
Troubleshooting Updates
If you experience issues after updating:
Clear npm cache:
npm cache clean --forceUninstall and reinstall:
npm uninstall -g @hillnote/mcp-server npm install -g @hillnote/mcp-serverRestart your MCP client completely (not just reload - fully quit and reopen)
Configuration
The MCP server automatically discovers all your Hillnote workspaces from the app's configuration:
- macOS:
~/Library/Application Support/Hillnote/workspaces.json - Windows:
%APPDATA%/Hillnote/workspaces.json - Linux:
~/.config/Hillnote/workspaces.json
Configuration Examples
NPM Installation
If installed via NPM, use your global Node modules path:
{
"mcpServers": {
"hillnote": {
"command": "hillnote-mcp"
}
}
}
Find your path with: npm root -g
Source Installation
If cloned from GitHub:
{
"mcpServers": {
"hillnote": {
"command": "node",
"args": ["/path/to/hillnote-mcp-server/index.js"]
}
}
}
Client-Specific Configuration
Claude Desktop
Location: ~/Library/Application Support/Claude/claude_desktop_config.json
Add the configuration above to this file.
Cursor
Location: Settings → Features → MCP
Add the configuration above to the MCP servers section.
VS Code
Install an MCP extension and add the configuration to your settings.json or extension configuration.
Available Tools
📁 Workspace Management
list_workspaces
Lists all available workspaces with document counts and metadata.
// No input required
// Returns: Array of workspace objects with path, name, overview, and documentCount
read_registry
Get complete workspace overview including all documents, folders, and relationships.
// Input: { workspace: "workspace-name" }
// Returns: Complete registry with documents and folder structure
📄 Document Operations
read_document
Read a specific document's content and metadata.
// Input: { workspace: "workspace-name", documentId: "doc-id" }
// Returns: Document content, metadata, and frontmatter
add_document
Create a new document with content and metadata.
// Input: {
// workspace: "workspace-name",
// name: "Document Name",
// content: "Document content",
// emoji: "📄",
// description: "Brief description",
// parent: "optional-folder-id"
// }
// Returns: { success: true, documentId: "new-id", fileName: "document-name.md" }
update_document
Update an existing document's content or metadata.
// Input: {
// workspace: "workspace-name",
// documentId: "doc-id",
// content: "New content",
// name: "New Name",
// emoji: "📝",
// description: "Updated description"
// }
// Returns: { success: true }
rename_document
Rename a document and update its file name.
// Input: { workspace: "workspace-name", documentId: "doc-id", newTitle: "New Title" }
// Returns: { success: true, newFileName: "new-title.md" }
delete_document
Delete a document from the workspace.
// Input: { workspace: "workspace-name", documentId: "doc-id" }
// Returns: { success: true }
🔍 Search
search_documents
Search documents with fuzzy matching and smart ranking.
// Input: {
// query: "search term",
// workspace: "optional-workspace",
// fuzzy: true,
// threshold: 0.6,
// limit: 10
// }
// Returns: Ranked search results with snippets and scores
✏️ Content Manipulation
insert_content
Insert content at a specific position with validation.
// Input: {
// workspace: "workspace-name",
// documentId: "doc-id",
// position: "start" | "end" | number | { line: number } | { after: "heading" },
// text: "Content to insert",
// validate: true,
// preview: true
// }
// Returns: { success: true, preview: "...", validation: {...} }
replace_content
Replace text in a document with preview and occurrence info.
// Input: {
// workspace: "workspace-name",
// documentId: "doc-id",
// searchText: "text to find",
// replaceText: "replacement text",
// all: false,
// caseSensitive: false,
// wholeWord: false,
// useRegex: false
// }
// Returns: { success: true, replacements: 1, preview: "..." }
delete_content
Delete content between positions or patterns.
// Input: {
// workspace: "workspace-name",
// documentId: "doc-id",
// startPos: 0 | { line: 5 } | { pattern: "## Section" },
// endPos: 100 | { line: 10 } | { pattern: "## Next Section" }
// }
// Returns: { success: true, deletedChars: 95, preview: "..." }
append_to_section
Append content to a specific markdown section.
// Input: {
// workspace: "workspace-name",
// documentId: "doc-id",
// sectionHeading: "## Notes",
// content: "Additional notes"
// }
// Returns: { success: true }
🎯 AI Recipe Management
Recipes are AI prompt overrides that trigger custom instructions when a user's request matches specific topics.
list_recipes
List all AI prompt recipes in a workspace.
// Input: { workspacePath: "/path/to/workspace" }
// Returns: Array of recipe objects with metadata
get_recipe
Get a specific recipe by ID.
// Input: { workspacePath: "/path/to/workspace", recipeId: "recipe-id" }
// Returns: Complete recipe with trigger, instructions, and document references
create_recipe
Create a new AI prompt recipe.
// Input: {
// workspacePath: "/path/to/workspace",
// recipe: {
// when_user_asks_about: "quarterly reports",
// override_instructions: "Use the company template and include KPIs...",
// required_documents: ["documents/template.md"],
// optional_documents: ["documents/past-reports.md"],
// output_format: "markdown"
// }
// }
// Returns: { success: true, recipe: { id: "recipe_...", ... } }
update_recipe
Update an existing recipe.
// Input: {
// workspacePath: "/path/to/workspace",
// recipeId: "recipe-id",
// updates: {
// when_user_asks_about: "updated trigger",
// override_instructions: "updated instructions"
// }
// }
// Returns: { success: true }
get_recipe_documents
Load the content of documents referenced by a recipe.
// Input: { workspacePath: "/path/to/workspace", recipeId: "recipe-id", includeOptional: true }
// Returns: { recipe: {...}, documents: { required: [...], optional: [...] } }
📋 Database & Task Management
Databases are flexible folders containing markdown files (rows) with a database.json configuration. They can be used as task boards by adding status columns with kanban views.
create_database
Create a new database in a workspace.
// Input: {
// workspace: "workspace-name",
// name: "Project Tasks",
// columns: [
// { id: "title", name: "Title", type: "title" },
// { id: "status", name: "Status", type: "status",
// options: ["To Do", "In Progress", "Done", "Archived"],
// optionColors: { "To Do": "gray", "In Progress": "amber", "Done": "emerald", "Archived": "purple" },
// optionStates: { "To Do": "normal", "In Progress": "normal", "Done": "done", "Archived": "archive" }
// },
// { id: "priority", name: "Priority", type: "select", options: ["Low", "Medium", "High"] },
// { id: "recurring", name: "Recurring", type: "recurring" }
// ],
// views: [
// { id: "kanban", name: "Board", type: "kanban", groupBy: "status" },
// { id: "table", name: "Table", type: "table" }
// ],
// defaultView: "kanban",
// folderPath: "optional/subfolder"
// }
// Returns: { success: true, name: "...", path: "..." }
Column types: title, text, number, select, multiselect, status, checkbox, date, url, email, recurring
Status columns support optionStates mapping each option to "normal", "done" (strikethrough), or "archive" (dimmed) — enabling kanban board behaviour.
Recurring columns support auto-resetting tasks on daily/weekly/monthly/yearly schedules.
read_database
Read a database with optional filtering, sorting, and searching.
// Input: {
// workspace: "workspace-name",
// databasePath: "Project Tasks",
// search: "optional search query",
// filters: [{ column: "status", operator: "equals", value: "In Progress" }],
// sort: { column: "priority", direction: "desc" },
// viewId: "kanban",
// limit: 50
// }
// Returns: Database config (columns, views) and matching rows
list_databases
List all databases in a workspace.
// Input: { workspace: "workspace-name" }
// Returns: Array of databases with metadata and row counts
delete_database
Delete a database and all its rows permanently.
// Input: { workspace: "workspace-name", databasePath: "Project Tasks" }
// Returns: { success: true }
add_rows
Add one or more rows to a database.
// Input: {
// workspace: "workspace-name",
// databasePath: "Project Tasks",
// rows: [
// { title: "Implement feature X", status: "To Do", priority: "High", _content: "Task details..." },
// { title: "Fix bug Y", status: "In Progress", priority: "Medium" }
// ]
// }
// Returns: { success: true, added: [...] }
update_rows
Update rows by ID (file path) or matching criteria.
// Input: {
// workspace: "workspace-name",
// databasePath: "Project Tasks",
// updates: { status: "Done", priority: "Low" },
// ids: ["/path/to/row.md"], // by file path
// where: { status: "In Progress" } // or by criteria
// }
// Returns: { success: true, updated: [...] }
delete_rows
Delete rows by ID or matching criteria.
// Input: {
// workspace: "workspace-name",
// databasePath: "Project Tasks",
// ids: ["/path/to/row.md"],
// where: { status: "Archived" }
// }
// Returns: { success: true }
add_column
Add a new column to a database.
// Input: {
// workspace: "workspace-name",
// databasePath: "Project Tasks",
// column: { id: "assignee", name: "Assignee", type: "text" },
// defaultValue: "Unassigned"
// }
// Returns: { success: true }
update_column
Update column properties (name, type, options, colors, states).
// Input: {
// workspace: "workspace-name",
// databasePath: "Project Tasks",
// columnId: "status",
// updates: { options: ["To Do", "In Progress", "Review", "Done"] }
// }
// Returns: { success: true }
delete_column
Remove a column from a database and all rows.
// Input: { workspace: "workspace-name", databasePath: "Project Tasks", columnId: "priority" }
// Returns: { success: true }
create_view
Create a saved view with filters, sorts, and display options.
// Input: {
// workspace: "workspace-name",
// databasePath: "Project Tasks",
// view: {
// name: "Active Tasks",
// type: "kanban", // table, kanban, gallery, chart
// groupBy: "status",
// filters: [{ column: "status", operator: "notEquals", value: "Archived" }],
// sorts: [{ column: "priority", direction: "desc" }]
// }
// }
// Returns: { success: true, viewId: "..." }
list_views
List all saved views for a database.
// Input: { workspace: "workspace-name", databasePath: "Project Tasks" }
// Returns: Array of view configurations
🎨 Slide Presentations
Slides use a two-phase workflow: write the story first, then add visual design.
get_slides_story_guide
Get the storytelling guide with 8 proven techniques (Hero's Journey, Sparklines, In Medias Res, etc.).
// No input required
// Returns: Story-writing guide with narrative techniques and structure advice
// Important: Do NOT use any visual layout markers (~split, ~inline, ~bg-, etc.) during this phase
get_slides_visual_guide
Get the visual design guide for adding layout markers, images, charts, and diagrams.
// Input: { documentPath: "documents/my-presentation.slides.md" }
// Returns: Visual design guide with layout markers, chart types, mermaid diagrams, and examples
// Note: Requires the .slides.md file to already exist (proves story has been drafted)
Important: When creating slides with add_document, the title MUST end with .slides.md (e.g., "My Presentation.slides.md"). The .slides.md extension is what makes it a slide presentation.
Example workflow:
// 1. Get the story guide first
get_slides_story_guide()
// 2. Create the slide presentation (story content only, no visual markers)
add_document({
workspace: "workspace-name",
name: "Quarterly Review.slides.md", // Note: ends with .slides.md
content: `---
type: slides
theme: minimal
---
# Quarterly Review
Q4 2024 Results
***
# Key Metrics
- Revenue: $1.2M
- Growth: 25%
- Users: 10,000+
`
})
// 3. Get the visual guide and enhance slides in batches of 3-5
get_slides_visual_guide({ documentPath: "documents/quarterly-review.slides.md" })
// Then edit the file to add ~split, ~inline, ~bg-, images, charts, etc.
🎨 Canvas Drawings
get_canvas_guide
Get the comprehensive guide for creating and editing Excalidraw canvas drawings in Hillnote.
// No input required
// Returns: Complete guide with element types, layout planning, spacing rules, colors, and best practices
Important: When creating a canvas with add_document, the title MUST end with .canvas.md (e.g., "Architecture Diagram.canvas.md"). Do NOT provide content — the system generates it automatically.
read_canvas
Read and parse a canvas file, returning a structured description of all elements.
// Input: { workspace: "workspace-name", canvasPath: "documents/my-drawing.canvas.md" }
// Returns: { canvasPath: "...", elementCount: 5, elements: [...] }
add_canvas_elements
Add shapes, text, arrows, and other elements to a canvas file.
// Input: {
// workspace: "workspace-name",
// canvasPath: "documents/my-drawing.canvas.md",
// elements: [
// { type: "rectangle", x: 0, y: 0, width: 200, height: 100, label: "Start", backgroundColor: "#a5d8ff" },
// { type: "arrow", x: 200, y: 50, points: [[0, 0], [100, 0]] },
// { type: "rectangle", x: 300, y: 0, width: 200, height: 100, label: "End", backgroundColor: "#b2f2bb" },
// { type: "text", x: 0, y: 120, text: "My Diagram", fontSize: 28 }
// ]
// }
// Returns: { success: true, added: 4, totalElements: 4, elementIds: [...] }
Supported element types: rectangle, ellipse, diamond, text, arrow, line
Element properties:
- Position/size:
x,y,width,height - Styling:
strokeColor,backgroundColor,fillStyle(solid/hachure/cross-hatch),strokeWidth,roughness(0-2),opacity(0-100) - Text:
text,fontSize,fontFamily(1=Virgil, 2=Helvetica, 3=Cascadia, 5=Excalifont),textAlign - Arrows/lines:
points(e.g.,[[0,0],[200,100]]),startArrowhead,endArrowhead - Shapes:
label(centered text inside rectangle/ellipse/diamond) - Grouping:
groupId
clear_canvas
Remove all elements from a canvas file, giving a blank slate.
// Input: { workspace: "workspace-name", canvasPath: "documents/my-drawing.canvas.md" }
// Returns: { success: true, message: "All elements cleared from canvas" }
Example workflow:
// 1. Get the canvas guide first
get_canvas_guide()
// 2. Create a new canvas
add_document({
workspace: "workspace-name",
name: "Architecture Diagram.canvas.md" // Note: ends with .canvas.md, no content needed
})
// 3. Add elements to the canvas
add_canvas_elements({
workspace: "workspace-name",
canvasPath: "documents/architecture-diagram.canvas.md",
elements: [
{ type: "text", x: 0, y: 0, text: "System Architecture", fontSize: 28 },
{ type: "rectangle", x: 0, y: 50, width: 200, height: 80, label: "Frontend", backgroundColor: "#a5d8ff" },
{ type: "arrow", x: 200, y: 90, points: [[0, 0], [100, 0]] },
{ type: "rectangle", x: 300, y: 50, width: 200, height: 80, label: "Backend", backgroundColor: "#b2f2bb" }
]
})
// 4. To redraw from scratch
clear_canvas({ workspace: "workspace-name", canvasPath: "documents/architecture-diagram.canvas.md" })
// Then add_canvas_elements again with new elements
🛠️ HTML Tool Management
add_html_tool
Create an interactive HTML tool in the workspace.
// Input: {
// workspacePath: "/path/to/workspace",
// toolName: "calculator",
// description: "Scientific calculator",
// category: "utilities", // optional
// files: [
// { filename: "index.html", content: "<!DOCTYPE html>...", isEntryPoint: true },
// { filename: "styles.css", content: "body { ... }" },
// { filename: "script.js", content: "// JS code" }
// ]
// }
// Returns: { success: true, path: "resources/html/calculator", entryPoint: "index.html", markdownLink: "[html:calculator](...)" }
edit_html_tool
Edit files in an existing HTML tool (create, update, or delete files).
// Input: {
// workspacePath: "/path/to/workspace",
// toolName: "calculator",
// category: "utilities", // optional
// operations: [
// { action: "update", filename: "index.html", content: "<!DOCTYPE html>..." },
// { action: "create", filename: "utils.js", content: "// new file" },
// { action: "delete", filename: "old-file.js" }
// ],
// updateMetadata: { description: "Updated calculator" }
// }
// Returns: { success: true, changes: { created: [...], updated: [...], deleted: [...] } }
add_tool_to_doc
Insert an HTML tool reference into a document.
// Input: {
// workspacePath: "/path/to/workspace",
// documentPath: "documents/my-doc.md",
// toolName: "calculator",
// displayName: "My Calculator", // optional
// position: "end" // "end", "beginning", or "after:<text>"
// }
// Returns: { success: true, toolLink: "[html:My Calculator](...)" }
list_html_tools
List all HTML tools in a workspace.
// Input: { workspacePath: "/path/to/workspace", category: "utilities" }
// Returns: Array of HTML tools with metadata and markdown links
get_html_tool
Get a specific HTML tool's details and files.
// Input: { workspacePath: "/path/to/workspace", toolName: "calculator", category: "utilities" }
// Returns: Tool info with all file contents, entry point, and markdown link
read_html_file
Read the content of a specific file inside an HTML tool.
// Input: { workspacePath: "/path/to/workspace", filePath: "resources/html/calculator/index.html" }
// Returns: { filePath: "...", content: "..." }
write_html_file
Write or create a file inside an HTML tool folder.
// Input: { workspacePath: "/path/to/workspace", filePath: "resources/html/calculator/style.css", content: "body { ... }" }
// Returns: { success: true, filePath: "..." }
replace_in_html_file
Find and replace text in an HTML tool file.
// Input: {
// workspacePath: "/path/to/workspace",
// filePath: "resources/html/calculator/index.html",
// searchText: "<title>Old Title</title>",
// replaceText: "<title>New Title</title>"
// }
// Returns: { success: true, filePath: "..." }
Workspace Structure
Hillnote workspaces are typically stored in your Documents folder or custom locations:
~/Documents/YourWorkspace/
├── readme.md # Workspace overview
├── documents-registry.json # Document metadata
├── ai_prompt_overrides.json # AI prompt recipes/overrides
├── documents/ # Markdown documents and databases
│ ├── document-1.md
│ ├── folder/
│ │ └── document-2.md
│ └── Project Tasks/ # Database (e.g., task board)
│ ├── database.json # Database configuration (columns, views)
│ ├── implement-feature-x.md # Row (task) with frontmatter
│ └── fix-bug-y.md # Row (task) with frontmatter
└── resources/ # Assets and tools
├── images/ # Image attachments
└── html/ # HTML tools
└── tool-name/
├── index.html
└── assets/
Document Format
Documents use Markdown with YAML frontmatter:
---
title: Document Title
tags: [tag1, tag2]
emoji: 📄
description: Brief description
created: 2024-01-01T00:00:00Z
modified: 2024-01-02T00:00:00Z
---
# Document Title
Your content here...
Development
Project Structure
mcp-server/
├── index.js # Main server entry point
├── config.json # Server configuration
├── package.json # Dependencies
├── src/
│ ├── tools/
│ │ ├── index.js # Tool aggregator
│ │ ├── workspace.js # Workspace tools
│ │ ├── document.js # Document tools
│ │ ├── content.js # Content manipulation
│ │ ├── search.js # Search tools
│ │ ├── recipe.js # Recipe management
│ │ ├── html-tool.js # HTML tool management
│ │ ├── database.js # Database, row, column, and view management
│ │ ├── slides.js # Slide presentation guides (story + visual)
│ │ └── canvas.js # Excalidraw canvas drawings
│ └── utils/
│ └── helpers.js # Utility functions
└── README.md
Adding New Tools
- Create a new tool file in
src/tools/ - Export tool definitions and handlers
- Import in
src/tools/index.js - Tools are automatically available to MCP clients
Running in Development
# Enable watch mode
npm run dev
# Run the server
npm start
Error Handling
All tools use structured error responses:
InvalidParams: Missing or invalid parametersInternalError: Server-side errorsMethodNotFound: Unknown tool name
Security
- File operations are sandboxed to workspace directories
- No network requests are made
- Path traversal protection included
- Input validation on all operations
License
MIT - See LICENSE file
Support
- Issues: GitHub Issues
- Email: support@hillnote.com
- Documentation: Hillnote Docs
Built with ❤️ by Rajath Bail