A comprehensive reference implementation that demonstrates every capability of the mctx framework in one well-commented file. You get five tools covering sync returns, structured objects, progress streaming, LLM sampling via `res.ask`, and user identity through `mctx.userId`. Resources show both static URIs and dynamic templates. Prompts illustrate single-message and multi-message conversation patterns. Every tool includes annotation hints with rationale, structured logging throughout, and full test coverage via JSON-RPC requests. Clone it to study the patterns, fork it as a starting point for your own server, or reference it when you need to see how progress notifications or LLM delegation actually work in practice.
mctx — The best way to Build an MCP Server
The comprehensive reference implementation for @mctx-ai/mcp. Every framework capability in one well-commented file — clone it, study it, fork it as a template for your own MCP server.
src/index.ts covers every pattern the framework supports:
Tool Patterns
greet: receives args, returns a formatted string; demonstrates environment variable configuration via GREETINGcalculate: returns a structured result object (auto-serialized to JSON); demonstrates input validation and error throwinganalyze: emits progress via res.progress(current, total); demonstrates streaming updates during long-running operationssmart-answer: delegates to the client's LLM via res.ask; demonstrates graceful fallback when sampling is unavailablewhoami: reads mctx.userId, the stable mctx user ID injected server-side by the platform; demonstrates graceful degradation outside mctxResource Patterns
docs://readme: exact URI, no parameters, returns plain textuser://{userId}: extracts userId from the URI path, returns a JSON profilePrompt Patterns
code-review: returns a plain string that becomes one user messagedebug: uses conversation() to build structured user/assistant dialogueInfrastructure
readOnlyHint, destructiveHint, openWorldHint, and idempotentHint with inline rationale explaining each choicelog.info, log.debug, log.warning, log.error, and log.notice throughoutprocess.env.GREETING lazily inside the handler (not at module scope)src/index.test.ts tests every tool, resource, and prompt via JSON-RPC 2.0 requestsOnce connected to an MCP client, try phrases like these:
Greetings and identity
greet with name: "Alice"whoami to return your stable mctx user IDgreet in a loop for each nameMath and analysis
calculate with operation: "multiply"analyze and streams three progress phasesQ&A and LLM sampling
smart-answer, which delegates to the client's LLM via asksmart-answerResources
docs://readmeuser://42Prompts
code-review prompt with a code snippetdebug prompt with an error and optional contextgreet(name: "Alice")
→ "Hello, Alice!"
whoami()
→ "Your mctx user ID is: user_abc123. This ID is stable across all your devices and sessions."
calculate(operation: "multiply", a: 6, b: 7)
→ { "operation": "multiply", "a": 6, "b": 7, "result": 42 }
analyze(topic: "quantum computing")
→ [progress: 1/3] → [progress: 2/3] → [progress: 3/3]
→ "Analysis of "quantum computing" complete. Found 42 insights across 7 categories."
smart-answer(question: "What is the capital of France?")
→ "Question: What is the capital of France?\n\nAnswer: Paris."
Read URI: docs://readme
→ "Welcome to the example MCP server built with @mctx-ai/mcp..."
Read URI: user://42
→ { "id": "42", "name": "User 42", "joined": "2024-01-01", "role": "developer" }
code-review(code: "const x = eval(input)", language: "javascript")
→ "Please review this javascript for bugs, security issues, and improvements:..."
debug(error: "TypeError: Cannot read properties of undefined")
→ [user] "I'm seeing this error: TypeError: Cannot read..."
→ [assistant] "I will analyze the error and provide step-by-step debugging guidance."
This repo is a GitHub template. Click Use this template on GitHub, then:
1. Clone your new repo
git clone https://github.com/your-username/your-repo.git
cd your-repo
2. Run the setup script
./setup.sh
setup.sh prompts for a project name and description, asks whether to keep the example code or start from a minimal skeleton, updates package.json, rewrites README.md with a clean starting point, installs dependencies, creates an initial git commit, and deletes itself.
3. Start developing
npm run dev
If you kept the examples, src/index.ts is unchanged — study the patterns and modify from there. If you started empty, you get a minimal skeleton with a single hello tool to build from.
Build
npm run build
Bundles src/index.ts to dist/index.js using esbuild (minified ESM output).
Dev server
npm run dev
# Test environment variables during dev:
GREETING="Howdy" npm run dev
Runs parallel watch mode: esbuild rebuilds on source changes, mctx-dev hot-reloads the server on rebuild.
Testing
npm test # Run all tests
npm test -- --watch # Watch mode
npm test src/index.test.ts # Specific file
npm test -- -t "greet" # Pattern match
Linting and formatting
npm run lint
npm run format
npm run format:check
GREETING — Customizes the greeting in the greet tool (default: "Hello"). Set GREETING="Howdy" to get "Howdy, Alice!".
src/index.ts → Server implementation — all capabilities in one file
├─ Tools → greet, whoami, calculate, analyze, smart-answer
├─ Resources → docs://readme (static), user://{userId} (dynamic)
├─ Prompts → code-review (single-message), debug (multi-message)
└─ Export → fetch handler for JSON-RPC 2.0 over HTTP
src/index.test.ts → Tests for every tool, resource, and prompt
dist/index.js → Bundled output (generated by esbuild, not committed on main)
mctx does not run build commands. It serves dist/index.js from the release branch — no npm run build at deploy time.
dist/ is gitignored on main. The release pipeline (.github/workflows/release.yml) builds dist/index.js from source and commits it to release automatically. Source-only on main; built output on release.
Deployment trigger: mctx watches for version changes in package.json on the release branch. A version bump triggers a new deployment. A push with no version bump does not trigger deployment.
Conventional commits determine the version bump:
| Commit prefix | Bump |
|---|---|
feat!: or fix!: | Major |
feat: | Minor |
| Everything else | Patch |
This repo uses squash merging — PR title becomes the commit subject, so PR titles must follow conventional commit format.
Do not edit the release branch directly. Do not commit dist/index.js on main.
Three package.json fields and README.md determine how developers find your MCP server.
description — Appears in the MCP Community Registry (truncates at ~100–150 chars) and on your mctx.ai page. Front-load the most important information.homepage — Clickable link on your public mctx.ai page. Point it at your GitHub repo or docs site.README.md — Becomes the documentation on your mctx.ai page and is indexed by Context7 for AI assistant discovery. Lead with what the MCP server does; the first ~4,000 characters are what AI assistants use to understand and recommend it.@mctx-ai/mcp — Framework documentation and API reference