Skip to main content
Glama

Clear Semantic Index

semantic_clear
DestructiveIdempotent

Delete all indexed data from the local vector store and remove corresponding embeddings, resetting semantic memory for fresh indexing.

Instructions

Delete all indexed data from the local vector store AND remove corresponding ...

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The handler function for the 'semantic_clear' tool. It calls service.status() to get the count before clearing, then service.clear() to delete the vector store, and also attempts to clear Spotlight entries via Swift bridge (best-effort). Returns cleared count and whether Spotlight was cleared.
    // -- Clear: delete all vector store data + Spotlight entries --
    server.registerTool(
      "semantic_clear",
      {
        title: "Clear Semantic Index",
        description:
          "Delete all indexed data from the local vector store AND remove corresponding entries from macOS Spotlight. " +
          "Use for privacy or to force a fresh re-index. Requires Swift bridge for Spotlight cleanup.",
        inputSchema: {},
        annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
      },
      async () => {
        try {
          const before = await service.status();
          await service.clear();
          // Also clear Spotlight entries if Swift bridge is available
          const swiftErr = await checkSwiftBridge();
          if (!swiftErr) {
            try {
              await runSwift("spotlight-clear", "{}");
            } catch {
              // Spotlight clear is best-effort
            }
          }
          return ok({
            cleared: before.total,
            spotlightCleared: !swiftErr,
            message: "Vector store and Spotlight index cleared.",
          });
        } catch (e) {
          return toolError("clear index", e);
        }
      },
    );
  • Input schema for semantic_clear — empty object (no inputs required). Annotations mark it as destructive (non-readOnly) and idempotent.
    title: "Clear Semantic Index",
    description:
      "Delete all indexed data from the local vector store AND remove corresponding entries from macOS Spotlight. " +
      "Use for privacy or to force a fresh re-index. Requires Swift bridge for Spotlight cleanup.",
    inputSchema: {},
  • The function registerSemanticTools that registers the 'semantic_clear' tool (line 161) along with other semantic tools on the MCP server. The overall registration function is exported and called from src/server/mcp-setup.ts line 134.
    export function registerSemanticTools(server: McpServer, config: AirMcpConfig): void {
      const service = new SemanticSearchService(config);
    
      // -- Index: build/rebuild the vector store from Apple app data --
      server.registerTool(
        "semantic_index",
        {
          title: "Build Semantic Index",
          description:
            "Index data from enabled Apple apps (Notes, Calendar, Reminders, Mail, Photos, Finder) into the local " +
            "vector store for semantic search. Run this once, then use semantic_search. Replaces any existing " +
            "index. Requires Swift bridge (npm run swift-build).",
          inputSchema: {
            sources: z
              .array(z.enum(["notes", "calendar", "reminders", "mail", "photos", "finder"]))
              .optional()
              .describe("Which sources to index. Defaults to all enabled modules."),
          },
          annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
        },
        async ({ sources }, extra) => {
          try {
            const progressToken = extra._meta?.progressToken;
            const onProgress =
              progressToken !== undefined
                ? async (progress: number, total: number, message: string) => {
                    await extra.sendNotification({
                      method: "notifications/progress",
                      params: { progressToken, progress, total, message },
                    });
                  }
                : undefined;
    
            const { indexed, errors, store } = await service.index(sources, onProgress);
            if (indexed === 0) {
              return errUpstream(`No items to index.${errors.length > 0 ? " Errors: " + errors.join("; ") : ""}`);
            }
            return ok({
              indexed,
              store,
              ...(errors.length > 0 ? { warnings: errors } : {}),
            });
          } catch (e) {
            return toolError("index", e);
          }
        },
      );
    
      // -- Search: semantic search across indexed data --
      server.registerTool(
        "semantic_search",
        {
          title: "Semantic Search",
          description:
            "Search across Apple app data by meaning, not just keywords. " +
            "Finds related notes, events, reminders, and emails even if they use different words. " +
            "Auto-indexes on first use and refreshes every 30 minutes.",
          inputSchema: {
            query: z.string().max(500).describe("Natural language search query"),
            sources: z
              .array(z.enum(["notes", "calendar", "reminders", "mail"]))
              .optional()
              .describe("Filter by source type"),
            limit: z.number().int().min(1).max(50).optional().describe("Max results (default 10)"),
            threshold: z.number().min(0).max(1).optional().describe("Minimum similarity (default 0.5)"),
          },
          annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
        },
        async ({ query, sources, limit, threshold }) => {
          try {
            const result = await service.search(query, { sources, limit, threshold });
            return okUntrusted(result);
          } catch (e) {
            return toolError("semantic search", e);
          }
        },
      );
    
      // -- Find Related: given an item, find semantically related items --
      server.registerTool(
        "find_related",
        {
          title: "Find Related Items",
          description:
            "Given a note, event, reminder, or email ID, find semantically related items across all indexed Apple apps. " +
            "Discovers cross-app connections (e.g., a calendar event related to notes and reminders about the same topic).",
          inputSchema: {
            id: z.string().max(500).describe("Item ID (as stored in the vector index)"),
            limit: z.number().int().min(1).max(50).optional().describe("Max results (default 10)"),
            threshold: z.number().min(0).max(1).optional().describe("Minimum similarity (default 0.6)"),
          },
          annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
        },
        async ({ id, limit, threshold }) => {
          try {
            const result = await service.findRelated(id, { limit, threshold });
            return ok(result);
          } catch (e) {
            return toolError("semantic search", e);
          }
        },
      );
    
      // -- Spotlight: push indexed data to macOS Spotlight for Siri discovery --
      server.registerTool(
        "spotlight_sync",
        {
          title: "Sync to Spotlight",
          description:
            "Push semantically indexed data to macOS Core Spotlight, making it discoverable via Spotlight search and Siri. " +
            "Run after semantic_index to expose your notes, events, reminders, and emails to system-wide search. " +
            "Requires Swift bridge (npm run swift-build).",
          inputSchema: {},
          annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
        },
        async () => {
          try {
            const swiftErr = await checkSwiftBridge();
            if (swiftErr) return errSwift(swiftErr);
    
            const stats = await service.status();
            if (stats.total === 0) {
              return errNotFound("No indexed data. Run semantic_index first.");
            }
    
            // Get all entries from the store and push to Spotlight
            const store = await service.getStoreData();
            const items = Object.values(store).map((entry) => ({
              id: entry.id,
              title: entry.title,
              content: entry.text,
              source: entry.source,
            }));
    
            const result = await runSwift<{ indexed: number; success: boolean }>(
              "spotlight-index",
              JSON.stringify({ items }),
            );
            return ok(result);
          } catch (e) {
            return toolError("spotlight sync", e);
          }
        },
      );
    
      // -- Clear: delete all vector store data + Spotlight entries --
      server.registerTool(
        "semantic_clear",
        {
          title: "Clear Semantic Index",
          description:
            "Delete all indexed data from the local vector store AND remove corresponding entries from macOS Spotlight. " +
            "Use for privacy or to force a fresh re-index. Requires Swift bridge for Spotlight cleanup.",
          inputSchema: {},
          annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
        },
        async () => {
          try {
            const before = await service.status();
            await service.clear();
            // Also clear Spotlight entries if Swift bridge is available
            const swiftErr = await checkSwiftBridge();
            if (!swiftErr) {
              try {
                await runSwift("spotlight-clear", "{}");
              } catch {
                // Spotlight clear is best-effort
              }
            }
            return ok({
              cleared: before.total,
              spotlightCleared: !swiftErr,
              message: "Vector store and Spotlight index cleared.",
            });
          } catch (e) {
            return toolError("clear index", e);
          }
        },
      );
    
      // -- Spotlight Clear: remove only Spotlight entries (keep vector store) --
      server.registerTool(
        "spotlight_clear",
        {
          title: "Clear Spotlight Index",
          description:
            "Remove all AirMCP entries from macOS Spotlight without clearing the local vector store. Requires Swift bridge.",
          inputSchema: {},
          annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
        },
        async () => {
          try {
            const swiftErr = await checkSwiftBridge();
            if (swiftErr) return errSwift(swiftErr);
            const result = await runSwift<{ cleared: boolean }>("spotlight-clear", "{}");
            return ok(result);
          } catch (e) {
            return toolError("spotlight clear", e);
          }
        },
      );
    
      // -- Stats: vector store status --
      server.registerTool(
        "semantic_status",
        {
          title: "Semantic Index Status",
          description: "Show the current state of the semantic vector index -- total entries, breakdown by source.",
          inputSchema: {},
          annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
        },
        async () => {
          try {
            const status = await service.status();
            return ok(status);
          } catch (e) {
            return toolError("check semantic status", e);
          }
        },
      );
    }
  • SemanticSearchService.clear() — delegates to this.store.clear() to delete all vector store data.
    async clear(): Promise<void> {
      await this.store.clear();
    }
  • VectorStore.clear() — resets the in-memory cache and persists an empty store to disk, effectively deleting all indexed data.
    /** Clear entire store (for privacy / fresh re-index). */
    async clear(): Promise<void> {
      this.loadPromise = null; // Cancel any in-flight load before overwriting cache
      this.cache = { version: 1, entries: {} };
      await this.save(this.cache);
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already convey destructiveHint=true and idempotentHint=true, indicating deletion and safe re-execution. The description adds minimal context (removing 'corresponding ...') but is incomplete. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single incomplete sentence, which is concise but poorly structured. It fails to complete the thought, indicating rushed or truncated content. Front-loading is not effective due to the break.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero parameters and no output schema, the tool is simple, but the description is incomplete and lacks details about what exactly gets deleted (e.g., embeddings, metadata). For a destructive action, more completeness is expected, such as noting irreversibility or backup needs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters exist, so schema coverage is 100%. Baseline of 4 applies; description does not need to add param details. The incomplete description does not detract from parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Title 'Clear Semantic Index' and description 'Delete all indexed data from the local vector store' specify the action and resource. It distinguishes from sibling tools like semantic_index (create) and semantic_search (query). However, the description is incomplete (trailing '...'), slightly reducing clarity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives like semantic_delete or spotlights. The description implies clearing all indexed data, but fails to mention prerequisites or consequences (e.g., irreversible data loss). No when-not information is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/heznpc/AirMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server