@neottia/searchable-mcp 0.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dragos Cirjan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # @neottia/searchable-mcp
2
+
3
+ Generic stdio MCP server for the five Searchable tools.
4
+
5
+ ```sh
6
+ pnpm dlx @neottia/searchable-mcp
7
+ ```
8
+
9
+ Run the command from the project working directory after setting `modules.searchable.enabled: true`. The server exposes tools only. Use MCP `tools/list` to verify `web_search`, `web_fetch`, `web_stash`, `web_grep`, and `web_ask`.
10
+
11
+ The server resolves the complete `@neottia/config-registry` snapshot once for its working directory and passes the immutable Searchable shard to its runtime and tools. It forwards request cancellation, returns object results as structured content and JSON text, and returns redacted structured errors as text. It owns one Searchable runtime and closes network and cache resources with `server.close()` or process termination.
12
+
13
+ Read the [Searchable MCP guide](https://github.com/dragoscirjan/neottia/blob/main/docs/mcp/searchable.md).
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { createSearchableServer } from './server.js';
4
+ const server = createSearchableServer();
5
+ let closing = false;
6
+ async function close() {
7
+ if (closing)
8
+ return;
9
+ closing = true;
10
+ await server.close();
11
+ }
12
+ process.once('SIGINT', () => void close());
13
+ process.once('SIGTERM', () => void close());
14
+ await server.connect(new StdioServerTransport());
15
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,MAAM,GAAG,sBAAsB,EAAE,CAAC;AACxC,IAAI,OAAO,GAAG,KAAK,CAAC;AACpB,KAAK,UAAU,KAAK;IAClB,IAAI,OAAO;QAAE,OAAO;IACpB,OAAO,GAAG,IAAI,CAAC;IACf,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC;AACD,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;AAC3C,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;AAC5C,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './server.js';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from './server.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import type { ResolvedConfigSnapshot } from '@neottia/config';
3
+ import { type SearchableConfigInput, type SearchableRuntimeFactory } from '@neottia/searchable-core';
4
+ export interface CreateSearchableServerOptions {
5
+ readonly cwd?: string;
6
+ readonly name?: string;
7
+ readonly version?: string;
8
+ readonly snapshot?: ResolvedConfigSnapshot;
9
+ readonly env?: NodeJS.ProcessEnv;
10
+ readonly configOverrides?: Partial<SearchableConfigInput>;
11
+ readonly runtimeFactory?: SearchableRuntimeFactory;
12
+ }
13
+ export declare function createSearchableServer(options?: CreateSearchableServerOptions): Server;
package/dist/server.js ADDED
@@ -0,0 +1,59 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
3
+ import { resolveHostConfigSnapshot } from '@neottia/config-registry';
4
+ import { createSearchableRuntime, findSearchableTool, searchableToolJsonSchema, SEARCHABLE_TOOLS, SearchableError, searchableConfigContribution, serializeSearchableError, } from '@neottia/searchable-core';
5
+ export function createSearchableServer(options = {}) {
6
+ const cwd = options.cwd ?? process.cwd();
7
+ const snapshot = resolveHostConfigSnapshot({
8
+ interactive: false,
9
+ cwd,
10
+ ...(options.snapshot ? { snapshot: options.snapshot } : {}),
11
+ ...(options.env ? { env: options.env } : {}),
12
+ ...(options.configOverrides ? { overrides: { modules: { searchable: options.configOverrides } } } : {}),
13
+ });
14
+ const config = snapshot.get(searchableConfigContribution);
15
+ const runtime = (options.runtimeFactory ?? createSearchableRuntime)({ cwd, config });
16
+ const server = new Server({ name: options.name ?? '@neottia/searchable-mcp', version: options.version ?? '0.1.0' }, { capabilities: { tools: {} } });
17
+ const baseClose = server.close.bind(server);
18
+ let closePromise;
19
+ server.close = () => {
20
+ closePromise ??= Promise.allSettled([runtime.close(), baseClose()]).then((results) => {
21
+ const errors = results.flatMap((result) => (result.status === 'rejected' ? [result.reason] : []));
22
+ if (errors.length)
23
+ throw new AggregateError(errors, 'Searchable MCP shutdown failed.');
24
+ });
25
+ return closePromise;
26
+ };
27
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
28
+ tools: SEARCHABLE_TOOLS.map((definition) => ({
29
+ name: definition.name,
30
+ description: definition.description,
31
+ inputSchema: searchableToolJsonSchema(definition.name, 'input'),
32
+ outputSchema: searchableToolJsonSchema(definition.name, 'output'),
33
+ })),
34
+ }));
35
+ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
36
+ const definition = findSearchableTool(request.params.name);
37
+ if (!definition)
38
+ return toolError(new SearchableError('validation', 'TOOL_NOT_FOUND', `Unknown tool: ${request.params.name}`));
39
+ try {
40
+ const result = await definition.run({ cwd, services: runtime, signal: extra.signal, config }, request.params.arguments ?? {});
41
+ const structured = result;
42
+ return {
43
+ content: [{ type: 'text', text: JSON.stringify(structured, null, 2) }],
44
+ structuredContent: structured,
45
+ };
46
+ }
47
+ catch (error) {
48
+ return toolError(error instanceof SearchableError
49
+ ? error
50
+ : new SearchableError('service', 'SERVICE_FAILED', 'Searchable service failed.'));
51
+ }
52
+ });
53
+ return server;
54
+ }
55
+ function toolError(error) {
56
+ const body = serializeSearchableError(error);
57
+ return { content: [{ type: 'text', text: JSON.stringify(body) }], isError: true };
58
+ }
59
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@neottia/searchable-mcp",
3
+ "version": "0.2.0",
4
+ "description": "Generic MCP stdio server for Neottia Searchable",
5
+ "author": "Dragos Cirjan",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "sideEffects": false,
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/dragoscirjan/neottia.git",
12
+ "directory": "packages/searchable-mcp"
13
+ },
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "bin": {
18
+ "searchable-mcp": "./dist/cli.js"
19
+ },
20
+ "main": "./dist/index.js",
21
+ "types": "./dist/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "default": "./dist/index.js"
26
+ }
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "README.md",
31
+ "LICENSE"
32
+ ],
33
+ "engines": {
34
+ "node": ">=22.16.0"
35
+ },
36
+ "dependencies": {
37
+ "@modelcontextprotocol/sdk": "^1.30.0",
38
+ "@neottia/config": "^0.2.0",
39
+ "@neottia/config-registry": "^0.2.0",
40
+ "@neottia/searchable-core": "0.2.0"
41
+ },
42
+ "devDependencies": {
43
+ "@templ-project/tsconfig": "^0.2.2",
44
+ "@types/node": "^25.0.3",
45
+ "typescript": "^5.9.3",
46
+ "vitest": "^4.1.11",
47
+ "@neottia/testkit": "0.1.0"
48
+ },
49
+ "scripts": {
50
+ "build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json",
51
+ "pretest": "node ../../scripts/run-unless-workspace-prebuilt.mjs pnpm --filter @neottia/searchable-mcp... run build",
52
+ "test": "vitest run --root ../.. packages/searchable-mcp/src",
53
+ "typecheck": "tsc --noEmit"
54
+ }
55
+ }