OSTI MCP Server
by jsevarts
README.md
# OSTI MCP Server
An [MCP](https://modelcontextprotocol.io) server that exposes [OSTI.gov](https://www.osti.gov)'s
public search API as tools Claude can call directly — so Claude can search and
retrieve DOE-sponsored scientific literature (technical reports, journal
articles, theses/dissertations, patents, datasets) in the middle of a
conversation.
## What it does
Two tools:
- **`search_osti`** — keyword/author/identifier search over OSTI records,
with filters for research organization, sponsoring DOE office,
publication date range, product type (journal article, technical report,
thesis, patent, dataset), and full-text availability. Returns a `total`
count of all matching records (not just the current page) alongside the
page itself; `rows` is capped at 100 per request.
- **`get_osti_record`** — fetch full metadata (abstract, subjects,
identifiers, links to citation and full-text pages) for a single record by
its OSTI ID.
No API key or authentication is required — this only uses OSTI's public
read/search API, not the authenticated ELINK submission API.
## Install
Requires Python 3.10+. Dependencies are declared once in `pyproject.toml`,
so pick whichever environment manager you use:
**pip / venv:**
```bash
git clone https://github.com/jsevarts/mcp-osti.git
cd mcp-osti
python3 -m venv venv
source venv/bin/activate
pip install -e ".[dev]"
```
**conda:**
```bash
git clone https://github.com/jsevarts/mcp-osti.git
cd mcp-osti
conda env create -f environment.yml
conda activate osti-mcp
```
## Try it out
Sanity-check the server directly:
```bash
python osti_mcp_server.py
```
Or open the [MCP Inspector](https://github.com/modelcontextprotocol/inspector)
for interactive testing:
```bash
mcp dev osti_mcp_server.py
```
## Register with Claude Code / Claude Desktop / Claude Science
Point at the Python interpreter inside whichever environment you created
above — e.g. `venv/bin/python3` for pip/venv, or the output of
`conda run -n osti-mcp which python3` for conda.
**Claude Code:**
```bash
claude mcp add --transport stdio osti -- /full/path/to/python3 /full/path/to/osti_mcp_server.py
```
**Claude Desktop / Claude Science** (Settings → Developer → Edit Config, add
to `mcpServers`):
```json
{
"mcpServers": {
"osti": {
"command": "/full/path/to/python3",
"args": ["/full/path/to/osti_mcp_server.py"]
}
}
}
```
Restart the app afterward.
## Example query
> "Search OSTI for recent DOE-funded work on phase-field modeling of grain
> boundary migration, and pull the full abstract for the most relevant
> result."
## API notes
Verified against the live API, not just the [docs page](https://www.osti.gov/api/v1/docs):
- `GET /records` returns a bare JSON array at the top level (no `records`
wrapper). Pagination metadata (`X-Total-Count`, `Link`) comes back in
response headers, not the JSON body.
- `GET /records/{osti_id}` **also** returns a JSON array (containing zero or
one record), not a single object — easy to miss.
- `publication_date_start`/`_end` must be sent as `MM/DD/YYYY`. Sending ISO
dates causes an HTTP 500 rather than a clean error. This server accepts
ISO `YYYY-MM-DD` dates from the caller and converts them internally, so
Claude can pass normal ISO dates without knowing about this quirk.
- OSTI doesn't publish a documented hard rate limit. It does send an
`X-Rate-Limit-Remaining` header, but it read `0` on every request observed
during testing even as requests kept succeeding — it doesn't appear to be
reliably actionable, so this server doesn't throttle on it. Keep `rows`
modest and avoid tight request loops.
## Testing
```bash
pip install -e ".[dev]" # or: conda env create -f environment.yml && conda activate osti-mcp
python -m pytest tests/
```
Tests mock `requests.get`, so they run offline.
## License
MIT — see [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues