Skip to content

v0.8.0 — Scaffolds you can test

Choose a tag to compare

@IBJunior IBJunior released this 19 Sep 18:05
· 7 commits to main since this release
418db03

A scaffolded MCP server used to start with a greet tool that returned a string, and nothing to verify it. That is a poor thing for a scaffolder to teach: a tool description is a contract with a caller that cannot read your code, so an unverified contract is the default failure. Generated projects now start with a realistic example, a passing test suite, an AGENTS.md, and the tool-design skill.

Note: this changes what newly scaffolded projects look like. Existing generated projects are unaffected — they pin their own dependencies.

A worked example worth copying

The greet tool is gone. In its place is a small notes server designed against the tool-design principles, chosen so its contract has something to verify:

list_notes(tag?, limit=20)         -> page + matched/returned/truncated + hint
get_note(id)                       -> the note, or an actionable isError
create_note(title, body, tags?)    -> the note including its new id
notes://{id}                       -> ResourceTemplate, list implemented
summarize-notes                    -> prompt over a tag

It demonstrates four things a toy example cannot:

  • Truncation is signalled, not silently applied. A capped list reports matched: 30, returned: 5, truncated: true plus a hint on how to narrow it. A tool that quietly caps results lies to the agent calling it.
  • An unknown filter is distinguishable from an empty result. Both return no rows; conflating them makes an agent report "you have none" when the truth is "you misspelled it".
  • Failures return isError with a next move, not thrown exceptions or bare codes.
  • Results chain. create_note returns the id, so the agent can read it back without a lookup.

Tool names carry their noun but no server namespace — list_notes, not notes_list. Most MCP clients prepend the server name, so a hardcoded prefix would surface as my-server_notes_list.

Tests that run green immediately

SDK projects ship a working suite — no config to add:

  • src/notes-store.test.ts — the data layer on its own, no transport.
  • src/server.test.ts — a real MCP client over an in-memory transport, asserting on the payload a tool actually returns.

Nine tests, deliberately. The suite is a template people copy, so each one pins something a tool's description promises and nothing else checks. None exercise the example's own data structures.

FastMCP projects keep their existing example and ship without tests for now.

Structure

server.ts is now a composition root; definitions live beside it:

src/
  server.ts        # creates the McpServer, registers the primitives
  tools.ts         # registerTools(server)
  prompts.ts       # registerPrompts(server)
  resources.ts     # registerResources(server)
  notes-store.ts   # data layer, no MCP imports
  index.ts         # transport wiring

Keeping the data layer free of MCP imports is what makes it testable without a server — and its state must stay at module scope, because createMcpHandler runs the server factory once per request.

AGENTS.md in every project

Written for whoever changes the project, as distinct from the README. It carries the traps that are invisible until they bite: state discarded between requests on HTTP, stdout belonging to the protocol on stdio, and OAuthError-not-Error when OAuth is enabled. Plus how to write a good tool, and how to organize tools as they grow — flat files, then src/tools/, then feature folders.

It stays example-agnostic, so it remains accurate after you delete the notes example.

The tool-design skill, bundled

Projects get Agentailor's tool-design skill at .agents/skills/tool-design/.

It is bundled with the CLI, not fetched — scaffolding needs no network and stays instant, and a given CLI version always emits a known version of the skill. It does age; pull a newer copy when you want one:

npx skills update -p -y

.agents/ rather than .claude/, following the same move to tool-agnostic locations that AGENTS.md made. Pass --no-skills to skip it.

Dependency refresh

Templates move to TypeScript 7 (the Go-native compiler) and dotenv 18, both verified by generating and building every variant. Also @modelcontextprotocol/inspector 2.7, hono 4.13, zod 4.6, jose 6.2.12, fastmcp 4.20, @types/node 26.6.

update-template-deps now tags major bumps [MAJOR] and repeats them in a summary, so a compiler rewrite can't land unannounced.

Repo housekeeping

  • CLAUDE.md → AGENTS.md, the cross-agent convention.
  • vitest.config.ts scopes the test run, so local scratch projects under generated/ no longer leak into it.

New CLI option

Option Default Description
--no-skills false Skip adding the tool-design skill

Upgrading

npx @agentailor/create-mcp-server@0.8.0

Full changelog: v0.7.1...v0.8.0