RunR v0.5.7

Documentation

MCP server starter — TypeScript

server.ts is a Model Context Protocol server on the official TypeScript SDK (@modelcontextprotocol/sdk): Streamable HTTP at /mcp on $PORT, stateless (a new server and transport per request), behind the RunR MCP gateway (docs/mcp.md).

File
runtime.yaml the mcp-node runtime: image ghcr.io/brf-tech/runr/reqs/node:22-slim, dependencies from package.json into /app/code/node_modules, run.command node --experimental-strip-types --disable-warning=ExperimentalWarning /app/code/server.ts (http mode), starter template server.ts
server.ts tools hello, add, whoami, resource starter://about, prompt greet; verifySignature checks X-RunR-Signature
package.json @modelcontextprotocol/sdk, zod; "type": "module"
Dockerfile the same server as an image for a CaaS project

Node runs the TypeScript file directly (type stripping), so there is no build step for the code — only npm install for the dependencies. Type stripping removes types; it does not transform syntax, so keep to erasable TypeScript: types, interfaces, as, no enum, no namespace, no constructor parameter properties, and import local files with their .ts extension.

Deploy on RunR#

Projects → New MCP server → TypeScript. RunR creates a FaaS project on mcp-node with these files; the first save builds the dependencies into the version's image. Deploy it, then connect:

claude mcp add --transport http my-server https://runr.example.com/mcp/servers/<project slug>

Add a tool#

server.registerTool(
  "forecast",
  {
    title: "Weather forecast",
    description: "Weather forecast for a city.",
    inputSchema: { city: z.string(), days: z.number().int().min(1).max(7).default(3) },
  },
  async ({ city, days }) => ({ content: [{ type: "text", text: `${city}: sunny for ${days} days` }] }),
);

buildServer(identity) receives the caller the gateway identified (identity.user, identity.auth, identity.scopes), so tools can act on behalf of that user.

Run locally#

npm install
PORT=8080 npm start
npx @modelcontextprotocol/inspector   # connect to http://localhost:8080/mcp (Streamable HTTP)

Without RUNR_MCP_GATEWAY_KEY the server accepts unsigned requests; with it set, only requests signed like the gateway does (see the Python README for a signing snippet) get through.

As your own image#

docker build -t registry.example.com/acme/mcp-node:1.0 .
docker push registry.example.com/acme/mcp-node:1.0

Then Projects → New MCP server → Container image with that image and port 8080.

RunR v0.5.7 · MIT License