Merge pull request #181 from jonathanhefner/generate-api-docs

Add API documentation with GitHub Pages deployment
This commit is contained in:
Koichi ITO 2025-11-27 12:54:46 +09:00 • committed by GitHub
commit 00392b660d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 202 additions and 0 deletions

View file

@ -31,3 +31,14 @@ jobs:
ruby-version: 3.2 # Specify the oldest supported Ruby version. ruby-version: 3.2 # Specify the oldest supported Ruby version.
bundler-cache: true bundler-cache: true
- run: bundle exec rake rubocop - run: bundle exec rake rubocop
yard:
runs-on: ubuntu-latest
name: YARD Documentation
steps:
- uses: actions/checkout@v5
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.2 # Specify the oldest supported Ruby version.
bundler-cache: true
- run: bundle exec yard --no-output

View file

@ -23,3 +23,35 @@ jobs:
bundler-cache: true bundler-cache: true
ruby-version: 3.4 ruby-version: 3.4
- uses: rubygems/release-gem@v1 - uses: rubygems/release-gem@v1
publish_gh_pages:
if: github.repository_owner == 'modelcontextprotocol'
name: Publish Documentation to GitHub Pages
runs-on: ubuntu-latest
needs: [publish_gem]
permissions:
contents: write
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0 # Fetch all history for all branches and tags
- name: Configure Git
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: Get version tag
id: version
run: |
git fetch --tags
TAG=$(git describe --tags --exact-match HEAD)
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- name: Generate GitHub Pages
run: ./bin/generate-gh-pages.sh ${{ steps.version.outputs.tag }}
- name: Push to gh-pages
run: git push origin gh-pages

View file

@ -17,6 +17,8 @@ gem "activesupport"
gem "debug" gem "debug"
gem "rake", "~> 13.0" gem "rake", "~> 13.0"
gem "sorbet-static-and-runtime" gem "sorbet-static-and-runtime"
gem "yard", "~> 0.9"
gem "yard-sorbet", "~> 0.9"
group :test do group :test do
gem "faraday", ">= 2.0" gem "faraday", ">= 2.0"

View file

@ -940,3 +940,8 @@ The client provides a wrapper class for tools returned by the server:
- `MCP::Client::Tool` - Represents a single tool with its metadata - `MCP::Client::Tool` - Represents a single tool with its metadata
This class provides easy access to tool properties like name, description, input schema, and output schema. This class provides easy access to tool properties like name, description, input schema, and output schema.
## Documentation
- [SDK API documentation](https://rubydoc.info/gems/mcp)
- [Model Context Protocol documentation](https://modelcontextprotocol.io)

119
bin/generate-gh-pages.sh Executable file
View file

@ -0,0 +1,119 @@
#!/bin/bash
set -e
# Generates versioned documentation links and commits to gh-pages branch
#
# PURPOSE:
# This script generates a landing page with links to API documentation on
# RubyDoc.info for a specific version tag. This script is invoked by the
# publish-gh-pages job in the GitHub Actions workflow
# (.github/workflows/release.yml) when a release is published.
#
# HOW IT WORKS:
# - Creates isolated git worktrees for the specified tag and gh-pages branch
# - Copies static Jekyll template files from docs/
# - Generates _data/versions.yml with list of versions
# - Commits changes to gh-pages (does not push automatically)
#
# WORKFLOW:
# 1. Run this script with a tag name: `generate-gh-pages.sh v1.2.3`
# 2. Script generates docs and commits to local gh-pages branch
# 3. Push gh-pages branch to deploy: `git push origin gh-pages`
# Parse semantic version from tag name (ignoring arbitrary prefixes)
if [[ "${1}" =~ ([0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?)$ ]]; then
VERSION="v${BASH_REMATCH[1]}"
else
echo "Error: Must specify a tag name that contains a valid semantic version"
echo "Usage: ${0} <tag-name>"
echo "Examples:"
echo " ${0} 1.2.3"
echo " ${0} v2.0.0-rc.1"
exit 1
fi
TAG_NAME="${1}"
REPO_ROOT="$(git rev-parse --show-toplevel)"
echo "Generating documentation for tag: ${TAG_NAME}"
# Create temporary directories for both worktrees
WORKTREE_DIR=$(mktemp -d)
GHPAGES_WORKTREE_DIR=$(mktemp -d)
# Set up trap to clean up both worktrees on exit
trap 'git worktree remove --force "${WORKTREE_DIR}" 2>/dev/null || true; \
git worktree remove --force "${GHPAGES_WORKTREE_DIR}" 2>/dev/null || true' EXIT
echo "Creating worktree for ${TAG_NAME}..."
git worktree add --quiet "${WORKTREE_DIR}" "${TAG_NAME}"
# Check if gh-pages branch exists
if git show-ref --verify --quiet refs/heads/gh-pages; then
echo "Creating worktree for existing gh-pages branch..."
git worktree add --quiet "${GHPAGES_WORKTREE_DIR}" gh-pages
elif git ls-remote --exit-code --heads origin gh-pages > /dev/null 2>&1; then
echo "Creating worktree for gh-pages branch from remote..."
git worktree add --quiet "${GHPAGES_WORKTREE_DIR}" -b gh-pages origin/gh-pages
else
echo "Creating worktree for new orphan gh-pages branch..."
git worktree add --quiet --detach "${GHPAGES_WORKTREE_DIR}"
git -C "${GHPAGES_WORKTREE_DIR}" checkout --orphan gh-pages
git -C "${GHPAGES_WORKTREE_DIR}" rm -rf . > /dev/null 2>&1 || true
fi
# Change to gh-pages worktree
cd "${GHPAGES_WORKTREE_DIR}"
# Determine if this tag is the latest version
echo "Determining if ${VERSION} is the latest version..."
# Get all existing version tags from the repository (reverse sorted, newest first)
ALL_VERSIONS=$(
git -C "${REPO_ROOT}" tag --list | \
sed -nE 's/^[^0-9]*([0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?)$/v\1/p' | \
sort -Vr
)
# Get the latest version from all version tags
LATEST_VERSION=$(echo "${ALL_VERSIONS}" | head -n 1)
if [ "${VERSION}" = "${LATEST_VERSION}" ]; then
echo "${VERSION} is the latest version"
else
echo "${VERSION} is not the latest version (latest is ${LATEST_VERSION})"
fi
# Update custom documentation for latest version
if [ "${VERSION}" = "${LATEST_VERSION}" ]; then
echo "Updating custom documentation..."
# Clean up old custom docs from gh-pages root
echo "Cleaning gh-pages root..."
git ls-tree --name-only HEAD | xargs -r git rm -rf
# Copy custom docs from docs/ directory
echo "Copying custom docs from ${WORKTREE_DIR}/docs/..."
cp -r "${WORKTREE_DIR}/docs/." "${GHPAGES_WORKTREE_DIR}/"
fi
# Generate version data for Jekyll
echo "Generating _data/versions.yml..."
mkdir -p _data
echo "${ALL_VERSIONS}" | sed 's/^v/- /' > _data/versions.yml
# Stage all changes
git add .
# Commit if there are changes
if git diff --staged --quiet; then
echo "No changes to commit"
else
echo "Committing documentation for ${VERSION}..."
git commit -m "Add ${VERSION} docs"
echo "Documentation committed to gh-pages branch!"
echo "Push to remote to deploy to GitHub Pages"
fi
echo "Done!"

6
docs/_config.yml Normal file
View file

@ -0,0 +1,6 @@
# Use package name as site title
title: "MCP Ruby SDK"
# Include generated files and directories which may start with underscores
include:
- "_*"

7
docs/index.md Normal file
View file

@ -0,0 +1,7 @@
---
# Empty Jekyll front matter to enable Liquid templating (see {{ ... }} below)
---
{% for version in site.data.versions -%}
- [v{{ version }}](https://rubydoc.info/gems/mcp/{{ version }})
{% endfor %}

19
docs/latest/index.html Normal file
View file

@ -0,0 +1,19 @@
---
# Empty Jekyll front matter to enable Liquid templating (see {{ ... }} below)
---
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Redirecting to latest documentation...</title>
<meta http-equiv="refresh" content="0; url=https://rubydoc.info/gems/mcp">
<link rel="canonical" href="https://rubydoc.info/gems/mcp">
</head>
<body>
<p>Redirecting to <a href="https://rubydoc.info/gems/mcp">latest documentation</a>...</p>
<script>
window.location.href = "https://rubydoc.info/gems/mcp";
</script>
</body>
</html>

View file

@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
spec.metadata["homepage_uri"] = spec.homepage spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage
spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues" spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
spec.metadata["documentation_uri"] = "https://rubydoc.info/gems/mcp"
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
%x(git ls-files -z).split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } %x(git ls-files -z).split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }