opencontext-mcp 1.2.1 → 1.3.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 +38 -12
- package/dist/cli/index.d.ts +25 -0
- package/dist/cli/index.js +97 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/{config.d.ts → config/index.d.ts} +1 -1
- package/dist/config/index.js +62 -0
- package/dist/config/index.js.map +1 -0
- package/dist/index.js +52 -9
- package/dist/index.js.map +1 -1
- package/dist/init/constants.d.ts +6 -0
- package/dist/init/constants.js +17 -0
- package/dist/init/constants.js.map +1 -0
- package/dist/init/display.d.ts +9 -0
- package/dist/init/display.js +28 -0
- package/dist/init/display.js.map +1 -0
- package/dist/init/files.d.ts +12 -0
- package/dist/init/files.js +39 -0
- package/dist/init/files.js.map +1 -0
- package/dist/init/index.d.ts +6 -0
- package/dist/init/index.js +157 -0
- package/dist/init/index.js.map +1 -0
- package/dist/init/inspect.d.ts +21 -0
- package/dist/init/inspect.js +57 -0
- package/dist/init/inspect.js.map +1 -0
- package/dist/init/integrations/claude.d.ts +17 -0
- package/dist/init/integrations/claude.js +94 -0
- package/dist/init/integrations/claude.js.map +1 -0
- package/dist/init/integrations/opencode.d.ts +20 -0
- package/dist/init/integrations/opencode.js +108 -0
- package/dist/init/integrations/opencode.js.map +1 -0
- package/dist/init/integrations/workflow-files.d.ts +23 -0
- package/dist/init/integrations/workflow-files.js +102 -0
- package/dist/init/integrations/workflow-files.js.map +1 -0
- package/dist/init/prompts.d.ts +9 -0
- package/dist/init/prompts.js +17 -0
- package/dist/init/prompts.js.map +1 -0
- package/dist/server/http.d.ts +21 -0
- package/dist/server/http.js +63 -0
- package/dist/server/http.js.map +1 -0
- package/dist/{server.d.ts → server/index.d.ts} +3 -1
- package/dist/{server.js → server/index.js} +7 -4
- package/dist/server/index.js.map +1 -0
- package/dist/shared/constants.d.ts +27 -0
- package/dist/shared/constants.js +26 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/errors.d.ts +17 -0
- package/dist/shared/errors.js +28 -0
- package/dist/shared/errors.js.map +1 -0
- package/dist/shared/types.d.ts +29 -0
- package/dist/shared/types.js +17 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/{context-store.d.ts → store/context-store.d.ts} +2 -16
- package/dist/store/context-store.js +147 -0
- package/dist/store/context-store.js.map +1 -0
- package/dist/store/index-builder.d.ts +32 -0
- package/dist/store/index-builder.js +162 -0
- package/dist/store/index-builder.js.map +1 -0
- package/dist/validation/index.d.ts +16 -0
- package/dist/validation/index.js +39 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/{validation.d.ts → validation/write-guard.d.ts} +0 -16
- package/dist/{validation.js → validation/write-guard.js} +2 -38
- package/dist/validation/write-guard.js.map +1 -0
- package/package.json +2 -2
- package/dist/config.js +0 -145
- package/dist/config.js.map +0 -1
- package/dist/context-store.js +0 -296
- package/dist/context-store.js.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/types.d.ts +0 -56
- package/dist/types.js +0 -63
- package/dist/types.js.map +0 -1
- package/dist/validation.js.map +0 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompts the user for a yes/no answer.
|
|
3
|
+
* @param rl - Readline interface
|
|
4
|
+
* @param message - Prompt message
|
|
5
|
+
* @param defaultYes - Default answer when the user presses Enter
|
|
6
|
+
* @returns true if user confirms
|
|
7
|
+
*/
|
|
8
|
+
export async function promptForConfirm(rl, message, defaultYes = false) {
|
|
9
|
+
const hint = defaultYes ? "Y/n" : "y/N";
|
|
10
|
+
const answer = await rl.question(`${message} (${hint}): `);
|
|
11
|
+
const trimmed = answer.trim().toLowerCase();
|
|
12
|
+
if (trimmed === "") {
|
|
13
|
+
return defaultYes;
|
|
14
|
+
}
|
|
15
|
+
return trimmed === "y" || trimmed === "yes";
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/init/prompts.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,EAAsB,EACtB,OAAe,EACf,UAAU,GAAG,KAAK;IAElB,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IACxC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,OAAO,KAAK,IAAI,KAAK,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QACnB,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,OAAO,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,KAAK,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
export interface HttpServerOptions {
|
|
3
|
+
host: string;
|
|
4
|
+
port: number;
|
|
5
|
+
buildServer: () => Promise<McpServer>;
|
|
6
|
+
}
|
|
7
|
+
export interface HttpServerHandle {
|
|
8
|
+
/** Fully-qualified MCP endpoint URL, e.g. http://127.0.0.1:3001/mcp */
|
|
9
|
+
url: string;
|
|
10
|
+
close: () => Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Serves an MCP server over HTTP using the Streamable HTTP transport.
|
|
14
|
+
*
|
|
15
|
+
* Each request gets a fresh server instance and a stateless transport, matching
|
|
16
|
+
* the MCP Streamable HTTP reference pattern: no sessions are tracked in memory.
|
|
17
|
+
*
|
|
18
|
+
* @param options - Host, port, and a server factory
|
|
19
|
+
* @returns The endpoint URL and a close handle
|
|
20
|
+
*/
|
|
21
|
+
export declare function startHttpServer(options: HttpServerOptions): Promise<HttpServerHandle>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createServer, } from "node:http";
|
|
2
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
3
|
+
import { SERVER_NAME, SERVER_VERSION } from "../shared/constants.js";
|
|
4
|
+
import { getErrorMessage } from "../shared/errors.js";
|
|
5
|
+
/**
|
|
6
|
+
* Serves an MCP server over HTTP using the Streamable HTTP transport.
|
|
7
|
+
*
|
|
8
|
+
* Each request gets a fresh server instance and a stateless transport, matching
|
|
9
|
+
* the MCP Streamable HTTP reference pattern: no sessions are tracked in memory.
|
|
10
|
+
*
|
|
11
|
+
* @param options - Host, port, and a server factory
|
|
12
|
+
* @returns The endpoint URL and a close handle
|
|
13
|
+
*/
|
|
14
|
+
export async function startHttpServer(options) {
|
|
15
|
+
const handleRequest = async (req, res) => {
|
|
16
|
+
if (req.method === "GET" && req.url === "/") {
|
|
17
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
18
|
+
res.end(JSON.stringify({ name: SERVER_NAME, version: SERVER_VERSION }));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const mcpServer = await options.buildServer();
|
|
23
|
+
// Omitting sessionIdGenerator puts the transport in stateless mode.
|
|
24
|
+
const transport = new StreamableHTTPServerTransport();
|
|
25
|
+
await mcpServer.connect(transport);
|
|
26
|
+
try {
|
|
27
|
+
await transport.handleRequest(req, res);
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
await mcpServer.close();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (!res.headersSent) {
|
|
35
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
36
|
+
res.end(JSON.stringify({
|
|
37
|
+
jsonrpc: "2.0",
|
|
38
|
+
error: { code: -32603, message: getErrorMessage(error) },
|
|
39
|
+
id: null,
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const server = createServer(handleRequest);
|
|
45
|
+
await new Promise((resolve, reject) => {
|
|
46
|
+
server.once("error", reject);
|
|
47
|
+
server.listen(options.port, options.host, () => {
|
|
48
|
+
server.off("error", reject);
|
|
49
|
+
resolve();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
const address = server.address();
|
|
53
|
+
const boundPort = typeof address === "object" && address !== null ? address.port : options.port;
|
|
54
|
+
const displayHost = options.host === "0.0.0.0" || options.host === "::" ? "localhost" : options.host;
|
|
55
|
+
const url = `http://${displayHost}:${boundPort}/mcp`;
|
|
56
|
+
return {
|
|
57
|
+
url,
|
|
58
|
+
close: async () => {
|
|
59
|
+
await new Promise((resolve) => server.close(() => resolve()));
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/server/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import { type ResolvedConfig } from "
|
|
2
|
+
import { type ResolvedConfig } from "../config/index.js";
|
|
3
3
|
/**
|
|
4
4
|
* Creates and configures the OpenContext MCP server.
|
|
5
5
|
* Registers all available tools (save_context, read_context).
|
|
@@ -7,3 +7,5 @@ import { type ResolvedConfig } from "./config.js";
|
|
|
7
7
|
* @param config - Optional pre-loaded config (loads from disk if omitted)
|
|
8
8
|
*/
|
|
9
9
|
export declare function createOpenContextServer(basePath?: string, config?: ResolvedConfig): Promise<McpServer>;
|
|
10
|
+
export { startHttpServer } from "./http.js";
|
|
11
|
+
export type { HttpServerOptions, HttpServerHandle } from "./http.js";
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { ContextStore } from "
|
|
4
|
-
import { SERVER_NAME, SERVER_VERSION
|
|
5
|
-
import {
|
|
3
|
+
import { ContextStore } from "../store/context-store.js";
|
|
4
|
+
import { SERVER_NAME, SERVER_VERSION } from "../shared/constants.js";
|
|
5
|
+
import { getErrorMessage } from "../shared/errors.js";
|
|
6
|
+
import { textResult } from "../shared/types.js";
|
|
7
|
+
import { loadConfig } from "../config/index.js";
|
|
6
8
|
/**
|
|
7
9
|
* Creates and configures the OpenContext MCP server.
|
|
8
10
|
* Registers all available tools (save_context, read_context).
|
|
@@ -89,4 +91,5 @@ export async function createOpenContextServer(basePath, config) {
|
|
|
89
91
|
});
|
|
90
92
|
return server;
|
|
91
93
|
}
|
|
92
|
-
|
|
94
|
+
export { startHttpServer } from "./http.js";
|
|
95
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** MCP server identifier used in protocol handshakes. */
|
|
2
|
+
export declare const SERVER_NAME = "opencontext-mcp";
|
|
3
|
+
/** Current server version for compatibility checks. */
|
|
4
|
+
export declare const SERVER_VERSION = "1.2.1";
|
|
5
|
+
/** Filename for the auto-generated context index. */
|
|
6
|
+
export declare const INDEX_FILENAME = "index.md";
|
|
7
|
+
/** Package name published on npm, launched via npx in generated configs. */
|
|
8
|
+
export declare const OPENCONTEXT_MCP_PACKAGE = "opencontext-mcp";
|
|
9
|
+
/** Default host the HTTP(S) server binds to. */
|
|
10
|
+
export declare const DEFAULT_HTTP_HOST = "127.0.0.1";
|
|
11
|
+
/** Default port the HTTP(S) server listens on. */
|
|
12
|
+
export declare const DEFAULT_HTTP_PORT = 3032;
|
|
13
|
+
/** Topic names reserved by the system — cannot be written by external agents. */
|
|
14
|
+
export declare const RESERVED_TOPICS: ReadonlySet<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Allowed values for the topic status field in YAML frontmatter.
|
|
17
|
+
* Kept next to the badges so both stay in sync.
|
|
18
|
+
*/
|
|
19
|
+
export type TopicStatus = "active" | "deprecated" | "superseded";
|
|
20
|
+
/** Badge prefix used in index.md for non-active topics. */
|
|
21
|
+
export declare const STATUS_BADGES: ReadonlyMap<TopicStatus, string>;
|
|
22
|
+
/**
|
|
23
|
+
* Regex pattern for validating topic names.
|
|
24
|
+
* Allows lowercase alphanumeric with single hyphens or underscores as separators.
|
|
25
|
+
* Examples: "api_contracts", "auth-rules", "migration-v2"
|
|
26
|
+
*/
|
|
27
|
+
export declare const TOPIC_PATTERN: RegExp;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** MCP server identifier used in protocol handshakes. */
|
|
2
|
+
export const SERVER_NAME = "opencontext-mcp";
|
|
3
|
+
/** Current server version for compatibility checks. */
|
|
4
|
+
export const SERVER_VERSION = "1.2.1";
|
|
5
|
+
/** Filename for the auto-generated context index. */
|
|
6
|
+
export const INDEX_FILENAME = "index.md";
|
|
7
|
+
/** Package name published on npm, launched via npx in generated configs. */
|
|
8
|
+
export const OPENCONTEXT_MCP_PACKAGE = "opencontext-mcp";
|
|
9
|
+
/** Default host the HTTP(S) server binds to. */
|
|
10
|
+
export const DEFAULT_HTTP_HOST = "127.0.0.1";
|
|
11
|
+
/** Default port the HTTP(S) server listens on. */
|
|
12
|
+
export const DEFAULT_HTTP_PORT = 3032;
|
|
13
|
+
/** Topic names reserved by the system — cannot be written by external agents. */
|
|
14
|
+
export const RESERVED_TOPICS = new Set(["index"]);
|
|
15
|
+
/** Badge prefix used in index.md for non-active topics. */
|
|
16
|
+
export const STATUS_BADGES = new Map([
|
|
17
|
+
["deprecated", "[DEPRECATED]"],
|
|
18
|
+
["superseded", "[SUPERSEDED]"],
|
|
19
|
+
]);
|
|
20
|
+
/**
|
|
21
|
+
* Regex pattern for validating topic names.
|
|
22
|
+
* Allows lowercase alphanumeric with single hyphens or underscores as separators.
|
|
23
|
+
* Examples: "api_contracts", "auth-rules", "migration-v2"
|
|
24
|
+
*/
|
|
25
|
+
export const TOPIC_PATTERN = /^[a-z0-9]+(?:[_-][a-z0-9]+)*$/;
|
|
26
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/shared/constants.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,MAAM,CAAC,MAAM,WAAW,GAAG,iBAAiB,CAAC;AAE7C,uDAAuD;AACvD,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAEtC,qDAAqD;AACrD,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;AAEzC,4EAA4E;AAC5E,MAAM,CAAC,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;AAEzD,gDAAgD;AAChD,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAC;AAE7C,kDAAkD;AAClD,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAEtC,iFAAiF;AACjF,MAAM,CAAC,MAAM,eAAe,GAAwB,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAQvE,2DAA2D;AAC3D,MAAM,CAAC,MAAM,aAAa,GAAqC,IAAI,GAAG,CAAC;IACrE,CAAC,YAAY,EAAE,cAAc,CAAC;IAC9B,CAAC,YAAY,EAAE,cAAc,CAAC;CAC/B,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error for user input validation problems.
|
|
3
|
+
* Thrown when topic names, content, or other user inputs fail validation.
|
|
4
|
+
*/
|
|
5
|
+
export declare class UserInputError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Safely extracts an error message from unknown error types.
|
|
10
|
+
* Handles Error objects, strings, and any other unexpected value.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getErrorMessage(error: unknown): string;
|
|
13
|
+
/**
|
|
14
|
+
* Type guard for Node.js filesystem errors.
|
|
15
|
+
* Lets callers distinguish ENOENT, EACCES, etc. from other failures.
|
|
16
|
+
*/
|
|
17
|
+
export declare function isNodeError(error: unknown): error is NodeJS.ErrnoException;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error for user input validation problems.
|
|
3
|
+
* Thrown when topic names, content, or other user inputs fail validation.
|
|
4
|
+
*/
|
|
5
|
+
export class UserInputError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "UserInputError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Safely extracts an error message from unknown error types.
|
|
13
|
+
* Handles Error objects, strings, and any other unexpected value.
|
|
14
|
+
*/
|
|
15
|
+
export function getErrorMessage(error) {
|
|
16
|
+
if (error instanceof Error) {
|
|
17
|
+
return error.message;
|
|
18
|
+
}
|
|
19
|
+
return "An unknown error occurred.";
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Type guard for Node.js filesystem errors.
|
|
23
|
+
* Lets callers distinguish ENOENT, EACCES, etc. from other failures.
|
|
24
|
+
*/
|
|
25
|
+
export function isNodeError(error) {
|
|
26
|
+
return error instanceof Error && "code" in error;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/shared/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IAED,OAAO,4BAA4B,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { TopicStatus } from "./constants.js";
|
|
2
|
+
/** Outcome of a config/file upsert, used for user-facing status output. */
|
|
3
|
+
export type ConfigStatus = "created" | "updated" | "unchanged" | "skipped";
|
|
4
|
+
/** Result of writing or updating an agent integration config file. */
|
|
5
|
+
export interface ConfigWriteResult {
|
|
6
|
+
status: ConfigStatus;
|
|
7
|
+
message: string;
|
|
8
|
+
}
|
|
9
|
+
/** Parsed YAML frontmatter from a topic file. All fields optional. */
|
|
10
|
+
export interface TopicFrontmatter {
|
|
11
|
+
description?: string;
|
|
12
|
+
status?: TopicStatus;
|
|
13
|
+
/** The topic this one replaces (used by the newer topic). */
|
|
14
|
+
supersedes?: string;
|
|
15
|
+
/** The topic that replaced this one (used by the older topic). */
|
|
16
|
+
superseded_by?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a standardized MCP tool response object.
|
|
20
|
+
* @param text - Response message
|
|
21
|
+
* @param isError - Whether this is an error response (default: false)
|
|
22
|
+
*/
|
|
23
|
+
export declare function textResult(text: string, isError?: boolean): {
|
|
24
|
+
isError?: boolean;
|
|
25
|
+
content: {
|
|
26
|
+
type: "text";
|
|
27
|
+
text: string;
|
|
28
|
+
}[];
|
|
29
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a standardized MCP tool response object.
|
|
3
|
+
* @param text - Response message
|
|
4
|
+
* @param isError - Whether this is an error response (default: false)
|
|
5
|
+
*/
|
|
6
|
+
export function textResult(text, isError = false) {
|
|
7
|
+
return {
|
|
8
|
+
content: [
|
|
9
|
+
{
|
|
10
|
+
type: "text",
|
|
11
|
+
text,
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
...(isError ? { isError: true } : {}),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAqBA;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,OAAO,GAAG,KAAK;IACtD,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI;aACL;SACF;QACD,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtC,CAAC;AACJ,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ResolvedConfig } from "
|
|
1
|
+
import { type ResolvedConfig } from "../config/index.js";
|
|
2
2
|
/**
|
|
3
3
|
* Manages context file storage operations.
|
|
4
4
|
* Handles reading, writing, and listing context files in the configured directory.
|
|
@@ -14,7 +14,7 @@ export declare class ContextStore {
|
|
|
14
14
|
getTopicFilePath(topic: string): string;
|
|
15
15
|
/**
|
|
16
16
|
* Saves context content to a topic file.
|
|
17
|
-
* Validates payload using
|
|
17
|
+
* Validates the payload using the write guard before writing.
|
|
18
18
|
* @param topicInput - Topic name (will be validated and trimmed)
|
|
19
19
|
* @param content - Markdown content to save
|
|
20
20
|
* @returns Success message with file location
|
|
@@ -41,22 +41,8 @@ export declare class ContextStore {
|
|
|
41
41
|
* @returns Sorted array of topic names
|
|
42
42
|
*/
|
|
43
43
|
listTopics(): Promise<string[]>;
|
|
44
|
-
/**
|
|
45
|
-
* Parses YAML frontmatter from markdown content.
|
|
46
|
-
* Returns extracted fields or empty object if no frontmatter found.
|
|
47
|
-
* Uses simple line-by-line parsing — no external YAML dependency.
|
|
48
|
-
*/
|
|
49
|
-
private parseFrontmatter;
|
|
50
|
-
/**
|
|
51
|
-
* Extracts a short description from markdown content.
|
|
52
|
-
* Strategy: frontmatter description → first heading → first paragraph → fallback.
|
|
53
|
-
* @param content - Raw markdown content
|
|
54
|
-
* @returns Truncated description (max 120 chars)
|
|
55
|
-
*/
|
|
56
|
-
private extractDescription;
|
|
57
44
|
/**
|
|
58
45
|
* Rebuilds the auto-generated index.md file in the context directory.
|
|
59
|
-
* Scans all topic files, extracts metadata, and writes a compact index.
|
|
60
46
|
* @returns The generated index markdown content
|
|
61
47
|
*/
|
|
62
48
|
rebuildContextIndex(): Promise<string>;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { mkdir, readdir, readFile, writeFile, lstat, unlink } from "node:fs/promises";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { UserInputError, isNodeError } from "../shared/errors.js";
|
|
4
|
+
import { validateTopic, sanitizeTopicPath } from "../validation/index.js";
|
|
5
|
+
import { validateWritePayload } from "../validation/write-guard.js";
|
|
6
|
+
import { buildContextIndex } from "./index-builder.js";
|
|
7
|
+
import { DEFAULT_CONFIG } from "../config/index.js";
|
|
8
|
+
/**
|
|
9
|
+
* Manages context file storage operations.
|
|
10
|
+
* Handles reading, writing, and listing context files in the configured directory.
|
|
11
|
+
*/
|
|
12
|
+
export class ContextStore {
|
|
13
|
+
basePath;
|
|
14
|
+
config;
|
|
15
|
+
contextDir;
|
|
16
|
+
constructor(basePath = process.cwd(), config = DEFAULT_CONFIG) {
|
|
17
|
+
this.basePath = basePath;
|
|
18
|
+
this.config = config;
|
|
19
|
+
this.contextDir = path.join(this.basePath, this.config.path);
|
|
20
|
+
}
|
|
21
|
+
/** Returns the absolute path to the context directory. */
|
|
22
|
+
getContextDirectory() {
|
|
23
|
+
return this.contextDir;
|
|
24
|
+
}
|
|
25
|
+
/** Returns the absolute path to a topic file. */
|
|
26
|
+
getTopicFilePath(topic) {
|
|
27
|
+
return path.join(this.contextDir, `${topic}.md`);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Saves context content to a topic file.
|
|
31
|
+
* Validates the payload using the write guard before writing.
|
|
32
|
+
* @param topicInput - Topic name (will be validated and trimmed)
|
|
33
|
+
* @param content - Markdown content to save
|
|
34
|
+
* @returns Success message with file location
|
|
35
|
+
* @throws UserInputError if validation fails
|
|
36
|
+
*/
|
|
37
|
+
async saveContext(topicInput, content) {
|
|
38
|
+
const guardResult = validateWritePayload(topicInput, content, {
|
|
39
|
+
maxFileSizeKb: this.config.guard.maxFileSizeKb,
|
|
40
|
+
strictPatternCheck: this.config.guard.strictPatternCheck,
|
|
41
|
+
});
|
|
42
|
+
if (!guardResult.allowed) {
|
|
43
|
+
console.error(`WriteGuard Rejected: ${guardResult.reason} (Code: ${guardResult.code})`);
|
|
44
|
+
throw new UserInputError(`WriteGuard Rejected: ${guardResult.reason} (Code: ${guardResult.code})`);
|
|
45
|
+
}
|
|
46
|
+
const topic = validateTopic(topicInput);
|
|
47
|
+
const filePath = sanitizeTopicPath(this.contextDir, topic);
|
|
48
|
+
// Reject writes to existing symlinks — prevents symlink traversal attacks
|
|
49
|
+
try {
|
|
50
|
+
const fileStat = await lstat(filePath);
|
|
51
|
+
if (fileStat.isSymbolicLink()) {
|
|
52
|
+
throw new UserInputError(`Refusing to overwrite symlink at ${this.config.path}/${topic}.md. Delete the symlink first.`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (isNodeError(error) && error.code === "ENOENT") {
|
|
57
|
+
// File does not exist yet — normal case, continue
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
await mkdir(this.contextDir, { recursive: true });
|
|
64
|
+
await writeFile(filePath, content, "utf8");
|
|
65
|
+
return `Saved context topic "${topic}" to ${this.config.path}/${topic}.md.`;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Reads context content from a topic file, or lists all topics if none specified.
|
|
69
|
+
* @param topicInput - Optional topic name to read
|
|
70
|
+
* @returns Topic content or list of available topics
|
|
71
|
+
* @throws UserInputError if topic doesn't exist or is invalid
|
|
72
|
+
*/
|
|
73
|
+
async readContext(topicInput) {
|
|
74
|
+
if (topicInput !== undefined) {
|
|
75
|
+
const topic = validateTopic(topicInput);
|
|
76
|
+
try {
|
|
77
|
+
const filePath = sanitizeTopicPath(this.contextDir, topic);
|
|
78
|
+
return await readFile(filePath, "utf8");
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (isNodeError(error) && error.code === "ENOENT") {
|
|
82
|
+
throw new UserInputError(`No context found for topic "${topic}" at ${this.config.path}/${topic}.md.`);
|
|
83
|
+
}
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const topics = await this.listTopics();
|
|
88
|
+
if (topics.length === 0) {
|
|
89
|
+
return `No OpenContext topics found in ${this.config.path}/. Use save_context to create one.`;
|
|
90
|
+
}
|
|
91
|
+
if (!this.config.autoIndex) {
|
|
92
|
+
return topics.map((t) => `- ${t}`).join("\n");
|
|
93
|
+
}
|
|
94
|
+
return this.rebuildContextIndex();
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Deletes a context topic file from the context directory.
|
|
98
|
+
* @param topicInput - Topic name to delete
|
|
99
|
+
* @returns Success message with confirmation
|
|
100
|
+
* @throws UserInputError if topic doesn't exist or is invalid
|
|
101
|
+
*/
|
|
102
|
+
async deleteContext(topicInput) {
|
|
103
|
+
const topic = validateTopic(topicInput);
|
|
104
|
+
const filePath = sanitizeTopicPath(this.contextDir, topic);
|
|
105
|
+
try {
|
|
106
|
+
await unlink(filePath);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
if (isNodeError(error) && error.code === "ENOENT") {
|
|
110
|
+
throw new UserInputError(`No context found for topic "${topic}" at ${this.config.path}/${topic}.md.`);
|
|
111
|
+
}
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
if (this.config.autoIndex) {
|
|
115
|
+
await this.rebuildContextIndex();
|
|
116
|
+
}
|
|
117
|
+
return `Deleted context topic "${topic}" from ${this.config.path}/${topic}.md.`;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Lists all available context topics.
|
|
121
|
+
* Scans the context directory for .md files and returns sorted topic names.
|
|
122
|
+
* @returns Sorted array of topic names
|
|
123
|
+
*/
|
|
124
|
+
async listTopics() {
|
|
125
|
+
try {
|
|
126
|
+
const entries = await readdir(this.contextDir, { withFileTypes: true });
|
|
127
|
+
return entries
|
|
128
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith(".md"))
|
|
129
|
+
.map((entry) => entry.name.slice(0, -".md".length))
|
|
130
|
+
.sort((a, b) => a.localeCompare(b));
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
if (isNodeError(error) && error.code === "ENOENT") {
|
|
134
|
+
return [];
|
|
135
|
+
}
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Rebuilds the auto-generated index.md file in the context directory.
|
|
141
|
+
* @returns The generated index markdown content
|
|
142
|
+
*/
|
|
143
|
+
async rebuildContextIndex() {
|
|
144
|
+
return buildContextIndex(this.contextDir);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=context-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-store.js","sourceRoot":"","sources":["../../src/store/context-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type TopicStatus } from "../shared/constants.js";
|
|
2
|
+
import type { TopicFrontmatter } from "../shared/types.js";
|
|
3
|
+
export interface TopicIndexEntry {
|
|
4
|
+
topic: string;
|
|
5
|
+
filename: string;
|
|
6
|
+
description: string;
|
|
7
|
+
date: string;
|
|
8
|
+
sizeBytes: number;
|
|
9
|
+
status: TopicStatus | undefined;
|
|
10
|
+
supersedes: string | undefined;
|
|
11
|
+
superseded_by: string | undefined;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Parses YAML frontmatter from markdown content.
|
|
15
|
+
* Returns extracted fields or an empty object when no frontmatter is present.
|
|
16
|
+
* Uses simple line-by-line parsing — no external YAML dependency.
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseFrontmatter(content: string): TopicFrontmatter;
|
|
19
|
+
/**
|
|
20
|
+
* Extracts a short description from markdown content.
|
|
21
|
+
* Strategy: frontmatter description → first heading → first paragraph → fallback.
|
|
22
|
+
* @param content - Raw markdown content
|
|
23
|
+
* @returns Truncated description (max 120 chars)
|
|
24
|
+
*/
|
|
25
|
+
export declare function extractDescription(content: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Rebuilds the auto-generated index.md file in the context directory.
|
|
28
|
+
* Scans all topic files, extracts metadata, and writes a compact index.
|
|
29
|
+
* @param contextDir - Absolute path to the .opencontext directory
|
|
30
|
+
* @returns The generated index markdown content ("" when no topics exist)
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildContextIndex(contextDir: string): Promise<string>;
|