Official Model Context Protocol (MCP) server for Hillnote, enabling AI assistants to interact with your document workspaces programmatically.
Platform Support: Currently supports macOS. Windows support coming soon with Hillnote for Windows launch.
- π 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
- π Tasklist Management - Create and manage Kanban-style tasklists with full task CRUD operations
- π·οΈ Metadata Support - Rich document metadata with tags, emojis, and descriptions
- macOS (Windows support coming soon)
- Hillnote Desktop App for macOS
- Node.js >= 18.0.0
- MCP-compatible client (Claude Desktop, Cursor, VS Code, etc.)
# 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/-g flag is required for global installation. Without it, the package installs locally and won't work with the Claude Desktop configuration.
# 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# 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.)# 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 clientTo 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 versionIf you experience issues after updating:
-
Clear npm cache:
npm cache clean --force
-
Uninstall and reinstall:
npm uninstall -g @hillnote/mcp-server npm install -g @hillnote/mcp-server
-
Restart your MCP client completely (not just reload - fully quit and reopen)
The MCP server automatically discovers all your Hillnote workspaces from the app's configuration at ~/Library/Application Support/Hillnote/workspaces.json.
If installed via NPM, use your global Node modules path:
{
"mcpServers": {
"hillnote": {
"command": "hillnote-mcp"
}
}
}Find your path with: npm root -g
If cloned from GitHub:
{
"mcpServers": {
"hillnote": {
"command": "node",
"args": ["/path/to/hillnote-mcp-server/index.js"]
}
}
}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.
Lists all available workspaces with document counts and metadata.
// No input required
// Returns: Array of workspace objects with path, name, overview, and documentCountGet complete workspace overview including all documents, folders, and relationships.
// Input: { workspace: "workspace-name" }
// Returns: Complete registry with documents and folder structureRead a specific document's content and metadata.
// Input: { workspace: "workspace-name", documentId: "doc-id" }
// Returns: Document content, metadata, and frontmatterCreate 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 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 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 a document from the workspace.
// Input: { workspace: "workspace-name", documentId: "doc-id" }
// Returns: { success: true }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 scoresInsert 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 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 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 content to a specific markdown section.
// Input: {
// workspace: "workspace-name",
// documentId: "doc-id",
// sectionHeading: "## Notes",
// content: "Additional notes"
// }
// Returns: { success: true }List all AI prompt recipes in a workspace.
// Input: { workspacePath: "/path/to/workspace" }
// Returns: Array of recipe objects with metadataGet a specific recipe by ID.
// Input: { workspacePath: "/path/to/workspace", recipeId: "recipe-id" }
// Returns: Complete recipe with prompts and configurationCreate a new AI prompt recipe.
// Input: {
// workspacePath: "/path/to/workspace",
// name: "Recipe Name",
// description: "What this recipe does",
// prompts: [...],
// config: {...}
// }
// Returns: { success: true, recipeId: "new-id" }Update an existing recipe.
// Input: { workspacePath: "/path/to/workspace", recipeId: "id", updates: {...} }
// Returns: { success: true }Delete a recipe.
// Input: { workspacePath: "/path/to/workspace", recipeId: "id" }
// Returns: { success: true }Create a new tasklist (Kanban board) in a workspace.
// Input: {
// workspace: "workspace-name",
// tasklist: {
// name: "Project Tasks",
// columns: [
// { name: "To Do", color: "blue" },
// { name: "In Progress", color: "orange" },
// { name: "Done", isDoneColumn: true, color: "green" }
// ],
// viewMode: "projects" // or "flat"
// }
// }
// Returns: { success: true, tasklistName: "...", tasklistPath: "documents/...", columns: [...] }List all tasklists in a workspace.
// Input: { workspace: "workspace-name" }
// Returns: Array of tasklists with task counts, project counts, and columnsRead a complete tasklist structure with all task metadata.
// Input: { workspace: "workspace-name", tasklist: "Project Tasks" }
// Returns: Complete tasklist with columns, projects, tasks, and metadata
// Note: Task content not included - use read_document to read task contentCreate a new task in a tasklist.
// Input: {
// workspace: "workspace-name",
// tasklist: "Project Tasks",
// task: {
// name: "Implement feature X",
// content: "Task description...",
// status: "To Do",
// project: "Backend", // optional
// priority: "high", // low, medium, high
// assignedTo: "[email protected]",
// startDate: "2024-01-01",
// endDate: "2024-01-15",
// isRecurring: false,
// emoji: "π₯"
// }
// }
// Returns: { success: true, taskName: "...", taskPath: "...", status: "..." }Move a task to a different column/status.
// Input: {
// workspace: "workspace-name",
// tasklist: "Project Tasks",
// taskName: "Implement feature X",
// newStatus: "In Progress"
// }
// Returns: { success: true, taskName: "...", oldStatus: "...", newStatus: "..." }Update task properties (priority, assignments, dates, recurring settings).
// Input: {
// workspace: "workspace-name",
// tasklist: "Project Tasks",
// taskName: "Implement feature X",
// metadata: {
// priority: "high",
// assignedTo: "[email protected]",
// startDate: "2024-01-01",
// endDate: "2024-01-15",
// isRecurring: true,
// recurrenceFrequency: "weekly" // daily, weekly, monthly, yearly
// }
// }
// Returns: { success: true, taskName: "...", updatedFields: [...] }Create an interactive HTML tool in the workspace.
// Input: {
// workspacePath: "/path/to/workspace",
// toolName: "calculator",
// description: "Scientific calculator",
// files: [
// { name: "index.html", content: "<!DOCTYPE html>..." },
// { name: "styles.css", content: "body { ... }" },
// { name: "script.js", content: "// JS code" }
// ]
// }
// Returns: { success: true, toolPath: "resources/html/calculator", url: "..." }List all HTML tools in a workspace.
// Input: { workspacePath: "/path/to/workspace" }
// Returns: Array of HTML tools with metadataGet a specific HTML tool's files.
// Input: { workspacePath: "/path/to/workspace", toolName: "calculator" }
// Returns: Tool info with all file contentsUpdate an HTML tool's files.
// Input: {
// workspacePath: "/path/to/workspace",
// toolName: "calculator",
// updates: { description: "...", files: [...] }
// }
// Returns: { success: true }Delete an HTML tool.
// Input: { workspacePath: "/path/to/workspace", toolName: "calculator" }
// Returns: { success: true }Hillnote workspaces on macOS are typically stored in your Documents folder or custom locations:
~/Documents/YourWorkspace/
βββ readme.md # Workspace overview
βββ documents-registry.json # Document metadata
βββ ai-recipes.json # AI prompt recipes
βββ documents/ # Markdown documents and tasklists
β βββ document-1.md
β βββ folder/
β β βββ document-2.md
β βββ Project Tasks/ # Tasklist (Kanban board)
β βββ tasklist.json # Tasklist configuration
β βββ task-1.md # Root-level task
β βββ Backend/ # Project folder
β βββ task-2.md # Task in project
βββ resources/ # Assets and tools
βββ images/ # Image attachments
βββ html/ # HTML tools
βββ tool-name/
βββ index.html
βββ assets/
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...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
β β βββ tasklist.js # Tasklist/Kanban management
β βββ utils/
β βββ helpers.js # Utility functions
βββ README.md
- 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
# Enable watch mode
npm run dev
# Run the server
npm startAll tools use structured error responses:
InvalidParams: Missing or invalid parametersInternalError: Server-side errorsMethodNotFound: Unknown tool name
- File operations are sandboxed to workspace directories
- No network requests are made
- Path traversal protection included
- Input validation on all operations
MIT - See LICENSE file
- Issues: GitHub Issues
- Email: [email protected]
- Documentation: Hillnote Docs
Built with β€οΈ by Rajath Bail