wikicitation-mcp 0.3.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.
- wikicitation_mcp-0.3.0/.github/workflows/tests.yml +62 -0
- wikicitation_mcp-0.3.0/.gitignore +10 -0
- wikicitation_mcp-0.3.0/CHANGELOG.md +41 -0
- wikicitation_mcp-0.3.0/CONTRIBUTING.md +224 -0
- wikicitation_mcp-0.3.0/LICENSE +21 -0
- wikicitation_mcp-0.3.0/PKG-INFO +437 -0
- wikicitation_mcp-0.3.0/README.md +388 -0
- wikicitation_mcp-0.3.0/annotate_utils.py +219 -0
- wikicitation_mcp-0.3.0/citation_utils.py +286 -0
- wikicitation_mcp-0.3.0/config/mcp_config.json +54 -0
- wikicitation_mcp-0.3.0/install.cmd +221 -0
- wikicitation_mcp-0.3.0/mcp_interface.R +460 -0
- wikicitation_mcp-0.3.0/paper/cdss_fig1_sciscore.png +0 -0
- wikicitation_mcp-0.3.0/paper/cdss_fig2_types.png +0 -0
- wikicitation_mcp-0.3.0/paper/cdss_fig5_topcited.png +0 -0
- wikicitation_mcp-0.3.0/paper/fig1_citation_history.png +0 -0
- wikicitation_mcp-0.3.0/paper/paper.bib +335 -0
- wikicitation_mcp-0.3.0/paper/paper.md +288 -0
- wikicitation_mcp-0.3.0/paper/paper.pdf +0 -0
- wikicitation_mcp-0.3.0/pyproject.toml +60 -0
- wikicitation_mcp-0.3.0/pytest.ini +4 -0
- wikicitation_mcp-0.3.0/r_bridge.py +127 -0
- wikicitation_mcp-0.3.0/server.py +647 -0
- wikicitation_mcp-0.3.0/tests/test_annotate_utils.py +274 -0
- wikicitation_mcp-0.3.0/tests/test_bridge.py +339 -0
- wikicitation_mcp-0.3.0/tests/test_citation_utils.py +255 -0
- wikicitation_mcp-0.3.0/tests/test_wiki_api.py +289 -0
- wikicitation_mcp-0.3.0/uv.lock +1678 -0
- wikicitation_mcp-0.3.0/wiki_api.py +343 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Set up Python 3.11
|
|
17
|
+
uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.11"
|
|
20
|
+
|
|
21
|
+
- name: Install uv
|
|
22
|
+
run: pip install uv
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: uv sync --dev
|
|
26
|
+
|
|
27
|
+
- name: Run unit tests (no R required)
|
|
28
|
+
run: uv run pytest -k "not bridge and not integration" -v
|
|
29
|
+
|
|
30
|
+
test-with-r:
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
- name: Set up Python 3.11
|
|
37
|
+
uses: actions/setup-python@v5
|
|
38
|
+
with:
|
|
39
|
+
python-version: "3.11"
|
|
40
|
+
|
|
41
|
+
- name: Set up R
|
|
42
|
+
uses: r-lib/actions/setup-r@v2
|
|
43
|
+
with:
|
|
44
|
+
r-version: "4.3"
|
|
45
|
+
|
|
46
|
+
- name: Install wikilite and dependencies
|
|
47
|
+
run: |
|
|
48
|
+
Rscript -e "install.packages('remotes', repos='https://cloud.r-project.org')"
|
|
49
|
+
Rscript -e "remotes::install_github('jsobel1/wikilite')"
|
|
50
|
+
|
|
51
|
+
- name: Install uv
|
|
52
|
+
run: pip install uv
|
|
53
|
+
|
|
54
|
+
- name: Install Python dependencies
|
|
55
|
+
run: uv sync --dev
|
|
56
|
+
|
|
57
|
+
- name: Run unit + bridge tests
|
|
58
|
+
run: uv run pytest -k "not integration" -v
|
|
59
|
+
|
|
60
|
+
- name: Run integration tests
|
|
61
|
+
run: uv run pytest --run-integration -v
|
|
62
|
+
continue-on-error: true # network calls may flake; don't block CI
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `wikicitation-mcp` are documented here.
|
|
4
|
+
This project adheres to [Semantic Versioning](https://semver.org/).
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## [0.2.0] — 2026-04-25
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Streamable-HTTP transport mode for registration with the claude.ai web interface
|
|
12
|
+
- `uvx wikicitation-mcp` entry point for pip-installable deployment
|
|
13
|
+
- `annotate_doi_list_cross_ref` batch annotation with CrossRef polite-pool support
|
|
14
|
+
- `get_sci_score` corpus-wide quality scoring (proportion of templates with a DOI)
|
|
15
|
+
- Static and interactive visualisation tools (PNG base64 + self-contained HTML)
|
|
16
|
+
- pytest suite: unit tests (mocked subprocess), bridge tests (real Rscript),
|
|
17
|
+
and integration tests (live MediaWiki API, auto-skipped when wikilite absent)
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- Migrated R backend from `WikiCitationHistoRy` to `wikilite`
|
|
21
|
+
- Renamed server from `WikiCitationHistoRy-mcp` to `wikicitation-mcp`
|
|
22
|
+
- R bridge now uses a fresh `Rscript` subprocess per call (eliminates shared
|
|
23
|
+
session state and memory leaks; adds ~0.3 s per-call overhead)
|
|
24
|
+
- Error boundaries: R-level exceptions are now propagated as descriptive
|
|
25
|
+
Python `RuntimeError` rather than raw stderr output
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- `get_top_cited_papers`: resolved `pkg.env not found` error on Windows
|
|
29
|
+
- Auto-detection of `Rscript` on Windows when not in `PATH`
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## [0.1.0] — 2026-01-10
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
- Initial public release
|
|
37
|
+
- 43 MCP tools wrapping the wikilite R package
|
|
38
|
+
- stdio transport (Claude Desktop / Claude Code)
|
|
39
|
+
- JSON-over-stdio R bridge (`r_bridge.py` + `mcp_interface.R`)
|
|
40
|
+
- Configuration for Claude Desktop (`config/mcp_config.json`)
|
|
41
|
+
- Windows installer script (`install.cmd`)
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Contributing to wikicitation-mcp
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing! This document explains how to
|
|
4
|
+
report bugs, request features, and submit code changes.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Table of Contents
|
|
9
|
+
|
|
10
|
+
- [Code of Conduct](#code-of-conduct)
|
|
11
|
+
- [Reporting Bugs](#reporting-bugs)
|
|
12
|
+
- [Requesting Features](#requesting-features)
|
|
13
|
+
- [Development Setup](#development-setup)
|
|
14
|
+
- [Running the Test Suite](#running-the-test-suite)
|
|
15
|
+
- [Submitting a Pull Request](#submitting-a-pull-request)
|
|
16
|
+
- [Code Style](#code-style)
|
|
17
|
+
- [Adding or Modifying Tools](#adding-or-modifying-tools)
|
|
18
|
+
- [Support and Questions](#support-and-questions)
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Code of Conduct
|
|
23
|
+
|
|
24
|
+
This project follows the
|
|
25
|
+
[Contributor Covenant](https://www.contributor-covenant.org/version/2/1/code_of_conduct/)
|
|
26
|
+
code of conduct. By participating you agree to abide by its terms. Please
|
|
27
|
+
report unacceptable behaviour to the repository maintainer via a private
|
|
28
|
+
GitHub message or the email address in `pyproject.toml`.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Reporting Bugs
|
|
33
|
+
|
|
34
|
+
Before opening an issue, please:
|
|
35
|
+
|
|
36
|
+
1. Search [existing issues](https://github.com/jsobel1/wikicitation-mcp/issues)
|
|
37
|
+
to avoid duplicates.
|
|
38
|
+
2. Reproduce the bug on the latest commit of `main`.
|
|
39
|
+
|
|
40
|
+
When opening a bug report, include:
|
|
41
|
+
|
|
42
|
+
- Your operating system and Python version (`python --version`).
|
|
43
|
+
- Your R version (`R --version`) and `wikilite` version
|
|
44
|
+
(`packageVersion("wikilite")` inside R).
|
|
45
|
+
- The exact tool call or natural-language prompt that triggered the bug.
|
|
46
|
+
- The full error message and stack trace (Python side) or R traceback.
|
|
47
|
+
- Whether the bug is reproducible with a public Wikipedia article (preferred)
|
|
48
|
+
or only with a private/restricted one.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Requesting Features
|
|
53
|
+
|
|
54
|
+
Open an issue with the label **enhancement**. Please describe:
|
|
55
|
+
|
|
56
|
+
- The Wikipedia citation analysis task you are trying to accomplish.
|
|
57
|
+
- Which existing `wikilite` R function, if any, would cover it (see the
|
|
58
|
+
[wikilite documentation](https://github.com/jsobel1/wikilite)).
|
|
59
|
+
- Any relevant API endpoints or data sources involved.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Development Setup
|
|
64
|
+
|
|
65
|
+
### Prerequisites
|
|
66
|
+
|
|
67
|
+
| Tool | Minimum version |
|
|
68
|
+
|------|----------------|
|
|
69
|
+
| Python | 3.10 |
|
|
70
|
+
| [uv](https://docs.astral.sh/uv/) | latest |
|
|
71
|
+
| R | 4.0 |
|
|
72
|
+
| wikilite R package | latest (`remotes::install_github("jsobel1/wikilite")`) |
|
|
73
|
+
|
|
74
|
+
### Clone and install
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
git clone https://github.com/jsobel1/wikicitation-mcp.git
|
|
78
|
+
cd wikicitation-mcp
|
|
79
|
+
|
|
80
|
+
# Create virtual environment and install dependencies
|
|
81
|
+
uv sync --dev
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Verify the R bridge
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
uv run python -c "
|
|
88
|
+
import asyncio, json
|
|
89
|
+
from r_bridge import call_r_tool
|
|
90
|
+
result = asyncio.run(call_r_tool('count_citations', {'article': 'Zeitgeber'}))
|
|
91
|
+
print(json.dumps(result, indent=2))
|
|
92
|
+
"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
A successful response returns a JSON object with citation counts. If you see
|
|
96
|
+
a `RuntimeError`, check that `Rscript` is on your `PATH` and that `wikilite`
|
|
97
|
+
is installed in R.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Running the Test Suite
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
uv run pytest
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The suite has three levels:
|
|
108
|
+
|
|
109
|
+
| Level | What it tests | Requires R? |
|
|
110
|
+
|-------|--------------|-------------|
|
|
111
|
+
| Unit | JSON serialisation, error propagation, timeout handling | No |
|
|
112
|
+
| Bridge | Real `Rscript` subprocess against known wikitext | Yes |
|
|
113
|
+
| Integration | Live MediaWiki API calls (skipped if `wikilite` absent) | Yes + network |
|
|
114
|
+
|
|
115
|
+
To run only unit tests (no R needed):
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
uv run pytest -k "not bridge and not integration"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
To run the full suite including live API calls:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
uv run pytest --run-integration
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
All tests must pass before a pull request will be merged.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Submitting a Pull Request
|
|
132
|
+
|
|
133
|
+
1. **Fork** the repository and create a feature branch from `main`:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
git checkout -b feature/my-improvement
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
2. **Make your changes** following the code style guidelines below.
|
|
140
|
+
|
|
141
|
+
3. **Add or update tests** — new MCP tools should have at least a unit test
|
|
142
|
+
(mocked subprocess) and a bridge test.
|
|
143
|
+
|
|
144
|
+
4. **Update documentation** — if you add a tool, document it in `README.md`
|
|
145
|
+
under the appropriate category table.
|
|
146
|
+
|
|
147
|
+
5. **Commit with a descriptive message**:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
Add get_citation_network tool for co-citation graph export
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
6. **Push and open a PR** against `main`. The PR description should explain
|
|
154
|
+
*what* changed and *why*, and link to any relevant issue.
|
|
155
|
+
|
|
156
|
+
Pull requests are reviewed by the maintainer. Please allow up to two weeks
|
|
157
|
+
for an initial response. Large or complex changes may require discussion
|
|
158
|
+
before implementation — consider opening an issue first.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Code Style
|
|
163
|
+
|
|
164
|
+
**Python**
|
|
165
|
+
|
|
166
|
+
- Follow [PEP 8](https://peps.python.org/pep-0008/).
|
|
167
|
+
- Use type annotations for all function signatures.
|
|
168
|
+
- Keep MCP tool docstrings concise — they appear in the LLM tool catalogue.
|
|
169
|
+
- Format with [ruff](https://docs.astral.sh/ruff/):
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
uv run ruff format .
|
|
173
|
+
uv run ruff check .
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**R**
|
|
177
|
+
|
|
178
|
+
- Follow the [tidyverse style guide](https://style.tidyverse.org/) for any
|
|
179
|
+
changes to `mcp_interface.R`.
|
|
180
|
+
- All R-level errors must be caught and returned as a JSON object with key
|
|
181
|
+
`"error"` so the Python bridge can re-raise them as descriptive
|
|
182
|
+
`RuntimeError` exceptions.
|
|
183
|
+
|
|
184
|
+
**Commits**
|
|
185
|
+
|
|
186
|
+
- Write commit messages in the imperative mood: *"Add …"*, *"Fix …"*, *"Remove …"*.
|
|
187
|
+
- Keep the subject line to 72 characters or fewer.
|
|
188
|
+
- Reference issue numbers where applicable: `Fix timeout on large articles (#12)`.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Adding or Modifying Tools
|
|
193
|
+
|
|
194
|
+
`wikicitation-mcp` wraps functions from the `wikilite` R package. To add a
|
|
195
|
+
new tool:
|
|
196
|
+
|
|
197
|
+
1. **Identify the `wikilite` function** you want to expose and its expected
|
|
198
|
+
arguments and return structure.
|
|
199
|
+
|
|
200
|
+
2. **Add the R dispatch** in `mcp_interface.R` — add a case to the main
|
|
201
|
+
`switch` statement that calls the function and returns
|
|
202
|
+
`jsonlite::toJSON(result, auto_unbox = TRUE)`.
|
|
203
|
+
|
|
204
|
+
3. **Register the MCP tool** in `server.py` using the `@mcp.tool()` decorator.
|
|
205
|
+
Provide a clear docstring and typed argument schema; the docstring text
|
|
206
|
+
is shown to the LLM as the tool description.
|
|
207
|
+
|
|
208
|
+
4. **Write tests** — at minimum a unit test that mocks the subprocess and
|
|
209
|
+
verifies JSON round-tripping, and a bridge test that exercises the R
|
|
210
|
+
dispatch layer against known input.
|
|
211
|
+
|
|
212
|
+
5. **Update `README.md`** — add a row to the relevant category table.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Support and Questions
|
|
217
|
+
|
|
218
|
+
For general questions about usage, open a
|
|
219
|
+
[GitHub Discussion](https://github.com/jsobel1/wikicitation-mcp/discussions).
|
|
220
|
+
For bug reports and feature requests, use
|
|
221
|
+
[GitHub Issues](https://github.com/jsobel1/wikicitation-mcp/issues).
|
|
222
|
+
|
|
223
|
+
This project is maintained by a single developer. Response times may vary,
|
|
224
|
+
but all issues and PRs will receive a reply within two weeks.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jonathan Sobel
|
|
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.
|