ai-toolkit-rules
Mandatory engineering, security, testing, git, performance, quality, and response rules.…
MCP server design: tool schemas, resources, stdio/SSE, capability negotiation. Triggers: MCP, Model Context Protocol, JSON-RPC, stdio, SSE, Claude Desktop.
$ npx -y skills add softspark/ai-toolkit --skill mcp-patterns --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/mcp-patternsContext preview
The summary Claude sees to decide when to auto-load this skill.
MCP server design: tool schemas, resources, stdio/SSE, capability negotiation. Triggers: MCP, Model Context Protocol, JSON-RPC, stdio, SSE, Claude Desktop.
name: mcp-patterns description: "MCP server design: tool schemas, resources, stdio/SSE, capability negotiation. Triggers: MCP, Model Context Protocol, JSON-RPC, stdio, SSE, Claude Desktop." effort: medium user-invocable: false allowed-tools: Read
| Concept | Description | |---------|-------------| | **Server** | Exposes tools, resources, prompts to clients | | **Client** | Connects to servers, invokes tools | | **Transport** | Communication layer (stdio, HTTP, SSE) | | **Tool** | Executable function with JSON Schema | | **Resource** | Read-only data (files, URLs) | | **Prompt** | Reusable prompt template |
---
// TypeScript with @modelcontextprotocol/sdk
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [{
name: "search_kb",
description: "Search the knowledge base",
inputSchema: {
type: "object",
properties: {
query: {
type: "string",
description: "Search query"
},
limit: {
type: "number",
description: "Max results",
default: 10
}
},
required: ["query"]
},
annotations: {
readOnlyHint: true, // Doesn't modify state
idempotentHint: true, // Same input = same output
openWorldHint: false // Bounded result set
}
}]
}));| Annotation | Meaning | Use When | |------------|---------|----------| | `readOnlyHint` | No side effects | Read operations | | `destructiveHint` | Deletes/modifies data | Write operations | | `idempotentHint` | Safe to retry | GET-like operations | | `openWorldHint` | Results may change | External API calls |
---
The `description` is the only signal the model uses to route a request. The schema constrains the *call*; the description decides *whether the call happens at all*. Treat it as a routing contract, not API prose. A good one has five parts, in this order:
1. **One-line purpose** — what the tool does, in plain terms. Lead with a verb. `Search indexed knowledge-base documents and return ranked passages.` Skip the HTTP verb and endpoint; `calls GET /v2/search` tells the model nothing about intent. 2. **WHEN TO USE** — concrete trigger phrasings the user might say, not abstract categories. List the actual shapes: *"find docs about X", "what does the KB say about Y", "look up the runbook for Z"*. Models match on surface form, so give them surface forms. 3. **WHEN NOT TO USE** — the section that does most of the disambiguation work. Name the near-miss tools and the boundary that separates them. This is where you prevent the model from firing the wrong tool on a request that *looks* similar. Empty WHEN NOT TO USE = the tool is under-specified. 4. **CRITICAL** — one line for the single non-obvious failure mode. The constraint a reader would not guess from the schema: a required ordering, an ID that must come from another call, a cost/irreversibility warning. One line, not a checklist. 5. **Self-test** — close with a question the model can apply to itself to decide fit. `Ask: is the user looking up existing content, or asking me to create new content? This tool is read-only — if they want to create, stop.`
Positive triggers tell the model when a tool *could* apply; negative ones are what stop it firing on overlapping requests. When two tools have similar purposes (`search_kb` vs `search_code`, `get_document` vs `list_documents`), the only thing keeping the model off the wrong one is each description naming the other and drawing the line. Budget more words for the boundary than the bullseye.
When tools overlap, make each WHEN NOT TO USE point at its neighbour and state the discriminator explicitly:
search_kb
WHEN NOT TO USE: do not use to fetch a document you already have the id for —
that is get_document. Use search_kb only when you need to discover *which*
document, by meaning or keyword.
get_document
WHEN NOT TO USE: do not use to find a document by topic or keyword — you must
already hold an exact id (from search_kb results). For discovery, use search_kb.name: cancel_workflow
description: |
Stop a running agent workflow and discard its in-flight results.
WHEN TO USE: the user says "cancel the workflow", "stop run abc123",
"kill that job", or asks to halt a workflow that get_workflow_status
reports as RUNNING.
WHEN NOT TO USE:
- To inspect progress without stopping — use get_workflow_status.
- To start a fresh run — use start_workflow.
- On a workflow already in a terminal state (COMPLETED/FAILED) — the call
is a no-op and signals the model misread the status.
CRITICAL: cancellation is irreversible and drops partial output. Confirm the
workflowId came from list_workflows or get_workflow_status — never type one
from memory.
Self-test: am I stopping work that is genuinely still RUNNING, or did I confuse
"check status" with "cancel"? If I have not seen a RUNNING status, do not call this.A description that survives this rubric routes correctly without the model reading your source. One that skips WHEN NOT TO USE will misfire the moment a second, similar tool exists in the same server.
---
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio";
const transport = new StdioServerTransport();
await server.connect(transport);# FastAPI implementation
from fastapi import FastAPI
from sse_starlette.sse import EventSourceResponse
app = FastAPI()
@app.get("/mcp/sse")
async def sse_endpoint():
async def event_generator():
while True:
# Yield MCP events
yielAI coding toolkit with machine-enforced safety, 116 skills, 44 agents, lifecycle hooks, persona presets, opt-in plugin packs, and benchmark tooling.
Repo: softspark/ai-toolkit
Mandatory engineering, security, testing, git, performance, quality, and response rules.…
Searches past coding sessions for observations, decisions, context. Triggers: mem-search,…
Accessibility validator: WCAG 2.1 AA, EN 301 549, EAA. Triggers: a11y, accessibility, WCAG,…
Creates new specialized agents with frontmatter, tools, delegation. Triggers: new agent,…
Analyzes code quality, complexity, patterns across codebase. Triggers: quality report,…
API design: naming, versioning, pagination, idempotency, OpenAPI, error contracts and safe…