Yes. Below is a concise design doc that Cursor can follow to build an MCP server that exposes Synergy/DE documentation as tools and resources.
## Overview
Build a read‑only MCP server that lets Cursor (and other MCP clients) search, retrieve, and browse Synergy/DE documentation topics from the public docs site and optionally from locally installed/offline docs.[1][2]
The server will provide:
- Tools for free‑text search, topic lookup by ID/URL, and “related topics” navigation.[3][1]
- Resources that make common doc sections (e.g., Language, General Guides, Data Access, Development Tools) discoverable and fetchable as structured content.[4][1]
## Goals and Non‑Goals
Goals:
- Make Synergy/DE docs easily accessible from Cursor via MCP tools and resources.[5][6]
- Support versioned docs (e.g., latest, 12.x, 11.x), with a reasonable default (e.g., “latest”).[7][1][4]
- Provide high‑signal, chunked content suitable for LLM consumption (titles, summary, body, links).[2][1]
- Work with stdio transport, and be deployable as a standalone service later if desired.[8][5]
Non‑Goals:
- No write operations or editing of documentation.
- No authentication or access to non‑public Synergex resources (e.g., behind login) beyond what the user mounts locally.[9][2]
## Data Sources and Structure
Primary sources:
- Online Synergy/DE docs site (HTML): https://www.synergex.com/docs/ with versioned paths like /versions/v111/, /versions/v1033/, etc.[1][4][3]
- Optional: locally installed documentation (CHM, HTML, or packaged help) that the user has downloaded from the Synergex Resource Center.[2]
Assumed structure (a discovery spike must confirm/refresh these assumptions before building parsers):
- Top‑level sections: “Language”, “General Guides”, “Data Access and Connectivity”, “Development Tools”, “Updating”, etc.[3][1]
- Each topic has:
- URL (and possibly some stable topic ID derived from it).
- Title and breadcrumb path (e.g., Language > Reference > Statements).
- Main HTML content.
- Local navigation links (previous, next, parent) and related links.[2]
Internal representation:
- Topic:
- id: string (e.g., normalized URL).
- version: string (e.g., “latest”, “12.3”, “11.1.1”).[4][7]
- title: string.
- section: string (Language / General Guides / etc.).[1]
- path: string[] (breadcrumb).
- summary: string (first N characters or a meta summary).
- body_chunks: TopicChunk[] where each chunk is ~1–2k chars.
- links: { type: "prev" | "next" | "parent" | "related"; target_topic_id: string }[].
- TopicChunk:
- topic_id: string.
- chunk_index: number.
- text: string (plain text, lightly cleaned from HTML).
- Indexes:
- Full‑text search index over (title, summary, body_text).
- Map from URL → topic_id.
- Map from section/version → topic_ids.
For offline docs:
- Pluggable “DocProvider” interface with implementations:
- OnlineProvider (HTTP + caching).
- LocalProvider (file system path or CHM/HTML export).[2]
- Provider precedence: when both sources exist, try Local → Online and record which source served the topic so caches/indexes stay coherent. Provide a future hook for merging results but keep initial behavior deterministic.
Before work on parsing or search begins, schedule a short doc-discovery task that hits at least one page per major section/version, captures DOM snapshots, and verifies breadcrumb/link selectors. Update these requirements if the structure diverges.
## MCP Surface: Tools
Design tools around common workflows in Cursor: “find topic”, “open topic”, “explore neighbors”.
1) search_docs
- Purpose: Full‑text search across docs for a query.
- Input:
- query: string.
- version?: string (default “latest”).[7][1]
- section?: string (optional filter).
- limit?: number (default 10).
- Output:
- results: {
topic_id: string;
title: string;
section: string;
version: string;
url: string;
summary: string;
}[]
2) get_topic
- Purpose: Retrieve a single topic in a form safe for the model.
- Input:
- topic_id?: string.
- url?: string (if given, normalize to topic_id).
- version?: string (optional; may be encoded in topic_id).
- max_chunks?: number (default 3).
- Output:
- topic_id, title, section, version, url, path, summary.
- chunks: TopicChunk[] (capped by max_chunks).
- links: as described above.
3) get_related_topics
- Purpose: Explore neighbors (breadcrumbs and related links).
- Input:
- topic_id: string.
- Output:
- parent?: { topic_id, title, url }.
- previous?: { topic_id, title, url }.
- next?: { topic_id, title, url }.
- related: { topic_id, title, url }[].
4) list_section_topics
- Purpose: Enumerate topics in a section (useful for browsing and quick discovery).
- Input:
- section: string (e.g., “Language”).[1]
- version?: string (default “latest”).
- limit?: number (default 50).
- Output:
- topics: { topic_id, title, url, summary }[].
5) describe_docs
- Purpose: Provide metadata about available versions and sections so Cursor can reason about the dataset.
- Input: empty.
- Output:
- versions: string[] (e.g., ["latest", "12.3", "11.1.1", "10.3.3"]).[4][7]
- sections: string[] (from the top‑level nav).[3][1]
- source: "online" | "local" | "hybrid".
All tools are read‑only.
### Error payload contract (applies to all tools/resources)
- Every failure returns `{ code: string; message: string; details?: Record<string, unknown>; retryable?: boolean }` and uses well-known codes such as `INVALID_INPUT`, `NOT_FOUND`, `NETWORK_ERROR`, `INTERNAL_ERROR`.
- Tool handlers never throw uncaught exceptions; they log internally and convert errors to this format.
- Include the resolved version/section in `details` when helpful so callers can debug mismatches.
## MCP Surface: Resources
Expose documentation as MCP resources so Cursor can treat specific topics or sections as “files” and mount them in context.[6][5]
Resource types:
1) Topic resource
- URI scheme: synergyde:topic/{topic_id}
- Read:
- Returns a single plain‑text chunk or the concatenated text of the first N chunks.
- Metadata:
- title, section, version, url, path.
2) Section resource
- URI scheme: synergyde:section/{version}/{section}
- Read:
- Returns an index of key topics in that section (titles + URLs + 1‑line summaries).
Optional:
- Expose resources for “errors” or “reference lists” if those exist as specific pages in the docs (e.g., error code tables).[2]
## Transport, Config, and Deployment
Transport:
- Start with stdio MCP server (Node or TypeScript using @modelcontextprotocol/sdk).[8][5]
Configuration:
- Environment variables:
- SYNERGYDE_DOC_BASE_URL (default https://www.synergex.com/docs/).[1]
- SYNERGYDE_DOC_DEFAULT_VERSION (default “latest”).[7]
- SYNERGYDE_LOCAL_DOC_PATH (optional; path to local documentation tree).[2]
- SYNERGYDE_CACHE_DIR (for on‑disk caching of fetched and parsed topics).
Cursor configuration:
- Project or global MCP config:
- name: synergyde-docs
- command: node ./dist/server.js
- transport: stdio.[10][5]
Deployment:
- Optionally later, move to HTTP/SSE transport to share the server across a team; the internal logic should be transport‑agnostic.[11][5][8]
## Parsing, Indexing, and Caching
HTML parsing:
- Use a robust HTML parser to:
- Extract title, main content region, breadcrumb nav, and navigation links.[1][2]
- Strip boilerplate (header, footer, navigation menus) and preserve headings and lists in a minimal text form.
- Honor the public site’s `robots.txt` and rate-limiting guidance; never crawl private or disallowed paths.
Chunking:
- Split body into chunks by headings while keeping chunks under a configured token/character budget (~1–2k chars or ≤1.2k tokens).
- Cap responses returned to Cursor (tools + resources) at ~8k tokens total and prefer returning the smallest chunk set that answers the request. Document these limits so downstream callers can plan context usage.
Index:
- Build or lazily maintain:
- An in‑memory search index (e.g., simple TF‑IDF / BM25 over text; or call out to an existing search API if the site exposes one).[3][1]
- Persist:
- Cache of parsed topics on disk keyed by version + topic_id.
- Simple index metadata (topic lists per section/version).
Performance and rate limiting:
- Use HTTP caching (ETag/Last‑Modified) where available to avoid re‑fetching unchanged topics.[1]
- Implement a basic per‑host rate limit for online fetching to avoid hammering docs.synergex.com.
- Respect back-off headers and surface a clear `NETWORK_ERROR` when throttled.
## Error Handling and Safeguards
- If a topic cannot be fetched/parsing fails, return a structured error to the MCP client with a brief message and suggest trying a simpler query or a different version.
- If the user requests a non‑existent version or section, surface allowed values from describe_docs.
- If the network is unavailable and no local docs are configured, the server should return a clear error message indicating that online docs are unreachable.
- Follow test-driven development where feasible: write or update failing unit tests before implementing provider/search/parsing features, and maintain ≥80% statement coverage across the codebase (measured via Vitest/Jest coverage reports). Document coverage targets in CI.
## Usage Patterns in Cursor
Examples of how Cursor can leverage this server:[10][5][6]
- When the user asks “How do I use X in Synergy DBL?”, Cursor:
- Calls search_docs(query="X", section="Language").
- Calls get_topic on the top result and injects chunks as context.
- When refactoring a legacy Synergy/DE codebase, Cursor:
- Uses list_section_topics("General Guides") to find modernization guides.[7][1]
- Uses related topics to navigate between reference and examples.
- When troubleshooting failed calls, Cursor inspects error payloads (code/message/details) and can re-run using different versions/sections without guessing at the failure mode.
This design should be concrete enough for Cursor to scaffold a Node/TypeScript MCP server that wraps Synergy/DE documentation in a clean, read‑only API optimized for LLM usage.
[1](https://www.synergex.com/docs/)
[2](https://www.youtube.com/watch?v=8_Q9g2CpOM8)
[3](https://www.synergex.com/docs/versions/v1033/)
[4](https://www.synergex.com/docs/versions/v111/)
[5](https://cursor.com/docs/context/mcp)
[6](https://cursor.com/docs/cookbook/web-development)
[7](https://resources.synergex.com/SiteCurrentVersion)
[8](https://docs.cursor.com/en/guides/tutorials/building-mcp-server)
[9](https://resources.synergex.com/SiteAbout)
[10](https://cursor101.com/article/cursor-what-is-mcp)
[11](https://skywork.ai/skypage/en/The-Ultimate-Guide-to-Cursor-MCP-Servers-for-AI-Engineers/1971383920724340736)
[12](https://github.com/Synergex/SynPSG_PDF)
[13](https://documentation.help/Synergy-OpenNET/IDH_Topic20.htm)
[14](https://www.synergex.com/products-connectivity-open-source/)
[15](https://www.youtube.com/watch?v=QfbwgDScoRM)
[16](https://www.youtube.com/watch?v=Ix2_QW2Jb6Y)
[17](https://www.reddit.com/r/PHP/comments/ivpfcf/php_community_synergy_initiative/)
[18](https://www.youtube.com/watch?v=atSqS0an3yU)
[19](https://resources.synergex.com/SiteAnswer?id=a2Z6Q000001EnvtUAC)
[20](https://composio.dev/blog/mcp-server-step-by-step-guide-to-building-from-scrtch)