@aiwayds/dsh-mcp-adapter 0.5.0 → 0.6.0
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/README.md +50 -4
- package/README.zh.md +51 -5
- package/lib/index.d.ts +340 -23
- package/lib/index.js +829 -74
- package/lib/index.js.map +1 -1
- package/lib/jev/backends.d.ts +35 -0
- package/lib/jev/backends.js +48 -0
- package/lib/jev/backends.js.map +1 -0
- package/lib/jev/client.d.ts +133 -0
- package/lib/jev/client.js +288 -0
- package/lib/jev/client.js.map +1 -0
- package/lib/jev/config.d.ts +82 -0
- package/lib/jev/config.js +55 -0
- package/lib/jev/config.js.map +1 -0
- package/lib/jev/dual.d.ts +42 -0
- package/lib/jev/dual.js +42 -0
- package/lib/jev/dual.js.map +1 -0
- package/lib/jev/gate.d.ts +51 -0
- package/lib/jev/gate.js +141 -0
- package/lib/jev/gate.js.map +1 -0
- package/lib/jev/log.d.ts +93 -0
- package/lib/jev/log.js +138 -0
- package/lib/jev/log.js.map +1 -0
- package/lib/jev/seams.d.ts +118 -0
- package/lib/jev/seams.js +364 -0
- package/lib/jev/seams.js.map +1 -0
- package/lib/jev/thresholds.d.ts +37 -0
- package/lib/jev/thresholds.js +44 -0
- package/lib/jev/thresholds.js.map +1 -0
- package/lib/rank.d.ts +157 -0
- package/lib/rank.js +327 -0
- package/lib/rank.js.map +1 -0
- package/lib/usage.d.ts +232 -0
- package/lib/usage.js +362 -0
- package/lib/usage.js.map +1 -0
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -57,6 +57,9 @@ import type { Context } from '@deepseek-ai/cordis';
|
|
|
57
57
|
import z from '@deepseek-ai/schemastery';
|
|
58
58
|
import type { ContentBlock, ToolSchema } from '@deepseek-ai/dsh-llm';
|
|
59
59
|
import type { ToolDefinition, ToolExecution, ToolExecutionResult } from '@deepseek-ai/dsh-tools';
|
|
60
|
+
import type { JevConfigValue } from './jev/config.ts';
|
|
61
|
+
import type { RankCandidate } from './rank.ts';
|
|
62
|
+
import type { SuggestionRecord } from './usage.ts';
|
|
60
63
|
import type { ScopeKey } from '@deepseek-ai/dsh-scope';
|
|
61
64
|
/** Cordis plugin name used by loader diagnostics. */
|
|
62
65
|
export declare const name = "mcp-adapter";
|
|
@@ -195,8 +198,72 @@ export declare function resolveGateDir(configured: string): string;
|
|
|
195
198
|
* synchronous (boot-time, once); writes land atomically (tmp file + rename)
|
|
196
199
|
* so a crash mid-write can never leave a torn document, and the in-memory
|
|
197
200
|
* mirror only advances after the file is durably renamed into place.
|
|
201
|
+
*
|
|
202
|
+
* Legacy absorption (one-time, 0.1.5 → 0.1.7): on a FRESH gate — no
|
|
203
|
+
* gate.json yet — the machine state from the removed settings registry is
|
|
204
|
+
* absorbed once from the host's legacy settings documents (see
|
|
205
|
+
* {@link absorbLegacyGate}). Opt-in through `options.home`: the legacy
|
|
206
|
+
* documents are a HOME-level concern (not this store's `dir`), and stores
|
|
207
|
+
* built without a home (bare test harnesses) stay exactly as isolated as
|
|
208
|
+
* before.
|
|
209
|
+
*/
|
|
210
|
+
export declare function createFileGateStore(dir: string, warn: GateWarn, options?: GateStoreOptions): GateStore;
|
|
211
|
+
/**
|
|
212
|
+
* dsh 0.1.7 renamed the old `<home>/settings.yaml` to
|
|
213
|
+
* `settings.yaml.imported` after a one-shot import keyed by "section name =
|
|
214
|
+
* entry id". This plugin's old `mcp-adapter:` section (the machine-maintained
|
|
215
|
+
* id registry / disabled set) does not match the entry id `dsh-mcp-adapter`
|
|
216
|
+
* and was silently dropped by the host — the state lives on only in the
|
|
217
|
+
* renamed document. {@link absorbLegacyGate} recovers it once into the
|
|
218
|
+
* plugin's own gate.json.
|
|
219
|
+
*/
|
|
220
|
+
/** Legacy host settings documents, in read priority order. */
|
|
221
|
+
export declare const LEGACY_SETTINGS_FILES: readonly ["settings.yaml.imported", "settings.yaml"];
|
|
222
|
+
/** Legacy top-level section name in the old settings document. */
|
|
223
|
+
export declare const LEGACY_GATE_SECTION = "mcp-adapter";
|
|
224
|
+
/** Audit marker file name: `<home>/storages/mcp-adapter/<name>`. */
|
|
225
|
+
export declare const LEGACY_IMPORT_MARKER = "legacy-import.json";
|
|
226
|
+
/** Marker outcomes written for every settled absorption pass. */
|
|
227
|
+
export type LegacyGateOutcome = 'imported' | 'no-op' | 'no-legacy' | 'no-section';
|
|
228
|
+
/**
|
|
229
|
+
* Extract the top-level `mcp-adapter:` section of the old settings document.
|
|
230
|
+
* Handles both shapes the 0.1.5 writer produced:
|
|
231
|
+
* - single-line values (`serverIds: '{"fs": 1}'`, `disabled: '[1]'`);
|
|
232
|
+
* - block collections (`serverIds:` followed by deeper-indented
|
|
233
|
+
* `name: <int>` lines; `disabled:` followed by `- <int>` lines).
|
|
234
|
+
* Everything else (comments, folded scalars, nested junk) is skipped.
|
|
235
|
+
* undefined = no section found. Pure function — tests run it against
|
|
236
|
+
* literal strings.
|
|
198
237
|
*/
|
|
199
|
-
export declare function
|
|
238
|
+
export declare function legacyGateSection(text: string): {
|
|
239
|
+
serverIds?: unknown;
|
|
240
|
+
disabled?: unknown;
|
|
241
|
+
} | undefined;
|
|
242
|
+
/**
|
|
243
|
+
* Turn one decoded section into the raw candidate {@link normalizeServerGate}
|
|
244
|
+
* sanitizes: flow-JSON strings are JSON-parsed (malformed → undefined, the
|
|
245
|
+
* key degrades to "absent"), already-decoded block collections pass through.
|
|
246
|
+
*/
|
|
247
|
+
export declare function legacyGateCandidate(section: {
|
|
248
|
+
serverIds?: unknown;
|
|
249
|
+
disabled?: unknown;
|
|
250
|
+
}): {
|
|
251
|
+
serverIds?: unknown;
|
|
252
|
+
disabled?: unknown;
|
|
253
|
+
};
|
|
254
|
+
/** Construction options for {@link createFileGateStore} beyond the two
|
|
255
|
+
* historical arguments (all optional — bare harnesses change nothing). */
|
|
256
|
+
export interface GateStoreOptions {
|
|
257
|
+
/** Summary-line seam for the absorption (default: silent). */
|
|
258
|
+
info?: GateWarn;
|
|
259
|
+
/**
|
|
260
|
+
* The dsh home holding the legacy settings documents and the audit marker
|
|
261
|
+
* (production: `resolveDshHome()` at the call site). Absorption runs ONLY
|
|
262
|
+
* when a home is provided — a store built without one never reads outside
|
|
263
|
+
* its own directory.
|
|
264
|
+
*/
|
|
265
|
+
home?: string;
|
|
266
|
+
}
|
|
200
267
|
/**
|
|
201
268
|
* Live config reference. 0.1.7 settings contract: volatile `Config` fields
|
|
202
269
|
* reach `apply` as host-swapped references — `.get()` snapshots the current
|
|
@@ -210,8 +277,15 @@ export interface VolatileRef<T> {
|
|
|
210
277
|
* Resolved adapter configuration as `apply` receives it. Every knob is
|
|
211
278
|
* user-tunable from the settings page (entry `dsh-mcp-adapter`) and hot-reloads
|
|
212
279
|
* without a plugin restart.
|
|
280
|
+
*
|
|
281
|
+
* The seven `jev*` keys are the System One decision settings (see
|
|
282
|
+
* ./jev/config.ts): the master switch, the backend/model to ask, the request
|
|
283
|
+
* timeout, the outbound secret list, and the local laya pace-maker. They are
|
|
284
|
+
* spread into {@link Config} from `JEV_CONFIG_FIELDS` so the settings schema
|
|
285
|
+
* and this interface cannot drift, and they are read through their volatile
|
|
286
|
+
* refs per use like every other knob.
|
|
213
287
|
*/
|
|
214
|
-
export interface AdapterConfig {
|
|
288
|
+
export interface AdapterConfig extends JevConfigValue {
|
|
215
289
|
/** Tool-name prefix to fold out of assembled prompts. */
|
|
216
290
|
prefix: VolatileRef<string>;
|
|
217
291
|
/** Name patterns ("*" wildcard) kept native in the prompt. */
|
|
@@ -228,7 +302,7 @@ export interface AdapterConfig {
|
|
|
228
302
|
/**
|
|
229
303
|
* Gate storage directory override; empty (default) =
|
|
230
304
|
* `<dsh home>/storages/mcp-adapter`. Read once at apply time (the store is
|
|
231
|
-
* built there
|
|
305
|
+
* built there; changing it takes effect on the next plugin restart).
|
|
232
306
|
*/
|
|
233
307
|
storageDir: VolatileRef<string>;
|
|
234
308
|
}
|
|
@@ -322,6 +396,19 @@ export interface McpListOptions {
|
|
|
322
396
|
* once at apply time and must observe later /mcp disable/enable writes.
|
|
323
397
|
*/
|
|
324
398
|
getGate?: () => ServerGateState | undefined;
|
|
399
|
+
/**
|
|
400
|
+
* Optional async relevance reranker for `{ query }` calls ONLY (production:
|
|
401
|
+
* the System One seam). Called with the candidate pool — the lexical
|
|
402
|
+
* shortlist, or the whole visible catalog when the prefilter matched
|
|
403
|
+
* nothing — and resolves to the preferred order, or to `undefined` to keep
|
|
404
|
+
* the order it was given.
|
|
405
|
+
*
|
|
406
|
+
* Deliberately a promise-returning callback on a SYNCHRONOUS builder: the
|
|
407
|
+
* remote call happens in the async execute layer, and this builder stays a
|
|
408
|
+
* pure function of (args, schemas, options, ranking). Disabled, failed, or
|
|
409
|
+
* absent rerank ⇒ `undefined` ⇒ the given order, i.e. pre-seam behavior.
|
|
410
|
+
*/
|
|
411
|
+
rankQuery?: (query: string, candidates: readonly RankCandidate[]) => Promise<readonly string[] | undefined>;
|
|
325
412
|
}
|
|
326
413
|
/** Normalized `mcp_list` arguments. */
|
|
327
414
|
export interface McpListArgs {
|
|
@@ -331,6 +418,13 @@ export interface McpListArgs {
|
|
|
331
418
|
server?: string;
|
|
332
419
|
/** Inline every tool's schema in the catalog. */
|
|
333
420
|
verbose?: boolean;
|
|
421
|
+
/**
|
|
422
|
+
* Free-text relevance query. Absent (or blank) = the unfiltered catalog,
|
|
423
|
+
* byte-identical to the pre-query behavior; present = a ranked SHORTLIST
|
|
424
|
+
* plus the total match count, never a silent narrowing of the only
|
|
425
|
+
* discovery path the model has.
|
|
426
|
+
*/
|
|
427
|
+
query?: string;
|
|
334
428
|
}
|
|
335
429
|
/** One catalog entry; `parameters` is present only when expanded. */
|
|
336
430
|
export interface CatalogToolEntry {
|
|
@@ -343,9 +437,24 @@ export interface CatalogServerEntry {
|
|
|
343
437
|
server: string;
|
|
344
438
|
tools: CatalogToolEntry[];
|
|
345
439
|
}
|
|
346
|
-
/**
|
|
440
|
+
/**
|
|
441
|
+
* `mcp_list`'s canonical result: catalog, single expansion, or error.
|
|
442
|
+
*
|
|
443
|
+
* The `{ servers }` variant carries four OPTIONAL keys that are present only
|
|
444
|
+
* on a query answer: `query`, `ranked`, `total` and `note`. They are what
|
|
445
|
+
* makes the subset self-describing — the model can see that this is a ranked
|
|
446
|
+
* shortlist of N of M matches and that the full catalog is one no-argument
|
|
447
|
+
* call away, and `ranked: false` says the prefilter matched nothing at all
|
|
448
|
+
* and this is the semantic fallback rather than a ranking. An unqueried
|
|
449
|
+
* catalog omits them entirely, so the wire value stays byte-identical to the
|
|
450
|
+
* pre-seam shape.
|
|
451
|
+
*/
|
|
347
452
|
export type McpListResult = {
|
|
348
453
|
servers: CatalogServerEntry[];
|
|
454
|
+
query?: string;
|
|
455
|
+
ranked?: boolean;
|
|
456
|
+
total?: number;
|
|
457
|
+
note?: string;
|
|
349
458
|
} | {
|
|
350
459
|
tool: {
|
|
351
460
|
name: string;
|
|
@@ -355,9 +464,43 @@ export type McpListResult = {
|
|
|
355
464
|
} | {
|
|
356
465
|
error: string;
|
|
357
466
|
};
|
|
467
|
+
/**
|
|
468
|
+
* A precomputed ranking for one `{ query }` catalog call — the seam between
|
|
469
|
+
* the async jev layer and the pure builder. `pool`/`total` are the LEXICAL
|
|
470
|
+
* result (so the builder does not have to redo the work and cannot disagree
|
|
471
|
+
* with the shortlist jev was asked about); `order` is jev's permutation of
|
|
472
|
+
* that pool, absent when there is no opinion (fail-open ⇒ `pool` order).
|
|
473
|
+
*/
|
|
474
|
+
export interface ListRanking {
|
|
475
|
+
/** The query this ranking was computed for. */
|
|
476
|
+
query: string;
|
|
477
|
+
/**
|
|
478
|
+
* The candidate set, at most {@link RANK_CANDIDATE_LIMIT} names: the lexical
|
|
479
|
+
* shortlist, best first — or, under {@link ListRanking.semantic}, the whole
|
|
480
|
+
* visible catalog in registry order.
|
|
481
|
+
*/
|
|
482
|
+
pool: readonly string[];
|
|
483
|
+
/** Every lexical match, uncapped — the denominator of the `total` field. */
|
|
484
|
+
total: number;
|
|
485
|
+
/** Reranked names, best first (production: the jev answer). */
|
|
486
|
+
order?: readonly string[];
|
|
487
|
+
/**
|
|
488
|
+
* True when the lexical prefilter matched NOTHING and `pool` is instead the
|
|
489
|
+
* SEMANTIC-FALLBACK set: the whole visible catalog, capped, handed to a
|
|
490
|
+
* reranker that can still tell a Chinese query from an English description
|
|
491
|
+
* and an ASCII one cannot. Absent (the ordinary case) = a lexical ranking,
|
|
492
|
+
* and the answer says `ranked: true` with no mention of a fallback.
|
|
493
|
+
*/
|
|
494
|
+
semantic?: boolean;
|
|
495
|
+
}
|
|
358
496
|
/**
|
|
359
497
|
* Narrow arbitrary model arguments to the `mcp_list` shape, dropping
|
|
360
498
|
* unknown or mistyped keys instead of throwing (the model misbehaves).
|
|
499
|
+
*
|
|
500
|
+
* A blank `query` is dropped rather than kept: an empty search is not a
|
|
501
|
+
* search, and honoring it would put the catalog on a different code path (the
|
|
502
|
+
* ranked one) for a request that means "show me everything".
|
|
503
|
+
*
|
|
361
504
|
* @param args - raw model arguments.
|
|
362
505
|
* @returns the normalized catalog query.
|
|
363
506
|
*/
|
|
@@ -385,21 +528,55 @@ export declare function serverOfToolName(name: string, prefix: string): string;
|
|
|
385
528
|
* @returns the single-line truncated description.
|
|
386
529
|
*/
|
|
387
530
|
export declare function truncateDescription(text: string, limit: number): string;
|
|
531
|
+
/**
|
|
532
|
+
* The lexical relevance shortlist for one `query` catalog call — the pure,
|
|
533
|
+
* synchronous half of seam B. This is both what the jev reranker is asked
|
|
534
|
+
* about and the order that stands when jev is disabled or fails.
|
|
535
|
+
*
|
|
536
|
+
* @param args - the normalized catalog query (must carry a `query`).
|
|
537
|
+
* @param schemas - schemas visible to the calling agent.
|
|
538
|
+
* @param options - catalog knobs.
|
|
539
|
+
* @param gate - live disabled-server snapshot (default: none disabled).
|
|
540
|
+
* @returns the shortlist (name + full description per entry, so a reranker
|
|
541
|
+
* can ask about them without re-reading the schemas) plus the uncapped
|
|
542
|
+
* match count. A query the prefilter cannot lexically match comes back
|
|
543
|
+
* `semantic` with the whole visible catalog as its pool. A structured error
|
|
544
|
+
* means the catalog itself is empty or fully gated.
|
|
545
|
+
*/
|
|
546
|
+
export declare function listQueryRanking(args: McpListArgs, schemas: readonly ToolSchema[], options: McpListOptions, gate?: ServerGateState): {
|
|
547
|
+
pool: readonly RankCandidate[];
|
|
548
|
+
total: number;
|
|
549
|
+
semantic?: boolean;
|
|
550
|
+
error?: string;
|
|
551
|
+
};
|
|
388
552
|
/**
|
|
389
553
|
* Build the `mcp_list` result over the currently visible schemas.
|
|
390
554
|
*
|
|
391
555
|
* Priority: `tool` (full single-tool expansion) > catalog (optionally
|
|
392
|
-
* filtered by `server`, optionally `verbose
|
|
393
|
-
* and any query that selects nothing
|
|
394
|
-
*
|
|
556
|
+
* filtered by `server`, optionally `verbose`, optionally ranked by `query`).
|
|
557
|
+
* Unknown or non-MCP `tool`, and any query that selects nothing out of an
|
|
558
|
+
* empty or fully gated catalog, return a structured error — never a throw —
|
|
559
|
+
* so the model can correct itself.
|
|
560
|
+
*
|
|
561
|
+
* A `query` that the LEXICAL prefilter cannot match is NOT an error: it
|
|
562
|
+
* degrades to the semantic fallback (the whole visible catalog, capped, and
|
|
563
|
+
* `ranked: false`), because "no word of the query appeared anywhere" is not
|
|
564
|
+
* "no tool matches" — see {@link semanticFallbackPool}.
|
|
565
|
+
*
|
|
566
|
+
* `query` is a MODEL-EXPLICIT narrowing: it is the only catalog path that
|
|
567
|
+
* consults `ranking` (production: the System One seam), and a missing/failed
|
|
568
|
+
* rerank degrades to the lexical order. With no `query`, this function is the
|
|
569
|
+
* pre-seim builder unchanged.
|
|
395
570
|
*
|
|
396
571
|
* @param args - the normalized catalog query.
|
|
397
572
|
* @param schemas - schemas visible to the calling agent.
|
|
398
573
|
* @param options - catalog knobs.
|
|
399
574
|
* @param gate - live disabled-server snapshot (default: none disabled).
|
|
575
|
+
* @param ranking - precomputed relevance ranking for `args.query`
|
|
576
|
+
* (production: the async layer's jev answer).
|
|
400
577
|
* @returns the canonical result value.
|
|
401
578
|
*/
|
|
402
|
-
export declare function buildMcpListResult(args: McpListArgs, schemas: readonly ToolSchema[], options: McpListOptions, gate?: ServerGateState): McpListResult;
|
|
579
|
+
export declare function buildMcpListResult(args: McpListArgs, schemas: readonly ToolSchema[], options: McpListOptions, gate?: ServerGateState, ranking?: ListRanking): McpListResult;
|
|
403
580
|
/** Structural slice of a resolvable tool: what dispatch actually consumes. */
|
|
404
581
|
export interface DispatchableTool<E> {
|
|
405
582
|
/** Cooperative timeout budget declared by the tool, if any. */
|
|
@@ -407,6 +584,36 @@ export interface DispatchableTool<E> {
|
|
|
407
584
|
/** The tool body dispatch invokes. */
|
|
408
585
|
execute(args: unknown, exec: E): Promise<unknown>;
|
|
409
586
|
}
|
|
587
|
+
/**
|
|
588
|
+
* The near-miss seam of the unknown-tool branch (seam C).
|
|
589
|
+
*
|
|
590
|
+
* `candidates` is deliberately cheap and SYNCHRONOUS — it is called on a path
|
|
591
|
+
* the model is already reading an error on, and it must answer even when jev
|
|
592
|
+
* is off, timing out, or broken. `rerank` is the optional async refinement
|
|
593
|
+
* (production: the System One seam); `undefined`, a rejection, or an
|
|
594
|
+
* unusable answer all mean "keep the lexical order", which is the behavior
|
|
595
|
+
* the branch had before the seam existed.
|
|
596
|
+
*/
|
|
597
|
+
export interface DidYouMeanHook {
|
|
598
|
+
/** Visible tool names a near-miss may point at, in the calling scope. */
|
|
599
|
+
candidates(): readonly RankCandidate[];
|
|
600
|
+
/** Optional async reorder; absent/undefined/throw ⇒ lexical order stands. */
|
|
601
|
+
rerank?(tool: string, candidates: readonly RankCandidate[]): Promise<readonly string[] | undefined>;
|
|
602
|
+
}
|
|
603
|
+
/** The near-miss pool cap — the same batch ceiling the jev seams use. */
|
|
604
|
+
export declare const DID_YOU_MEAN_POOL_LIMIT = 40;
|
|
605
|
+
/**
|
|
606
|
+
* The visible tools a near-miss may point at: this scope's prefix-matching
|
|
607
|
+
* MCP tools under the servers whitelist, minus the meta-tools and minus
|
|
608
|
+
* disabled servers (dispatch would refuse those anyway, so naming one would
|
|
609
|
+
* be advice the model cannot take).
|
|
610
|
+
*
|
|
611
|
+
* @param schemas - schemas visible to the calling agent.
|
|
612
|
+
* @param options - adapter knobs (prefix/servers).
|
|
613
|
+
* @param gate - live disabled-server snapshot (default: none disabled).
|
|
614
|
+
* @returns the pool, in registry order.
|
|
615
|
+
*/
|
|
616
|
+
export declare function didYouMeanPool(schemas: readonly ToolSchema[], options: Pick<McpCommandOptions, 'prefix' | 'servers'>, gate?: ServerGateState): RankCandidate[];
|
|
410
617
|
/**
|
|
411
618
|
* Dispatch one `mcp_call` to the resolved child tool.
|
|
412
619
|
*
|
|
@@ -433,6 +640,11 @@ export interface DispatchableTool<E> {
|
|
|
433
640
|
* Errors never throw out of dispatch: a child rejection (or raced timeout)
|
|
434
641
|
* is wrapped into a structured `{ error }` the model can correct and retry.
|
|
435
642
|
*
|
|
643
|
+
* The unknown-tool branch additionally offers near-misses (seam C): a lexical
|
|
644
|
+
* prefilter over the scope's visible tools always answers, and an optional
|
|
645
|
+
* async rerank (production: System One) can reorder it. The base error text
|
|
646
|
+
* is unchanged, so this stays a pure addition to the message.
|
|
647
|
+
*
|
|
436
648
|
* @param args - raw model arguments (`{ tool, arguments? }`, validated here).
|
|
437
649
|
* @param prefix - the configured MCP prefix.
|
|
438
650
|
* @param resolve - scope-aware tool resolver (production: `ctx.tools.get`).
|
|
@@ -442,9 +654,11 @@ export interface DispatchableTool<E> {
|
|
|
442
654
|
* disabled branch sits after the prefix/whitelist validation: a disabled
|
|
443
655
|
* server's tools are refused with an explicit `/mcp enable <id>` hint
|
|
444
656
|
* before the child is ever resolved.
|
|
657
|
+
* @param didYouMean - the near-miss seam for the unknown-tool branch
|
|
658
|
+
* (default: none — the pre-seam message, unchanged).
|
|
445
659
|
* @returns the child's resolved value verbatim, or a structured error.
|
|
446
660
|
*/
|
|
447
|
-
export declare function dispatchMcpCall<E>(args: unknown, prefix: string, resolve: (name: string) => DispatchableTool<E> | undefined, exec: E, servers?: readonly string[], gate?: ServerGateState): Promise<unknown>;
|
|
661
|
+
export declare function dispatchMcpCall<E>(args: unknown, prefix: string, resolve: (name: string) => DispatchableTool<E> | undefined, exec: E, servers?: readonly string[], gate?: ServerGateState, didYouMean?: DidYouMeanHook): Promise<unknown>;
|
|
448
662
|
/** Knobs shared by every /mcp renderer — plain data, no Cordis. */
|
|
449
663
|
export interface McpCommandOptions {
|
|
450
664
|
/** Tool-name prefix identifying MCP tools. */
|
|
@@ -470,6 +684,36 @@ export interface McpCommandOptions {
|
|
|
470
684
|
* one in the first place.
|
|
471
685
|
*/
|
|
472
686
|
unassignedServers?: readonly string[];
|
|
687
|
+
/**
|
|
688
|
+
* The seven System One settings as plain data (production: the live
|
|
689
|
+
* volatile config refs, resolved per invocation). Absent ⇒ the views stay
|
|
690
|
+
* byte-identical to the pre-jev plugin — a caller that does not wire the
|
|
691
|
+
* decision support never sees a jev line.
|
|
692
|
+
*/
|
|
693
|
+
jev?: McpJevOptions;
|
|
694
|
+
/**
|
|
695
|
+
* Recorded usage counters for the views that talk about the suggestion
|
|
696
|
+
* cadence (production: the usage mirror). Absent ⇒ those views report "no
|
|
697
|
+
* usage recorded yet" instead of a number.
|
|
698
|
+
*/
|
|
699
|
+
usage?: McpUsageOptions;
|
|
700
|
+
}
|
|
701
|
+
/** The seven jev settings, flattened for display. */
|
|
702
|
+
export interface McpJevOptions {
|
|
703
|
+
readonly jevEnabled: boolean;
|
|
704
|
+
readonly jevBackend: string;
|
|
705
|
+
readonly jevModel: string;
|
|
706
|
+
readonly jevTimeoutMs: number;
|
|
707
|
+
readonly jevSecretFile: string;
|
|
708
|
+
readonly jevLayaFallback: boolean;
|
|
709
|
+
readonly jevLayaUrl: string;
|
|
710
|
+
}
|
|
711
|
+
/** Recorded-usage counters, flattened for display. */
|
|
712
|
+
export interface McpUsageOptions {
|
|
713
|
+
/** Dispatches recorded across every tool. */
|
|
714
|
+
readonly totalCalls: number;
|
|
715
|
+
/** Tools carrying at least one recorded call. */
|
|
716
|
+
readonly toolCount: number;
|
|
473
717
|
}
|
|
474
718
|
/** Usage text returned for unparseable /mcp invocations. */
|
|
475
719
|
export declare const MCP_COMMAND_USAGE: string;
|
|
@@ -481,6 +725,8 @@ export type ParsedMcpCommandInput = {
|
|
|
481
725
|
name: string;
|
|
482
726
|
} | {
|
|
483
727
|
form: 'config';
|
|
728
|
+
} | {
|
|
729
|
+
form: 'suggest';
|
|
484
730
|
} | {
|
|
485
731
|
form: 'disable';
|
|
486
732
|
id: number;
|
|
@@ -493,9 +739,10 @@ export type ParsedMcpCommandInput = {
|
|
|
493
739
|
/**
|
|
494
740
|
* Parse one /mcp raw input into its form. `''` and `'list'` are the tree
|
|
495
741
|
* overview; `'list <name>'` is a server/tool detail; `'config'` shows the
|
|
496
|
-
* effective configuration; `'
|
|
497
|
-
*
|
|
498
|
-
*
|
|
742
|
+
* effective configuration; `'suggest'` shows the current keep suggestions;
|
|
743
|
+
* `'disable <n>'` / `'enable <n>'` are whole-server toggles (n is the stable id
|
|
744
|
+
* shown by `/mcp`, so a bare `0` or non-numeric token is already usage).
|
|
745
|
+
* Everything else parses to the usage error.
|
|
499
746
|
* @param rawInput - exact text following the command name.
|
|
500
747
|
* @returns the normalized command form.
|
|
501
748
|
*/
|
|
@@ -643,6 +890,24 @@ export interface McpDetailView {
|
|
|
643
890
|
* @returns the rendered view.
|
|
644
891
|
*/
|
|
645
892
|
export declare function renderMcpDetail(name: string, schemas: readonly ToolSchema[], options: McpCommandOptions): McpDetailView;
|
|
893
|
+
/**
|
|
894
|
+
* Render the keep-suggestion view (`/mcp suggest`): the current batch of
|
|
895
|
+
* System One verdicts about which FOLDED tools earned a permanent place in
|
|
896
|
+
* every prompt, each with its probability, the usage evidence behind it, and
|
|
897
|
+
* the exact `keep` pattern the operator would write.
|
|
898
|
+
*
|
|
899
|
+
* Strictly a DISPLAY (red line ③): nothing here writes keep, prefix or the
|
|
900
|
+
* gate — the operator decides, one settings-page edit, with the same manual
|
|
901
|
+
* authority they have over every other knob.
|
|
902
|
+
*
|
|
903
|
+
* Every state is explained rather than blank: jev off, jev on with no batch
|
|
904
|
+
* yet, and jev on with rows. Output is line-capped defensively.
|
|
905
|
+
*
|
|
906
|
+
* @param suggestions - the current batch (production: suggestions.json).
|
|
907
|
+
* @param options - adapter knobs; `jev.jevEnabled` and `usage` are read.
|
|
908
|
+
* @returns the rendered view.
|
|
909
|
+
*/
|
|
910
|
+
export declare function renderMcpSuggest(suggestions: readonly SuggestionRecord[], options: Pick<McpCommandOptions, 'jev' | 'usage'>): string;
|
|
646
911
|
/**
|
|
647
912
|
* Render the effective configuration with each knob's hitting tools:
|
|
648
913
|
* which names match the prefix, what each keep pattern holds back, and what
|
|
@@ -686,6 +951,13 @@ export interface McpCommandView {
|
|
|
686
951
|
* finishes in the background — same-process code cannot hard-kill it.
|
|
687
952
|
*/
|
|
688
953
|
signal?: AbortSignal;
|
|
954
|
+
/**
|
|
955
|
+
* The current keep-suggestion batch for `/mcp suggest` (production: read
|
|
956
|
+
* from `<gate dir>/suggestions.json` at invocation time). Absent ⇒ the view
|
|
957
|
+
* reports "no suggestions yet", which is also what a missing or unreadable
|
|
958
|
+
* document means.
|
|
959
|
+
*/
|
|
960
|
+
suggestions?: readonly SuggestionRecord[];
|
|
689
961
|
}
|
|
690
962
|
/** CommandResult-compatible outcome (platform shape: success may omit text). */
|
|
691
963
|
export interface McpCommandOutcome {
|
|
@@ -759,18 +1031,54 @@ export declare function renderDispatched(metaArgs: unknown, value: unknown, reso
|
|
|
759
1031
|
export declare function delegateFinalizeContent(metaArgs: unknown, result: Readonly<ToolExecutionResult>, exec: Readonly<ToolExecution>, resolveChild: (name: string) => ToolDefinition | undefined): ContentBlock[] | undefined;
|
|
760
1032
|
/**
|
|
761
1033
|
* Build the `mcp_list` meta-tool definition.
|
|
762
|
-
*
|
|
763
|
-
*
|
|
764
|
-
*
|
|
765
|
-
*
|
|
766
|
-
*
|
|
1034
|
+
*
|
|
1035
|
+
* The execute layer is where the async seam lives: a no-argument call is the
|
|
1036
|
+
* pre-seim builder verbatim (no promise, no remote), and only a `query` call
|
|
1037
|
+
* consults `options.rankQuery` — and even then only AFTER a candidate pool
|
|
1038
|
+
* exists, so a disabled/failed rerank changes the ORDER and nothing else.
|
|
1039
|
+
*
|
|
1040
|
+
* @param options - catalog knobs (prefix, description limit, optional
|
|
1041
|
+
* rankQuery). MAY be a live options object (plain getters): the factory
|
|
1042
|
+
* reads `prefix`, `servers`, `descriptionLimit`, `getGate` and
|
|
1043
|
+
* `rankQuery` through the object on EVERY execution, so volatile config can
|
|
1044
|
+
* be wired by reference — only the description text freezes at factory
|
|
1045
|
+
* time.
|
|
767
1046
|
* @param listSchemas - visible-schemas source (production: `ctx.tools.schemas`,
|
|
768
1047
|
* called with the calling agent so restrictions are respected).
|
|
769
1048
|
* @returns the complete tool definition.
|
|
770
1049
|
*/
|
|
771
1050
|
export declare function createMcpListTool(options: McpListOptions, listSchemas: (scope?: ScopeKey) => readonly ToolSchema[]): ToolDefinition;
|
|
1051
|
+
/**
|
|
1052
|
+
* Optional seams {@link createMcpCallTool} wires into mcp_call. All three are
|
|
1053
|
+
* contained: a throwing hook degrades to the pre-seam behavior and never
|
|
1054
|
+
* breaks a dispatch.
|
|
1055
|
+
*/
|
|
1056
|
+
export interface McpCallHooks {
|
|
1057
|
+
/**
|
|
1058
|
+
* Near-miss pool for the unknown-tool branch, resolved in the CALLING
|
|
1059
|
+
* agent's scope (production: the scope's visible prefix tools). Absent ⇒
|
|
1060
|
+
* the pre-seam error text, unchanged.
|
|
1061
|
+
*/
|
|
1062
|
+
didYouMean?: (scope: ScopeKey | undefined) => readonly RankCandidate[];
|
|
1063
|
+
/**
|
|
1064
|
+
* Async rerank of that pool (production: System One). Resolving to
|
|
1065
|
+
* `undefined` or rejecting keeps the lexical order.
|
|
1066
|
+
*/
|
|
1067
|
+
didYouMeanRank?: (scope: ScopeKey | undefined, tool: string, candidates: readonly RankCandidate[]) => Promise<readonly string[] | undefined>;
|
|
1068
|
+
/**
|
|
1069
|
+
* Told about every finished dispatch, success and failure alike (production:
|
|
1070
|
+
* the usage store). Receives `tool: undefined` for a call that never named
|
|
1071
|
+
* one. Synchronous and best-effort: this is on the hot path, so it must not
|
|
1072
|
+
* return a promise and must never be awaited.
|
|
1073
|
+
*/
|
|
1074
|
+
onDispatched?: (event: {
|
|
1075
|
+
tool: string | undefined;
|
|
1076
|
+
error: boolean;
|
|
1077
|
+
}) => void;
|
|
1078
|
+
}
|
|
772
1079
|
/**
|
|
773
1080
|
* Build the `mcp_call` meta-tool definition.
|
|
1081
|
+
*
|
|
774
1082
|
* @param prefix - the configured MCP prefix (dispatch boundary). A thunk is
|
|
775
1083
|
* accepted so volatile config is re-read on every dispatch; a plain string
|
|
776
1084
|
* freezes the boundary at factory time.
|
|
@@ -782,9 +1090,10 @@ export declare function createMcpListTool(options: McpListOptions, listSchemas:
|
|
|
782
1090
|
* gate store's current mirror; default/omitted: nothing is disabled).
|
|
783
1091
|
* Deliberately a callback — the definition object outlives any one gate
|
|
784
1092
|
* snapshot and must observe later /mcp enable/disable writes.
|
|
1093
|
+
* @param hooks - the usage/did-you-mean seams (default: none wired).
|
|
785
1094
|
* @returns the complete tool definition.
|
|
786
1095
|
*/
|
|
787
|
-
export declare function createMcpCallTool(prefix: string | (() => string), resolve: (name: string, scope?: ScopeKey) => ToolDefinition | undefined, servers?: readonly string[] | (() => readonly string[]), getGate?: () => ServerGateState | undefined): ToolDefinition;
|
|
1096
|
+
export declare function createMcpCallTool(prefix: string | (() => string), resolve: (name: string, scope?: ScopeKey) => ToolDefinition | undefined, servers?: readonly string[] | (() => readonly string[]), getGate?: () => ServerGateState | undefined, hooks?: McpCallHooks): ToolDefinition;
|
|
788
1097
|
/**
|
|
789
1098
|
* Register the two meta-tools and install the assembly folding listener.
|
|
790
1099
|
*
|
|
@@ -799,11 +1108,19 @@ export declare function createMcpCallTool(prefix: string | (() => string), resol
|
|
|
799
1108
|
* unreadable document degrades to the empty gate (everything enabled) at
|
|
800
1109
|
* load time, keeping the assemble waterfall alive.
|
|
801
1110
|
*
|
|
802
|
-
* Config volatility: every knob (prefix/keep/servers/descriptionLimit
|
|
803
|
-
* volatile reference — 0.1.7 settings-page writes swap
|
|
804
|
-
* WITHOUT remounting the plugin, so nothing captured at apply
|
|
805
|
-
* stale: the waterfall, both meta-tools and the /mcp command all
|
|
806
|
-
* through {@link cfgNow} per use.
|
|
1111
|
+
* Config volatility: every knob (prefix/keep/servers/descriptionLimit AND the
|
|
1112
|
+
* seven jev* keys) is a volatile reference — 0.1.7 settings-page writes swap
|
|
1113
|
+
* values in place WITHOUT remounting the plugin, so nothing captured at apply
|
|
1114
|
+
* time may go stale: the waterfall, both meta-tools and the /mcp command all
|
|
1115
|
+
* re-read through {@link cfgNow} / {@link jevEnv} per use.
|
|
1116
|
+
*
|
|
1117
|
+
* System One wiring (the only remote calls in this plugin): the decision log,
|
|
1118
|
+
* the usage mirror and the suggestion document all live in the SAME gate
|
|
1119
|
+
* directory as gate.json. The seams are wired to exactly three places — the
|
|
1120
|
+
* background keep-suggestion batch ({@link maybeSuggestBatch}, fired by the
|
|
1121
|
+
* usage counter and awaited by nobody), `mcp_list`'s model-explicit `query`,
|
|
1122
|
+
* and `mcp_call`'s unknown-tool branch. Folding, an unqueried catalog, and a
|
|
1123
|
+
* successful dispatch touch none of them.
|
|
807
1124
|
*
|
|
808
1125
|
* Commands: `/mcp` mounts through a runtime `ctx.inject(['commands'], ...)`,
|
|
809
1126
|
* so hosts without the commands service keep this plugin fully functional —
|