Skip to content

Commit 9584b65

Browse files
feat/build pkgx install (#9)
* wip: testing pkgx & docker builds * feat: pkgx mcp registry * feat: pkgx --------- Signed-off-by: Brian Horakh <[email protected]>
1 parent 344dfe4 commit 9584b65

File tree

9 files changed

+228
-20
lines changed

9 files changed

+228
-20
lines changed

.github/workflows/docker.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,43 @@ jobs:
5454
platforms: linux/amd64
5555
tags: ${{ steps.meta.outputs.tags }}
5656
labels: ${{ steps.meta.outputs.labels }}
57+
58+
publish-mcp:
59+
needs: build-and-push
60+
if: startsWith(github.ref, 'refs/tags/v')
61+
runs-on: ubuntu-latest
62+
permissions:
63+
contents: read
64+
id-token: write
65+
steps:
66+
- name: Checkout
67+
uses: actions/checkout@v4
68+
69+
- name: Install MCP Publisher
70+
run: |
71+
curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" \
72+
| tar xz mcp-publisher
73+
chmod +x mcp-publisher
74+
75+
- name: Prepare server manifest
76+
run: |
77+
VERSION=${GITHUB_REF#refs/tags/v}
78+
IMAGE_REPO=$(echo "${GITHUB_REPOSITORY}" | tr '[:upper:]' '[:lower:]')
79+
IMAGE="ghcr.io/${IMAGE_REPO}:$VERSION"
80+
jq --arg v "$VERSION" --arg image "$IMAGE" '
81+
.version = $v
82+
| .packages = (.packages // [] | map(
83+
if .registryType == "oci" then
84+
(.identifier = $image)
85+
else .
86+
end
87+
| (if has("version") then .version = $v else . end)
88+
))
89+
' server.json > server.publish.json
90+
mv server.publish.json server.json
91+
92+
- name: Login to MCP Registry
93+
run: ./mcp-publisher login github-oidc
94+
95+
- name: Publish to MCP Registry
96+
run: ./mcp-publisher publish

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@
77
- add an Alpine-based Docker image build + entrypoint script plus usage docs for container publishing
88
- publish the container automatically to GHCR using `.github/workflows/docker.yml`
99
- update Docker builder stage to the latest stable Rust toolchain (1.91.1) for smaller, faster binaries
10+
- add a self-contained pkgx pantry (`pkgx/`) with build/test metadata so `pkgx cratedocs` can install the server via the pkgx runtime, plus README instructions for using and upstreaming it
11+
- add `just install-pkgx` to verify the pkgx pantry wiring end-to-end (falls back to a helpful message until the package is mirrored onto dist.pkgx.dev)

README.md

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Rust Cargo Docs RAG MCP
22

3-
`rust-cargo-docs-rag-mcp` is an MCP (Model Context Protocol) server that provides Rust crate documentation lookup and search tools intended for LLM assistants and other tooling.
3+
`rust-cargo-docs-rag-mcp` is an MCP (Model Context Protocol) server that provides tools for Rust crate documentation lookup. It allows LLMs to look up documentation for Rust crates they are unfamiliar with.
44

55
This README focuses on how to build, version, release, and install the project using two common paths:
66
1. pkgx (build/install locally from source)
@@ -10,6 +10,30 @@ This README focuses on how to build, version, release, and install the project u
1010

1111
## Release / Versioning workflow (maintainers)
1212

13+
```bash
14+
git clone https://github.com/promptexecution/rust-cargo-docs-rag-mcp.git
15+
cd rust-cargo-docs-rag-mcp
16+
cargo build --release
17+
cargo install --path .
18+
# Or install the pkgx-managed binary and check its version
19+
just install-pkgx
20+
```
21+
22+
### Installing with pkgx
23+
24+
The repository includes a mini [pkgx pantry](./pkgx) so you can build and run the CLI through `pkgx` without touching your global toolchain:
25+
26+
```bash
27+
git clone https://github.com/promptexecution/rust-cargo-docs-rag-mcp.git
28+
cd rust-cargo-docs-rag-mcp
29+
export PKGX_PANTRY_PATH=$PWD/pkgx
30+
export PKGX_PANTRY_DIR=$PWD/pkgx # pkgx^2 compatibility
31+
pkgx cratedocs version
32+
```
33+
34+
`pkgx` will download the tagged source tarball, compile `cratedocs` with the required Rust toolchain, and cache the result for subsequent runs. Once you're ready to upstream this package to the central [pkgx pantry](https://github.com/pkgxdev/pantry), copy `pkgx/projects/github.com/promptexecution/rust-cargo-docs-rag-mcp/package.yml` into a new PR there.
35+
36+
## Running the Server
1337
This repository is wired to Cocogitto via `cog.toml`. Typical flow to create a release:
1438

1539
1. Install Cocogitto (once)
@@ -66,6 +90,32 @@ Run in stdio mode:
6690
docker run --rm -e CRATEDOCS_MODE=stdio -i ghcr.io/promptexecution/rust-cargo-docs-rag-mcp:latest
6791
```
6892

93+
### Using Docker
94+
95+
You can also build and run the server in an Alpine-based container. Prebuilt images are automatically published to GHCR via [`.github/workflows/docker.yml`](.github/workflows/docker.yml):
96+
97+
```bash
98+
docker pull ghcr.io/promptexecution/rust-cargo-docs-rag-mcp:latest
99+
```
100+
101+
To build locally (useful before pushing to another registry):
102+
103+
```bash
104+
# Build the image (adjust the tag to match your registry)
105+
docker build -t promptexecution/rust-cargo-docs-rag-mcp .
106+
107+
# Run HTTP/SSE mode on port 8080
108+
docker run --rm -p 8080:8080 promptexecution/rust-cargo-docs-rag-mcp
109+
```
110+
111+
Configuration is controlled through environment variables:
112+
- `CRATEDOCS_MODE` (default `http`): switch to `stdio` to expose the stdio MCP server
113+
- `CRATEDOCS_ADDRESS` (default `0.0.0.0:8080`): bind the HTTP server to a specific interface/port
114+
- `CRATEDOCS_DEBUG` (default `false`): set to `true` to enable verbose logging in HTTP mode
115+
116+
All additional arguments appended to `docker run ... -- <args>` are forwarded to the underlying `cratedocs` process.
117+
118+
### Directly Testing Documentation Tools
69119
### Environment Variables
70120

71121
- `CRATEDOCS_MODE` (default: `http`) — set to `stdio` to run the stdio MCP server
@@ -397,6 +447,17 @@ Then reference it normally in `mcp_settings.json`:
397447

398448
---
399449

450+
## Versioning & Releases
451+
452+
This repository includes a [`cog.toml`](./cog.toml) profile wired to [`scripts/set-version.sh`](./scripts/set-version.sh) so [Cocogitto](https://github.com/cocogitto/cocogitto) can bump the crate version and regenerate the changelog automatically.
453+
454+
Typical release flow:
455+
1. `cargo install cocogitto` (once)
456+
2. `cog bump minor` (or `patch`/`major`) – this updates `Cargo.toml`, `Cargo.lock`, and `CHANGELOG.md`
457+
3. Review the generated changelog, run tests, and push the resulting tag/commit
458+
459+
See [`CHANGELOG.md`](./CHANGELOG.md) for the latest published versions.
460+
400461
## License
401462

402463
MIT License

docker/entrypoint.sh

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
#!/bin/sh
2-
set -e
2+
set -eu
33

4-
# docker/entrypoint.sh - small wrapper to start cratedocs with the configured mode
54
MODE="${CRATEDOCS_MODE:-http}"
65
ADDRESS="${CRATEDOCS_ADDRESS:-0.0.0.0:8080}"
76
DEBUG="${CRATEDOCS_DEBUG:-false}"
87

8+
if [ "$MODE" = "http" ]; then
9+
if [ "$DEBUG" = "true" ]; then
10+
exec /usr/local/bin/cratedocs http --address "$ADDRESS" --debug "$@"
11+
else
12+
exec /usr/local/bin/cratedocs http --address "$ADDRESS" "$@"
13+
fi
14+
else
15+
exec /usr/local/bin/cratedocs "$MODE" "$@"
16+
fi
917
# If explicit args provided, run with those
1018
if [ "$#" -gt 0 ]; then
1119
exec /usr/local/bin/cratedocs "$@"

justfile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ pkgx-test:
1616
run:
1717
cargo run --bin cratedocs http --address 0.0.0.0:3000 --debug
1818

19+
install-pkgx:
20+
@echo "Using pkgx pantry at {{invocation_directory()}}/pkgx"
21+
PKGX_PANTRY_PATH={{invocation_directory()}}/pkgx \
22+
PKGX_PANTRY_DIR={{invocation_directory()}}/pkgx \
23+
pkgx cratedocs version || \
24+
(echo "pkgx failed (likely no network); see README for manual steps" && exit 1)
25+
1926
docker-build:
2027
docker build -t promptexecution/rust-cargo-docs-rag-mcp .
2128

pkgx/pkgx.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
dependencies:
2+
pkgx.sh/brewkit: ^0 || ^1
3+
4+
env:
5+
PKGX_PANTRY_PATH: ${{srcroot}}
6+
PKGX_PANTRY_DIR: ${{srcroot}}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
distributable:
2+
url: https://github.com/promptexecution/rust-cargo-docs-rag-mcp/archive/refs/tags/{{ version.tag }}.tar.gz
3+
strip-components: 1
4+
5+
versions:
6+
github: promptexecution/rust-cargo-docs-rag-mcp
7+
8+
dependencies:
9+
openssl.org: '>=1.1'
10+
11+
build:
12+
dependencies:
13+
rust-lang.org: '>=1.91'
14+
rust-lang.org/cargo: '*'
15+
script:
16+
- cargo install --locked \
17+
--root={{ prefix }} \
18+
--path=. \
19+
--bin cratedocs
20+
21+
provides:
22+
- bin/cratedocs
23+
24+
test:
25+
- cratedocs version | grep {{version}}

scripts/set-version.sh

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,52 @@
1-
#!/bin/sh
2-
set -e
1+
#!/usr/bin/env bash
2+
set -euo pipefail
33

4-
if [ -z "$1" ]; then
5-
echo "Usage: $0 <version>" >&2
6-
exit 2
4+
if [ "$#" -ne 1 ]; then
5+
echo "usage: $0 <semver>" >&2
6+
exit 1
77
fi
8-
VER="$1"
98

10-
# Update Cargo.toml version field
11-
if command -v perl >/dev/null 2>&1; then
12-
perl -0777 -pe "s/^version\s*=\s*\".*\"/version = \"${VER}\"/m" -i Cargo.toml
13-
else
14-
sed -E "s/^version[[:space:]]*=.*$/version = \"${VER}\"/" Cargo.toml > Cargo.toml.tmp && mv Cargo.toml.tmp Cargo.toml
15-
fi
9+
version="$1"
1610

17-
# Regenerate lockfile
18-
if command -v cargo >/dev/null 2>&1; then
19-
cargo generate-lockfile || true
20-
fi
11+
# Update Cargo.toml package version (first occurrence only to avoid dependency matches)
12+
python3 - "$version" <<'PY'
13+
import pathlib, re, sys
14+
version = sys.argv[1]
15+
path = pathlib.Path("Cargo.toml")
16+
text = path.read_text()
17+
new_text, count = re.subn(r'(?m)^(version\s*=\s*)"[^"]+"', rf'\1"{version}"', text, count=1)
18+
if count != 1:
19+
raise SystemExit("Could not update version in Cargo.toml")
20+
path.write_text(new_text)
21+
PY
22+
23+
# Update Cargo.lock entry for this crate
24+
python3 - "$version" <<'PY'
25+
import pathlib, sys
26+
version = sys.argv[1]
27+
path = pathlib.Path("Cargo.lock")
28+
lines = path.read_text().splitlines()
29+
out_lines = []
30+
in_pkg = False
31+
target = 'name = "rust-cargo-docs-rag-mcp"'
32+
updated = False
33+
for line in lines:
34+
stripped = line.strip()
35+
if stripped == target:
36+
in_pkg = True
37+
out_lines.append(line)
38+
continue
39+
if in_pkg and stripped.startswith("version = "):
40+
out_lines.append(f'version = "{version}"')
41+
in_pkg = False
42+
updated = True
43+
continue
44+
if stripped.startswith("name = ") and stripped != target:
45+
in_pkg = False
46+
out_lines.append(line)
47+
48+
if not updated:
49+
raise SystemExit("Could not update version in Cargo.lock")
2150
22-
exit 0
51+
path.write_text("\n".join(out_lines) + "\n")
52+
PY

server.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-10-17/server.schema.json",
3+
"name": "io.github.promptexecution/rust-cargo-docs-rag-mcp",
4+
"title": "Rust Cargo Docs RAG",
5+
"description": "Lookup Rust crate and item documentation via docs.rs and crates.io search.",
6+
"websiteUrl": "https://github.com/promptexecution/rust-cargo-docs-rag-mcp",
7+
"repository": {
8+
"url": "https://github.com/promptexecution/rust-cargo-docs-rag-mcp",
9+
"source": "github"
10+
},
11+
"version": "0.3.0",
12+
"packages": [
13+
{
14+
"registryType": "oci",
15+
"identifier": "ghcr.io/promptexecution/rust-cargo-docs-rag-mcp:0.3.0",
16+
"runtimeHint": "docker",
17+
"transport": {
18+
"type": "stdio"
19+
},
20+
"environmentVariables": [
21+
{
22+
"name": "CRATEDOCS_MODE",
23+
"value": "stdio",
24+
"description": "Ensure the container exposes the MCP stdio transport when run by clients."
25+
}
26+
]
27+
}
28+
]
29+
}

0 commit comments

Comments
 (0)