mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-06-09 01:35:18 +02:00
Default mcp.expose to true (the manifest entry is the opt-in)
expose controls MCP-catalog membership only — it is not an authorization gate (invocation is gated by invoke_query regardless). So requiring a per-query mcp.expose: true was friction with no safety benefit: a non-exposed query is still HTTP-invocable by name. Flip the default so declaring a query in the manifest exposes it to the agent tool catalog by default; expose: false is the escape hatch for service-only queries. Both the absent-mcp path (Default impl) and the present-but-no-expose path (serde default fn) now yield true. Doc comments + cli-reference updated; the config round-trip test asserts the new default.
This commit is contained in:
parent
f4c38bb75a
commit
6cad21cb6a
3 changed files with 30 additions and 13 deletions
|
|
@ -115,17 +115,33 @@ pub struct QueryEntry {
|
|||
|
||||
/// MCP exposure for a stored query. A *deployment* concern (the same
|
||||
/// `.gq` may be exposed in one graph and hidden in another), so it lives
|
||||
/// in YAML rather than in the `.gq` source. Default `expose: false` —
|
||||
/// a query is HTTP-callable but absent from the MCP tool catalog unless
|
||||
/// the operator opts in. The catalog projection lands in a later slice;
|
||||
/// v1 round-trips these fields.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
/// in YAML rather than in the `.gq` source. **Default `expose: true`** —
|
||||
/// declaring a query in the manifest *is* the opt-in, so it appears in the
|
||||
/// MCP tool catalog (`GET /queries`) by default; set `expose: false` to
|
||||
/// keep a query HTTP/service-callable but hidden from the agent tool list.
|
||||
/// `expose` governs catalog membership only — it is **not** an
|
||||
/// authorization gate (invocation is gated by `invoke_query`), so a hidden
|
||||
/// query is still invocable by name with the right permission.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct McpSettings {
|
||||
#[serde(default)]
|
||||
#[serde(default = "mcp_expose_default")]
|
||||
pub expose: bool,
|
||||
pub tool_name: Option<String>,
|
||||
}
|
||||
|
||||
fn mcp_expose_default() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
impl Default for McpSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
expose: mcp_expose_default(),
|
||||
tool_name: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum AliasCommand {
|
||||
|
|
@ -601,9 +617,9 @@ queries:
|
|||
assert_eq!(find_user.file, "./queries/find_user.gq");
|
||||
assert!(find_user.mcp.expose);
|
||||
assert_eq!(find_user.mcp.tool_name.as_deref(), Some("lookup_user"));
|
||||
// Default exposure is false (safe by default) and tool_name absent.
|
||||
// Default exposure is true (the manifest entry is the opt-in); tool_name absent.
|
||||
let audit = &prod["internal_audit"];
|
||||
assert!(!audit.mcp.expose);
|
||||
assert!(audit.mcp.expose);
|
||||
assert!(audit.mcp.tool_name.is_none());
|
||||
|
||||
// Top-level registry (single-graph mode).
|
||||
|
|
|
|||
|
|
@ -36,9 +36,10 @@ pub struct StoredQuery {
|
|||
pub source: Arc<str>,
|
||||
/// Parsed declaration (params, mutations, description, …).
|
||||
pub decl: QueryDecl,
|
||||
/// Whether this query is listed in the MCP tool catalog. Default
|
||||
/// `false`: HTTP-callable but not MCP-enumerated until the operator
|
||||
/// opts in. Consulted by the catalog projection (a later slice).
|
||||
/// Whether this query is listed in the MCP tool catalog (`GET /queries`).
|
||||
/// Default `true` (the manifest entry is the opt-in); `expose: false`
|
||||
/// keeps it HTTP/service-callable but hidden from the agent tool list.
|
||||
/// Catalog membership only — not an authorization gate.
|
||||
pub expose: bool,
|
||||
/// Optional MCP tool-name override; defaults to `name`.
|
||||
pub tool_name: Option<String>,
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ graphs:
|
|||
<query-name>: # key MUST equal the `query <name>` symbol inside the .gq
|
||||
file: <path-to-.gq> # relative to this config's directory
|
||||
mcp:
|
||||
expose: false # default false: HTTP-callable but not listed as an MCP tool
|
||||
expose: true # default true: listed in the MCP catalog (GET /queries); set false to hide (still HTTP-callable)
|
||||
tool_name: <name> # optional MCP tool-name override (defaults to <query-name>;
|
||||
# must be unique across exposed queries)
|
||||
server:
|
||||
|
|
@ -68,7 +68,7 @@ aliases:
|
|||
branch: <name>
|
||||
format: <output-format>
|
||||
queries: # top-level stored-query registry (single-graph mode); mirrors top-level `policy`
|
||||
<query-name>: { file: <path-to-.gq>, mcp: { expose: false } }
|
||||
<query-name>: { file: <path-to-.gq> } # mcp.expose defaults to true
|
||||
policy:
|
||||
file: ./policy.yaml
|
||||
```
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue