mirror of
https://github.com/hansjone/dsh-search-mcp.git
synced 2026-10-14 09:20:45 +08:00
Restore Search MCP settings on Desktop via Settings sidebar.
Mark Config volatile, always register settings.section with a deferred form scope, and keep the Web plugins card (0.2.3). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
743e894598
commit
c1fed965b1
5 changed files with 322 additions and 123 deletions
62
lib/index.js
62
lib/index.js
|
|
@ -29,29 +29,38 @@ export const name = 'search-mcp';
|
|||
/** The web seam this provider registers into. */
|
||||
export const inject = ['web'];
|
||||
|
||||
/**
|
||||
* DSH ≥0.1.7 / 0.2.0 only projects Config fields marked `.volatile()` into the
|
||||
* settings UI. Zero volatile fields → the whole entry is silently filtered.
|
||||
* Older schemastery without `volatile` keeps the bare schema (≤0.1.5 path).
|
||||
*/
|
||||
function vol(schema) {
|
||||
return typeof schema?.volatile === 'function' ? schema.volatile() : schema;
|
||||
}
|
||||
|
||||
const serverSchema = z.object({
|
||||
id: z.string(),
|
||||
kind: z.string().default('custom'),
|
||||
transport: z.string().default('http'),
|
||||
url: z.string().default(''),
|
||||
command: z.string().default(''),
|
||||
args: z.array(z.string()).default([]),
|
||||
apiKey: z.string().role('secret'),
|
||||
apiKeyEnv: z.string().role('credential-ref').default(''),
|
||||
authStyle: z.string().default(''),
|
||||
authParam: z.string().default(''),
|
||||
authPrefix: z.string().default(''),
|
||||
toolName: z.string().default(''),
|
||||
id: vol(z.string()),
|
||||
kind: vol(z.string().default('custom')),
|
||||
transport: vol(z.string().default('http')),
|
||||
url: vol(z.string().default('')),
|
||||
command: vol(z.string().default('')),
|
||||
args: vol(z.array(z.string()).default([])),
|
||||
apiKey: vol(z.string().role('secret')),
|
||||
apiKeyEnv: vol(z.string().role('credential-ref').default('')),
|
||||
authStyle: vol(z.string().default('')),
|
||||
authParam: vol(z.string().default('')),
|
||||
authPrefix: vol(z.string().default('')),
|
||||
toolName: vol(z.string().default('')),
|
||||
// Note: this schemastery fork has no `.optional()`; object fields are
|
||||
// optional unless `.required()` is applied, so absence is already allowed.
|
||||
maxResults: z.number().step(1).min(1).max(50),
|
||||
maxResults: vol(z.number().step(1).min(1).max(50)),
|
||||
});
|
||||
|
||||
export const Config = z.object({
|
||||
defaultServer: z.string().default(''),
|
||||
maxResults: z.number().step(1).min(1).max(50).default(8),
|
||||
searchTimeoutMs: z.number().step(1).min(1000).default(30000),
|
||||
servers: z.array(serverSchema).default([]),
|
||||
defaultServer: vol(z.string().default('')),
|
||||
maxResults: vol(z.number().step(1).min(1).max(50).default(8)),
|
||||
searchTimeoutMs: vol(z.number().step(1).min(1000).default(30000)),
|
||||
servers: vol(z.array(serverSchema).default([])),
|
||||
});
|
||||
|
||||
/** Settings namespace owning this plugin's section (Settings → Plugins card). */
|
||||
|
|
@ -87,6 +96,23 @@ export function apply(ctx, config) {
|
|||
settings.installSection(ctx, SEARCH_MCP_SETTINGS_NAMESPACE, Config, config, hooks);
|
||||
return;
|
||||
}
|
||||
// ≤0.1.5 / some Desktop builds: explicit namespace registration.
|
||||
// ≥0.1.7: Config is projected from the Loader entry — register may be
|
||||
// absent or refuse; follow describe().
|
||||
if (typeof settings?.register === 'function') {
|
||||
try {
|
||||
settings.register(SEARCH_MCP_SETTINGS_NAMESPACE, Config, { base: config, applies: 'live' });
|
||||
settingsCtx.logger?.info?.(
|
||||
'dsh-search-mcp: settings namespace "%s" registered',
|
||||
SEARCH_MCP_SETTINGS_NAMESPACE,
|
||||
);
|
||||
} catch (error) {
|
||||
settingsCtx.logger?.warn?.(
|
||||
'dsh-search-mcp: settings.register failed (will follow describe): %s',
|
||||
error instanceof Error ? error.message : error,
|
||||
);
|
||||
}
|
||||
}
|
||||
// DSH ≥0.1.7 / 0.2.0 — Config projection via describe() (no installSection).
|
||||
const readLive = () => {
|
||||
const row = describeRows(settings?.describe).find((item) => item.ns === SEARCH_MCP_SETTINGS_NAMESPACE);
|
||||
|
|
@ -106,7 +132,7 @@ export function apply(ctx, config) {
|
|||
}, 2_000);
|
||||
settingsCtx.effect(() => () => clearInterval(timer), 'dsh-search-mcp: settings describe poll');
|
||||
settingsCtx.logger?.info?.(
|
||||
'dsh-search-mcp: following settings via describe() (no installSection — DSH ≥0.1.7 path)',
|
||||
'dsh-search-mcp: following settings via describe() (DSH ≥0.1.7 / 0.2 path)',
|
||||
);
|
||||
});
|
||||
// `registerSearchProvider` owns its cleanup via ctx.effect (HMR/dispose safe).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue