workiva-mcp
# workiva-mcp
An MCP server for the Workiva platform that pairs API tools with an
accumulating knowledge base of confirmed API behaviour — the quirks, dead
ends, and undocumented requirements that otherwise cost every agent (and
every teammate) the same hour of rediscovery.
The mechanism that makes the pairing matter: **failing API calls
automatically attach the matching KB entry.** An agent that hits
`400 "unable to match urn"` gets the fix inside the error message itself,
without ever knowing the KB exists.
**Status: v0.1.0** — the full planned surface is live: 22 tools across the
KB, credential profiles, Wdata, Graph and Spreadsheets, plus the escape
hatch and the drafts → PR contribution loop.
## Install
```bash
claude mcp add --scope user workiva -- uvx --from git+https://github.com/woof-xyz/workiva-mcp@v0.1.0 workiva-mcp
```
`--scope user` registers the server once for your account, available in
every directory. Without it, `claude mcp add` defaults to **local** scope —
private to you in the one directory you ran it from, which is why the server
seems to vanish in every other project. The third option, `--scope project`,
writes a `.mcp.json` into the repo so teammates get the server on clone.
Add `-e WORKIVA_ALLOW_WRITES=1` before `--` to enable write tools (see
*Write safety*). **Pin a tag** — uv caches git resolutions, so an unpinned
`main` silently freezes at whatever commit it first resolved. Upgrading =
re-add with the new tag. Credentials go in `~/.workiva/credentials`
(*Credentials* below); the KB tools work with no credentials at all.
## Tools
| Group | Tools |
|---|---|
| KB | `kb_search` · `kb_list` · `kb_get` · `kb_add` |
| Profiles | `profile_list` · `profile_use` |
| Wdata (read) | `wdata_list_tables` (with `sql_ref`) · `wdata_get_table` · `wdata_list_queries` · `wdata_run_sql` · `wdata_run_saved_query` · `wdata_list_connections` |
| Wdata (write) | `wdata_create_table` · `wdata_upload_and_import` · `wdata_refresh_connection` |
| Graph | `graph_types` · `graph_records` · `graph_edits` (write) |
| Spreadsheets | `spreadsheet_list_sheets` · `spreadsheet_ui_url` · `spreadsheet_update` (write) |
| Anything else | `workiva_request` (platform / wdata / chains) |
Every API tool runs through the auto-attach mechanism: failures come back
wearing the matching KB entries, resolution included.
## What the KB knows
25 seeded entries, all confirmed against the live API in July 2026:
**4 blockers** (no API path exists — e.g. connections cannot be created
programmatically), **12 gotchas** (the obvious approach fails first — e.g.
Wdata SQL cannot reference tables by name), and **9 nuances**. Entries are
dated, version-pinned, and carry the literal error strings they match.
## Layout
```
workiva-mcp/
src/workiva_mcp/
server.py # MCP tools
kb.py # KB toolchain: parse, validate, build index, search
client.py # Workiva API client: credentials, token refresh, three hosts
promote.py # KB drafts -> branch -> PR (planned)
kb/ # the knowledge base: entries/*.md + SCHEMA.md + index.json
tests/
.githooks/ # pre-push gate: ruff + pytest + kb check
```
## Development
One-time setup after cloning — activate the pre-push gate:
```bash
git config core.hooksPath .githooks
```
Every push then runs ruff, the tests, and the KB check first
(`git push --no-verify` bypasses in an emergency).
```bash
uv run workiva-mcp # boots the stdio server
uv run pytest # tests
uv run ruff check . # lint
uv run python -m workiva_mcp.kb check # validate entries + index currency
uv run python -m workiva_mcp.kb build # rebuild kb/index.json after editing entries
```
`kb/index.json` is generated — never edit it by hand; edit `kb/entries/*.md`
and rebuild.
Register with Claude Code from a clone:
```bash
claude mcp add --scope user workiva -- uv run --directory <path-to-clone> workiva-mcp
```
(`--scope user` makes the dev server available everywhere; drop it to keep
it confined to the directory you register it from.)
## Credentials
```ini
# ~/.workiva/credentials (chmod 600)
[settings]
default_profile = sandbox
[default]
client_id = ...
client_secret = ...
[sandbox]
client_id = ...
client_secret = ...
# optional per-profile endpoint overrides:
# token_url / platform_base / wdata_base / chains_base
```
The file is re-read at call time, so edits — rotating a secret, switching
`default_profile` — take effect on the next call without restarting the
server. With no file at all, `WORKIVA_CLIENT_ID` / `WORKIVA_CLIENT_SECRET`
serve the default profile. `WORKIVA_CREDENTIALS_FILE` overrides the file
location.
**Switching profiles** is a tool call, not a file edit: `profile_list`
shows every profile with the active one marked, and `profile_use("sandbox")`
makes all subsequent API calls authenticate as that profile — a fresh token
is fetched on the next call. The switch is session-scoped: nothing is
written to the file, and a restart returns to the configured default
(`profile_use("")` does the same without restarting). Precedence:
`profile_use` override > `WORKIVA_PROFILE` > `[settings] default_profile` >
`[default]`.
## Write safety
The server is **read-only by default**: tools marked WRITE (create table,
upload/import, connection refresh, …) refuse with an explanatory message and
touch nothing. Enable writes with `WORKIVA_ALLOW_WRITES=1` in the server's
environment, or `allow_writes = true` under `[settings]` in
`~/.workiva/credentials` — the file is re-read at call time, so flipping it
takes effect immediately, and an explicit env value (even `0`) always wins.
Read-only means *no user-visible workspace mutations*: `wdata_run_sql`'s
internal temp-query mechanics stay allowed.
## Capturing new knowledge
`kb_add` writes drafts to `~/.workiva/kb/drafts/` (override with
`WORKIVA_KB_DRAFTS`) — local, instant, no review, never part of the package.
Search reads bundled entries **and** your drafts, so a quirk you hit today
helps you again tomorrow, before any review happens. Drafts carry
`confidence: reported` and pass the same schema linter as real entries.
Promotion into the shared KB is a deliberate human act:
```bash
uv run workiva-kb list # what's waiting locally
uv run workiva-kb promote <draft-id> ... # re-stamp as confirmed, branch, commit, open PR
```
(`--no-pr` for branch+commit only, `--keep-drafts` to leave local copies,
`--confidence` to override the `confirmed` re-stamp.) Workspace-specific
findings simply never get promoted.
## Roadmap
- [x] Scaffold: package, entry point, empty stdio server
- [x] KB data vendored: 25 entries, schema, CC-BY-4.0 license
- [x] KB toolchain: parse + validate + index build + weighted search, tests, pre-push gate
- [x] KB tools: `kb_search` / `kb_list` / `kb_get`, KB packaged into the wheel
- [x] Local drafts overlay + `kb_add`
- [x] Workiva client foundation: credential profiles in `~/.workiva/credentials`, token lifecycle, three-host transport
- [x] Auto-hint mechanism + read-only Wdata tools
- [x] SQL execution, saved queries, connections listing
- [x] Write gate (`WORKIVA_ALLOW_WRITES` / `allow_writes`) + modifying Wdata tools: create table, upload → import → poll, connection refresh
- [x] Graph + Spreadsheets tools (writes gated)
- [x] Escape hatch (platform / wdata / chains)
- [x] `promote` CLI: drafts → PR (`workiva-kb`)
- [x] `v0.1.0` tag, `uvx` install verified
- [x] Credential profile switching: `profile_list` / `profile_use`
- [ ] NOTICE file — deferred until copyright ownership is settled (see the
plan's open item); Apache-2.0 is complete without it
## License
Code: Apache-2.0 (see `LICENSE`). KB entries under `kb/`, once landed:
CC-BY-4.0.
TDQS
Scored across 20 tools
Each tool targets a distinct operation within its domain (KB, Wdata, Graph, Spreadsheets, general request). No two tools overlap in purpose; the knowledge base tools are clearly differentiated from data operations, and the escape hatch covers anything not wrapped.
Names follow domain-specific prefixes (kb_, wdata_, graph_, spreadsheet_) with verb_noun patterns mostly, though some graph tools use plain nouns (graph_types) and the escape hatch uses workiva_request. Minor inconsistency across groups but still predictable.
20 tools is well-scoped for the Workiva API surface, covering multiple sub-APIs without being overwhelming. Each tool serves a clear purpose, and the count feels balanced.
Covers core workflows: KB management, Wdata CRUD and SQL, graph operations, spreadsheet updates, and a general escape hatch. Missing direct spreadsheet creation and some admin operations, but the escape hatch fills gaps effectively.