This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Monorepo for the Umbraco MCP (Model Context Protocol) Server SDK - infrastructure for building MCP servers that expose Umbraco APIs to AI assistants.
| Workspace | Description | Published |
|---|---|---|
packages/mcp-server-sdk/ |
Core npm package @umbraco-cms/mcp-server-sdk |
Yes |
packages/hosted-mcp/ |
Hosted MCP on Cloudflare Workers @umbraco-cms/mcp-hosted |
Yes |
packages/create-mcp-server/ |
CLI scaffolding tool @umbraco-cms/create-umbraco-mcp-server |
Yes |
template/ |
Starter kit for new MCP server projects (copied by create-mcp-server); ships with .mcp.json for Claude Code |
No |
plugins/ |
Claude Code plugins for SDK development (building, testing) | No |
tests/cli/ |
CLI integration tests and LLM eval tests | No |
docs/ |
CLI reference and planning docs | No |
Each workspace has its own CLAUDE.md with detailed guidance.
npm install # Install all workspace dependencies
npm run build # Build SDK
npm run test # Test SDKWorkspace-specific commands use -w flag: npm run build -w packages/mcp-server-sdk
Run all tests before merging. Tests are grouped by what they cover and what infrastructure they need.
| Command | What it tests | Tests |
|---|---|---|
npm run test |
SDK unit tests (tool filtering, config, helpers, CLI commands) | ~425 |
npm test -w packages/hosted-mcp |
Hosted MCP unit tests (config, auth, consent, server creation) | ~191 |
npm test -w packages/create-mcp-server |
Scaffolding CLI unit tests | ~121 |
| Command | What it tests | Tests |
|---|---|---|
npm run test:cli |
CLI integration tests — runs built template binary with filtering, introspection, dry-run, input sanitization | ~21 |
npm run test:integration |
Hosted MCP Wrangler integration tests | ~20 |
npm run test:integration:chained |
Chained hosted MCP integration tests | ~18 |
| Command | What it tests | Tests |
|---|---|---|
npm run test:e2e |
Hosted MCP Playwright E2E — OAuth flow, tool selection, readOnly filtering via MCP Inspector | ~15 |
npm run test:e2e:chained |
Chained MCP Playwright E2E — chained tool discovery, consent screen, filtering | ~12 |
| Command | What it tests | Tests |
|---|---|---|
npm run test:template |
Template tool handler unit tests — MSW intercepts API calls, no Umbraco needed | ~24 |
Note: USE_MOCK_API=true enables MSW interception. Without it, tests hit the real Umbraco API (this is the default for scaffolded sites). The test:template script sets it automatically.
| Command | What it tests | Tests |
|---|---|---|
npm run test:cli:evals |
LLM eval tests — agent uses mcp-cli skill to run and interpret CLI commands | ~21 |
| Command | What it tests | Tests |
|---|---|---|
TEST_SQL_CONNECTION_STRING="..." npm run test:e2e -w packages/create-mcp-server |
New-instance CLI E2E — scaffold, init's "create new" branch (PSW), Umbraco setup, discover, generate, compile, test | ~19 |
TEST_SQL_CONNECTION_STRING="..." npm run test:e2e:existing -w packages/create-mcp-server |
Existing-instance CLI E2E — spawns a copy of tests/umbraco-instance/ on a random port against a per-test SQL Server DB, runs scaffold + init's "use existing" branch, asserts .env, orval.config.ts, and a real API call |
~3 |
| Entry Point | Purpose |
|---|---|
@umbraco-cms/mcp-server-sdk |
Main: tool helpers, decorators, types, config loaders, CLI helpers (handleCliCommands) |
@umbraco-cms/mcp-server-sdk/testing |
Test utilities: setupTestEnvironment, setupMswServer, snapshot helpers |
@umbraco-cms/mcp-server-sdk/evals |
LLM eval framework: runScenarioTest, verification helpers |
@umbraco-cms/mcp-server-sdk/config |
Configuration loading |
@umbraco-cms/mcp-server-sdk/helpers |
API call helpers only |
@umbraco-cms/mcp-server-sdk/constants |
Umbraco well-known IDs |
ToolDefinition - Type-safe tool structure with name, description, input/output schemas, slices, annotations, and handler.
Tool Collections - Groups of related tools with metadata (name, displayName, description, dependencies).
Tool Filtering - Filter tools by modes (collection groups), slices (operation categories), collections, or individual tool names. Configured via env vars or CLI flags.
API Call Helpers - Standardized handlers for GET, DELETE, PUT, POST operations with automatic error handling and ProblemDetails support.
MCP Chaining - Proxy tools from other MCP servers via McpClientManager.
- The test Umbraco instance lives at
tests/umbraco-instance/ - You MUST start the Umbraco instance before running any Playwright tests:
dotnet run --project tests/umbraco-instance - This applies when running tests against any host (this repo, CMS, Forms, etc.) — the instance must always be running first
- When running Playwright tests for the first time in a session, run a single test first to verify the setup is working. If it passes, then run the full suite.
- Stale
workerdprocesses can hold ports (8787, 8789 etc.) after interrupted test runs. If tests fail with "Address already in use", kill them:lsof -i :8787thenkill -9 <pid>
- Run with
npm run test:integrationandnpm run test:integration:chained - Use Wrangler's
unstable_dev()— do NOT useunstable_startWorker()which hangs with OAuthProvider-wrapped Workers - Require
--runInBand --forceExitbecause Wrangler workers don't exit cleanly - Wrangler migrations must use
new_sqlite_classes, notnew_classes, for Durable Objects
- Run with
npm run test:evals(from template or host projects) - Require
npm run buildfirst — evals run againstdist/index.js, not source - Require
ANTHROPIC_API_KEYenvironment variable or a Claude Code subscription
After creating or pushing to a PR, ask the user if they want you to monitor the CI build. If yes:
- Wait for the GitHub Actions workflow to complete:
gh pr checks <pr-number> --watch - If checks fail, inspect the failure:
gh run view <run-id> --log-failed - Fix the issue, push, and repeat until CI is green
Do not just push a PR and walk away — the CI build includes tests that don't run locally (CLI E2E with SQL Server, Playwright E2E, scaffolding compilation checks). Always offer to follow through, but respect that sometimes the user doesn't need this.
The local Umbraco instance uses HTTPS with self-signed certs. TLS rejection must be disabled in three places:
- Environment variable:
NODE_TLS_REJECT_UNAUTHORIZED=0 - Jest setup file:
https.globalAgent.options.rejectUnauthorized = false(env var alone is insufficient in Jest VM context) - Playwright config:
ignoreHTTPSErrors: true
All packages are versioned together and published from the main branch via Azure Pipelines.
- Create a release branch from
dev:release/<version>(e.g.release/17.0.0-beta.9) - Bump the version in all files (use find-and-replace for the old version string):
package.json(root)packages/mcp-server-sdk/package.jsonpackages/hosted-mcp/package.jsonpackages/create-mcp-server/package.jsontemplate/package.jsonplugins/package.jsonplugins/.claude-plugin/plugin.json.claude-plugin/marketplace.json(metadata.versionand eachplugins[].version)
- Run
npm install --package-lock-onlyto updatepackage-lock.json - Verify no stale versions:
grep -r "beta.OLD" package.json packages/*/package.json template/package.json plugins/package.json plugins/.claude-plugin/plugin.json .claude-plugin/marketplace.json - Commit, push, and create a PR from the release branch into
main - CI runs all tests including LLM evals and skill E2E (release PRs only)
- Merge when all checks pass — Azure Pipelines publishes packages to npm
- Create a GitHub Release tagged
v<version>from the merge commit - Merge
mainback intodevvia PR (to sync version numbers)
After a release is published, main has the version bump commit that dev doesn't. Create a PR to merge main back:
git checkout dev && git pull
git checkout -b chore/merge-main-to-dev
git merge origin/main --no-edit
# Resolve any conflicts (take dev's version for code, main's for versions)
git push -u origin chore/merge-main-to-dev
gh pr create --base dev --title "Merge main into dev after <version> release"- Prerelease:
17.0.0-beta.N(published with--tag betadist-tag) - Stable:
17.0.0(published with--tag latestdist-tag)
The template's package.json uses file: references to mcp-server-sdk and mcp-hosted for monorepo development. The create-mcp-server scaffold tool (src/scaffold.ts) rewrites these to published npm versions when users create new projects.
- Node.js 22+
- .NET 10 (for test Umbraco instance)
- ESM modules (type: "module")