loading…
Search for a command to run...
loading…
A fully working MCP server built from scratch in plain Node.js, implementing tools, resources, prompts, notifications, and sampling according to the MCP specifi
A fully working MCP server built from scratch in plain Node.js, implementing tools, resources, prompts, notifications, and sampling according to the MCP specification, designed to connect to Claude Desktop or any MCP client.
A learning repository for complete beginners. No frameworks. No black boxes. Pure Node.js.
By the end you will have built a working MCP server you can connect to Claude Desktop - and you will understand every line of it.
Start with 01-what-is-mcp/README.md. That module explains what MCP is, why it exists, and the mental model every later module builds on.
A fully working MCP server in plain Node.js that exposes real tools, follows the protocol exactly, and connects to Claude Desktop (or any MCP client) without modification.
You will build it piece by piece. Each module answers one question. The answer to that question makes the next question obvious.

Module 06 is the tools milestone. Module 09 adds prompts (Desktop / Cursor slash commands). Modules 07–11 complete the protocol. Module 12 connects MCP to agent workflows (custom loop + optional LangChain).
mcp-from-scratch/
├── README.md ← you are here
├── package.json ← { "type": "module" } - that is all
├── images/ ← shared diagrams and screenshots used across modules
├── models/ ← shared GGUF cache reused by modules 11 and 12
│
├── 01-what-is-mcp/
│ ├── README.md
│ └── ANSWERS.md ← optional self-check answers; this module is docs-only
│
├── 02-json-rpc/
│ ├── README.md
│ ├── run.md
│ └── src/
│ ├── jsonrpc.js ← encode and decode messages
│ └── dispatcher.js ← route method calls to handlers
│
├── 03-stdio-transport/
│ ├── README.md
│ ├── run.md
│ └── src/
│ ├── framing.js ← buffer stdin, emit complete messages
│ ├── server.js ← reads from stdin, writes to stdout
│ └── client.js ← spawns server, sends a message, reads reply
│
├── 04-lifecycle/
│ ├── README.md
│ ├── run.md
│ └── src/
│ ├── session.js ← state machine: CREATED → INITIALIZING → READY → CLOSED
│ ├── server.js ← handles initialize, sends initialized notification
│ └── client.js ← sends initialize, waits for handshake to complete
│
├── 05-tools-list/
│ ├── README.md
│ ├── run.md
│ └── src/
│ ├── registry.js ← store tool definitions
│ ├── server.js ← handles tools/list
│ └── client.js ← calls tools/list, prints what it finds
│
├── 06-tools-call/
│ ├── README.md
│ ├── run.md ← pick run-local or run-desktop
│ ├── run-local.md ← full local checklist
│ ├── run-desktop.md ← full Desktop checklist
│ └── src/
│ ├── server.js ← handles tools/call, runs the function, returns result
│ ├── client.js ← calls a tool, prints the result
│ ├── inspector.md ← MCP Inspector (launch, connect, Claude Desktop limits)
│ ├── connect.md ← wire to Claude Desktop (overview)
│ ├── connect-macos.md
│ ├── connect-windows.md
│ └── connect-linux.md
│
├── 07-errors/
│ ├── README.md
│ ├── run.md
│ └── src/
│ ├── errors.js ← JSON-RPC error codes vs isError tool results
│ ├── server.js
│ └── client.js
│
├── 08-resources/
│ ├── README.md
│ ├── run.md
│ └── src/
│ ├── registry.js ← store resource definitions + readers
│ ├── server.js ← handles resources/list and resources/read
│ └── client.js
│
├── 09-prompts/
│ ├── README.md
│ ├── run.md
│ └── src/
│ ├── registry.js ← prompt definitions + resolvers
│ ├── demo-prompts.js ← shared registration for tutorial prompts
│ ├── server.js ← handles prompts/list and prompts/get
│ ├── client.js
│ ├── inspector.md ← MCP Inspector walkthrough
│ ├── connect-prompts.md ← wire prompts to Desktop / Cursor
│ ├── connect-prompts-macos.md
│ ├── connect-prompts-windows.md
│ ├── connect-prompts-linux.md
│ └── connect-cursor.md
│
├── 10-notifications/
│ ├── README.md
│ ├── run.md
│ └── src/
│ ├── server.js ← pushes tools/list_changed + resources/list_changed + resources/updated
│ └── client.js ← listens for server-sent notifications
│
├── 11-sampling/
│ ├── README.md
│ ├── package.json ← node-llama-cpp for the local sampling client
│ ├── run.md
│ └── src/
│ ├── server.js ← sends sampling/createMessage to the client
│ ├── llm.js ← loads GGUF, runs sampling/createMessage
│ └── client.js ← host: local LLM + MCP client
│
└── 12-mcp-and-agents/
├── README.md ← why MCP for agents; LangChain vs custom loop
├── package.json ← node-llama-cpp for the custom local agent loop
├── run.md
├── src/
│ ├── mcp-session.js ← reusable client: handshake, list, call
│ ├── tool-schema.js ← MCP tools → model tool schema
│ ├── llm.js ← local GGUF model via node-llama-cpp
│ └── agent-loop.js ← plan → act → observe demo
└── langchain-example/ ← optional; npm deps (@langchain/mcp-adapters)
├── README.md
├── .env.example
├── package.json
└── agent.mjs
One rule: no npm dependencies in modules 01–10 (and module 11’s server). Every server runs with node src/server.js. The only entry in root package.json is "type": "module" to enable ESM imports. If you find yourself reaching for a package, that is a sign the module needs to teach you what the package was hiding.
Exceptions:
node-llama-cpp (npm install in that folder). The server stays dependency-free.node-llama-cpp (npm install in that folder), while keeping the MCP host logic explicit.Modules 11 and 12 share the repository-level models/ cache, so once one module downloads the GGUF, the other reuses it. On first run, expect roughly 1.5-1.6 GB of model files for the default Qwen GGUF.
Most code modules follow the same three-part pattern:
README.md - opens with the question the module answers, explains the concept plainly, shows the relevant raw JSON, and links to the exact spec section at the bottom. Read this first.
src/ - the implementation. Heavily commented. Every non-obvious decision has a comment explaining why, not just what.
run.md - the exact commands to run, and what you should see when it works. If your output does not match, it tells you what to check.
Two important exceptions:
README.md, then use ANSWERS.md as a self-check.README.md + src/ + run.md pattern.Module 06 uses two self-contained run files: run-local.md or run-desktop.md - pick one at run.md.
You do not need to know anything about protocols, networking, or AI systems. Those concepts will be introduced when they are needed.
git clone https://github.com/pguso/mcp-from-scratch.git
cd mcp-from-scratch
Open 01-what-is-mcp/README.md.
Do not skip ahead. Each module assumes you have run the code in the previous one.
This repository teaches the MCP specification version 2025-11-25. Every module links to the relevant section. Once you finish module 11, you will be able to read the full specification and understand all of it. Module 12 is readable after module 06 if you want to run the agent examples; modules 07–11 are not blockers for that narrative.
The specification lives at: https://modelcontextprotocol.io/specification/2025-11-25
It is not a production MCP SDK. It is not the fastest path to shipping. It is not a collection of examples you copy and modify.
It is a path from zero to genuine understanding. When you finish, you will know what every MCP SDK does under the hood - because you will have done it yourself.
Выполни в терминале:
claude mcp add mcp-from-scratch-server -- npx Безопасность
Низкий рискАвтоматическая эвристика по публичным данным — не гарантия безопасности.