◆ docs

The MCP server

rickub hosts a remote Model Context Protocol server, so an AI agent — Claude Code, Cursor, or anything that speaks MCP — can read and drive your repositories with the same access token you use for the API.

The server lives at https://rickub.com/api/mcp and speaks the remote Streamable HTTP transport (JSON-RPC 2.0 over a single HTTPS endpoint — no local process to install, nothing to keep running on your machine). Point a client at the URL, hand it a token, and it can call rickub's tools directly.

Mint a token

The MCP server authenticates with a personal access token — the same token the JSON API and CLI use, sent as Authorization: Bearer <token>. Create one under Settings → Access tokens, copy it once, and keep it somewhere your client can read it (an environment variable or your client's secret store).

Tip

Give an agent the narrowest token it needs. A Read-only token lets an agent browse code, read issues and watch CI, but every mutating tool refuses it — the safest default for an assistant you only want to look. Hand out a Full access token only when the agent genuinely needs to open merge requests, comment, or dispatch workflows.

Connect a managed client (OAuth)

Hosted clients that manage their own connections — Claude.ai integrations, ChatGPT connectors — don't take a pasted token. rickub's MCP endpoint is an OAuth 2.1 protected resource, so you add it by URL alone and authorize it in the browser: paste https://rickub.com/api/mcp into the client's "add MCP server" (or "custom connector") box and it walks the flow for you.

  1. The client calls the endpoint, gets a 401 with a WWW-Authenticate header, and discovers the authorization server from /.well-known/oauth-protected-resource (RFC 9728) and /.well-known/oauth-authorization-server (RFC 8414).
  2. It registers itself automatically (RFC 7591 Dynamic Client Registration) at /oauth/register — no client id to copy.
  3. It sends you to a rickub consent screen (sign in if you aren't already). The screen names the app and whether it asked for read-only or full access.
  4. Approve, and the client exchanges a one-time, PKCE-protected code for an access token — the same credential model a personal access token uses, so every permission check and read/write scope still applies.
Note

The access token an OAuth connection mints shows up under Settings → Access tokens named MCP: <app>, and revoking it there disconnects that client at once — no different from a token you minted by hand. It also expires on its own, at which point the client re-runs the browser flow.

Connect Claude Code

Claude Code adds a remote MCP server in one command — the http transport is the Streamable HTTP one, and a header carries your token:

claude mcp add --transport http rickub https://rickub.com/api/mcp \
  --header "Authorization: Bearer $RICKUB_TOKEN"

That writes the server into Claude Code's config; claude mcp list shows it and /mcp inside a session lists the tools it exposes.

Connect any MCP client

Clients that read a JSON config (Cursor, Claude Desktop, and most others) take an mcpServers entry with a url and a bearer header. The shape is the same everywhere:

{
  "mcpServers": {
    "rickub": {
      "url": "https://rickub.com/api/mcp",
      "headers": { "Authorization": "Bearer rickub_pat_xxx" }
    }
  }
}
Note

Different clients keep this file in different places (a project .mcp.json, a global settings file, or a GUI form). Whatever the location, the url + Authorization header pair is all rickub needs — it is a plain remote server with no custom handshake.

Verify it works

Once the server is added, ask your agent to run the list_repos tool (or whoami) — a token that is wired up correctly comes straight back with your repositories. To check the endpoint by hand, list the tools then call a read-only one over plain HTTPS:

# list the tools the server offers
curl -sS https://rickub.com/api/mcp \
  -H "Authorization: Bearer $RICKUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

# call one — who owns this token?
curl -sS https://rickub.com/api/mcp \
  -H "Authorization: Bearer $RICKUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"whoami","arguments":{}}}'
Heads up

A missing or wrong token gets a 401, never a partial answer — an unreadable repository returns a not-found rather than confirming it exists. If a mutating call comes back this token is read-only, mint a Full-access token for that agent.

What the tools cover

The server exposes seventy-odd tools, each one backed by the same permission checks and plan limits as the website and the JSON API — so an agent can never do through MCP what its token could not do in the browser. The surface, by area:

  • Repositories — list_repos, get_repo, create_repo, update_repo, delete_repo, rename/transfer via move_repo, star_repo / watch_repo (and their un- counterparts), and collaborators via add_collaborator / remove_collaborator.
  • Merge requests — list_merge_requests (filter by title query, labels, milestone, sort; page with page/per_page), get_merge_request, get_merge_request_diff (the changed files and unified diff, with names_only and a files path filter when the whole diff is too large to send), create_merge_request, update_merge_request (correct the title and/or the description after the fact — an omitted field is left alone), comment_merge_request, review_merge_request, merge_merge_request, close_merge_request / reopen_merge_request, set_merge_request_draft.
  • Issues, labels & milestones — list_issues (same filters as the merge-request list: query, labels, milestone, sort, page/per_page — ask a question instead of paging a whole tracker), get_issue, create_issue, update_issue (state, title and/or description in one call), comment_issue, assign_issue, set_issue_labels, the label vocabulary itself via list_labels / create_label / update_label, and the *_milestone tools.
  • Releases — list_releases, get_release, create_release, update_release, delete_release (creating/editing needs admin; publishing a draft fires the release webhook and on: release workflows).
  • Webhooks & tags — repository webhooks via list_webhooks, create_webhook, update_webhook, delete_webhook (admin-only; payload URLs are SSRF-guarded), and create_tag.
  • CI — list_runs, get_run, get_run_logs (pass job to fetch one job's log instead of every job concatenated), list_run_artifacts, dispatch_workflow, rerun_run, cancel_run, and a server-side wait_for_run. See CI / Actions to learn what those runs do.
  • Code browsing — get_file, list_dir, list_commits, get_commit, compare, list_refs.
  • Organizations & search — get_org, list_org_members, list_org_teams, and search_repos.

What a list tool returns

list_issues and list_merge_requests both answer with an object, not a bare array: {"issues": […], "has_next": true} and {"merge_requests": […], "has_next": true}. has_next is the only honest way to page — an empty page is not the same signal, and a bare array cannot carry one. Page with page and per_page (default 30, max 100) until has_next is false, and narrow with query, labels (at most 10, and every one must exist), milestone and sort rather than paging to find one row.

MCP surface changes

The tool surface is meant to grow additively: new tools and new optional arguments appear without notice, and existing tools keep the arguments and the result shape they already had. When that cannot be honoured, the change is recorded here before it ships, with the date, so an agent author has something to read that is not a diff. There is no deprecation window yet; until there is, treat anything in this section as a break you must act on.

  • 2026-09-19 — BREAKING: list_merge_requests returns an object. It used to return a bare array of merge requests. It now returns {"merge_requests": […], "has_next": bool}, matching list_issues, because the tool gained filtering and paging and a bare array cannot say whether a further page exists. A client doing result[0] must read result.merge_requests[0] instead.
  • 2026-09-19 — wait_for_run clamps timeout_seconds. Not a break in shape: a longer wait is reduced to the ceiling rather than refused, and the answer now carries max_wait_seconds. See below.
  • 2026-09-20 — dispatch_workflow takes inputs, workflow and tags. Additive: inputs (an object of workflow_dispatch input values), workflow (run one workflow, by file name or path) and a tag as ref are new and optional. Inputs are validated the way GitHub validates them, and an invalid_inputs error names the input and lists what the workflow declares, so an agent can correct itself from the error alone. Two refusals changed wording: an unknown ref is now unknown_ref (was unknown_branch), and an account that is out of CI minutes now gets quota_exceeded instead of a quiet dispatched: 0.
  • 2026-09-19 — new tools. update_merge_request, get_merge_request_diff, list_labels, create_label, update_label, assign_issue, list_run_artifacts; update_issue gained title; both list tools gained filters.

Waiting for a run

wait_for_run holds its request open and polls server-side, which is far cheaper than an agent looping on get_run — but a held-open request is only as long as the shortest timeout in front of the server. Any reverse proxy or load balancer applies its own per-request cap, and when that fires first the client sees a severed connection ("socket connection was closed unexpectedly") rather than an answer. The MCP endpoint answers one JSON response per POST, so there are no keep-alive frames to ride under it.

So timeout_seconds is clamped to the deployment's ceiling — 45 seconds unless this installation says otherwise, which it does with RICKUB_MCP_MAX_WAIT_SECONDS. Asking for more is not an error: you get the ceiling, the answer carries max_wait_seconds so you can see why, and a run still going comes back with timed_out: true and final: false. That is a signal to call wait_for_run again, not a failure.

Every tool advertises MCP annotation hints — read tools are marked read-only, deletes and merges as destructive, updates as idempotent — so a well-behaved client can auto-approve a harmless read but pause before a destructive call.

Beyond tools, the server offers a few prompt templates (triage_issues, review_merge_request) a client can surface as slash-commands, read resources (rickub://me and rickub://me/repos, scoped to your own token), and argument completions of owner/repo. In Claude Code, /mcp lists them.

The tools return the same JSON shapes as the JSON API, so anything you can read there an agent can read here. Revoke a token under Settings → Access tokens and every client using it stops at once.

Was this page helpful?