own-mcp-server
by mayo-byte07
README.md
# Own MCP Server
A custom **[Model Context Protocol](https://modelcontextprotocol.io) (MCP) server**, built from scratch in Node.js using the official [`@modelcontextprotocol/sdk`](https://github.com/modelcontextprotocol/typescript-sdk). It runs over stdio and exposes four real, working tools that any MCP-compatible client (Claude Desktop, Claude Code, the MCP Inspector, etc.) can call.
This isn't a toy/hello-world stub — every tool actually does something:
| Tool | What it does |
|---|---|
| `calculate` | Safely evaluates arithmetic expressions (`+ - * /`, parentheses) with a hand-written parser — no `eval()`. |
| `get_current_time` | Returns the current date/time in any IANA timezone (e.g. `Asia/Kolkata`). |
| `get_weather` | Fetches **live** current weather for any place name via the free [Open-Meteo](https://open-meteo.com) API — no API key required. |
| `add_note` / `list_notes` / `delete_note` | A persistent notes store — notes are saved to `data/notes.json` on disk and survive server restarts. |
## Project structure
```
own-mcp-server/
├── src/
│ ├── index.js # Server entry point — registers tools, connects stdio transport
│ └── tools/
│ ├── calculator.js # calculate
│ ├── time.js # get_current_time
│ ├── weather.js # get_weather (live API call)
│ └── notes.js # add_note / list_notes / delete_note (persisted to disk)
├── test/
│ └── test-server.mjs # End-to-end test: spawns the server and drives it with a real MCP client
├── data/
│ └── .gitkeep # notes.json is created here at runtime (gitignored)
├── .github/workflows/test.yml# CI: runs the test suite on every push/PR
├── claude_desktop_config.example.json
├── package.json
├── .gitignore
├── LICENSE
└── README.md
```
## How it works
1. **`McpServer`** from the SDK is instantiated once in `src/index.js`.
2. Each file in `src/tools/` exports a `register*Tool(server)` function that calls `server.registerTool(name, schema, handler)` to add one or more tools.
3. `src/index.js` imports and calls each of those registration functions, then connects the server to a `StdioServerTransport` — this is what lets Claude Desktop / Claude Code talk to it as a subprocess over stdin/stdout.
4. Input validation for every tool is done with [Zod](https://zod.dev) schemas, so malformed calls are rejected with a clear error before your handler code ever runs.
## Requirements
- [Node.js](https://nodejs.org) 18 or newer
- npm
## Setup
```bash
git clone https://github.com/mayo-byte07/OWN-MCP-SERVER.git
cd OWN-MCP-SERVER
npm install
```
## Running it
You normally don't run this directly — an MCP client launches it as a subprocess. But you can smoke-test it standalone:
```bash
npm start
```
You should see `own-mcp-server running on stdio` printed to stderr. The process will then sit waiting for MCP protocol messages on stdin — that's expected; press `Ctrl+C` to stop it.
## Testing it
An automated end-to-end test spawns the real server, connects a real MCP client to it, and calls every tool:
```bash
npm test
```
Expected output includes a listing of all six tools and a successful call to each one (`calculate`, `get_current_time`, `add_note`, `list_notes`, `delete_note`, `get_weather`).
You can also poke at it interactively with the official [MCP Inspector](https://github.com/modelcontextprotocol/inspector):
```bash
npm run inspect
```
This opens a web UI where you can call each tool by hand and see the raw request/response.
## Connecting it to Claude Desktop
1. Open your Claude Desktop config file:
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
2. Add an entry like the one in [`claude_desktop_config.example.json`](./claude_desktop_config.example.json), pointing `args` at the **absolute path** to `src/index.js` on your machine:
```json
{
"mcpServers": {
"own-mcp-server": {
"command": "node",
"args": ["/absolute/path/to/OWN-MCP-SERVER/src/index.js"]
}
}
}
```
3. Restart Claude Desktop. The four tools should now show up under the 🔌 tools icon in a new conversation.
## Connecting it to Claude Code
```bash
claude mcp add own-mcp-server -- node /absolute/path/to/OWN-MCP-SERVER/src/index.js
```
## Extending it
To add a new tool:
1. Create a new file in `src/tools/`, e.g. `src/tools/mytool.js`.
2. Export a function that registers it:
```js
import { z } from "zod";
export function registerMyTool(server) {
server.registerTool(
"my_tool",
{
title: "My Tool",
description: "What it does.",
inputSchema: { someInput: z.string().describe("What this argument is for") },
},
async ({ someInput }) => {
return { content: [{ type: "text", text: `You said: ${someInput}` }] };
}
);
}
```
3. Import and call it in `src/index.js` alongside the others.
4. Add a case for it in `test/test-server.mjs` so CI keeps covering it.
## Why stdio and not HTTP?
Stdio transport is the simplest and most common way to run a *local* MCP server — the client launches your script as a child process and talks to it over stdin/stdout, so there's no port, no auth, and no network exposure to manage. If you need a remote/shared server later, the SDK also supports an HTTP + SSE transport (`StreamableHTTPServerTransport`) — see the [SDK docs](https://github.com/modelcontextprotocol/typescript-sdk) for that setup.
## License
MIT — see [LICENSE](./LICENSE).
TDQS
A4/5.0
Scored across 6 tools
Disambiguation5/5
Each tool has a clearly distinct purpose: arithmetic, time, weather, and note management. There is no overlap or ambiguity between any of the six tools.
Naming Consistency5/5
All tool names follow a consistent lowercase verb-first pattern such as get_weather, add_note, list_notes, and delete_note. The single verb 'calculate' is slightly generic but still fits the naming style.
Tool Count5/5
Six tools is a well-scoped size for a small utility server. Each tool serves a distinct function without excess or redundancy.
Completeness4/5
The note feature covers add, list, and delete, but there is no way to retrieve the full content of a single note or update it. Since notes are simple and list provides metadata, this is a minor gap rather than a critical one.
Maintenance
ActivityMaintained
ResponsivenessNo issues