Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions .github/workflows/publish-mcp-registry.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: Publish MCP Registry

# Publishes server.json to the official MCP registry (#9526), so `io.github.JSONbored/loopover` is
# discoverable by any registry-aware client.
#
# workflow_dispatch ONLY, and main-only. Publishing announces a version to a public registry, which is not
# something a branch build or a merge should do on its own -- the version it advertises comes from
# @loopover/mcp's package.json, which the release automation bumps, so a publish is a deliberate follow-up to
# a release rather than a side effect of one.
#
# ANTI-ROT: the first step re-runs scripts/check-server-manifest.ts, which asserts every watched path still
# EXISTS before validating any field. metagraphed's version-sync workflow rotted silently for months because
# it watched a path that had been renamed -- it kept passing while doing nothing at all. A workflow that can
# quietly watch nothing is worse than no workflow, so this one fails loudly instead.

on:
workflow_dispatch:
inputs:
dry_run:
description: "Validate and print what would be published, without publishing"
type: boolean
default: false

permissions:
contents: read
# GitHub OIDC is how mcp-publisher proves this repo owns the io.github.JSONbored/* namespace. No
# long-lived registry credential exists to leak.
id-token: write

concurrency:
group: publish-mcp-registry
cancel-in-progress: false

jobs:
publish:
Comment thread
JSONbored marked this conversation as resolved.
name: Publish server.json
runs-on: ubuntu-latest
# A deployment environment, so the one job in this repo that holds `id-token: write` and writes to a
# public registry can carry protection rules (required reviewers, a wait timer) configured outside the
# workflow file. Without it, anyone who can dispatch a workflow can publish.
environment: mcp-registry
# Belt and braces alongside the dispatch-only trigger: a dispatch can name any ref, and a registry
# publish must only ever describe what is on main.
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

- name: Setup Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version-file: .nvmrc

# Runs BEFORE anything else: a manifest whose version disagrees with the shipped package, or a watched
# path that has been renamed away, must stop the publish rather than announce something untrue.
- name: Validate server.json and its watched paths
run: node --experimental-strip-types scripts/check-server-manifest.ts

- name: Install mcp-publisher
env:
MCP_PUBLISHER_VERSION: v1.8.0
# The tag is mutable; this is not. A release tag can be moved to point at a different commit, and
# this binary authenticates as this repository and writes to a public registry -- so the download
# is checked against the exact bytes reviewed here, and a mismatch fails the job rather than
# publishing under a binary nobody looked at.
MCP_PUBLISHER_SHA256: 1370446bbe74d562608e8005a6ccce02d146a661fbd78674e11cc70b9618d6cf
run: |
set -euo pipefail
curl -fsSL "https://github.com/modelcontextprotocol/registry/releases/download/${MCP_PUBLISHER_VERSION}/mcp-publisher_linux_amd64.tar.gz" -o mcp-publisher.tar.gz
echo "${MCP_PUBLISHER_SHA256} mcp-publisher.tar.gz" | sha256sum --check --strict -
tar -xzf mcp-publisher.tar.gz mcp-publisher
chmod +x mcp-publisher

- name: Login via GitHub OIDC
run: ./mcp-publisher login github-oidc

- name: Publish
if: ${{ !inputs.dry_run }}
run: ./mcp-publisher publish

- name: Dry run — report what would be published
if: ${{ inputs.dry_run }}
run: |
echo "DRY RUN: server.json validated and OIDC login succeeded; publish skipped."
cat server.json
209 changes: 192 additions & 17 deletions apps/loopover-ui/content/docs/mcp-clients.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,39 @@ description: Configure your coding agent to talk to the LoopOver MCP. Pick stdio
eyebrow: Get started
---

{/* GENERATED:MCP-CLIENT-CONFIG:BEGIN — edit packages/loopover-contract/src/client-config.ts, then `npm run mcp:client-config` */}

## Generate config

These commands print config only. They do not mutate your local client files.
Every block on this page is what `init-client` prints. It prints config only — it never edits your client files.

<CodeBlock
lang="bash"
code={`loopover-mcp init-client --print codex
loopover-mcp init-client --print claude
loopover-mcp init-client --print cursor
loopover-mcp init-client --print mcp
loopover-mcp init-client --print vscode`}
loopover-mcp init-client --print vscode
loopover-mcp init-client --print codex --mode remote
loopover-mcp init-client --print claude --mode remote
loopover-mcp init-client --print cursor --mode remote
loopover-mcp init-client --print vscode --mode remote
loopover-mcp init-client --print codex --mode miner
loopover-mcp init-client --print claude --mode miner
loopover-mcp init-client --print cursor --mode miner
loopover-mcp init-client --print mcp --mode miner
loopover-mcp init-client --print vscode --mode miner`}
/>

`--print mcp` uses the same JSON snippet as Claude Desktop and Cursor for other stdio MCP hosts
that expect the `mcpServers` shape. Every generated snippet assumes `loopover-mcp` is on your
`PATH` (install it globally first, per [Quickstart](/docs/quickstart)) — pass
`--command /absolute/path/to/loopover-mcp` if your client doesn't inherit your shell PATH.
## Local stdio (gateway)

The recommended default. Runs `loopover-mcp` on your machine, keeps auth and git analysis local, and — once you have run `loopover-mcp login` — mounts the remote tool set too, so one entry serves every tool your session entitles you to.

## Codex (OpenAI)
- Run `loopover-mcp login` before starting the client; without a session you get the local-git tools only, plus an advisory resource explaining how to get the rest.
- Pass `--no-remote` to keep the server purely local and skip the remote mount entirely.
- Assumes `loopover-mcp` is on your PATH; pass `--command /absolute/path/to/loopover-mcp` if your client does not inherit your shell PATH.

### Codex (OpenAI) (stdio)

<CodeBlock
filename="~/.codex/config.toml"
Expand All @@ -32,7 +46,7 @@ command = "loopover-mcp"
args = ["--stdio"]`}
/>

## Claude Desktop
### Claude Desktop / Claude Code (stdio)

<CodeBlock
filename="claude_desktop_config.json"
Expand All @@ -47,7 +61,7 @@ args = ["--stdio"]`}
}`}
/>

## Cursor
### Cursor (stdio)

<CodeBlock
filename=".cursor/mcp.json"
Expand All @@ -62,10 +76,22 @@ args = ["--stdio"]`}
}`}
/>

## VS Code
### Other `mcpServers` hosts (stdio)

<CodeBlock
filename="mcp.json"
lang="json"
code={`{
"mcpServers": {
"loopover": {
"command": "loopover-mcp",
"args": ["--stdio"]
}
}
}`}
/>

VS Code's native MCP support uses a `servers` map with an explicit transport type instead of the
`mcpServers` shape the other JSON hosts use:
### VS Code (stdio)

<CodeBlock
filename=".vscode/mcp.json"
Expand All @@ -81,14 +107,163 @@ VS Code's native MCP support uses a `servers` map with an explicit transport typ
}`}
/>

## Remote MCP
## Remote streamable-http

For agents that run in the cloud, or anywhere you do not want a local Node process. Connects straight to the hosted server; the local-git tools are not available over this transport because there is no local checkout to read.

- Authenticates with a bearer token read from `LOOPOVER_API_TOKEN` — the same variable the CLI honors. Set it in the environment your client starts in; never paste the token into the config file.
- Tools whose work is a local git operation are absent here by design. Use the stdio mode if you need them.

### Codex (OpenAI) (remote)

<CodeBlock
filename="~/.codex/config.toml"
lang="toml"
code={`[mcp_servers.loopover]
url = "https://api.loopover.ai/mcp"
bearer_token_env_var = "LOOPOVER_API_TOKEN"`}
/>

Codex releases before its RMCP client became the default also need `experimental_use_rmcp_client = true` at the top level of config.toml.

### Claude Desktop / Claude Code (remote)

<CodeBlock
filename=".mcp.json"
lang="json"
code={`{
"mcpServers": {
"loopover": {
"type": "http",
"url": "https://api.loopover.ai/mcp",
"headers": {
"Authorization": "Bearer \${LOOPOVER_API_TOKEN}"
}
}
}
}`}
/>

### Cursor (remote)

<CodeBlock
filename=".cursor/mcp.json"
lang="json"
code={`{
"mcpServers": {
"loopover": {
"type": "http",
"url": "https://api.loopover.ai/mcp",
"headers": {
"Authorization": "Bearer \${LOOPOVER_API_TOKEN}"
}
}
}
}`}
/>

### VS Code (remote)

<CodeBlock
filename=".vscode/mcp.json"
lang="json"
code={`{
"servers": {
"loopover": {
"type": "http",
"url": "https://api.loopover.ai/mcp",
"headers": {
"Authorization": "Bearer \${LOOPOVER_API_TOKEN}"
}
}
}
}`}
/>

## Miner stdio

AMS's own local state-visibility tools, as a separate stdio server. It stays separate on purpose: it reads this machine's SQLite state and shares no code or network path with the hosted server.

- Takes no flags and needs no login — everything it reads is already on this machine.
- A dual-role operator runs this alongside the stdio gateway; the two entries coexist in one client config.

### Codex (OpenAI) (miner)

<CodeBlock
filename="~/.codex/config.toml"
lang="toml"
code={`[mcp_servers.loopover-miner]
command = "loopover-miner-mcp"
args = []`}
/>

### Claude Desktop / Claude Code (miner)

<CodeBlock
filename="claude_desktop_config.json"
lang="json"
code={`{
"mcpServers": {
"loopover-miner": {
"command": "loopover-miner-mcp",
"args": []
}
}
}`}
/>

### Cursor (miner)

<CodeBlock
filename=".cursor/mcp.json"
lang="json"
code={`{
"mcpServers": {
"loopover-miner": {
"command": "loopover-miner-mcp",
"args": []
}
}
}`}
/>

### Other `mcpServers` hosts (miner)

<CodeBlock
filename="mcp.json"
lang="json"
code={`{
"mcpServers": {
"loopover-miner": {
"command": "loopover-miner-mcp",
"args": []
}
}
}`}
/>

### VS Code (miner)

<CodeBlock
filename=".vscode/mcp.json"
lang="json"
code={`{
"servers": {
"loopover-miner": {
"type": "stdio",
"command": "loopover-miner-mcp",
"args": []
}
}
}`}
/>

The Worker also exposes a remote MCP endpoint. Use this when your agent runs in the cloud or you
don't want a local Node process.
Every block above comes from the same grid the CLI prints from, so a snippet copied from here and one printed by `init-client` can never disagree.

<CodeBlock lang="http" code={`https://api.loopover.ai/mcp`} />
{/* GENERATED:MCP-CLIENT-CONFIG:END */}

<Callout variant="safety">
Local `--stdio` is the default recommendation. It keeps auth + analysis on your machine and is the
easiest path to log into with GitHub Device Flow.
easiest path to log into with GitHub Device Flow — and, since it mounts the remote tool set too, it
is the only mode that gives you every tool from one entry.
</Callout>
Loading
Loading