Files
Kigi-CLI/crates/codegen/kigi-shell/src/session/mcp_descriptors.rs
T
ZacharyZhang-NY 5e4e24db99 M2 audit: excise managed connectors and xAI media-gen tools
Managed connectors (grok.com MCP admin) removed root-and-branch:
- The managed-MCP fetch/injection pipeline is gone, including the whole
  kigi-shell-session-support crate (managed-config fetch client, gateway
  tool catalog + dispatch, header injection, refresh task), reactive
  managed re-auth, mcp_doctor's grok.com-source discovery, and the
  [managed_mcps] config surface.
- TUI: the 'Managed by grok.com' section, connectors URL/deep-link,
  Action::OpenManagedConnectors, and session_team_id are gone. Local MCP
  management (list/toggle/add/remove/auth/tools) is fully intact.
- Kept as LOCAL policy: managed-settings.json MCP allow/deny enforcement,
  the multi-source local MCP merge, folder-trust gating. PluginOrigin
  Project/User labels kept (they tag locally discovered plugin dirs).

imagine/media-gen tools (xAI image/video generation) removed:
- image_gen, image_edit, video_gen, image_to_video, reference_to_video
  implementations, registrations, ToolKind/ToolInput/Output variants
  (serde-safe), config plumbing end to end, ZDR video machinery,
  /imagine + /imagine-video commands and guidance text, the bundled
  imagine skill (added to legacy cleanup so user installs delete it),
  and the media-gen render path.
- Kept: image INPUT (paste/attach, [Image #N] meta, pdf/image fetch,
  clipboard wrap), generic media-ref rendering, and the generic tool
  401-retry machinery (tests renamed, assertions unweakened).
- deploy_app stays: it is a permanently-disabled local stub deploying
  nowhere.

121 files changed, 8 deleted. Gates: workspace check/clippy 0/0, fmt,
deny ok; suites green (tools 2554, shell 4862, tui 6608, workspace
1042). Remaining grok.com strings live only in the auth-method ids and
changelog archives (§9/M3 sweep).
2026-07-17 23:45:05 -04:00

64 lines
2.4 KiB
Rust

//! MCP descriptor mirror.
//!
//! Some templates read MCP metadata from an on-disk descriptor tree. Keep that
//! tree current as servers connect by (re)writing descriptors for connected
//! servers on every MCP tool-set change, not just at the first turn.
//!
//! Local MCP writes are upsert-only — folders for servers removed mid-session are
//! not pruned (cleaned on the next session's first-turn build); pruning against
//! an async-changing client set risks deleting a just-connected server's folder.
//!
//! Owning the descriptor I/O here keeps `acp_session.rs` thin.
use std::path::{Path, PathBuf};
use std::sync::Arc;
use crate::session::mcp_servers::{McpClient, sanitize_descriptor_segment};
/// Per-server descriptor folder: `<mcps_root>/<sanitized server name>`. Uses the
/// sanitizer shared with `kigi-mcp` so the advertised folder matches disk.
pub(crate) fn server_descriptor_dir(mcps_root: &Path, server_name: &str) -> PathBuf {
mcps_root.join(sanitize_descriptor_segment(server_name))
}
/// Upsert the on-disk tool descriptors for the given connected clients.
///
/// Safe to run concurrently (the first-turn build and the background handshake
/// task can both call it): `materialize_descriptors` writes each file
/// atomically, so overlapping writers converge without a lock. Errors are
/// logged, not propagated.
pub(crate) async fn materialize_descriptors_for_clients(
mcps_root: &Path,
clients: Vec<(String, Arc<McpClient>)>,
) {
for (name, client) in clients {
let server_dir = server_descriptor_dir(mcps_root, &name);
if let Err(e) = client.materialize_descriptors(&server_dir).await {
tracing::warn!(
server = %name,
path = %server_dir.display(),
error = %e,
"failed to materialize MCP descriptors",
);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sanitize_replaces_unsafe_chars_and_never_empty() {
assert_eq!(sanitize_descriptor_segment("a/b:c d"), "a_b_c_d");
assert_eq!(sanitize_descriptor_segment(""), "_");
assert_eq!(sanitize_descriptor_segment("keep-1.2_x"), "keep-1.2_x");
}
#[test]
fn server_dir_is_joined_under_root() {
let root = Path::new("/home/u/.kigi/projects/enc/mcps");
assert_eq!(server_descriptor_dir(root, "vercel"), root.join("vercel"));
}
}