workday-docs-mcp
README.md
# workday-docs-mcp
> An MCP server that grounds an AI coding agent in the **Workday developer documentation** — so it answers from the real docs and helps build Workday Extend apps correctly, instead of guessing.
Point your IDE agent (Claude Code, Cursor, etc.) at this server and it can search, read, and cite the official Workday docs on demand. With the included [Extend builder skill](skills/), a developer with **no Workday Extend experience** can build apps that are grounded in the actual PMD components, functions, and APIs — not plausible-looking hallucinations.
It's a thin, cached layer over the documentation behind developer.workday.com. **No login, no API keys, no Workday account required** — it reads the public docs.
---
## Why it exists
A general-purpose LLM has almost no Workday Extend in its training data, so it confidently writes **invalid** PMD (Workday's declarative page metadata) and invents endpoints that don't exist. This server replaces those guesses with retrieved, authoritative reference — and gives the agent the canonical doc link so a human can verify.
## What it looks like in use
> **You:** *"I'm building a Workday Extend app and want a page that shows a list of expense reports in a table. How do I do that?"*
>
> **Agent:** *(calls `lookup_extend_reference` → grounds on the real `grid` widget docs)*
> "You'll use the **`grid`** widget bound to an inbound endpoint. Here's the PMD, with the real attributes (`rows`, `columns`, `cellTemplate`)… *[cites developer.workday.com/wcp_docs/…]*"
The agent reaches for the tools on its own (especially with the skill installed), grounds the answer, and links the source.
## Tools
| Tool | Purpose |
|------|---------|
| `search_workday_docs` | Find docs by concept / widget / API / task → lightweight pointers (title, breadcrumb, `doc_id`, link). |
| `get_workday_doc` | Fetch a full page as markdown by `doc_id` or a pasted `wcp_docs/<id>.html` link. Always returns the canonical link. |
| `browse_workday_toc` | Walk the documentation hierarchy when keyword search misses. |
| `lookup_extend_reference` | **Build-focused.** Given an intent ("sortable grid", "format a date"), returns the best Extend **component / PMD-function / scripting** reference page **with its content inline** + alternatives. Scope with `kind`. |
All four tools declare an `outputSchema` (clients receive validated `structuredContent`, not just text) and annotations (`readOnlyHint`, `idempotentHint`, `openWorldHint` — none are destructive).
Typical flow: `search` → pick a `doc_id` → `get` → answer & cite the `html_url`. When *building* an Extend app, reach for `lookup_extend_reference` first.
## Requirements
- **Node 22+** — runs the TypeScript sources directly, no build step (verified on Node 25).
- An MCP-capable client (Claude Code, Cursor, Claude Desktop, …).
## Quick start
```bash
git clone https://github.com/philippesimard00/workday-docs-mcp.git
cd workday-docs-mcp
npm install
npm run build-index # one-time, ~1 min: builds the Tier-2 full-text index (recommended)
```
Connect it to **Claude Code** (user scope = available in every project):
```bash
claude mcp add workday-docs --scope user -- node "$(pwd)/src/server.ts"
claude mcp list # expect: workday-docs ✓ Connected
```
Or add it to any MCP client's config manually (use the **absolute path** to `src/server.ts` on your machine):
```jsonc
{
"mcpServers": {
"workday-docs": {
"command": "node",
"args": ["/absolute/path/to/workday-docs-mcp/src/server.ts"]
}
}
}
```
> Skipping `build-index` still works — search just falls back to title-only matching. See [Search modes](#search-modes).
## The Extend builder skill
`skills/workday-extend-builder/` is a [Claude Code Skill](https://docs.claude.com/en/docs/claude-code) that teaches the agent Workday Extend's mental model (declarative metadata + scripting, the real file types) and directs it to these tools — especially `lookup_extend_reference` — *before* it writes any code. This is what makes the "no prior experience" case work. Install it (per developer):
```bash
ln -s "$(pwd)/skills/workday-extend-builder" ~/.claude/skills/workday-extend-builder
```
See [skills/README.md](skills/README.md) for details and the per-team customization section.
## Search modes
`search_workday_docs` and `lookup_extend_reference` run in one of two modes; the response's `engine` field tells you which:
- **`title`** (zero setup): matches page titles + breadcrumbs only. Fine for "find the page about X"; weak on how-to phrasing.
- **`fulltext`** (after `npm run build-index`): BM25 over page **bodies**. Built for app-building — intent queries like *"sortable grid with pagination"* land on the right component. The index (~1,250 docs) is fetched once and cached at `~/.cache/workday-docs-mcp/`; the server uses it automatically on next start. Re-run `build-index` to refresh.
## How it works
The Workday developer site is a JavaScript single-page app, so the docs aren't readable by a normal fetch of a page URL. The content is served as markdown behind it, via two endpoints:
| What | URL |
|---|---|
| Master table of contents | `https://developer.workday.com/doc/wcp_docs.yml` |
| Page markdown | `https://developer.workday.com/doc/<DOC_ID>.md` |
| Canonical human link | `https://developer.workday.com/wcp_docs/<DOC_ID>.html` |
The server loads the TOC (cached 6h), serves page markdown (cached on disk), and — for full-text mode — builds a local BM25 index over every page body. All knowledge of these URLs is isolated in one file (`src/workday-docs-adapter.ts`), and a startup health check fails loudly if Workday changes the doc structure.
## Project layout
```
src/
types.ts Shared types (TocNode, IndexEntry, SearchHit)
workday-docs-adapter.ts The seam — the only file that knows Workday's URLs (TOC, page fetch, caching, health check)
search.ts Tier-1 ranking (title/breadcrumb) — fallback
fulltext.ts Tier-2 BM25 inverted index over page bodies (pure JS, no native deps)
build-index.ts One-time builder for the Tier-2 index
server.ts MCP wiring: 4 tools + stdio transport + boot health check
smoke.ts Live end-to-end check, no MCP transport
test-client.ts Drives the tools over the real MCP protocol (stdio)
evals/ 12-question evaluation suite (verified) + how to run it
skills/ workday-extend-builder Claude Code skill + install guide
```
## Development
```bash
npm run typecheck # tsc, no emit
npm run smoke # hits the live endpoints: loads TOC, searches, fetches a page
npm run test-client # drives all tools over the real MCP protocol (stdio)
```
`evals/workday_docs_eval.xml` is a 12-question suite (answers verified against live data) for measuring how well an LLM can answer real Workday questions with only these tools — useful as a regression/quality benchmark. See [evals/README.md](evals/README.md).
## Notes & limitations
- **Unofficial.** This project is **not affiliated with or endorsed by Workday.** It reads publicly available documentation pages.
- **Undocumented endpoints.** `wcp_docs.yml` and `/doc/*.md` aren't a published API — Workday could change them. They're isolated in `src/workday-docs-adapter.ts`, and `assertSchemaIntact()` fails loudly at startup if the structure changes. Great for a dev-productivity tool; treat as a maintenance liability for anything critical.
- **Docs, not data.** The server reads the *documentation*. It does not access any Workday tenant, customer data, or authenticated API.
- **Search quality** depends on the index — build it (`npm run build-index`) for app-building. A future semantic (embeddings) tier would slot into the same search layer without changing the tools.
TDQS
A4.7/5.0
Scored across 4 tools
Disambiguation5/5
Each tool serves a distinct purpose: browsing hierarchy, fetching pages, searching general docs, and specialized reference lookup. No overlap in functionality.
Naming Consistency5/5
All tools use consistent snake_case with a verb_noun pattern (browse_, get_, lookup_, search_), making them predictable.
Tool Count5/5
Four tools are well-scoped for a documentation MCP: browsing, searching, fetching, and reference lookup. No excess or deficiency.
Completeness5/5
The set covers core documentation needs: exploration via TOC, full-text search, page retrieval, and targeted reference lookups. No obvious gaps.
Maintenance
ActivityInactive
ResponsivenessNo issues