feat!: migrate SDK + MCP to omnigraph-server v0.7.0 (cluster-only)#12
Conversation
Sync the SDK to omnigraph-server v0.7.0. The dominant upstream change is
cluster-only serving (RFC-011 #250): every operational endpoint moves from
`/x` to `/graphs/{graph_id}/x`; only `GET /healthz` and `GET /graphs` stay
flat. Also: canonical `POST /load` (deprecating `/ingest`, #222), optional
`expect_mutation` on stored-query invoke (#247), and a 409 on schema apply
for cluster-managed graphs (#258).
Breaking (hard cutover, per repo major.minor=server policy):
- `graphId` is now required for graph-scoped operations. The transport throws
the new typed `ConfigurationError` (status 0) before any network call when a
graph-scoped method runs without one. `health()` and `graphs.list()` remain
graph-independent. SDK 0.7.x targets a 0.7.x server only.
SDK:
- add `og.load()` (canonical); mark `og.ingest()` deprecated (server keeps it
as a shim with Deprecation/Link headers)
- `expectMutation` passthrough on `queries.invoke()`
- regen types from v0.7.0 spec: `IngestOutput.base_branch` now nullable/optional;
`InvokeRequest.expect_mutation` added
- export `ConfigurationError`
MCP:
- add `load` tool (canonical); `ingest` becomes the deprecated alias
- require `OMNIGRAPH_GRAPH_ID` (cluster-only)
Tooling/CI:
- `check-coverage` is graphId-prefix-aware (mirrors the transport rewrite)
- e2e rewritten to boot a local-filesystem cluster (cluster import/apply/load,
`--cluster` boot) with Cedar policy bundles granting `graph_list` +
per-graph data actions; collapsed the two jobs into one (alpha + beta)
- bump all three versions to 0.7.0; README/MCP docs updated for the cluster model
- sync-cookbook: skills moved to ModernRelay/omnigraph (skills/omnigraph/references)
Verified end-to-end against the real v0.7.0 server binary: 90 unit + 21 live
e2e tests pass; full gate (versions/drift/coverage/build/typecheck/test) green.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b5bfa40fbb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| - name: Start omnigraph-server in multi-graph mode | ||
| omnigraph cluster import --config "$dir" | ||
| omnigraph cluster apply --config "$dir" |
There was a problem hiding this comment.
Pass an actor to cluster apply
In this fresh Actions runner, nothing creates an operator config with operator.actor before the new cluster setup runs. The 0.7 command reference documents cluster apply as omnigraph cluster apply --config <dir> --as <actor> (reference), so this job can fail during setup before the server ever starts; add an explicit actor such as --as ci here, or create the operator config first.
Useful? React with 👍 / 👎.
This major release drops the deprecated SDK methods and MCP tools in favor of a single canonical surface: query / mutate / load. Removed: - SDK: og.read(), og.change(), og.ingest() and the ChangeInput / LegacyChangeInput / ReadInput types (+ the change-input normalization shim). - MCP: the `read`, `change`, `ingest` tools (and their legacy-field handling). The server still serves /read, /change, /ingest as indefinite shims, so a pre-0.7 SDK keeps working — this SDK just no longer calls them. check-coverage now carries an explicit INTENTIONALLY_UNBOUND allowlist for those three spec ops, logged on every run (never silent) and fail-fast if the allowlist goes stale, so coverage stays honest for everything else. Tests converted (read→query, change→mutate, ingest→load) or dropped where they exercised removed alias behavior; READMES + MCP instructions updated to the canonical verbs. Verified: full gate green; 86 unit + 20 live e2e tests pass against the edge (latest upstream) server.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 97bfb58. Configure here.
… apply
omnigraph-server 0.7.0 is cluster-only, and a cluster-managed graph rejects
POST /graphs/{id}/schema/apply with 409 ("schema apply disabled for
cluster-backed serving"). The MCP previously exposed a `schema_apply` tool that
called og.schema.apply() and advertised idempotent HTTP migration — on the only
supported deployment it could never succeed, and the INSTRUCTIONS steered agents
to it.
Schema evolution on a cluster graph is an operator action (`omnigraph cluster
apply`), outside the data-plane HTTP API this MCP wraps. So:
- remove the `schema_apply` MCP tool; keep `schema_get` (read-only).
- rewrite the INSTRUCTIONS norms + best-practices pointer accordingly.
- README/test updated; added a test asserting schema_apply is NOT exposed.
The SDK keeps og.schema.apply() — it is a faithful binding for the spec endpoint
and correctly surfaces the 409 (covered by a unit test); the README now caveats
that it is rejected on a cluster-managed graph. Coverage unaffected
(/schema/apply still bound by the SDK method). Full gate green.

What
Syncs
@modernrelay/omnigraphand@modernrelay/omnigraph-mcpfrom server pin v0.6.1 → v0.7.0.Of the 231 upstream commits in
v0.6.1..v0.7.0, only 6 touch the HTTP contract (verified by diffing the actualopenapi.json). v0.6.2 was a pure no-op (byte-identical spec apart frominfo.version), so this goes straight to 0.7.0./x→/graphs/{graph_id}/x; only/healthz+/graphsstay flat/ingestno longer implicitly forks (missing branch w/ofrom→ 404);IngestOutput.base_branchnullablePOST /load;/ingestdeprecated (kept as a shim, emits Deprecation/Link)expect_mutationonPOST /queries/{name}(mismatch → 400)POST /…/schema/applycan return 409 on a cluster-managed graphNet schema-component delta is exactly two edits:
base_branchnullable/optional and the new optionalexpect_mutation. Codegen is types-only, so the upstreamoperationId → cluster_*rename is a non-event here.Breaking change —
graphIdis now required (hard cutover)The server is cluster-only, so graph-scoped calls require a
graphId. The transport throws the new typedConfigurationError(status 0, client-side, before any network call) when a graph-scoped method runs without one.health()andgraphs.list()remain graph-independent. Per the repo'smajor.minor = serverpolicy, SDK 0.7.x targets a 0.7.x server only; stay on@modernrelay/omnigraph@0.6.xfor a 0.6.x server.Changes
SDK
og.load()(canonical) added;og.ingest()marked@deprecatedConfigurationErrorexported; transport guard for missinggraphIdexpectMutationpassthrough onqueries.invoke()MCP
loadtool added;ingestbecomes the deprecated aliasOMNIGRAPH_GRAPH_IDnow required at thebinentrypointsync-cookbookrepointed to the relocated skill references inModernRelay/omnigraph(skills/omnigraph/references); 3 new refs (cluster/migrations/stored-queries) marked skippedTooling / CI
check-coveragemade graphId-prefix-aware (mirrors the transport rewrite)cluster import→cluster apply→load --mode overwrite→omnigraph-server --cluster, with Cedar policy bundles grantinggraph_list(cluster-scoped) + the per-graph data actions. The two e2e jobs collapse into one (alpha + beta).Verification
Run against the real v0.7.0 server binary (macos-arm64), not just mocks:
check-versions,check-drift,check-coverage(20/20),build,typecheckGET /graphsis closed-by-default and opens with acluster-scopedgraph_listgrant; data plane works; bad token → 401Consumer migration
graphId(discover viaog.graphs.list()→og.graph(id)); graph-scoped calls without one throwConfigurationErrorog.ingest()→og.load()(identical shapes; ingest stays as a shim)from(else 404)schema.apply()on a cluster-managed graph returns 409Note
High Risk
Major breaking API and routing changes (required graphId, removed SDK/MCP aliases) affect all consumers; upgrading the server without updating clients like omnigraph-ui will break graph calls with 404s while health checks still pass.
Overview
Breaking release for
@modernrelay/omnigraphand@modernrelay/omnigraph-mcp: server pin 0.6.1 → 0.7.0, packages at 0.7.0, OpenAPI/types regenerated for cluster-scoped paths.The SDK now treats 0.7.0 as cluster-only: graph-scoped calls go under
/graphs/{graphId}/…, and missinggraphIdthrowsConfigurationErrorbefore the network (onlyhealth()andgraphs.list()stay flat). Removedog.read,og.change, andog.ingest; callers useog.query,og.mutate, andog.load(POST /load). Bulk load no longer implicitly forks a branch withoutfrom. Stored-query invoke can passexpectMutation.schema.apply()remains but cluster graphs can answer 409.MCP requires
OMNIGRAPH_GRAPH_IDat startup; legacyread/change/ingesttools are gone in favor ofquery/mutate/load, andschema_applyis not exposed (schema via cluster apply). Cookbook sync pulls fromModernRelay/omnigraphskill references.CI/docs: e2e collapses to one job that builds a local
cluster.yamlcluster (alpha + beta, Cedar policies), seeds withomnigraph load, and runs tests withomnigraph-server --cluster.check-coveragestrips the graph prefix when matching spec ops and allowlists deprecated/read,/change,/ingestshims as intentionally unbound.Reviewed by Cursor Bugbot for commit e6b33e6. Bugbot is set up for automated code reviews on this repo. Configure here.
Greptile Summary
Migrates
@modernrelay/omnigraphand@modernrelay/omnigraph-mcpfrom server pin v0.6.1 → v0.7.0 (cluster-only). Graph-scoped HTTP calls are now routed under/graphs/{graphId}/…; a missinggraphIdthrowsConfigurationErrorclient-side before any network call. The deprecatedog.read/og.change/og.ingestaliases are dropped in favour ofog.query/og.mutate/og.load.ConfigurationError,og.load()canonical endpoint,expectMutationpassthrough on stored-query invoke, regenerated types (base_branchnullable, optionalexpectMutation), andog.graph(id)for scoped fan-out.loadtool replacesingest;schema_applytool removed (cluster graphs reject HTTP schema apply with 409);OMNIGRAPH_GRAPH_IDrequired atbinstartup; INSTRUCTIONS string and cookbook sync all updated.cluster import/apply, andomnigraph loadseed the local-filesystem cluster before booting the server.Confidence Score: 4/5
Safe to merge as an npm package release, but deploying the 0.7.0 server alongside the current
omnigraph-uiwill silently break all UI data-fetching — the UI's healthz probe stays green while every branch/commit/query call 404s.The SDK and MCP changes are well-implemented and thoroughly tested (90 unit + 21 live e2e). The transport guard, path-prefixing, error hierarchy, coverage check, and CI rewrite are all correct. The blocking concern is cross-repo:
omnigraph-ui/src/lib/omnigraph.tsstill calls flat paths (/snapshot,/branches,/commits,/read,/change,/export) with no cluster routing awareness. Upgrading the server to 0.7.0 without a companion UI PR will break every UI data call while the health indicator stays green, making the failure hard to notice.omnigraph-ui/src/lib/omnigraph.tsin the related UI repo needs a companion PR before the 0.7.0 server is deployed.Important Files Changed
graphIdprefixing under/graphs/{id}/…,FLAT_PATHSexempts/healthzand/graphs, and throwsConfigurationError(status 0) before any network call when a graph-scoped op is issued without agraphId. Logic is clean and well-tested.ConfigurationError(client-side, status 0) to the typed error hierarchy and exports it. No issues.og.read,og.change,og.ingest; adds canonicalog.load()(POST /load),og.graph(id)for scoped clones; all graph-scoped methods delegate through Transport which handles the/graphs/{id}/prefix.read,change,ingest,schema_applytools; addsloadtool; INSTRUCTIONS string fully updated to canonicalload/mutate/querylanguage. Minor:graphId?: stringinCreateServerOptionsis typed as optional but required at runtime for all graph-scoped tool calls.OMNIGRAPH_GRAPH_IDis missing. No issues./graphs/{id}/from spec paths before matching, allowlists deprecated/read,/change,/ingestshims, and has a stale-allowlist check that fails CI if the server drops a shim from the spec. Logic is sound.cluster-scoped (graph_list) and per-graph data actions. Clean consolidation with good coverage of auth (UnauthorizedError) and cluster routing.expectMutationpassthrough oninvoke(); camelCase input is correctly converted to snake_caseexpect_mutationby the transport'scamelToSnakeserializer. No issues.Comments Outside Diff (3)
packages/mcp/src/server.ts, line 40-48 (link)ingestreferences in system INSTRUCTIONSThe
INSTRUCTIONSstring — which is injected as the LLM system prompt — still referencesingestin four places after this PR promotesloadas the canonical tool:omnigraph://best-practices/datadescription says "before ingest"`ingest mode: "merge"` upserts by @keybranches_create → \ingest` onto the branch`fall back to \ingest` on a branch`Agents reading these instructions will preferentially call the deprecated
ingestshim instead of the canonicalloadtool, which is the opposite of the migration intent. Sinceingestis kept as a shim it won't break anything at runtime today, but the instructions actively work against the deprecation.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
packages/sdk/README.md, line 8-11 (link)omnigraph-uiraw HTTP calls are broken against the 0.7.0 serveromnigraph-ui/src/lib/omnigraph.tsmakes directfetchcalls to flat paths (/snapshot,/branches,/commits,/read,/change,/export) with nographIdawareness. Every one of these routes is now served exclusively under/graphs/{id}/…in the 0.7.0 cluster-only server — only/healthzstays flat. Upgrading the server to 0.7.0 will silently break all UI data-fetching (every call returns 404), leaving the health indicator green while all branch/commit/data calls fail. The UI'shealthz()probe returningtruewill mask the failures from end-users.A companion PR to
omnigraph-uiis needed: at minimum add aVITE_OMNIGRAPH_GRAPH_IDenv var and prefix all non-healthz paths with/graphs/${graphId}/, and migrate theGET /exportcall toPOST /graphs/${graphId}/exportwith a body (the HTTP method changed too).packages/sdk/README.md, line 1 (link)omnigraph-uiraw HTTP calls are broken against the 0.7.0 serveromnigraph-ui/src/lib/omnigraph.tsmakes directfetchcalls to flat paths (/snapshot,/branches,/commits,/read,/change,/export) with nographIdawareness. Every one of these routes is now served exclusively under/graphs/{id}/…in the 0.7.0 cluster-only server — only/healthzstays flat. Upgrading the server to 0.7.0 while the UI is still on flat paths will silently break all data-fetching (every call returns 404) while thehealthz()probe continues to returntrue, masking the failures from end-users.A companion PR to
omnigraph-uiis needed before this PR is safe to deploy: add aVITE_OMNIGRAPH_GRAPH_IDenv var and prefix all non-healthz calls with/graphs/${graphId}/….Reviews (3): Last reviewed commit: "fix(mcp)!: drop schema_apply tool — clus..." | Re-trigger Greptile