opencontext-mcp 1.2.0 → 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 +53 -7
- 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 -295
- 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
package/README.md
CHANGED
|
@@ -22,18 +22,36 @@ No vector databases, no cloud subscriptions, and no hidden state. Memory is plai
|
|
|
22
22
|
|
|
23
23
|
### Quickstart
|
|
24
24
|
|
|
25
|
-
Run directly without installation via `npx`:
|
|
25
|
+
Run the MCP server directly without installation via `npx`:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
28
|
npx -y opencontext-mcp
|
|
29
29
|
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
### One-Command Setup
|
|
33
|
+
|
|
34
|
+
Scaffold OpenContext in the current project interactively:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx -y opencontext-mcp init
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`init` walks you through the setup (enabling OpenCode and Claude Code integration) and generates everything you need:
|
|
41
|
+
|
|
42
|
+
- `.opencontext/` — directory that holds your context topic files
|
|
43
|
+
- `.opencontext.json` — configuration template
|
|
44
|
+
- `opencode.json` — MCP server entry for OpenCode
|
|
45
|
+
- `.mcp.json` — MCP server entry for Claude Code
|
|
46
|
+
- `AGENTS.md` / `CLAUDE.md` — workflow reminders for your agents
|
|
47
|
+
|
|
48
|
+
The `init` command takes no arguments: it always runs in the current directory, prompts interactively, and never overwrites an existing config.
|
|
49
|
+
|
|
32
50
|
### Client Setup
|
|
33
51
|
|
|
34
52
|
#### OpenCode
|
|
35
53
|
|
|
36
|
-
Add OpenContext to your project MCP configuration (`opencode.json`):
|
|
54
|
+
Add OpenContext to your project MCP configuration (`opencode.json`) — or let `opencontext-mcp init` do it for you:
|
|
37
55
|
|
|
38
56
|
```json
|
|
39
57
|
{
|
|
@@ -66,6 +84,22 @@ Add OpenContext to your MCP settings file (`claude_desktop_config.json` or Curso
|
|
|
66
84
|
|
|
67
85
|
---
|
|
68
86
|
|
|
87
|
+
### Remote Access (HTTP)
|
|
88
|
+
|
|
89
|
+
Expose the MCP server over the network with the Streamable HTTP transport. The endpoint URL is printed to stderr on startup.
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Plain HTTP on 127.0.0.1:3032 (default)
|
|
93
|
+
opencontext-mcp --http
|
|
94
|
+
|
|
95
|
+
# Custom port / bind to all interfaces
|
|
96
|
+
opencontext-mcp server --http --port 8787 --host 0.0.0.0
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The server listens at `http://<host>:<port>/mcp` (stateless Streamable HTTP — one request at a time, no sessions). `GET /` returns basic server info, handy for a browser health check.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
69
103
|
### Core Tools
|
|
70
104
|
|
|
71
105
|
| Tool | Parameters | Description |
|
|
@@ -121,27 +155,19 @@ When a topic becomes obsolete, call `delete_context` to remove it. For deprecate
|
|
|
121
155
|
|
|
122
156
|
### Configuration
|
|
123
157
|
|
|
124
|
-
Customize storage paths and security boundaries with an optional `.opencontext.
|
|
158
|
+
Customize storage paths and security boundaries with an optional `.opencontext.json` file in your repository root (plain JSON — comments are not supported):
|
|
125
159
|
|
|
126
|
-
```
|
|
160
|
+
```json
|
|
127
161
|
{
|
|
128
|
-
// Storage location (default: ".opencontext")
|
|
129
162
|
"path": ".opencontext",
|
|
130
|
-
|
|
131
|
-
// Prevent agents from writing or updating files
|
|
132
163
|
"readOnly": false,
|
|
133
|
-
|
|
134
|
-
// Auto-generate index.md with topic descriptions
|
|
135
164
|
"autoIndex": true,
|
|
136
|
-
|
|
137
|
-
// Write guard & prompt injection defenses
|
|
138
165
|
"guard": {
|
|
139
166
|
"enabled": true,
|
|
140
167
|
"maxFileSizeKb": 50,
|
|
141
168
|
"strictPatternCheck": true
|
|
142
169
|
}
|
|
143
170
|
}
|
|
144
|
-
|
|
145
171
|
```
|
|
146
172
|
|
|
147
173
|
---
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface ServerCliArgs {
|
|
2
|
+
command: "server";
|
|
3
|
+
transport: "stdio" | "http";
|
|
4
|
+
port: number;
|
|
5
|
+
host: string;
|
|
6
|
+
}
|
|
7
|
+
export type CliArgs = ServerCliArgs | {
|
|
8
|
+
command: "init";
|
|
9
|
+
} | {
|
|
10
|
+
command: "help";
|
|
11
|
+
} | {
|
|
12
|
+
command: "version";
|
|
13
|
+
};
|
|
14
|
+
export declare class CliError extends Error {
|
|
15
|
+
constructor(message: string);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parses command-line arguments into a structured CliArgs object.
|
|
19
|
+
* @param argv - Raw process.argv (defaults to process.argv)
|
|
20
|
+
* @returns Parsed arguments
|
|
21
|
+
* @throws CliError on invalid arguments
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseArgs(argv?: string[]): CliArgs;
|
|
24
|
+
export declare function printHelp(): void;
|
|
25
|
+
export declare function printVersion(): void;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { SERVER_VERSION, DEFAULT_HTTP_HOST, DEFAULT_HTTP_PORT, } from "../shared/constants.js";
|
|
2
|
+
export class CliError extends Error {
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "CliError";
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
const USAGE = `Usage: opencontext-mcp [command] [options]
|
|
9
|
+
|
|
10
|
+
Commands:
|
|
11
|
+
(default) Start the MCP server (stdio transport)
|
|
12
|
+
server Start the MCP server (alias of the default)
|
|
13
|
+
init Initialize OpenContext in the current directory
|
|
14
|
+
--help, -h Show this help message
|
|
15
|
+
--version, -v Show version number
|
|
16
|
+
|
|
17
|
+
Server options:
|
|
18
|
+
--http Serve over HTTP using the Streamable HTTP transport
|
|
19
|
+
--port <port> HTTP port (default: 3032)
|
|
20
|
+
--host <host> Interface to bind (default: 127.0.0.1)
|
|
21
|
+
|
|
22
|
+
Examples:
|
|
23
|
+
opencontext-mcp Start MCP server over stdio
|
|
24
|
+
opencontext-mcp --http Serve over HTTP at http://127.0.0.1:3032/mcp
|
|
25
|
+
opencontext-mcp server --http --port 8787`;
|
|
26
|
+
/**
|
|
27
|
+
* Parses command-line arguments into a structured CliArgs object.
|
|
28
|
+
* @param argv - Raw process.argv (defaults to process.argv)
|
|
29
|
+
* @returns Parsed arguments
|
|
30
|
+
* @throws CliError on invalid arguments
|
|
31
|
+
*/
|
|
32
|
+
export function parseArgs(argv = process.argv) {
|
|
33
|
+
const args = argv.slice(2);
|
|
34
|
+
if (args.length === 0) {
|
|
35
|
+
return { command: "server", transport: "stdio", port: DEFAULT_HTTP_PORT, host: DEFAULT_HTTP_HOST };
|
|
36
|
+
}
|
|
37
|
+
const first = args[0];
|
|
38
|
+
if (first === undefined) {
|
|
39
|
+
return { command: "server", transport: "stdio", port: DEFAULT_HTTP_PORT, host: DEFAULT_HTTP_HOST };
|
|
40
|
+
}
|
|
41
|
+
if (first === "--help" || first === "-h") {
|
|
42
|
+
return { command: "help" };
|
|
43
|
+
}
|
|
44
|
+
if (first === "--version" || first === "-v") {
|
|
45
|
+
return { command: "version" };
|
|
46
|
+
}
|
|
47
|
+
if (first === "init") {
|
|
48
|
+
return { command: "init" };
|
|
49
|
+
}
|
|
50
|
+
let index = first === "server" ? 1 : 0;
|
|
51
|
+
let transport = "stdio";
|
|
52
|
+
let port = DEFAULT_HTTP_PORT;
|
|
53
|
+
let host = DEFAULT_HTTP_HOST;
|
|
54
|
+
while (index < args.length) {
|
|
55
|
+
const arg = args[index];
|
|
56
|
+
if (arg === undefined) {
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
switch (arg) {
|
|
60
|
+
case "--http":
|
|
61
|
+
transport = "http";
|
|
62
|
+
index += 1;
|
|
63
|
+
break;
|
|
64
|
+
case "--port": {
|
|
65
|
+
const value = args[index + 1];
|
|
66
|
+
if (value === undefined || !/^\d+$/.test(value)) {
|
|
67
|
+
throw new CliError("--port requires a numeric value");
|
|
68
|
+
}
|
|
69
|
+
port = Number(value);
|
|
70
|
+
index += 2;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
case "--host": {
|
|
74
|
+
const value = args[index + 1];
|
|
75
|
+
if (value === undefined) {
|
|
76
|
+
throw new CliError("--host requires a value");
|
|
77
|
+
}
|
|
78
|
+
host = value;
|
|
79
|
+
index += 2;
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
default:
|
|
83
|
+
if (arg.startsWith("-")) {
|
|
84
|
+
throw new CliError(`Unknown option: ${arg}\n\nRun "opencontext-mcp --help" for usage.`);
|
|
85
|
+
}
|
|
86
|
+
throw new CliError(`Unknown command: ${arg}\n\nRun "opencontext-mcp --help" for usage.`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return { command: "server", transport, port, host };
|
|
90
|
+
}
|
|
91
|
+
export function printHelp() {
|
|
92
|
+
process.stdout.write(USAGE + "\n");
|
|
93
|
+
}
|
|
94
|
+
export function printVersion() {
|
|
95
|
+
process.stdout.write(SERVER_VERSION + "\n");
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,7 +18,7 @@ export interface OpenContextConfig {
|
|
|
18
18
|
export type ResolvedConfig = Required<Omit<OpenContextConfig, "$schema">>;
|
|
19
19
|
export declare const DEFAULT_CONFIG: ResolvedConfig;
|
|
20
20
|
/**
|
|
21
|
-
* Loads configuration from .opencontext.
|
|
21
|
+
* Loads configuration from .opencontext.json in the given directory.
|
|
22
22
|
* Falls back to DEFAULT_CONFIG if no file exists or parsing fails.
|
|
23
23
|
*/
|
|
24
24
|
export declare function loadConfig(cwd?: string): Promise<ResolvedConfig>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
export const DEFAULT_CONFIG = {
|
|
4
|
+
path: ".opencontext",
|
|
5
|
+
readOnly: false,
|
|
6
|
+
disabled: false,
|
|
7
|
+
autoIndex: true,
|
|
8
|
+
history: {
|
|
9
|
+
enabled: false,
|
|
10
|
+
maxBackupsPerTopic: 5,
|
|
11
|
+
retentionDays: 7,
|
|
12
|
+
},
|
|
13
|
+
guard: {
|
|
14
|
+
enabled: true,
|
|
15
|
+
maxFileSizeKb: 50,
|
|
16
|
+
strictPatternCheck: true,
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
const CONFIG_FILENAME = ".opencontext.json";
|
|
20
|
+
/**
|
|
21
|
+
* Merges a partial config object into a full one, recursing into nested
|
|
22
|
+
* objects (e.g. history, guard) instead of replacing them wholesale.
|
|
23
|
+
*/
|
|
24
|
+
function deepMerge(target, source) {
|
|
25
|
+
const result = { ...target };
|
|
26
|
+
for (const key of Object.keys(source)) {
|
|
27
|
+
const sourceVal = source[key];
|
|
28
|
+
const targetVal = result[key];
|
|
29
|
+
if (sourceVal !== null &&
|
|
30
|
+
typeof sourceVal === "object" &&
|
|
31
|
+
!Array.isArray(sourceVal) &&
|
|
32
|
+
targetVal !== null &&
|
|
33
|
+
typeof targetVal === "object" &&
|
|
34
|
+
!Array.isArray(targetVal)) {
|
|
35
|
+
result[key] = deepMerge(targetVal, sourceVal);
|
|
36
|
+
}
|
|
37
|
+
else if (sourceVal !== undefined) {
|
|
38
|
+
result[key] = sourceVal;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Loads configuration from .opencontext.json in the given directory.
|
|
45
|
+
* Falls back to DEFAULT_CONFIG if no file exists or parsing fails.
|
|
46
|
+
*/
|
|
47
|
+
export async function loadConfig(cwd = process.cwd()) {
|
|
48
|
+
const filePath = path.join(cwd, CONFIG_FILENAME);
|
|
49
|
+
try {
|
|
50
|
+
const raw = await readFile(filePath, "utf8");
|
|
51
|
+
const parsed = JSON.parse(raw);
|
|
52
|
+
return deepMerge(DEFAULT_CONFIG, parsed);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (error.code === "ENOENT") {
|
|
56
|
+
return DEFAULT_CONFIG;
|
|
57
|
+
}
|
|
58
|
+
console.error(`OpenContext: failed to parse ${CONFIG_FILENAME}: ${error.message}`);
|
|
59
|
+
return DEFAULT_CONFIG;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAsBlC,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,IAAI,EAAE,cAAc;IACpB,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE,IAAI;IACf,OAAO,EAAE;QACP,OAAO,EAAE,KAAK;QACd,kBAAkB,EAAE,CAAC;QACrB,aAAa,EAAE,CAAC;KACjB;IACD,KAAK,EAAE;QACL,OAAO,EAAE,IAAI;QACb,aAAa,EAAE,EAAE;QACjB,kBAAkB,EAAE,IAAI;KACzB;CACF,CAAC;AAEF,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAE5C;;;GAGG;AACH,SAAS,SAAS,CAAoC,MAAS,EAAE,MAAkB;IACjF,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;IAC7B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAmB,EAAE,CAAC;QACxD,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,IACE,SAAS,KAAK,IAAI;YAClB,OAAO,SAAS,KAAK,QAAQ;YAC7B,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;YACzB,SAAS,KAAK,IAAI;YAClB,OAAO,SAAS,KAAK,QAAQ;YAC7B,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EACzB,CAAC;YACA,MAAkC,CAAC,GAAa,CAAC,GAAG,SAAS,CAC5D,SAAoC,EACpC,SAAoC,CACrC,CAAC;QACJ,CAAC;aAAM,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,CAAC,GAAG,SAA0B,CAAC;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IAEjD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAsB,CAAC;QACpD,OAAO,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,OAAO,cAAc,CAAC;QACxB,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,gCAAgC,eAAe,KAAM,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9F,OAAO,cAAc,CAAC;IACxB,CAAC;AACH,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,62 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
-
import { createOpenContextServer } from "./server.js";
|
|
4
|
-
import { SERVER_NAME,
|
|
3
|
+
import { createOpenContextServer, startHttpServer } from "./server/index.js";
|
|
4
|
+
import { SERVER_NAME, SERVER_VERSION } from "./shared/constants.js";
|
|
5
|
+
import { getErrorMessage } from "./shared/errors.js";
|
|
6
|
+
import { parseArgs, printHelp, printVersion, CliError } from "./cli/index.js";
|
|
7
|
+
import { runInit } from "./init/index.js";
|
|
5
8
|
/**
|
|
6
|
-
* Main entry point for the OpenContext
|
|
7
|
-
*
|
|
9
|
+
* Main entry point for the OpenContext CLI.
|
|
10
|
+
* Routes to the appropriate command based on CLI arguments.
|
|
8
11
|
*/
|
|
9
12
|
async function main() {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
let args;
|
|
14
|
+
try {
|
|
15
|
+
args = parseArgs();
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
if (error instanceof CliError) {
|
|
19
|
+
process.stderr.write(`Error: ${error.message}\n`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
throw error;
|
|
23
|
+
}
|
|
24
|
+
switch (args.command) {
|
|
25
|
+
case "help":
|
|
26
|
+
printHelp();
|
|
27
|
+
return;
|
|
28
|
+
case "version":
|
|
29
|
+
printVersion();
|
|
30
|
+
return;
|
|
31
|
+
case "init":
|
|
32
|
+
await runInit();
|
|
33
|
+
return;
|
|
34
|
+
case "server":
|
|
35
|
+
default: {
|
|
36
|
+
if (args.transport === "http") {
|
|
37
|
+
const handle = await startHttpServer({
|
|
38
|
+
host: args.host,
|
|
39
|
+
port: args.port,
|
|
40
|
+
buildServer: () => createOpenContextServer(),
|
|
41
|
+
});
|
|
42
|
+
process.stderr.write(`[opencontext] v${SERVER_VERSION} active. ${handle.url}\n`);
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
const server = await createOpenContextServer();
|
|
46
|
+
const transport = new StdioServerTransport();
|
|
47
|
+
await server.connect(transport);
|
|
48
|
+
if (process.env.OPENCONTEXT_TELEMETRY_DISABLED !== "1" &&
|
|
49
|
+
process.env.DO_NOT_TRACK !== "1") {
|
|
50
|
+
process.stderr.write(`[opencontext] v${SERVER_VERSION} active. https://github.com/slxca/opencontext\n`);
|
|
51
|
+
}
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
13
55
|
}
|
|
56
|
+
// Clean exit on SIGINT — no orphaned temp files
|
|
57
|
+
process.on("SIGINT", () => {
|
|
58
|
+
process.exit(0);
|
|
59
|
+
});
|
|
14
60
|
main().catch((error) => {
|
|
15
61
|
console.error(`Failed to start ${SERVER_NAME}: ${getErrorMessage(error)}`);
|
|
16
62
|
process.exit(1);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C;;;GAGG;AACH,KAAK,UAAU,IAAI;IACjB,IAAI,IAAI,CAAC;IACT,IAAI,CAAC;QACH,IAAI,GAAG,SAAS,EAAE,CAAC;IACrB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;YAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;YAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IAED,QAAQ,IAAI,CAAC,OAAO,EAAE,CAAC;QACrB,KAAK,MAAM;YACT,SAAS,EAAE,CAAC;YACZ,OAAO;QAET,KAAK,SAAS;YACZ,YAAY,EAAE,CAAC;YACf,OAAO;QAET,KAAK,MAAM;YACT,MAAM,OAAO,EAAE,CAAC;YAChB,OAAO;QAET,KAAK,QAAQ,CAAC;QACd,OAAO,CAAC,CAAC,CAAC;YACR,IAAI,IAAI,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;gBAC9B,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC;oBACnC,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,WAAW,EAAE,GAAG,EAAE,CAAC,uBAAuB,EAAE;iBAC7C,CAAC,CAAC;gBACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,cAAc,YAAY,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;gBACjF,MAAM;YACR,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,uBAAuB,EAAE,CAAC;YAC/C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAEhC,IACE,OAAO,CAAC,GAAG,CAAC,8BAA8B,KAAK,GAAG;gBAClD,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,GAAG,EAChC,CAAC;gBACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,kBAAkB,cAAc,iDAAiD,CAClF,CAAC;YACJ,CAAC;YACD,MAAM;QACR,CAAC;IACH,CAAC;AACH,CAAC;AAED,gDAAgD;AAChD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;IACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,OAAO,CAAC,KAAK,CAAC,mBAAmB,WAAW,KAAK,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Filename of the generated OpenContext config template. */
|
|
2
|
+
export declare const CONFIG_FILENAME = ".opencontext.json";
|
|
3
|
+
/** Directory that holds the context topic files. */
|
|
4
|
+
export declare const CONTEXT_DIR_NAME = ".opencontext";
|
|
5
|
+
/** Template written when no .opencontext.json exists yet. */
|
|
6
|
+
export declare const CONFIG_CONTENT = "{\n \"path\": \".opencontext\",\n \"readOnly\": false,\n \"autoIndex\": true,\n \"guard\": {\n \"enabled\": true,\n \"maxFileSizeKb\": 50,\n \"strictPatternCheck\": true\n }\n}\n";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Filename of the generated OpenContext config template. */
|
|
2
|
+
export const CONFIG_FILENAME = ".opencontext.json";
|
|
3
|
+
/** Directory that holds the context topic files. */
|
|
4
|
+
export const CONTEXT_DIR_NAME = ".opencontext";
|
|
5
|
+
/** Template written when no .opencontext.json exists yet. */
|
|
6
|
+
export const CONFIG_CONTENT = `{
|
|
7
|
+
"path": ".opencontext",
|
|
8
|
+
"readOnly": false,
|
|
9
|
+
"autoIndex": true,
|
|
10
|
+
"guard": {
|
|
11
|
+
"enabled": true,
|
|
12
|
+
"maxFileSizeKb": 50,
|
|
13
|
+
"strictPatternCheck": true
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/init/constants.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,MAAM,CAAC,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAEnD,oDAAoD;AACpD,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAE/C,6DAA6D;AAC7D,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;CAU7B,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ConfigStatus } from "../shared/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Prints a step indicator to stderr.
|
|
4
|
+
* @param label - Step label
|
|
5
|
+
* @param done - Whether to show a checkmark (done) or spinner text
|
|
6
|
+
*/
|
|
7
|
+
export declare function printStep(label: string, done?: boolean): void;
|
|
8
|
+
/** Prints a config/generation result line to stderr. */
|
|
9
|
+
export declare function printResult(status: ConfigStatus | "invalid", message: string): void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prints a step indicator to stderr.
|
|
3
|
+
* @param label - Step label
|
|
4
|
+
* @param done - Whether to show a checkmark (done) or spinner text
|
|
5
|
+
*/
|
|
6
|
+
export function printStep(label, done = true) {
|
|
7
|
+
const icon = done ? "\x1b[32m✓\x1b[0m" : "\x1b[36m●\x1b[0m";
|
|
8
|
+
process.stderr.write(` ${icon} ${label}\n`);
|
|
9
|
+
}
|
|
10
|
+
/** Maps a config result to a terminal status icon. */
|
|
11
|
+
function statusIcon(status) {
|
|
12
|
+
switch (status) {
|
|
13
|
+
case "created":
|
|
14
|
+
return "\x1b[32m✓\x1b[0m";
|
|
15
|
+
case "updated":
|
|
16
|
+
return "\x1b[33m~ \x1b[0m";
|
|
17
|
+
case "unchanged":
|
|
18
|
+
return "\x1b[36m✓\x1b[0m";
|
|
19
|
+
case "skipped":
|
|
20
|
+
return "\x1b[90m-\x1b[0m";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** Prints a config/generation result line to stderr. */
|
|
24
|
+
export function printResult(status, message) {
|
|
25
|
+
const icon = status === "invalid" ? "\x1b[31m!\x1b[0m" : statusIcon(status);
|
|
26
|
+
process.stderr.write(` ${icon} ${message}\n`);
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=display.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display.js","sourceRoot":"","sources":["../../src/init/display.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,IAAI,GAAG,IAAI;IAClD,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,kBAAkB,CAAC;IAC5D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED,sDAAsD;AACtD,SAAS,UAAU,CAAC,MAAoB;IACtC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,SAAS;YACZ,OAAO,kBAAkB,CAAC;QAC5B,KAAK,SAAS;YACZ,OAAO,mBAAmB,CAAC;QAC7B,KAAK,WAAW;YACd,OAAO,kBAAkB,CAAC;QAC5B,KAAK,SAAS;YACZ,OAAO,kBAAkB,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,WAAW,CAAC,MAAgC,EAAE,OAAe;IAC3E,MAAM,IAAI,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAC5E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,OAAO,IAAI,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Writes a file atomically using a temp-then-rename pattern.
|
|
3
|
+
* @param filePath - Target file path
|
|
4
|
+
* @param content - File content
|
|
5
|
+
*/
|
|
6
|
+
export declare function atomicWrite(filePath: string, content: string): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Validates an existing .opencontext.json file.
|
|
9
|
+
* Leaves the file content untouched; only reports whether it parses.
|
|
10
|
+
* @returns true when the existing config is parseable JSON
|
|
11
|
+
*/
|
|
12
|
+
export declare function validateConfigFile(filePath: string): Promise<boolean>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { readFile, writeFile, unlink, rename } from "node:fs/promises";
|
|
2
|
+
/**
|
|
3
|
+
* Writes a file atomically using a temp-then-rename pattern.
|
|
4
|
+
* @param filePath - Target file path
|
|
5
|
+
* @param content - File content
|
|
6
|
+
*/
|
|
7
|
+
export async function atomicWrite(filePath, content) {
|
|
8
|
+
const tmpPath = filePath + ".tmp";
|
|
9
|
+
try {
|
|
10
|
+
await writeFile(tmpPath, content, "utf8");
|
|
11
|
+
await rename(tmpPath, filePath);
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
// Clean up temp file on failure
|
|
15
|
+
try {
|
|
16
|
+
await unlink(tmpPath);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// Ignore cleanup errors
|
|
20
|
+
}
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Validates an existing .opencontext.json file.
|
|
26
|
+
* Leaves the file content untouched; only reports whether it parses.
|
|
27
|
+
* @returns true when the existing config is parseable JSON
|
|
28
|
+
*/
|
|
29
|
+
export async function validateConfigFile(filePath) {
|
|
30
|
+
try {
|
|
31
|
+
const raw = await readFile(filePath, "utf8");
|
|
32
|
+
JSON.parse(raw);
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/init/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEvE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB,EAAE,OAAe;IACjE,MAAM,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1C,MAAM,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,gCAAgC;QAChC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;QAAC,MAAM,CAAC;YACP,wBAAwB;QAC1B,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAgB;IACvD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|