Catalog MCP
by jphittell
README.md
# Catalog MCP
Standalone read-only MCP server for browsing Oracle HDL business object metadata from the local business-object ingestion repository.
The catalog index treats `attributes/*.json` as the source of truth. `manifest.json` is optional supplemental metadata used only when it matches an indexed attribute document.
## Local setup
1. Create a virtual environment with Python 3.10+.
2. Install dependencies.
3. Point `CATALOG_MCP_DATA_ROOT` at the business-object ingestion repo if you do not want the default sibling path.
```bash
'/Users/justin/.cache/codex-runtimes/codex-primary-runtime/dependencies/python/bin/python3' -m venv .venv
.venv/bin/python -m pip install -e '.[dev]'
cp .env.example .env
```
You can optionally scope the server to one or more exact business objects:
```bash
CATALOG_MCP_ALLOWED_OBJECTS=Worker
```
or:
```bash
CATALOG_MCP_ALLOWED_OBJECTS=Worker,Location
```
## Run the server
```bash
.venv/bin/python -m catalog_mcp.server
```
The server runs over `stdio` by default.
You can also use the checked-in launcher, which defaults `CATALOG_MCP_DATA_ROOT` to the sibling business-object repo on this laptop:
```bash
./scripts/run_catalog_mcp.sh
```
## Register with Codex
Add the server to local Codex MCP config:
```bash
codex mcp add businessObjectCatalog -- /Users/justin/Documents/Codex/Projects/MCP/scripts/run_catalog_mcp.sh
```
Verify the registration:
```bash
codex mcp list
codex mcp get businessObjectCatalog
```
## Test
```bash
.venv/bin/pytest
```
Run the end-to-end pressure matrix:
```bash
.venv/bin/python scripts/pressure_test_catalog.py
```
## Public MCP surface
- Tools:
- `catalog_health`
- `get_catalog_stats`
- `list_catalog_entries`
- `get_catalog_entry`
- `get_catalog_component`
- `get_catalog_attribute`
- `search_catalog`
- `search_catalog_attributes`
- `get_related_entries`
- `refresh_catalog_index`
- Resources:
- `catalog://summary`
- `catalog://product-areas`
- `catalog://stats`
- `catalog://entries/{entry_id}`
## Exact-Scope Retrieval
If an agent already knows the object, component, or field, prefer exact retrieval over broad search.
Examples:
```json
{"identifier":"Worker"}
```
```json
{"identifier":"Worker","component_name":"Worker"}
```
```json
{"identifier":"Worker","component_name":"Worker","attribute_name":"WorkerNumber"}
```