mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-06-24 02:38:06 +02:00
Add the `omnigraph-mcp` crate (stateless Streamable-HTTP transport, `McpBackend`
seam, fail-closed Host/Origin policy) and the server backend projecting built-in
operations and the per-graph stored-query registry as MCP tools + resources over
`POST /graphs/{id}/mcp`. Every tool delegates to the same engine/handler
functions the REST routes use and is gated by the same Cedar `authorize` path;
reads/writes carry structured output.
Includes three correctness fixes from review + live testing:
- tools/list is a faithful relaxation of the per-call gate: a built-in whose
authorization depends on a caller-chosen branch is shown iff the actor could
invoke it on some branch, via PolicyEngine::permits_on_any_branch (capability
probe through the same Cedar authorizer). A fabricated-`main` probe wrongly
hid graph_mutate under the canonical "protect main, write unprotected" policy.
- The stored-query surface honors mode + `expose` on call as well as on list:
resolve_stored_tool is the single membership test, so the meta pair
(stored_query_list/stored_query_run) is callable only in `meta` mode and
stored_query_run resolves exposed-only. An `expose:false` query is unreachable
by name on the agent surface (it stays HTTP/service-callable).
- The loopback Host allow-list is the full set [127.0.0.1, ::1, localhost]
(matches rmcp's default), so an IPv6 loopback `Host: [::1]` is accepted
regardless of which stack the server bound.
The protocol-version contract is documented (initialize negotiates the version
in its body, so the MCP-Protocol-Version header is validated on non-init
requests only) and pinned by a test.
Tests: omnigraph-mcp/tests/standalone.rs, omnigraph-server/tests/mcp.rs,
omnigraph-policy permits_on_any_branch unit test, omnigraph-api-types schema
projection. Full workspace gate green.
28 lines
1.3 KiB
TOML
28 lines
1.3 KiB
TOML
[package]
|
|
name = "omnigraph-mcp"
|
|
version = "0.7.0"
|
|
edition = "2024"
|
|
description = "MCP (Model Context Protocol) Streamable-HTTP transport and backend seam for Omnigraph. Contains the rmcp dependency and defines the McpBackend trait the server implements; names no omnigraph engine/server type, so the dependency edge is server → mcp."
|
|
license = "MIT"
|
|
repository = "https://github.com/ModernRelay/omnigraph"
|
|
homepage = "https://github.com/ModernRelay/omnigraph"
|
|
documentation = "https://docs.rs/omnigraph-mcp"
|
|
|
|
[dependencies]
|
|
# rmcp is contained to this crate. `server` + `transport-streamable-http-server`
|
|
# give the StreamableHttpService tower wiring. Do NOT enable rmcp's `local`
|
|
# feature — it cfg's the tower wiring out (transport mod is gated on
|
|
# `not(feature = "local")`).
|
|
rmcp = { version = "1.7", default-features = false, features = ["server", "transport-streamable-http-server"] }
|
|
axum = { workspace = true }
|
|
http = "1"
|
|
# `limit` adds RequestBodyLimitLayer; features are additive with the workspace's
|
|
# `trace`. rmcp reads the body directly (no axum extractor), so axum's
|
|
# DefaultBodyLimit does not bound /mcp — this layer is the real bound.
|
|
tower-http = { workspace = true, features = ["limit"] }
|
|
tokio = { workspace = true }
|
|
async-trait = { workspace = true }
|
|
serde_json = { workspace = true }
|
|
|
|
[dev-dependencies]
|
|
tower = { workspace = true }
|