# Joplin MCP Server
A **FastMCP-based Model Context Protocol (MCP) server** for [Joplin](https://joplinapp.org/) note-taking application via its Python API [joppy](https://github.com/marph91/joppy), enabling AI assistants to interact with your Joplin notes, notebooks, and tags through a standardized interface.
## Table of Contents
- [What You Can Do](#what-you-can-do)
- [Quick Start](#quick-start)
- [Example Usage](#example-usage)
- [Tool Permissions](#tool-permissions)
- [Advanced Configuration](#advanced-configuration)
- [Project Structure](#project-structure)
- [Testing](#testing)
- [Complete Tool Reference](#complete-tool-reference)
## What You Can Do
This MCP server provides **18 optimized tools** for comprehensive Joplin integration:
### **Note Management**
- **Find & Search**: `find_notes`, `find_notes_with_tag`, `find_notes_in_notebook`, `get_all_notes`
- **CRUD Operations**: `get_note`, `create_note`, `update_note`, `delete_note`
### **Notebook Management**
- **Organize**: `list_notebooks`, `create_notebook`, `update_notebook`, `delete_notebook`
### **Tag Management**
- **Categorize**: `list_tags`, `create_tag`, `delete_tag`, `get_tags_by_note`
- **Link**: `tag_note`, `untag_note`
### **System**
- **Health**: `ping_joplin`
## Quick Start
### 1. Install the Package
```bash
pip install joplin-mcp
```
### 2. Configure Joplin
1. Open **Joplin Desktop** → **Tools** → **Options** → **Web Clipper**
2. **Enable** the Web Clipper service
3. **Copy** the Authorization token
### 3. Run Setup Script
```bash
joplin-mcp-install
```
This interactive script will:
- Configure your Joplin API token
- Set tool permissions (Create/Update/Delete)
- Set up Claude Desktop automatically
- Test the connection
### 4. Choose Your AI Client
#### Option A: Claude Desktop
After running the setup script, restart Claude Desktop and you're ready to go!
```
"List my notebooks" or "Create a note about today's meeting"
```
#### Option B: OllMCP (Local AI Models)
If Claude Desktop was configured above, you can run the following to detect joplin-mcp automatically by OllMCP (Ollama served agents).
```bash
# Install ollmcp
pip install ollmcp
# Run with auto-discovery and your preferred Ollama model, such as:
ollmcp --auto-discovery --model qwen3:4b
```
## Example Usage
Once configured, you can ask your AI assistant:
- **"List all my notebooks"** - See your Joplin organization
- **"Find notes about Python programming"** - Search your knowledge base
- **"Create a meeting note for today's standup"** - Quick note creation
- **"Tag my recent AI notes as 'important'"** - Organize with tags
- **"Show me my todos"** - Find task items with `find_notes(task=True)`
## Tool Permissions
The setup script offers **3 security levels**:
- **Read** (always enabled): Browse and search your notes safely
- **Write** (optional): Create new notes, notebooks, and tags
- **Update** (optional): Modify existing content
- **Delete** (optional): Remove content permanently
Choose the level that matches your comfort and use case.
---
## Advanced Configuration
### Alternative Installation (Development)
For developers or users who want the latest features:
#### macOS/Linux:
```bash
git clone https://github.com/alondmnt/joplin-mcp.git
cd joplin-mcp
./install.sh
```
#### Windows:
```batch
git clone https://github.com/alondmnt/joplin-mcp.git
cd joplin-mcp
install.bat
```
### Manual Configuration
If you prefer manual setup or the script doesn't work:
#### 1. Create Configuration File
Create `joplin-mcp.json` in your project directory:
```json
{
"token": "your_api_token_here",
"host": "localhost",
"port": 41184,
"timeout": 30,
"verify_ssl": false
}
```
#### 2. Claude Desktop Configuration
Add to your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"joplin": {
"command": "joplin-mcp-server",
"env": {
"JOPLIN_TOKEN": "your_token_here"
}
}
}
}
```
#### 3. OllMCP Manual Configuration
```bash
# Set environment variable
export JOPLIN_TOKEN="your_token_here"
# Run with manual server configuration
ollmcp --server "joplin:joplin-mcp-server" --model qwen3:4b
```
### Tool Permission Configuration
Fine-tune which operations the AI can perform by editing your config:
```json
{
"tools": {
"create_note": true,
"update_note": true,
"delete_note": false,
"create_notebook": true,
"delete_notebook": false,
"create_tag": true,
"delete_tag": false
}
}
```
### Environment Variables
Alternative to JSON configuration:
```bash
export JOPLIN_TOKEN="your_api_token_here"
export JOPLIN_HOST="localhost"
export JOPLIN_PORT="41184"
export JOPLIN_TIMEOUT="30"
```
### HTTP Transport Support
The server supports both STDIO and HTTP transports:
```bash
# STDIO (default)
joplin-mcp-server
# HTTP transport
python run_fastmcp_server.py --transport http --port 8000
```
# Claude Desktop HTTP config
```json
{
"mcpServers": {
"joplin": {
"transport": "http",
"url": "http://localhost:8000/mcp"
}
}
}
```
### Configuration Reference
#### Basic Settings
| Option | Default | Description |
|--------|---------|-------------|
| `token` | *required* | Joplin API authentication token |
| `host` | `localhost` | Joplin server hostname |
| `port` | `41184` | Joplin Web Clipper port |
| `timeout` | `30` | Request timeout in seconds |
| `verify_ssl` | `false` | SSL certificate verification |
#### Tool Permissions
| Option | Default | Description |
|--------|---------|-------------|
| `tools.create_note` | `true` | Allow creating new notes |
| `tools.update_note` | `true` | Allow modifying existing notes |
| `tools.delete_note` | `true` | Allow deleting notes |
| `tools.create_notebook` | `true` | Allow creating new notebooks |
| `tools.update_notebook` | `false` | Allow modifying notebook titles |
| `tools.delete_notebook` | `true` | Allow deleting notebooks |
| `tools.create_tag` | `true` | Allow creating new tags |
| `tools.update_tag` | `false` | Allow modifying tag titles |
| `tools.delete_tag` | `true` | Allow deleting tags |
| `tools.tag_note` | `true` | Allow adding tags to notes |
| `tools.untag_note` | `true` | Allow removing tags from notes |
| `tools.find_notes` | `true` | Allow text search across notes (with task filtering) |
| `tools.find_notes_with_tag` | `true` | Allow finding notes by tag (with task filtering) |
| `tools.find_notes_in_notebook` | `true` | Allow finding notes by notebook (with task filtering) |
| `tools.get_all_notes` | `false` | Allow getting all notes (disabled by default - can fill context window) |
| `tools.get_note` | `true` | Allow getting specific notes |
| `tools.list_notebooks` | `true` | Allow listing all notebooks |
| `tools.list_tags` | `true` | Allow listing all tags |
| `tools.get_tags_by_note` | `true` | Allow getting tags for specific notes |
| `tools.ping_joplin` | `true` | Allow testing server connectivity |
#### Content Exposure (Privacy Settings)
| Option | Default | Description |
|--------|---------|-------------|
| `content_exposure.search_results` | `"preview"` | Content visibility in search results: `"none"`, `"preview"`, `"full"` |
| `content_exposure.individual_notes` | `"full"` | Content visibility for individual notes: `"none"`, `"preview"`, `"full"` |
| `content_exposure.listings` | `"none"` | Content visibility in note listings: `"none"`, `"preview"`, `"full"` |
| `content_exposure.max_preview_length` | `200` | Maximum length of content previews (characters) |
## Project Structure
- **`run_fastmcp_server.py`** - FastMCP server launcher
- **`src/joplin_mcp/`** - Main package directory
- `fastmcp_server.py` - Server implementation with 17 tools (by default)
- `models.py` - Data models and schemas
- `config.py` - Configuration management
- **`docs/`** - API documentation
- **`tests/`** - Test suite
## Testing
Test your connection:
```bash
# For pip install
joplin-mcp-server
# For development
python run_fastmcp_server.py
```
You should see:
```
Starting Joplin FastMCP Server...
Successfully connected to Joplin!
Found X notebooks, Y notes, Z tags
FastMCP server starting...
Available tools: 17 tools ready
```
## Complete Tool Reference
| Tool | Permission | Description |
|------|------------|-------------|
| **Finding Notes** | | |
| `find_notes` | Read | Full-text search across all notes (supports task filtering) |
| `find_notes_with_tag` | Read | Find notes with specific tag (supports task filtering) |
| `find_notes_in_notebook` | Read | Find notes in specific notebook (supports task filtering) |
| `get_all_notes` | Read | Get all notes, most recent first *(disabled by default)* |
| `get_note` | Read | Get specific note by ID |
| **Managing Notes** | | |
| `create_note` | Write | Create new notes |
| `update_note` | Update | Modify existing notes |
| `delete_note` | Delete | Remove notes |
| **Managing Notebooks** | | |
| `list_notebooks` | Read | Browse all notebooks |
| `create_notebook` | Write | Create new notebooks |
| `update_notebook` | Update | Modify notebook titles |
| `delete_notebook` | Delete | Remove notebooks |
| **Managing Tags** | | |
| `list_tags` | Read | View all available tags |
| `create_tag` | Write | Create new tags |
| `delete_tag` | Delete | Remove tags |
| `get_tags_by_note` | Read | List tags on specific note |
| **Tag-Note Relationships** | | |
| `tag_note` | Update | Add tags to notes |
| `untag_note` | Update | Remove tags from notes |
| **System Tools** | | |
| `ping_joplin` | Read | Test connectivity |
Raw data
{
"_id": null,
"home_page": null,
"name": "joplin-mcp",
"maintainer": "Joplin MCP Contributors",
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "joplin, mcp, model-context-protocol, notes, ai, assistant",
"author": "Joplin MCP Contributors",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/f4/7d/b3ae1854682ef8103b173c6f6d2e4c3252caa50d25bc68e63f637f534d9e/joplin_mcp-0.1.1.tar.gz",
"platform": null,
"description": "# Joplin MCP Server\n\nA **FastMCP-based Model Context Protocol (MCP) server** for [Joplin](https://joplinapp.org/) note-taking application via its Python API [joppy](https://github.com/marph91/joppy), enabling AI assistants to interact with your Joplin notes, notebooks, and tags through a standardized interface.\n\n## Table of Contents\n\n- [What You Can Do](#what-you-can-do)\n- [Quick Start](#quick-start)\n- [Example Usage](#example-usage)\n- [Tool Permissions](#tool-permissions)\n- [Advanced Configuration](#advanced-configuration)\n- [Project Structure](#project-structure)\n- [Testing](#testing)\n- [Complete Tool Reference](#complete-tool-reference)\n\n## What You Can Do\n\nThis MCP server provides **18 optimized tools** for comprehensive Joplin integration:\n\n### **Note Management**\n- **Find & Search**: `find_notes`, `find_notes_with_tag`, `find_notes_in_notebook`, `get_all_notes`\n- **CRUD Operations**: `get_note`, `create_note`, `update_note`, `delete_note`\n\n### **Notebook Management** \n- **Organize**: `list_notebooks`, `create_notebook`, `update_notebook`, `delete_notebook`\n\n### **Tag Management**\n- **Categorize**: `list_tags`, `create_tag`, `delete_tag`, `get_tags_by_note`\n- **Link**: `tag_note`, `untag_note`\n\n### **System**\n- **Health**: `ping_joplin`\n\n## Quick Start\n\n### 1. Install the Package\n\n```bash\npip install joplin-mcp\n```\n\n### 2. Configure Joplin\n\n1. Open **Joplin Desktop** \u2192 **Tools** \u2192 **Options** \u2192 **Web Clipper**\n2. **Enable** the Web Clipper service\n3. **Copy** the Authorization token\n\n### 3. Run Setup Script\n\n```bash\njoplin-mcp-install\n```\n\nThis interactive script will:\n- Configure your Joplin API token\n- Set tool permissions (Create/Update/Delete)\n- Set up Claude Desktop automatically\n- Test the connection\n\n### 4. Choose Your AI Client\n\n#### Option A: Claude Desktop\nAfter running the setup script, restart Claude Desktop and you're ready to go!\n\n```\n\"List my notebooks\" or \"Create a note about today's meeting\"\n```\n\n#### Option B: OllMCP (Local AI Models)\n\nIf Claude Desktop was configured above, you can run the following to detect joplin-mcp automatically by OllMCP (Ollama served agents).\n\n```bash\n# Install ollmcp\npip install ollmcp\n\n# Run with auto-discovery and your preferred Ollama model, such as:\nollmcp --auto-discovery --model qwen3:4b\n```\n\n## Example Usage\n\nOnce configured, you can ask your AI assistant:\n\n- **\"List all my notebooks\"** - See your Joplin organization\n- **\"Find notes about Python programming\"** - Search your knowledge base \n- **\"Create a meeting note for today's standup\"** - Quick note creation\n- **\"Tag my recent AI notes as 'important'\"** - Organize with tags\n- **\"Show me my todos\"** - Find task items with `find_notes(task=True)`\n\n## Tool Permissions\n\nThe setup script offers **3 security levels**:\n\n- **Read** (always enabled): Browse and search your notes safely\n- **Write** (optional): Create new notes, notebooks, and tags \n- **Update** (optional): Modify existing content\n- **Delete** (optional): Remove content permanently\n\nChoose the level that matches your comfort and use case.\n\n---\n\n## Advanced Configuration\n\n### Alternative Installation (Development)\n\nFor developers or users who want the latest features:\n\n#### macOS/Linux:\n```bash\ngit clone https://github.com/alondmnt/joplin-mcp.git\ncd joplin-mcp\n./install.sh\n```\n\n#### Windows:\n```batch\ngit clone https://github.com/alondmnt/joplin-mcp.git\ncd joplin-mcp\ninstall.bat\n```\n\n### Manual Configuration\n\nIf you prefer manual setup or the script doesn't work:\n\n#### 1. Create Configuration File\n\nCreate `joplin-mcp.json` in your project directory:\n\n```json\n{\n \"token\": \"your_api_token_here\",\n \"host\": \"localhost\", \n \"port\": 41184,\n \"timeout\": 30,\n \"verify_ssl\": false\n}\n```\n\n#### 2. Claude Desktop Configuration\n\nAdd to your `claude_desktop_config.json`:\n\n```json\n{\n \"mcpServers\": {\n \"joplin\": {\n \"command\": \"joplin-mcp-server\",\n \"env\": {\n \"JOPLIN_TOKEN\": \"your_token_here\"\n }\n }\n }\n}\n```\n\n#### 3. OllMCP Manual Configuration\n\n```bash\n# Set environment variable\nexport JOPLIN_TOKEN=\"your_token_here\"\n\n# Run with manual server configuration\nollmcp --server \"joplin:joplin-mcp-server\" --model qwen3:4b\n```\n\n### Tool Permission Configuration\n\nFine-tune which operations the AI can perform by editing your config:\n\n```json\n{\n \"tools\": {\n \"create_note\": true,\n \"update_note\": true, \n \"delete_note\": false,\n \"create_notebook\": true,\n \"delete_notebook\": false,\n \"create_tag\": true,\n \"delete_tag\": false\n }\n}\n```\n\n### Environment Variables\n\nAlternative to JSON configuration:\n\n```bash\nexport JOPLIN_TOKEN=\"your_api_token_here\"\nexport JOPLIN_HOST=\"localhost\"\nexport JOPLIN_PORT=\"41184\"\nexport JOPLIN_TIMEOUT=\"30\"\n```\n\n### HTTP Transport Support\n\nThe server supports both STDIO and HTTP transports:\n\n```bash\n# STDIO (default)\njoplin-mcp-server\n\n# HTTP transport \npython run_fastmcp_server.py --transport http --port 8000\n```\n\n# Claude Desktop HTTP config\n```json\n{\n \"mcpServers\": {\n \"joplin\": {\n \"transport\": \"http\",\n \"url\": \"http://localhost:8000/mcp\"\n }\n }\n}\n```\n\n### Configuration Reference\n\n#### Basic Settings\n| Option | Default | Description |\n|--------|---------|-------------|\n| `token` | *required* | Joplin API authentication token |\n| `host` | `localhost` | Joplin server hostname |\n| `port` | `41184` | Joplin Web Clipper port |\n| `timeout` | `30` | Request timeout in seconds |\n| `verify_ssl` | `false` | SSL certificate verification |\n\n#### Tool Permissions\n| Option | Default | Description |\n|--------|---------|-------------|\n| `tools.create_note` | `true` | Allow creating new notes |\n| `tools.update_note` | `true` | Allow modifying existing notes |\n| `tools.delete_note` | `true` | Allow deleting notes |\n| `tools.create_notebook` | `true` | Allow creating new notebooks |\n| `tools.update_notebook` | `false` | Allow modifying notebook titles |\n| `tools.delete_notebook` | `true` | Allow deleting notebooks |\n| `tools.create_tag` | `true` | Allow creating new tags |\n| `tools.update_tag` | `false` | Allow modifying tag titles |\n| `tools.delete_tag` | `true` | Allow deleting tags |\n| `tools.tag_note` | `true` | Allow adding tags to notes |\n| `tools.untag_note` | `true` | Allow removing tags from notes |\n| `tools.find_notes` | `true` | Allow text search across notes (with task filtering) |\n| `tools.find_notes_with_tag` | `true` | Allow finding notes by tag (with task filtering) |\n| `tools.find_notes_in_notebook` | `true` | Allow finding notes by notebook (with task filtering) |\n| `tools.get_all_notes` | `false` | Allow getting all notes (disabled by default - can fill context window) |\n| `tools.get_note` | `true` | Allow getting specific notes |\n| `tools.list_notebooks` | `true` | Allow listing all notebooks |\n| `tools.list_tags` | `true` | Allow listing all tags |\n| `tools.get_tags_by_note` | `true` | Allow getting tags for specific notes |\n| `tools.ping_joplin` | `true` | Allow testing server connectivity |\n\n#### Content Exposure (Privacy Settings)\n| Option | Default | Description |\n|--------|---------|-------------|\n| `content_exposure.search_results` | `\"preview\"` | Content visibility in search results: `\"none\"`, `\"preview\"`, `\"full\"` |\n| `content_exposure.individual_notes` | `\"full\"` | Content visibility for individual notes: `\"none\"`, `\"preview\"`, `\"full\"` |\n| `content_exposure.listings` | `\"none\"` | Content visibility in note listings: `\"none\"`, `\"preview\"`, `\"full\"` |\n| `content_exposure.max_preview_length` | `200` | Maximum length of content previews (characters) |\n\n## Project Structure\n\n- **`run_fastmcp_server.py`** - FastMCP server launcher\n- **`src/joplin_mcp/`** - Main package directory\n - `fastmcp_server.py` - Server implementation with 17 tools (by default)\n - `models.py` - Data models and schemas\n - `config.py` - Configuration management\n- **`docs/`** - API documentation\n- **`tests/`** - Test suite\n\n## Testing\n\nTest your connection:\n\n```bash\n# For pip install\njoplin-mcp-server\n\n# For development \npython run_fastmcp_server.py\n```\n\nYou should see:\n```\nStarting Joplin FastMCP Server...\nSuccessfully connected to Joplin!\nFound X notebooks, Y notes, Z tags\nFastMCP server starting...\nAvailable tools: 17 tools ready\n```\n\n## Complete Tool Reference\n\n| Tool | Permission | Description |\n|------|------------|-------------|\n| **Finding Notes** | | |\n| `find_notes` | Read | Full-text search across all notes (supports task filtering) |\n| `find_notes_with_tag` | Read | Find notes with specific tag (supports task filtering) |\n| `find_notes_in_notebook` | Read | Find notes in specific notebook (supports task filtering) |\n| `get_all_notes` | Read | Get all notes, most recent first *(disabled by default)* |\n| `get_note` | Read | Get specific note by ID |\n| **Managing Notes** | | |\n| `create_note` | Write | Create new notes |\n| `update_note` | Update | Modify existing notes |\n| `delete_note` | Delete | Remove notes |\n| **Managing Notebooks** | | |\n| `list_notebooks` | Read | Browse all notebooks |\n| `create_notebook` | Write | Create new notebooks |\n| `update_notebook` | Update | Modify notebook titles |\n| `delete_notebook` | Delete | Remove notebooks |\n| **Managing Tags** | | |\n| `list_tags` | Read | View all available tags |\n| `create_tag` | Write | Create new tags |\n| `delete_tag` | Delete | Remove tags |\n| `get_tags_by_note` | Read | List tags on specific note |\n| **Tag-Note Relationships** | | |\n| `tag_note` | Update | Add tags to notes |\n| `untag_note` | Update | Remove tags from notes |\n| **System Tools** | | |\n| `ping_joplin` | Read | Test connectivity |\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Model Context Protocol (MCP) server for Joplin note-taking application",
"version": "0.1.1",
"project_urls": {
"Documentation": "https://github.com/alondmnt/joplin-mcp/blob/main/README.md",
"Homepage": "https://github.com/alondmnt/joplin-mcp",
"Issues": "https://github.com/alondmnt/joplin-mcp/issues",
"Repository": "https://github.com/alondmnt/joplin-mcp"
},
"split_keywords": [
"joplin",
" mcp",
" model-context-protocol",
" notes",
" ai",
" assistant"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "b0a6286574b685f754c850c30ca79e694dd437c679b37c136d68e60171a727a6",
"md5": "cc52676c41dbe713b592bd745460ce51",
"sha256": "c98a08c4a8acce8c53ac963237f4f0805125a2a057abe7b87a32a29d68edde8e"
},
"downloads": -1,
"filename": "joplin_mcp-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "cc52676c41dbe713b592bd745460ce51",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 44005,
"upload_time": "2025-07-09T00:13:43",
"upload_time_iso_8601": "2025-07-09T00:13:43.715404Z",
"url": "https://files.pythonhosted.org/packages/b0/a6/286574b685f754c850c30ca79e694dd437c679b37c136d68e60171a727a6/joplin_mcp-0.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "f47db3ae1854682ef8103b173c6f6d2e4c3252caa50d25bc68e63f637f534d9e",
"md5": "07e1d6dd1832d466f048ca7153304de5",
"sha256": "0d549125ae85f67f7d95696dcd1460734a65ca63e51298d3df9d24c0e8535889"
},
"downloads": -1,
"filename": "joplin_mcp-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "07e1d6dd1832d466f048ca7153304de5",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 60841,
"upload_time": "2025-07-09T00:13:44",
"upload_time_iso_8601": "2025-07-09T00:13:44.939940Z",
"url": "https://files.pythonhosted.org/packages/f4/7d/b3ae1854682ef8103b173c6f6d2e4c3252caa50d25bc68e63f637f534d9e/joplin_mcp-0.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-09 00:13:44",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "alondmnt",
"github_project": "joplin-mcp",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "mcp",
"specs": [
[
">=",
"1.0.0"
]
]
},
{
"name": "joppy",
"specs": [
[
">=",
"1.0.0"
]
]
},
{
"name": "fastmcp",
"specs": [
[
">=",
"2.0.0"
]
]
},
{
"name": "pydantic",
"specs": [
[
">=",
"2.0.0"
]
]
},
{
"name": "httpx",
"specs": [
[
">=",
"0.24.0"
]
]
},
{
"name": "typing-extensions",
"specs": [
[
">=",
"4.0.0"
]
]
},
{
"name": "PyYAML",
"specs": [
[
">=",
"6.0.0"
]
]
},
{
"name": "pytest",
"specs": [
[
">=",
"7.0.0"
]
]
},
{
"name": "pytest-asyncio",
"specs": [
[
">=",
"0.21.0"
]
]
},
{
"name": "pytest-mock",
"specs": [
[
">=",
"3.10.0"
]
]
},
{
"name": "coverage",
"specs": [
[
">=",
"7.0.0"
]
]
},
{
"name": "black",
"specs": [
[
">=",
"23.0.0"
]
]
},
{
"name": "ruff",
"specs": [
[
">=",
"0.1.0"
]
]
},
{
"name": "mypy",
"specs": [
[
">=",
"1.0.0"
]
]
},
{
"name": "pre-commit",
"specs": [
[
">=",
"3.0.0"
]
]
}
],
"lcname": "joplin-mcp"
}