Read-only MCP server for DSpace 7+ repositories
Project description
dspace-mcp
A read-only MCP server that lets an AI assistant talk to any DSpace 7+ repository.
Ask your repository questions in plain language — "how many theses did we publish in 2025?", "which authors appear most often in this collection?", "summarise the PDF attached to this item" — and the assistant answers by querying the DSpace REST API directly.
Read-only by construction, not by promise
The server holds no credentials and never issues a request other than GET.
It cannot deposit, edit or delete anything, and it cannot read what the public
cannot already see — embargoed items, workflow submissions and restricted
collections stay invisible.
That is a property of the code, not of the model's behaviour: there is nothing to prompt-inject your way into. A test in the suite asserts that no other HTTP method ever leaves the process.
Install
Nothing to install if you have uv:
uvx dspace-mcp --base-url https://demo.dspace.org/server
Or with pip:
pip install dspace-mcp
Configure your MCP client
Claude Code:
claude mcp add dspace -- uvx dspace-mcp --base-url https://demo.dspace.org/server
Claude Desktop / any client using mcp.json:
{
"mcpServers": {
"dspace": {
"command": "uvx",
"args": ["dspace-mcp", "--base-url", "https://demo.dspace.org/server"]
}
}
}
Point --base-url at your own repository's REST API — usually your DSpace URL
with /server appended. If you leave /server off, the server detects it and
corrects the URL for you.
To connect to several repositories, add several entries under different names. One process serves exactly one repository, which keeps the assistant from mixing them up.
Tools
| Tool | What it does |
|---|---|
search_items |
Search items; filter by year range, author, collection; sort by relevance, date or title. limit=0 returns just the count. |
get_item |
Fetch one item by UUID, Handle or DOI — whichever identifier you happen to have. |
list_communities |
Walk the community tree (up to 3 levels). |
list_collections |
List collections, of one community or of the whole repository. |
list_bitstreams |
List an item's files with sizes, MIME types, checksums and download URLs. |
get_bitstream_text |
Extract the text of a PDF so the assistant can read or summarise it. |
list_facet_values |
Count values of a facet (authors, subjects, years) — the repository does the counting, so no records are downloaded. |
get_item_statistics |
View count of an item. |
get_repository_info |
Name, version, item counts, and which search filters, sort fields and facets this instance actually supports. |
Two things worth knowing
Ask get_repository_info first. DSpace installations differ: the set of
search filters and facets is configured per instance, so a filter that exists
on one repository returns an error on another. This tool reports what the
instance in front of you supports.
Counting is free. search_items with limit=0, and list_facet_values,
answer "how many" questions with a single request and a handful of tokens,
instead of downloading records and counting them.
Configuration
| Variable | Default | Meaning |
|---|---|---|
DSPACE_BASE_URL |
(required) | REST API root, e.g. https://demo.dspace.org/server |
DSPACE_TIMEOUT |
15 |
seconds per HTTP request |
DSPACE_MAX_RESULTS |
50 |
hard ceiling on how many records any tool may return |
DSPACE_PDF_MAX_MB |
20 |
refuse to download PDFs larger than this |
Every variable has a matching flag: --base-url, --timeout,
--max-results, --pdf-max-mb.
Compatibility
Nothing here branches on a version number. The server asks each instance which search filters, sort fields and facets it supports and works from that answer, which is what actually varies between installations — two sites on the same DSpace version can differ more than two versions of the same site.
The offline test suite runs against recorded responses from a live DSpace
10.1-SNAPSHOT (demo.dspace.org), covering every endpoint the server touches,
plus root and search responses from a vanilla 7.6.5, a DSpace-CRIS 8.2 and an
11.0-SNAPSHOT for comparing response shape. The contract tests
(pytest -m live) run against one instance at a time — demo.dspace.org by
default, or point DSPACE_TEST_URL at your own.
While the tool was being designed, its assumptions about the REST API were checked by hand against live instances of 7.2.1, 7.5, 7.6.5, 8.2, 8.4, 9.2, 10.1 and 11.0-SNAPSHOT. That was a survey of the API, not a test run of this code. If it misbehaves on a version or a configuration I could not test, a bug report is welcome.
Development
git clone https://github.com/mpasternak/dspace-mcp
cd dspace-mcp
uv sync --dev
uv run pytest # unit tests, offline
uv run pytest -m live # contract tests against demo.dspace.org
uv run ruff check .
Contributions are welcome. The design and its rationale — including why
several plausible-sounding assumptions about the DSpace API turned out to be
wrong — live in docs/superpowers/specs/.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dspace_mcp-0.1.1.tar.gz.
File metadata
- Download URL: dspace_mcp-0.1.1.tar.gz
- Upload date:
- Size: 76.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f93a5bae52624c2b2ea51e0f3b17a8fa748b074c9197f1b7ec6ef5f8bb337870
|
|
| MD5 |
eda1fe2135da419e39f71c74b3e14c74
|
|
| BLAKE2b-256 |
4eecfc40156836903f7eb7a27cdb0cb4510ee18e4f0a47f0d635dcc3965374ac
|
Provenance
The following attestation bundles were made for dspace_mcp-0.1.1.tar.gz:
Publisher:
publish.yml on mpasternak/dspace-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dspace_mcp-0.1.1.tar.gz -
Subject digest:
f93a5bae52624c2b2ea51e0f3b17a8fa748b074c9197f1b7ec6ef5f8bb337870 - Sigstore transparency entry: 2219176952
- Sigstore integration time:
-
Permalink:
mpasternak/dspace-mcp@08cd42d2123b83ef27664f04bd94784671d961a9 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/mpasternak
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@08cd42d2123b83ef27664f04bd94784671d961a9 -
Trigger Event:
release
-
Statement type:
File details
Details for the file dspace_mcp-0.1.1-py3-none-any.whl.
File metadata
- Download URL: dspace_mcp-0.1.1-py3-none-any.whl
- Upload date:
- Size: 32.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6d00bce5d150b6e27e78914735c75ed52f0de337a061efd5737e38db3ab82fca
|
|
| MD5 |
a5dc55a8fe2070d6c91f36b50ec695fc
|
|
| BLAKE2b-256 |
52d1aa73e7126c2240a7c51fef215fcc0e0efae807aaf4b8bf080c0726f0b2e7
|
Provenance
The following attestation bundles were made for dspace_mcp-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on mpasternak/dspace-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dspace_mcp-0.1.1-py3-none-any.whl -
Subject digest:
6d00bce5d150b6e27e78914735c75ed52f0de337a061efd5737e38db3ab82fca - Sigstore transparency entry: 2219177398
- Sigstore integration time:
-
Permalink:
mpasternak/dspace-mcp@08cd42d2123b83ef27664f04bd94784671d961a9 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/mpasternak
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@08cd42d2123b83ef27664f04bd94784671d961a9 -
Trigger Event:
release
-
Statement type: