r-werner/simple-mcp-js
If you are the rightful owner of simple-mcp-js and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
This document provides a comprehensive overview of a simple Model Context Protocol (MCP) server implemented using the official MCP SDK, featuring Server-Sent Events (SSE) for communication and dynamic JavaScript tool loading.
Simple MCP Server over SSE
A minimal Model Context Protocol (MCP) server using the official @modelcontextprotocol/sdk. Communicates via Server-Sent Events (SSE) and dynamically loads JavaScript tools from a tools/ folder.
Features
- Official MCP SDK - Uses
@modelcontextprotocol/sdkfor guaranteed protocol compliance - TypeScript server - Full type safety with
src/server.ts - JavaScript tools - No compilation required for tools
- JSDoc-based schemas - Automatic schema generation from comments
- SSE transport - Compatible with Langflow and MCP Inspector
- Per-connection isolation - Each client gets a unique session
- Hot reload - Automatic server restart on code changes (dev mode)
Quick Start
-
Install dependencies:
npm install -
Start development server:
npm run dev -
Server is ready at:
- URL:
http://localhost:7861 - SSE endpoint:
http://localhost:7861/mcp/sse
- URL:
Project Structure
simple-mcp-js/
├── src/
│ └── server.ts # Main server (TypeScript, uses official SDK)
├── tools/
│ └── adder.js # Example tool (JavaScript)
├── package.json
├── tsconfig.json
└── README.md
Note: No dist/ folder - server runs directly via tsx for faster iteration.
Creating Tools
Tools are written in pure JavaScript with JSDoc comments. Create a new file in tools/:
/**
* Multiplies two numbers together.
* @mcp.title "Number Multiplier"
* @param {number} x - First number
* @param {number} y - Second number
* @returns {number} The product
*/
export function multiplier(args) {
return args.x * args.y;
}
Restart the server to reload tools (or use npm run dev for auto-restart).
How It Works
Server Architecture
The server uses the official MCP SDK pattern:
-
Tool Loading (src/server.ts:130-146)
- Scans
tools/directory at startup - Parses JSDoc comments to extract metadata
- Dynamically imports JavaScript functions
- Scans
-
Server Creation (src/server.ts:178-219)
- Creates
McpServerinstance from official SDK - Registers tools using
server.tool()method - Converts JSDoc schemas to Zod for validation
- Creates
-
SSE Transport (src/server.ts:229-260)
- Uses
SSEServerTransportfrom SDK - Each connection gets a unique UUID session
- Handles connection lifecycle automatically
- Uses
Session Management
- Client connects to
GET /mcp/sse - SDK generates session UUID (e.g.,
3a9cb941-2313-4777-aac9-250c485de7d2) - Client sends messages to
POST /mcp/sse/message?sessionId=<uuid> - Transport routes messages to correct MCP server instance
Langflow Integration
- In Langflow, add an MCP Tools component
- Select SSE as the transport type
- Set URL to:
http://localhost:7861/mcp/sse - Langflow will automatically handle session routing
- Test by calling tools like
adderwith{"a": 2, "b": 3}
MCP Inspector Integration
Test the server with the official MCP Inspector:
npx @modelcontextprotocol/inspector
When prompted, enter:
- Transport: SSE
- URL:
http://localhost:7861/mcp/sse
The inspector will show:
- ✅ Available tools (
tools/list) - ✅ Tool execution (
tools/call) - ✅ Connection status
API Endpoints
GET /mcp/sse
Opens SSE stream for MCP communication.
Response:
- Stream of Server-Sent Events
- Includes
endpointevent with message POST URL
POST /mcp/sse/message?sessionId=<uuid>
Receives JSON-RPC requests from the client.
Request body:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}
Supported methods:
initialize- MCP handshaketools/list- Get available toolstools/call- Execute a tool
Supported JSDoc Tags
| JSDoc Tag | Purpose | Example |
|---|---|---|
| Description | Tool description | Adds two numbers |
@mcp.title | Custom tool title | @mcp.title "Number Adder" |
@param {type} name | Required parameter | @param {number} a - First number |
@param {type} [name] | Optional parameter | @param {string} [prefix] |
@returns {type} | Return type | @returns {number} |
Supported types: string, number, boolean
Testing with curl
Terminal 1 - Open SSE stream:
curl -N "http://localhost:7861/mcp/sse"
You'll see the endpoint event with the POST URL.
Terminal 2 - List tools:
curl -X POST "http://localhost:7861/mcp/sse/message?sessionId=<uuid-from-endpoint>" \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Terminal 2 - Call a tool:
curl -X POST "http://localhost:7861/mcp/sse/message?sessionId=<uuid-from-endpoint>" \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"adder","arguments":{"a":2,"b":3}}}'
Watch Terminal 1 for JSON-RPC responses via SSE.
Development
Running the Server
-
Development mode (auto-restart on changes):
npm run dev -
Direct execution (no auto-restart):
tsx src/server.ts
Adding/Editing Tools
- Create or edit a
.jsfile intools/ - Add JSDoc comments
- Export a function with the same name as the file
- Server auto-restarts (in dev mode) or manually restart
Server Logs
The server provides detailed logging:
🚀 MCP Server with Official SDK
🌐 Server listening on http://localhost:7861
📡 SSE endpoint: http://localhost:7861/mcp/sse
✅ Loaded 1 tool:
- adder(a, b): Adds two numbers and returns the sum.
📡 SSE connection request from ::1
✅ Client connected (session: 3a9cb941-2313-4777-aac9-250c485de7d2)
📥 Message from session 3a9cb941-...: initialize
📥 Message from session 3a9cb941-...: tools/list
Implementation Notes
Why Official SDK?
This implementation uses the official @modelcontextprotocol/sdk because:
- ✅ Guaranteed protocol compliance - No manual SSE event formatting
- ✅ Battle-tested - Used by all official MCP implementations
- ✅ Future-proof - Automatically updated with protocol changes
- ✅ Simpler code - ~75 fewer lines than custom implementation
Why TypeScript Server + JavaScript Tools?
- Server in TypeScript: Type safety for complex protocol handling
- Tools in JavaScript: No build step when adding/editing tools
Port Configuration
Server runs on port 7861 by default. Change via environment variable:
PORT=8080 npm run dev
Dependencies
Runtime:
express- HTTP server framework@modelcontextprotocol/sdk- Official MCP implementationcomment-parser- Extract JSDoc metadatazod- Schema validation (required by SDK)
Development:
typescript- Type checkingtsx- Fast TypeScript executionnodemon- Auto-restart on file changes@types/*- TypeScript definitions
Troubleshooting
"Port already in use"
Kill existing processes:
killall -9 node nodemon tsx
"Tool not found"
Check server logs on startup - tools must:
- Be in
tools/directory - Have
.jsextension - Export a function
- Have valid JSDoc comment as first block
"Session not found"
Make sure to use the sessionId from the endpoint event in the POST URL.
Resources
- Official MCP SDK: https://github.com/modelcontextprotocol/typescript-sdk
- MCP Specification: https://modelcontextprotocol.io/
License
MIT