everything-mcp-server 0.0.0-stage → 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 +21 -0
- package/README.md +262 -2
- package/README.zh-CN.md +263 -0
- package/THIRD_PARTY_NOTICES.md +9 -0
- package/examples/c-drive-folders.json +11 -0
- package/examples/c-drive-largest.json +15 -0
- package/package.json +51 -4
- package/src/agent.js +92 -0
- package/src/cli.js +37 -0
- package/src/compact.js +64 -0
- package/src/discovery.js +47 -0
- package/src/everything.js +166 -0
- package/src/ipc.js +82 -0
- package/src/process.js +22 -0
- package/src/schema.js +92 -0
- package/src/server.js +41 -0
- package/src/validation.js +42 -0
- package/vendor/es/ARM/es.exe +0 -0
- package/vendor/es/ARM64/es.exe +0 -0
- package/vendor/es/LICENSE +21 -0
- package/vendor/es/manifest.json +26 -0
- package/vendor/es/x64/es.exe +0 -0
- package/vendor/es/x86/es.exe +0 -0
package/src/server.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { readFileSync } from 'node:fs';
|
|
5
|
+
import { AgentClient } from './agent.js';
|
|
6
|
+
import { syntax } from './everything.js';
|
|
7
|
+
import { compactSearch } from './compact.js';
|
|
8
|
+
import { errorResult, requestsSchema, diagnosticSchema, searchOutputSchema, statusOutputSchema } from './schema.js';
|
|
9
|
+
|
|
10
|
+
export const instructions = 'Search the selected Everything index. columns label row cells. When base is present, join it and relative row paths with a single / for absolute paths. Continue with next_offset and the same filters. Sizes are indexed logical bytes.';
|
|
11
|
+
const { name, version = 'unreleased' } = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
|
|
12
|
+
|
|
13
|
+
export function createServer(client = new AgentClient()) {
|
|
14
|
+
const server = new McpServer({ name, version }, { instructions });
|
|
15
|
+
const register = (name, description, inputSchema, outputSchema, handler) => server.registerTool(name, {
|
|
16
|
+
description, inputSchema, outputSchema,
|
|
17
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
18
|
+
}, async (args, extra) => {
|
|
19
|
+
try {
|
|
20
|
+
const result = outputSchema.parse(await handler(args, extra.signal));
|
|
21
|
+
const failed = result.ready === false || result.results?.every(item => item.error);
|
|
22
|
+
return { content: [{ type: 'text', text: JSON.stringify(result) }], structuredContent: result, ...(failed ? { isError: true } : {}) };
|
|
23
|
+
} catch (error) {
|
|
24
|
+
return { content: [{ type: 'text', text: JSON.stringify(errorResult(error)) }], isError: true };
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
register('search', 'Find file/folder paths and indexed metadata across drives or within root. Use workspace search or rg for file contents. Submit 1–8 requests; recursive:false browses; count:0 counts; add kind:"file", fields:["size"] to sum matched bytes.', requestsSchema, searchOutputSchema, (args, signal) => compactSearch(client, args, signal));
|
|
29
|
+
register('status', 'Check connection status, selected instance, version, and index readiness.', diagnosticSchema, statusOutputSchema, (args, signal) => client.status(signal, args.verbose));
|
|
30
|
+
server.registerResource('everything-syntax', 'everything://syntax', { description: 'Query syntax and result semantics', mimeType: 'application/json' }, async uri => ({ contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(syntax) }] }));
|
|
31
|
+
return server;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function startServer() {
|
|
35
|
+
await createServer().connect(new StdioServerTransport());
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
39
|
+
try { await startServer(); }
|
|
40
|
+
catch (error) { console.error(JSON.stringify(errorResult(error))); process.exitCode = 1; }
|
|
41
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
|
+
import { AgentError } from './schema.js';
|
|
3
|
+
|
|
4
|
+
// Preserve quoted filename literals while identifying query functions.
|
|
5
|
+
export function queryFunctions(query) {
|
|
6
|
+
const plain = query.replace(/"[^"]*"/g, ' ');
|
|
7
|
+
return [...plain.matchAll(/(?<![a-z0-9_-])\$?([a-z][a-z0-9_-]*):/gi)].map(match => match[1].toLowerCase());
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function validateQuery(input) {
|
|
11
|
+
if (input.regex) return [];
|
|
12
|
+
const functions = queryFunctions(input.query);
|
|
13
|
+
for (const fn of functions) {
|
|
14
|
+
if (/content$/.test(fn) || ['include-filelist', 'include', 'filter', 'macro'].includes(fn)) {
|
|
15
|
+
throw new AgentError('UNSUPPORTED_QUERY', `Query function '${fn}:' is not supported in file path searches.`);
|
|
16
|
+
}
|
|
17
|
+
if (fn === 'regex') throw new AgentError('UNSUPPORTED_QUERY', 'Set regex:true and place the pattern in query.');
|
|
18
|
+
if (['sort', 'count', 'offset', 'distinct', 'unique'].includes(fn)) {
|
|
19
|
+
throw new AgentError('UNSUPPORTED_QUERY', `Query function '${fn}:' alters result semantics; use corresponding request parameters instead.`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return functions;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function validateRoot(root, timeoutMs = 3000, signal) {
|
|
26
|
+
let timer;
|
|
27
|
+
const cleanup = new AbortController();
|
|
28
|
+
try {
|
|
29
|
+
const info = await Promise.race([
|
|
30
|
+
stat(root),
|
|
31
|
+
new Promise((_, reject) => { timer = setTimeout(() => reject(new AgentError('ROOT_CHECK_TIMEOUT', 'Root accessibility check timed out', true)), timeoutMs); }),
|
|
32
|
+
...(signal ? [new Promise((_, reject) => {
|
|
33
|
+
if (signal.aborted) reject(new AgentError('CANCELLED', 'Request cancelled', true));
|
|
34
|
+
else signal.addEventListener('abort', () => reject(new AgentError('CANCELLED', 'Request cancelled', true)), { once: true, signal: cleanup.signal });
|
|
35
|
+
})] : []),
|
|
36
|
+
]);
|
|
37
|
+
if (!info.isDirectory()) throw new AgentError('ROOT_NOT_DIRECTORY', 'Provide a directory as root');
|
|
38
|
+
} catch (error) {
|
|
39
|
+
if (error instanceof AgentError) throw error;
|
|
40
|
+
throw new AgentError(['ENOENT', 'ENOTDIR'].includes(error.code) ? 'ROOT_NOT_FOUND' : 'ROOT_INACCESSIBLE', 'Provide an accessible root directory', false, 'Check the root path spelling, availability, and permissions.');
|
|
41
|
+
} finally { clearTimeout(timer); cleanup.abort(); }
|
|
42
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 voidtools
|
|
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.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.1.0.38",
|
|
3
|
+
"source": "https://github.com/voidtools/ES/tree/1.1.0.38",
|
|
4
|
+
"files": [
|
|
5
|
+
{
|
|
6
|
+
"path": "x64/es.exe",
|
|
7
|
+
"sha256": "f7378761cf6e01f51c4123a485e628d70e3fea147d341f473ce2820844e5cee5",
|
|
8
|
+
"source": "https://www.voidtools.com/ES-1.1.0.38.x64.zip"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"path": "x86/es.exe",
|
|
12
|
+
"sha256": "d3fef37ce9f25a44bb2898848b8eca0f44b0b22766b644c6e4e436b7f9d4b4fe",
|
|
13
|
+
"source": "https://www.voidtools.com/ES-1.1.0.38.x86.zip"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"path": "ARM64/es.exe",
|
|
17
|
+
"sha256": "7fc406610559f686a95a9bfc4472acffdebcc143b485ae9371b5ef4590e7ec31",
|
|
18
|
+
"source": "https://www.voidtools.com/ES-1.1.0.38.ARM64.zip"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"path": "ARM/es.exe",
|
|
22
|
+
"sha256": "7a0ebe57eecdc1c7ae227732020f3b14ad80a8cea78f4d91c35bb8d8e1eac11d",
|
|
23
|
+
"source": "https://www.voidtools.com/ES-1.1.0.38.ARM.zip"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
Binary file
|
|
Binary file
|