mcp-server-builder
Skill0 starsChanged 25 days agoMITView on GitHub
Use when building or debugging a Model Context Protocol server over stdio for Codex, Claude Code, Cursor, or another MCP client. Covers the JSON-RPC handshake, tools/list and tools/call schemas, error handling, logging, input validation, timeout and size limits, tests, and registration with codex mcp add.
17 other projects use a version of this.
Adopted by
Most recently taken up by
- darkweb19/skillstheir own version, first seen Nov 8, 2026
- Cure-Consulting-Group/ProductEngineeringSkillstheir own version, first seen Nov 4, 2026
- sguys99/mcp-connectorstheir own version, first seen Oct 25, 2026
- techsaurabh-394/claude-skillstheir own version, first seen Oct 25, 2026
- viasrijan/crazy-skillstheir own version, first seen Oct 20, 2026
- shahrukh-hack/vibe-skillstheir own version, first seen Oct 20, 2026
Used with
Projects with it also use agent-designer, env-secrets-manager and 1 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
Arnav-0Skillagent-designer
Use when the user asks to design multi-agent systems, create agent architectures, define agent communication patterns, or build autonomous agent workflows.
Also in 4 projects that use this
Arnav-0Skillenv-secrets-manager
Env & Secrets Manager
Also in 3 projects that use this
JeffallanSkillrag-architect
Designs and implements production-grade RAG systems by chunking documents, generating embeddings, configuring vector stores, building hybrid search pipelines, applying reranking, and evaluating retrieval quality. Use when building RAG systems, vector databases, or knowledge-grounded AI applications requiring semantic search, document retrieval, context augmentation, similarity search, or embedding-based indexing.
Also in 3 projects that use this
Other versions17 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 17
- OneWave-AI/claude-skills★ 378same name
- timothywarner-org/context-engineering★ 27same name
- Hassaan146/claude-skills★ 18same name
- yeaight7/agent-powerups★ 6same name
- Cure-Consulting-Group/ProductEngineeringSkills★ 3same name
- techsaurabh-394/claude-skills★ 3same name
- csiddhant796-blip/claude-skills-collection★ 2same name
- Hussain-Elfalah/Agentic-Skills★ 2same name
- codecharmhq/claude-code-skills★ 1same name
- DROOdotFOO/agent-skills★ 1same name
7 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository18 other files it gives its agents.
- docs/agents.mdAGENTS.md
- agent-skill-authorSkill
- api-contract-reviewSkill
- codex-cli-workflowsSkill
- codex-plugin-authorSkill
- context-budgetSkill
- dependency-auditSkill
- docs-writerSkill
- git-recoverySkill
- incident-postmortemSkill
- performance-profileSkill
- pr-reviewerSkill
- release-engineerSkill
- repo-onboardingSkill
- skill-security-reviewSkill
- sql-migration-reviewSkill
- terminal-debuggerSkill
- test-first-fixSkill
The file
We split this skill into the rules it gives an agent
11 rules. 0 are common, 7 are distinctive, and 4 are very specific to this project.
0
Common
Most of the 13 edited versions we read keep these.
7
Distinctive
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 22
Use this skill when:
- Very specific: line 64
Every request with an id gets exactly one response with the same id.
- Very specific: line 66
Write one JSON object per line, terminated by \n.
- Distinctive: line 67
Never write logs, banners, or progress to stdout.
- Distinctive: line 81
Do not expose twenty endpoints because the underlying API has twenty.
- Very specific: line 99
Use enum for fixed choices.
- Distinctive: line 100
Do not accept a free-form shell command when a structured argument works.
- Distinctive: line 201
Test malformed input and unknown tools too.
- Very specific: line 217
Never put a token in the command line where it appears in process listings or shell history.
- Distinctive: line 237
Never pass an argument to a shell.
- Distinctive: line 239
Keep credentials in the environment, never in tool output.
“Common” is measured: kept by at least 6 in 10 of the 13 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
MCP Server Builder
An MCP server is a process that exposes tools, resources, or prompts to an agent over JSON-RPC. The stdio transport is newline-delimited JSON: one message per line, no headers, no extra output.
Almost every broken server fails on one of four things: it prints logs to stdout, it never answers initialize, its tool schema does not match its arguments, or it throws instead of returning a tool error.
When to use
Use this skill when:
- You need to expose a local API, database, or file operation to an agent.
- A registered MCP server shows no tools.
- A tool call hangs, returns an invalid response, or crashes the client.
- You are reviewing an MCP server for security.
- You are packaging a server inside a Codex plugin.
Minimal protocol
The client starts the process and sends:
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"client","version":"1.0.0"}}}The server replies with its capabilities and server info. The client then sends:
{"jsonrpc":"2.0","method":"notifications/initialized"}Tool discovery:
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}Tool call:
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"echo","arguments":{"text":"hi"}}}Response:
{"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text","text":"hi"}]}}Rules:
- Every request with an
idgets exactly one response with the sameid. - Notifications have no
idand get no response. - Write one JSON object per line, terminated by
\n. - Never write logs, banners, or progress to stdout.
- Protocol errors use JSON-RPC error codes. Tool failures use
result.isErrorwith content, so the model can read the failure.
Workflow
1. Decide the tool surface
A good tool is:
- Named as a verb and a noun:
search_issues,read_file,create_invoice. - Described in one sentence that states when to use it.
- Narrow enough that its arguments are obvious.
- Safe by default: read-only unless a write is the point.
Do not expose twenty endpoints because the underlying API has twenty. Expose the five operations an agent needs, with clear names.
2. Define input schemas
{
"type": "object",
"additionalProperties": false,
"required": ["query"],
"properties": {
"query": { "type": "string", "minLength": 1, "maxLength": 500 },
"limit": { "type": "integer", "minimum": 1, "maximum": 50, "default": 10 }
}
}- Set
additionalProperties: false. - Bound strings, numbers, and array lengths.
- Use
enumfor fixed choices. - Do not accept a free-form shell command when a structured argument works.
- Validate again at runtime. The client may not enforce the schema.
3. Implement the loop
import readline from 'node:readline';
const send = (message) => process.stdout.write(`${JSON.stringify(message)}\n`);
const text = (value) => ({ content: [{ type: 'text', text: String(value) }] });
const tools = [
{
name: 'echo',
description: 'Return the input text. Use to test connectivity.',
inputSchema: {
type: 'object',
additionalProperties: false,
required: ['text'],
properties: { text: { type: 'string', maxLength: 1000 } },
},
},
];
const rl = readline.createInterface({ input: process.stdin, crlfDelay: Infinity });
rl.on('line', async (line) => {
if (!line.trim()) return;
let request;
try {
request = JSON.parse(line);
} catch {
send({ jsonrpc: '2.0', id: null, error: { code: -32700, message: 'Parse error' } });
return;
}
if (request.method === 'initialize') {
send({
jsonrpc: '2.0',
id: request.id,
result: {
protocolVersion: request.params?.protocolVersion ?? '2025-06-18',
capabilities: { tools: {} },
serverInfo: { name: 'echo-server', version: '1.0.0' },
},
});
return;
}
if (request.method === 'notifications/initialized') return;
if (request.method === 'tools/list') {
send({ jsonrpc: '2.0', id: request.id, result: { tools } });
return;
}
if (request.method === 'tools/call') {
const { name, arguments: args = {} } = request.params ?? {};
try {
if (name === 'echo') {
if (typeof args.text !== 'string') throw new Error('text must be a string');
send({ jsonrpc: '2.0', id: request.id, result: text(args.text) });
} else {
send({ jsonrpc: '2.0', id: request.id, error: { code: -32602, message: `Unknown tool: ${name}` } });
}
} catch (error) {
send({
jsonrpc: '2.0',
id: request.id,
result: { isError: true, content: [{ type: 'text', text: error.message }] },
});
}
return;
}
if (request.method === 'ping') {
send({ jsonrpc: '2.0', id: request.id, result: {} });
return;
}
if (request.id !== undefined) {
send({ jsonrpc: '2.0', id: request.id, error: { code: -32601, message: 'Method not found' } });
}
});
console.error('echo-server ready'); // stderr only4. Test without a client
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
'{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"echo","arguments":{"text":"hi"}}}' \
| node server.mjsExpected: four lines of JSON, no extra text. The notification produces no response, so three responses plus silence.
Test malformed input and unknown tools too. A server that crashes on bad JSON will take down the session.
5. Register with Codex
codex mcp add echo -- node /absolute/path/server.mjs
codex mcp list
codex mcp get echoFor an HTTP server:
codex mcp add remote --url https://example.com/mcpNever put a token in the command line where it appears in process listings or shell history. Use --env or the server's own environment.
6. Handle failure modes
| Failure | Response |
| Invalid JSON | JSON-RPC -32700, keep serving |
| Unknown method | -32601 |
| Invalid arguments | -32602 or isError with a readable message |
| Tool exception | result.isError with content |
| Timeout | Abort the work, return isError, do not hang forever |
| Oversized input | Reject before parsing |
| Upstream 5xx | Return a short error with retry guidance |
| Client disconnects | Stop work, exit cleanly |
Set timeouts on every network call. Cap response size. Stream only if the client supports it.
Security
- Validate every argument. The model can send anything.
- Never pass an argument to a shell. Use an argument array.
- Restrict file paths to an allowed root.
- Keep credentials in the environment, never in tool output.
- Make read-only tools read-only at the implementation level, not only in the description.
- For destructive tools, require an explicit confirmation argument and return a dry-run result first.
- Rate-limit expensive tools.
- Log to stderr with secrets redacted.
Common failures
| Symptom | Cause | Fix |
| Client shows zero tools | tools/list missing or wrong shape | Return { tools: [...] } |
| Connection closes immediately | Printed to stdout before the handshake | Remove all stdout logging |
| Tool call hangs | No response sent on that path | Ensure every request id gets a response |
Invalid arguments | Schema and runtime disagree | Compare inputSchema with the handler |
| Works in curl, not in client | Newline framing or buffering | Flush after each message, one per line |
| Random crashes | Unhandled promise rejection | Catch per request |
Verification checklist
- Handshake works with a raw stdin test.
tools/listdescribes every tool with a bounded schema.- Every tool call returns a response, including errors.
- Invalid JSON does not kill the process.
- Logs go to stderr only.
- Timeouts and size limits exist.
- Arguments are validated at runtime.
- File paths and shell arguments are contained.
- Registration with
codex mcp addworks andcodex mcp listshows it. - A real agent can call each tool.
References
references/protocol.mdcontains message examples, error codes, and a tool schema checklist.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

