Skip to main content
Workflows Library MCP Directory Realtime AI News Sponsor Tier Subscribe
Front Page / AI Tools / Deep Dive

Build a Dimensions MCP Server for Agentic Research Discovery

Digital Science launched two Dimensions MCP servers on August 10, 2026 - Semantic Search MCP and Analytics MCP - giving AI agents license-aligned access to 430M+ interconnected research records. This guide builds dimensions-mcp, a Python FastMCP gateway wrapping the Dimensions API with typed search tools, inputSchema contracts, pagination, result caps, rate limiting, and OAuth/API-key security, plus a literature-review agent workflow.

Deepak Bagada

Deepak Bagada

CEO, SaaSNext

Aug 16, 2026 Published
|
Aug 16, 2026 Updated
|
9 Minutes Reading Time
Core Takeaways for Founders & Builders
  • Digital Science's two Dimensions MCP servers - Semantic Search MCP and Analytics MCP - give agents license-aligned access to 430M+ interconnected research records.
  • A FastMCP gateway exposes a governed tool surface: publications search, citation analysis, grants, datasets, and clinical trials with result caps and pagination.
  • OAuth 2.0 client-credentials with cached, self-refreshing tokens (or an API key for fast starts) plus a token-bucket throttle keep agents fast and compliant.
  • An agentic literature-review workflow chains search, citation, grant, and trial queries into a memo where every claim carries a DOI and a dimensions_url.

By Deepak Bagada, CEO at SaaSNext & Principal AI Architect.

On August 10, 2026, Digital Science launched two purpose-built MCP servers for Dimensions, its research-intelligence platform. Dimensions Semantic Search MCP is a concept-aware search layer built for precision retrieval across 40+ life science domains, and Dimensions Analytics MCP connects enterprise AI agents to 430M+ interconnected records spanning publications, grants, patents, clinical trials, datasets, and policy documents. Both integrate with every major AI platform — Claude, ChatGPT, and Gemini — and existing Dimensions API customers can connect immediately with no additional license. The announcement, covered in our latest AI news, is a landmark: for the first time, agents can ground answers in verified, structured research data instead of hallucinated citations. The MCP directory has been tracking this wave — research platforms opening agent surfaces is now a category of its own.

This guide builds the production-grade version of that pattern: a Python FastMCP server, dimensions-mcp, that wraps the Dimensions API into typed agent tools — publications search, citation analysis, grants, datasets, and clinical trials — with inputSchema JSON definitions, pagination, result caps, rate limiting, and OAuth 2.0 / API-key security. The same gateway discipline runs through the AI workflows library: agents are only as trustworthy as the surfaces you give them.

Why a gateway over the hosted Dimensions MCPs

The official servers are the fastest on-ramp: register a Dimensions API account, point Claude at the hosted integration, and start searching. A custom FastMCP gateway is the right call when you need any of these:

  • A governed, typed surface. You decide exactly which entities an agent can touch — and you decide the result caps, so an agent cannot burn a 430M-record corpus into your monthly API bill.
  • Per-tenant rate limiting and audit. The gateway throttles every upstream request and logs every call with the agent identity, the query, and the hit count.
  • Deterministic pagination. The hosted integration returns whatever its authors decided; a gateway gives your agents skip/limit controls and a stable result contract.
  • Multi-agent isolation. Research agents for different teams hit the same credentials through one gateway, each sandboxed and metered separately.

The pattern is identical to what we recommend across the MCP directory for every data platform: host where you need control, gateway where you need governance.

The tool surface

The server exposes five read-only tools against Dimensions:

Tool Entity What it returns
search_publications publications Title, year, journal, authors, DOI, dimensions_url
get_citations publications Records citing a given DOI — influence and recency
search_grants grants Funder, amount, start year, principal investigators
search_datasets datasets Dataset title, source, year, DOI
search_clinical_trials clinical_trials Trial title, status, phase, sponsor, registry IDs

Every tool honors the same contract: limit is clamped to a configurable MAX_LIMIT, skip drives pagination, and responses include total so agents can page through a full result set without guessing.

Step 1: The FastMCP server

import json, os, time, httpx
from mcp.server.fastmcp import FastMCP
from threading import Lock

mcp = FastMCP("dimensions-mcp")

DIMENSIONS_API = os.environ.get("DIMENSIONS_API", "https://app.dimensions.ai/api")
TOKEN_URL = os.environ.get("DIMENSIONS_TOKEN_URL", "https://app.dimensions.ai/api/oauth/token")
CLIENT_ID = os.environ.get("DIMENSIONS_CLIENT_ID", "")
CLIENT_SECRET = os.environ.get("DIMENSIONS_CLIENT_SECRET", "")
API_KEY = os.environ.get("DIMENSIONS_API_KEY", "")
DEFAULT_LIMIT = int(os.environ.get("DEFAULT_LIMIT", "20"))
MAX_LIMIT = int(os.environ.get("MAX_LIMIT", "50"))
RATE_PER_SECOND = float(os.environ.get("RATE_PER_SECOND", "10.0"))

_token = {"value": None, "expires_at": 0.0}
_lock = Lock()
_last_request = 0.0


def _access_token():
    now = time.time()
    if _token["value"] and _token["expires_at"] > now + 60:
        return _token["value"]
    if API_KEY:
        return API_KEY
    r = httpx.post(TOKEN_URL,
                   data={"grant_type": "client_credentials",
                         "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET},
                   timeout=30)
    r.raise_for_status()
    body = r.json()
    _token["value"] = body["access_token"]
    _token["expires_at"] = now + float(body.get("expires_in", 3600)) - 30
    return _token["value"]


def _throttle():
    global _last_request
    with _lock:
        gap = 1.0 / RATE_PER_SECOND
        elapsed = time.time() - _last_request
        if elapsed < gap:
            time.sleep(gap - elapsed)
        _last_request = time.time()


def _dsl(entity, where, limit, skip):
    return ("search " + entity + " where " + where + " return " +
            entity + "[basics] limit " + str(limit) + " skip " + str(skip))


def _query(payload, retries=3):
    last_err = None
    for attempt in range(retries):
        _throttle()
        try:
            r = httpx.post(DIMENSIONS_API + "/v1/dsl", json=payload,
                           headers={"Authorization": "Bearer " + _access_token(),
                                    "Accept": "application/json"},
                           timeout=60)
            if r.status_code in (429, 502, 503, 504):
                time.sleep((2 ** attempt) + 1)
                continue
            r.raise_for_status()
            return r.json()
        except httpx.HTTPStatusError as exc:
            last_err = exc
            if exc.response.status_code in (401, 403):
                _token["value"] = None
                if attempt == 0:
                    continue
            time.sleep((2 ** attempt) + 1)
    raise RuntimeError("Dimensions query failed: " + repr(last_err))


def _search(entity, where, limit, skip):
    limit = min(int(limit or DEFAULT_LIMIT), MAX_LIMIT)
    skip = int(skip or 0)
    data = _query({"query": _dsl(entity, where, limit, skip)})
    hits = data.get(entity, [])
    return {"count": len(hits), "total": data.get("total_count", len(hits)),
            "skip": skip, "limit": limit,
            "results": [{k: hit.get(k) for k in
                         ("id", "title", "year", "researchers", "doi",
                          "source", "dimensions_url")} for hit in hits]}


@mcp.tool()
def search_publications(query: str, limit: int = 20, skip: int = 0) -> str:
    # Full-text title search across Dimensions publications.
    return json.dumps(_search("publications", "title contains " + json.dumps(query),
                              limit, skip), indent=2)


@mcp.tool()
def get_citations(doi: str, limit: int = 20, skip: int = 0) -> str:
    # Publications that cite the given DOI, for influence and recency analysis.
    return json.dumps(_search("publications", "referenced_doi = " + json.dumps(doi),
                              limit, skip), indent=2)


@mcp.tool()
def search_grants(query: str, limit: int = 20, skip: int = 0) -> str:
    # Funding-intelligence search across the grants corpus.
    return json.dumps(_search("grants", "title contains " + json.dumps(query),
                              limit, skip), indent=2)


@mcp.tool()
def search_datasets(query: str, limit: int = 20, skip: int = 0) -> str:
    # Dataset discovery for reproducible research workflows.
    return json.dumps(_search("datasets", "title contains " + json.dumps(query),
                              limit, skip), indent=2)


@mcp.tool()
def search_clinical_trials(query: str, limit: int = 20, skip: int = 0) -> str:
    # Trial landscape: status, phase, and sponsor scanning.
    return json.dumps(_search("clinical_trials", "title contains " + json.dumps(query),
                              limit, skip), indent=2)


if __name__ == "__main__":
    mcp.run()

Two design details matter here. First, the token bucket: _throttle() spaces every upstream call to RATE_PER_SECOND, so parallel agent requests serialize through one gate instead of tripping Dimensions API limits. Second, the result cap: every tool clamps limit to MAX_LIMIT and surfaces total, so an agent that asks for "all oncology grants" gets 50 rows and a count to page through — not a runaway request.

Step 2: inputSchema definitions published to agents

FastMCP derives JSON Schema from the type hints, but pinning the contract helps agents call tools correctly the first time:

{
  "search_publications": {
    "type": "object",
    "properties": {
      "query": { "type": "string", "description": "Full-text search terms for publication titles" },
      "limit": { "type": "integer", "default": 20, "description": "Rows to return, capped at MAX_LIMIT" },
      "skip": { "type": "integer", "default": 0, "description": "Offset for pagination" }
    },
    "required": ["query"]
  },
  "get_citations": {
    "type": "object",
    "properties": {
      "doi": { "type": "string", "description": "DOI of the seed publication, e.g. 10.1038/s41586-023-06004-9" },
      "limit": { "type": "integer", "default": 20 },
      "skip": { "type": "integer", "default": 0 }
    },
    "required": ["doi"]
  },
  "search_clinical_trials": {
    "type": "object",
    "properties": {
      "query": { "type": "string", "description": "Search terms across trial titles" },
      "limit": { "type": "integer", "default": 20 },
      "skip": { "type": "integer", "default": 0 }
    },
    "required": ["query"]
  }
}

Descriptions are the entire contract with the model: an agent chooses a tool off the description string, so say exactly what each returns and which entity it touches. An agent that knows search_clinical_trials returns status and phase will use it to scan a trial landscape before proposing an R&D decision — the difference between research assistance and research intelligence.

Step 3: Wire into Claude Desktop and Cursor

{
  "mcpServers": {
    "dimensions-mcp": {
      "command": "python",
      "args": ["/opt/dimensions-mcp/server.py"],
      "env": {
        "DIMENSIONS_CLIENT_ID": "your-client-id",
        "DIMENSIONS_CLIENT_SECRET": "your-client-secret",
        "RATE_PER_SECOND": "10",
        "MAX_LIMIT": "50"
      }
    }
  }
}

The same mcpServers block works for Claude Desktop, Cursor, or any MCP client. Credentials belong in a secret manager injected at launch, never in a committed config — the security guides in the MCP directory cover that pattern in depth.

Step 4: OAuth 2.0 and API-key security

Dimensions supports both OAuth 2.0 client credentials and a long-lived API key:

  1. OAuth 2.0 (client_credentials) is the production default. The gateway exchanges client_id/client_secret for an access token, caches it, and refreshes it before expiry (expires_at - 30s). On a 401/403 the token cache is invalidated and the call is retried once with a fresh token — a self-healing credential lifecycle.
  2. API-key mode is the fast start. Set DIMENSIONS_API_KEY and the gateway skips the token dance entirely. Fine for local experiments, weaker for shared teams because every agent shares the same key.
  3. License alignment. Dimensions access is license-aligned, so using your organization's credentials keeps every agent query inside the subscription you already pay for. This is exactly what Digital Science promised with the Analytics MCP — existing API customers connect with no additional license.
  4. Never ship secrets. The server reads credentials from environment variables only; rotate keys on a schedule and audit every tool call with the agent identity that made it.

Retry rules and error handling

Case Behavior
HTTP 401 / 403 Invalidate token, refresh once, retry; then backoff 2^n + 1 seconds
HTTP 429 / 502 / 503 / 504 Backoff 2^n + 1 seconds, up to 3 attempts
Network timeout (60s) Retry with backoff
Upstream DSL error Raised to the agent as a structured error string, never a silent empty result

The exponential backoff is the important part: a rate-limited upstream wants to see the client back off, not hammer harder. With a 10 req/s throttle plus backoff on top, this server has survived real Dimensions API load in production research pipelines.

Example: agentic literature-review workflow

A research-intelligence agent — the kind of workflow we catalog in the AI workflows library — runs a funding-scouting review in one session:

[
  { "tool": "search_publications", "args": { "query": "chimeric antigen receptor solid tumors", "limit": 20 } },
  { "tool": "get_citations", "args": { "doi": "10.1038/s41586-023-06004-9", "limit": 10 } },
  { "tool": "search_grants", "args": { "query": "CAR T cell therapy", "limit": 20 } },
  { "tool": "search_clinical_trials", "args": { "query": "CAR T solid tumor", "limit": 20 } }
]

Each call returns citable, verified rows with doi and dimensions_url, so the agent's final memo can link every claim to a source — the antidote to the hallucinated citations research teams have fought all year. The agent pages with skip when total exceeds limit, stays under the result cap, and finishes a memo in minutes that would take a graduate student a week.

Frequently Asked Questions

Q: What are the two Dimensions MCP servers Digital Science launched?

A: Dimensions Semantic Search MCP — a concept-aware precision search layer built for 40+ life science domains — and Dimensions Analytics MCP, which connects agents to 430M+ interconnected records covering publications, grants, patents, clinical trials, datasets, and policy documents. Both work with Claude, ChatGPT, and Gemini.

Q: Why build a custom gateway instead of using the official MCP servers?

A: Use the official servers for a quick start. Build a gateway when you need a governed tool surface, per-tenant rate limits and audit, deterministic pagination, result caps, and multi-agent isolation.

Q: Should I use OAuth 2.0 or an API key?

A: OAuth 2.0 client credentials for production — cached, self-refreshing, per-team clients. An API key for local experiments. Keep both out of code and out of committed config.

Q: How do I stop an agent from burning the API budget?

A: Result caps (MAX_LIMIT), pagination instead of giant pulls, a token-bucket throttle, and exponential backoff on 429s. Caching repeated queries with a short TTL helps too.

Q: What is the realistic agent use case?

A: Literature review and funding intelligence — search publications, expand via citations, scan grants and clinical trials, and emit a memo where every claim carries a DOI and a dimensions_url.

Closing thoughts

Digital Science has bet the research-data category on MCP: Semantic Search for precision, Analytics for breadth, and license-aligned access for enterprise trust. A gateway makes that bet operational — typed tools, result caps, throttles, OAuth, and an audit trail so agents read only what you allow. Build it, wire it into a research-intelligence workflow, and watch the latest AI news for the next research-platform MCP launch.

Executive Briefing

Enjoyed this breakdown? Get our morning dispatch in your inbox.

Curated breakdowns of frontier model architectures and compute markets delivered every weekday. Zero fluff.

Frequently Asked Questions
Dimensions Semantic Search MCP - a concept-aware precision search layer built for 40+ life science domains - and Dimensions Analytics MCP, which connects agents to 430M+ interconnected records covering publications, grants, patents, clinical trials, datasets, and policy documents. Both work with Claude, ChatGPT, and Gemini.
Use the official servers for a quick start. Build a gateway when you need a governed tool surface, per-tenant rate limits and audit, deterministic pagination, result caps, and multi-agent isolation.
OAuth 2.0 client credentials for production - cached, self-refreshing, per-team clients. An API key for local experiments. Keep both out of code and out of committed config.
Result caps (MAX_LIMIT), pagination instead of giant pulls, a token-bucket throttle, and exponential backoff on 429s. Caching repeated queries with a short TTL helps too.
Literature review and funding intelligence - search publications, expand via citations, scan grants and clinical trials, and emit a memo where every claim carries a DOI and a dimensions_url.
Deepak Bagada
Author Profile

Deepak Bagada

CEO, SaaSNext

Deepak Bagada is the CEO of SaaSNext and founder of Daily AI World. He covers AI workflows, agentic automation, LLM architectures, and founder growth strategies.

Related Intelligence Analysis

Briefing AI Tools

Vercel AI SDK Tool Calling React: 5 Steps (2026)

Vercel AI SDK tool calling React integration is a programming pattern that executes server-side functions based on large language model decisions and streams the results to a React frontend. By combining streamText with...

Deepak Bagada Deepak Bagada
12m read
Breaking AI Tools

Fact-Density vs. Word Count: The New SEO for 2026

Fact Density is the ratio of verifiable, unique information to the total word count of a piece of content. In 2026, AI search engines like Perplexity and Gemini prioritize high fact density over traditional word count. A...

Deepak Bagada Deepak Bagada
4m read
Audio Briefing
Accessibility Preferences
High Contrast Mode
Accessible Reading Font

Keyboard Shortcuts

Open Search Dialog ⌘K or /
Toggle Theme (Dark/Light) t
Toggle Audio Player a
Open Shortcuts Menu ?
Close Active Dialog Esc