MCP-Server
README.md
# MCP Server with Management UI
A production-ready [Model Context Protocol](https://modelcontextprotocol.io) server built with TypeScript, featuring:
- **6 built-in tools** – file read/write/list, HTTP fetch, system info, and env variable reader
- **Dual transport** – stdio (Claude Desktop) and SSE/HTTP (Claude.ai)
- **Management Dashboard** – live tool list, interactive tool tester, and request log
- **Extensible** – add new tools in minutes
---
## Prerequisites
- [Node.js](https://nodejs.org) v18 or higher (`node --version` to check)
- [Claude Desktop](https://claude.ai/download) (for local MCP integration)
---
## Quick Start
### 1 · Install dependencies
```bash
npm run install:all
```
Installs both server and UI packages.
### 2 · Configure environment
```bash
# Windows
copy .env.example .env
# macOS / Linux
cp .env.example .env
```
Edit `.env` to set `PORT`, `SERVER_NAME`, or any API keys you need.
### 3 · Development mode (hot-reload)
Open **two terminals**:
```bash
# Terminal 1 – backend server with hot-reload
npm run dev
# Terminal 2 – UI dev server (proxies API calls to the backend)
cd ui && npm run dev
```
- Backend API + SSE: `http://localhost:3000`
- Management UI (dev): `http://localhost:5173/ui`
### 4 · Production build
```bash
npm run build # compiles TypeScript + builds React UI
npm start # starts everything on :3000
```
Open `http://localhost:3000/ui` in your browser.
---
## Connecting to Claude Desktop (stdio)
Claude Desktop launches the server as a child process automatically — no running server needed.
### Step 1 — Build the server
```bash
npm run build
```
### Step 2 — Find the correct config file location
The location depends on how Claude Desktop was installed:
| Installation type | Config path |
|---|---|
| **Windows Store / MSIX** | `%LOCALAPPDATA%\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\claude_desktop_config.json` |
| **Windows direct installer** | `%APPDATA%\Claude\claude_desktop_config.json` |
| **macOS** | `~/Library/Application Support/Claude/claude_desktop_config.json` |
> **Tip (Windows):** Run this in PowerShell to find the right file automatically:
> ```powershell
> Get-ChildItem "$env:LOCALAPPDATA" -Recurse -Filter "claude_desktop_config.json" -ErrorAction SilentlyContinue
> Get-ChildItem "$env:APPDATA" -Recurse -Filter "claude_desktop_config.json" -ErrorAction SilentlyContinue
> ```
### Step 3 — Write the config
Replace `YOU` and `C:/path/to` with your actual username and project path.
```json
{
"mcpServers": {
"mcp-server": {
"command": "node",
"args": ["C:/Users/YOU/Projects/mcp-server/dist/index.js", "--stdio"]
}
}
}
```
> **Windows tip:** If `node` isn't found by Claude Desktop, use the full path instead:
> ```powershell
> (Get-Command node).Source # prints e.g. C:\Program Files\nodejs\node.exe
> ```
> Then set `"command": "C:/Program Files/nodejs/node.exe"`.
### Step 4 — Restart Claude Desktop
- Fully quit Claude Desktop (right-click tray icon → **Quit**, don't just close the window)
- Reopen it from the Start Menu / Applications
- Open a new chat and ask: *"What tools do you have available?"*
Claude will list all 6 tools automatically — no connect button required.
---
## Connecting to Claude.ai (SSE)
Claude.ai's custom connector requires a publicly accessible **HTTPS** URL.
### Step 1 — Start the server
```bash
npm start
```
### Step 2 — Expose it with a tunnel
```bash
# Using ngrok (https://ngrok.com)
ngrok http 3000
# Copy the https://xxxx.ngrok-free.app URL
```
Alternatives: [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/), [localtunnel](https://github.com/localtunnel/localtunnel)
### Step 3 — Add the connector in Claude.ai
In Claude Desktop or Claude.ai:
- Click **+** → **Connectors** → **Add custom connector**
- **Name**: `mcp-server`
- **URL**: `https://xxxx.ngrok-free.app/sse`
---
## Available Tools
| Tool | Description |
|---|---|
| `read_file` | Read a file's contents (utf-8 or base64) |
| `write_file` | Write / append text to a file |
| `list_directory` | List files in a directory (optionally recursive) |
| `fetch_url` | Make HTTP requests (GET, POST, PUT, DELETE, PATCH) |
| `get_system_info` | OS, CPU, memory, network, and process details |
| `get_environment_variable` | Read environment variables from the server process |
---
## Adding New Tools
All tools live in `src/tools/`. Create a new file, export a `register*Tools` function, and call it from `src/server.ts`.
**Example – add a calculator tool:**
```typescript
// src/tools/calculator.ts
import { z } from 'zod';
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { registerTool } from './registry.js';
export function registerCalculatorTools(server: McpServer): void {
registerTool(
server,
'calculate',
'Evaluate a simple arithmetic expression and return the result.',
{
expression: z.string().describe('Arithmetic expression, e.g. "2 + 2 * 10"'),
},
async ({ expression }) => {
const result = Function(`"use strict"; return (${expression})`)();
return { content: [{ type: 'text' as const, text: String(result) }] };
},
);
}
```
Then in `src/server.ts`:
```typescript
import { registerCalculatorTools } from './tools/calculator.js';
// inside createMcpServer():
registerCalculatorTools(server);
```
The new tool appears in the Management UI and is immediately available to Claude.
---
## Project Structure
```
mcp-server/
├── src/
│ ├── index.ts # Entry point – detects --stdio vs HTTP mode
│ ├── server.ts # McpServer factory, registers all tools
│ ├── web.ts # Express server (SSE transport + REST API for UI)
│ ├── logger.ts # Circular in-memory request log (200 entries)
│ ├── types.ts # Shared TypeScript types
│ └── tools/
│ ├── registry.ts # registerTool() wrapper + direct invocation map
│ ├── file.ts # read_file, write_file, list_directory
│ ├── fetch.ts # fetch_url
│ └── system.ts # get_system_info, get_environment_variable
├── ui/
│ ├── src/
│ │ ├── App.tsx # Tabbed layout (Tools / Tester / Logs)
│ │ ├── api.ts # REST client for the management API
│ │ └── components/
│ │ ├── ServerStatus.tsx # Live uptime, port, request count
│ │ ├── ToolList.tsx # Expandable list with JSON schemas
│ │ ├── ToolTester.tsx # Select tool → edit JSON → invoke
│ │ └── RequestLog.tsx # Auto-refreshing log with expand
│ └── vite.config.ts
├── dist/ # Compiled server output (after npm run build)
├── .env # Local config – not committed
├── .env.example # Template for .env
├── claude_desktop_config.json # Example config snippet
├── package.json
└── tsconfig.json
```
---
## Scripts
| Command | Description |
|---|---|
| `npm run dev` | Run server with hot-reload (tsx watch) |
| `npm run dev:stdio` | Run in stdio mode for Claude Desktop testing |
| `npm run build` | Compile TypeScript + build React UI |
| `npm start` | Run compiled server (HTTP/SSE + UI mode) |
| `npm run start:stdio` | Run compiled server in stdio mode |
| `npm run install:all` | Install all dependencies (server + UI) |
| `npm run setup` | Full first-time setup: install + build |
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues