Featured

Deploy OpenClaw in 60 seconds — 20% off logoDeploy OpenClaw in 60 seconds — 20% off

Launch OpenClaw on Hostinger in about 60 seconds and keep your agent live 24/7. Our referral link gives you 20% off, no coupon code needed.

Launch on Hostinger
Run your Hermes agent on Hostinger, fully managed logoRun your Hermes agent on Hostinger, fully managed

Launch Hermes on Hostinger in one click, fully managed, no VPS knowledge needed. Use code ZACAARON10 for 10% off.

Launch on Hostinger
Crawl and scrape any site into clean data, 10% off logoCrawl and scrape any site into clean data, 10% off

Firecrawl crawls and scrapes any site into clean markdown for your agent. Get 1,000 free credits, and new users get 10% off their first purchase.

Try Firecrawl free
Your own AI agent, running 24/7 with QwikClaw logoYour own AI agent, running 24/7 with QwikClaw

QwikClaw sets up and runs an always-on OpenClaw agent for you. One click, no config files, no server setup.

Deploy now
One API to scrape, enrich, and extract the internet. logoOne API to scrape, enrich, and extract the internet.

Context.dev gives your agents a single API to scrape, enrich, and extract live web data — no proxies, no parsers, no maintenance.

Start building free
SetupClaw: done-for-you OpenClaw for founders & exec teams logoSetupClaw: done-for-you OpenClaw for founders & exec teams

White-glove OpenClaw for founders and exec teams (4–50+ employees): we install, harden, integrate your tools, and maintain it — secured from day one.

Get it set up for you
SEO data APIs for your agent, $1 free credit logoSEO data APIs for your agent, $1 free credit

DataForSEO gives your agent live access to SERP results, keyword data, backlinks, and on-page SEO data through one API. New accounts get a $1 credit, good for up to 20,000 keyword or backlink lookups.

Try DataForSEO free
Reach 47,000+ AI builders

A flat monthly placement in front of developers actively installing AI tools. No lock-in, cancel anytime.

Advertise here

Works with

Claude CodeClaude DesktopCursorVS CodeClineCodex CLIOpenClaw+ any MCP client

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

MCP server providing time retrieval and echo tools, running as an independent network process over Streamable HTTP.

README.md

jarvis-mcp-server

Standalone MCP server(s) for Jarvis. It currently hosts a time server (in the time_server/ package) that reports the current local time for a city, and is structured to grow more tool domains over time — each added as its own package alongside time_server/.

Unlike a stdio MCP server (which a client launches as a subprocess), it runs as an independent network process over Streamable HTTP, so it has its own lifecycle and can be reached by the MCP Inspector, a CLI client, or a Cloud Run deployment.

Tools

| Tool | Args | Returns | |---|---|---| | get_current_time | city: str | Current local time + timezone for the city | | get_weather_digest | period: str (e.g. 24h, 7d), city: str (default Tokyo) | Aggregated weather digest for a city (JSON) | | get_weather_readings | city: str (default Tokyo), period: str (≤ 7 days) | Compact per-day weather report (JSON) — input to the anomaly pipeline | | detect_weather_anomalies | weather_report: str (a get_weather_readings report) | Deterministic anomaly report (JSON) | | send_telegram_alert | anomaly_report: str (a detect_weather_anomalies report), notify_when_clear: bool (default false) | Sends a Telegram alert if anomalies exist; with notify_when_clear=true also sends an "all clear" message when none (JSON result) | | add_city | city: str | Start collecting weather for a city; returns the tracked-city list | | remove_city | city: str | Stop collecting a city (its history is kept); returns the tracked-city list | | list_cities | — | The cities currently being collected | | echo | text: str | The input unchanged (connectivity smoke-test) |

get_current_time is a two-hop pipeline: Open-Meteo geocoding (city → lat/lon) → TimeAPI.io (lat/lon → local time). Both APIs are free and need no key. If the network is unavailable it falls back to the system UTC clock, so a call never hard-fails.

Tokyo weather digest (a scheduled agent)

The weather_digest/ package runs a continuous agent: while the server is up, a background thread collects the current weather once an hour for every tracked city (Open-Meteo, with a mock fallback when offline) and stores each reading in SQLite (weather_measurements table). The scheduler starts with the server (via the ASGI lifespan) and stops cleanly on shutdown — it runs independently of any tool call.

Tracked cities are managed at runtime. Tokyo is tracked by default; add_city / remove_city / list_cities change the set live (no restart). add_city does one immediate collection so a new city has data right away; remove_city only stops future collection — the city's stored history is preserved (re-adding resumes with it intact). The set is persisted in a tracked_cities table, so it survives restarts.

get_weather_digest(period, city) aggregates the stored readings over a window (city defaults to Tokyo):

{
  "city": "Tokyo", "period": "24h", "sample_count": 36,
  "average_temperature": 19.0, "min_temperature": 12.7, "max_temperature": 24.1,
  "most_common_condition": "overcast", "rainfall_occurrences": 7,
  "temperature_trend": "rising",
  "window_start": "...", "window_end": "..."
}

On a fresh/empty database the store auto-seeds 7 days of realistic hourly mock readings (multiple conditions, rainfall, diurnal temperature swing), so a digest is demoable immediately — before the hourly scheduler has collected anything live.

| Env var | Default | Purpose | |---|---|---| | WEATHER_DB_PATH | weather_digest/weather.db | SQLite file location | | WEATHER_CITY | Tokyo | Default city (always tracked + seeded); add more via add_city | | WEATHER_COLLECT_INTERVAL_S | 3600 | Seconds between collections (lower for demos) |

Cloud Run note: with --min-instances 0 the service scales to zero when idle, so the hourly collection only runs while an instance is alive. The seed data keeps the digest meaningful regardless; set --min-instances 1 for uninterrupted hourly collection.

Weather-anomaly pipeline (three chained tools)

A realistic workflow built from three tools the LLM chains automatically:

get_weather_readings → detect_weather_anomalies → send_telegram_alert

"Analyze Tokyo weather for the last week. If unusual weather conditions are detected, send a Telegram alert."

  1. get_weather_readings(city, period) reads the stored measurements and rolls

them up server-side into a compact per-day report (mean/min/max temperature and rainy fraction per UTC day). The raw rows never leave the server, so the data the model relays to the next tool stays tiny. period is capped at 7 days.

  1. detect_weather_anomalies(weather_report) applies deterministic rules to

that report and lists any anomalies. It accepts only a get_weather_readings report — a raw-readings array, a missing marker, too many day-buckets, or an oversized payload are rejected in code (not just by the prompt), so a large array can never be relayed in. Rules (thresholds overridable via ANOMALY_* env vars):

| Anomaly | Trigger | Default | |---|---|---| | rapid_temperature_rise / _drop | max/min day-over-day mean Δ | ±6 °C | | high_temperature_variability | window max − min | 18 °C | | high_rainfall_frequency | mean daily rainy fraction | 40 % | | unusually_dry | mean daily rainy fraction (≥ 3 days) | 5 % | | prolonged_bad_weather | consecutive mostly-rainy days | 3 days | | warming_trend / cooling_trend | first-half vs second-half mean Δ | ±4 °C |

  1. send_telegram_alert(anomaly_report, notify_when_clear=false) sends a

Telegram message only if anomalies were found (otherwise it skips). Pass notify_when_clear=true to also send a reassuring "all clear" message when no anomalies were detected — handy for a scheduled all-is-well check-in. If Telegram is not configured it reports that without failing. Uses the Telegram Bot API over stdlib urllib (no new dependency); the bot token is never logged or returned.

| Env var | Default | Purpose | |---|---|---| | TELEGRAM_BOT_TOKEN | _(unset)_ | Bot token from @BotFather. Unset → sends are skipped with not configured. | | TELEGRAM_CHAT_ID | _(unset)_ | Chat/channel id to deliver alerts to. | | ANOMALY_* | _(rule defaults)_ | Override any threshold above, e.g. ANOMALY_RAPID_TEMP_DELTA_C=8. |

To get a TELEGRAM_CHAT_ID: message your bot, then open https://api.telegram.org/bot<token>/getUpdates and read result[].message.chat.id.

Run locally

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python -m time_server.server          # serves http://0.0.0.0:8080/mcp

Configuration (env vars)

| Var | Default | Purpose | |---|---|---| | HOST | 0.0.0.0 | Bind address | | PORT | 8080 | Bind port (Cloud Run injects this) | | TRANSPORT | streamable-http | streamable-http \| sse \| stdio | | MCP_API_KEY | _(unset)_ | If set, every request (except /healthz) must send a matching X-API-Key. Unset → open server (local/Inspector only). | | LOG_LEVEL | INFO | Server log verbosity |

Security

  • Auth: set MCP_API_KEY; clients must send it as the X-API-Key header.

Comparison is constant-time and the key is never logged. Leaving it unset logs a loud warning and runs the server open — fine for local Inspector testing, never for a public deployment.

  • Health: GET /healthz is unauthenticated (for Cloud Run / curl probes).

Test with the MCP Inspector

In a second terminal (server still running):

npx @modelcontextprotocol/inspector

In the Inspector UI:

  1. Transport Type: Streamable HTTP
  2. URL: http://localhost:8080/mcp
  3. Connect → open the Tools tab → run get_current_time with city = London.

Automated checks

python tests/smoke_http.py      # end-to-end over Streamable HTTP (server must be up)
pytest -q                       # offline unit tests (no network, no server)

Deployment

See DEPLOY.md for the Cloud Run build/deploy commands, secret setup, and how scaling / cold starts work.

Roadmap

  • [x] Standalone Streamable HTTP server + tools (get_current_time, get_weather_digest)
  • [x] Scheduled weather-digest agent (hourly collection → SQLite → aggregation)
  • [x] Runtime-managed multi-city collection (add_city / remove_city / list_cities)
  • [x] Weather-anomaly pipeline (get_weather_readingsdetect_weather_anomaliessend_telegram_alert)
  • [x] Local test via MCP Inspector
  • [x] JarvisCLI client wired (auth-aware, degrades cleanly when down/unauthorized)
  • [x] API-key auth middleware (pure-ASGI, constant-time, /healthz exempt)
  • [x] Dockerfile (slim, non-root, port 8080)
  • [x] Cloud Run deploy guide

See related servers & alternatives →

Related MCP servers

Browse all →

Related guides

Hand-picked reading to help you choose and use Other servers.