dspace-mcp 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.
- dspace_mcp-0.1.0/.gitignore +14 -0
- dspace_mcp-0.1.0/LICENSE +21 -0
- dspace_mcp-0.1.0/PKG-INFO +157 -0
- dspace_mcp-0.1.0/README.md +130 -0
- dspace_mcp-0.1.0/pyproject.toml +72 -0
- dspace_mcp-0.1.0/src/dspace_mcp/__init__.py +3 -0
- dspace_mcp-0.1.0/src/dspace_mcp/client.py +413 -0
- dspace_mcp-0.1.0/src/dspace_mcp/config.py +284 -0
- dspace_mcp-0.1.0/src/dspace_mcp/pdf.py +134 -0
- dspace_mcp-0.1.0/src/dspace_mcp/server.py +275 -0
- dspace_mcp-0.1.0/src/dspace_mcp/shaping.py +318 -0
- dspace_mcp-0.1.0/src/dspace_mcp/tools.py +515 -0
- dspace_mcp-0.1.0/tests/conftest.py +31 -0
- dspace_mcp-0.1.0/tests/fixtures/README.md +67 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_401_malformed_uuid.json +1 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_404.json +1 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_bitstreamformat.json +16 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_bitstreams.json +66 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_bundles.json +45 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_communities_top.json +120 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_community_collections.json +174 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_facets.json +81 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_facets_author.json +64 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_item.json +216 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_item_identifiers.json +25 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_pid_find_headers.txt +20 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_root.json +280 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_root_headers.txt +19 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_search_objects.json +720 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_search_objects_page1.json +1357 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace10_usagereport_totalvisits.json +20 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace11_root.json +280 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace7_root.json +206 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace7_search_objects.json +757 -0
- dspace_mcp-0.1.0/tests/fixtures/dspace8_root.json +308 -0
- dspace_mcp-0.1.0/tests/test_client.py +839 -0
- dspace_mcp-0.1.0/tests/test_config.py +329 -0
- dspace_mcp-0.1.0/tests/test_live.py +149 -0
- dspace_mcp-0.1.0/tests/test_pdf.py +289 -0
- dspace_mcp-0.1.0/tests/test_server.py +93 -0
- dspace_mcp-0.1.0/tests/test_shaping.py +747 -0
- dspace_mcp-0.1.0/tests/test_tools.py +723 -0
dspace_mcp-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Michał Pasternak
|
|
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,157 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dspace-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Read-only MCP server for DSpace 7+ repositories
|
|
5
|
+
Project-URL: Homepage, https://github.com/mpasternak/dspace-mcp
|
|
6
|
+
Project-URL: Repository, https://github.com/mpasternak/dspace-mcp
|
|
7
|
+
Project-URL: Issues, https://github.com/mpasternak/dspace-mcp/issues
|
|
8
|
+
Author-email: Michał Pasternak <michal.dtz@gmail.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: dspace,llm,mcp,oai,open-access,repository
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Education
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Text Processing :: Indexing
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: httpx>=0.27
|
|
24
|
+
Requires-Dist: mcp[cli]>=1.28.0
|
|
25
|
+
Requires-Dist: pypdf>=4.0
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# dspace-mcp
|
|
29
|
+
|
|
30
|
+
[](https://github.com/mpasternak/dspace-mcp/actions/workflows/ci.yml)
|
|
31
|
+
[](https://pypi.org/project/dspace-mcp/)
|
|
32
|
+
[](https://pypi.org/project/dspace-mcp/)
|
|
33
|
+
[](LICENSE)
|
|
34
|
+
|
|
35
|
+
A read-only [MCP](https://modelcontextprotocol.io/) server that lets an AI
|
|
36
|
+
assistant talk to any [DSpace](https://dspace.org/) 7+ repository.
|
|
37
|
+
|
|
38
|
+
Ask your repository questions in plain language — *"how many theses did we
|
|
39
|
+
publish in 2025?"*, *"which authors appear most often in this collection?"*,
|
|
40
|
+
*"summarise the PDF attached to this item"* — and the assistant answers by
|
|
41
|
+
querying the DSpace REST API directly.
|
|
42
|
+
|
|
43
|
+
## Read-only by construction, not by promise
|
|
44
|
+
|
|
45
|
+
The server holds no credentials and never issues a request other than `GET`.
|
|
46
|
+
It cannot deposit, edit or delete anything, and it cannot read what the public
|
|
47
|
+
cannot already see — embargoed items, workflow submissions and restricted
|
|
48
|
+
collections stay invisible.
|
|
49
|
+
|
|
50
|
+
That is a property of the code, not of the model's behaviour: there is nothing
|
|
51
|
+
to prompt-inject your way into. A test in the suite asserts that no other HTTP
|
|
52
|
+
method ever leaves the process.
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
Nothing to install if you have [uv](https://docs.astral.sh/uv/):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
uvx dspace-mcp --base-url https://demo.dspace.org/server
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Or with pip:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install dspace-mcp
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Configure your MCP client
|
|
69
|
+
|
|
70
|
+
**Claude Code:**
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
claude mcp add dspace -- uvx dspace-mcp --base-url https://demo.dspace.org/server
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Claude Desktop / any client using `mcp.json`:**
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"mcpServers": {
|
|
81
|
+
"dspace": {
|
|
82
|
+
"command": "uvx",
|
|
83
|
+
"args": ["dspace-mcp", "--base-url", "https://demo.dspace.org/server"]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Point `--base-url` at your own repository's REST API — usually your DSpace URL
|
|
90
|
+
with `/server` appended. If you leave `/server` off, the server detects it and
|
|
91
|
+
corrects the URL for you.
|
|
92
|
+
|
|
93
|
+
To connect to several repositories, add several entries under different names.
|
|
94
|
+
One process serves exactly one repository, which keeps the assistant from
|
|
95
|
+
mixing them up.
|
|
96
|
+
|
|
97
|
+
## Tools
|
|
98
|
+
|
|
99
|
+
| Tool | What it does |
|
|
100
|
+
|---|---|
|
|
101
|
+
| `search_items` | Search items; filter by year range, author, collection; sort by relevance, date or title. `limit=0` returns just the count. |
|
|
102
|
+
| `get_item` | Fetch one item by **UUID, Handle or DOI** — whichever identifier you happen to have. |
|
|
103
|
+
| `list_communities` | Walk the community tree (up to 3 levels). |
|
|
104
|
+
| `list_collections` | List collections, of one community or of the whole repository. |
|
|
105
|
+
| `list_bitstreams` | List an item's files with sizes, MIME types, checksums and download URLs. |
|
|
106
|
+
| `get_bitstream_text` | Extract the text of a PDF so the assistant can read or summarise it. |
|
|
107
|
+
| `list_facet_values` | Count values of a facet (authors, subjects, years) — the repository does the counting, so no records are downloaded. |
|
|
108
|
+
| `get_item_statistics` | View count of an item. |
|
|
109
|
+
| `get_repository_info` | Name, version, item counts, and which search filters, sort fields and facets this instance actually supports. |
|
|
110
|
+
|
|
111
|
+
### Two things worth knowing
|
|
112
|
+
|
|
113
|
+
**Ask `get_repository_info` first.** DSpace installations differ: the set of
|
|
114
|
+
search filters and facets is configured per instance, so a filter that exists
|
|
115
|
+
on one repository returns an error on another. This tool reports what the
|
|
116
|
+
instance in front of you supports.
|
|
117
|
+
|
|
118
|
+
**Counting is free.** `search_items` with `limit=0`, and `list_facet_values`,
|
|
119
|
+
answer "how many" questions with a single request and a handful of tokens,
|
|
120
|
+
instead of downloading records and counting them.
|
|
121
|
+
|
|
122
|
+
## Configuration
|
|
123
|
+
|
|
124
|
+
| Variable | Default | Meaning |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| `DSPACE_BASE_URL` | *(required)* | REST API root, e.g. `https://demo.dspace.org/server` |
|
|
127
|
+
| `DSPACE_TIMEOUT` | `15` | seconds per HTTP request |
|
|
128
|
+
| `DSPACE_MAX_RESULTS` | `50` | hard ceiling on how many records any tool may return |
|
|
129
|
+
| `DSPACE_PDF_MAX_MB` | `20` | refuse to download PDFs larger than this |
|
|
130
|
+
|
|
131
|
+
Every variable has a matching flag: `--base-url`, `--timeout`,
|
|
132
|
+
`--max-results`, `--pdf-max-mb`.
|
|
133
|
+
|
|
134
|
+
## Compatibility
|
|
135
|
+
|
|
136
|
+
Verified against DSpace 7.2.1, 7.5, 7.6.5, 8.2, 8.4, 9.2, 10.1 and
|
|
137
|
+
11.0-SNAPSHOT. The test suite runs against recorded responses from real
|
|
138
|
+
instances of versions 7, 8, 10 and 11.
|
|
139
|
+
|
|
140
|
+
## Development
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
git clone https://github.com/mpasternak/dspace-mcp
|
|
144
|
+
cd dspace-mcp
|
|
145
|
+
uv sync --dev
|
|
146
|
+
uv run pytest # unit tests, offline
|
|
147
|
+
uv run pytest -m live # contract tests against demo.dspace.org
|
|
148
|
+
uv run ruff check .
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Contributions are welcome. The design and its rationale — including why
|
|
152
|
+
several plausible-sounding assumptions about the DSpace API turned out to be
|
|
153
|
+
wrong — live in `docs/superpowers/specs/`.
|
|
154
|
+
|
|
155
|
+
## License
|
|
156
|
+
|
|
157
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# dspace-mcp
|
|
2
|
+
|
|
3
|
+
[](https://github.com/mpasternak/dspace-mcp/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/dspace-mcp/)
|
|
5
|
+
[](https://pypi.org/project/dspace-mcp/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
A read-only [MCP](https://modelcontextprotocol.io/) server that lets an AI
|
|
9
|
+
assistant talk to any [DSpace](https://dspace.org/) 7+ repository.
|
|
10
|
+
|
|
11
|
+
Ask your repository questions in plain language — *"how many theses did we
|
|
12
|
+
publish in 2025?"*, *"which authors appear most often in this collection?"*,
|
|
13
|
+
*"summarise the PDF attached to this item"* — and the assistant answers by
|
|
14
|
+
querying the DSpace REST API directly.
|
|
15
|
+
|
|
16
|
+
## Read-only by construction, not by promise
|
|
17
|
+
|
|
18
|
+
The server holds no credentials and never issues a request other than `GET`.
|
|
19
|
+
It cannot deposit, edit or delete anything, and it cannot read what the public
|
|
20
|
+
cannot already see — embargoed items, workflow submissions and restricted
|
|
21
|
+
collections stay invisible.
|
|
22
|
+
|
|
23
|
+
That is a property of the code, not of the model's behaviour: there is nothing
|
|
24
|
+
to prompt-inject your way into. A test in the suite asserts that no other HTTP
|
|
25
|
+
method ever leaves the process.
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
Nothing to install if you have [uv](https://docs.astral.sh/uv/):
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
uvx dspace-mcp --base-url https://demo.dspace.org/server
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or with pip:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install dspace-mcp
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Configure your MCP client
|
|
42
|
+
|
|
43
|
+
**Claude Code:**
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
claude mcp add dspace -- uvx dspace-mcp --base-url https://demo.dspace.org/server
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Claude Desktop / any client using `mcp.json`:**
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"mcpServers": {
|
|
54
|
+
"dspace": {
|
|
55
|
+
"command": "uvx",
|
|
56
|
+
"args": ["dspace-mcp", "--base-url", "https://demo.dspace.org/server"]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Point `--base-url` at your own repository's REST API — usually your DSpace URL
|
|
63
|
+
with `/server` appended. If you leave `/server` off, the server detects it and
|
|
64
|
+
corrects the URL for you.
|
|
65
|
+
|
|
66
|
+
To connect to several repositories, add several entries under different names.
|
|
67
|
+
One process serves exactly one repository, which keeps the assistant from
|
|
68
|
+
mixing them up.
|
|
69
|
+
|
|
70
|
+
## Tools
|
|
71
|
+
|
|
72
|
+
| Tool | What it does |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `search_items` | Search items; filter by year range, author, collection; sort by relevance, date or title. `limit=0` returns just the count. |
|
|
75
|
+
| `get_item` | Fetch one item by **UUID, Handle or DOI** — whichever identifier you happen to have. |
|
|
76
|
+
| `list_communities` | Walk the community tree (up to 3 levels). |
|
|
77
|
+
| `list_collections` | List collections, of one community or of the whole repository. |
|
|
78
|
+
| `list_bitstreams` | List an item's files with sizes, MIME types, checksums and download URLs. |
|
|
79
|
+
| `get_bitstream_text` | Extract the text of a PDF so the assistant can read or summarise it. |
|
|
80
|
+
| `list_facet_values` | Count values of a facet (authors, subjects, years) — the repository does the counting, so no records are downloaded. |
|
|
81
|
+
| `get_item_statistics` | View count of an item. |
|
|
82
|
+
| `get_repository_info` | Name, version, item counts, and which search filters, sort fields and facets this instance actually supports. |
|
|
83
|
+
|
|
84
|
+
### Two things worth knowing
|
|
85
|
+
|
|
86
|
+
**Ask `get_repository_info` first.** DSpace installations differ: the set of
|
|
87
|
+
search filters and facets is configured per instance, so a filter that exists
|
|
88
|
+
on one repository returns an error on another. This tool reports what the
|
|
89
|
+
instance in front of you supports.
|
|
90
|
+
|
|
91
|
+
**Counting is free.** `search_items` with `limit=0`, and `list_facet_values`,
|
|
92
|
+
answer "how many" questions with a single request and a handful of tokens,
|
|
93
|
+
instead of downloading records and counting them.
|
|
94
|
+
|
|
95
|
+
## Configuration
|
|
96
|
+
|
|
97
|
+
| Variable | Default | Meaning |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| `DSPACE_BASE_URL` | *(required)* | REST API root, e.g. `https://demo.dspace.org/server` |
|
|
100
|
+
| `DSPACE_TIMEOUT` | `15` | seconds per HTTP request |
|
|
101
|
+
| `DSPACE_MAX_RESULTS` | `50` | hard ceiling on how many records any tool may return |
|
|
102
|
+
| `DSPACE_PDF_MAX_MB` | `20` | refuse to download PDFs larger than this |
|
|
103
|
+
|
|
104
|
+
Every variable has a matching flag: `--base-url`, `--timeout`,
|
|
105
|
+
`--max-results`, `--pdf-max-mb`.
|
|
106
|
+
|
|
107
|
+
## Compatibility
|
|
108
|
+
|
|
109
|
+
Verified against DSpace 7.2.1, 7.5, 7.6.5, 8.2, 8.4, 9.2, 10.1 and
|
|
110
|
+
11.0-SNAPSHOT. The test suite runs against recorded responses from real
|
|
111
|
+
instances of versions 7, 8, 10 and 11.
|
|
112
|
+
|
|
113
|
+
## Development
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
git clone https://github.com/mpasternak/dspace-mcp
|
|
117
|
+
cd dspace-mcp
|
|
118
|
+
uv sync --dev
|
|
119
|
+
uv run pytest # unit tests, offline
|
|
120
|
+
uv run pytest -m live # contract tests against demo.dspace.org
|
|
121
|
+
uv run ruff check .
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Contributions are welcome. The design and its rationale — including why
|
|
125
|
+
several plausible-sounding assumptions about the DSpace API turned out to be
|
|
126
|
+
wrong — live in `docs/superpowers/specs/`.
|
|
127
|
+
|
|
128
|
+
## License
|
|
129
|
+
|
|
130
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "dspace-mcp"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Read-only MCP server for DSpace 7+ repositories"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = { text = "MIT" }
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "Michał Pasternak", email = "michal.dtz@gmail.com" },
|
|
10
|
+
]
|
|
11
|
+
keywords = ["dspace", "mcp", "repository", "oai", "llm", "open-access"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Development Status :: 4 - Beta",
|
|
14
|
+
"Intended Audience :: Developers",
|
|
15
|
+
"Intended Audience :: Education",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.10",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Topic :: Text Processing :: Indexing",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"mcp[cli]>=1.28.0",
|
|
26
|
+
"httpx>=0.27",
|
|
27
|
+
"pypdf>=4.0",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://github.com/mpasternak/dspace-mcp"
|
|
32
|
+
Repository = "https://github.com/mpasternak/dspace-mcp"
|
|
33
|
+
Issues = "https://github.com/mpasternak/dspace-mcp/issues"
|
|
34
|
+
|
|
35
|
+
[project.scripts]
|
|
36
|
+
dspace-mcp = "dspace_mcp.server:main"
|
|
37
|
+
|
|
38
|
+
[dependency-groups]
|
|
39
|
+
dev = [
|
|
40
|
+
"pytest>=8.0",
|
|
41
|
+
"pytest-asyncio>=0.23",
|
|
42
|
+
"respx>=0.21",
|
|
43
|
+
"ruff>=0.6",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
[build-system]
|
|
47
|
+
requires = ["hatchling"]
|
|
48
|
+
build-backend = "hatchling.build"
|
|
49
|
+
|
|
50
|
+
[tool.hatch.build.targets.wheel]
|
|
51
|
+
packages = ["src/dspace_mcp"]
|
|
52
|
+
|
|
53
|
+
[tool.hatch.build.targets.sdist]
|
|
54
|
+
include = ["src/dspace_mcp", "tests", "README.md", "LICENSE"]
|
|
55
|
+
|
|
56
|
+
[tool.pytest.ini_options]
|
|
57
|
+
asyncio_mode = "auto"
|
|
58
|
+
testpaths = ["tests"]
|
|
59
|
+
markers = [
|
|
60
|
+
"live: contract tests against a live DSpace instance (deselected by default)",
|
|
61
|
+
]
|
|
62
|
+
addopts = "-m 'not live'"
|
|
63
|
+
|
|
64
|
+
[tool.ruff]
|
|
65
|
+
line-length = 88
|
|
66
|
+
target-version = "py310"
|
|
67
|
+
|
|
68
|
+
[tool.ruff.lint]
|
|
69
|
+
select = ["E", "F", "I", "W", "UP", "B"]
|
|
70
|
+
|
|
71
|
+
[tool.ruff.lint.isort]
|
|
72
|
+
known-first-party = ["dspace_mcp", "conftest"]
|