simple-mcp-js

r-werner/simple-mcp-js

3.2

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.

Tools
1
Resources
0
Prompts
0

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/sdk for 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

  1. Install dependencies:

    npm install
    
  2. Start development server:

    npm run dev
    
  3. Server is ready at:

    • URL: http://localhost:7861
    • SSE endpoint: http://localhost:7861/mcp/sse

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:

  1. Tool Loading (src/server.ts:130-146)

    • Scans tools/ directory at startup
    • Parses JSDoc comments to extract metadata
    • Dynamically imports JavaScript functions
  2. Server Creation (src/server.ts:178-219)

    • Creates McpServer instance from official SDK
    • Registers tools using server.tool() method
    • Converts JSDoc schemas to Zod for validation
  3. SSE Transport (src/server.ts:229-260)

    • Uses SSEServerTransport from SDK
    • Each connection gets a unique UUID session
    • Handles connection lifecycle automatically

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

  1. In Langflow, add an MCP Tools component
  2. Select SSE as the transport type
  3. Set URL to: http://localhost:7861/mcp/sse
  4. Langflow will automatically handle session routing
  5. Test by calling tools like adder with {"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 endpoint event 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 handshake
  • tools/list - Get available tools
  • tools/call - Execute a tool

Supported JSDoc Tags

JSDoc TagPurposeExample
DescriptionTool descriptionAdds two numbers
@mcp.titleCustom tool title@mcp.title "Number Adder"
@param {type} nameRequired 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

  1. Create or edit a .js file in tools/
  2. Add JSDoc comments
  3. Export a function with the same name as the file
  4. 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 implementation
  • comment-parser - Extract JSDoc metadata
  • zod - Schema validation (required by SDK)

Development:

  • typescript - Type checking
  • tsx - Fast TypeScript execution
  • nodemon - 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 .js extension
  • 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

License

MIT