Distributing via Protégé’s “Check for plugins”
Protégé can discover and install this plugin from File ▸ Check for plugins — no manual jar
copying. That menu reads a plugin registry (a .repository URL list) and, for each listed
update descriptor (update.properties), offers the plugin when its id
(= Bundle-SymbolicName, here io.github.hakjuoh) is either not yet installed, or installed at a
lower version. Both files are published from this GitHub repo, so you can install straight from
the official registry with nothing to fill in:
protege-mcp.repository— the registry list, served from themainbranch athttps://raw.githubusercontent.com/hakjuoh/protege-mcp/main/protege-mcp.repository. Because Protégé’s “Plugin registry” is a single URL, this file lists our descriptor and nests Protégé’s default registry, so pointing Protégé here shows protege-mcp alongside the full official catalog (Cellfie, ELK, OntoGraf, OWLViz, …) — you don’t lose the standard plugins.update.properties— the update descriptor it points at (id/name/version/download/readme/author), served fromhttps://raw.githubusercontent.com/hakjuoh/protege-mcp/main/update.properties. ItsdownloadURL is the jar attached to the v0.1.0 GitHub Release.
This is Distribution Path B (how the jar is delivered), the counterpart to the manual-copy install (Distribution Path A). It is unrelated to Architecture Approach B (the in-app Claude chat) in
DESIGN.md— that is the plugin’s internal shape, not its delivery. The sameBundle-SymbolicName/ version rules used here are described inDESIGN.md§7 (Packaging).
Install from the official registry (no setup)
-
Point Protégé at the registry. Settings ▸ Plugins ▸ “Plugin registry” → paste
https://raw.githubusercontent.com/hakjuoh/protege-mcp/main/protege-mcp.repository(The field defaults to the official Protégé registry; “Reset to default registry location” restores it.)
- Discover it. File ▸ Check for plugins → “Protege MCP Server” appears in the list (together with the official plugins, since this registry nests Protégé’s default one).
- Install it. Select it and confirm. Protégé downloads the jar named in
update.properties(download=…/releases/download/v0.1.0/protege-mcp-0.1.0.jar) straight from the GitHub Release and drops it into your plugins directory. - Restart Protégé on a Java 17+ JVM (see Requirements). On reload you get the MCP Server view and the Settings ▸ MCP tab.
How the discovery chain is wired (all on GitHub). The registry URL you paste serves
protege-mcp.repository; its single line points Protégé at the rawupdate.propertiesonmain; that descriptor’sdownloadpoints at theprotege-mcp-0.1.0.jarasset on the v0.1.0 Release. Registry list → update descriptor → release asset — three hops, all hosted by this repo, nothing to host yourself.
If Check for plugins shows an empty list, the registry or
downloadURL was unreachable: an unresolvable URL is logged atinfolevel and silently skipped, not shown as an error. Confirm the registry URL above resolves (open it in a browser) and that the v0.1.0 Release asset exists.
Use your own fork
If you fork the project and want to serve the plugin from your account instead:
- Publish the jar. Build (
mvn clean package) and uploadtarget/protege-mcp-<v>.jarsomewhere downloadable — e.g. attach it to a GitHub Release on your fork. - Repoint the URLs. In
update.properties, setdownload=(andreadme=) to your fork’s URLs; inprotege-mcp.repository, change the raw URL so it resolves to your fork’supdate.properties. Commit and push both so their raw URLs are reachable, e.g.https://raw.githubusercontent.com/<you>/protege-mcp/main/protege-mcp.repository. Pointreadme=at a raw, self-contained simple HTML file (like the official plugins’readme.html— heredocs/readme.html), e.g.raw.githubusercontent.com/<you>/protege-mcp/main/docs/readme.html. Protégé ignores the serverContent-Type(raw GitHub servestext/plain) and instead sniffs the body for<html>, rendering it as HTML in a SwingJEditorPane(HTML 3.2) when found, else as plain text — so a raw.htmlfile renders formatted. Never use agithub.com/…/blob/…page: that returns the GitHub web-app HTML, which renders as garbage and whose fetch freezes the dialog.license=is opened in the external browser, so a/blob/URL is fine there. - Point Protégé at your registry (step 1 above) and run Check for plugins.
Quick local test (no hosting)
Serve the repo over loopback HTTP and point a temporary jar URL at your build output:
# from the repo root, after `mvn clean package`:
python3 -m http.server 8000 # serves ./protege-mcp.repository, ./update.properties, ./target/...
Temporarily set download=http://127.0.0.1:8000/target/protege-mcp-<v>.jar in update.properties,
then set the Plugin-registry preference to http://127.0.0.1:8000/protege-mcp.repository and run
Check for plugins.
The registry URL you put in Settings must be http(s) — Check for plugins does an
HttpURLConnectionHEAD on it first, so afile://registry root fails there with an uncaughtClassCastException(the action only catchesIOException, so it errors out rather than showing the normal “could not connect” dialog). Thedownload=URL inside the descriptor may befile://.
Version rules (so it actually shows up)
version is compared as an OSGi version. OSGi orders an empty qualifier before a non-empty
one, so 0.1.0 < 0.1.0.SNAPSHOT. Consequences:
- Installing into a Protégé that doesn’t have the plugin yet → it appears regardless of
version. - Updating over an already-installed build →
versionmust be strictly greater than the installed bundle version. Over a0.1.0.SNAPSHOTdev build, use e.g.0.1.1, not0.1.0; to ship an update over the released0.1.0, bumpupdate.propertiesversionand the bundle version together (e.g.0.1.1) and attach the new jar to a matching Release.
Or get it into the official list
To appear in everyone’s Protégé (the default registry), open a PR adding your update.properties
URL to update-info/5.0.0/plugins.repository in
protegeproject/autoupdate — same descriptor format
as above.