@vivantel/virage-mcp 0.1.2
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 +81 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +27 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +27 -0
- package/dist/index.test.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +62 -0
- package/dist/server.js.map +1 -0
- package/dist/tools.d.ts +43 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +61 -0
- package/dist/tools.js.map +1 -0
- package/package.json +66 -0
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# @vivantel/virage-mcp
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@vivantel/virage-mcp)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
MCP (Model Context Protocol) stdio server for [Virage RAG](https://github.com/vivantel/virage). Expose your indexed knowledge base to AI assistants — search and inspect chunks directly from Claude Desktop, Claude Code, or any MCP-compatible client.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **search** — semantic vector search with similarity scores
|
|
11
|
+
- **list_chunks** — browse indexed chunks, filter by source file
|
|
12
|
+
- **get_chunk** — fetch a single chunk by content hash
|
|
13
|
+
- **list_source_files** — see all indexed files with chunk counts
|
|
14
|
+
- **get_stats** — index statistics (totals, embedding/upload status)
|
|
15
|
+
|
|
16
|
+
All tools are **read-only** — the server never modifies your index.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @vivantel/virage-mcp
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
Requires a `virage.config.json` in your project (generated by `virage init`).
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
virage-mcp --config ./virage.config.json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Claude Desktop configuration
|
|
33
|
+
|
|
34
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"mcpServers": {
|
|
39
|
+
"virage": {
|
|
40
|
+
"command": "npx",
|
|
41
|
+
"args": [
|
|
42
|
+
"@vivantel/virage-mcp",
|
|
43
|
+
"--config",
|
|
44
|
+
"/absolute/path/to/your/virage.config.json"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Claude Code configuration
|
|
52
|
+
|
|
53
|
+
Run inside your project:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
claude mcp add virage -- npx @vivantel/virage-mcp --config ./virage.config.json
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Programmatic use
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { createMcpServer } from "@vivantel/virage-mcp";
|
|
63
|
+
import { loadConfig, EmbeddingsDb, defaultEmbeddingsDb } from "@vivantel/virage-core";
|
|
64
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
65
|
+
|
|
66
|
+
const cfg = await loadConfig("./virage.config.json");
|
|
67
|
+
const db = new EmbeddingsDb(defaultEmbeddingsDb());
|
|
68
|
+
await cfg.vectorStore.initialize();
|
|
69
|
+
|
|
70
|
+
const server = createMcpServer({ db, embedder: cfg.embedder, vectorStore: cfg.vectorStore });
|
|
71
|
+
await server.connect(new StdioServerTransport());
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Requirements
|
|
75
|
+
|
|
76
|
+
- Node.js ≥ 18
|
|
77
|
+
- A configured Virage project with `virage.config.json` and a populated `.virage/embeddings.db`
|
|
78
|
+
|
|
79
|
+
## License
|
|
80
|
+
|
|
81
|
+
MIT © Vivantel
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { loadConfig, EmbeddingsDb, defaultEmbeddingsDb, } from "@vivantel/virage-core";
|
|
4
|
+
import { createMcpServer } from "./server.js";
|
|
5
|
+
const configIdx = process.argv.indexOf("--config");
|
|
6
|
+
if (configIdx === -1 || !process.argv[configIdx + 1]) {
|
|
7
|
+
process.stderr.write("Usage: virage-mcp --config <path-to-virage.config.json>\n");
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
const configPath = process.argv[configIdx + 1];
|
|
11
|
+
const cfg = await loadConfig(configPath);
|
|
12
|
+
const dbPath = cfg.options?.embeddingsFile?.replace(/\.json$/, ".db") ?? defaultEmbeddingsDb();
|
|
13
|
+
const db = new EmbeddingsDb(dbPath);
|
|
14
|
+
await cfg.vectorStore.initialize();
|
|
15
|
+
const ctx = { db, embedder: cfg.embedder, vectorStore: cfg.vectorStore };
|
|
16
|
+
const server = createMcpServer(ctx);
|
|
17
|
+
const transport = new StdioServerTransport();
|
|
18
|
+
await server.connect(transport);
|
|
19
|
+
process.on("SIGINT", () => {
|
|
20
|
+
db.close();
|
|
21
|
+
process.exit(0);
|
|
22
|
+
});
|
|
23
|
+
process.on("SIGTERM", () => {
|
|
24
|
+
db.close();
|
|
25
|
+
process.exit(0);
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -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,EACL,UAAU,EACV,YAAY,EACZ,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AACnD,IAAI,SAAS,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,CAAC;IACrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,2DAA2D,CAC5D,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AACD,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;AAE/C,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;AAEzC,MAAM,MAAM,GAER,GAAG,CAAC,OACL,EAAE,cAAc,EAAE,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,mBAAmB,EAAE,CAAC;AAExE,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;AACpC,MAAM,GAAG,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;AAEnC,MAAM,GAAG,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC;AACzE,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;AACpC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAEhC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;IACxB,EAAE,CAAC,KAAK,EAAE,CAAC;IACX,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AACH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;IACzB,EAAE,CAAC,KAAK,EAAE,CAAC;IACX,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { createMcpServer } from "./server.js";
|
|
3
|
+
import { handleSearch, handleListChunks, handleGetChunk, handleListSourceFiles, handleGetStats, } from "./tools.js";
|
|
4
|
+
describe("package exports", () => {
|
|
5
|
+
it("createMcpServer is a function", () => {
|
|
6
|
+
expect(typeof createMcpServer).toBe("function");
|
|
7
|
+
});
|
|
8
|
+
it("tool handlers are functions", () => {
|
|
9
|
+
expect(typeof handleSearch).toBe("function");
|
|
10
|
+
expect(typeof handleListChunks).toBe("function");
|
|
11
|
+
expect(typeof handleGetChunk).toBe("function");
|
|
12
|
+
expect(typeof handleListSourceFiles).toBe("function");
|
|
13
|
+
expect(typeof handleGetStats).toBe("function");
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
describe("createMcpServer", () => {
|
|
17
|
+
it("creates a server with registered tools", () => {
|
|
18
|
+
const ctx = {
|
|
19
|
+
db: {},
|
|
20
|
+
embedder: {},
|
|
21
|
+
vectorStore: {},
|
|
22
|
+
};
|
|
23
|
+
const server = createMcpServer(ctx);
|
|
24
|
+
expect(server).toBeDefined();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,OAAO,eAAe,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,OAAO,YAAY,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,CAAC,OAAO,gBAAgB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACjD,MAAM,CAAC,OAAO,cAAc,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC/C,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,MAAM,CAAC,OAAO,cAAc,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,GAAG,GAAG;YACV,EAAE,EAAE,EAAW;YACf,QAAQ,EAAE,EAAW;YACrB,WAAW,EAAE,EAAW;SACzB,CAAC;QACF,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAS7C,wBAAgB,eAAe,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,CAwF1D"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { handleSearch, handleListChunks, handleGetChunk, handleListSourceFiles, handleGetStats, } from "./tools.js";
|
|
4
|
+
export function createMcpServer(ctx) {
|
|
5
|
+
const server = new McpServer({ name: "virage-mcp", version: "0.1.0" });
|
|
6
|
+
server.tool("search", "Semantic vector search over the indexed documents. Returns top matching chunks with similarity scores.", {
|
|
7
|
+
query: z.string().describe("Search query text"),
|
|
8
|
+
top_k: z
|
|
9
|
+
.number()
|
|
10
|
+
.int()
|
|
11
|
+
.min(1)
|
|
12
|
+
.max(50)
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Number of results to return (default: 5)"),
|
|
15
|
+
collection: z
|
|
16
|
+
.string()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe("Optional collection name to search within"),
|
|
19
|
+
}, async (args) => {
|
|
20
|
+
const results = await handleSearch(args, ctx);
|
|
21
|
+
return {
|
|
22
|
+
content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
server.tool("list_chunks", "List indexed chunks, optionally filtered by source file.", {
|
|
26
|
+
source_file: z.string().optional().describe("Filter by source file path"),
|
|
27
|
+
limit: z
|
|
28
|
+
.number()
|
|
29
|
+
.int()
|
|
30
|
+
.min(1)
|
|
31
|
+
.max(1000)
|
|
32
|
+
.optional()
|
|
33
|
+
.describe("Maximum number of chunks to return (default: 100)"),
|
|
34
|
+
}, async (args) => {
|
|
35
|
+
const results = await handleListChunks(args, ctx);
|
|
36
|
+
return {
|
|
37
|
+
content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
server.tool("get_chunk", "Get a single chunk by its content hash.", {
|
|
41
|
+
content_hash: z.string().describe("16-character hex content hash"),
|
|
42
|
+
}, async (args) => {
|
|
43
|
+
const result = await handleGetChunk(args, ctx);
|
|
44
|
+
return {
|
|
45
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
server.tool("list_source_files", "List all indexed source files with their chunk counts.", {}, async () => {
|
|
49
|
+
const results = await handleListSourceFiles({}, ctx);
|
|
50
|
+
return {
|
|
51
|
+
content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
server.tool("get_stats", "Get index statistics: total chunks, embedding and upload status.", {}, async () => {
|
|
55
|
+
const result = await handleGetStats({}, ctx);
|
|
56
|
+
return {
|
|
57
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
return server;
|
|
61
|
+
}
|
|
62
|
+
//# 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/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { EmbeddingsDb, EmbeddingProvider, VectorStore } from "@vivantel/virage-core";
|
|
2
|
+
export interface McpContext {
|
|
3
|
+
db: EmbeddingsDb;
|
|
4
|
+
embedder: EmbeddingProvider;
|
|
5
|
+
vectorStore: VectorStore;
|
|
6
|
+
}
|
|
7
|
+
export declare function handleSearch(args: {
|
|
8
|
+
query: string;
|
|
9
|
+
top_k?: number;
|
|
10
|
+
collection?: string;
|
|
11
|
+
}, ctx: McpContext): Promise<{
|
|
12
|
+
id: string;
|
|
13
|
+
content: string;
|
|
14
|
+
metadata: Record<string, unknown>;
|
|
15
|
+
similarity: number;
|
|
16
|
+
sourceFile: string;
|
|
17
|
+
}[]>;
|
|
18
|
+
export declare function handleListChunks(args: {
|
|
19
|
+
source_file?: string;
|
|
20
|
+
limit?: number;
|
|
21
|
+
}, ctx: McpContext): Promise<{
|
|
22
|
+
contentHash: string | undefined;
|
|
23
|
+
sourceFile: string;
|
|
24
|
+
content: string;
|
|
25
|
+
metadata: Record<string, unknown>;
|
|
26
|
+
}[]>;
|
|
27
|
+
export declare function handleGetChunk(args: {
|
|
28
|
+
content_hash: string;
|
|
29
|
+
}, ctx: McpContext): Promise<import("@vivantel/virage-core").Chunk>;
|
|
30
|
+
export declare function handleListSourceFiles(_args: Record<string, never>, ctx: McpContext): Promise<{
|
|
31
|
+
sourceFile: string;
|
|
32
|
+
chunkCount: number;
|
|
33
|
+
commitHash: string | null;
|
|
34
|
+
}[]>;
|
|
35
|
+
export declare function handleGetStats(_args: Record<string, never>, ctx: McpContext): Promise<{
|
|
36
|
+
totalChunks: number;
|
|
37
|
+
embeddedCount: number;
|
|
38
|
+
uploadedCount: number;
|
|
39
|
+
pendingEmbedCount: number;
|
|
40
|
+
pendingUploadCount: number;
|
|
41
|
+
lastUpdated: number | null;
|
|
42
|
+
}>;
|
|
43
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACZ,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,YAAY,CAAC;IACjB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5D,GAAG,EAAE,UAAU;;;;;;KAehB;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EAC9C,GAAG,EAAE,UAAU;;;;;KAYhB;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,EAC9B,GAAG,EAAE,UAAU,kDAOhB;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAC5B,GAAG,EAAE,UAAU;;;;KAehB;AAED,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAC5B,GAAG,EAAE,UAAU;;;;;;;GAkBhB"}
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export async function handleSearch(args, ctx) {
|
|
2
|
+
const embedding = await ctx.embedder.embed(args.query);
|
|
3
|
+
const results = await ctx.vectorStore.search(embedding, args.top_k ?? 5, args.collection);
|
|
4
|
+
return results.map((r) => ({
|
|
5
|
+
id: r.id,
|
|
6
|
+
content: r.content,
|
|
7
|
+
metadata: r.metadata,
|
|
8
|
+
similarity: r.similarity,
|
|
9
|
+
sourceFile: r.metadata["sourceFile"] ?? r.id,
|
|
10
|
+
}));
|
|
11
|
+
}
|
|
12
|
+
export async function handleListChunks(args, ctx) {
|
|
13
|
+
let chunks = ctx.db.getAllChunks();
|
|
14
|
+
if (args.source_file) {
|
|
15
|
+
chunks = chunks.filter((c) => c.sourceFile === args.source_file);
|
|
16
|
+
}
|
|
17
|
+
return chunks.slice(0, args.limit ?? 100).map((c) => ({
|
|
18
|
+
contentHash: c.contentHash,
|
|
19
|
+
sourceFile: c.sourceFile,
|
|
20
|
+
content: c.content.slice(0, 200),
|
|
21
|
+
metadata: c.metadata,
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
export async function handleGetChunk(args, ctx) {
|
|
25
|
+
const chunk = ctx.db
|
|
26
|
+
.getAllChunks()
|
|
27
|
+
.find((c) => c.contentHash === args.content_hash);
|
|
28
|
+
if (!chunk)
|
|
29
|
+
throw new Error(`Chunk not found: ${args.content_hash}`);
|
|
30
|
+
return chunk;
|
|
31
|
+
}
|
|
32
|
+
export async function handleListSourceFiles(_args, ctx) {
|
|
33
|
+
const chunks = ctx.db.getAllChunks();
|
|
34
|
+
const fileStates = ctx.db.getFileStates();
|
|
35
|
+
const countMap = new Map();
|
|
36
|
+
for (const c of chunks) {
|
|
37
|
+
countMap.set(c.sourceFile, (countMap.get(c.sourceFile) ?? 0) + 1);
|
|
38
|
+
}
|
|
39
|
+
return Array.from(countMap.entries()).map(([sourceFile, chunkCount]) => ({
|
|
40
|
+
sourceFile,
|
|
41
|
+
chunkCount,
|
|
42
|
+
commitHash: fileStates.get(sourceFile) ?? null,
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
export async function handleGetStats(_args, ctx) {
|
|
46
|
+
const allChunks = ctx.db.getAllChunks();
|
|
47
|
+
const embedded = ctx.db.getAll();
|
|
48
|
+
const pendingEmbedCount = ctx.db.getPendingEmbedChunks().length;
|
|
49
|
+
const pendingUploadCount = ctx.db.pendingCount();
|
|
50
|
+
const uploadedCount = allChunks.length - pendingEmbedCount - pendingUploadCount;
|
|
51
|
+
const meta = ctx.db.getMeta();
|
|
52
|
+
return {
|
|
53
|
+
totalChunks: allChunks.length,
|
|
54
|
+
embeddedCount: embedded.length,
|
|
55
|
+
uploadedCount: Math.max(0, uploadedCount),
|
|
56
|
+
pendingEmbedCount,
|
|
57
|
+
pendingUploadCount,
|
|
58
|
+
lastUpdated: meta?.updatedAt ?? null,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vivantel/virage-mcp",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "MCP stdio server for Virage RAG — search and inspect your index from AI assistants",
|
|
6
|
+
"author": "Vivantel",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"rag",
|
|
10
|
+
"mcp",
|
|
11
|
+
"model-context-protocol",
|
|
12
|
+
"embeddings",
|
|
13
|
+
"search",
|
|
14
|
+
"virage"
|
|
15
|
+
],
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/vivantel/virage",
|
|
19
|
+
"directory": "packages/virage-mcp"
|
|
20
|
+
},
|
|
21
|
+
"main": "dist/index.js",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"import": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"bin": {
|
|
29
|
+
"virage-mcp": "./dist/cli.js"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"README.md"
|
|
34
|
+
],
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18.0.0"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "rm -rf dist && tsc",
|
|
43
|
+
"type-check": "tsc --noEmit",
|
|
44
|
+
"test": "vitest run",
|
|
45
|
+
"prepublishOnly": "npm run build",
|
|
46
|
+
"lint": "eslint src/",
|
|
47
|
+
"lint:fix": "eslint src/ --fix",
|
|
48
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
49
|
+
"format:check": "prettier --check \"src/**/*.ts\"",
|
|
50
|
+
"fix": "npm run lint:fix && npm run format"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
54
|
+
"zod": "^3.24.0",
|
|
55
|
+
"@vivantel/virage-core": "0.2.11"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"@vivantel/virage-core": "*"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@vivantel/virage-core": "0.2.11",
|
|
62
|
+
"@types/node": "^25.9.1",
|
|
63
|
+
"typescript": "^6.0.3",
|
|
64
|
+
"vitest": "^4.1.8"
|
|
65
|
+
}
|
|
66
|
+
}
|