agent-discover 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,66 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.2.3] - 2026-04-09
9
+
10
+ ### Documentation
11
+
12
+ - **README.md**: bumped test count to 179, added the new badge for 11 registry actions, rewrote the "MCP Tools" section to document `find_tool` / `find_tools` / `get_schema` / `proxy_call` with the auto_activate guidance, expanded the Features list to lead with single-call discovery + pluggable embeddings + indirect invocation, added the embeddings env-var section, linked the bench README headline result.
13
+ - **CHANGELOG.md**: backfilled v1.1.3 / v1.1.4 / v1.2.0 / v1.2.1 / v1.2.2 entries.
14
+ - **docs/API.md**: documented all 4 new registry actions with parameters and example payloads + responses, added the no-match threshold semantics for `find_tool`.
15
+ - **docs/ARCHITECTURE.md**: added the embeddings provider layer to the layered diagram, documented the `src/embeddings/` subsystem (none/local/openai), the hybrid retrieval pipeline, the `0.25` no-match threshold, the migration to schema V5, and the new `embedding` / `embedding_model` columns on `server_tools`.
16
+ - **docs/USER-MANUAL.md**: new sections for `registry_find_tool` / `registry_find_tools` / `registry_get_schema` / `registry_proxy_call` with usage examples, added the embeddings env-var table to the configuration section.
17
+ - **docs/SETUP.md**: added the embeddings env-var table with full enable/disable walkthrough for both local and openai providers.
18
+
19
+ ## [1.2.2] - 2026-04-09
20
+
21
+ ### Fixed
22
+
23
+ - **`find_tool` / `find_tools` no-match detection.** Hybrid retrieval (introduced in 1.2.0) returned at least one match for every query because cosine similarity is non-zero for every embedded tool, so the existing `matches.length === 0` guard never fired and a query like `"totally nonexistent xyzzy"` would surface a low-confidence garbage tool. Both actions now apply a `MIN_SCORE_THRESHOLD = 0.25` to the top result and return `{ found: false, top_score, hint }` when nothing crosses it. Real queries (typical scores > 0.4) are unaffected; garbage matches (~0.1) are now correctly rejected. Caught by the v1.2.x E2E test pass.
24
+
25
+ ## [1.2.1] - 2026-04-09
26
+
27
+ ### Added
28
+
29
+ - **Pluggable embedding providers (`src/embeddings/`).** Multi-provider subsystem mirroring agent-knowledge's pattern, with semantic search opt-in via `AGENT_DISCOVER_EMBEDDING_PROVIDER` (default `none` so existing installs without an embedding key keep working with BM25-only ranking). Providers shipped:
30
+ - `none` — `NoopEmbeddingProvider`, returned by default. Reports unavailable so callers transparently fall back to BM25.
31
+ - `openai` — `OpenAIEmbeddingProvider`, `text-embedding-3-small` (1536 dims), native `fetch`, batched 256 inputs per request.
32
+ - `local` — `LocalEmbeddingProvider`, `Xenova/all-MiniLM-L6-v2` (384 dims) via `@huggingface/transformers` (optional peer dep, dynamically imported via indirect string so the package isn't required at compile time). q8 quantized, configurable `AGENT_DISCOVER_EMBEDDING_THREADS` and `AGENT_DISCOVER_EMBEDDING_IDLE_TIMEOUT`.
33
+ - **Provider factory** (`src/embeddings/factory.ts`) caches the resolved provider, falls back to `NoopEmbeddingProvider` on any unavailable / API-key-missing / model-load-failure case so the registry never crashes on a misconfiguration.
34
+ - **Shared math + encoding helpers** (`cosineSimilarity`, `encodeEmbedding` / `decodeEmbedding`) exported from `src/embeddings/index.ts`.
35
+
36
+ ### Changed
37
+
38
+ - `RegistryService` constructor no longer eagerly creates the embedding provider — it's lazily resolved via `getEmbeddings()` so the factory's dynamic imports only run when somebody actually saves or searches tools.
39
+ - `saveToolsWithEmbeddings()` returns `{ embedded, skipped, provider }` and tolerates per-tool null embeddings cleanly.
40
+ - `searchToolsHybrid()` awaits the provider, falls back to plain `searchTools()` when `provider.name === 'none'` or the query embedding fails.
41
+
42
+ ## [1.2.0] - 2026-04-09
43
+
44
+ ### Added
45
+
46
+ - **`find_tool` registry action — single-call tool discovery.** Hybrid BM25 + semantic ranking returns the top match with a confidence label (`high` / `medium` / `low` derived from the score gap to the runner-up), compact `required_args`, and 4 ranked alternatives in `other_matches`. Auto-activates the owning child server so the agent can call the proxied tool immediately on the next turn. Replaces the old multi-call `search → list → activate` flow that took ~16 round-trips per task in the bench baseline.
47
+ - **`find_tools` registry action — batch variant.** Pass `intents: ["intent1", "intent2", …]` to discover N tools in one round-trip for multi-step tasks.
48
+ - **`get_schema` registry action.** Returns the full `input_schema` for a tool already discovered via `find_tool`. Use only when the compact `required_args` summary isn't enough (conditional / polymorphic args). Compact-first delivery cuts `find_tool` result tokens 5–10× on heavy registries.
49
+ - **`proxy_call` registry action.** Invokes a discovered tool **through** agent-discover without exposing it to the host catalog. Combined with `find_tool({auto_activate: false})`, this keeps the host MCP catalog at exactly 5 agent-discover actions regardless of how many tools the registered child servers actually expose — critical at large catalog sizes where firing `notifications/tools/list_changed` would flood the host with thousands of schemas.
50
+ - **`did_you_mean` recovery on tool errors.** When a proxied tool call fails (validation error, missing args, runtime error), the proxy intercepts the response, runs a BM25 search by the failed tool name, and attaches a `did_you_mean` array of similarly-named alternatives. Lets the agent recover from a wrong-tool selection in one extra turn instead of giving up or re-running discovery.
51
+ - **FTS5 + BM25 ranking on `server_tools`** (migration v4). Adds a `server_tools_fts` virtual table with name × 4 / description × 1 column weighting, plus a query preprocessor that expands verb synonyms (`fetch → get`, `cancel → delete`, etc.) and singularizes plurals (`subscriptions → subscription`).
52
+ - **Embedding columns on `server_tools`** (migration v5). `embedding` (TEXT, base64-encoded float32) and `embedding_model` columns for semantic search. Embeddings are optional; tools without one fall back to BM25 ranking only.
53
+ - **Hybrid retrieval (`searchToolsHybrid`).** Brute-force cosine similarity over the entire embedded catalog + BM25 candidate union, scored 70% semantic / 30% lexical. Closes the natural-language gap that pure BM25 misses (e.g. "billing arrangement" → "subscription").
54
+ - **Bench harness** under `bench/` comparing eager tool loading vs deferred discovery. Real Claude Code (`bench/drivers/cli.ts`) and OpenCode (`bench/drivers/opencode.ts`) drivers, isolated bench DB, scoring with `success` / `choice_accuracy` / `distractor_call_rate` / `refusal_rate` metrics, and a standalone `bench/rescore.ts` that re-applies the current scoring logic to captured event streams without spending fresh API tokens. Headline result at N=1000 on OpenCode + gpt-5-mini against an adversarial natural-language verb pack: discover 100% / 100% / 0% vs eager 80% / 80% / 20%, with ~27% lower per-turn token cost. Full results in `bench/README.md`.
55
+
56
+ ## [1.1.4] - 2026-04-09
57
+
58
+ ### Added
59
+
60
+ - Bench iteration adding `find_tools` (plural) and `did_you_mean` recovery — both later carried forward into v1.2.0. See `bench/README.md` for the historical context.
61
+
62
+ ## [1.1.3] - 2026-04-09
63
+
64
+ ### Added
65
+
66
+ - Bench iteration adding BM25 + confidence labels + compact-first schema delivery — later carried forward into v1.2.0.
67
+
8
68
  ## [1.1.2] - 2026-04-08
9
69
 
10
70
  ### Fixed
package/README.md CHANGED
@@ -2,8 +2,9 @@
2
2
 
3
3
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
4
4
  [![Node.js](https://img.shields.io/badge/node-%3E%3D20.11-brightgreen)](https://nodejs.org/)
5
- [![Tests](https://img.shields.io/badge/tests-151%20passing-brightgreen)]()
5
+ [![Tests](https://img.shields.io/badge/tests-179%20passing-brightgreen)]()
6
6
  [![MCP Tools](https://img.shields.io/badge/MCP%20tools-1-purple)]()
7
+ [![Registry Actions](https://img.shields.io/badge/registry%20actions-11-blueviolet)]()
7
8
  [![REST Endpoints](https://img.shields.io/badge/REST-19%20endpoints-orange)]()
8
9
 
9
10
  **MCP server registry and marketplace.** Discover, install, activate, and manage MCP tools on demand. Acts as a dynamic proxy -- activated servers have their tools merged into the registry's own tool list, so agents can use them without restarting.
@@ -37,6 +38,11 @@ Static MCP configs mean every server is always running, even when unused. Adding
37
38
 
38
39
  ## Features
39
40
 
41
+ - **Single-call tool discovery (`find_tool`)** — hybrid BM25 + semantic ranking returns the top match with a confidence label, compact `required_args`, and 4 ranked alternatives. Auto-activates the owning child server so the agent can call the proxied tool immediately on the next turn. Replaces the multi-step `search → list → activate` dance with one round-trip.
42
+ - **Batch discovery (`find_tools`)** — pass an array of intents to discover N tools in a single round-trip for multi-step tasks.
43
+ - **Indirect invocation (`proxy_call`)** — call a discovered tool **through** agent-discover without exposing it to the host catalog. Keeps the host MCP surface at exactly 5 actions regardless of how many tools the registered child servers expose — critical for very large catalogs where flooding the host with thousands of schemas would blow the model's context budget.
44
+ - **Pluggable embeddings (`AGENT_DISCOVER_EMBEDDING_PROVIDER`)** — semantic search is opt-in via `none` (default, BM25 only) / `local` (Xenova/all-MiniLM-L6-v2 via `@huggingface/transformers`) / `openai` (`text-embedding-3-small`). Provider failures fall back to BM25 cleanly. Mirrors agent-knowledge's pattern so the same model can be reused.
45
+ - **`did_you_mean` recovery** — when a proxied tool call fails, the proxy attaches BM25-ranked similar-tool suggestions to the error response so the agent can correct in one extra turn instead of giving up.
40
46
  - **Local registry** -- register MCP servers in a SQLite database with name, command, args, env, tags
41
47
  - **Federated marketplace search** -- a single query hits the official MCP registry, npm, and PyPI in parallel, dedupes by `<source>:<name>`, and collapses version duplicates
42
48
  - **PyPI integration** -- curated list of well-known Python MCP servers (`mcp-server-fetch`, `mcp-server-git`, `mcp-server-time`, `mcp-server-postgres`, `mcp-server-sqlite`, `mcp-proxy`, …) plus live metadata via the PyPI JSON API; Python entries install via `uvx`
@@ -49,10 +55,11 @@ Static MCP configs mean every server is always running, even when unused. Adding
49
55
  - **Secret management** -- store API keys and tokens per server, automatically injected as env vars (stdio) or HTTP headers (SSE/streamable-http) on activation; CRLF-validated to prevent header injection
50
56
  - **Health checks** -- connect/disconnect probes for inactive servers, tool-list checks for active ones, with error count tracking
51
57
  - **Per-tool metrics** -- call counts, error counts, and average latency recorded automatically on every proxied tool call
52
- - **Full-text search** -- FTS5 search across server names, descriptions, and tags
58
+ - **Full-text search** -- FTS5 search across server names, descriptions, and tags + cross-server tool index for `find_tool`
53
59
  - **Pre-download** -- fire-and-forget `npm cache add` (npx servers) or `uv tool install` (uvx servers) on registration, plus a dedicated `/preinstall` endpoint
54
60
  - **Real-time dashboard** -- web UI at http://localhost:3424 with Servers and Browse tabs, dark/light theme, WebSocket updates
55
61
  - **3 transport layers** -- MCP (stdio), REST API (HTTP), WebSocket (real-time events)
62
+ - **Bench harness** -- under `bench/`, comparing eager tool loading vs deferred discovery against real Claude Code and OpenCode hosts. Headline result at N=1000 against an adversarial natural-language verb pack: discover 100% accuracy + 27% lower per-turn token cost vs eager 80% accuracy. See [`bench/README.md`](bench/README.md).
56
63
 
57
64
  ---
58
65
 
@@ -106,14 +113,26 @@ node dist/server.js --port 3424
106
113
 
107
114
  ## MCP Tools (1)
108
115
 
109
- A single action-based tool handles every operation via the `action` parameter — this keeps the prompt-overhead cost minimal.
110
-
111
- | Tool | Actions | Description |
112
- | ---------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
113
- | `registry` | `list`, `install`, `uninstall`, `activate`, `deactivate`, `browse`, `status` | Registry + server lifecycle search local servers, install from marketplace or manual config, activate/deactivate, browse, show status |
116
+ A single action-based tool handles every operation via the `action` parameter — this keeps the prompt-overhead cost minimal regardless of how many child servers are registered.
117
+
118
+ | Action | Purpose |
119
+ | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
120
+ | `find_tool` | **Single-call discovery.** Hybrid BM25 + semantic search top match + confidence label + compact `required_args` + 4 alternatives. Auto-activates the owning server. |
121
+ | `find_tools` | **Batch discovery.** Pass `intents: [...]` to discover N tools in one round-trip. Use for multi-step tasks. |
122
+ | `get_schema` | Full `input_schema` for a discovered tool. Only needed when the compact `required_args` summary isn't enough (conditional / polymorphic args). |
123
+ | `proxy_call` | Invoke a discovered tool **through** agent-discover without exposing it to the host catalog. Pair with `find_tool({auto_activate: false})` for huge catalogs. |
124
+ | `list` | Search the local registry by server (FTS5). |
125
+ | `install` | Add a server from the marketplace or via manual config (command + args + env). |
126
+ | `uninstall` | Remove a server. |
127
+ | `activate` | Start a server, discover its tools, expose them to the host as `serverName__toolName`. |
128
+ | `deactivate` | Stop a server, hide its tools. |
129
+ | `browse` | Federated search across the official MCP registry, npm, and PyPI. |
130
+ | `status` | Active servers summary (names, tool counts, tool lists). |
114
131
 
115
132
  Activated servers expose their tools through agent-discover, namespaced as `serverName__toolName`. For example, activating a server named `filesystem` that exposes `read_file` makes it available as `filesystem__read_file`.
116
133
 
134
+ When `find_tool` is called with `auto_activate: false` (recommended for catalogs above ~1k tools), the proxy connection is opened silently and tools must be invoked via `proxy_call` instead of being added to the host's catalog. This keeps the host MCP surface area constant regardless of how many tools the registered child servers expose.
135
+
117
136
  ---
118
137
 
119
138
  ## REST API (19 endpoints)
@@ -170,11 +189,29 @@ npm run test:e2e:ui # Playwright dashboard smoke tests
170
189
 
171
190
  ## Environment Variables
172
191
 
192
+ ### Core
193
+
173
194
  | Variable | Default | Description |
174
195
  | --------------------- | ----------------------------- | -------------------- |
175
196
  | `AGENT_DISCOVER_PORT` | `3424` | Dashboard HTTP port |
176
197
  | `AGENT_DISCOVER_DB` | `~/.claude/agent-discover.db` | SQLite database path |
177
198
 
199
+ ### Embeddings (semantic search for `find_tool`)
200
+
201
+ Embeddings are **opt-in**. The default is `none`, which means `find_tool` ranks by BM25 + verb synonyms only. Setting a provider enables hybrid BM25 + cosine retrieval, which closes the natural-language gap (e.g. "billing arrangement" → "subscription") that BM25 alone misses.
202
+
203
+ | Variable | Default | Description |
204
+ | --------------------------------------- | ------- | ----------------------------------------------------------------------- |
205
+ | `AGENT_DISCOVER_EMBEDDING_PROVIDER` | `none` | `none` \| `local` \| `openai` |
206
+ | `AGENT_DISCOVER_EMBEDDING_MODEL` | — | Override the default model id for the chosen provider |
207
+ | `AGENT_DISCOVER_EMBEDDING_THREADS` | `1` | Local provider only — onnx runtime thread count |
208
+ | `AGENT_DISCOVER_EMBEDDING_IDLE_TIMEOUT` | `60` | Local provider only — seconds before unloading the model from RAM |
209
+ | `AGENT_DISCOVER_OPENAI_API_KEY` | — | OpenAI API key for embeddings (falls back to `OPENAI_API_KEY` if unset) |
210
+
211
+ **Local provider** uses `Xenova/all-MiniLM-L6-v2` (384 dims) via `@huggingface/transformers`. Install the optional peer dependency with `npm install @huggingface/transformers` if you want to use it. No network calls, no API key.
212
+
213
+ **OpenAI provider** uses `text-embedding-3-small` (1536 dims). Same model as agent-knowledge so the two servers can share an embedding key.
214
+
178
215
  ### Host package manager prerequisites
179
216
 
180
217
  agent-discover spawns child MCP servers via the host's installed package managers. Install whatever you intend to use; missing tools are reported by `GET /api/prereqs` and surfaced as a banner in the Browse tab.
@@ -2,7 +2,7 @@
2
2
  "id": "agent-discover",
3
3
  "name": "Discover",
4
4
  "icon": "explore",
5
- "version": "1.2.2",
5
+ "version": "1.2.3",
6
6
  "description": "MCP server registry — browse, install, configure, monitor",
7
7
  "ui": "./dist/ui/app.js",
8
8
  "css": "./dist/ui/styles.css",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-discover",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "mcpName": "io.github.keshrath/agent-discover",
5
5
  "description": "MCP server registry and marketplace — discover, install, activate, and manage MCP tools on demand",
6
6
  "type": "module",