From e7ba67041ea90f92fce791a768808af3adbf515e Mon Sep 17 00:00:00 2001 From: Mark Mennell Date: Thu, 17 Sep 2026 21:25:24 +0800 Subject: [PATCH 1/2] Make registry connections and onboarding provider-neutral --- README.md | 32 +++++++++++++++++++++++++++----- server.json | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8bd68fe..fc16490 100644 --- a/README.md +++ b/README.md @@ -10,23 +10,45 @@ attachments and wait for replies, through a deployed [fmsg Web API](https://github.com/markmnl/fmsg-webapi). Connect through stdio in hosts such as Claude Code, Claude Desktop, Cursor and VS Code, or through HTTP using API-key headers or configured OAuth. +Use your choice of fmsg hosting provider, or self-host. No hosting provider or identity provider +is built in. + - **stdio** for local hosts: one address per server process, configured by two environment variables. - **Streamable HTTP** for shared or remote deployments: one endpoint serving many users, each authenticated by their own fmsg API key or OAuth connection. - The fmsg Web API client is exported for reuse: `import { FmsgClient } from "@markmnl/fmsg-mcp/client"`. -## 1. Get an fmsg address and API key +## 1. Choose a connection + +### OAuth: connect and sign in + +Get an OAuth-enabled MCP URL from your fmsg hosting provider, add it to your AI host, and sign in. +You do not need an API key or a local installation for this connection. Your AI host must support +the authorization server's client registration method; see [OAuth onboarding](docs/oauth.md#discovery-and-client-onboarding). +Operators can enable this with [HTTP OAuth](docs/oauth.md). -Connecting to an existing OAuth-enabled endpoint? Add its MCP URL to your host and sign in; -you can skip the API-key setup below. Operators can enable this with [HTTP OAuth](docs/oauth.md). +### API key: use locally or over HTTP You send as an fmsg address, authenticated by an API key (`fmsgk_…`) issued by your fmsg host: -- **No host yet?** Create an account at a public fmsg host such as [fmsg.io](https://fmsg.io) and - add an agent (sub-account) to get an API URL and key. +- **Using a hosting provider?** Create an account with an fmsg hosting provider and obtain an + API URL and API key for the address your agent will use. - **Self-hosting?** Run the stack with [fmsg-docker](https://github.com/markmnl/fmsg-docker) and issue a key with `fmsg-webapi api-key create`. +Use the API URL and key for local installation below, or use your provider's API-key MCP endpoint +with an `Authorization: Bearer fmsgk_...` header. The endpoint must use the fmsg Web API that accepts +your key. + +### MCP Registry + +Find `io.github.markmnl/fmsg-mcp` in the [official MCP Registry](https://registry.modelcontextprotocol.io/?q=io.github.markmnl%2Ffmsg-mcp). +The listing offers local npm installation and configurable remote connections for OAuth or API keys. +For a remote connection, supply the MCP endpoint from your fmsg hosting provider or your own deployment; +the registry input takes its hostname and path without the `https://` prefix, such as `mcp.example.com/mcp`. +OAuth sign-in is discovered from that endpoint; the API-key option additionally asks for your key. +If your AI host cannot configure registry URL templates, add the full MCP URL directly instead. + ## 2. Install Requires Node.js 22 or later. diff --git a/server.json b/server.json index 24168a0..d63087f 100644 --- a/server.json +++ b/server.json @@ -1,7 +1,9 @@ { "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", "name": "io.github.markmnl/fmsg-mcp", - "description": "Send and receive fmsg federated messages from any AI agent via a deployed fmsg Web API", + "title": "fmsg", + "description": "Federated messaging with your fmsg hosting provider. Connect with OAuth or an API key.", + "websiteUrl": "https://github.com/markmnl/fmsg-mcp#readme", "repository": { "url": "https://github.com/markmnl/fmsg-mcp", "source": "github" @@ -19,7 +21,7 @@ "environmentVariables": [ { "name": "FMSG_API_URL", - "description": "Base URL of the fmsg Web API", + "description": "Base URL of your hosting provider's or self-hosted fmsg Web API", "isRequired": true }, { @@ -40,5 +42,48 @@ } ] } + ], + "remotes": [ + { + "type": "streamable-http", + "url": "https://{oauth_mcp_endpoint}", + "variables": { + "oauth_mcp_endpoint": { + "description": "OAuth MCP endpoint from your fmsg hosting provider: hostname and path without https://. Sign in through your AI host; no API key needed.", + "isRequired": true, + "format": "string", + "placeholder": "mcp.example.com/mcp" + } + } + }, + { + "type": "streamable-http", + "url": "https://{api_key_mcp_endpoint}", + "variables": { + "api_key_mcp_endpoint": { + "description": "API-key MCP endpoint from your fmsg hosting provider: hostname and path without https://. Use an endpoint that accepts your key.", + "isRequired": true, + "format": "string", + "placeholder": "mcp.example.com/mcp" + } + }, + "headers": [ + { + "name": "Authorization", + "description": "Your fmsg API key for the selected MCP endpoint", + "isRequired": true, + "isSecret": true, + "value": "Bearer {api_key}", + "variables": { + "api_key": { + "description": "API key accepted by this endpoint's fmsg Web API, starting with fmsgk_", + "isRequired": true, + "isSecret": true, + "format": "string" + } + } + } + ] + } ] } From 15b555ebfeb1eae35ce3a7c9a0007f8b4a6cf917 Mon Sep 17 00:00:00 2001 From: Mark Mennell Date: Thu, 17 Sep 2026 21:29:45 +0800 Subject: [PATCH 2/2] Publish MCP Registry metadata automatically after npm releases --- .github/workflows/publish.yml | 44 ++++++++++++++++++++++++++++++++++- AGENTS.md | 5 +++- README.md | 7 ++++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index bacd1cc..cfa6876 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,4 +1,4 @@ -name: Publish to npm +name: Publish to npm and MCP Registry on: release: @@ -38,3 +38,45 @@ jobs: - run: npm test - run: npm pack --dry-run --ignore-scripts - run: npm publish --access public + + publish-registry: + name: Publish MCP Registry metadata + needs: publish + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.release.tag_name }} + - uses: actions/setup-node@v4 + with: + node-version: "22" + - name: Set registry version from release tag + env: + RELEASE_TAG: ${{ github.event.release.tag_name }} + run: | + node --input-type=module <<'JS' + import fs from 'node:fs'; + const server = JSON.parse(fs.readFileSync('server.json', 'utf8')); + const version = process.env.RELEASE_TAG.slice(1); + server.version = version; + server.packages.forEach(pkg => { pkg.version = version; }); + fs.writeFileSync('server.json', JSON.stringify(server, null, 2) + '\n'); + JS + - name: Install mcp-publisher + env: + MCP_PUBLISHER_VERSION: "1.8.1" + MCP_PUBLISHER_SHA256: "a06c9096dcb9727c13555b6be26c7effa707b01f06a4c561ba7a3635443cf2cc" + run: | + publisher_dir="$RUNNER_TEMP/mcp-publisher" + mkdir -p "$publisher_dir" + curl --fail --location --retry 3 \ + "https://github.com/modelcontextprotocol/registry/releases/download/v${MCP_PUBLISHER_VERSION}/mcp-publisher_linux_amd64.tar.gz" \ + --output "$publisher_dir/archive.tar.gz" + printf '%s %s\n' "$MCP_PUBLISHER_SHA256" "$publisher_dir/archive.tar.gz" | sha256sum --check --strict + tar -xzf "$publisher_dir/archive.tar.gz" -C "$publisher_dir" mcp-publisher + echo "$publisher_dir" >> "$GITHUB_PATH" + - name: Authenticate to MCP Registry + run: mcp-publisher login github-oidc + - name: Publish server to MCP Registry + run: mcp-publisher publish server.json diff --git a/AGENTS.md b/AGENTS.md index b0f0bce..7727762 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -80,4 +80,7 @@ bash .github/scripts/run-fmsg-docker-e2e.sh # real stacks via fmsg-docke ## Releasing Tag `vX.Y.Z`, publish a GitHub release; `.github/workflows/publish.yml` sets the version from the -tag, runs the checks and publishes to npm with OIDC trusted publishing. +tag, runs the checks and publishes to npm with OIDC trusted publishing. After npm succeeds, a +separate job publishes the matching `server.json` to the MCP Registry using GitHub OIDC; no +registry secret is required. Drafts and prereleases do not publish. If only the registry job +fails, re-run failed jobs to retry it without republishing npm. diff --git a/README.md b/README.md index fc16490..070ff98 100644 --- a/README.md +++ b/README.md @@ -235,4 +235,11 @@ bash .github/scripts/run-fmsg-docker-e2e.sh # end to end on See [AGENTS.md](./AGENTS.md) for layout and conventions, [ROADMAP.md](./ROADMAP.md) for remaining integration work, and [CHANGELOG.md](./CHANGELOG.md) for release notes. +### Releasing + +Publish a stable GitHub release tagged `vX.Y.Z` to run the checks, publish the npm package, and +then update the MCP Registry with the same version. Both use OIDC authentication; no dedicated +registry secret is needed. Drafts and prereleases do not publish. Registry publishing runs as a +separate job, so if it fails after npm succeeds, use **Re-run failed jobs** on the release workflow. + [MIT licensed](./LICENSE)