mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-06-21 02:28:07 +02:00
docs(mcp): document the MCP surface, authoring controls, and skill (v0.8.0)
Document the per-graph MCP surface (POST /graphs/{id}/mcp, shipped in the
preceding commits and landing under v0.8.0) and the `.gq` authoring controls
that shape stored-query tools.
- New docs/user/operations/mcp.md: the client-facing guide — transport, tool
catalog (built-ins + stored queries), projection modes, structured output,
authorization (call-authoritative + list-relaxation), Host/Origin policy, the
protocol-version contract.
- docs/user/operations/server.md: the /mcp endpoint + an "MCP surface" section;
docs/user/index.md: a "Connect an MCP agent" pointer.
- docs/user/queries/index.md: an Annotations section — query @description /
@instruction / @mcp(expose, tool_name) and per-parameter @description.
- AGENTS.md: topic-table row + MCP note on the HTTP-server capability row.
- docs/dev/testing.md: the omnigraph-mcp crate + server tests/mcp.rs.
- docs/dev/rfc-005 §D5: retire the "cluster = everything exposed" bridge —
cluster mode honors source `@mcp(expose: …)`; presentation vs authorization
split made explicit.
- skills/omnigraph: server-policy.md MCP section; stored-queries.md corrected
(per-query controls now ship via @mcp, not "planned"); SKILL.md MCP triggers,
Deep Dives row, version → 0.8.0.
- docs/releases/v0.8.0.md: the MCP surface + authoring-controls release notes.
Crate version manifests are deliberately NOT bumped — that is the v0.8.0
release-cut step; this lands on the feature branch.
This commit is contained in:
parent
c8e91c11f0
commit
c06343362a
11 changed files with 349 additions and 13 deletions
89
docs/releases/v0.8.0.md
Normal file
89
docs/releases/v0.8.0.md
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
# Omnigraph v0.8.0
|
||||
|
||||
v0.8.0 makes every served graph an **MCP (Model Context Protocol) server**. An
|
||||
MCP-capable agent — Claude Code/Desktop, Cursor, the OpenAI Responses `mcp` tool,
|
||||
and others — can connect to a graph and operate it directly: run reads and
|
||||
mutations, load data, manage branches, browse commits, read the schema, and
|
||||
invoke the graph's curated stored queries. The surface adds no new capability and
|
||||
no new business logic; every tool delegates to the same engine/handler path the
|
||||
REST routes use and is gated by the same Cedar policy.
|
||||
|
||||
## Highlights
|
||||
|
||||
### MCP surface (`POST /graphs/{id}/mcp`)
|
||||
|
||||
- **One MCP endpoint per served graph**, mounted automatically by the cluster
|
||||
server — no separate flag. It is a stateless Streamable-HTTP transport: a
|
||||
single `application/json` JSON-RPC response per call, no SSE, no session id.
|
||||
- **Built-in tools** cover the operational surface: `graph_query`,
|
||||
`graph_mutate`, `graph_load`, `graph_snapshot`, `schema_get`, `branch_list`,
|
||||
`branch_create` / `branch_delete` / `branch_merge`, `commit_list` /
|
||||
`commit_get`, `schema_apply` (disabled with a `409` under cluster-backed
|
||||
serving — evolve via `cluster apply` and restart), and a `graph_health`
|
||||
liveness probe.
|
||||
- **Stored queries as tools.** A graph's stored-query registry is projected as
|
||||
tools, in one of two modes chosen automatically from the exposed-query count:
|
||||
`per_query` (each exposed query is its own typed tool) below a threshold, or a
|
||||
`stored_query_list` + `stored_query_run` discovery/execute pair at or above it,
|
||||
so a client's tool count stays bounded.
|
||||
- **Resources.** The graph schema (`omnigraph://schema`) and branch list
|
||||
(`omnigraph://branches`) are exposed as MCP resources.
|
||||
- **Structured output.** Tool results carry `structuredContent` (the same typed
|
||||
result envelopes as the REST routes) plus a text mirror.
|
||||
|
||||
### Authorization parity with REST
|
||||
|
||||
- Every tool and resource resolves the actor from the bearer token and passes the
|
||||
same Cedar gate as the equivalent REST route; the call-time gate is
|
||||
authoritative.
|
||||
- **`tools/list` is a relaxation of the per-call gate**: a tool the actor could
|
||||
invoke on *some* branch is listed, so listing never hides a tool you can call,
|
||||
while an actor with no grant for an action still does not see its tools. Under
|
||||
the common "protect `main`, write feature branches" policy, `graph_mutate` is
|
||||
listed for an actor who can write unprotected branches.
|
||||
- Stored queries sit behind the coarse `invoke_query` gate (a stored mutation is
|
||||
additionally `change`-gated); for a caller without `invoke_query`, a stored
|
||||
tool masks as an unknown tool so the catalog can't be probed. An
|
||||
`expose: false` query is unreachable on the MCP surface entirely (not listed,
|
||||
not runnable by name) while remaining HTTP/service callable.
|
||||
|
||||
### Authoring stored queries as MCP tools
|
||||
|
||||
`.gq` gains the controls to shape how a stored query appears as an MCP tool, all
|
||||
carried in the query source:
|
||||
|
||||
- **`@instruction("…")` reaches agents.** The query's `@instruction` annotation
|
||||
is folded into the MCP tool description (after `@description`), so the
|
||||
how/when-to-use guidance shows up in `tools/list` — previously it surfaced only
|
||||
in the REST catalog.
|
||||
- **Per-parameter docs.** A leading `@description("…")` on a parameter
|
||||
(`@description("the user's slug") $slug: String`) is surfaced into the
|
||||
parameter's JSON-Schema `description` in both the MCP tool input schema and the
|
||||
`GET /queries` catalog.
|
||||
- **`@mcp(tool_name: "…", expose: <bool>)`.** A dedicated MCP-presentation
|
||||
annotation: `tool_name` overrides the tool id (unique-checked at boot, can't
|
||||
shadow a built-in); `expose: false` hides the query from the agent tool surface
|
||||
(`tools/list` / `stored_query_list` / `stored_query_run`) while keeping it
|
||||
HTTP/service-callable by name. `expose` is presentation only — Cedar
|
||||
`invoke_query` remains the authority for who may call a query.
|
||||
|
||||
### Transport hardening
|
||||
|
||||
- **Fail-closed Host / Origin posture**, derived from the bind address at
|
||||
startup. A loopback bind accepts the full loopback `Host` set
|
||||
(`127.0.0.1`, `::1`, `localhost`) regardless of which IP stack it bound; a
|
||||
non-loopback bind rejects an unexpected browser `Origin` and restricts `Host`
|
||||
to the configured public hosts.
|
||||
- The `MCP-Protocol-Version` header is validated on follow-up requests (an
|
||||
unsupported version is a `400`); `initialize` negotiates the version in its
|
||||
body and is exempt by design.
|
||||
|
||||
## Upgrade notes
|
||||
|
||||
- **No breaking changes.** The REST surface, CLI, cluster config, and on-disk
|
||||
format are unchanged. The MCP endpoint is additive.
|
||||
- **Pointing an agent at a graph:** configure your MCP client with the URL
|
||||
`https://<host>/graphs/<id>/mcp` and the same bearer token you use for REST.
|
||||
See [docs/user/operations/mcp.md](../user/operations/mcp.md) for the connect
|
||||
recipe, the tool catalog, projection modes, and the Host/Origin and
|
||||
protocol-version contracts. Design and rationale: RFC-003.
|
||||
Loading…
Add table
Add a link
Reference in a new issue