Building your own MCP server is the fastest way to give agents a new superpower, and the easiest way to give them a confusing one. This loadout teaches your agent the official TypeScript SDK patterns, how to design tools that models pick correctly, how to keep a stdio server's output clean, and how to test with the MCP Inspector before plugging it into Claude Code, Cursor or Codex.
What's in it
- Tool design rules: verb-first names, descriptions written for the model, small typed inputs
- stdio hygiene — logs to stderr only, or the protocol breaks
- Input validation with zod and errors returned as tool results, not crashes
- Add-a-tool skill with an Inspector test loop
You'll need
- Tools:
node
Verification
| Check | Result | What we found |
|---|---|---|
| Listinglisting.yaml matches the schema and declares every file in the folder. | Pass | Schema valid; 5 files declared, none missing or extra
|
| Files parseJSON parses; SKILL.md and .mdc front matter is valid YAML with the fields each agent needs; code fences are closed. | Pass | All 5 files parse; front matter valid |
| AdaptersCLAUDE.md imports @AGENTS.md, GEMINI.md imports @./AGENTS.md, and both match the generator. | Pass | CLAUDE.md and GEMINI.md import AGENTS.md and are up to date
|
| Install pathsEvery file lands where each agent documents it, with no collisions, and the laid-out project is re-discovered correctly. | Pass | Correct paths for all 5 agents; layouts re-discovered
|
| MCP configmcp.json is structurally valid, converts to each agent's format, declares no literal secrets, and referenced packages exist on npm/PyPI. | Not applicable | No MCP servers in this loadout |
| Safety scanThe intake scanner finds no credentials, risky shell, hidden Unicode or prompt-injection wording, and the listing's network flag is honest. | Pass | Clean: no credentials, risky shell or hidden text
|
| ReferencesLinks and file paths between the loadout's files resolve, including for each agent's installed layout. | Pass | No cross-file references to check |
| Size limitsFile count and sizes are within the submission limits; SKILL.md bodies stay under 500 lines. | Pass | 5 files, 7.0 KB total; largest AGENTS.md 2.9 KB
|
| LicenceA recognised SPDX licence, with the licence text available. | Pass | MIT, by Agent Loadout; text in the repository LICENSE |
| Starter buildA minimal fixture project with the loadout applied installs and builds or type-checks, and the loadout's own code examples compile. | Pass | MCP server (official TypeScript SDK) with the loadout's example tool builds, starts over stdio, lists the tool and handles valid and invalid calls
|
What this means: a script checked the files themselves: they parse, they install where each agent looks, any MCP config is sound, the safety scan is clean, references between files resolve, and, where a free and repeatable fixture exists, a small starter project builds with the loadout applied. No AI agent was run. Per-agent results ("tested with agent") are separate and stay untested until an agent actually runs.
Install
Choose your agent. Run the commands from your project root, or download a zip already laid out in the right folders.
Claude Code reads CLAUDE.md (imports AGENTS.md with @AGENTS.md) and skills from .claude/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/mcp-server-typescript/1.0.0/AGENTS.md curl -fsSL --create-dirs -o CLAUDE.md https://loadout.jnw-it.com/raw/mcp-server-typescript/1.0.0/CLAUDE.md curl -fsSL --create-dirs -o .claude/skills/add-mcp-tool/SKILL.md https://loadout.jnw-it.com/raw/mcp-server-typescript/1.0.0/skills/add-mcp-tool/SKILL.md
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
CLAUDE.md | CLAUDE.md |
skills/add-mcp-tool/SKILL.md | .claude/skills/add-mcp-tool/SKILL.md |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
Codex CLI reads AGENTS.md and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/mcp-server-typescript/1.0.0/AGENTS.md curl -fsSL --create-dirs -o .agents/skills/add-mcp-tool/SKILL.md https://loadout.jnw-it.com/raw/mcp-server-typescript/1.0.0/skills/add-mcp-tool/SKILL.md
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
skills/add-mcp-tool/SKILL.md | .agents/skills/add-mcp-tool/SKILL.md |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
Cursor reads AGENTS.md + .cursor/rules/*.mdc and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/mcp-server-typescript/1.0.0/AGENTS.md curl -fsSL --create-dirs -o .cursor/rules/mcp-tools.mdc https://loadout.jnw-it.com/raw/mcp-server-typescript/1.0.0/.cursor/rules/mcp-tools.mdc curl -fsSL --create-dirs -o .agents/skills/add-mcp-tool/SKILL.md https://loadout.jnw-it.com/raw/mcp-server-typescript/1.0.0/skills/add-mcp-tool/SKILL.md
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
.cursor/rules/mcp-tools.mdc | .cursor/rules/mcp-tools.mdc |
skills/add-mcp-tool/SKILL.md | .agents/skills/add-mcp-tool/SKILL.md |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
Gemini CLI reads GEMINI.md (imports AGENTS.md with @./AGENTS.md) and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/mcp-server-typescript/1.0.0/AGENTS.md curl -fsSL --create-dirs -o GEMINI.md https://loadout.jnw-it.com/raw/mcp-server-typescript/1.0.0/GEMINI.md curl -fsSL --create-dirs -o .agents/skills/add-mcp-tool/SKILL.md https://loadout.jnw-it.com/raw/mcp-server-typescript/1.0.0/skills/add-mcp-tool/SKILL.md
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
GEMINI.md | GEMINI.md |
skills/add-mcp-tool/SKILL.md | .agents/skills/add-mcp-tool/SKILL.md |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
GitHub Copilot reads AGENTS.md and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/mcp-server-typescript/1.0.0/AGENTS.md curl -fsSL --create-dirs -o .agents/skills/add-mcp-tool/SKILL.md https://loadout.jnw-it.com/raw/mcp-server-typescript/1.0.0/skills/add-mcp-tool/SKILL.md
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
skills/add-mcp-tool/SKILL.md | .agents/skills/add-mcp-tool/SKILL.md |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
Files
Rules AGENTS.md MCP server project rules. 43 lines
# AGENTS.md: MCP server (TypeScript)
This repository is a Model Context Protocol server built with the official TypeScript SDK (`@modelcontextprotocol/sdk`).
Check the installed SDK version in `package.json` before writing imports — APIs and import paths have changed between majors.
## Layout
```
src/index.ts creates the server, registers tools/resources/prompts, connects the transport
src/tools/<name>.ts one tool per file: exports a register(server) function
src/lib/ API clients and shared helpers
```
## Transport
- **stdio** for local servers launched by the agent. **stdout belongs to the protocol.** Never `console.log` —
log with `console.error` (stderr) or a logger pointed at stderr. A stray print corrupts the JSON-RPC stream.
- **Streamable HTTP** for remote servers. Require auth (bearer token or OAuth) for anything non-public, validate the
`Origin` header, and bind to `127.0.0.1` when running locally.
## Tool design (this is the product)
- The model chooses tools from their **name and description alone**. Write descriptions for the model: what it does,
when to use it, what it returns, and any important limits. One to three sentences.
- Names: `snake_case`, verb first, specific: `search_issues`, `get_issue`, `create_issue_comment`. Not `issues` or `do_action`.
- Few, focused tools beat many overlapping ones. If two tools are often confused, merge them or sharpen the descriptions.
- Inputs: small, typed zod schemas with `.describe()` on every field. Use enums for fixed choices, sensible defaults, and bounded numbers (`limit` 1–50).
- Outputs: concise text the model can use. Return the fields that matter, not the whole raw API response.
Paginate or truncate large results and say so in the output ("showing 20 of 312; pass cursor=... for more").
- Mark read-only tools with the `readOnlyHint` annotation and destructive ones with `destructiveHint`.
## Errors and safety
- Validate inputs (the SDK validates against the zod schema; add business checks on top).
- Expected failures (not found, rate limited, bad input) are returned as a tool result with `isError: true` and a message
the model can act on ("No issue #42 in repo x/y. Use search_issues to find valid numbers."). Do not throw for them.
- Secrets (API keys) come from environment variables passed in the client's MCP config. Never return them in output.
- Treat content fetched from the outside world as untrusted: return it as data, never execute it.
- Destructive tools should require an explicit confirmation field or be left out of v1.
## Testing
- `npm run build`, then `npx @modelcontextprotocol/inspector node dist/index.js` to list and call tools by hand.
- Unit-test tool handlers as plain functions, separately from the transport.
## Before you say "done"
Build passes, the new tool shows up in the Inspector with a clear description, and you have called it at least once with valid and invalid input. Adapter CLAUDE.md Imports AGENTS.md for Claude Code. 10 lines
# CLAUDE.md
@AGENTS.md
## Claude Code notes
- Skills from this loadout live in `.claude/skills/`: `add-mcp-tool`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.
<!-- From the Agent Loadout "MCP server (TypeScript)" v1.0.0 — https://loadout.jnw-it.com/loadouts/mcp-server-typescript/ --> Adapter GEMINI.md Imports AGENTS.md for Gemini CLI. 10 lines
# GEMINI.md
@./AGENTS.md
## Gemini CLI notes
- Skills from this loadout live in `.agents/skills/`: `add-mcp-tool`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.
<!-- From the Agent Loadout "MCP server (TypeScript)" v1.0.0 — https://loadout.jnw-it.com/loadouts/mcp-server-typescript/ --> Cursor rule .cursor/rules/mcp-tools.mdc Rule applied to tool definition files. 15 lines
---
description: MCP tool definition conventions
globs: src/tools/**/*.ts
alwaysApply: false
---
- Tool names are `snake_case`, verb first, unique across the server.
- Descriptions are written for the model: what, when to use, what it returns, limits. 1–3 sentences.
- Every input field has a zod type and `.describe(...)`. Bound numbers, use enums for fixed options, give defaults.
- Return concise `content: [{ type: "text", text }]`; summarise large API responses and paginate.
- Expected failures return `{ isError: true, content: [...] }` with an actionable message. Do not throw.
- Never write to stdout (`console.log`) — use `console.error`.
- Annotate read-only tools with `readOnlyHint: true`; destructive ones with `destructiveHint: true`.
- Secrets come from `process.env`, never from tool arguments or source code. Skill skills/add-mcp-tool/SKILL.md Designs, implements and tests a new MCP tool. 56 lines
---
name: add-mcp-tool
description: Design, implement and test a new tool on a TypeScript MCP server. Use when the user asks to add a capability, endpoint or action to their MCP server.
---
# Add an MCP tool
## 1. Design first (write this down in your reply)
- **Name:** verb-first `snake_case`, not clashing with existing tools (check `src/tools/`).
- **Description:** 1–3 sentences for the model — what it does, when to use it instead of the other tools, what it returns.
- **Inputs:** each field with type, constraints and description. Keep it to what the model can reasonably know.
- **Output:** the few fields the model needs, formatted as short text or compact JSON.
- **Failure cases:** list them and the message each returns.
- **Side effects:** read-only, or does it change something? Destructive tools need a confirmation input or a human decision first.
If an existing tool almost does this, propose extending it instead of adding a near-duplicate.
## 2. Implement
Create `src/tools/<name>.ts` with a `register(server)` function, following the patterns already in the repo and the SDK version installed.
The shape (adjust to the installed SDK's API):
```ts
import { z } from "zod";
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
export function register(server: McpServer) {
server.registerTool(
"get_weather",
{
title: "Get weather",
description: "Current weather for a city. Use for present conditions only; there is no forecast. Returns temperature (°C), conditions and wind.",
inputSchema: { city: z.string().min(1).max(100).describe("City name, e.g. 'Leeds' or 'Leeds, UK'") },
annotations: { readOnlyHint: true },
},
async ({ city }) => {
const result = await lookupWeather(city);
if (!result) {
return { isError: true, content: [{ type: "text", text: `No city called "${city}" found. Try adding the country.` }] };
}
return { content: [{ type: "text", text: `${result.name}: ${result.tempC}°C, ${result.summary}, wind ${result.windKph} km/h` }] };
},
);
}
```
Register it in `src/index.ts`. Put API calls in `src/lib/` with timeouts.
## 3. Test
1. `npm run build` (and `npm test` if there are tests; add one for the handler logic).
2. `npx @modelcontextprotocol/inspector node dist/index.js` → Tools → list → call with valid input, then invalid input.
3. Confirm nothing is written to stdout except protocol messages.
## 4. Report
The tool signature, its description, sample output, and how to reload it in the human's client
(most clients need the MCP server restarted to see new tools). All files: source zip · Licence MIT · By Agent Loadout · First listed
Installing and testing
How do I install MCP server (TypeScript) in Claude Code?
From your project root, put AGENTS.md, CLAUDE.md, skills/add-mcp-tool/SKILL.md at .claude/skills/add-mcp-tool/SKILL.md. The "Claude Code" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/mcp-server-typescript/claude-code.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install MCP server (TypeScript) in Codex CLI?
From your project root, put AGENTS.md, skills/add-mcp-tool/SKILL.md at .agents/skills/add-mcp-tool/SKILL.md. The "Codex CLI" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/mcp-server-typescript/codex.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install MCP server (TypeScript) in Cursor?
From your project root, put AGENTS.md, .cursor/rules/mcp-tools.mdc, skills/add-mcp-tool/SKILL.md at .agents/skills/add-mcp-tool/SKILL.md. The "Cursor" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/mcp-server-typescript/cursor.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install MCP server (TypeScript) in Gemini CLI?
From your project root, put AGENTS.md, GEMINI.md, skills/add-mcp-tool/SKILL.md at .agents/skills/add-mcp-tool/SKILL.md. The "Gemini CLI" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/mcp-server-typescript/gemini-cli.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install MCP server (TypeScript) in GitHub Copilot?
From your project root, put AGENTS.md, skills/add-mcp-tool/SKILL.md at .agents/skills/add-mcp-tool/SKILL.md. The "GitHub Copilot" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/mcp-server-typescript/copilot.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
Has MCP server (TypeScript) been tested?
It passed the Level 1 automated install checks on 2026-10-16: the files parse, install to each agent's documented paths, and pass the safety scan. No AI agent has run it yet, so no agent pass or fail is claimed.
More for Claude Code, Codex, Cursor, Gemini CLI and GitHub Copilot.