docmost-mcp-remote 1.0.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.
Files changed (109) hide show
  1. docmost_mcp_remote-1.0.0/.dockerignore +10 -0
  2. docmost_mcp_remote-1.0.0/.env.example +46 -0
  3. docmost_mcp_remote-1.0.0/.github/dependabot.yml +17 -0
  4. docmost_mcp_remote-1.0.0/.github/workflows/ci.yml +145 -0
  5. docmost_mcp_remote-1.0.0/.github/workflows/release.yml +163 -0
  6. docmost_mcp_remote-1.0.0/.gitignore +220 -0
  7. docmost_mcp_remote-1.0.0/CHANGELOG.md +43 -0
  8. docmost_mcp_remote-1.0.0/CONTRIBUTING.md +55 -0
  9. docmost_mcp_remote-1.0.0/Dockerfile +27 -0
  10. docmost_mcp_remote-1.0.0/LICENSE +201 -0
  11. docmost_mcp_remote-1.0.0/NOTICE +5 -0
  12. docmost_mcp_remote-1.0.0/PKG-INFO +434 -0
  13. docmost_mcp_remote-1.0.0/README.md +400 -0
  14. docmost_mcp_remote-1.0.0/README.ru.md +123 -0
  15. docmost_mcp_remote-1.0.0/SECURITY.md +41 -0
  16. docmost_mcp_remote-1.0.0/compose.yaml +56 -0
  17. docmost_mcp_remote-1.0.0/docs/DESIGN.md +161 -0
  18. docmost_mcp_remote-1.0.0/docs/GLOSSARY.md +27 -0
  19. docmost_mcp_remote-1.0.0/docs/RELEASING.md +62 -0
  20. docmost_mcp_remote-1.0.0/docs/ROADMAP.md +201 -0
  21. docmost_mcp_remote-1.0.0/docs/adr/0001-new-repository-from-scratch.md +23 -0
  22. docmost_mcp_remote-1.0.0/docs/adr/0002-per-member-docmost-identity.md +16 -0
  23. docmost_mcp_remote-1.0.0/docs/adr/0003-oauth-and-bearer-with-postgres.md +15 -0
  24. docmost_mcp_remote-1.0.0/docs/adr/0004-scoped-writes-no-permanent-delete.md +18 -0
  25. docmost_mcp_remote-1.0.0/docs/adr/0005-python-fastmcp-uv.md +25 -0
  26. docmost_mcp_remote-1.0.0/docs/adr/0006-apache-2-license.md +44 -0
  27. docmost_mcp_remote-1.0.0/docs/docmost-api-notes.md +94 -0
  28. docmost_mcp_remote-1.0.0/docs/security-model.md +95 -0
  29. docmost_mcp_remote-1.0.0/pyproject.toml +81 -0
  30. docmost_mcp_remote-1.0.0/server.json +91 -0
  31. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/__init__.py +10 -0
  32. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/__main__.py +54 -0
  33. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/admin.py +174 -0
  34. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/auth.py +20 -0
  35. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/config.py +167 -0
  36. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/crypto.py +96 -0
  37. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/db/__init__.py +1 -0
  38. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/db/admin_store.py +257 -0
  39. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/db/engine.py +81 -0
  40. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/db/migrations/env.py +41 -0
  41. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/db/migrations/script.py.mako +22 -0
  42. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/db/migrations/versions/0001_members_sessions_grants_and_tokens.py +111 -0
  43. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/db/migrations/versions/0002_oauth_clients_requests_and_codes.py +74 -0
  44. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/db/migrations/versions/0003_snapshots.py +49 -0
  45. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/db/migrations/versions/0004_audit_log.py +47 -0
  46. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/db/oauth_store.py +336 -0
  47. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/db/schema.py +209 -0
  48. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/db/snapshot_store.py +118 -0
  49. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/db/store.py +273 -0
  50. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/docmost/__init__.py +28 -0
  51. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/docmost/backend.py +101 -0
  52. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/docmost/ce.py +335 -0
  53. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/docmost/errors.py +39 -0
  54. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/docmost/models.py +133 -0
  55. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/docmost/positions.py +145 -0
  56. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/docmost/prosemirror.py +58 -0
  57. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/docmost/version.py +49 -0
  58. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/guard.py +80 -0
  59. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/members.py +164 -0
  60. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/oauth.py +345 -0
  61. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/py.typed +0 -0
  62. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/ratelimit.py +56 -0
  63. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/server.py +146 -0
  64. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/tools/__init__.py +1 -0
  65. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/tools/account.py +38 -0
  66. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/tools/common.py +35 -0
  67. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/tools/read.py +254 -0
  68. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/tools/spaces.py +47 -0
  69. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/tools/untrusted.py +35 -0
  70. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/tools/write.py +442 -0
  71. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/web/__init__.py +1 -0
  72. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/web/routes.py +418 -0
  73. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/web/style.css +19 -0
  74. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/web/templates/account.html +58 -0
  75. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/web/templates/base.html +15 -0
  76. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/web/templates/consent.html +22 -0
  77. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/web/templates/login.html +14 -0
  78. docmost_mcp_remote-1.0.0/src/docmost_mcp_remote/web/templates/message.html +6 -0
  79. docmost_mcp_remote-1.0.0/tests/__init__.py +0 -0
  80. docmost_mcp_remote-1.0.0/tests/conftest.py +92 -0
  81. docmost_mcp_remote-1.0.0/tests/fakes.py +84 -0
  82. docmost_mcp_remote-1.0.0/tests/harness.py +91 -0
  83. docmost_mcp_remote-1.0.0/tests/integration/__init__.py +0 -0
  84. docmost_mcp_remote-1.0.0/tests/integration/compose.yaml +33 -0
  85. docmost_mcp_remote-1.0.0/tests/integration/conftest.py +112 -0
  86. docmost_mcp_remote-1.0.0/tests/integration/test_docmost_ce.py +153 -0
  87. docmost_mcp_remote-1.0.0/tests/integration/test_oauth_flow.py +27 -0
  88. docmost_mcp_remote-1.0.0/tests/integration/test_sign_in.py +32 -0
  89. docmost_mcp_remote-1.0.0/tests/integration/test_tools.py +85 -0
  90. docmost_mcp_remote-1.0.0/tests/integration/test_write_tools.py +106 -0
  91. docmost_mcp_remote-1.0.0/tests/test_admin.py +154 -0
  92. docmost_mcp_remote-1.0.0/tests/test_config.py +94 -0
  93. docmost_mcp_remote-1.0.0/tests/test_crypto.py +65 -0
  94. docmost_mcp_remote-1.0.0/tests/test_docmost_client.py +262 -0
  95. docmost_mcp_remote-1.0.0/tests/test_docmost_helpers.py +58 -0
  96. docmost_mcp_remote-1.0.0/tests/test_guard.py +94 -0
  97. docmost_mcp_remote-1.0.0/tests/test_members.py +144 -0
  98. docmost_mcp_remote-1.0.0/tests/test_migrations.py +102 -0
  99. docmost_mcp_remote-1.0.0/tests/test_oauth.py +552 -0
  100. docmost_mcp_remote-1.0.0/tests/test_positions.py +86 -0
  101. docmost_mcp_remote-1.0.0/tests/test_ratelimit.py +40 -0
  102. docmost_mcp_remote-1.0.0/tests/test_read_tools.py +194 -0
  103. docmost_mcp_remote-1.0.0/tests/test_release_metadata.py +62 -0
  104. docmost_mcp_remote-1.0.0/tests/test_server.py +57 -0
  105. docmost_mcp_remote-1.0.0/tests/test_store.py +98 -0
  106. docmost_mcp_remote-1.0.0/tests/test_untrusted.py +55 -0
  107. docmost_mcp_remote-1.0.0/tests/test_web.py +134 -0
  108. docmost_mcp_remote-1.0.0/tests/test_write_tools.py +440 -0
  109. docmost_mcp_remote-1.0.0/uv.lock +2808 -0
@@ -0,0 +1,10 @@
1
+ .git
2
+ .github
3
+ .venv
4
+ .env
5
+ **/__pycache__
6
+ .mypy_cache
7
+ .pytest_cache
8
+ .ruff_cache
9
+ docs
10
+ tests
@@ -0,0 +1,46 @@
1
+ # Public https URL where MCP clients reach this server (behind your reverse proxy).
2
+ PUBLIC_URL=https://mcp.example.com
3
+
4
+ # Base URL of your Docmost instance.
5
+ DOCMOST_URL=https://docs.example.com
6
+ # Set to true only for a Docmost reachable over http on a trusted private network.
7
+ DOCMOST_ALLOW_INSECURE_HTTP=false
8
+
9
+ # Password for the bundled Postgres. Use a long random value.
10
+ POSTGRES_PASSWORD=
11
+
12
+ # Encrypts stored Docmost sessions and snapshots and signs cookies. At least 32 characters,
13
+ # for example the output of: openssl rand -hex 32
14
+ # Losing it signs every member out; leaking it together with the database
15
+ # exposes their Docmost sessions.
16
+ SECRET_KEY=
17
+ # During a key rotation: the old key, so existing sessions stay readable.
18
+ SECRET_KEY_PREVIOUS=
19
+
20
+ # Comma-separated emails allowed to sign in. Empty allows every Docmost user.
21
+ ALLOWED_EMAILS=
22
+
23
+ # Comma-separated space slugs or ids members may use through this server.
24
+ # Empty allows every space the member can see in Docmost.
25
+ ALLOWED_SPACES=
26
+
27
+ # When a member's Docmost session expires: "ask" them to sign in again (default),
28
+ # or "stored_password" to keep their password encrypted and sign in automatically.
29
+ RELOGIN_MODE=ask
30
+
31
+ # Days page snapshots (copies of page bodies taken before every change) are kept.
32
+ SNAPSHOT_RETENTION_DAYS=30
33
+ # Days audit log entries (who called which tool on which page) are kept.
34
+ AUDIT_RETENTION_DAYS=90
35
+ # Tool calls one member may make per minute, over all their clients.
36
+ TOOL_CALLS_PER_MINUTE=60
37
+
38
+ # Reverse proxies whose X-Forwarded-For header is trusted for rate limiting.
39
+ # The compose file publishes the port on 127.0.0.1 only and trusts every
40
+ # client by default ("*"). Set the proxy's address if you publish it elsewhere.
41
+ # FORWARDED_ALLOW_IPS=*
42
+
43
+ LOG_LEVEL=info
44
+
45
+ # Image tag. "1" follows 1.x releases; a full version such as 1.0.0 pins one.
46
+ # IMAGE_TAG=1
@@ -0,0 +1,17 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: uv
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ groups:
8
+ python:
9
+ patterns: ["*"]
10
+ - package-ecosystem: github-actions
11
+ directory: /
12
+ schedule:
13
+ interval: weekly
14
+ - package-ecosystem: docker
15
+ directory: /
16
+ schedule:
17
+ interval: weekly
@@ -0,0 +1,145 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master, develop]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ concurrency:
12
+ group: ci-${{ github.ref }}
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ lint:
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v5
20
+ - uses: astral-sh/setup-uv@v7
21
+ with:
22
+ enable-cache: true
23
+ - run: uv sync --locked
24
+ - run: uv run ruff format --check .
25
+ - run: uv run ruff check .
26
+ - run: uv run mypy
27
+
28
+ test:
29
+ runs-on: ubuntu-latest
30
+ services:
31
+ postgres:
32
+ image: postgres:17-alpine
33
+ env:
34
+ POSTGRES_USER: test
35
+ POSTGRES_PASSWORD: test
36
+ POSTGRES_DB: test
37
+ ports:
38
+ - 5432:5432
39
+ options: >-
40
+ --health-cmd "pg_isready -U test" --health-interval 2s --health-timeout 3s
41
+ --health-retries 30
42
+ env:
43
+ DATABASE_TEST_URL: postgresql://test:test@localhost:5432/test
44
+ strategy:
45
+ fail-fast: false
46
+ matrix:
47
+ python: ["3.12", "3.13"]
48
+ steps:
49
+ - uses: actions/checkout@v5
50
+ - uses: astral-sh/setup-uv@v7
51
+ with:
52
+ enable-cache: true
53
+ python-version: ${{ matrix.python }}
54
+ - run: uv sync --locked
55
+ - run: uv run pytest
56
+
57
+ audit:
58
+ runs-on: ubuntu-latest
59
+ steps:
60
+ - uses: actions/checkout@v5
61
+ - uses: astral-sh/setup-uv@v7
62
+ with:
63
+ enable-cache: true
64
+ - run: uv sync --locked
65
+ - name: Audit locked runtime dependencies
66
+ run: |
67
+ uv export --frozen --no-dev --no-emit-project --format requirements-txt -o requirements.txt
68
+ uv run pip-audit --strict --disable-pip --require-hashes -r requirements.txt
69
+
70
+ integration:
71
+ name: integration (Docmost ${{ matrix.docmost }})
72
+ runs-on: ubuntu-latest
73
+ continue-on-error: ${{ matrix.canary }}
74
+ strategy:
75
+ fail-fast: false
76
+ matrix:
77
+ # Oldest supported, previous and newest tested release. "latest" warns early
78
+ # when a new Docmost release is out and the tested range needs a bump.
79
+ docmost: ["0.70.3", "0.96.0", "0.97.0"]
80
+ canary: [false]
81
+ include:
82
+ - docmost: latest
83
+ canary: true
84
+ services:
85
+ postgres:
86
+ image: postgres:17-alpine
87
+ env:
88
+ POSTGRES_USER: test
89
+ POSTGRES_PASSWORD: test
90
+ POSTGRES_DB: test
91
+ ports:
92
+ - 5433:5432
93
+ options: >-
94
+ --health-cmd "pg_isready -U test" --health-interval 2s --health-timeout 3s
95
+ --health-retries 30
96
+ env:
97
+ DOCMOST_VERSION: ${{ matrix.docmost }}
98
+ DOCMOST_TEST_URL: http://localhost:3000
99
+ DATABASE_TEST_URL: postgresql://test:test@localhost:5433/test
100
+ steps:
101
+ - uses: actions/checkout@v5
102
+ - uses: astral-sh/setup-uv@v7
103
+ with:
104
+ enable-cache: true
105
+ - name: Start Docmost
106
+ run: docker compose -f tests/integration/compose.yaml up -d --wait --wait-timeout 180
107
+ - name: Wait for Docmost
108
+ run: |
109
+ for i in $(seq 1 90); do
110
+ if curl -fsS http://localhost:3000/api/health; then exit 0; fi
111
+ sleep 2
112
+ done
113
+ docker compose -f tests/integration/compose.yaml logs docmost
114
+ exit 1
115
+ - run: uv sync --locked
116
+ - run: uv run pytest tests/integration
117
+ - name: Docmost logs
118
+ if: failure()
119
+ run: docker compose -f tests/integration/compose.yaml logs docmost
120
+
121
+ docker:
122
+ runs-on: ubuntu-latest
123
+ steps:
124
+ - uses: actions/checkout@v5
125
+ - name: Prepare .env
126
+ run: |
127
+ cp .env.example .env
128
+ sed -i "s/^POSTGRES_PASSWORD=$/POSTGRES_PASSWORD=ci-only/" .env
129
+ sed -i "s/^SECRET_KEY=$/SECRET_KEY=$(openssl rand -hex 32)/" .env
130
+ docker compose config --quiet
131
+ - name: Build the image
132
+ run: docker build -t ghcr.io/bbik52/docmost-mcp-remote:ci .
133
+ - name: Start the compose stack
134
+ run: IMAGE_TAG=ci docker compose up -d --wait --wait-timeout 120
135
+ - name: Smoke test
136
+ run: |
137
+ curl -fsS http://127.0.0.1:8000/healthz
138
+ curl -fsS -o /dev/null http://127.0.0.1:8000/login
139
+ test "$(curl -s -o /dev/null -w '%{http_code}' -X POST http://127.0.0.1:8000/mcp)" = 401
140
+ curl -fsS http://127.0.0.1:8000/.well-known/oauth-protected-resource/mcp
141
+ docker compose exec -T server docmost-mcp-remote admin members
142
+ test "$(docker image inspect -f '{{index .Config.Labels "io.modelcontextprotocol.server.name"}}' ghcr.io/bbik52/docmost-mcp-remote:ci)" = io.github.bbik52/docmost-mcp-remote
143
+ - name: Logs
144
+ if: always()
145
+ run: docker compose logs
@@ -0,0 +1,163 @@
1
+ name: Release
2
+
3
+ # Runs when a version tag such as v1.0.0 is pushed to master. Publishes the
4
+ # package to PyPI, the image to ghcr.io, a GitHub release and the entry in the
5
+ # official MCP Registry. See docs/RELEASING.md.
6
+
7
+ on:
8
+ push:
9
+ tags: ["v[0-9]+.[0-9]+.[0-9]+"]
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ concurrency:
15
+ group: release
16
+ cancel-in-progress: false
17
+
18
+ env:
19
+ IMAGE: ghcr.io/bbik52/docmost-mcp-remote
20
+ MCP_PUBLISHER_VERSION: v1.8.4
21
+
22
+ jobs:
23
+ check:
24
+ runs-on: ubuntu-latest
25
+ outputs:
26
+ version: ${{ steps.version.outputs.version }}
27
+ steps:
28
+ - uses: actions/checkout@v5
29
+ with:
30
+ fetch-depth: 0
31
+ - uses: astral-sh/setup-uv@v7
32
+ with:
33
+ enable-cache: true
34
+ - name: Tag matches the project version and is on master
35
+ id: version
36
+ run: |
37
+ version="${GITHUB_REF_NAME#v}"
38
+ project="$(uv version --short)"
39
+ if [ "$version" != "$project" ]; then
40
+ echo "Tag $GITHUB_REF_NAME does not match project version $project" >&2
41
+ exit 1
42
+ fi
43
+ git fetch --no-tags origin master
44
+ if ! git merge-base --is-ancestor "$GITHUB_SHA" origin/master; then
45
+ echo "Tag $GITHUB_REF_NAME is not on master" >&2
46
+ exit 1
47
+ fi
48
+ echo "version=$version" >> "$GITHUB_OUTPUT"
49
+ - run: uv sync --locked
50
+ - name: Release metadata is consistent
51
+ run: uv run pytest tests/test_release_metadata.py
52
+ - name: Changelog has an entry for this version
53
+ run: grep -q "^## \[${{ steps.version.outputs.version }}\]" CHANGELOG.md
54
+
55
+ build:
56
+ needs: check
57
+ runs-on: ubuntu-latest
58
+ steps:
59
+ - uses: actions/checkout@v5
60
+ - uses: astral-sh/setup-uv@v7
61
+ - run: uv build
62
+ - uses: actions/upload-artifact@v7
63
+ with:
64
+ name: dist
65
+ path: dist/
66
+ if-no-files-found: error
67
+
68
+ pypi:
69
+ needs: build
70
+ runs-on: ubuntu-latest
71
+ environment:
72
+ name: pypi
73
+ url: https://pypi.org/project/docmost-mcp-remote/
74
+ permissions:
75
+ id-token: write
76
+ steps:
77
+ - uses: actions/download-artifact@v8
78
+ with:
79
+ name: dist
80
+ path: dist/
81
+ - uses: pypa/gh-action-pypi-publish@release/v1
82
+
83
+ image:
84
+ needs: check
85
+ runs-on: ubuntu-latest
86
+ permissions:
87
+ contents: read
88
+ packages: write
89
+ steps:
90
+ - uses: actions/checkout@v5
91
+ - uses: docker/setup-qemu-action@v4
92
+ - uses: docker/setup-buildx-action@v4
93
+ - uses: docker/login-action@v4
94
+ with:
95
+ registry: ghcr.io
96
+ username: ${{ github.actor }}
97
+ password: ${{ secrets.GITHUB_TOKEN }}
98
+ - id: meta
99
+ uses: docker/metadata-action@v6
100
+ with:
101
+ images: ${{ env.IMAGE }}
102
+ tags: |
103
+ type=semver,pattern={{version}}
104
+ type=semver,pattern={{major}}.{{minor}}
105
+ type=semver,pattern={{major}}
106
+ - uses: docker/build-push-action@v7
107
+ with:
108
+ context: .
109
+ platforms: linux/amd64,linux/arm64
110
+ push: true
111
+ tags: ${{ steps.meta.outputs.tags }}
112
+ labels: ${{ steps.meta.outputs.labels }}
113
+ annotations: ${{ steps.meta.outputs.annotations }}
114
+
115
+ github-release:
116
+ needs: [check, build, pypi, image]
117
+ runs-on: ubuntu-latest
118
+ permissions:
119
+ contents: write
120
+ steps:
121
+ - uses: actions/checkout@v5
122
+ - uses: actions/download-artifact@v8
123
+ with:
124
+ name: dist
125
+ path: dist/
126
+ - name: Create the release
127
+ env:
128
+ GH_TOKEN: ${{ github.token }}
129
+ VERSION: ${{ needs.check.outputs.version }}
130
+ run: |
131
+ awk -v v="$VERSION" '
132
+ $0 ~ "^## \\[" v "\\]" { found = 1; next }
133
+ found && /^## \[/ { exit }
134
+ found { print }
135
+ ' CHANGELOG.md > notes.md
136
+ printf '\nImage: `%s:%s`\n' "$IMAGE" "$VERSION" >> notes.md
137
+ gh release create "$GITHUB_REF_NAME" dist/* --title "$VERSION" --notes-file notes.md --verify-tag
138
+
139
+ mcp-registry:
140
+ needs: [pypi, image]
141
+ runs-on: ubuntu-latest
142
+ permissions:
143
+ contents: read
144
+ id-token: write
145
+ steps:
146
+ - uses: actions/checkout@v5
147
+ - uses: sigstore/cosign-installer@v4
148
+ - name: Download and verify mcp-publisher
149
+ run: |
150
+ set -euo pipefail
151
+ archive="mcp-publisher_linux_amd64.tar.gz"
152
+ base_url="https://github.com/modelcontextprotocol/registry/releases/download/${MCP_PUBLISHER_VERSION}"
153
+ curl -fsSL -o "$archive" "$base_url/$archive"
154
+ curl -fsSL -o "$archive.sigstore.json" "$base_url/$archive.sigstore.json"
155
+ cosign verify-blob \
156
+ --bundle "$archive.sigstore.json" \
157
+ --certificate-identity "https://github.com/modelcontextprotocol/registry/.github/workflows/release.yml@refs/tags/${MCP_PUBLISHER_VERSION}" \
158
+ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
159
+ "$archive"
160
+ tar xzf "$archive" mcp-publisher
161
+ - run: ./mcp-publisher validate
162
+ - run: ./mcp-publisher login github-oidc
163
+ - run: ./mcp-publisher publish
@@ -0,0 +1,220 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ *.lcov
51
+ .hypothesis/
52
+ .pytest_cache/
53
+ cover/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ .pybuilder/
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ # For a library or package, you might want to ignore these files since the code is
88
+ # intended to run in multiple environments; otherwise, check them in:
89
+ # .python-version
90
+
91
+ # pipenv
92
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
94
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
95
+ # install all needed dependencies.
96
+ # Pipfile.lock
97
+
98
+ # uv
99
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
100
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
101
+ # commonly ignored for libraries.
102
+ # uv.lock
103
+
104
+ # poetry
105
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
106
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
107
+ # commonly ignored for libraries.
108
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
109
+ # poetry.lock
110
+ # poetry.toml
111
+
112
+ # pdm
113
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
114
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
115
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
116
+ # pdm.lock
117
+ # pdm.toml
118
+ .pdm-python
119
+ .pdm-build/
120
+
121
+ # pixi
122
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
123
+ # pixi.lock
124
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
125
+ # in the .venv directory. It is recommended not to include this directory in version control.
126
+ .pixi/*
127
+ !.pixi/config.toml
128
+
129
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
130
+ __pypackages__/
131
+
132
+ # Celery stuff
133
+ celerybeat-schedule*
134
+ celerybeat.pid
135
+
136
+ # Redis
137
+ *.rdb
138
+ *.aof
139
+ *.pid
140
+
141
+ # RabbitMQ
142
+ mnesia/
143
+ rabbitmq/
144
+ rabbitmq-data/
145
+
146
+ # ActiveMQ
147
+ activemq-data/
148
+
149
+ # SageMath parsed files
150
+ *.sage.py
151
+
152
+ # Environments
153
+ .env
154
+ .envrc
155
+ .venv
156
+ env/
157
+ venv/
158
+ ENV/
159
+ env.bak/
160
+ venv.bak/
161
+
162
+ # Spyder project settings
163
+ .spyderproject
164
+ .spyproject
165
+
166
+ # Rope project settings
167
+ .ropeproject
168
+
169
+ # mkdocs/Zensical documentation
170
+ /site
171
+
172
+ # mypy
173
+ .mypy_cache/
174
+ .dmypy.json
175
+ dmypy.json
176
+
177
+ # Pyre type checker
178
+ .pyre/
179
+
180
+ # pytype static type analyzer
181
+ .pytype/
182
+
183
+ # Cython debug symbols
184
+ cython_debug/
185
+
186
+ # PyCharm
187
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
188
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
189
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
190
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
191
+ # .idea/
192
+
193
+ # Abstra
194
+ # Abstra is an AI-powered process automation framework.
195
+ # Ignore directories containing user credentials, local state, and settings.
196
+ # Learn more at https://abstra.io/docs
197
+ .abstra/
198
+
199
+ # Visual Studio Code
200
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore that
201
+ # can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
202
+ # and can be added to the global gitignore or merged into this file. However, if you prefer, you
203
+ # could uncomment the following to ignore the entire vscode folder
204
+ # .vscode/
205
+ # Temporary file for partial code execution
206
+ tempCodeRunnerFile.py
207
+
208
+ # Ruff stuff:
209
+ .ruff_cache/
210
+
211
+ # PyPI configuration file
212
+ .pypirc
213
+
214
+ # Marimo
215
+ marimo/_static/
216
+ marimo/_lsp/
217
+ __marimo__/
218
+
219
+ # Streamlit
220
+ .streamlit/secrets.toml
@@ -0,0 +1,43 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are listed here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
5
+ [semantic versioning](https://semver.org/). A release that needs attention
6
+ when upgrading lists it under "Upgrade notes".
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [1.0.0] - 2026-10-25
11
+
12
+ First release.
13
+
14
+ ### Added
15
+
16
+ - Remote MCP server (streamable HTTP at `/mcp`) for Docmost Community Edition
17
+ 0.70.0 or newer.
18
+ - Per-member sign-in with the member's own Docmost account; every tool call
19
+ runs as that member with their Docmost rights. Optional `ALLOWED_EMAILS`
20
+ and `ALLOWED_SPACES` limits.
21
+ - OAuth 2.1 authorization server following the MCP authorization spec:
22
+ dynamic client registration, PKCE (S256), consent page with `read`,
23
+ `write` and `delete` scopes, resource-bound tokens, rotating refresh tokens
24
+ with reuse detection. Personal bearer tokens for scripts. Grants and tokens
25
+ are listed and revoked on the account page.
26
+ - Read tools: `whoami`, `list_spaces`, `list_pages`, `recent_pages`,
27
+ `get_page` (Markdown), `search`, `list_comments`, `list_trash`,
28
+ `list_snapshots`. Page content is returned inside an untrusted-content
29
+ envelope.
30
+ - Write tools: `create_page`, `update_page` (append, prepend, replace),
31
+ `rename_page`, `move_page`, `add_comment`, `restore_snapshot`; delete-scope
32
+ tools `trash_page` and `restore_page`. No permanent delete.
33
+ - Encrypted snapshot of a page body before every change, kept for
34
+ `SNAPSHOT_RETENTION_DAYS`; read-back after every write to catch changes
35
+ Docmost did not apply.
36
+ - Per-member rate limit (`TOOL_CALLS_PER_MINUTE`) and an audit log of tool
37
+ calls without content (`AUDIT_RETENTION_DAYS`).
38
+ - `admin` command line: list members and grants, revoke grants or members,
39
+ disable members, read the audit log, rotate `SECRET_KEY`.
40
+ - Database schema migrations applied at startup under a lock; an older
41
+ server refuses to start on a schema upgraded by a newer one.
42
+ - Container image for linux/amd64 and linux/arm64, `compose.yaml` with
43
+ Postgres, and a PyPI package.
@@ -0,0 +1,55 @@
1
+ # Contributing
2
+
3
+ Thanks for your interest. Issues and pull requests are welcome.
4
+
5
+ ## Ground rules
6
+
7
+ - **Clean implementation.** Do not copy code, structure or tool descriptions
8
+ from docmost-mcp-oss or from Docmost (AGPL-3.0). Write from the observed
9
+ behavior of the Docmost HTTP API. See
10
+ [ADR 0001](docs/adr/0001-new-repository-from-scratch.md).
11
+ - **English** for code, comments, docs, commit messages and pull requests.
12
+ - Security-relevant changes need tests. Never log passwords, tokens, page
13
+ content or tool arguments.
14
+ - Larger design changes start with an issue or an ADR in `docs/adr/`.
15
+ - Database changes come with an Alembic migration in the same pull request
16
+ and follow "Database migrations" in [docs/DESIGN.md](docs/DESIGN.md):
17
+ never edit a released migration, keep existing data.
18
+
19
+ ## Setup
20
+
21
+ Requires [uv](https://docs.astral.sh/uv/) and Python 3.12 or newer.
22
+
23
+ ```sh
24
+ uv sync
25
+ docker run -d -p 5433:5432 -e POSTGRES_USER=test -e POSTGRES_PASSWORD=test postgres:17-alpine
26
+ DATABASE_TEST_URL=postgresql://test:test@localhost:5433/test uv run pytest
27
+ ```
28
+
29
+ Before pushing:
30
+
31
+ ```sh
32
+ uv run ruff format .
33
+ uv run ruff check .
34
+ uv run mypy
35
+ uv run pytest
36
+ ```
37
+
38
+ ## Pull requests
39
+
40
+ - The repository uses git flow. Branch from `develop` as `feature/<topic>`
41
+ (or `bugfix/<topic>`) and open the pull request against `develop`.
42
+ `master` only receives `release/*` and `hotfix/*` merges and holds tagged
43
+ releases.
44
+ - One topic per pull request.
45
+ - Describe what changed and why; link the roadmap phase or issue.
46
+ - CI must be green.
47
+ - Changes to authentication, OAuth, tokens, cryptography, the sign-in and
48
+ consent pages or the write path are reviewed with extra care; see
49
+ "Contributions and project security" in [docs/DESIGN.md](docs/DESIGN.md).
50
+
51
+ ## License of contributions
52
+
53
+ The project is licensed under the [Apache License 2.0](LICENSE). By opening a
54
+ pull request you agree that your contribution is licensed under the same
55
+ terms (section 5 of the license). There is no separate contributor agreement.