MCP Hub
Back to servers

octo-mcp-server

A production-ready MCP server built with Node.js and Express that supports remote deployment via HTTP and SSE. It provides a modular framework for building and scaling tools while serving multiple clients concurrently.

glama
Updated
Mar 19, 2026

octo-mcp-server

A production-ready Model Context Protocol (MCP) server built with Node.js, TypeScript, and Express. It uses HTTP + SSE (Server-Sent Events) as the transport so it can be deployed remotely and serve multiple clients concurrently.

Project structure

src/
  index.ts        # Entry point — creates Express app, mounts /sse and /message routes
  server.ts       # MCP server factory, session registry, message routing
  tools/
    echo.ts       # Example tool: returns its input unchanged
Dockerfile
tsconfig.json
package.json
.env.example

Adding a new tool

  1. Create src/tools/my-tool.ts and export a registerMyTool(server: McpServer) function:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import * as z from 'zod/v4';

export function registerMyTool(server: McpServer): void {
  server.tool(
    'my-tool',
    'Description shown to the LLM',
    { input: z.string() },
    async ({ input }) => ({
      content: [{ type: 'text', text: `Result: ${input}` }],
    }),
  );
}
  1. Import and call it in src/server.ts:
import { registerMyTool } from './tools/my-tool.js';
// inside createMcpServer:
registerMyTool(server);

That's it.

Local development

Prerequisites

  • Node.js ≥ 18
  • npm

Setup

cp .env.example .env          # edit PORT or add API keys as needed
npm install
npm run build
npm start

The server starts on http://localhost:3000 (or whatever PORT is set to).

Verify with curl

# Health check
curl http://localhost:3000/health

# Open an SSE stream (keep this terminal open)
curl -N http://localhost:3000/sse
# You will see: event: endpoint\ndata: /message?sessionId=<ID>

# In another terminal, call the echo tool (replace <SESSION_ID>)
curl -X POST "http://localhost:3000/message?sessionId=<SESSION_ID>" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "echo",
      "arguments": { "message": "hello world" }
    }
  }'

Available npm scripts

ScriptDescription
npm run buildCompile TypeScript → dist/
npm startRun the compiled server
npm run devRun with ts-node (no compile)
npm run cleanDelete dist/

Docker

# Build
docker build -t octo-mcp-server .

# Run (pass environment variables with -e or --env-file)
docker run -p 3000:3000 --env-file .env octo-mcp-server

Deploy to Azure Web App

Option A — Deploy a Docker container (recommended)

  1. Push your image to a container registry (Azure Container Registry, Docker Hub, etc.):
az acr build --registry <your-registry> --image octo-mcp-server:latest .
  1. Create the Web App (Linux, Docker):
az group create --name rg-octo-mcp --location eastus

az appservice plan create \
  --name plan-octo-mcp \
  --resource-group rg-octo-mcp \
  --is-linux \
  --sku B1

az webapp create \
  --name octo-mcp-server \
  --resource-group rg-octo-mcp \
  --plan plan-octo-mcp \
  --deployment-container-image-name <your-registry>.azurecr.io/octo-mcp-server:latest
  1. Set environment variables:
az webapp config appsettings set \
  --name octo-mcp-server \
  --resource-group rg-octo-mcp \
  --settings PORT=3000 MY_API_KEY=...
  1. Enable Always On so the server stays warm:
az webapp config set \
  --name octo-mcp-server \
  --resource-group rg-octo-mcp \
  --always-on true

SSE note: Azure App Service by default has a 230-second idle request timeout. For long-lived SSE connections you may need to send keep-alive comments or configure the timeout via az webapp config set --http20-enabled true.

Option B — Deploy from source with Oryx build

  1. Zip the source (exclude node_modules and dist):
zip -r deploy.zip . --exclude "node_modules/*" "dist/*" ".git/*"
  1. Deploy:
az webapp deployment source config-zip \
  --name octo-mcp-server \
  --resource-group rg-octo-mcp \
  --src deploy.zip

Azure will run npm install && npm run build && npm start automatically via the Oryx build system.

Environment variables

VariableDefaultDescription
PORT3000TCP port the server listens on

Add any tool-specific secrets (API keys, connection strings) here as well.

API endpoints

MethodPathDescription
GET/healthReturns {"status":"ok","timestamp":"…"}
GET/sseOpens an SSE stream; emits the POST endpoint + session ID
POST/messageReceives JSON-RPC 2.0 messages (?sessionId=<id>)

Reviews

No reviews yet

Sign in to write a review