Rebasely Beta: data may be purged

examples/MCP-tools Public

Markdown · 4.8 KiB · at fcaf000

mcp-tools

A small Model Context Protocol server on Cloudflare Workers. It gives models three exact, read-only tools for things they tend to get wrong: unit arithmetic, the current time somewhere else, and counting words.

The server speaks Streamable HTTP at /mcp, holds no sessions, and counts tool calls per day in a KV namespace.

Tools

convert_units

Converts between units of length, mass, volume (US customary) and temperature. Units can be symbols or names: km, kilometres, °F, pounds.

{ "value": 26.2, "from": "miles", "to": "km" }
{ "quantity": "length", "value": 26.2, "from": "mi", "result": 42.1648128, "to": "km" }

Converting between quantities, an unknown unit, or a temperature below absolute zero returns an error result that says what to send instead.

time_in_zone

The local date, time, weekday and UTC offset in an IANA time zone, now or at a given instant. A city that names one zone (tokyo, new york) works too.

{ "zone": "tokyo", "at": "2026-10-14T17:00:00Z" }
{
  "zone": "Asia/Tokyo",
  "instant": "2026-10-14T17:00:00.000Z",
  "date": "2026-10-15",
  "time": "02:00:00",
  "weekday": "Thursday",
  "utc_offset": "+09:00",
  "utc_offset_minutes": 540,
  "formatted": "Thursday, October 15, 2026 at 2:00:00 AM GMT+9"
}

Leave out at for the current time. An instant without Z or an offset is refused, since it would be read in the server's own zone.

text_stats

Characters (as a reader sees them, so an emoji counts once), words, sentences, paragraphs and reading time.

{ "text": "MCP gives models tools. This server has three of them." }
{
  "characters": 54,
  "characters_excluding_spaces": 45,
  "words": 10,
  "sentences": 2,
  "paragraphs": 1,
  "reading_time_seconds": 3,
  "reading_time": "under a minute"
}

words_per_minute sets the reading speed (default 238).

Connecting a client

The endpoint is http://localhost:8787/mcp locally, or https://mcp-tools.<your subdomain>.workers.dev/mcp once deployed. No auth.

MCP Inspector. Run npx @modelcontextprotocol/inspector, choose the Streamable HTTP transport, and enter the URL.

Claude Code.

claude mcp add --transport http mcp-tools http://localhost:8787/mcp

Claude Desktop. Desktop starts local servers over stdio, so bridge with mcp-remote in claude_desktop_config.json:

{
  "mcpServers": {
    "mcp-tools": { "command": "npx", "args": ["-y", "mcp-remote", "http://localhost:8787/mcp"] }
  }
}

curl. Each message is its own POST, and Accept must list both types:

curl -s http://localhost:8787/mcp \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"convert_units","arguments":{"value":100,"from":"C","to":"F"}}}'

GET /stats?days=7 returns calls and errors per tool for the last seven UTC days.

Running it

Node 24 or later.

npm install
npm test            # node:test, no Workers runtime needed
npm run typecheck
npm run dev         # wrangler dev on http://localhost:8787

npx wrangler deploy deploys it. The USAGE namespace in wrangler.jsonc has no id, so the first deploy creates it.

Design notes

  • Stateless. Every POST gets a fresh McpServer and a WebStandardStreamableHTTPServerTransport with no session id and JSON responses. Any isolate can answer any request; nothing needs a Durable Object.
  • Tools are pure. Each tool in src/tools/ is a name, a description written for the model, zod input and output schemas, and a function from input to output. src/server.ts is the only file that knows about MCP.
  • Errors are results. A tool throws ToolError with advice ("Use an IANA name such as Europe/Paris"), and the server returns it with isError: true so the model can read it and try again.
  • Counting stays off the request path. Usage writes go through ctx.waitUntil, after the response. The counts are approximate, which is fine for seeing what gets used.

The longer versions are in the knowledge base under .rebasely/kb/, and the component map is .rebasely/architecture/system.yaml.

Layout

src/
  index.ts            Worker entry
  worker.ts           routes: /mcp, /stats, CORS
  server.ts           createServer(): registers the tools with McpServer
  usage.ts            per-day counters in KV
  tools/
    convert-units.ts
    time-in-zone.ts
    text-stats.ts
    errors.ts         ToolError
    types.ts          defineTool and the Tool type
test/                 node:test suites, plus an in-memory client and KV fakes
.rebasely/
  architecture/       components, views and flows
  kb/                 concepts, decisions and guides
  workflows/ci.yml    typecheck and tests on every push

License

MIT