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
5 changes: 1 addition & 4 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ jobs:
- name: Checkout
uses: actions/checkout@v7

# Version comes from package.json "packageManager" (do not set "version" here).
- name: Setup pnpm
uses: pnpm/action-setup@v6
with:
version: 10

- name: Setup Node.js
uses: actions/setup-node@v7
Expand All @@ -53,8 +52,6 @@ jobs:

- name: Setup pnpm
uses: pnpm/action-setup@v6
with:
version: 10

- name: Setup Node.js
uses: actions/setup-node@v7
Expand Down
132 changes: 132 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Publish @fqueis/openapi-contract to npm when a new version lands on main.
#
# Auth: npm Trusted Publishing (OIDC). Requires id-token: write,
# Node >= 22.14, npm CLI >= 11.5.1, and a Trusted Publisher on npmjs.com pointing
# at this workflow file (publish.yml) for repo fqueis/openapi-contract.
#
# Gate: skip if package.json version is already on the registry.
# Otherwise: lint + test + build, create GitHub Release (notes since previous tag),
# then pnpm publish. workflow_dispatch retries a failed publish without a new bump.
#
# Bootstrap: the first package version must exist on npm (local publish + 2FA) before
# Trusted Publisher can be configured; after that, CI owns subsequent publishes.
name: Publish

on:
push:
branches: [main]
workflow_dispatch:

permissions:
contents: write
id-token: write

concurrency:
group: publish-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

jobs:
publish:
name: publish
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 0

- name: Setup pnpm
uses: pnpm/action-setup@v6

- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: '22.14'
cache: pnpm
registry-url: https://registry.npmjs.org

- name: Ensure npm CLI supports trusted publishing
run: npm install -g npm@latest

- name: Install dependencies
run: pnpm install --ignore-scripts --frozen-lockfile

- name: Resolve version and check npm
id: version
run: |
VERSION="$(node -p "JSON.parse(require('fs').readFileSync('package.json','utf8')).version")"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Package version: $VERSION"

if npm view "@fqueis/openapi-contract@$VERSION" version >/dev/null 2>&1; then
echo "already_published=true" >> "$GITHUB_OUTPUT"
echo "Version $VERSION is already on npm — skipping publish."
else
echo "already_published=false" >> "$GITHUB_OUTPUT"
echo "Version $VERSION is not on npm — will publish."
fi

- name: Lint
if: steps.version.outputs.already_published == 'false'
run: pnpm lint

- name: Test
if: steps.version.outputs.already_published == 'false'
run: pnpm test

- name: Build
if: steps.version.outputs.already_published == 'false'
run: pnpm build

- name: Create GitHub Release
if: steps.version.outputs.already_published == 'false'
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.version.outputs.version }}
run: |
set -euo pipefail
TAG="v${VERSION}"

if gh release view "$TAG" >/dev/null 2>&1; then
echo "Release $TAG already exists — skipping create."
exit 0
fi

PREV_TAG="$(git describe --tags --abbrev=0 2>/dev/null || true)"
NOTES_FILE="$(mktemp)"

if [ -z "$PREV_TAG" ]; then
{
echo "## ${TAG}"
echo
echo "Initial release of \`@fqueis/openapi-contract\`."
} > "$NOTES_FILE"
else
{
echo "## ${TAG}"
echo
echo "Changes since ${PREV_TAG}:"
echo
git log "${PREV_TAG}..HEAD" --pretty=format:"- %s (%h)" --no-merges
echo
} > "$NOTES_FILE"

if ! grep -q '^- ' "$NOTES_FILE"; then
{
echo "## ${TAG}"
echo
echo "Changes since ${PREV_TAG}:"
echo
echo "- No non-merge commits since ${PREV_TAG}."
} > "$NOTES_FILE"
fi
fi

gh release create "$TAG" \
--title "$TAG" \
--notes-file "$NOTES_FILE" \
--target "${{ github.sha }}"

- name: Publish to npm
if: steps.version.outputs.already_published == 'false'
run: pnpm publish --access public --no-git-checks
35 changes: 26 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

MCP server that reads **OpenAPI contracts** from local (or remote) backends so agents can build frontends and mobile apps against the real API shape. This release is **read-only**: it inspects the OpenAPI document and never executes HTTP calls against your API. Backends are registered on demand; there is no env list of backends.

[![npm](https://img.shields.io/npm/v/@fqueis/openapi-contract.svg)](https://www.npmjs.com/package/@fqueis/openapi-contract)
[![PR Checks](https://github.com/fqueis/openapi-contract/actions/workflows/pr-checks.yml/badge.svg)](https://github.com/fqueis/openapi-contract/actions/workflows/pr-checks.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE.md)

Expand All @@ -23,12 +24,34 @@ Built with [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcon
## Requirements

- Node.js >= 18
- [pnpm](https://pnpm.io/)
- A backend that exposes OpenAPI (Nest Swagger: `/docs-json`, etc.)
- [pnpm](https://pnpm.io/) — only if you develop or contribute to this repo

---

## Setup
## Usage in Cursor (`mcp.json`)

Add to your Cursor MCP config (`~/.cursor/mcp.json` or Cursor Settings → MCP).

**Recommended (npm):**

```json
{
"mcpServers": {
"openapi-contract": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@fqueis/openapi-contract"]
}
}
}
```

You can run the server from a local clone for development, but for normal use prefer the published package above.

---

## Local development / contributors

```bash
cd /path/to/openapi-contract
Expand All @@ -37,13 +60,7 @@ pnpm build
pnpm test
```

---

## Usage in Cursor (`mcp.json`)

Add to your Cursor MCP config (`~/.cursor/mcp.json` or Cursor Settings → MCP).

**Recommended (built JS):**
**Built JS:**

```json
{
Expand Down
18 changes: 15 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "openapi-contract",
"name": "@fqueis/openapi-contract",
"version": "1.0.0",
"description": "MCP server that reads OpenAPI contracts from local backends for frontend/mobile agents",
"type": "module",
Expand All @@ -18,15 +18,27 @@
"lint:fix": "eslint \"{src,tests}/**/*.ts\" --fix",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage"
"test:coverage": "vitest run --coverage",
"prepublishOnly": "pnpm run build"
},
"keywords": [
"mcp",
"openapi",
"swagger"
],
"author": "",
"author": "fqueis",
"license": "MIT",
"homepage": "https://github.com/fqueis/openapi-contract#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/fqueis/openapi-contract.git"
},
"bugs": {
"url": "https://github.com/fqueis/openapi-contract/issues"
},
"publishConfig": {
"access": "public"
},
"packageManager": "pnpm@10.33.2",
"engines": {
"node": ">=18"
Expand Down