Skip to content

feat!: migrate SDK + MCP to omnigraph-server v0.7.0 (cluster-only)#12

Merged
ragnorc merged 3 commits into
mainfrom
ragnorc/sdk-upstream-update-plan
Jun 16, 2026
Merged

feat!: migrate SDK + MCP to omnigraph-server v0.7.0 (cluster-only)#12
ragnorc merged 3 commits into
mainfrom
ragnorc/sdk-upstream-update-plan

Conversation

@ragnorc

@ragnorc ragnorc commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

What

Syncs @modernrelay/omnigraph and @modernrelay/omnigraph-mcp from 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 actual openapi.json). v0.6.2 was a pure no-op (byte-identical spec apart from info.version), so this goes straight to 0.7.0.

upstream contract effect
#250 cluster-only: every op re-rooted /x/graphs/{graph_id}/x; only /healthz + /graphs stay flat
#184 /ingest no longer implicitly forks (missing branch w/o from → 404); IngestOutput.base_branch nullable
#222 canonical POST /load; /ingest deprecated (kept as a shim, emits Deprecation/Link)
#247 optional expect_mutation on POST /queries/{name} (mismatch → 400)
#258 POST /…/schema/apply can return 409 on a cluster-managed graph

Net schema-component delta is exactly two edits: base_branch nullable/optional and the new optional expect_mutation. Codegen is types-only, so the upstream operationId → cluster_* rename is a non-event here.

Breaking change — graphId is now required (hard cutover)

The server is cluster-only, so graph-scoped calls require a graphId. The transport throws the new typed ConfigurationError (status 0, client-side, before any network call) when a graph-scoped method runs without one. health() and graphs.list() remain graph-independent. Per the repo's major.minor = server policy, SDK 0.7.x targets a 0.7.x server only; stay on @modernrelay/omnigraph@0.6.x for a 0.6.x server.

Changes

SDK

  • og.load() (canonical) added; og.ingest() marked @deprecated
  • ConfigurationError exported; transport guard for missing graphId
  • expectMutation passthrough on queries.invoke()
  • regenerated types from the v0.7.0 spec

MCP

  • load tool added; ingest becomes the deprecated alias
  • OMNIGRAPH_GRAPH_ID now required at the bin entrypoint
  • sync-cookbook repointed to the relocated skill references in ModernRelay/omnigraph (skills/omnigraph/references); 3 new refs (cluster/migrations/stored-queries) marked skipped

Tooling / CI

  • check-coverage made graphId-prefix-aware (mirrors the transport rewrite)
  • e2e rewritten to boot a local-filesystem cluster (no object storage): cluster importcluster applyload --mode overwriteomnigraph-server --cluster, with Cedar policy bundles granting graph_list (cluster-scoped) + the per-graph data actions. The two e2e jobs collapse into one (alpha + beta).
  • versions bumped to 0.7.0 across root/sdk/mcp; SDK + MCP READMEs updated for the cluster model

Verification

Run against the real v0.7.0 server binary (macos-arm64), not just mocks:

  • full gate green: check-versions, check-drift, check-coverage (20/20), build, typecheck
  • 90 unit tests + 21 live e2e tests pass against a booted cluster server (alpha + beta, authenticated with policy bundles)
  • confirmed GET /graphs is closed-by-default and opens with a cluster-scoped graph_list grant; data plane works; bad token → 401

Consumer migration

  • pass a graphId (discover via og.graphs.list()og.graph(id)); graph-scoped calls without one throw ConfigurationError
  • og.ingest()og.load() (identical shapes; ingest stays as a shim)
  • loading into a missing branch now requires from (else 404)
  • schema.apply() on a cluster-managed graph returns 409

Note

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/omnigraph and @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 missing graphId throws ConfigurationError before the network (only health() and graphs.list() stay flat). Removed og.read, og.change, and og.ingest; callers use og.query, og.mutate, and og.load (POST /load). Bulk load no longer implicitly forks a branch without from. Stored-query invoke can pass expectMutation. schema.apply() remains but cluster graphs can answer 409.

MCP requires OMNIGRAPH_GRAPH_ID at startup; legacy read / change / ingest tools are gone in favor of query / mutate / load, and schema_apply is not exposed (schema via cluster apply). Cookbook sync pulls from ModernRelay/omnigraph skill references.

CI/docs: e2e collapses to one job that builds a local cluster.yaml cluster (alpha + beta, Cedar policies), seeds with omnigraph load, and runs tests with omnigraph-server --cluster. check-coverage strips the graph prefix when matching spec ops and allowlists deprecated /read, /change, /ingest shims 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/omnigraph and @modernrelay/omnigraph-mcp from server pin v0.6.1 → v0.7.0 (cluster-only). Graph-scoped HTTP calls are now routed under /graphs/{graphId}/…; a missing graphId throws ConfigurationError client-side before any network call. The deprecated og.read / og.change / og.ingest aliases are dropped in favour of og.query / og.mutate / og.load.

  • SDK: New ConfigurationError, og.load() canonical endpoint, expectMutation passthrough on stored-query invoke, regenerated types (base_branch nullable, optional expectMutation), and og.graph(id) for scoped fan-out.
  • MCP: load tool replaces ingest; schema_apply tool removed (cluster graphs reject HTTP schema apply with 409); OMNIGRAPH_GRAPH_ID required at bin startup; INSTRUCTIONS string and cookbook sync all updated.
  • CI e2e: Two separate jobs (single + multi-graph) collapsed into one cluster-based job; Cedar policy bundles, cluster import/apply, and omnigraph load seed 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-ui will 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.ts still 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.ts in the related UI repo needs a companion PR before the 0.7.0 server is deployed.

Important Files Changed

Filename Overview
packages/sdk/src/transport.ts Core routing rewrite: adds graphId prefixing under /graphs/{id}/…, FLAT_PATHS exempts /healthz and /graphs, and throws ConfigurationError (status 0) before any network call when a graph-scoped op is issued without a graphId. Logic is clean and well-tested.
packages/sdk/src/errors.ts Adds ConfigurationError (client-side, status 0) to the typed error hierarchy and exports it. No issues.
packages/sdk/src/client.ts Drops deprecated og.read, og.change, og.ingest; adds canonical og.load() (POST /load), og.graph(id) for scoped clones; all graph-scoped methods delegate through Transport which handles the /graphs/{id}/ prefix.
packages/mcp/src/server.ts Removes read, change, ingest, schema_apply tools; adds load tool; INSTRUCTIONS string fully updated to canonical load/mutate/query language. Minor: graphId?: string in CreateServerOptions is typed as optional but required at runtime for all graph-scoped tool calls.
packages/mcp/src/bin.ts Correctly adds a startup guard that exits with a clear error if OMNIGRAPH_GRAPH_ID is missing. No issues.
scripts/check-coverage.ts Made graphId-prefix-aware: strips /graphs/{id}/ from spec paths before matching, allowlists deprecated /read, /change, /ingest shims, and has a stale-allowlist check that fails CI if the server drops a shim from the spec. Logic is sound.
.github/workflows/e2e.yml Collapses two e2e jobs into one cluster-based flow; boots a local-filesystem cluster with Cedar policy bundles for both cluster-scoped (graph_list) and per-graph data actions. Clean consolidation with good coverage of auth (UnauthorizedError) and cluster routing.
packages/sdk/src/resources/queries.ts Adds expectMutation passthrough on invoke(); camelCase input is correctly converted to snake_case expect_mutation by the transport's camelToSnake serializer. No issues.

Comments Outside Diff (3)

  1. packages/mcp/src/server.ts, line 40-48 (link)

    P2 Stale ingest references in system INSTRUCTIONS

    The INSTRUCTIONS string — which is injected as the LLM system prompt — still references ingest in four places after this PR promotes load as the canonical tool:

    Agents reading these instructions will preferentially call the deprecated ingest shim instead of the canonical load tool, which is the opposite of the migration intent. Since ingest is 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!

    Fix in Claude Code

  2. packages/sdk/README.md, line 8-11 (link)

    P1 omnigraph-ui raw HTTP calls are broken against the 0.7.0 server

    omnigraph-ui/src/lib/omnigraph.ts makes direct fetch calls to flat paths (/snapshot, /branches, /commits, /read, /change, /export) with no graphId awareness. Every one of these routes is now served exclusively under /graphs/{id}/… in the 0.7.0 cluster-only server — only /healthz stays 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's healthz() probe returning true will mask the failures from end-users.

    A companion PR to omnigraph-ui is needed: at minimum add a VITE_OMNIGRAPH_GRAPH_ID env var and prefix all non-healthz paths with /graphs/${graphId}/, and migrate the GET /export call to POST /graphs/${graphId}/export with a body (the HTTP method changed too).

    Fix in Claude Code

  3. packages/sdk/README.md, line 1 (link)

    P1 omnigraph-ui raw HTTP calls are broken against the 0.7.0 server

    omnigraph-ui/src/lib/omnigraph.ts makes direct fetch calls to flat paths (/snapshot, /branches, /commits, /read, /change, /export) with no graphId awareness. Every one of these routes is now served exclusively under /graphs/{id}/… in the 0.7.0 cluster-only server — only /healthz stays 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 the healthz() probe continues to return true, masking the failures from end-users.

    A companion PR to omnigraph-ui is needed before this PR is safe to deploy: add a VITE_OMNIGRAPH_GRAPH_ID env var and prefix all non-healthz calls with /graphs/${graphId}/….

    Fix in Claude Code

Fix All in Claude Code

Reviews (3): Last reviewed commit: "fix(mcp)!: drop schema_apply tool — clus..." | Re-trigger Greptile

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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread .github/workflows/e2e.yml

- name: Start omnigraph-server in multi-graph mode
omnigraph cluster import --config "$dir"
omnigraph cluster apply --config "$dir"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread packages/mcp/src/server.ts
… 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.
@ragnorc ragnorc merged commit aea2e0e into main Jun 16, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant