Skip to main content
Glama
VelixirNET

template-mcp-server

by VelixirNET

Remote MCP server

Deploy on velixir

Your own Model Context Protocol server on a public HTTPS URL, so Claude Code, Cursor, VS Code and other MCP clients can call tools you write. TypeScript on the official SDK, served over Streamable HTTP, with a secret token in front.

Deploy it on velixir, then set one secret and redeploy to switch it on.

What it shows

  • The current transport. Streamable HTTP in stateless mode, on the official @modelcontextprotocol/sdk 1.x. Every request is answered on its own, so the server runs on the Free plan, survives restarts and redeploys without breaking clients, and scales to more than one replica.

  • All three MCP primitives. Four tools (roll_dice, current_time, text_stats, generate_uuid), a resource (time://zones) and a prompt (plan_meeting), each with typed inputs, and the tools with structured output.

  • Safe example tools. None of them makes a network request, touches the filesystem or runs a command, so nothing a model sends them can reach anything else.

  • Bearer-token auth. Clients send Authorization: Bearer <MCP_AUTH_TOKEN>, compared in constant time. Until the token is set, /mcp answers 503 and the home page explains what to do, while /healthz stays green.

  • A landing page with copy-paste setup. It shows the endpoint and the configuration for each client below. It never shows the token.

  • Logs you can read. One line per MCP request, such as POST /mcp 200 4ms tools/call roll_dice, and never the body or the token.

Related MCP server: Python MCP Server Kit

Setting it up on velixir

  1. Deploy it from the gallery, or your own copy with velixir deploy.

  2. Generate a token: openssl rand -hex 32, or 32 or more random characters from a password manager. Tokens shorter than 16 characters are refused.

  3. On the app's Environment tab, set MCP_AUTH_TOKEN to the token and tick Treat as secret.

  4. Redeploy, with the Redeploy button on the live release in the Deploys tab.

  5. Open the app's URL. The page shows your endpoint, https://<your-app>.velixir.run/mcp, and the client configuration with your address filled in.

On a custom domain, set PUBLIC_URL (for example https://mcp.example.com) so the page shows that address instead.

Connecting a client

Replace the URL with your endpoint and YOUR_TOKEN with the token you set.

Claude Code

claude mcp add --transport http velixir https://your-app.velixir.run/mcp \
  --header "Authorization: Bearer YOUR_TOKEN"

That adds it for the current project, visible only to you; add --scope user to have it in every project. /mcp inside Claude Code shows whether it connected. To share the server with your team in a committed .mcp.json, keep the token out of the file: Claude Code expands environment variables there.

{
  "mcpServers": {
    "velixir": {
      "type": "http",
      "url": "https://your-app.velixir.run/mcp",
      "headers": { "Authorization": "Bearer ${MCP_AUTH_TOKEN}" }
    }
  }
}

Cursor

In ~/.cursor/mcp.json for every project, or .cursor/mcp.json for one:

{
  "mcpServers": {
    "velixir": {
      "url": "https://your-app.velixir.run/mcp",
      "headers": { "Authorization": "Bearer ${env:MCP_AUTH_TOKEN}" }
    }
  }
}

${env:MCP_AUTH_TOKEN} reads the token from the environment Cursor was started in.

VS Code

In .vscode/mcp.json, or through MCP: Open User Configuration for every workspace. VS Code asks for the token the first time and stores it securely:

{
  "inputs": [
    { "type": "promptString", "id": "mcp-token", "description": "MCP_AUTH_TOKEN", "password": true }
  ],
  "servers": {
    "velixir": {
      "type": "http",
      "url": "https://your-app.velixir.run/mcp",
      "headers": { "Authorization": "Bearer ${input:mcp-token}" }
    }
  }
}

Codex CLI

In ~/.codex/config.toml, with the token in the MCP_AUTH_TOKEN environment variable:

[mcp_servers.velixir]
url = "https://your-app.velixir.run/mcp"
bearer_token_env_var = "MCP_AUTH_TOKEN"

Clients that only support OAuth

Some clients cannot send a fixed token to a remote server, so they cannot use this one as it stands:

  • Claude on the web, desktop and mobile (custom connectors) supports OAuth or no authentication. Sending a fixed token in a header is a beta open to a limited set of organisations, set up by an organisation Owner. The desktop app's own config file only runs local servers.

  • ChatGPT (developer mode and apps) supports OAuth, no authentication, or a mix of the two.

Connecting those means adding OAuth to the server, which this template does not do.

Running it locally

npm install
npm run build
MCP_AUTH_TOKEN=local-dev-token-change-me npm start

Then open http://localhost:8080, and point a client at http://localhost:8080/mcp. Or call a tool with curl:

curl http://localhost:8080/mcp \
  -H "Authorization: Bearer local-dev-token-change-me" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"roll_dice","arguments":{"notation":"2d6"}}}'

The Accept header is required: the Streamable HTTP spec has clients accept both JSON and event streams, and the SDK answers 406 without it.

Adding your own tools

Tools, the resource and the prompt live in src/mcp.ts. A new tool is one registerTool call with a description, a zod schema for its input and an async function that returns its result. The landing page lists whatever the server serves, so it stays accurate as you change it.

Keep the bar the examples set. A tool runs with arguments a model wrote, so one that fetches a URL, reads a path or runs a command needs strict limits before it goes on a public endpoint. On velixir, apps can reach the web (ports 80 and 443) and nothing else.

Deploying

velixir deploy

Things to know

Stateless means no server-to-client messages. Every POST is answered with one JSON body. There are no progress notifications, no mid-call questions to the user or the model (sampling, elicitation) and no list-changed notifications, and GET /mcp answers 405, which tells clients to carry on without a stream. That suits tools that answer at once. Long-running tools that report progress need the SDK's stateful mode and a plan that does not sleep.

The Free plan sleeps. After 15 idle minutes the app stops, and the next request wakes it. The server itself starts in under a second, but that first call waits for the wake-up, so expect it to be noticeably slower than the rest. Pick a paid plan if that matters to you.

It fits the smallest plan with room to spare. Capped at 256 MB, it measured about 30 MB idle and peaked under 50 MB under light load (thousands of calls, up to 25 at once).

One token for everyone. Anyone holding the token can call every tool, and the server cannot tell clients apart. To rotate it, set a new MCP_AUTH_TOKEN, redeploy, and update every client. Per-user access needs OAuth.

"Needs authentication" means the token is wrong. A missing or wrong token gets a 401, and some clients read that as a cue to start an OAuth sign-in, which this server does not offer. Check the Authorization header the client sends, and the app log, which records each 401.

No rate limiting. A client with the token can call as fast as it likes. Add a limit before you add a tool that is expensive to run.

Browser-based clients are refused. Requests carrying a foreign Origin header get a 403, as the MCP spec asks, and the server sends no CORS headers. Desktop, editor and command-line clients send no Origin and are unaffected.

The start command lives in nixpacks.toml. It runs node dist/server.js directly instead of npm start, so the server receives the stop signal on a redeploy or a sleep and exits cleanly. If you change the start script, change it there too.

Endpoints

Method

Path

Does

POST

/mcp

MCP over Streamable HTTP. Needs the bearer token

GET, DELETE

/mcp

405: stateless, so there is no stream to open and no session to end

GET

/

The landing page, or setup instructions until MCP_AUTH_TOKEN is set

GET

/healthz

200 while the process is up, including before the token is set

Licence

MIT.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Local MCP server that wraps the headless Claude Code CLI as MCP tools, providing stateless access to Claude's coding capabilities through prompt-based interactions. It enables users to execute Claude Code commands with various prompt formats and structured outputs directly from MCP clients.
    3
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables developers to build and deploy secure, typed Model Context Protocol servers with tools, resources, prompts, bearer-token authentication, per-tool scopes, rate limiting, and health probes over Streamable HTTP.
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables building and running zero-dependency MCP servers with automatic JSON Schema generation, exposing Python tools to Claude Desktop, Cursor, and autonomous agent fleets.
    2
    Apache 2.0
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables users to deploy and host a remote MCP server on Cloudflare Workers without requiring authentication, and connect it to clients like Cloudflare AI Playground and Claude Desktop for using custom MCP tools.
    -