kyp-mem 0.2.0 → 0.2.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 +20 -26
- package/bin/cli.mjs +53 -18
- package/bin/install.mjs +59 -18
- package/kyp_mem/__init__.py +2 -2
- package/kyp_mem/cli.py +135 -42
- package/kyp_mem/server.py +1 -1
- package/kyp_mem/ui.py +1 -1
- package/package.json +7 -6
- package/pyproject.toml +4 -4
- package/kyp_mem/__pycache__/__init__.cpython-314.pyc +0 -0
- package/kyp_mem/__pycache__/cli.cpython-314.pyc +0 -0
- package/kyp_mem/__pycache__/config.cpython-314.pyc +0 -0
- package/kyp_mem/__pycache__/ui.cpython-314.pyc +0 -0
- package/kyp_mem/__pycache__/vault.cpython-314.pyc +0 -0
package/README.md
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
# KYP-MEM — Know Your Project Memory
|
|
2
2
|
|
|
3
|
-
**Headless
|
|
3
|
+
**Headless knowledge base for AI agents.** Markdown notes with wikilinks, backlinks, tags, related notes, and a neon web UI — all powered by an MCP server so Claude (or any AI) can read and write your project knowledge directly.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
npx -y kyp-mem
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or install the command globally:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g kyp-mem
|
|
9
15
|
```
|
|
10
16
|
|
|
11
17
|
## Setup (3 commands)
|
|
12
18
|
|
|
13
19
|
```bash
|
|
14
20
|
# 1. Choose where your vault (knowledge base) lives
|
|
15
|
-
kyp-mem init
|
|
21
|
+
npx -y kyp-mem init
|
|
16
22
|
|
|
17
23
|
# 2. Connect to Claude Code — auto-configures MCP
|
|
18
|
-
kyp-mem setup-claude
|
|
24
|
+
npx -y kyp-mem setup-claude
|
|
19
25
|
|
|
20
26
|
# 3. Restart Claude Code — done!
|
|
21
27
|
# kyp-mem now runs headlessly every session.
|
|
@@ -27,10 +33,10 @@ That's it. Claude now has `kyp_read`, `kyp_write`, `kyp_search`, and 7 other too
|
|
|
27
33
|
## Optional: Web UI
|
|
28
34
|
|
|
29
35
|
```bash
|
|
30
|
-
kyp-mem ui
|
|
36
|
+
npx -y kyp-mem ui
|
|
31
37
|
```
|
|
32
38
|
|
|
33
|
-
Opens
|
|
39
|
+
Opens a rich interface at `localhost:3333` with:
|
|
34
40
|
- Collapsible folder tree
|
|
35
41
|
- Rendered markdown with syntax highlighting
|
|
36
42
|
- Clickable `[[wikilinks]]`
|
|
@@ -50,7 +56,7 @@ Opens an Obsidian-like interface at `localhost:3333` with:
|
|
|
50
56
|
```
|
|
51
57
|
|
|
52
58
|
- **Headless by default** — runs as an MCP server (stdio), no GUI needed
|
|
53
|
-
- **Markdown files on disk** —
|
|
59
|
+
- **Markdown files on disk** — plain `.md` files with YAML frontmatter, no database
|
|
54
60
|
- **In-memory index** — links, backlinks, tags, search, similarity scoring
|
|
55
61
|
- **Web UI optional** — `kyp-mem ui` when you want to browse visually
|
|
56
62
|
|
|
@@ -59,7 +65,7 @@ Opens an Obsidian-like interface at `localhost:3333` with:
|
|
|
59
65
|
| Command | What it does |
|
|
60
66
|
|---------|-------------|
|
|
61
67
|
| `kyp-mem init` | First-time setup — choose vault location |
|
|
62
|
-
| `kyp-mem setup-claude` |
|
|
68
|
+
| `kyp-mem setup-claude` | Register the MCP server with Claude Code for this project |
|
|
63
69
|
| `kyp-mem setup-claude --global` | Configure globally (all projects) |
|
|
64
70
|
| `kyp-mem serve` | Start MCP server (used by Claude, not you) |
|
|
65
71
|
| `kyp-mem ui` | Open web UI at localhost:3333 |
|
|
@@ -83,7 +89,7 @@ Opens an Obsidian-like interface at `localhost:3333` with:
|
|
|
83
89
|
|
|
84
90
|
## Note Format
|
|
85
91
|
|
|
86
|
-
Standard markdown with YAML frontmatter
|
|
92
|
+
Standard markdown with YAML frontmatter:
|
|
87
93
|
|
|
88
94
|
```markdown
|
|
89
95
|
---
|
|
@@ -104,21 +110,11 @@ Settings are defined in `HedgeConfig`. See [[Risk Management]] for safety checks
|
|
|
104
110
|
|
|
105
111
|
If you prefer to configure manually instead of using `setup-claude`:
|
|
106
112
|
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
"mcpServers": {
|
|
110
|
-
"kyp-mem": {
|
|
111
|
-
"command": "kyp-mem",
|
|
112
|
-
"args": ["serve"],
|
|
113
|
-
"env": {
|
|
114
|
-
"KYP_VAULT": "~/.kyp-mem/vault"
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
113
|
+
```bash
|
|
114
|
+
claude mcp add -s local -e KYP_VAULT="$HOME/.kyp-mem/vault" kyp-mem -- npx -y kyp-mem serve
|
|
119
115
|
```
|
|
120
116
|
|
|
121
|
-
|
|
117
|
+
Use `-s user` instead of `-s local` to make it available in all projects.
|
|
122
118
|
|
|
123
119
|
## Architecture
|
|
124
120
|
|
|
@@ -134,12 +130,10 @@ Add to `~/.claude/settings.json` (global) or `.claude/settings.json` (per-projec
|
|
|
134
130
|
└── ...
|
|
135
131
|
```
|
|
136
132
|
|
|
137
|
-
## Publishing to
|
|
133
|
+
## Publishing to npm
|
|
138
134
|
|
|
139
135
|
```bash
|
|
140
|
-
|
|
141
|
-
python3 -m build
|
|
142
|
-
twine upload dist/*
|
|
136
|
+
npm publish
|
|
143
137
|
```
|
|
144
138
|
|
|
145
139
|
## License
|
package/bin/cli.mjs
CHANGED
|
@@ -1,33 +1,68 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { spawnSync } from "child_process";
|
|
4
|
+
import { delimiter, dirname, resolve } from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
4
6
|
|
|
5
7
|
const args = process.argv.slice(2);
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const root = resolve(__dirname, "..");
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const env = {
|
|
12
|
+
...process.env,
|
|
13
|
+
PYTHONPATH: process.env.PYTHONPATH
|
|
14
|
+
? `${root}${delimiter}${process.env.PYTHONPATH}`
|
|
15
|
+
: root,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
function run(command, cmdArgs, stdio = "ignore") {
|
|
19
|
+
return spawnSync(command, cmdArgs, { stdio, env });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function pythonCandidates() {
|
|
23
|
+
if (process.env.KYP_MEM_PYTHON) {
|
|
24
|
+
return [[process.env.KYP_MEM_PYTHON, []]];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const candidates = [
|
|
28
|
+
["python3", []],
|
|
29
|
+
["python", []],
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
if (process.platform === "win32") {
|
|
33
|
+
candidates.unshift(["py", ["-3"]]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return candidates;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function findPython() {
|
|
40
|
+
for (const [command, prefixArgs] of pythonCandidates()) {
|
|
41
|
+
const result = run(command, [...prefixArgs, "--version"]);
|
|
42
|
+
if (result.status === 0) {
|
|
43
|
+
return [command, prefixArgs];
|
|
44
|
+
}
|
|
13
45
|
}
|
|
46
|
+
|
|
47
|
+
return null;
|
|
14
48
|
}
|
|
15
49
|
|
|
16
|
-
|
|
17
|
-
if (tryRun("kyp-mem", args)) process.exit(0);
|
|
50
|
+
const python = findPython();
|
|
18
51
|
|
|
19
|
-
|
|
20
|
-
|
|
52
|
+
if (python) {
|
|
53
|
+
const [command, prefixArgs] = python;
|
|
54
|
+
const result = run(command, [...prefixArgs, "-m", "kyp_mem.cli", ...args], "inherit");
|
|
21
55
|
|
|
22
|
-
|
|
23
|
-
|
|
56
|
+
if (result.signal) {
|
|
57
|
+
process.kill(process.pid, result.signal);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
process.exit(result.status ?? 1);
|
|
61
|
+
}
|
|
24
62
|
|
|
25
63
|
console.error("");
|
|
26
|
-
console.error(" \x1b[31mError:\x1b[0m
|
|
64
|
+
console.error(" \x1b[31mError:\x1b[0m Python 3 was not found.");
|
|
27
65
|
console.error("");
|
|
28
|
-
console.error(" Install
|
|
29
|
-
console.error(" \x1b[33mpip install kyp-mem\x1b[0m");
|
|
30
|
-
console.error(" Or from source:");
|
|
31
|
-
console.error(" \x1b[33mpip install git+https://github.com/Adhithya-Karthikeyan/KYP-MEM.git\x1b[0m");
|
|
66
|
+
console.error(" Install Python 3.10+ and rerun this command.");
|
|
32
67
|
console.error("");
|
|
33
68
|
process.exit(1);
|
package/bin/install.mjs
CHANGED
|
@@ -1,36 +1,77 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { spawnSync } from "child_process";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
5
|
import { dirname, resolve } from "path";
|
|
6
6
|
|
|
7
7
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
8
|
const root = resolve(__dirname, "..");
|
|
9
9
|
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
function run(command, args, options = {}) {
|
|
11
|
+
return spawnSync(command, args, {
|
|
12
|
+
cwd: root,
|
|
13
|
+
stdio: options.stdio ?? "ignore",
|
|
14
|
+
env: {
|
|
15
|
+
...process.env,
|
|
16
|
+
PIP_DISABLE_PIP_VERSION_CHECK: "1",
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function pythonCandidates() {
|
|
22
|
+
if (process.env.KYP_MEM_PYTHON) {
|
|
23
|
+
return [[process.env.KYP_MEM_PYTHON, []]];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const candidates = [
|
|
27
|
+
["python3", []],
|
|
28
|
+
["python", []],
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
if (process.platform === "win32") {
|
|
32
|
+
candidates.unshift(["py", ["-3"]]);
|
|
16
33
|
}
|
|
34
|
+
|
|
35
|
+
return candidates;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function findPython() {
|
|
39
|
+
for (const [command, prefixArgs] of pythonCandidates()) {
|
|
40
|
+
const result = run(command, [...prefixArgs, "--version"]);
|
|
41
|
+
if (result.status === 0) {
|
|
42
|
+
return [command, prefixArgs];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return null;
|
|
17
47
|
}
|
|
18
48
|
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
execSync("kyp-mem --help", { stdio: "pipe" });
|
|
49
|
+
if (process.env.KYP_MEM_SKIP_PYTHON_INSTALL === "1") {
|
|
22
50
|
process.exit(0);
|
|
23
|
-
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const python = findPython();
|
|
54
|
+
|
|
55
|
+
if (!python) {
|
|
56
|
+
console.log(" \x1b[33m!\x1b[0m Python 3 was not found.");
|
|
57
|
+
console.log(" \x1b[33m!\x1b[0m Install Python 3.10+ and run: python3 -m pip install --user .");
|
|
58
|
+
process.exit(0);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const [pythonCommand, pythonPrefixArgs] = python;
|
|
24
62
|
|
|
25
63
|
console.log(" Installing kyp-mem Python package...");
|
|
26
64
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
65
|
+
const result = run(
|
|
66
|
+
pythonCommand,
|
|
67
|
+
[...pythonPrefixArgs, "-m", "pip", "install", "--user", "."],
|
|
68
|
+
{ stdio: "inherit" },
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if (result.status === 0) {
|
|
32
72
|
console.log(" \x1b[32m✓\x1b[0m kyp-mem installed successfully");
|
|
33
73
|
} else {
|
|
34
|
-
console.log(" \x1b[33m!\x1b[0m Could not auto-install Python package.");
|
|
35
|
-
console.log(
|
|
74
|
+
console.log(" \x1b[33m!\x1b[0m Could not auto-install the Python package.");
|
|
75
|
+
console.log(` \x1b[33m!\x1b[0m Run manually from ${root}:`);
|
|
76
|
+
console.log(" python3 -m pip install --user .");
|
|
36
77
|
}
|
package/kyp_mem/__init__.py
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"""KYP-MEM — Know Your Project Memory. Headless
|
|
1
|
+
"""KYP-MEM — Know Your Project Memory. Headless knowledge base for AI agents."""
|
|
2
2
|
|
|
3
|
-
__version__ = "0.2.
|
|
3
|
+
__version__ = "0.2.1"
|
package/kyp_mem/cli.py
CHANGED
|
@@ -4,6 +4,7 @@ import os
|
|
|
4
4
|
import json
|
|
5
5
|
import shutil
|
|
6
6
|
import argparse
|
|
7
|
+
import subprocess
|
|
7
8
|
from pathlib import Path
|
|
8
9
|
|
|
9
10
|
C = "\033[36m" # cyan
|
|
@@ -16,7 +17,7 @@ R = "\033[0m" # reset
|
|
|
16
17
|
def main():
|
|
17
18
|
parser = argparse.ArgumentParser(
|
|
18
19
|
prog="kyp-mem",
|
|
19
|
-
description="KYP-MEM — Know Your Project Memory. Headless
|
|
20
|
+
description="KYP-MEM — Know Your Project Memory. Headless knowledge base for AI agents.",
|
|
20
21
|
)
|
|
21
22
|
parser.add_argument("--vault", default=None, help="Override vault path")
|
|
22
23
|
|
|
@@ -74,7 +75,7 @@ def _run_init():
|
|
|
74
75
|
print(f"{C} ██║ ██╗ ██║ ██║ ██║ ╚═╝ ██║███████╗██║ ╚═╝ ██║{R}")
|
|
75
76
|
print(f"{C} ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝{R}")
|
|
76
77
|
print()
|
|
77
|
-
print(f" {D}Know Your Project — Headless
|
|
78
|
+
print(f" {D}Know Your Project — Headless knowledge base for AI agents{R}")
|
|
78
79
|
print()
|
|
79
80
|
print(f" {Y}>> First-time setup{R}")
|
|
80
81
|
print()
|
|
@@ -107,20 +108,112 @@ def _run_setup_claude(global_config: bool = False):
|
|
|
107
108
|
from .config import get_vault_path
|
|
108
109
|
|
|
109
110
|
vault_path = get_vault_path()
|
|
111
|
+
mcp_command, mcp_args = _get_mcp_command()
|
|
112
|
+
claude_scope = "user" if global_config else "local"
|
|
113
|
+
scope_label = "global user" if global_config else "local project"
|
|
114
|
+
|
|
115
|
+
registered, detail = _register_with_claude_mcp(
|
|
116
|
+
claude_scope,
|
|
117
|
+
mcp_command,
|
|
118
|
+
mcp_args,
|
|
119
|
+
vault_path,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
print()
|
|
123
|
+
print(f" {C}KYP-MEM{R} — Claude Code Setup")
|
|
124
|
+
print()
|
|
125
|
+
if registered:
|
|
126
|
+
print(f" {G}✓{R} MCP server registered with Claude Code ({scope_label})")
|
|
127
|
+
else:
|
|
128
|
+
settings_path = _write_legacy_claude_settings(global_config, mcp_command, mcp_args, vault_path)
|
|
129
|
+
print(f" {Y}✗{R} Could not register with Claude Code's MCP manager")
|
|
130
|
+
print(f" {D} Reason: {detail}{R}")
|
|
131
|
+
print(f" {Y}!{R} Wrote legacy settings as a fallback")
|
|
132
|
+
print(f" {D} File: {settings_path}{R}")
|
|
133
|
+
print(f" {D} Command: {mcp_command} {' '.join(mcp_args)}{R}")
|
|
134
|
+
print(f" {D} Vault: {vault_path}{R}")
|
|
135
|
+
print()
|
|
136
|
+
print(f" {C}Done!{R} Restart Claude Code and kyp-mem will run automatically.")
|
|
137
|
+
print(f" Claude gets these tools: kyp_list, kyp_read, kyp_write, kyp_delete,")
|
|
138
|
+
print(f" kyp_search, kyp_tags, kyp_related, kyp_recent, kyp_stats")
|
|
139
|
+
print()
|
|
140
|
+
print(f" {D}To open the web UI anytime:{R} {Y}kyp-mem ui{R}")
|
|
141
|
+
print()
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _get_mcp_command() -> tuple[str, list[str]]:
|
|
110
145
|
kyp_mem_bin = shutil.which("kyp-mem")
|
|
146
|
+
npx_bin = shutil.which("npx")
|
|
147
|
+
|
|
148
|
+
if kyp_mem_bin and "_npx" not in Path(kyp_mem_bin).parts:
|
|
149
|
+
return kyp_mem_bin, ["serve"]
|
|
150
|
+
if npx_bin:
|
|
151
|
+
return npx_bin, ["-y", "kyp-mem", "serve"]
|
|
152
|
+
|
|
153
|
+
print(f" {Y}Warning:{R} 'kyp-mem' not found in PATH.")
|
|
154
|
+
print(f" {D}Make sure you installed with: npm install -g kyp-mem{R}")
|
|
155
|
+
print()
|
|
156
|
+
return "kyp-mem", ["serve"]
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _register_with_claude_mcp(
|
|
160
|
+
scope: str,
|
|
161
|
+
mcp_command: str,
|
|
162
|
+
mcp_args: list[str],
|
|
163
|
+
vault_path: str,
|
|
164
|
+
) -> tuple[bool, str]:
|
|
165
|
+
claude_bin = shutil.which("claude")
|
|
166
|
+
if not claude_bin:
|
|
167
|
+
return False, "'claude' CLI not found in PATH"
|
|
168
|
+
|
|
169
|
+
server_config = {
|
|
170
|
+
"type": "stdio",
|
|
171
|
+
"command": mcp_command,
|
|
172
|
+
"args": mcp_args,
|
|
173
|
+
"env": {
|
|
174
|
+
"KYP_VAULT": vault_path,
|
|
175
|
+
},
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
# Make setup idempotent when the user reruns it with a new vault or binary.
|
|
179
|
+
subprocess.run(
|
|
180
|
+
[claude_bin, "mcp", "remove", "-s", scope, "kyp-mem"],
|
|
181
|
+
stdout=subprocess.DEVNULL,
|
|
182
|
+
stderr=subprocess.DEVNULL,
|
|
183
|
+
text=True,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
result = subprocess.run(
|
|
187
|
+
[
|
|
188
|
+
claude_bin,
|
|
189
|
+
"mcp",
|
|
190
|
+
"add-json",
|
|
191
|
+
"-s",
|
|
192
|
+
scope,
|
|
193
|
+
"kyp-mem",
|
|
194
|
+
json.dumps(server_config),
|
|
195
|
+
],
|
|
196
|
+
capture_output=True,
|
|
197
|
+
text=True,
|
|
198
|
+
)
|
|
111
199
|
|
|
112
|
-
if
|
|
113
|
-
|
|
114
|
-
print(f" {D}Make sure you installed with: pip install kyp-mem{R}")
|
|
115
|
-
print()
|
|
116
|
-
kyp_mem_bin = "kyp-mem"
|
|
200
|
+
if result.returncode == 0:
|
|
201
|
+
return True, result.stdout.strip()
|
|
117
202
|
|
|
203
|
+
detail = (result.stderr or result.stdout or "unknown error").strip()
|
|
204
|
+
return False, detail
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def _write_legacy_claude_settings(
|
|
208
|
+
global_config: bool,
|
|
209
|
+
mcp_command: str,
|
|
210
|
+
mcp_args: list[str],
|
|
211
|
+
vault_path: str,
|
|
212
|
+
) -> Path:
|
|
118
213
|
if global_config:
|
|
119
214
|
settings_path = Path.home() / ".claude" / "settings.json"
|
|
120
|
-
scope = "global"
|
|
121
215
|
else:
|
|
122
216
|
settings_path = Path.cwd() / ".claude" / "settings.json"
|
|
123
|
-
scope = "project"
|
|
124
217
|
|
|
125
218
|
settings_path.parent.mkdir(parents=True, exist_ok=True)
|
|
126
219
|
|
|
@@ -132,31 +225,16 @@ def _run_setup_claude(global_config: bool = False):
|
|
|
132
225
|
settings = {}
|
|
133
226
|
|
|
134
227
|
mcp_servers = settings.setdefault("mcpServers", {})
|
|
135
|
-
|
|
136
228
|
mcp_servers["kyp-mem"] = {
|
|
137
|
-
"command":
|
|
138
|
-
"args":
|
|
229
|
+
"command": mcp_command,
|
|
230
|
+
"args": mcp_args,
|
|
139
231
|
"env": {
|
|
140
232
|
"KYP_VAULT": vault_path,
|
|
141
233
|
},
|
|
142
234
|
}
|
|
143
235
|
|
|
144
236
|
settings_path.write_text(json.dumps(settings, indent=2) + "\n")
|
|
145
|
-
|
|
146
|
-
print()
|
|
147
|
-
print(f" {C}KYP-MEM{R} — Claude Code Setup")
|
|
148
|
-
print()
|
|
149
|
-
print(f" {G}✓{R} MCP server added to {scope} settings")
|
|
150
|
-
print(f" {D} File: {settings_path}{R}")
|
|
151
|
-
print(f" {D} Command: {kyp_mem_bin} serve{R}")
|
|
152
|
-
print(f" {D} Vault: {vault_path}{R}")
|
|
153
|
-
print()
|
|
154
|
-
print(f" {C}Done!{R} Restart Claude Code and kyp-mem will run automatically.")
|
|
155
|
-
print(f" Claude gets these tools: kyp_list, kyp_read, kyp_write, kyp_delete,")
|
|
156
|
-
print(f" kyp_search, kyp_tags, kyp_related, kyp_recent, kyp_stats")
|
|
157
|
-
print()
|
|
158
|
-
print(f" {D}To open the web UI anytime:{R} {Y}kyp-mem ui{R}")
|
|
159
|
-
print()
|
|
237
|
+
return settings_path
|
|
160
238
|
|
|
161
239
|
|
|
162
240
|
def _run_stats():
|
|
@@ -204,22 +282,37 @@ def _run_doctor():
|
|
|
204
282
|
else:
|
|
205
283
|
print(f" {Y}✗{R} Vault not found: {vault_path}")
|
|
206
284
|
|
|
207
|
-
# Claude Code
|
|
208
|
-
|
|
285
|
+
# Claude Code MCP registration
|
|
286
|
+
claude_bin = shutil.which("claude")
|
|
287
|
+
if claude_bin:
|
|
288
|
+
result = subprocess.run(
|
|
289
|
+
[claude_bin, "mcp", "get", "kyp-mem"],
|
|
290
|
+
capture_output=True,
|
|
291
|
+
text=True,
|
|
292
|
+
)
|
|
293
|
+
if result.returncode == 0 and "Status: ✓ Connected" in result.stdout:
|
|
294
|
+
print(f" {G}✓{R} Claude Code MCP: kyp-mem connected")
|
|
295
|
+
elif result.returncode == 0:
|
|
296
|
+
print(f" {Y}✗{R} Claude Code MCP: kyp-mem registered but not connected")
|
|
297
|
+
else:
|
|
298
|
+
print(f" {Y}✗{R} Claude Code MCP: kyp-mem not active")
|
|
299
|
+
else:
|
|
300
|
+
print(f" {Y}✗{R} Claude Code CLI not found in PATH")
|
|
301
|
+
|
|
302
|
+
legacy_paths = [
|
|
209
303
|
("project", Path.cwd() / ".claude" / "settings.json"),
|
|
210
304
|
("global", Path.home() / ".claude" / "settings.json"),
|
|
211
|
-
]
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
print(f" {D}·{R} Claude Code ({label}): no settings file")
|
|
305
|
+
]
|
|
306
|
+
for label, path in legacy_paths:
|
|
307
|
+
if not path.exists():
|
|
308
|
+
continue
|
|
309
|
+
try:
|
|
310
|
+
s = json.loads(path.read_text())
|
|
311
|
+
except json.JSONDecodeError:
|
|
312
|
+
print(f" {Y}✗{R} Legacy Claude settings ({label}): invalid JSON")
|
|
313
|
+
continue
|
|
314
|
+
if "kyp-mem" in s.get("mcpServers", {}):
|
|
315
|
+
print(f" {D}·{R} Legacy Claude settings ({label}): kyp-mem entry present")
|
|
223
316
|
|
|
224
317
|
# Binary
|
|
225
318
|
kyp_bin = shutil.which("kyp-mem")
|
|
@@ -243,7 +336,7 @@ def _run_doctor():
|
|
|
243
336
|
def _print_banner():
|
|
244
337
|
print()
|
|
245
338
|
print(f"{C} KYP-MEM{R} — Know Your Project Memory")
|
|
246
|
-
print(f" {D}Headless
|
|
339
|
+
print(f" {D}Headless knowledge base for AI agents{R}")
|
|
247
340
|
print()
|
|
248
341
|
|
|
249
342
|
|
package/kyp_mem/server.py
CHANGED
package/kyp_mem/ui.py
CHANGED
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kyp-mem",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Know Your Project — Headless
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "Know Your Project — Headless knowledge base for AI agents. MCP-powered with wikilinks, backlinks, and neon web UI.",
|
|
5
5
|
"bin": {
|
|
6
|
-
"kyp-mem": "
|
|
6
|
+
"kyp-mem": "bin/cli.mjs"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
9
|
"bin/",
|
|
10
|
-
"kyp_mem
|
|
10
|
+
"kyp_mem/*.py",
|
|
11
|
+
"kyp_mem/static/",
|
|
11
12
|
"pyproject.toml",
|
|
12
13
|
"README.md",
|
|
13
14
|
"LICENSE"
|
|
@@ -17,7 +18,7 @@
|
|
|
17
18
|
},
|
|
18
19
|
"keywords": [
|
|
19
20
|
"knowledge-base",
|
|
20
|
-
"
|
|
21
|
+
"markdown",
|
|
21
22
|
"ai",
|
|
22
23
|
"mcp",
|
|
23
24
|
"claude",
|
|
@@ -29,7 +30,7 @@
|
|
|
29
30
|
"license": "MIT",
|
|
30
31
|
"repository": {
|
|
31
32
|
"type": "git",
|
|
32
|
-
"url": "https://github.com/Adhithya-Karthikeyan/KYP-MEM.git"
|
|
33
|
+
"url": "git+https://github.com/Adhithya-Karthikeyan/KYP-MEM.git"
|
|
33
34
|
},
|
|
34
35
|
"homepage": "https://github.com/Adhithya-Karthikeyan/KYP-MEM"
|
|
35
36
|
}
|
package/pyproject.toml
CHANGED
|
@@ -4,15 +4,15 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "kyp-mem"
|
|
7
|
-
version = "0.2.
|
|
8
|
-
description = "Know Your Project — Headless
|
|
7
|
+
version = "0.2.2"
|
|
8
|
+
description = "Know Your Project — Headless knowledge base for AI agents. MCP-powered with wikilinks, backlinks, and neon web UI."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
11
11
|
requires-python = ">=3.10"
|
|
12
12
|
authors = [
|
|
13
|
-
{name = "KDB AI Agency", email = "
|
|
13
|
+
{name = "KDB AI Agency", email = "skadhithya95@gmail.com"}
|
|
14
14
|
]
|
|
15
|
-
keywords = ["knowledge-base", "
|
|
15
|
+
keywords = ["knowledge-base", "markdown", "ai", "mcp", "notes", "wiki", "second-brain"]
|
|
16
16
|
classifiers = [
|
|
17
17
|
"Development Status :: 3 - Alpha",
|
|
18
18
|
"Intended Audience :: Developers",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|