openproject-ce-mcp 0.2.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.
- openproject_ce_mcp-0.2.0/.gitignore +38 -0
- openproject_ce_mcp-0.2.0/.mcp.json.example +40 -0
- openproject_ce_mcp-0.2.0/CHANGELOG.md +253 -0
- openproject_ce_mcp-0.2.0/LICENSE +21 -0
- openproject_ce_mcp-0.2.0/PKG-INFO +482 -0
- openproject_ce_mcp-0.2.0/README.md +431 -0
- openproject_ce_mcp-0.2.0/configure_mcp.py +34 -0
- openproject_ce_mcp-0.2.0/docs/architecture.md +173 -0
- openproject_ce_mcp-0.2.0/docs/claude-desktop.md +100 -0
- openproject_ce_mcp-0.2.0/docs/claude.md +144 -0
- openproject_ce_mcp-0.2.0/docs/codex.md +114 -0
- openproject_ce_mcp-0.2.0/docs/cursor.md +50 -0
- openproject_ce_mcp-0.2.0/docs/github.md +116 -0
- openproject_ce_mcp-0.2.0/docs/tools.md +272 -0
- openproject_ce_mcp-0.2.0/img/claude.jpg +0 -0
- openproject_ce_mcp-0.2.0/img/codex.jpg +0 -0
- openproject_ce_mcp-0.2.0/img/cursor.jpg +0 -0
- openproject_ce_mcp-0.2.0/img/github.jpg +0 -0
- openproject_ce_mcp-0.2.0/img/openproject-ce-mcp-hero.jpg +0 -0
- openproject_ce_mcp-0.2.0/pyproject.toml +111 -0
- openproject_ce_mcp-0.2.0/src/openproject_ce_mcp/__init__.py +3 -0
- openproject_ce_mcp-0.2.0/src/openproject_ce_mcp/client.py +6860 -0
- openproject_ce_mcp-0.2.0/src/openproject_ce_mcp/config.py +340 -0
- openproject_ce_mcp-0.2.0/src/openproject_ce_mcp/models.py +1355 -0
- openproject_ce_mcp-0.2.0/src/openproject_ce_mcp/server.py +111 -0
- openproject_ce_mcp-0.2.0/src/openproject_ce_mcp/setup_cli.py +1016 -0
- openproject_ce_mcp-0.2.0/src/openproject_ce_mcp/tools.py +3006 -0
- openproject_ce_mcp-0.2.0/tests/fixtures/spec.md +1 -0
- openproject_ce_mcp-0.2.0/tests/integration/__init__.py +0 -0
- openproject_ce_mcp-0.2.0/tests/integration/conftest.py +131 -0
- openproject_ce_mcp-0.2.0/tests/integration/test_boards.py +23 -0
- openproject_ce_mcp-0.2.0/tests/integration/test_memberships.py +41 -0
- openproject_ce_mcp-0.2.0/tests/integration/test_meta.py +69 -0
- openproject_ce_mcp-0.2.0/tests/integration/test_news.py +55 -0
- openproject_ce_mcp-0.2.0/tests/integration/test_projects.py +55 -0
- openproject_ce_mcp-0.2.0/tests/integration/test_semantic_identifiers.py +64 -0
- openproject_ce_mcp-0.2.0/tests/integration/test_time_entries.py +75 -0
- openproject_ce_mcp-0.2.0/tests/integration/test_versions.py +54 -0
- openproject_ce_mcp-0.2.0/tests/integration/test_work_packages.py +147 -0
- openproject_ce_mcp-0.2.0/tests/test_client.py +5650 -0
- openproject_ce_mcp-0.2.0/tests/test_config.py +254 -0
- openproject_ce_mcp-0.2.0/tests/test_configure_mcp.py +599 -0
- openproject_ce_mcp-0.2.0/tests/test_registry.py +61 -0
- openproject_ce_mcp-0.2.0/tests/test_server.py +232 -0
- openproject_ce_mcp-0.2.0/tests/test_tools.py +1428 -0
- openproject_ce_mcp-0.2.0/uv.lock +1066 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Python / build
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.egg-info/
|
|
4
|
+
dist/
|
|
5
|
+
build/
|
|
6
|
+
|
|
7
|
+
# Test / coverage
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
.ruff_cache/
|
|
10
|
+
.coverage
|
|
11
|
+
htmlcov/
|
|
12
|
+
|
|
13
|
+
# Virtual environments
|
|
14
|
+
.venv/
|
|
15
|
+
|
|
16
|
+
# Type checking
|
|
17
|
+
.mypy_cache/
|
|
18
|
+
|
|
19
|
+
# Local credentials and config
|
|
20
|
+
.env
|
|
21
|
+
.mcp.json
|
|
22
|
+
/AGENTS.md
|
|
23
|
+
|
|
24
|
+
# Tool-local state
|
|
25
|
+
.claude/
|
|
26
|
+
.codex/
|
|
27
|
+
.vscode/
|
|
28
|
+
.DS_Store
|
|
29
|
+
CONTINUE.md
|
|
30
|
+
|
|
31
|
+
# Local backups
|
|
32
|
+
*.bak.*
|
|
33
|
+
|
|
34
|
+
# OpenProject source clones for the API source-check tool (tools/api-check/)
|
|
35
|
+
.op-sources/
|
|
36
|
+
|
|
37
|
+
# Internal review notes
|
|
38
|
+
SELF_REVIEW.md
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"openproject": {
|
|
4
|
+
"command": "openproject-ce-mcp",
|
|
5
|
+
"env": {
|
|
6
|
+
"OPENPROJECT_BASE_URL": "https://op.example.com",
|
|
7
|
+
"OPENPROJECT_API_TOKEN": "replace-with-your-token",
|
|
8
|
+
|
|
9
|
+
"OPENPROJECT_ALLOWED_PROJECTS_READ": "*",
|
|
10
|
+
"OPENPROJECT_ALLOWED_PROJECTS_WRITE": "",
|
|
11
|
+
|
|
12
|
+
"OPENPROJECT_ENABLE_PROJECT_READ": "true",
|
|
13
|
+
"OPENPROJECT_ENABLE_WORK_PACKAGE_READ": "true",
|
|
14
|
+
"OPENPROJECT_ENABLE_MEMBERSHIP_READ": "true",
|
|
15
|
+
"OPENPROJECT_ENABLE_VERSION_READ": "true",
|
|
16
|
+
"OPENPROJECT_ENABLE_BOARD_READ": "true",
|
|
17
|
+
|
|
18
|
+
"OPENPROJECT_HIDE_PROJECT_FIELDS": "",
|
|
19
|
+
"OPENPROJECT_HIDE_WORK_PACKAGE_FIELDS": "",
|
|
20
|
+
"OPENPROJECT_HIDE_ACTIVITY_FIELDS": "",
|
|
21
|
+
"OPENPROJECT_HIDE_CUSTOM_FIELDS": "",
|
|
22
|
+
|
|
23
|
+
"OPENPROJECT_ENABLE_ADMIN_WRITE": "false",
|
|
24
|
+
|
|
25
|
+
"OPENPROJECT_ENABLE_PROJECT_WRITE": "false",
|
|
26
|
+
"OPENPROJECT_ENABLE_WORK_PACKAGE_WRITE": "false",
|
|
27
|
+
"OPENPROJECT_ENABLE_MEMBERSHIP_WRITE": "false",
|
|
28
|
+
"OPENPROJECT_ENABLE_VERSION_WRITE": "false",
|
|
29
|
+
"OPENPROJECT_ENABLE_BOARD_WRITE": "false",
|
|
30
|
+
|
|
31
|
+
"OPENPROJECT_TIMEOUT": "12",
|
|
32
|
+
"OPENPROJECT_VERIFY_SSL": "true",
|
|
33
|
+
"OPENPROJECT_DEFAULT_PAGE_SIZE": "20",
|
|
34
|
+
"OPENPROJECT_MAX_PAGE_SIZE": "50",
|
|
35
|
+
"OPENPROJECT_MAX_RESULTS": "100",
|
|
36
|
+
"OPENPROJECT_LOG_LEVEL": "WARNING"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file. Versions
|
|
4
|
+
follow [semantic versioning](https://semver.org); 0.1.0 is the first tagged
|
|
5
|
+
release and 0.0.1 is the development baseline.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 0.2.0 (unreleased)
|
|
10
|
+
|
|
11
|
+
First release published to PyPI. Supersedes the never-released 0.1.1 (its
|
|
12
|
+
package-rename and installer fixes are folded in here).
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **PyPI distribution.** The package is installable with `pip` / `pipx` /
|
|
17
|
+
`uv tool install openproject-ce-mcp`. A GitHub Actions workflow publishes to
|
|
18
|
+
PyPI on a version tag via trusted publishing (OIDC, no stored token).
|
|
19
|
+
- **`openproject-ce-mcp configure` setup command** (plus the
|
|
20
|
+
`openproject-ce-mcp-setup` alias), shipped in the installed package. It
|
|
21
|
+
registers the server with detected MCP clients and writes `.mcp.json`. Scope is
|
|
22
|
+
auto-detected — a project directory gets a local `.mcp.json`, elsewhere the
|
|
23
|
+
server is registered user-wide — and can be forced with `--local` / `--global`.
|
|
24
|
+
- Top-level CLI: `openproject-ce-mcp --help` / `--version`; running with no
|
|
25
|
+
arguments still starts the stdio server, unchanged for MCP clients.
|
|
26
|
+
- `check_api.py --constants` verifies hardcoded enum/constant values (emoji
|
|
27
|
+
reactions, version statuses and their operators) against the OpenProject source
|
|
28
|
+
across versions, catching a value rename the presence check would miss.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- Renamed the package to **openproject-ce-mcp** (distribution name, import
|
|
33
|
+
package `openproject_ce_mcp`, and the `openproject-ce-mcp` command). The PyPI
|
|
34
|
+
name `openproject-mcp` is taken by an unrelated project; the new name is free
|
|
35
|
+
and states the Community-Edition focus. The MCP server key stays `openproject`,
|
|
36
|
+
so existing client configs do not change.
|
|
37
|
+
- Documentation leads with the PyPI install path; the `curl … | sh` source
|
|
38
|
+
installer is kept as an alternative. Uninstall is documented per install type.
|
|
39
|
+
- The `User-Agent` header now derives from the package version instead of a
|
|
40
|
+
hardcoded string.
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- The `curl … | sh` installer no longer crashes with `EOFError` on the first
|
|
45
|
+
prompt: `get.sh` attaches the controlling terminal, and the prompt helpers fall
|
|
46
|
+
back to defaults when stdin is not interactive.
|
|
47
|
+
- Re-running `configure --global` pre-fills from an existing client registration
|
|
48
|
+
instead of demanding the base URL and token again.
|
|
49
|
+
- `configure` warns before writing a token-bearing `.mcp.json` into an unrelated
|
|
50
|
+
project directory, and when the server command cannot be resolved to an absolute
|
|
51
|
+
path (which would fail for GUI clients that do not inherit the shell `PATH`).
|
|
52
|
+
- The Docker integration-test harness (`docker/test/up.sh`) runs on the Bash 3.2
|
|
53
|
+
that ships with macOS (no `declare -A`).
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 0.1.0 – 2026-07-01
|
|
58
|
+
|
|
59
|
+
### Compatibility
|
|
60
|
+
|
|
61
|
+
- Reviewed for compatibility with OpenProject 17.5.1 / 17.5.0. No breaking API change
|
|
62
|
+
affects this server. The 17.5 change that replaces the `X-Requested-With` header check with
|
|
63
|
+
`Sec-Fetch-Site` applies to session authentication only; this server authenticates
|
|
64
|
+
with an API token (HTTP Basic auth) and is unaffected. The 17.4.1 security fixes
|
|
65
|
+
touch meeting, journal, and baseline endpoints that this server does not use.
|
|
66
|
+
- Verified against OpenProject 16.6 (classic), 17.4 (displayId), and 17.5 (semantic)
|
|
67
|
+
via the local Docker matrix, plus a source-level API audit across 16.0–17.5.
|
|
68
|
+
|
|
69
|
+
### Added
|
|
70
|
+
|
|
71
|
+
- Single work package tools now accept a project-prefixed identifier (e.g. `PROJ-123`)
|
|
72
|
+
in addition to the numeric id (sent as either a number or a string); the bulk tools
|
|
73
|
+
remain numeric-only. OpenProject 17.5 lets administrators switch the displayed
|
|
74
|
+
identifier to a project-based format exposed via `displayId`, and its
|
|
75
|
+
`work_packages/{id}` endpoints resolve that form server-side. References are passed
|
|
76
|
+
through to the endpoint verbatim, so the behaviour degrades cleanly: on instances
|
|
77
|
+
without semantic identifiers a project-prefixed reference simply yields a 404
|
|
78
|
+
(surfaced as not-found), while numeric ids keep working on every supported version.
|
|
79
|
+
- Relation and parent writes resolve a project-prefixed reference to the numeric id
|
|
80
|
+
before building the HAL link, since link hrefs are not resolved by `displayId`.
|
|
81
|
+
- Interactive setup can detect installed MCP clients (Claude Code, Claude Desktop,
|
|
82
|
+
Codex, Cursor, VS Code/Copilot) and register the server in a client's user-wide
|
|
83
|
+
config. Registration merges rather than overwrites, backing up the existing file.
|
|
84
|
+
- `uninstall.sh` / `uninstall.ps1` and a `configure_mcp.py --uninstall` mode remove
|
|
85
|
+
the `openproject` entry from client configs (keeping other servers, with backups)
|
|
86
|
+
and clean up the local environment.
|
|
87
|
+
- `OPENPROJECT_ATTACHMENT_ROOT` confines attachment uploads to a directory (default:
|
|
88
|
+
the working directory); files outside it, and credential/config files such as
|
|
89
|
+
`.mcp.json` / `.env` / private keys even inside it, are refused.
|
|
90
|
+
|
|
91
|
+
### Security
|
|
92
|
+
|
|
93
|
+
- Attachment uploads can no longer read arbitrary local files, closing a
|
|
94
|
+
credential-exfiltration path.
|
|
95
|
+
- `list_relations` is gated by the read scope and filtered by the project read
|
|
96
|
+
allowlist on both linked work packages; `update_relation`, `update_reminder`, and
|
|
97
|
+
`delete_reminder` apply the project write allowlist; `copy_project` validates its
|
|
98
|
+
destination; hidden work-package subjects no longer leak through relation tools.
|
|
99
|
+
- `OPENPROJECT_AUTO_CONFIRM_DELETE` now correctly governs the preview step for all
|
|
100
|
+
destructive deletes.
|
|
101
|
+
|
|
102
|
+
### Docs
|
|
103
|
+
|
|
104
|
+
- Onboarding docs reworked: install-once/register-per-client model, per-client
|
|
105
|
+
config matrix, per-OS paths, verification steps, and gitignore reminders. Added a
|
|
106
|
+
Cursor guide and a generic "any other MCP client" note.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 0.0.1 (development baseline)
|
|
111
|
+
|
|
112
|
+
Initial development baseline. The pre-release history is kept below as dated
|
|
113
|
+
milestones.
|
|
114
|
+
|
|
115
|
+
### 2026-05-18
|
|
116
|
+
|
|
117
|
+
#### Compatibility
|
|
118
|
+
|
|
119
|
+
- Verified against OpenProject 17.4. No breaking API changes in 17.4.
|
|
120
|
+
- Work package responses now expose a `display_id` field (`displayId` in the API),
|
|
121
|
+
introduced in 17.4 as preparation for project-based identifiers in 17.5.
|
|
122
|
+
The numeric `id` remains the canonical identifier for all tool parameters; `display_id`
|
|
123
|
+
is informational and may show a project-prefixed form (e.g. `ABC-42`) once 17.5 is deployed.
|
|
124
|
+
|
|
125
|
+
#### Fixes
|
|
126
|
+
|
|
127
|
+
- Authentication header changed from `Bearer <token>` to `Basic base64(apikey:<token>)`,
|
|
128
|
+
aligning with the OpenProject API documentation. Both formats are accepted by OpenProject;
|
|
129
|
+
this change makes the implementation spec-compliant.
|
|
130
|
+
|
|
131
|
+
#### Bug fixes
|
|
132
|
+
|
|
133
|
+
- `list_work_packages`, `list_my_open_work_packages`, `list_versions`, and `list_projects`
|
|
134
|
+
now report `total` and `count` consistently when the read allowlist filters items out
|
|
135
|
+
of the API response. Previously `total` reflected the unfiltered server count while
|
|
136
|
+
`count`/`results` reflected the filtered set, producing responses like
|
|
137
|
+
`{"total": 8, "count": 0, "results": []}`. `next_offset` and `truncated` continue to
|
|
138
|
+
follow server-side pagination so callers still walk every page that may contain
|
|
139
|
+
allowed items.
|
|
140
|
+
- `list_work_packages` without an explicit `project` argument now correctly filters
|
|
141
|
+
results to allowed projects when `OPENPROJECT_ALLOWED_PROJECTS_READ` is restricted.
|
|
142
|
+
Previously the API returned all visible work packages and client-side filtering was
|
|
143
|
+
applied per-page, causing `total` to be unreliable. The server is now given a
|
|
144
|
+
project-id filter so only allowed work packages are returned from the start.
|
|
145
|
+
- Allowlist matching now resolves project names and hyphenated display names to their
|
|
146
|
+
canonical identifiers at startup, so HAL links that carry only the project id are
|
|
147
|
+
correctly matched against name-based allowlist entries.
|
|
148
|
+
|
|
149
|
+
#### Configuration
|
|
150
|
+
|
|
151
|
+
- `OPENPROJECT_ALLOWED_PROJECTS_READ` now accepts glob patterns in addition to exact
|
|
152
|
+
identifiers and names (e.g. `team-*` matches `team-alpha`, `team-beta`).
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
### 2026-04-08
|
|
157
|
+
|
|
158
|
+
#### Tools
|
|
159
|
+
|
|
160
|
+
- **Projects** — list, get, create, copy (with background job tracking), update, delete;
|
|
161
|
+
read admin context, project configuration, and lifecycle phase definitions/instances
|
|
162
|
+
- **Work packages** — list with structured filters (`project`, `type`, `version`,
|
|
163
|
+
`has_description`); free-text search with optional `project`, `status`, `open_only`,
|
|
164
|
+
`assignee_me` filters; get, create, subtask, update, delete; add comments; create/delete
|
|
165
|
+
relations; get relations and activity log; bulk create and bulk update; list own open
|
|
166
|
+
work packages
|
|
167
|
+
- **Watchers** — list, add, remove
|
|
168
|
+
- **Attachments** — list, get, upload, delete
|
|
169
|
+
- **File links** — list, delete (Nextcloud CE integration)
|
|
170
|
+
- **Time entries** — list, get, create, update, delete; list available activities
|
|
171
|
+
- **Versions** — list (global or project-scoped), get, create, update, delete
|
|
172
|
+
- **Boards** — list, get, create (basic and grouped), update, delete; list saved views,
|
|
173
|
+
get view
|
|
174
|
+
- **Memberships** — list, get, create, update, delete; list roles and principals; get
|
|
175
|
+
current user's project access
|
|
176
|
+
- **Users** — get current user; list, get, create, update, delete, lock, unlock
|
|
177
|
+
- **Groups** — list, get, create, update (full member-list replacement with add/remove
|
|
178
|
+
helpers), delete
|
|
179
|
+
- **Documents** — list, get, update (no create/delete endpoint in CE API)
|
|
180
|
+
- **News** — list, get, create, update, delete
|
|
181
|
+
- **Wiki pages** — get single page by id; no list tool (CE API v3 has no collection
|
|
182
|
+
endpoint — `GET /api/v3/projects/{id}/wiki_pages` is not implemented)
|
|
183
|
+
- **Categories** — list, get (no write API in CE)
|
|
184
|
+
- **Notifications** — list, mark single read, mark all read
|
|
185
|
+
- **Grids** — list, get, create, update, delete
|
|
186
|
+
- **User preferences** — get, update (always available — no write gate required)
|
|
187
|
+
- **Instance configuration** — get
|
|
188
|
+
- **Query metadata** — get filter, column, operator, sort-by; list/get filter-instance
|
|
189
|
+
schemas
|
|
190
|
+
- **Help texts** — list, get
|
|
191
|
+
- **Working days** — list working-day configuration; list non-working days
|
|
192
|
+
- **Custom options** — get
|
|
193
|
+
- **Relations (global)** — list, update
|
|
194
|
+
- **Actions & capabilities** — list
|
|
195
|
+
- **Text rendering** — render markdown or plain text to HTML via OpenProject API
|
|
196
|
+
|
|
197
|
+
#### Permission model
|
|
198
|
+
|
|
199
|
+
- Scoped read flags per chain: `OPENPROJECT_ENABLE_PROJECT_READ`,
|
|
200
|
+
`OPENPROJECT_ENABLE_WORK_PACKAGE_READ`, `OPENPROJECT_ENABLE_MEMBERSHIP_READ`,
|
|
201
|
+
`OPENPROJECT_ENABLE_VERSION_READ`, `OPENPROJECT_ENABLE_BOARD_READ` (all default `true`)
|
|
202
|
+
- Scoped write flags per chain: `OPENPROJECT_ENABLE_PROJECT_WRITE`,
|
|
203
|
+
`OPENPROJECT_ENABLE_WORK_PACKAGE_WRITE`, `OPENPROJECT_ENABLE_MEMBERSHIP_WRITE`,
|
|
204
|
+
`OPENPROJECT_ENABLE_VERSION_WRITE`, `OPENPROJECT_ENABLE_BOARD_WRITE` (all default `false`)
|
|
205
|
+
- `OPENPROJECT_ENABLE_ADMIN_WRITE` — dedicated opt-in for instance-wide user and group
|
|
206
|
+
management; never activated by project-scoped write flags (default `false`)
|
|
207
|
+
- No global shortcut flags — each scope must be enabled explicitly
|
|
208
|
+
- Two-layer safety model: MCP env-var gates (ceiling) + OpenProject server-side role
|
|
209
|
+
permissions (final authority); a `403` from OpenProject surfaces as a tool error
|
|
210
|
+
|
|
211
|
+
#### Architecture
|
|
212
|
+
|
|
213
|
+
- Five-module layout: `server.py`, `config.py`, `client.py`, `models.py`, `tools.py`
|
|
214
|
+
- All policy logic (read gates, write gates, project scoping, field hiding) concentrated
|
|
215
|
+
in `client.py` for easier security review
|
|
216
|
+
- Preview/confirm two-step pattern for all writes and deletes; bypassable globally via
|
|
217
|
+
`OPENPROJECT_AUTO_CONFIRM_WRITE` or per class via `OPENPROJECT_AUTO_CONFIRM_DELETE`
|
|
218
|
+
- Project allowlists matched case-insensitively against identifier, name, and numeric ID;
|
|
219
|
+
hyphenated name variant tested for HAL-embedded links
|
|
220
|
+
- Field hiding per entity type via `OPENPROJECT_HIDE_<ENTITY>_FIELDS`; hidden fields are
|
|
221
|
+
rejected on writes too
|
|
222
|
+
- HAL responses normalized into compact dataclasses; raw payloads never forwarded to MCP
|
|
223
|
+
clients
|
|
224
|
+
- Pagination bounded by `OPENPROJECT_DEFAULT_PAGE_SIZE`, `OPENPROJECT_MAX_PAGE_SIZE`,
|
|
225
|
+
`OPENPROJECT_MAX_RESULTS`
|
|
226
|
+
- Form validation against OpenProject schema endpoints before create/update writes
|
|
227
|
+
|
|
228
|
+
#### Test coverage
|
|
229
|
+
|
|
230
|
+
- 152 unit tests (httpx mock transport, no network)
|
|
231
|
+
- Integration test suite (`tests/integration/`) against a live OpenProject instance;
|
|
232
|
+
excluded from the default run, opt in with `-m integration`
|
|
233
|
+
|
|
234
|
+
#### Scope
|
|
235
|
+
|
|
236
|
+
- Community Edition only — Enterprise features (Placeholder Users, Budgets, Portfolios,
|
|
237
|
+
Programs, Custom Actions, Baseline Comparisons) are not implemented
|
|
238
|
+
- Nextcloud file links included (CE feature; returns empty list gracefully if Nextcloud
|
|
239
|
+
not connected)
|
|
240
|
+
- Project lifecycle phases included (read-only; degrades gracefully if unavailable)
|
|
241
|
+
|
|
242
|
+
#### Known API notes
|
|
243
|
+
|
|
244
|
+
- `GET /api/v3/projects/{id}/wiki_pages` is not implemented in OpenProject v3;
|
|
245
|
+
`list_wiki_pages` is therefore not provided. Individual pages are accessible via
|
|
246
|
+
`get_wiki_page`.
|
|
247
|
+
- Project-scoped endpoints for work packages and versions are deprecated in OpenProject
|
|
248
|
+
17.2 in favour of workspace-scoped alternatives; the deprecated paths remain in use as
|
|
249
|
+
the workspace-scoped alternatives are not yet stable in CE.
|
|
250
|
+
- Relations use the canonical `/api/v3/relations` endpoint with a filter instead of the
|
|
251
|
+
redirecting project-scoped path.
|
|
252
|
+
- Groups PATCH requires a complete `_links.members` array (full replacement); the client
|
|
253
|
+
fetches the current list and applies adds/removes before sending.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jürgen Tauschl
|
|
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.
|