Skip to main content
Glama
flatmarstheory

rag-reference-discovery-mcp

README.md
# rag-reference-discovery-mcp

A production-oriented, read-only MCP server for discovering and independently validating scholarly metadata from text extracted by an MCP client's own attachment/RAG system.

## Purpose and non-goals

The server accepts extracted assignment or research text, identifies deterministic local-NLP search concepts, queries Crossref, OpenAlex, and supplementary DataCite metadata, ranks candidates, and validates DOI metadata through independent registry sources and DOI content negotiation. It does not directly access client attachments, conversation context, private filesystem paths, or proprietary attachment IDs. It does not create Zotero items, change a Zotero library, download papers, scrape publisher HTML, bypass paywalls, or claim that metadata means a paper was read.

```mermaid
flowchart LR
  A[MCP Client RAG Attachments] --> B[Extracted text sent to MCP tool]
  B --> C[Keyword and query analysis]
  C --> D[Crossref/OpenAlex/DataCite discovery]
  D --> E[Candidate ranking]
  E --> F[DOI validation]
  F --> G[Zotero exact DOI check when configured]
  G --> H[Validated reference metadata returned]
```

## Quick start

```powershell
docker build -t rag-reference-discovery-mcp:latest .
docker run --rm -i --env-file "C:\\MCP\\.env" rag-reference-discovery-mcp:latest
```

Public-only operation needs no Zotero credentials:

```powershell
Copy-Item .env.example .env
# Leave ZOTERO_* values empty
docker run --rm -i --env-file .env rag-reference-discovery-mcp:latest
```

Compose:

```powershell
Copy-Item .env.example .env
docker compose build
docker compose run --rm rag-reference-discovery-mcp
```

The default transport is stdio. stdout is reserved for MCP protocol messages; diagnostics are sent to stderr.

## MCP client configuration

```json
{
  "mcpServers": {
    "rag-reference-discovery": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "--env-file",
        "C:\\MCP\\.env",
        "rag-reference-discovery-mcp:latest"
      ]
    }
  }
}
```

## Attachment handoff

The container cannot magically see attachments held by the MCP client. The client must extract the relevant text and pass it as `source_text` to `analyze_research_text` or `discover_and_validate_references`. `source_name`, `source_type`, `section_hint`, requirements, dates, and scope can be supplied as additional context. The resource tool is an explicit safe fallback: this standalone server returns `attachment_content_unavailable` unless a future MCP host adapter provides a standards-compliant readable resource context. It never fetches arbitrary URIs or local paths.

## Tools

### `analyze_research_text`

Input: `source_text`, optional `source_name`, `source_type`, `section_hint`, `assignment_requirements`, `max_keywords`, and `max_queries`. Returns a research profile, ranked explainable keywords, low-value terms, query variants, constraints, warnings, and source coverage.

Example:

```json
{
  "source_text": "Compare Kubernetes and Docker container orchestration security in higher education between 2022 and 2026.",
  "source_type": "assignment_brief",
  "assignment_requirements": "Use peer-reviewed scholarly sources.",
  "max_keywords": 10
}
```

### `analyze_attachment_resource`

Input: `resource_uri` and optional `section_hint`, requirements, and limits. Returns structured `attachment_content_unavailable` when no safe server-side resource adapter is present. Use direct extracted text for portable operation.

### `discover_references`

Input: at least one of `source_text`, `keywords`, or `queries`, with optional publication years, work types, open-access filter, limits, relevance threshold, and validation mode. Returns `discovered_candidates` separately from any validated records. Discovery uses allowlisted scholarly metadata endpoints only.

### `validate_reference`

Input: a raw DOI, `doi:` value, DOI URL, expected metadata, and options. It normalizes the DOI and independently checks Crossref, DataCite, OpenAlex, and DOI CSL-JSON content negotiation. Conflicting fields remain explicit.

Example:

```json
{
  "doi_or_url": "https://doi.org/10.1000/example",
  "expected_title": "Example study",
  "prefer_zotero": true,
  "include_abstract": false
}
```

### `discover_and_validate_references`

Input: `source_text`, optional requirements, date/type constraints, candidate and validation limits, relevance threshold, and Zotero preference. Runs analysis, discovery, ranking, and independent validation. It returns discovered candidates, validated references, and unresolved/rejected candidates separately. It is not a comprehensive literature review.

Example:

```json
{
  "source_text": "Investigate reproducible Kubernetes security practices for universities from 2022 to 2026.",
  "publication_from_year": 2022,
  "publication_to_year": 2026,
  "max_validated_references": 5
}
```

### `format_validated_reference`

Input: a validated reference object and one of `apa`, `harvard`, `ieee`, `vancouver`, `chicago-author-date`, `bibtex`, or `csl-json`. Only `validated` and `partially_validated` records are accepted. Missing fields stay missing.

### `health`

Returns server version, enabled sources, non-secret Zotero configuration state, cache settings, supported ingestion modes, and stdio transport.

## Zotero

Zotero is optional and read-only. Set `ZOTERO_LOCAL_API_URL` for an operator-configured local endpoint, or set `ZOTERO_API_KEY`, `ZOTERO_LIBRARY_TYPE`, and `ZOTERO_LIBRARY_ID` for optional Web API integration. Public discovery and registry validation work without Zotero. An exact normalized DOI match is a validation/enrichment check, never a discovery requirement. This release reports configuration and continues with independent registries; it never writes, saves, syncs, uploads, or deletes Zotero data.

## Configuration

See `.env.example` for `USER_AGENT`, timeouts, retry and concurrency limits, source text and batch limits, metadata/search TTL cache settings, ranking weights, logging, and optional Zotero variables. Credentials are never emitted in health responses or logs. Attachment text and API keys are not persistently cached. Metadata cache defaults are 24 hours; search cache defaults are 1 hour; transient failures are not cached.

## Security and privacy

Input text, terms, DOI values, and URLs are untrusted. The server uses bounded concurrency, explicit timeouts, allowlisted HTTPS hosts, conservative DOI parsing, and no arbitrary URL fetching. It rejects local/private hosts except an explicitly configured local Zotero endpoint. Retrieved metadata may be incomplete, inconsistent, or updated over time.

## Limitations

Metadata coverage varies by publisher and DOI agency. RAG extraction quality affects keyword quality. Local lexical ranking is not expert literature review. DOI validation confirms metadata consistency, not scientific quality. Some valid works do not have DOIs. Zotero absence does not invalidate a DOI record. Review formatted output against institutional style requirements.

## Troubleshooting

- **No candidates:** supply more specific text or explicit keywords; inspect `errors_by_source` and throttling warnings.
- **Generic keywords:** include the assignment's named technologies, population, method, period, and geography in `source_text`.
- **Invalid DOI:** pass a raw DOI or `https://doi.org/...`; arbitrary publisher URLs are intentionally not scraped.
- **Throttling/timeouts:** provide a descriptive contact `USER_AGENT`, reduce concurrency, and retry later.
- **Zotero not configured:** public validation remains available; this is expected.
- **Zotero mismatch:** exact DOI equality is required and registry conflicts are surfaced.
- **Docker stdin issues:** use `docker run --rm -i`; do not allocate a TTY.
- **Invalid MCP configuration:** use the stdio JSON configuration above and ensure the image is built locally.
- **Resource unavailable:** pass extracted attachment text through `source_text`.

## Development

Use uv for reproducible environments:

```powershell
uv sync --extra dev
uv run ruff check .
uv run pytest
uv lock
```

CI runs Ruff and pytest on Python 3.12 with mocked/local tests only. No live scholarly API calls are required by the test suite.

TDQS

B3.2/5.0

Scored across 7 tools

Disambiguation4/5

Most tools map to distinct workflow stages, but analyze_research_text and analyze_attachment_resource share a similar 'analyze' prefix and discover_references vs discover_and_validate_references could cause some selection confusion. The descriptions mostly clear this up, so the overlap is minor.

Naming Consistency4/5

The set largely follows a clear verb_noun snake_case pattern, e.g. discover_references, validate_reference, format_validated_reference. 'health' is a bare noun and 'discover_and_validate_references' uses a compound verb, creating minor deviations from the dominant pattern.

Tool Count5/5

Seven tools is a well-scoped size for a reference discovery and validation server. Each tool supports a distinct part of the analyze-discover-validate-format workflow without unnecessary bloat.

Completeness5/5

The tool surface covers the full intended pipeline: extracting search terms, discovering references, validating DOIs, combining discovery and validation, and formatting results. The health tool also covers operational needs, and no critical workflow appears missing.

Maintenance

ActivityMaintained
ResponsivenessNo issues