Contributing
How to build Protégé MCP from source, run its tests, find your way around the code, and add a tool.
Table of contents
- Build from source
- Run the tests
- Continuous integration
- Project layout
- How to add a tool
- Pull requests
- License
Build from source
You need Git, Apache Maven, and a JDK 17+ (the build targets --release 17):
git clone https://github.com/hakjuoh/protege-mcp.git
cd protege-mcp
mvn clean package
The target/ directory will contain protege-mcp-<version>.jar — a self-contained OSGi bundle that
inlines the MCP + Jetty + Jackson + Apache Jena stack. Protégé, the OWL API, Guava, and SLF4J are
provided (supplied by the Protégé platform at runtime), so they are not bundled.
To try your build, copy the jar into Protégé’s plugins/ folder (replacing any existing
protege-mcp-*.jar / io.github.hakjuoh-*.jar) and restart Protégé on a Java 17+ JVM. See
Installation.
Run the tests
mvn test
The suite covers the tool cores in isolation, and ToolPipelineTest chains them end-to-end
headlessly (load → edit → validate → govern → diff → SPARQL) so a cross-tool regression fails in
CI. What the unit tests cannot reach — the OSGi bundle loading in a real Protégé, the HTTP/OAuth
transport, EDT marshalling, and a live reasoner — is covered by a manual
Live smoke test checklist you run against the built jar before a release.
Continuous integration
CI runs mvn -B clean package
on JDK 17 (Temurin) for every push and pull request to main. Keep it green: a PR that fails to build
or test will not be merged.
Project layout
Everything lives under src/main/java/io/github/hakjuoh/:
| Package | Responsibility |
|---|---|
server |
The embedded HTTP MCP server: lifecycle (McpServerManager, McpServerController), Jetty host (EmbeddedHttpServer), auth (AccessTokenFilter), and OntologyAccess (marshals tool work onto the EDT). |
oauth |
The embedded OAuth authorization server (dynamic client registration, PKCE, consent, token store). |
tools |
The tool implementations. Each *Tools.java builds a list of SyncToolSpecifications; ToolCatalog aggregates them all. Prompts.java holds the guided prompts. |
chat |
The Ontology Assistant back end: the ChatProvider SPI and the Claude / Codex CLI providers + event parsers. |
ui |
Swing views/panels: McpServerView, McpPreferencesPanel, ChatView, ChatTab, ChatPreferencesPanel. |
config |
McpConfig — the settings snapshot backed by Protégé’s preferences store. |
The plugin’s extension points (views, tabs, preference panels, the editor-kit hook) are declared in
src/main/resources/plugin.xml.
How to add a tool
- Write the spec. In the appropriate
*Tools.java(or a new one), build aSyncToolSpecificationwithToolSpecs.of(name, description, inputSchema, handler):name— a stable, snake_case tool name.description— what it does and when to use it (LLM clients rely on this).inputSchema— a JSON SchemaMap(use theTools.schema()/ property helpers).handler— read args withTools.args(req), do the work, and return a structured result viaTools.json().put(...).result(). For reads, run throughctx.access().compute(...); for writes, gate with the read-only / confirm-write check and apply viaapplyChangesso the edit is GUI-visible and undoable.
- Register it. Make sure your
*Tools.specs(ctx)is added inToolCatalog.buildAll. - Test it. Add a unit test for the core, and extend
ToolPipelineTestif it participates in the end-to-end flow. - Document it. Add the tool to the matching page under Tools (arguments + returns), and bump the tool count in the README.
Keep every tool’s output structured JSON, reference entities by IRI or name, and — for create/add tools — report
new_entitiesand honourstrict, matching the existing tools.
Pull requests
- Branch from
main. - Make your change, with tests and docs.
- Open a PR against
main; make sure CI is green. - Keep commits focused; describe the why in the PR body.
Do not embed mutable VCS references (commit SHAs) in source or docs — use issue/PR numbers or release versions instead.
License
By contributing you agree that your contributions are licensed under the project’s BSD 2-Clause License.