Introduction
Hi everyone, recently I’ve seen people talking about MCP (Model Context Protocol) everywhere. From AI assistants and tool-calling to extensions, MCP keeps popping up 😐.
Since I’m currently learning it too, I want to share how to build your first MCP server using MCP Framework. After that, we’ll test it with MCP Inspector, then finally add it to an MCP host — in this case, Copilot.
Goals of this article:
- Understand MCP at its core: what it is, what problem it solves, and how its architecture works.
- Build a practical MCP server where, when a user asks for the current gold price, the Agent calls our MCP tool and returns a formatted response.
Implementation steps:
1) Why MCP was created
2) Build an MCP server with MCP Framework
3) Create a GoldPriceTool to fetch gold prices
4) Test/Debug with MCP Inspector
5) Set up Add MCP Server in Visual Studio Code
1) Why MCP was created
Before using MCP servers from large ecosystems (Docker MCP, Figma MCP, Chrome DevTools MCP, ...), we should understand what MCP was designed to solve. Once you truly understand “why MCP exists,” implementation becomes much easier and more reliable.
Before MCP
If each AI Agent (M) wants to connect to each tool/app (N), you must build separate integrations, resulting in a complex $M \times N$ connection matrix.

For example, with 5 AIs and 100 apps, you’d need 5x100 = 500 separate integrations. That’s painful — and whenever a tool changes its integration method, you have to update everything 😫😫
After MCP
Now MCP acts as a shared gateway where AI Agents (M) and tools/apps (N) each connect once, and MCP handles the interoperability layer. We only need $M + N$ connections instead of $M \times N$.
With 5 AIs and 100 apps, you only need 5 + 100 = 105 connections — much easier to manage 😎
MCP Architecture
MCP follows a client-server model. The MCP server exposes APIs for AI Agents to call when they need tools. The MCP server manages tools, receives requests from Agents, executes tools, and returns results.
That’s enough theory — let’s build our first MCP server to fetch gold prices 😁
2) Build an MCP server with MCP Framework
Initialize the project
# install MCP Framework
npm install -g mcp-framework
# create a new project
mcp create my-mcp-server
# enter the project directory
cd my-mcp-server
After installation, the project structure will look like this:
mcp-server-server/
├─ src/
│ ├─ index.ts
│ └─ tools/
│ └─ ExampleTool.ts
├─ dist/
│ ├─ index.js
│ └─ tools/
│ └─ ExampleTool.js
├─ node_modules/
└─ ...
-
src/index.ts: MCP server entry point, whereserver.start()is called. -
src/tools/ExampleTool.ts: sample tool showing thename,schema,executepattern. -
package.json: build/run scripts and project dependencies. -
dist/: compiled code; Inspector/Copilot runs from here.
Let’s edit ExampleTool at:
src/tools/ExampleTool.ts.
import { MCPTool } from "mcp-framework";
import { z } from "zod";
interface ExampleInput {
message: string;
}
class ExampleTool extends MCPTool<ExampleInput> {
name = "example_tool";
description = "An example tool that processes messages";
schema = {
message: {
type: z.string(),
description: "Message to process",
},
};
async execute(input: ExampleInput) {
return `Processed: ${input.message}`;
}
}
export default ExampleTool;
Quick explanation of the code above:
-
MCPTool<ExampleInput>: declares this as an MCP tool and defines the input type. -
name: tool identifier; it appears intools/list. -
schema: defines input data (here,messageas a string). -
execute(...): core logic; receives input and returns output to the client. -
export default: lets the framework auto-load tools fromsrc/tools.
Now we have a basic MCP server with a sample tool. Next, we’ll create a real tool to fetch gold prices.
3) Create GoldPriceTool to fetch gold prices
Create the tool with CLI
mcp add tool GoldPriceTool
The framework will generate the tool file in src/tools/.
Update GoldPriceTool.ts to:
import { MCPTool } from 'mcp-framework'
import { z } from 'zod'
interface Input {
message: string
}
type ApiRes = {
success: boolean
name: string
buy: number
sell: number
change_buy: number
change_sell: number
time: string
date: string
}
class GoldpriceTool extends MCPTool<Input> {
// Tool name shown in MCP Inspector
name = 'GoldpriceTool'
description = 'Get current gold price'
protected useStringify = false
schema = {
message: { type: z.string(), description: 'Input can be any text' },
}
private vnd = (n: number) => `${n.toLocaleString('vi-VN')} ₫`
private trend = (n: number) =>
n > 0
? `up ${this.vnd(n)}`
: n < 0
? `down ${this.vnd(Math.abs(n))}`
: 'no change'
async execute(_input: Input) {
// Call SJC 9999 gold price API
const r = await fetch('https://www.vang.today/api/prices?type=SJL1L10')
if (!r.ok) throw new Error(`HTTP ${r.status}`)
const d = (await r.json()) as ApiRes
if (!d.success) throw new Error('API request failed')
const buyTrendIcon =
d.change_buy > 0 ? '📈' : d.change_buy < 0 ? '📉' : '➖'
const sellTrendIcon =
d.change_sell > 0 ? '📈' : d.change_sell < 0 ? '📉' : '➖'
// Return formatted result
return [
`✨ ${d.name}`,
`💰 Buy price: ${this.vnd(d.buy)}`,
`🏷️ Sell price: ${this.vnd(d.sell)}`,
`${buyTrendIcon} Buy change: ${this.trend(d.change_buy)}`,
`${sellTrendIcon} Sell change: ${this.trend(d.change_sell)}`,
`🕒 Time: ${d.time} ${d.date}`,
].join('\n')
}
protected createErrorResponse(error: Error) {
return {
content: [
{ type: 'text' as const, text: `Error fetching gold price: ${error.message}` },
],
}
}
}
export default GoldpriceTool
After updating the tool, rebuild the project so dist/ has the latest code:
npm run build
Run locally
node dist/index.js
If you see logs like this:
[2026-03-04T14:48:13.579Z] [INFO] Initializing MCP Server: my-mcp-server@0.0.1
[2026-03-04T14:48:13.582Z] [INFO] Starting MCP server: (Framework: 0.2.18, SDK: 1.27.1)...
[2026-03-04T14:48:13.591Z] [INFO] Capabilities detected: {"tools":{}}
[2026-03-04T14:48:13.597Z] [INFO] Connecting transport (stdio) to SDK Server...
[2026-03-04T14:48:13.598Z] [INFO] Started my-mcp-server@0.0.1 successfully on transport stdio
[2026-03-04T14:48:13.598Z] [INFO] Tools (2): example_tool, GoldpriceTool
[2026-03-04T14:48:13.599Z] [INFO] Server running and ready
At this point, you can already call the tool from an AI Agent such as Copilot Chat. But for easier testing and tool inspection, we’ll use MCP Inspector next. 😁
4) Test/Debug with MCP Inspector
Quick intro: this is the official tool from the Model Context Protocol ecosystem (repo modelcontextprotocol/inspector), and it’s very convenient for testing/debugging MCP servers. Inspector provides a UI to call tools, view input/output, track history, and debug errors in real time.
Note: after filling Command and Arguments, click Connect (if the status stays Disconnected, Inspector cannot reach your server yet).
How to run Inspector
There are several ways; the fastest is using the official package:
npx @modelcontextprotocol/inspector
In the Inspector UI, select:
-
Transport:
STDIO -
Command:
node(the project runs on Node.js) -
Arguments: path to
dist/index.js
Example on Windows:
D:/TongHopProject/my-mcp-server/dist/index.js
After a successful connection, click List Tools to verify tools available on the server. If you see GoldpriceTool, this step is done.
Next, test the tool by clicking GoldpriceTool, entering any prompt into message, then clicking Run Tool.

Ta-da, the returned result matches exactly what we designed 😍
Next, we’ll add the server to an MCP Host (here, Copilot Chat) so this tool can be called directly.
5) Set up Add MCP Server in Visual Studio Code
At this step, the fastest way is to add the server directly via Command Palette:
- Press
Ctrl + Shift + P. - Type
> MCP: Add Server.... - Choose
Command (stdio). - In the
Commandfield, enter:node. - Enter a server name, for example:
GoldpriceServer. - Choose either
GlobalorWorkspaceconfig
After these steps, open mcp.json. If saved as global config, it is located at C:\Users\ADMIN\AppData\Roaming\Code\User\mcp.json; if saved as workspace config, it is in your project root. The content should look similar to:
{
"GoldpriceServer": {
"type": "stdio",
"command": "Node",
"args": []
}
}
Here, add the dist/index.js path to args like this:
{
"GoldpriceServer": {
"type": "stdio",
"command": "Node",
"args": ["D:/TongHopProject/my-mcp-server/dist/index.js"]
}
}
Then:
- Reload VS Code window.
- Open Copilot Chat and select any model in Agent mode.
- Enter prompt: “use MCP
GoldpriceToolto return the current gold price, keep the response short.”
Common issues
- Tool returns
Unknown tool→ incorrectnameor server not restarted. -
Invalid tools/call result→ response does not follow MCP content schema. - Extra trailing commas in saved JSON → caused by JSONC formatter; adjust settings if needed.
- After rebuilding, restart Inspector/Copilot session to load latest version.
Conclusion
Now you have the full flow: build MCP server → create tool → test with Inspector → add to mcp.json so Copilot can call it.
No enterprise drama needed — if you can run it, debug it, and understand the request flow, you’re already ahead of many beginners 👏
Contact me
- Facebook: https://www.facebook.com/duc.tai.4869/
- GitHub: https://github.com/ductaiii




Top comments (0)