Cycleo MCP server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Cycleo MCP servershow me my recent projects and their status"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Cycleo MCP server
Distributable, read-only MCP adapter for Cycleo. The server exposes a small allow-listed tool surface and calls Cycleo's versioned JSON API with the user-scoped OAuth bearer token.
This repository contains the MCP resource server only. Cycleo remains the
authorization server and data owner; the /oauth/* integration is documented
in docs/auth-integration.md and must be wired before production use.
Cycleo users who want to connect from their own computer should follow the workstation setup guide. It uses the hosted MCP endpoint; cloning or running this server locally is not required.
Local run
cp .env.example .env
npm run start:localThe local endpoint is http://localhost:8787/mcp. Open
http://localhost:8787/connect once to sign in through Cycleo. The server
stores only the OAuth token set locally with restrictive file permissions and
refreshes access tokens automatically. Set CYCLEO_API_BASE_URL to a local
Cycleo API when developing against a local checkout.
Local mode is explicit (MCP_AUTH_MODE=local) and the server refuses to start
unless MCP_HOST is a loopback host. The default token file is
~/.cycleo-mcp/tokens.json; override it with TOKEN_STORE_PATH when needed.
Related MCP server: sprout-mcp
Production boundary
Production must use MCP_AUTH_MODE=bearer. In that mode /connect and
/callback are disabled, no token is loaded from disk, and every MCP request
must provide its own OAuth bearer token. Set MCP_PUBLIC_URL, OAUTH_RESOURCE
and CYCLEO_API_BASE_URL to their HTTPS production values. OAUTH_CLIENT_ID,
OAUTH_REDIRECT_URI and TOKEN_STORE_PATH are local-mode settings.
ALLOWED_ORIGINS is a comma-separated allow-list for clients that send an
Origin header and defaults to the public resource origin. Requests from an
allow-listed Origin receive CORS response headers and OPTIONS preflight is
answered, so browser-based MCP clients can connect; any other Origin is
rejected with 403. ALLOWED_HOSTS is the matching allow-list for the Host
header (DNS-rebinding protection); it defaults to the OAUTH_RESOURCE host and
always permits loopback hosts so the systemd health check keeps working.
Optional hardening/performance knobs:
CYCLEO_MAX_RESPONSE_BYTES(default 1 MiB) caps each Cycleo API response.CYCLEO_MAX_RETRIES(default 2) retries transient Cycleo failures (network errors and HTTP 429/502/503/504) with exponential backoff and honoursRetry-After.AUTH_CACHE_TTL_MS(default 30000) caches theGET /auth/meidentity lookup so repeated MCP calls don't re-hit Cycleo — set to0to disable, and note a revoked token stays usable until the entry expires.RATE_LIMIT_PER_MIN(default 120) is a per-token fixed-window limit on/mcprequests; exceeding it returns429with aRetry-Afterheader. Set to0to disable.ACCESS_LOG(default on) writes one JSON line per request to stderr; set tooffto silence it.
On SIGTERM/SIGINT the server stops accepting connections, ends open SSE
streams and drains in-flight requests before exiting.
Transport
/mcp is Streamable HTTP. POST /mcp carries the JSON-RPC request/response
traffic. GET /mcp opens the server-to-client text/event-stream channel for
an initialized session (identified by the Mcp-Session-Id header); it is held
open with periodic keep-alive comments, and a session may hold at most four
concurrent streams (a fifth returns 409). DELETE /mcp terminates a session
and closes any streams it still holds; an expired or drained session does the
same, so keep-alive timers never outlive their session. Every session-scoped
response echoes the negotiated MCP-Protocol-Version header.
Protected-resource metadata (RFC 9728) is served both at
/.well-known/oauth-protected-resource and at the endpoint-suffixed
/.well-known/oauth-protected-resource/mcp that MCP clients probe.
The MCP server never receives Cycleo passwords and never connects to the Cycleo
database. It exchanges each client-facing MCP token for a distinct, short-lived
backend token before calling GET /auth/me, binds MCP sessions to that user and
league, and only calls the allow-listed read routes in src/tools.mjs,
src/resources.mjs and src/prompts.mjs. Ordinary Cycleo mobile tokens cannot
be exchanged and are rejected by the MCP authentication boundary.
Capabilities
The server advertises tools, resources and prompts.
Tools (
src/tools.mjs) — the allow-listed read actions: identity and season context, current server time, team and roster reads, race list/overview/result/ classification, league standings, rider/race/team search, rider profiles/start-list races, TransferAI advice, and transfer history/radar. Seedocs/tools.md.Resources (
src/resources.mjs) —resources/list,resources/readandresources/templates/listexpose the same user- and league-scoped Cycleo data as addressablecycleo://URIs (cycleo://team,cycleo://teams/{id}, …). Reads dispatch the same fixed GET routes as the tools.Prompts (
src/prompts.mjs) —prompts/listandprompts/getreturn read-only analysis prompts (cycleo_team_review,cycleo_transfer_plan,cycleo_race_preview) that steer a client toward the right tool calls.
See docs/resources-and-prompts.md.
CI/CD
GitHub Actions runs syntax checks, tests and the production dependency audit on
pushes and pull requests to main. CI covers Node 22 and 24.
The delivery workflow runs for version tags such as v1.2.3 and manual
dispatches. After re-running all checks, it deploys over SSH to
/var/www/cycleo.mcp/releases/<commit> and atomically switches
/var/www/cycleo.mcp/current. It restarts cycleo-mcp.service, verifies the
loopback health endpoint and restores the previous release if verification
fails.
Server preparation, the hardened unit template, required GitHub environment
secrets and release procedure are documented in
docs/systemd-deployment.md.
This server cannot be deployed
Maintenance
Related MCP Connectors
Multi-tenant hosted MCP server for Oura Ring — 21 read-only tools, OAuth per user.
OAuth-protected, read-only-by-default MCP server for provenance-labeled QuillCaddie project memory.
Hosted MCP server with managed OAuth for 15+ toolkits: Google Workspace, Fitbit, Oura, Kalshi, etc.
Private journal MCP server to search, analyze, and create Dabble Me entries securely via OAuth.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceFull-coverage, read-only MCP server for the Teamtailor recruitment API. Exposes 18 tools covering candidates, jobs, applications, offers, stages, departments, locations, users, and activities with strict input validation.-
- FlicenseAqualityCmaintenanceRead-only MCP server for the Sprout Social public API, exposing profile and post analytics as tools with raw JSON passthrough.5-
- AlicenseAqualityCmaintenanceRead-only MCP server for Favro, providing tools to list organizations, collections, boards, cards, comments, checklists, and search cards via the Favro API.146 npm1MIT
- AlicenseNot gradedqualityCmaintenanceRead-only MCP server for PostGrid Print & Mail, exposing constrained tools for ping, listing sub-organizations, and schema probing via the PostGrid API. Designed for Claude Cowork custom connectors with OAuth Individual sign-in.MIT