# miscite — LLM / AI Agent Guide > Scholar research workspace: semantic literature search, citation analysis, > research profile, library, alerts, and recommendations. ## What miscite does miscite is a citation-check and research workspace platform for academics. It analyzes PDF/DOCX manuscripts to flag citation issues (missing references, retractions, predatory venues, inappropriate citations), provides semantic literature search over OpenAlex-indexed academic works, and offers a full research workspace with library management, research profiles, and automated research alerts with LLM-planned search strategies. ## Connecting via MCP (recommended) miscite exposes all services through a Model Context Protocol (MCP) server using Streamable HTTP (`streamable-http`) transport. MCP endpoint: https://miscite.review/mcp/ ### Claude Code Add miscite to your project's `.mcp.json`: ```json { "mcpServers": { "miscite": { "type": "http", "url": "https://miscite.review/mcp/" } } } ``` Or run: `claude mcp add miscite --transport http https://miscite.review/mcp/` ### Claude Desktop Claude Desktop requires the `mcp-remote` bridge for remote HTTP servers. Add to your config file (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS, `%APPDATA%\Claude\claude_desktop_config.json` on Windows): ```json { "mcpServers": { "miscite": { "command": "npx", "args": ["mcp-remote", "https://miscite.review/mcp/"] } } } ``` ### OpenAI Codex Add to `~/.codex/config.toml` (global) or `.codex/config.toml` (project): ```toml [mcp_servers.miscite] url = "https://miscite.review/mcp/" ``` ### Other MCP clients Any MCP-compatible client can connect using: - **URL:** `https://miscite.review/mcp/` - **Transport:** Streamable HTTP ### Authentication Semantic search is free and open: the Search tools (`search`, `search_health`, `work_lookup`) and the `health`/`ready` probes need NO token. Passing a token to `search` is optional and only records the query in your search history. All other tools — including citation analysis / report checks, library, profile, alerts, and account — require an API Bearer token passed as the `token` parameter. Tokens are created from the account settings page at /account or via the `create_api_token` tool. ## Available MCP tools (43 total) Tool parameters are passed by name. The Search tools and the `health`/`ready` probes need no token; all other tools take a `token` (your API Bearer token; see Authentication above). ### Search (3 tools) `search` — Search academic literature. POST /api/v1/search/query - token (str, optional): no token needed; supply one only to record the query in your search history - query (str, required): search text, 1-1024 chars. Hybrid retrieval works best when the query mixes natural-language context with exact-match keywords. - limit (int, default 20): max results, 1-100 (out-of-range -> 422) - retrieval_mode (str, default "hybrid"): "semantic", "lexical", or "hybrid" - sort_by (str, default "relevance"): one of "relevance", "citations_desc", "year_desc". NOTE: "cited_by_count" is NOT valid — the REST endpoint rejects it with 422; use "citations_desc" (the MCP `search` tool also accepts the alias). - hybrid_alpha (float, default 0.7): semantic-vs-lexical blend for hybrid mode, 0.0-1.0 (higher favors semantic); ignored for non-hybrid modes. - filters (dict, optional): EXACT keys only. The filter schema is strict (extra="forbid"), so any unknown key — including "open_access" — is rejected with 422; it is never silently ignored. Common keys (use these exact names): publication_year_min / publication_year_max (int), publication_year_in (list[int]), citation_count_min / citation_count_max (int), languages (list[str]), is_oa (bool), open_access_statuses (list[str]), is_retracted (bool), has_fulltext (bool), has_abstract (bool), work_types (list[str]), source_names (list[str]), source_issn (list[str]), is_wos (bool), wos_indexes (list[str], e.g. ["SCIE","SSCI","AHCI","ESCI"]), wos_categories (list[str]), wos_perf_quartiles (list[str], e.g. ["Q1","Q2"]), wos_perf_jif_min / wos_perf_jif_max (float), wos_perf_jci_min / wos_perf_jci_max (float). Returns: an OBJECT (not a bare list) — {"query", "total_returned", "hits": [...]}. Each hit has openalex_id, score (+ semantic_score / lexical_score / hybrid_score), title, doi, publication_year, cited_by_count, fwci, source_display_name, wos_indexes, wos_categories, and a nested "payload" with the full work metadata. `search_health` — Check search service availability. GET /api/v1/search/health - token (str, optional): not required (open endpoint) Returns: {"status": "..."} only (the collection name and Qdrant mode are not exposed on this public endpoint). `work_lookup` — Look up a work by OpenAlex ID. GET /api/v1/search/works/{id} - token (str, optional): not required (open endpoint; include_fulltext is open too) - openalex_id (str, required): bare ID (e.g. "W2100837269") or the full "https://openalex.org/W..." URL that search hits return — both work - include_fulltext (bool, default false): also fetch fulltext markdown (slow) Returns: {"openalex_id", "payload": {...work metadata...}, "fulltext": {"ok", "markdown", "markdown_truncated", "markdown_char_count"} | null}. Metadata is under "payload"; "fulltext" is null unless include_fulltext=true, and when fulltext retrieval fails it is present with "ok": false and no markdown (the lookup itself still succeeds). ### Analysis (8 tools) Jobs run asynchronously. The job `status` is one of the UPPERCASE values PENDING, RUNNING, COMPLETED, FAILED, CANCELED. Terminal states are COMPLETED, FAILED, and CANCELED — stop polling on ANY of them. A check for only "COMPLETED" (or a lowercase "completed") will hang on a failed/canceled job. On FAILED, read `error_message`. `upload_document` — Upload PDF/DOCX for citation analysis. POST /api/v1/analysis/upload - token (str, required): API Bearer token - filename (str, required): must end in .pdf or .docx (validated by extension; a bad extension returns 400) - file_content_base64 (str, required): base64-encoded file content - content_type (str, default "application/pdf"): MIME type (stored, not validated) Returns 201 with {"id": "", "status": "PENDING"}. Analysis runs asynchronously (typically 1-5 minutes); poll `get_job` (or follow `get_job_events`) until status is COMPLETED/FAILED/CANCELED. May return 402 (insufficient balance) or 503 (maintenance). `list_jobs` — List analysis jobs. GET /api/v1/analysis/jobs - token (str, required): API Bearer token - status (str, optional): filter by "processing" (= PENDING or RUNNING), "completed" (= COMPLETED), or "failed" (= FAILED or CANCELED). Case-insensitive; an unrecognized value is ignored (returns all jobs). - limit (int, default 25): max results, 1-100 (out-of-range -> 422) - offset (int, default 0): pagination offset Returns: {"data": [...], "total", "limit", "offset"}. Each job has id, status (uppercase), filename, created_at, started_at, finished_at, error_message. `get_job` — Get job status and report. GET /api/v1/analysis/jobs/{job_id} - token (str, required): API Bearer token - job_id (str, required): the job ID Returns: {id, status, created_at, started_at, finished_at, error_message, report, data_sources, methodology_md, billing}. `report` is null until COMPLETED; then: - summary: {total_citations, total_intext_citations, ambiguous_bibliography_refs, missing_bibliography_refs, unresolved_references, retracted_references, predatory_matches, potentially_inappropriate} - issues[]: each with a `type` of missing_bibliography_ref, ambiguous_bibliography_ref, unresolved_reference, retracted_article, predatory_venue_match, potentially_inappropriate, preprint_has_published_version, or needs_manual_review - citations[]: per-citation {citation, match:{ref_id, status, confidence, method, notes, candidates[]}} - references[], and deep_analysis: ranked recommendations, suggestions, potential_reviewers, etc. (may be {"status": "failed"|"skipped"}) `get_job_events` — Follow job progress. GET /api/v1/analysis/jobs/{job_id}/events - token (str, required): API Bearer token - job_id (str, required): the job ID - since_id (int, default 0): return only events with id greater than this Returns: {status, error_message, events: [{id, stage, message, progress, created_at}]} where progress is 0.0-1.0. Pass the last seen event id as since_id to follow long analyses instead of opaque get_job polling. `cancel_job` — Cancel a running job. POST /api/v1/analysis/jobs/{job_id}/cancel - token (str, required): API Bearer token - job_id (str, required): the job ID Idempotent: returns {"status": "CANCELED"} on success, or {"status": , "message": "Job already finished."} if the job is already terminal. `delete_job` — Delete job and document. DELETE /api/v1/analysis/jobs/{job_id} - token (str, required): API Bearer token - job_id (str, required): the job ID Returns {"ok": true}. `get_report_pdf` — Download report as PDF. GET /api/v1/analysis/jobs/{job_id}/report.pdf - token (str, required): API Bearer token - job_id (str, required): the job ID Returns {"content_base64", "content_type": "application/pdf"} on success, or {"error", "status_code"} on failure — notably 409 until the report exists, so call only after status is COMPLETED. `share_report` — Share report via email. POST /api/v1/analysis/jobs/{job_id}/share-email - token (str, required): API Bearer token - job_id (str, required): job ID of a COMPLETED report (else 409) - recipient_email (str, required): valid email address (else 422) - personal_message (str, default ""): optional message, truncated to 500 chars Returns {"ok": true, "status": "sent"} (502 if the email fails to send). ### Library (12 tools) Manage a Zotero-style collection tree of saved references. Collections can be nested using path-style names (e.g. "Research/ML Papers"). System collections (Unfiled, Readlist, Own publications) cannot be deleted. Items can have file attachments (PDFs, etc.). `list_collections` — List all collections. GET /api/v1/sync/collections - token (str, required): API Bearer token Returns: list of collections with id, name, description, item count. `create_collection` — Create a collection. POST /api/v1/sync/collections - token (str, required): API Bearer token - name (str, required): collection name, max 120 chars - description (str, default ""): optional description `delete_collection` — Delete a collection. DELETE /api/v1/sync/collections/{id} - token (str, required): API Bearer token - collection_id (int, required): collection ID User-created collection deletes remove only the collection branch and move newly orphaned items to Unfiled. `list_items` — List library items. GET /api/v1/sync/items - token (str, required): API Bearer token - limit (int, default 100): max results, 1-500 - offset (int, default 0): pagination offset - since (str, optional): ISO datetime for incremental sync Returns: list of items with title, authors, DOI, source, year, notes, etc. `create_item` — Create a library item. POST /api/v1/sync/items - token (str, required): API Bearer token - title (str, required): title of the work - doi (str, default ""): DOI identifier - openalex_id (str, default ""): OpenAlex ID - authors (list[dict], optional): [{"name": "..."}, ...] - source_display_name (str, default ""): journal/source name - publication_year (int, optional): year of publication - work_type (str, default ""): e.g. "journal-article" - notes (str, default ""): user notes - collection_ids (list[int], optional): collections to add the item to Same normalized DOI is merged into the user's canonical library item. `update_item` — Update item metadata. PUT /api/v1/sync/items/{item_id} - token (str, required): API Bearer token - item_id (int, required): item ID - updates (dict, required): fields to update (title, doi, authors, notes, etc.) `delete_item` — Delete a library item. DELETE /api/v1/sync/items/{item_id} - token (str, required): API Bearer token - item_id (int, required): item ID `save_search_hit` — Save a search result to library. POST /api/v1/sync/items - token (str, required): API Bearer token - title (str, required): title of the work - openalex_id (str, default ""): OpenAlex ID from search results - doi (str, default ""): DOI from search results - collection_id (int, optional): collection to save into - payload (dict, optional): full work metadata payload from search results `list_item_files` — List files attached to a library item. GET /api/v1/sync/items/{item_id}/files - token (str, required): API Bearer token - item_id (int, required): library item ID Returns: list of files with id, filename, content_type, file_size, sha256, created_at. `download_file` — Download a library file as base64. GET /api/v1/sync/files/{file_id}/download - token (str, required): API Bearer token - file_id (int, required): file ID Returns: base64-encoded file content. `upload_item_file` — Upload a file attachment to a library item. POST /api/v1/sync/items/{item_id}/files - token (str, required): API Bearer token - item_id (int, required): library item ID - filename (str, required): original filename (e.g. "paper.pdf") - file_content_base64 (str, required): base64-encoded file content - content_type (str, default "application/pdf"): MIME type `delete_file` — Delete a file attachment. DELETE /api/v1/sync/files/{file_id} - token (str, required): API Bearer token - file_id (int, required): file ID ### Profile (5 tools) Research identity with LLM-summarized fields, interest tags (pinned + auto), and connected public profiles. `get_profile` — Get research profile. GET /api/v1/profile/ - token (str, required): API Bearer token Returns: profile fields, interest tags, connected sources, refresh status. `update_interests` — Update interest tags. PATCH /api/v1/profile/interests - token (str, required): API Bearer token - tags (list, required): list of tag strings or dicts with "label" and optional "pinned" (bool) keys. Example: ["machine learning", {"label": "NLP", "pinned": true}] `refresh_profile` — Trigger profile refresh. POST /api/v1/profile/refresh - token (str, required): API Bearer token Triggers async re-import from connected sources and LLM re-summarization. `list_sources` — List connected sources. GET /api/v1/profile/sources - token (str, required): API Bearer token Returns: sources by type (google_scholar, orcid, academia, homepage) with URL, fetch status, and extracted metadata. `sync_sources` — Connect/update profile sources. POST /api/v1/profile/sources/sync - token (str, required): API Bearer token - urls_by_type (dict, required): {"google_scholar": "https://scholar...", "orcid": "https://orcid.org/0000-...", "homepage": "https://faculty..."} ### Alerts (8 tools) Research alerts with LLM-planned multi-query searches, three-section digests (Latest Research, Most Relevant, Classics), engagement-aware query planning, and post-search LLM refinement. `list_alerts` — List all alerts. GET /api/v1/alerts/ - token (str, required): API Bearer token Returns: list of alerts with config, schedule, and last digest info. `save_alert` — Create or update an alert. POST /api/v1/alerts/ - token (str, required): API Bearer token - title (str, required): alert title - enabled (bool, default true): whether alert is active - include_profile (bool, default true): use profile interests in search - custom_query_text (str, default ""): custom search query - search_method (str, default "semantic"): "semantic", "lexical", or "hybrid" - frequency (str, default "weekly"): "daily", "weekly", "biweekly", "monthly" - library_item_ids (list[int], optional): library items as search context - wos_only (bool, default false): restrict to WoS-indexed works - wos_indexes (list[str], optional): e.g. ["SCIE", "SSCI"] - wos_quartiles (list[str], optional): e.g. ["Q1", "Q2"] - wos_jci_quartiles (list[str], optional): JCI quartile filters - day_of_week (int, optional): 0=Monday to 6=Sunday (for weekly) - day_of_month (int, optional): 1-28 (for monthly) - alert_id (int, optional): if set, updates existing alert `preview_alert` — Preview alert results without saving. POST /api/v1/alerts/preview - token (str, required): API Bearer token - (same config params as save_alert, minus alert_id) `toggle_alert` — Enable/disable an alert. PATCH /api/v1/alerts/{alert_id}/toggle - token (str, required): API Bearer token - alert_id (int, required): alert ID - enabled (bool, required): true to enable, false to disable `delete_alert` — Delete an alert. DELETE /api/v1/alerts/{alert_id} - token (str, required): API Bearer token - alert_id (int, required): alert ID `send_digest` — Generate and send digest now. POST /api/v1/alerts/{alert_id}/digest - token (str, required): API Bearer token - alert_id (int, required): alert ID `run_research_updates` — Generate fresh recommendations. POST /api/v1/alerts/research-updates - token (str, required): API Bearer token Generates profile-based research update recommendations using engagement-aware LLM query planning and post-search refinement. `save_research_update` — Save recommendation to library. POST /api/v1/alerts/research-updates/save - token (str, required): API Bearer token - hit_payload (dict, required): full search hit payload (must include openalex_id and/or title) - collection_id (int, optional): collection to save into ### Account (4 tools) `get_me` — Get current user info. GET /api/v1/sync/me - token (str, required): API Bearer token `list_api_tokens` — List API tokens. GET /api/v1/sync/tokens - token (str, required): API Bearer token `create_api_token` — Create new API token. POST /api/v1/sync/tokens - token (str, required): API Bearer token - label (str, default "API Token"): label for the token Returns the raw token value (shown only once — save it). `revoke_api_token` — Revoke an API token. DELETE /api/v1/sync/tokens/{token_id} - token (str, required): API Bearer token - token_id (int, required): token ID to revoke ### System (3 tools) `health` — Liveness probe. GET /healthz (no auth required) `ready` — Readiness probe. GET /readyz (no auth required) `feedback` — Submit user feedback. POST /api/feedback - token (str, required): API Bearer token - message (str, required): feedback text - page (str, default ""): page context - category (str, default ""): feedback category ## REST API (alternative) All MCP tools map 1:1 to JSON REST endpoints. Authenticate with `Authorization: Bearer ` header. The `/api/v1/search/*` endpoints are open (no auth required; a Bearer token is optional and only records search history). Key prefixes: - POST /api/v1/search/query — search (body: query, limit, retrieval_mode, sort_by, hybrid_alpha, filters) - GET /api/v1/search/works/{openalex_id} — work lookup (?include_fulltext=true) - POST /api/v1/analysis/upload — multipart file upload - GET /api/v1/analysis/jobs — list jobs (?status=&limit=&offset=) - GET /api/v1/analysis/jobs/{id} — job status + report - GET /api/v1/analysis/jobs/{id}/events — job progress events (?since_id=) - POST /api/v1/analysis/jobs/{id}/cancel — cancel - DELETE /api/v1/analysis/jobs/{id} — delete - GET /api/v1/analysis/jobs/{id}/report.pdf — PDF download - POST /api/v1/analysis/jobs/{id}/share-email — email share - POST /api/v1/analysis/jobs/{id}/share — enable/disable a public report access token - GET /api/v1/profile/ — profile - PATCH /api/v1/profile/interests — update interest tags - POST /api/v1/profile/refresh — trigger refresh - GET /api/v1/profile/sources — list sources - POST /api/v1/profile/sources/sync — connect sources - GET /api/v1/alerts/ — list alerts - POST /api/v1/alerts/ — create/update alert - POST /api/v1/alerts/preview — preview alert - PATCH /api/v1/alerts/{id}/toggle — toggle alert - DELETE /api/v1/alerts/{id} — delete alert - POST /api/v1/alerts/{id}/digest — send digest - POST /api/v1/alerts/research-updates — generate recommendations - POST /api/v1/alerts/research-updates/save — save recommendation - GET /api/v1/sync/me — current user - GET /api/v1/sync/collections — list collections - POST /api/v1/sync/collections — create collection - DELETE /api/v1/sync/collections/{id} — delete collection - GET /api/v1/sync/items — list items (?limit=&offset=&since=) - POST /api/v1/sync/items — create item - PUT /api/v1/sync/items/{id} — update item - DELETE /api/v1/sync/items/{id} — delete item - GET /api/v1/sync/items/{id}/files — list item files - POST /api/v1/sync/items/{id}/files — upload file (multipart) - GET /api/v1/sync/files/{id}/download — download file - DELETE /api/v1/sync/files/{id} — delete file - GET /api/v1/sync/tokens — list API tokens - POST /api/v1/sync/tokens — create API token (?label=) - DELETE /api/v1/sync/tokens/{id} — revoke API token - GET /api/v1/search-history/ — list search history - DELETE /api/v1/search-history/{id} — delete history entry ## Common workflows ### 1. Literature search and save 1. `search` with your query and filters 2. Review results (title, abstract, citation count, WoS metrics) 3. `work_lookup` with include_fulltext=true for promising results 4. `save_search_hit` to add to a library collection ### 2. Citation analysis 1. `upload_document` with base64 file content 2. Poll `get_job` (or follow `get_job_events`) until status is COMPLETED, FAILED, or CANCELED (typically 1-5 minutes); on FAILED read error_message 3. Read report.issues[] for retractions, predatory venues, missing refs 4. `get_report_pdf` for a formatted report 5. `share_report` to email results to collaborators ### 3. Research profile setup 1. `sync_sources` with Google Scholar / ORCID / homepage URLs 2. `refresh_profile` to import and summarize 3. `update_interests` to pin important tags 4. `run_research_updates` to get personalized recommendations ### 4. Research alerts 1. `save_alert` with search config and schedule 2. `preview_alert` to check results before committing 3. Digests auto-generate on schedule, or `send_digest` on demand 4. `save_research_update` to save interesting finds to library ## Error responses On error, tools return {"error": "description", "status_code": 4xx/5xx}. Common codes: 400 (bad input, e.g. unsupported file type), 401 (invalid/missing token), 402 (insufficient balance), 403 (forbidden), 404 (not found), 409 (not ready — e.g. report/share requested before the job is COMPLETED), 422 (validation error — e.g. unknown filter key, invalid sort_by, or out-of-range limit), 429 (rate limited), 502 (upstream or email failure), 503 (maintenance / service unavailable).