second-brain-joplin 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- second_brain_joplin-0.1.0/.editorconfig +18 -0
- second_brain_joplin-0.1.0/.env.example +5 -0
- second_brain_joplin-0.1.0/.github/ISSUE_TEMPLATE/bug.yml +32 -0
- second_brain_joplin-0.1.0/.github/ISSUE_TEMPLATE/epic.yml +24 -0
- second_brain_joplin-0.1.0/.github/ISSUE_TEMPLATE/feature.yml +27 -0
- second_brain_joplin-0.1.0/.github/ISSUE_TEMPLATE/spike.yml +25 -0
- second_brain_joplin-0.1.0/.github/ISSUE_TEMPLATE/task.yml +22 -0
- second_brain_joplin-0.1.0/.github/dependabot.yml +16 -0
- second_brain_joplin-0.1.0/.github/labeler.yml +23 -0
- second_brain_joplin-0.1.0/.github/project.yml +70 -0
- second_brain_joplin-0.1.0/.github/workflows/ci.yml +40 -0
- second_brain_joplin-0.1.0/.github/workflows/release.yml +30 -0
- second_brain_joplin-0.1.0/.gitignore +27 -0
- second_brain_joplin-0.1.0/.pre-commit-config.yaml +8 -0
- second_brain_joplin-0.1.0/.python-version +1 -0
- second_brain_joplin-0.1.0/CHANGELOG.md +31 -0
- second_brain_joplin-0.1.0/CONTRIBUTING.md +69 -0
- second_brain_joplin-0.1.0/LICENSE +21 -0
- second_brain_joplin-0.1.0/PKG-INFO +149 -0
- second_brain_joplin-0.1.0/README.md +120 -0
- second_brain_joplin-0.1.0/SECURITY.md +27 -0
- second_brain_joplin-0.1.0/docs/install.md +26 -0
- second_brain_joplin-0.1.0/docs/notebook-structure.md +29 -0
- second_brain_joplin-0.1.0/docs/project-management.md +79 -0
- second_brain_joplin-0.1.0/docs/reference/second-brain-inspiration.md +33 -0
- second_brain_joplin-0.1.0/docs/releasing.md +44 -0
- second_brain_joplin-0.1.0/pyproject.toml +72 -0
- second_brain_joplin-0.1.0/src/second_brain_joplin/__init__.py +3 -0
- second_brain_joplin-0.1.0/src/second_brain_joplin/joplin_client.py +43 -0
- second_brain_joplin-0.1.0/src/second_brain_joplin/server.py +82 -0
- second_brain_joplin-0.1.0/tests/conftest.py +17 -0
- second_brain_joplin-0.1.0/tests/test_cli.py +23 -0
- second_brain_joplin-0.1.0/tests/test_joplin_client.py +35 -0
- second_brain_joplin-0.1.0/tests/test_metadata.py +9 -0
- second_brain_joplin-0.1.0/tests/test_server.py +99 -0
- second_brain_joplin-0.1.0/uv.lock +1804 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
root = true
|
|
2
|
+
|
|
3
|
+
[*]
|
|
4
|
+
charset = utf-8
|
|
5
|
+
end_of_line = lf
|
|
6
|
+
insert_final_newline = true
|
|
7
|
+
trim_trailing_whitespace = true
|
|
8
|
+
indent_style = space
|
|
9
|
+
indent_size = 4
|
|
10
|
+
|
|
11
|
+
[*.{yml,yaml,json,toml}]
|
|
12
|
+
indent_size = 2
|
|
13
|
+
|
|
14
|
+
[*.md]
|
|
15
|
+
trim_trailing_whitespace = false
|
|
16
|
+
|
|
17
|
+
[Makefile]
|
|
18
|
+
indent_style = tab
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Bug
|
|
2
|
+
description: An unexpected problem or incorrect behavior
|
|
3
|
+
labels: ["needs-triage"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: description
|
|
7
|
+
attributes:
|
|
8
|
+
label: What happened
|
|
9
|
+
validations:
|
|
10
|
+
required: true
|
|
11
|
+
- type: textarea
|
|
12
|
+
id: expected
|
|
13
|
+
attributes:
|
|
14
|
+
label: What was expected
|
|
15
|
+
validations:
|
|
16
|
+
required: true
|
|
17
|
+
- type: textarea
|
|
18
|
+
id: repro
|
|
19
|
+
attributes:
|
|
20
|
+
label: Steps to reproduce
|
|
21
|
+
validations:
|
|
22
|
+
required: true
|
|
23
|
+
- type: input
|
|
24
|
+
id: version
|
|
25
|
+
attributes:
|
|
26
|
+
label: Package version
|
|
27
|
+
placeholder: "e.g. 0.1.0"
|
|
28
|
+
- type: textarea
|
|
29
|
+
id: env
|
|
30
|
+
attributes:
|
|
31
|
+
label: Environment
|
|
32
|
+
placeholder: "OS, Python version, Joplin version"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: Epic
|
|
2
|
+
description: A large, multi-issue initiative
|
|
3
|
+
labels: ["epic", "needs-triage"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: goal
|
|
7
|
+
attributes:
|
|
8
|
+
label: Goal
|
|
9
|
+
description: What does this epic accomplish when all sub-issues are closed?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: sub-issues
|
|
14
|
+
attributes:
|
|
15
|
+
label: Sub-issues
|
|
16
|
+
description: List the issues that make up this epic (fill in after filing them).
|
|
17
|
+
placeholder: "- [ ] #1\n- [ ] #2"
|
|
18
|
+
- type: textarea
|
|
19
|
+
id: acceptance
|
|
20
|
+
attributes:
|
|
21
|
+
label: Acceptance criteria
|
|
22
|
+
description: How do we know this epic is done?
|
|
23
|
+
validations:
|
|
24
|
+
required: true
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Feature
|
|
2
|
+
description: A request, idea, or new functionality
|
|
3
|
+
labels: ["needs-triage"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: Problem / motivation
|
|
9
|
+
description: What problem does this solve, or what need does it address?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: proposal
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposed solution
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
- type: textarea
|
|
19
|
+
id: alternatives
|
|
20
|
+
attributes:
|
|
21
|
+
label: Alternatives considered
|
|
22
|
+
- type: textarea
|
|
23
|
+
id: acceptance
|
|
24
|
+
attributes:
|
|
25
|
+
label: Acceptance criteria
|
|
26
|
+
validations:
|
|
27
|
+
required: true
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: Spike
|
|
2
|
+
description: A time-boxed investigation that informs follow-on work
|
|
3
|
+
labels: ["needs-triage"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: question
|
|
7
|
+
attributes:
|
|
8
|
+
label: Question to answer
|
|
9
|
+
description: What do we need to know by the end of this spike?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: input
|
|
13
|
+
id: timebox
|
|
14
|
+
attributes:
|
|
15
|
+
label: Timebox
|
|
16
|
+
placeholder: "e.g. 2 hours, 1 day"
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: output
|
|
21
|
+
attributes:
|
|
22
|
+
label: Expected output
|
|
23
|
+
description: What artifact or decision does this spike produce?
|
|
24
|
+
validations:
|
|
25
|
+
required: true
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: Task
|
|
2
|
+
description: A specific, well-scoped piece of work (including docs and chores)
|
|
3
|
+
labels: ["needs-triage"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: description
|
|
7
|
+
attributes:
|
|
8
|
+
label: What needs to be done
|
|
9
|
+
validations:
|
|
10
|
+
required: true
|
|
11
|
+
- type: textarea
|
|
12
|
+
id: acceptance
|
|
13
|
+
attributes:
|
|
14
|
+
label: Done when
|
|
15
|
+
description: Clear, verifiable definition of done.
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
- type: textarea
|
|
19
|
+
id: notes
|
|
20
|
+
attributes:
|
|
21
|
+
label: Implementation notes
|
|
22
|
+
description: Relevant context, links, or constraints.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "uv"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
labels:
|
|
8
|
+
- "dependencies"
|
|
9
|
+
|
|
10
|
+
- package-ecosystem: "github-actions"
|
|
11
|
+
directory: "/"
|
|
12
|
+
schedule:
|
|
13
|
+
interval: "weekly"
|
|
14
|
+
labels:
|
|
15
|
+
- "dependencies"
|
|
16
|
+
- "github_actions"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
component:joplin-api:
|
|
2
|
+
- src/second_brain_joplin/joplin_client.py
|
|
3
|
+
|
|
4
|
+
component:mcp:
|
|
5
|
+
- src/second_brain_joplin/server.py
|
|
6
|
+
- src/second_brain_joplin/tools.py
|
|
7
|
+
|
|
8
|
+
component:search:
|
|
9
|
+
- src/second_brain_joplin/search.py
|
|
10
|
+
|
|
11
|
+
component:docs:
|
|
12
|
+
- docs/**
|
|
13
|
+
- "*.md"
|
|
14
|
+
- "!CONTRIBUTING.md"
|
|
15
|
+
|
|
16
|
+
component:ci:
|
|
17
|
+
- .github/workflows/**
|
|
18
|
+
- .github/project.yml
|
|
19
|
+
- .github/labeler.yml
|
|
20
|
+
- pyproject.toml
|
|
21
|
+
|
|
22
|
+
component:templates:
|
|
23
|
+
- templates/**
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Declarative PM spec for second-brain-joplin.
|
|
2
|
+
# Applied manually via `gh` CLI or GitHub UI; no automated sync script at this stage.
|
|
3
|
+
# See docs/project-management.md for how this spec is used.
|
|
4
|
+
|
|
5
|
+
labels:
|
|
6
|
+
# component labels
|
|
7
|
+
- name: "component:joplin-api"
|
|
8
|
+
color: "0075ca"
|
|
9
|
+
description: "Joplin REST API client"
|
|
10
|
+
- name: "component:mcp"
|
|
11
|
+
color: "0075ca"
|
|
12
|
+
description: "MCP server and tool definitions"
|
|
13
|
+
- name: "component:search"
|
|
14
|
+
color: "0075ca"
|
|
15
|
+
description: "Semantic search and embeddings"
|
|
16
|
+
- name: "component:docs"
|
|
17
|
+
color: "0075ca"
|
|
18
|
+
description: "Documentation"
|
|
19
|
+
- name: "component:ci"
|
|
20
|
+
color: "0075ca"
|
|
21
|
+
description: "CI/CD and build"
|
|
22
|
+
- name: "component:templates"
|
|
23
|
+
color: "0075ca"
|
|
24
|
+
description: "Joplin note templates"
|
|
25
|
+
|
|
26
|
+
# phase labels
|
|
27
|
+
- name: "phase-0"
|
|
28
|
+
color: "e4e669"
|
|
29
|
+
description: "Bootstrap: repo scaffold, CI, package skeleton"
|
|
30
|
+
- name: "phase-1"
|
|
31
|
+
color: "e4e669"
|
|
32
|
+
description: "Core read MCP tools"
|
|
33
|
+
- name: "phase-2"
|
|
34
|
+
color: "e4e669"
|
|
35
|
+
description: "Semantic search"
|
|
36
|
+
- name: "phase-3"
|
|
37
|
+
color: "e4e669"
|
|
38
|
+
description: "Write workflow and publish"
|
|
39
|
+
|
|
40
|
+
# meta labels
|
|
41
|
+
- name: "epic"
|
|
42
|
+
color: "6f42c1"
|
|
43
|
+
description: "Multi-issue initiative"
|
|
44
|
+
- name: "backlog"
|
|
45
|
+
color: "d4c5f9"
|
|
46
|
+
description: "Unscheduled work"
|
|
47
|
+
- name: "needs-triage"
|
|
48
|
+
color: "e11d48"
|
|
49
|
+
description: "Not yet triaged"
|
|
50
|
+
- name: "blocked"
|
|
51
|
+
color: "b60205"
|
|
52
|
+
description: "Blocked by another issue or external dependency"
|
|
53
|
+
- name: "good first issue"
|
|
54
|
+
color: "7057ff"
|
|
55
|
+
description: "Good for newcomers"
|
|
56
|
+
- name: "help wanted"
|
|
57
|
+
color: "008672"
|
|
58
|
+
description: "Extra attention is needed"
|
|
59
|
+
|
|
60
|
+
milestones:
|
|
61
|
+
- title: "v0.1 — Bootstrap"
|
|
62
|
+
description: "Repo scaffold, CI, package skeleton"
|
|
63
|
+
- title: "v0.2 — Core Read Tools"
|
|
64
|
+
description: "All read MCP tools working against Joplin REST API"
|
|
65
|
+
- title: "v0.3 — Semantic Search"
|
|
66
|
+
description: "Embedding index and semantic search tool"
|
|
67
|
+
- title: "v0.4 — Write Workflow"
|
|
68
|
+
description: "Human-gated note creation"
|
|
69
|
+
- title: "v1.0 — Publish"
|
|
70
|
+
description: "PyPI release, full docs, Joplin note templates"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
name: Lint
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v7
|
|
15
|
+
- uses: astral-sh/setup-uv@v7
|
|
16
|
+
with:
|
|
17
|
+
enable-cache: true
|
|
18
|
+
- name: Install dependencies
|
|
19
|
+
run: uv sync
|
|
20
|
+
- name: Ruff check
|
|
21
|
+
run: uv run ruff check src tests
|
|
22
|
+
- name: Ruff format check
|
|
23
|
+
run: uv run ruff format --check src tests
|
|
24
|
+
|
|
25
|
+
test:
|
|
26
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
strategy:
|
|
29
|
+
matrix:
|
|
30
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v7
|
|
33
|
+
- uses: astral-sh/setup-uv@v7
|
|
34
|
+
with:
|
|
35
|
+
enable-cache: true
|
|
36
|
+
python-version: ${{ matrix.python-version }}
|
|
37
|
+
- name: Install dependencies
|
|
38
|
+
run: uv sync
|
|
39
|
+
- name: Run tests
|
|
40
|
+
run: uv run pytest --tb=short
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Release (PyPI)
|
|
2
|
+
|
|
3
|
+
# Builds the sdist + wheel and publishes to PyPI via an OIDC trusted publisher
|
|
4
|
+
# (no stored token). The trusted publisher is registered on https://pypi.org for
|
|
5
|
+
# the `jomkz/second-brain-joplin` repo, workflow `release.yml`, environment
|
|
6
|
+
# `pypi`. See docs/releasing.md.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
tags: ["v*"]
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
build-and-publish:
|
|
15
|
+
name: Build and publish to PyPI
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
environment: pypi
|
|
18
|
+
permissions:
|
|
19
|
+
id-token: write # required for OIDC trusted publishing
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v7
|
|
22
|
+
- uses: astral-sh/setup-uv@v7
|
|
23
|
+
with:
|
|
24
|
+
enable-cache: true
|
|
25
|
+
- name: Build sdist and wheel
|
|
26
|
+
run: uv build
|
|
27
|
+
- name: Validate metadata
|
|
28
|
+
run: uvx twine check dist/*
|
|
29
|
+
- name: Publish to PyPI
|
|
30
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.venv/
|
|
8
|
+
.env
|
|
9
|
+
|
|
10
|
+
# Ruff / pytest cache
|
|
11
|
+
.ruff_cache/
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.coverage
|
|
14
|
+
htmlcov/
|
|
15
|
+
|
|
16
|
+
# Embeddings / local index (generated at runtime)
|
|
17
|
+
.index/
|
|
18
|
+
*.npy
|
|
19
|
+
*.faiss
|
|
20
|
+
|
|
21
|
+
# macOS
|
|
22
|
+
.DS_Store
|
|
23
|
+
|
|
24
|
+
# Editor
|
|
25
|
+
.idea/
|
|
26
|
+
.vscode/
|
|
27
|
+
*.swp
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.11
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format is based on
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
|
|
5
|
+
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.1.0] — Bootstrap
|
|
10
|
+
|
|
11
|
+
Initial project skeleton — the MCP server starts and all tools are stubbed.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `second-brain-joplin` CLI with a `serve` subcommand and `--version`.
|
|
16
|
+
- FastMCP server exposing five stubbed tools (`joplin_overview`,
|
|
17
|
+
`joplin_search`, `joplin_read`, `joplin_recent`, `joplin_create`), each
|
|
18
|
+
returning a `{"status": "not implemented"}` payload.
|
|
19
|
+
- `JoplinClient` skeleton with a working `ping()` against the Joplin Web Clipper
|
|
20
|
+
REST API; remaining methods stubbed for v0.2.
|
|
21
|
+
- `.env` support via `python-dotenv` (`JOPLIN_API_TOKEN`, `JOPLIN_BASE_URL`).
|
|
22
|
+
- Test suite with `pytest` + `respx`, and a 90% coverage gate.
|
|
23
|
+
- uv-based toolchain, `uv.lock`, and CI (ruff lint + format check, pytest on
|
|
24
|
+
Python 3.11/3.12/3.13).
|
|
25
|
+
- PyPI release workflow via OIDC trusted publishing.
|
|
26
|
+
- Dependabot config; pre-commit, EditorConfig, and pinned Python version.
|
|
27
|
+
- Documentation: install, notebook structure (PARA), project management,
|
|
28
|
+
releasing runbook, security policy, and an inspiration/reference note.
|
|
29
|
+
|
|
30
|
+
[Unreleased]: https://github.com/jomkz/second-brain-joplin/compare/v0.1.0...HEAD
|
|
31
|
+
[0.1.0]: https://github.com/jomkz/second-brain-joplin/releases/tag/v0.1.0
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in second-brain-joplin.
|
|
4
|
+
|
|
5
|
+
## Development setup
|
|
6
|
+
|
|
7
|
+
We use [uv](https://docs.astral.sh/uv/) as the primary toolchain:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
git clone https://github.com/jomkz/second-brain-joplin
|
|
11
|
+
cd second-brain-joplin
|
|
12
|
+
uv sync
|
|
13
|
+
uv run pre-commit install # enable lint/format on commit
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
<details>
|
|
17
|
+
<summary>pip fallback</summary>
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
python -m venv .venv && source .venv/bin/activate
|
|
21
|
+
pip install -e ".[test]"
|
|
22
|
+
```
|
|
23
|
+
</details>
|
|
24
|
+
|
|
25
|
+
## Running tests
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
uv run pytest
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Tests enforce a 90% coverage gate (configured in `pyproject.toml`).
|
|
32
|
+
|
|
33
|
+
## Running the server locally
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
cp .env.example .env
|
|
37
|
+
# Edit .env with your Joplin API token; it is loaded automatically via python-dotenv
|
|
38
|
+
uv run second-brain-joplin serve
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Issue triage checklist
|
|
42
|
+
|
|
43
|
+
See [docs/project-management.md](docs/project-management.md) for the full model
|
|
44
|
+
(issue types, labels, milestones). Every triaged issue should have:
|
|
45
|
+
|
|
46
|
+
1. **Issue type** — Epic / Feature / Task / Spike / Bug (set via sidebar)
|
|
47
|
+
2. **Milestone** — which release it targets (or `backlog` label if unscheduled)
|
|
48
|
+
3. One or more **`component:*`** labels
|
|
49
|
+
4. **Phase label** if applicable (`phase-0` through `phase-3`)
|
|
50
|
+
5. **Parent Epic** set as a sub-issue where relevant
|
|
51
|
+
|
|
52
|
+
## Label conventions
|
|
53
|
+
|
|
54
|
+
| Prefix | Values | Applied by |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| `component:` | `joplin-api`, `mcp`, `search`, `docs`, `ci`, `templates` | Maintainer (issues); labeler bot (PRs) |
|
|
57
|
+
| `phase-` | `phase-0`, `phase-1`, `phase-2`, `phase-3` | Maintainer |
|
|
58
|
+
| meta | `epic`, `backlog`, `needs-triage`, `blocked`, `good first issue`, `help wanted` | Maintainer |
|
|
59
|
+
|
|
60
|
+
## Commit style
|
|
61
|
+
|
|
62
|
+
No strict convention yet — use a short imperative summary line. DCO sign-off (`git commit -s`) is encouraged but not enforced at this stage.
|
|
63
|
+
|
|
64
|
+
## Pull requests
|
|
65
|
+
|
|
66
|
+
- Target `main`.
|
|
67
|
+
- Keep PRs focused — one logical change per PR.
|
|
68
|
+
- Add or update tests for any new behavior.
|
|
69
|
+
- CI must pass before merge.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 jomkz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: second-brain-joplin
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server that connects Claude Code (and other MCP clients) to your Joplin knowledge base
|
|
5
|
+
Project-URL: Homepage, https://github.com/jomkz/second-brain-joplin
|
|
6
|
+
Project-URL: Repository, https://github.com/jomkz/second-brain-joplin
|
|
7
|
+
Project-URL: Issues, https://github.com/jomkz/second-brain-joplin/issues
|
|
8
|
+
License: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: ai,claude,joplin,knowledge-base,mcp,second-brain
|
|
11
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: fastmcp>=2.0
|
|
21
|
+
Requires-Dist: httpx>=0.27
|
|
22
|
+
Requires-Dist: python-dotenv>=1.0
|
|
23
|
+
Provides-Extra: test
|
|
24
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'test'
|
|
25
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'test'
|
|
26
|
+
Requires-Dist: pytest>=8.0; extra == 'test'
|
|
27
|
+
Requires-Dist: respx>=0.21; extra == 'test'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# second-brain-joplin
|
|
31
|
+
|
|
32
|
+
An MCP server that turns your [Joplin](https://joplinapp.org/) knowledge base into searchable memory for any MCP-capable AI client — Claude Code, Cursor, and others.
|
|
33
|
+
|
|
34
|
+
Inspired by [second-brain-mcp](https://github.com/noesskeetit/second-brain-mcp) (for Obsidian). This project covers the same use case for Joplin: your AI assistant reads, searches, and files notes directly, without leaving the tool you already use.
|
|
35
|
+
|
|
36
|
+
> **Status:** Pre-alpha — MCP tools are stubbed. See the [roadmap](#roadmap) and open issues.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## How it works
|
|
41
|
+
|
|
42
|
+
Joplin Desktop exposes a local REST API on `localhost:41184` (the Web Clipper service). This server wraps that API as MCP tools, so your AI client can query and update your notes in real time — no export step, no sync lag.
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
Claude Code / Cursor
|
|
46
|
+
│ MCP
|
|
47
|
+
▼
|
|
48
|
+
second-brain-joplin (this server)
|
|
49
|
+
│ HTTP + token
|
|
50
|
+
▼
|
|
51
|
+
Joplin Desktop (localhost:41184)
|
|
52
|
+
│
|
|
53
|
+
▼
|
|
54
|
+
Your notes
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Prerequisites
|
|
60
|
+
|
|
61
|
+
- **Joplin Desktop** running with the Web Clipper service enabled:
|
|
62
|
+
**Tools → Options → Web Clipper → Enable Web Clipper Service**
|
|
63
|
+
- **API token** — copy it from the Web Clipper settings panel
|
|
64
|
+
- **Python ≥ 3.11** or [`uvx`](https://docs.astral.sh/uv/) (recommended — no install needed)
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Quickstart
|
|
69
|
+
|
|
70
|
+
### Claude Code
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
claude mcp add -s user second-brain-joplin \
|
|
74
|
+
-e JOPLIN_API_TOKEN=your-token-here \
|
|
75
|
+
-- uvx second-brain-joplin serve
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Other MCP clients
|
|
79
|
+
|
|
80
|
+
| Setting | Value |
|
|
81
|
+
|---|---|
|
|
82
|
+
| Command | `uvx second-brain-joplin serve` |
|
|
83
|
+
| `JOPLIN_API_TOKEN` | token from Joplin Web Clipper settings |
|
|
84
|
+
| `JOPLIN_BASE_URL` | `http://localhost:41184` (default) |
|
|
85
|
+
|
|
86
|
+
See [docs/install.md](docs/install.md) for per-client setup guides.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## MCP Tools
|
|
91
|
+
|
|
92
|
+
| Tool | Description | Writes? |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| `joplin_overview` | List all notebooks with note counts | No |
|
|
95
|
+
| `joplin_search` | Keyword search across all notes | No |
|
|
96
|
+
| `joplin_read` | Read a note by ID | No |
|
|
97
|
+
| `joplin_recent` | Notes modified in the last N days | No |
|
|
98
|
+
| `joplin_create` | Create a note (human-gated) | Yes |
|
|
99
|
+
|
|
100
|
+
> All tools are stubbed in v0.1. Implementation tracked in [v0.2 milestone](https://github.com/jomkz/second-brain-joplin/milestone/2).
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## vs. second-brain-mcp (Obsidian)
|
|
105
|
+
|
|
106
|
+
| | [second-brain-mcp](https://github.com/noesskeetit/second-brain-mcp) | second-brain-joplin |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| Note app | Obsidian | Joplin |
|
|
109
|
+
| Storage | Plain `.md` files on disk | Joplin REST API |
|
|
110
|
+
| Requires app running | No | Yes (Joplin + Web Clipper) |
|
|
111
|
+
| Semantic search | Yes (bge-m3) | Planned (v0.3) |
|
|
112
|
+
| Write support | Human-gated | Human-gated (v0.4) |
|
|
113
|
+
| Install | `uvx second-brain-mcp` | `uvx second-brain-joplin` |
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Notebook structure
|
|
118
|
+
|
|
119
|
+
The [PARA method](https://fortelabs.com/blog/para/) works well with Joplin. See [docs/notebook-structure.md](docs/notebook-structure.md) for a recommended setup.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Roadmap
|
|
124
|
+
|
|
125
|
+
| Milestone | Theme | Status |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| [v0.1 — Bootstrap](https://github.com/jomkz/second-brain-joplin/milestone/1) | Repo, CI, package skeleton | Done |
|
|
128
|
+
| [v0.2 — Core Read Tools](https://github.com/jomkz/second-brain-joplin/milestone/2) | All read MCP tools working | Planned |
|
|
129
|
+
| [v0.3 — Semantic Search](https://github.com/jomkz/second-brain-joplin/milestone/3) | Embedding index, semantic search | Planned |
|
|
130
|
+
| [v0.4 — Write Workflow](https://github.com/jomkz/second-brain-joplin/milestone/4) | Human-gated note creation | Planned |
|
|
131
|
+
| [v1.0 — Publish](https://github.com/jomkz/second-brain-joplin/milestone/5) | PyPI, full docs, templates | Planned |
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Security & privacy
|
|
136
|
+
|
|
137
|
+
This server keeps your notes local: it talks only to Joplin's Web Clipper REST API on `localhost` and runs on your own machine. Anything an MCP client can read, the connected AI can read — so apply least privilege and don't expose notebooks with credentials or other sensitive data. Note creation is planned as an explicit human-gated flow (v0.4); v0.1 does no silent writes. See [SECURITY.md](SECURITY.md) for details and how to report a vulnerability.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Contributing
|
|
142
|
+
|
|
143
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). Issues and PRs welcome — especially for testing against different Joplin versions and OS platforms.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
MIT — see [LICENSE](LICENSE).
|