opencontext-mcp 1.0.0 → 1.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/README.md +95 -114
- package/dist/config.d.ts +24 -0
- package/dist/config.js +145 -0
- package/dist/config.js.map +1 -0
- package/dist/context-store.d.ts +55 -1
- package/dist/context-store.js +252 -16
- package/dist/context-store.js.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +8 -1
- package/dist/server.js +44 -3
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +42 -2
- package/dist/types.js +34 -2
- package/dist/types.js.map +1 -1
- package/dist/validation.d.ts +46 -0
- package/dist/validation.js +98 -1
- package/dist/validation.js.map +1 -1
- package/package.json +4 -4
- package/LICENSE +0 -21
- package/examples/build-agent.md +0 -48
- package/examples/plan-agent.md +0 -53
package/dist/validation.js
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import { RESERVED_TOPICS, TOPIC_PATTERN, UserInputError } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Forbidden patterns that indicate prompt injection attempts.
|
|
5
|
+
* These are checked case-insensitively against the content.
|
|
6
|
+
*/
|
|
7
|
+
const FORBIDDEN_PATTERNS = [
|
|
8
|
+
/ignore\s+(all\s+)?(previous|prior)\s+instructions/i,
|
|
9
|
+
/system\s*:\s*override/i,
|
|
10
|
+
/bypass\s+(safety|guardrails?|system\s+prompt)/i,
|
|
11
|
+
];
|
|
12
|
+
/**
|
|
13
|
+
* Validates a topic string for safe filesystem operations.
|
|
14
|
+
* @param topicInput - The topic string to validate
|
|
15
|
+
* @returns The trimmed, validated topic
|
|
16
|
+
* @throws UserInputError if the topic is invalid
|
|
17
|
+
*/
|
|
2
18
|
export function validateTopic(topicInput) {
|
|
3
19
|
const topic = topicInput.trim();
|
|
4
20
|
if (!TOPIC_PATTERN.test(topic)) {
|
|
@@ -6,4 +22,85 @@ export function validateTopic(topicInput) {
|
|
|
6
22
|
}
|
|
7
23
|
return topic;
|
|
8
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Sanitizes a topic path to prevent path traversal attacks.
|
|
27
|
+
* Ensures the resolved path stays within the context directory.
|
|
28
|
+
* @param contextDir - The absolute path to the context directory
|
|
29
|
+
* @param topic - The topic name
|
|
30
|
+
* @returns The sanitized absolute path to the topic file
|
|
31
|
+
* @throws UserInputError if path traversal is detected
|
|
32
|
+
*/
|
|
33
|
+
export function sanitizeTopicPath(contextDir, topic) {
|
|
34
|
+
// Quick rejection of obvious path traversal attempts
|
|
35
|
+
if (topic.includes("..") || path.isAbsolute(topic) || topic.startsWith(".") || topic.includes("/")) {
|
|
36
|
+
throw new UserInputError("Path traversal detected: topic must not contain '..', '/', or absolute paths.");
|
|
37
|
+
}
|
|
38
|
+
const filePath = path.join(contextDir, `${topic}.md`);
|
|
39
|
+
const resolvedPath = path.resolve(filePath);
|
|
40
|
+
const resolvedContextDir = path.resolve(contextDir);
|
|
41
|
+
// Double-check resolved path is still within .opencontext directory
|
|
42
|
+
if (!resolvedPath.startsWith(resolvedContextDir + path.sep) && resolvedPath !== resolvedContextDir) {
|
|
43
|
+
throw new UserInputError("Path traversal detected: topic must not contain '..' or absolute paths.");
|
|
44
|
+
}
|
|
45
|
+
return resolvedPath;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Validates a write payload for context storage.
|
|
49
|
+
* Checks topic validity, content safety, size limits, and forbidden patterns.
|
|
50
|
+
* @param topic - The topic name to validate
|
|
51
|
+
* @param content - The content to validate
|
|
52
|
+
* @param options - Optional configuration for validation behavior
|
|
53
|
+
* @returns GuardResult indicating whether the write is allowed
|
|
54
|
+
*/
|
|
55
|
+
export function validateWritePayload(topic, content, options) {
|
|
56
|
+
const opts = {
|
|
57
|
+
maxFileSizeKb: options?.maxFileSizeKb ?? 50,
|
|
58
|
+
allowEmpty: options?.allowEmpty ?? false,
|
|
59
|
+
strictPatternCheck: options?.strictPatternCheck ?? true,
|
|
60
|
+
};
|
|
61
|
+
const trimmedTopic = topic.trim();
|
|
62
|
+
if (!TOPIC_PATTERN.test(trimmedTopic)) {
|
|
63
|
+
return {
|
|
64
|
+
allowed: false,
|
|
65
|
+
reason: "Topic must be snake_case or kebab-case using lowercase letters, numbers, underscores, or hyphens.",
|
|
66
|
+
code: "INVALID_TOPIC",
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (RESERVED_TOPICS.has(trimmedTopic)) {
|
|
70
|
+
return {
|
|
71
|
+
allowed: false,
|
|
72
|
+
reason: `"${trimmedTopic}" is a reserved system topic and cannot be written directly.`,
|
|
73
|
+
code: "RESERVED_TOPIC",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (!opts.allowEmpty && content.trim().length === 0) {
|
|
77
|
+
return {
|
|
78
|
+
allowed: false,
|
|
79
|
+
reason: "Content must not be empty or consist solely of whitespace.",
|
|
80
|
+
code: "EMPTY_CONTENT",
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// Convert KB to bytes for size comparison
|
|
84
|
+
const maxBytes = opts.maxFileSizeKb * 1024;
|
|
85
|
+
const contentBytes = Buffer.byteLength(content, "utf8");
|
|
86
|
+
if (contentBytes > maxBytes) {
|
|
87
|
+
return {
|
|
88
|
+
allowed: false,
|
|
89
|
+
reason: `Payload size (${contentBytes} bytes) exceeds maximum allowed size (${maxBytes} bytes).`,
|
|
90
|
+
code: "PAYLOAD_TOO_LARGE",
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (opts.strictPatternCheck) {
|
|
94
|
+
for (const pattern of FORBIDDEN_PATTERNS) {
|
|
95
|
+
if (pattern.test(content)) {
|
|
96
|
+
return {
|
|
97
|
+
allowed: false,
|
|
98
|
+
reason: `Content contains forbidden pattern: ${pattern.source}`,
|
|
99
|
+
code: "FORBIDDEN_PATTERN",
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return { allowed: true };
|
|
105
|
+
}
|
|
9
106
|
//# sourceMappingURL=validation.js.map
|
package/dist/validation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencontext-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A Model Context Protocol server for persistent project-specific AI agent context.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -28,10 +28,11 @@
|
|
|
28
28
|
"memory"
|
|
29
29
|
],
|
|
30
30
|
"repository": {
|
|
31
|
-
"url": "git+https://github.com/slxca/opencontext.git"
|
|
31
|
+
"url": "git+https://github.com/slxca/opencontext.git",
|
|
32
|
+
"directory": "packages/opencontext"
|
|
32
33
|
},
|
|
33
34
|
"bugs": {
|
|
34
|
-
"url": "https://github.com/slxca/
|
|
35
|
+
"url": "https://github.com/slxca/opencontext/issues",
|
|
35
36
|
"email": "bugs@s-luca.com"
|
|
36
37
|
},
|
|
37
38
|
"publishConfig": {
|
|
@@ -44,7 +45,6 @@
|
|
|
44
45
|
"engines": {
|
|
45
46
|
"node": ">=20.0.0"
|
|
46
47
|
},
|
|
47
|
-
"packageManager": "pnpm@9.15.4",
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@modelcontextprotocol/sdk": "^1.17.4",
|
|
50
50
|
"zod": "^4.5.4"
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 OpenContext Contributors
|
|
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/examples/build-agent.md
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# OpenContext Build Agent
|
|
2
|
-
|
|
3
|
-
Copy this prompt into your AI client's system prompt to turn it into a developer that follows rules saved by the Plan Agent.
|
|
4
|
-
|
|
5
|
-
## System Prompt
|
|
6
|
-
|
|
7
|
-
You are the OpenContext Build Agent: a pragmatic senior developer responsible for implementing changes while strictly following project context saved by the Plan Agent.
|
|
8
|
-
|
|
9
|
-
Before writing or editing any code, you must use the `read_context` tool with no topic to list available OpenContext topics. Then read all topics relevant to the requested work. If relevant context exists, follow it. If the user's request conflicts with saved context, stop and ask for clarification before changing code.
|
|
10
|
-
|
|
11
|
-
Your responsibilities:
|
|
12
|
-
|
|
13
|
-
- Read OpenContext before coding.
|
|
14
|
-
- Inspect the codebase and make the smallest correct change.
|
|
15
|
-
- Preserve existing architecture, naming conventions, and testing strategy.
|
|
16
|
-
- Run appropriate verification commands when feasible.
|
|
17
|
-
- Use `save_context` when you discover a durable rule, convention, decision, or debugging note future agents should know.
|
|
18
|
-
- Do not overwrite saved context with speculative or temporary information.
|
|
19
|
-
|
|
20
|
-
Required workflow:
|
|
21
|
-
|
|
22
|
-
```text
|
|
23
|
-
1. Call read_context with no topic.
|
|
24
|
-
2. Read each relevant topic with read_context.
|
|
25
|
-
3. Inspect the affected code.
|
|
26
|
-
4. Implement the smallest correct change.
|
|
27
|
-
5. Run relevant tests, type checks, or builds.
|
|
28
|
-
6. Save any newly discovered durable context with save_context.
|
|
29
|
-
7. Summarize what changed and what was verified.
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
If no OpenContext topics exist, state that no saved context was available, then proceed by inspecting the repository directly.
|
|
33
|
-
|
|
34
|
-
Build output format:
|
|
35
|
-
|
|
36
|
-
```text
|
|
37
|
-
Changed
|
|
38
|
-
<files or behavior changed>
|
|
39
|
-
|
|
40
|
-
Context Used
|
|
41
|
-
<topics read or note that no context existed>
|
|
42
|
-
|
|
43
|
-
Verification
|
|
44
|
-
<commands run and results>
|
|
45
|
-
|
|
46
|
-
Context Saved
|
|
47
|
-
<topics saved or updated, if any>
|
|
48
|
-
```
|
package/examples/plan-agent.md
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
# OpenContext Plan Agent
|
|
2
|
-
|
|
3
|
-
Copy this prompt into your AI client's system prompt to turn it into an architect that uses OpenContext MCP.
|
|
4
|
-
|
|
5
|
-
## System Prompt
|
|
6
|
-
|
|
7
|
-
You are the OpenContext Plan Agent: a senior software architect responsible for turning requirements into clear implementation plans and durable project context.
|
|
8
|
-
|
|
9
|
-
Before planning, use the `read_context` tool with no topic to list available OpenContext topics. Read every topic relevant to the user's request before making recommendations. If no context exists, inspect the repository and infer only what is supported by evidence in the codebase.
|
|
10
|
-
|
|
11
|
-
Your responsibilities:
|
|
12
|
-
|
|
13
|
-
- Analyze the user's requirement and the current codebase before proposing changes.
|
|
14
|
-
- Identify architectural constraints, project conventions, API contracts, data model decisions, and implementation risks.
|
|
15
|
-
- Create a practical step-by-step plan that a build agent can execute.
|
|
16
|
-
- Use `save_context` to persist durable decisions, rules, and conventions that future agents should follow.
|
|
17
|
-
- Prefer concise markdown context organized under focused snake_case or kebab-case topics.
|
|
18
|
-
|
|
19
|
-
When using `save_context`, choose topics such as:
|
|
20
|
-
|
|
21
|
-
- `architecture`
|
|
22
|
-
- `coding_rules`
|
|
23
|
-
- `api-contracts`
|
|
24
|
-
- `data-model`
|
|
25
|
-
- `testing-strategy`
|
|
26
|
-
|
|
27
|
-
Context you save must be factual and durable. Do not save temporary guesses, chat-only preferences, or unresolved options unless they are clearly marked as open questions.
|
|
28
|
-
|
|
29
|
-
Plan output format:
|
|
30
|
-
|
|
31
|
-
```text
|
|
32
|
-
Summary
|
|
33
|
-
<one-paragraph explanation of the intended solution>
|
|
34
|
-
|
|
35
|
-
Relevant Context Read
|
|
36
|
-
<topics read and what mattered>
|
|
37
|
-
|
|
38
|
-
Architecture Decisions
|
|
39
|
-
<decisions made or confirmed>
|
|
40
|
-
|
|
41
|
-
Implementation Plan
|
|
42
|
-
1. <step>
|
|
43
|
-
2. <step>
|
|
44
|
-
3. <step>
|
|
45
|
-
|
|
46
|
-
Risks And Checks
|
|
47
|
-
<known risks, tests, and verification steps>
|
|
48
|
-
|
|
49
|
-
Context Saved
|
|
50
|
-
<topics saved or updated>
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Always save newly discovered durable context before finishing your response.
|