feat: DB inbound path (Toolbox config generator), MCP server fixes, v…#2
Merged
Conversation
…0.2.0
Bring up the ontology stack end-to-end and make the database inbound path
actually functional against the real Google MCP Toolbox.
- Add DSL -> Toolbox-native config generator (backend/mcp_server/toolbox_config.py)
+ `ontology mcp build`; `ontology deploy up` regenerates it automatically.
Maps type->kind, oracle database->serviceName, preserves ${VAR} (secrets stay
off disk), excludes ${...} raw-injection tools as gateway-native.
- Fix gateway _proxy_to_toolbox to use the Toolbox /mcp JSON-RPC endpoint
(legacy /api/tool/<name> is disabled in Toolbox >=1.5).
- Migrate custom MCP servers (canvas/slate/navigate/ldap) to FastMCP; Canvas
resolves by Canvas id / SIS id / sis_login_id and uses the real per-course
submissions endpoint.
- Add generic env-driven client-postgres source + parameterized
list-client-tables / describe-client-table tools + client-db-tools toolset.
- Split the higher-ed sample into config/tools.higher-ed.example.yaml and
config/roles.higher-ed.example.yaml so the default stack starts clean (the
Toolbox eagerly connects to every source at startup).
- docker-compose: load generated config via --config, fix duplicated toolbox arg.
- Add docs/read-only-db-user.md, per-service .env.*.example templates, CHANGELOG.
- Tests for the generator; update repo-config/identity tests for the new baseline.
- Bump version to 0.2.0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add MySQL support and make the DB connectors client-neutral so clients don't read them as backend-specific. - Add generic env-driven `client-mysql` source (CLIENT_MYSQL_*) + mysql-sql tools list-mysql-tables / describe-mysql-table (? placeholders, information_schema) + client-mysql-tools toolset. No generator change needed — MySQL is a first-class Toolbox source type. - Rename the Postgres connector for symmetry/neutrality: CLIENT_DB_* -> CLIENT_POSTGRES_*, list-client-tables -> list-postgres-tables, describe-client-table -> describe-postgres-table, client-db-tools -> client-postgres-tools. - Scrub deployment-specific names from tracked files (edx/openedx/ibl_dm_db/ dlmanager/ibl_local/ibleducation) -> generic placeholders; both connectors connect to any local or remote Postgres/MySQL by host + credentials. - Move source-network wiring out of the committed docker-compose.yml into a git-ignored override (add docker-compose.override.example.yml with a local and a remote pattern) so a fresh clone parses without pre-existing networks. - Docs: generic MySQL read-only user section + source-networking guidance. No version bump (branch not yet merged to main). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fixes raised in the setup/bringup-debug self-review before merge. - M1: extract a shared Toolbox /mcp client (backend/mcp_server/toolbox_client.py) and route BOTH the gateway (handlers._proxy_to_toolbox) and the sync engine (sync.engine.pull) through it. The sync engine was still calling the legacy /api/tool/<name> endpoint (disabled in Toolbox >=1.5) with the old response shape; now both callers use /mcp JSON-RPC and can't drift. - M2: Canvas get_student_submissions no longer aborts all courses when one course returns 403/concluded — per-course failures are skipped. - M3: Canvas user lookup no longer treats a bare numeric value as SIS-vs-Canvas ambiguously; a bare value is a Canvas user id and SIS ids must be passed as sis_user_id:<id> (they are often numeric). Docstrings/tool descriptions updated. - L1: `ontology deploy up` reports a clean error instead of a traceback when toolbox-config generation fails. - L2: removed the redundant local json import in the gateway proxy. - L3: MySQL list/describe tools alias columns so keys are lowercase (table_name/column_name), matching the Postgres tools. - L4: repo-config guard test now also requires client-mysql-tools. - L5: Canvas list endpoints follow Link rel=next pagination (no silent truncation). - Tests: new toolbox_client tests; updated sync pull test for the /mcp path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
Author
TestingAutomated (
|
| Component | Exercised | Result |
|---|---|---|
| Custom MCP servers (canvas/slate/navigate/ldap) | Import under FastMCP |
Pass |
| Canvas | get_student_courses / get_student_submissions against a live Canvas instance (admin token) |
Pass � returns real enrollment; per-course failures skipped; no crash |
PostgreSQL (client-postgres) |
list-postgres-tables / describe-postgres-table via the real Toolbox over /mcp against a live DB (~647 tables) |
Pass � real rows returned |
MySQL (client-mysql) |
list-mysql-tables / describe-mysql-table via the real Toolbox over /mcp against a live DB (~540 tables) |
Pass � real rows, keys lowercased to match Postgres |
| Read-only DB roles | SELECT succeeds; CREATE TABLE attempt |
Pass � writes denied on both Postgres and MySQL |
| Generated Toolbox config | Loaded by Google MCP Toolbox 1.5.0 and tools invoked over /mcp |
Pass |
| Compose portability | Base docker-compose.yml parses standalone; + override merges |
Pass |
Notes on the /mcp migration: both callers (the gateway handlers._proxy_to_toolbox and the sync engine pull()) now go through the shared toolbox_client, so the legacy /api/tool/<name> endpoint (disabled in Toolbox >= 1.5) is no longer used anywhere.
Not covered (tracked follow-ups)
- Full-stack
ontology deploy up(all services together) has not been run end-to-end. - The Canvas MCP server is validated live rather than via
pytest(it runs as a standalone container). config/initializer.pystill scaffolds the higher-ed sample forontology config init.
One-time normalization so the ruff CI (added next) passes repo-wide: - ruff format (0.14.14) applied to all Python files. - Import sorting (ruff check --select I) applied. - Removed a few unused imports / one unused local flagged by ruff check. No behavior changes; 173 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mirrors the data-manager workflow: pins ruff 0.14.14, checks `format --diff` and `check --select I` repo-wide, and lints changed files on every PR to main. Adds ruff.toml (target py311; excludes migrations + config/generated). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a Tests workflow: sets up Python 3.11, installs the package with the dev + django extras (what the suite needs), and runs `pytest` on PRs to main so the 173-test suite gates merges. Verified via a clean-venv install + run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`./dev.sh check` runs the same checks as CI (ruff format/import-sort/lint via the pinned 0.14.14, then pytest) so failures are caught before committing. Also `setup`, `test [args]`, `fmt`, `lint`. Documented under README "Local checks". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist
Changes
Makes the on-prem knowledge layer actually connect to real backends and cleans up the connector story so clients can point it at their own Canvas, PostgreSQL, and MySQL. Adds a DSL to Google MCP Toolbox config generator, fixes the custom MCP servers, ships generic backend-neutral database connectors, and separates deployment-specific wiring from the committed repo.
Branch:
setup/bringup-debug->main. Version stays0.2.0(unreleased).Why
The database inbound path was scaffolding: the shipped
docker-compose.ymlnever actually started the Toolbox (bad command), the repo'stools.yamlDSL is not the format the real Toolbox consumes, the gateway proxied to a Toolbox endpoint that is disabled in current versions, and all four custom MCP servers used an invalidmcp.server.ServerAPI. This branch makes the whole path work end-to-end and generic.What's included
Inbound: database path
backend/mcp_server/toolbox_config.py): translates the authoring DSL (kind: source|tool|toolset,type:) into the Toolbox-nativesources/tools/toolsetsmaps atconfig/generated/toolbox.yaml. Mapstype->kind, renames Oracledatabase->serviceName, preserves${VAR}tokens (secrets never written to disk), and excludes${...}raw-injection tools as gateway-native.ontology mcp build;ontology deploy upregenerates it automatically./mcpJSON-RPC endpoint (the legacy/api/tool/<name>REST path is disabled in Toolbox >= 1.5).client-postgres(CLIENT_POSTGRES_*) withlist-postgres-tables/describe-postgres-table.client-mysql(CLIENT_MYSQL_*) withlist-mysql-tables/describe-mysql-table(MySQL?placeholders +information_schema).Inbound: custom API MCP servers
canvas,slate,navigate,ldapfrom the invalidServer/@server.tool()usage toFastMCP.sis_login_id:(was SIS-only);get_student_submissionsuses the real per-course submissions endpoint and callsraise_for_status().Config and deployment
docker-compose.yml: Toolbox loads the generated config via--config; fixed the duplicatedtoolboxentrypoint arg. Deployment-specific external source networks were removed from the committed compose (a fresh clone now parses without pre-existing networks).docker-compose.override.yml, with a committeddocker-compose.override.example.ymlshowing Pattern A (local source container network, connect by hostname) and Pattern B (egress network for a remote source, connect by host/IP).config/tools.higher-ed.example.yaml+config/roles.higher-ed.example.yaml, so the default stack starts clean (the Toolbox eagerly connects to every source at startup)..env.*.exampletemplates;.gitignoreupdated so templates are tracked while real.env*, the override, and.python-versionstay ignored.Docs and tests
docs/read-only-db-user.md(read-only Postgres + MySQL user provisioning); updateddocs/deployment.mdanddocs/components/01-mcp-inbound.md; newCHANGELOG.md.Validation
Exercised end-to-end against live databases (not just unit tests):
/mcpagainst a live PostgreSQL and a live MySQL and returned real rows.docker-compose.ymlparses standalone (portable); base + override merges correctly.Notes and follow-ups (not in this PR)
config/initializer.py(used byontology config init) still scaffolds the full higher-ed sample.admin-dashboardservice referenced in compose has no build context yet.deploy up(all services together) has not been run end-to-end.Security
${VAR}tokens so credentials are never written to disk..exampletemplates are committed.