mcp-kb 0.1.0__py3-none-any.whl
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.
- mcp_kb/__init__.py +1 -0
- mcp_kb/cli/__init__.py +1 -0
- mcp_kb/cli/args.py +153 -0
- mcp_kb/cli/main.py +116 -0
- mcp_kb/cli/reindex.py +90 -0
- mcp_kb/config.py +69 -0
- mcp_kb/data/KNOWLEDBASE_DOC.md +36 -0
- mcp_kb/data/__init__.py +1 -0
- mcp_kb/ingest/__init__.py +1 -0
- mcp_kb/ingest/chroma.py +583 -0
- mcp_kb/knowledge/__init__.py +1 -0
- mcp_kb/knowledge/bootstrap.py +39 -0
- mcp_kb/knowledge/events.py +100 -0
- mcp_kb/knowledge/search.py +178 -0
- mcp_kb/knowledge/store.py +253 -0
- mcp_kb/security/__init__.py +1 -0
- mcp_kb/security/path_validation.py +105 -0
- mcp_kb/server/__init__.py +1 -0
- mcp_kb/server/app.py +201 -0
- mcp_kb/utils/__init__.py +1 -0
- mcp_kb/utils/filesystem.py +83 -0
- mcp_kb-0.1.0.dist-info/METADATA +176 -0
- mcp_kb-0.1.0.dist-info/RECORD +26 -0
- mcp_kb-0.1.0.dist-info/WHEEL +5 -0
- mcp_kb-0.1.0.dist-info/entry_points.txt +3 -0
- mcp_kb-0.1.0.dist-info/top_level.txt +1 -0
mcp_kb/server/app.py
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
"""FastMCP application that exposes knowledge base management tools.
|
2
|
+
|
3
|
+
The module builds a :class:`FastMCP` server configured with the knowledge base
|
4
|
+
operations defined elsewhere in the package. Using FastMCP drastically reduces
|
5
|
+
protocol boilerplate because the framework introspects type hints and
|
6
|
+
Docstrings to generate MCP-compatible tool schemas automatically.
|
7
|
+
"""
|
8
|
+
from __future__ import annotations
|
9
|
+
|
10
|
+
from dataclasses import dataclass
|
11
|
+
from typing import Iterable, List
|
12
|
+
|
13
|
+
from mcp.server.fastmcp import FastMCP
|
14
|
+
|
15
|
+
from mcp_kb.config import DOC_FILENAME
|
16
|
+
from mcp_kb.knowledge.events import (
|
17
|
+
KnowledgeBaseListener,
|
18
|
+
KnowledgeBaseSearchListener,
|
19
|
+
)
|
20
|
+
from mcp_kb.knowledge.search import build_tree_overview, read_documentation, search_text
|
21
|
+
from mcp_kb.knowledge.store import FileSegment, KnowledgeBase
|
22
|
+
from mcp_kb.security.path_validation import PathRules, PathValidationError
|
23
|
+
|
24
|
+
|
25
|
+
@dataclass
|
26
|
+
class ReadFileResult:
|
27
|
+
"""Structured output for the ``kb.read_file`` tool."""
|
28
|
+
|
29
|
+
path: str
|
30
|
+
start_line: int
|
31
|
+
end_line: int
|
32
|
+
content: str
|
33
|
+
|
34
|
+
|
35
|
+
@dataclass
|
36
|
+
class RegexReplaceResult:
|
37
|
+
"""Structured output describing the number of replacements performed."""
|
38
|
+
|
39
|
+
replacements: int
|
40
|
+
|
41
|
+
|
42
|
+
@dataclass
|
43
|
+
class SearchMatchResult:
|
44
|
+
"""Structured representation of a search result with contextual lines."""
|
45
|
+
|
46
|
+
path: str
|
47
|
+
line: int
|
48
|
+
context: List[str]
|
49
|
+
|
50
|
+
|
51
|
+
def create_fastmcp_app(
|
52
|
+
rules: PathRules,
|
53
|
+
*,
|
54
|
+
host: str | None = None,
|
55
|
+
port: int | None = None,
|
56
|
+
listeners: Iterable[KnowledgeBaseListener] | None = None,
|
57
|
+
) -> FastMCP:
|
58
|
+
"""Build and return a configured :class:`FastMCP` server instance.
|
59
|
+
|
60
|
+
Parameters
|
61
|
+
----------
|
62
|
+
rules:
|
63
|
+
Sanitised filesystem rules that restrict all knowledge base operations to
|
64
|
+
a designated root.
|
65
|
+
host:
|
66
|
+
Optional host interface for HTTP/SSE transports. ``None`` uses FastMCP's
|
67
|
+
defaults.
|
68
|
+
port:
|
69
|
+
Optional TCP port for HTTP/SSE transports. ``None`` uses FastMCP's defaults.
|
70
|
+
listeners:
|
71
|
+
Optional iterable of :class:`KnowledgeBaseListener` implementations that
|
72
|
+
should receive change notifications. The iterable is passed directly to
|
73
|
+
:class:`~mcp_kb.knowledge.store.KnowledgeBase` so that integrations such
|
74
|
+
as Chroma ingestion can react to file lifecycle events.
|
75
|
+
"""
|
76
|
+
|
77
|
+
kb = KnowledgeBase(rules, listeners=listeners)
|
78
|
+
search_providers: List[KnowledgeBaseSearchListener] = []
|
79
|
+
if listeners is not None:
|
80
|
+
for listener in listeners:
|
81
|
+
if isinstance(listener, KnowledgeBaseSearchListener):
|
82
|
+
search_providers.append(listener)
|
83
|
+
fastmcp_kwargs: dict[str, object] = {}
|
84
|
+
if host is not None:
|
85
|
+
fastmcp_kwargs["host"] = host
|
86
|
+
if port is not None:
|
87
|
+
fastmcp_kwargs["port"] = port
|
88
|
+
|
89
|
+
mcp = FastMCP(
|
90
|
+
"mcp-knowledge-base",
|
91
|
+
instructions=(
|
92
|
+
"You are connected to a local markdown knowledge base. Use the provided "
|
93
|
+
"tools to create, inspect, and organize content while respecting the "
|
94
|
+
"soft deletion semantics and the protected documentation folder."
|
95
|
+
),
|
96
|
+
**fastmcp_kwargs,
|
97
|
+
)
|
98
|
+
|
99
|
+
@mcp.tool(name="create_file", title="Create File")
|
100
|
+
def create_file(path: str, content: str) -> str:
|
101
|
+
"""Create or overwrite a markdown file at ``path`` with ``content``."""
|
102
|
+
|
103
|
+
try:
|
104
|
+
created = kb.create_file(path, content)
|
105
|
+
except PathValidationError as exc:
|
106
|
+
raise ValueError(str(exc)) from exc
|
107
|
+
return f"Created {created}"
|
108
|
+
|
109
|
+
@mcp.tool(name="read_file", title="Read File", structured_output=True)
|
110
|
+
def read_file(path: str, start_line: int | None = None, end_line: int | None = None) -> ReadFileResult:
|
111
|
+
"""Read a markdown file returning metadata about the extracted segment."""
|
112
|
+
|
113
|
+
try:
|
114
|
+
segment: FileSegment = kb.read_file(path, start_line=start_line, end_line=end_line)
|
115
|
+
except PathValidationError as exc:
|
116
|
+
raise ValueError(str(exc)) from exc
|
117
|
+
except FileNotFoundError as exc:
|
118
|
+
raise ValueError(str(exc)) from exc
|
119
|
+
return ReadFileResult(
|
120
|
+
path=str(segment.path),
|
121
|
+
start_line=segment.start_line,
|
122
|
+
end_line=segment.end_line,
|
123
|
+
content=segment.content,
|
124
|
+
)
|
125
|
+
|
126
|
+
@mcp.tool(name="append_file", title="Append File")
|
127
|
+
def append_file(path: str, content: str) -> str:
|
128
|
+
"""Append ``content`` to the file specified by ``path``."""
|
129
|
+
|
130
|
+
try:
|
131
|
+
target = kb.append_file(path, content)
|
132
|
+
except PathValidationError as exc:
|
133
|
+
raise ValueError(str(exc)) from exc
|
134
|
+
return f"Appended to {target}"
|
135
|
+
|
136
|
+
@mcp.tool(name="regex_replace", title="Regex Replace", structured_output=True)
|
137
|
+
def regex_replace(path: str, pattern: str, replacement: str) -> RegexReplaceResult:
|
138
|
+
"""Perform a regex-based replacement across the full file."""
|
139
|
+
|
140
|
+
try:
|
141
|
+
replacements = kb.regex_replace(path, pattern, replacement)
|
142
|
+
except PathValidationError as exc:
|
143
|
+
raise ValueError(str(exc)) from exc
|
144
|
+
return RegexReplaceResult(replacements=replacements)
|
145
|
+
|
146
|
+
@mcp.tool(name="delete", title="Soft Delete")
|
147
|
+
def delete(path: str) -> str:
|
148
|
+
"""Soft delete the file at ``path`` by appending the configured sentinel."""
|
149
|
+
|
150
|
+
try:
|
151
|
+
deleted = kb.soft_delete(path)
|
152
|
+
except PathValidationError as exc:
|
153
|
+
raise ValueError(str(exc)) from exc
|
154
|
+
except FileNotFoundError as exc:
|
155
|
+
raise ValueError(str(exc)) from exc
|
156
|
+
return f"Marked {deleted.name} as deleted"
|
157
|
+
|
158
|
+
@mcp.tool(name="search", title="Search", structured_output=True)
|
159
|
+
def search(query: str, limit: int = 5) -> List[SearchMatchResult]:
|
160
|
+
"""Search for ``query`` across the knowledge base with semantic ranking.
|
161
|
+
|
162
|
+
Registered listeners that implement the optional search interface are
|
163
|
+
queried first (e.g., the Chroma ingestor). When no listener returns a
|
164
|
+
result the tool falls back to streaming the markdown files directly so
|
165
|
+
callers always receive deterministic text snippets.
|
166
|
+
"""
|
167
|
+
|
168
|
+
if limit <= 0:
|
169
|
+
raise ValueError("limit must be greater than zero")
|
170
|
+
|
171
|
+
matches = search_text(
|
172
|
+
kb,
|
173
|
+
query,
|
174
|
+
providers=search_providers,
|
175
|
+
n_results=limit,
|
176
|
+
)
|
177
|
+
return [
|
178
|
+
SearchMatchResult(
|
179
|
+
path=str(match.path),
|
180
|
+
line=match.line_number,
|
181
|
+
context=match.context,
|
182
|
+
)
|
183
|
+
for match in matches
|
184
|
+
]
|
185
|
+
|
186
|
+
@mcp.tool(name="overview", title="Overview")
|
187
|
+
def overview() -> str:
|
188
|
+
"""Return a textual tree describing the knowledge base structure."""
|
189
|
+
|
190
|
+
return build_tree_overview(kb)
|
191
|
+
|
192
|
+
@mcp.tool(name="documentation", title="Documentation")
|
193
|
+
def documentation() -> str:
|
194
|
+
"""Read the knowledge base documentation if ``%s`` exists.""" % DOC_FILENAME
|
195
|
+
|
196
|
+
text = read_documentation(kb)
|
197
|
+
if not text:
|
198
|
+
return "Documentation is not available."
|
199
|
+
return text
|
200
|
+
|
201
|
+
return mcp
|
mcp_kb/utils/__init__.py
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
"""Utility helpers shared across the knowledge base server modules."""
|
@@ -0,0 +1,83 @@
|
|
1
|
+
"""Filesystem helpers wrapping Python's standard library primitives.
|
2
|
+
|
3
|
+
The knowledge base server performs numerous file operations. Consolidating the
|
4
|
+
logic in this module keeps the rest of the code focused on business semantics
|
5
|
+
such as validating incoming requests and shaping responses. Each helper function
|
6
|
+
is intentionally small so that callers can compose them for different workflows
|
7
|
+
without duplicating the low-level boilerplate.
|
8
|
+
"""
|
9
|
+
from __future__ import annotations
|
10
|
+
|
11
|
+
from contextlib import contextmanager
|
12
|
+
from pathlib import Path
|
13
|
+
from threading import Lock
|
14
|
+
from typing import Dict, Iterator
|
15
|
+
|
16
|
+
|
17
|
+
class FileLockRegistry:
|
18
|
+
"""In-memory lock registry to serialize write operations per file.
|
19
|
+
|
20
|
+
Using per-path locks prevents concurrent writes from interleaving content
|
21
|
+
and potentially corrupting files. The registry lazily creates locks when a
|
22
|
+
path is first encountered. We reuse locks for subsequent operations to avoid
|
23
|
+
unbounded memory usage.
|
24
|
+
"""
|
25
|
+
|
26
|
+
def __init__(self) -> None:
|
27
|
+
"""Initialize the registry with an empty dictionary."""
|
28
|
+
|
29
|
+
self._locks: Dict[Path, Lock] = {}
|
30
|
+
self._global_lock = Lock()
|
31
|
+
|
32
|
+
@contextmanager
|
33
|
+
def acquire(self, path: Path) -> Iterator[None]:
|
34
|
+
"""Context manager that acquires a lock for the supplied path.
|
35
|
+
|
36
|
+
The helper nests two locks: a global mutex to retrieve or create the
|
37
|
+
per-path lock, and the per-path lock itself for the duration of the
|
38
|
+
caller's critical section.
|
39
|
+
|
40
|
+
Parameters
|
41
|
+
----------
|
42
|
+
path:
|
43
|
+
Absolute path indicating which file should be protected.
|
44
|
+
"""
|
45
|
+
|
46
|
+
with self._global_lock:
|
47
|
+
lock = self._locks.setdefault(path, Lock())
|
48
|
+
lock.acquire()
|
49
|
+
try:
|
50
|
+
yield
|
51
|
+
finally:
|
52
|
+
lock.release()
|
53
|
+
|
54
|
+
|
55
|
+
def write_text(path: Path, content: str) -> None:
|
56
|
+
"""Write text content to ``path`` using UTF-8 encoding."""
|
57
|
+
|
58
|
+
path.write_text(content, encoding="utf-8")
|
59
|
+
|
60
|
+
|
61
|
+
def append_text(path: Path, content: str) -> None:
|
62
|
+
"""Append text content to ``path`` using UTF-8 encoding."""
|
63
|
+
|
64
|
+
with path.open("a", encoding="utf-8") as handle:
|
65
|
+
handle.write(content)
|
66
|
+
|
67
|
+
|
68
|
+
def read_text(path: Path) -> str:
|
69
|
+
"""Read UTF-8 text content from ``path`` and return it."""
|
70
|
+
|
71
|
+
return path.read_text(encoding="utf-8")
|
72
|
+
|
73
|
+
|
74
|
+
def ensure_parent_directory(path: Path) -> None:
|
75
|
+
"""Ensure the parent directory of ``path`` exists by creating it."""
|
76
|
+
|
77
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
78
|
+
|
79
|
+
|
80
|
+
def rename(path: Path, target: Path) -> None:
|
81
|
+
"""Rename ``path`` to ``target`` using ``Path.rename`` semantics."""
|
82
|
+
|
83
|
+
path.rename(target)
|
@@ -0,0 +1,176 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: mcp-kb
|
3
|
+
Version: 0.1.0
|
4
|
+
Summary: MCP server exposing a local markdown knowledge base
|
5
|
+
Author: LLM Maintainer
|
6
|
+
Requires-Python: >=3.11
|
7
|
+
Description-Content-Type: text/markdown
|
8
|
+
Requires-Dist: chromadb>=1.1.0
|
9
|
+
Requires-Dist: httpx>=0.28.1
|
10
|
+
Requires-Dist: mcp[cli]>=1.15.0
|
11
|
+
Provides-Extra: vector
|
12
|
+
Requires-Dist: tiktoken>=0.11.0; extra == "vector"
|
13
|
+
Requires-Dist: langchain-text-splitters>=0.3.11; extra == "vector"
|
14
|
+
|
15
|
+
# MCP Knowledge Base Server
|
16
|
+
|
17
|
+
This project implements a Model Context Protocol (MCP) server that manages a local markdown knowledge base. It provides tools for creating, reading, updating, searching, and organizing documents stored beneath a configurable root directory. The server uses `FastMCP` for transport and schema generation, so the Python tool functions double as the canonical source of truth for MCP metadata.
|
18
|
+
|
19
|
+
## Running the server
|
20
|
+
|
21
|
+
```bash
|
22
|
+
uv run mcp-kb-server --root /path/to/knowledgebase
|
23
|
+
```
|
24
|
+
|
25
|
+
To expose multiple transports, pass `--transport` flags (supported values: `stdio`,
|
26
|
+
`sse`, `http`):
|
27
|
+
|
28
|
+
```bash
|
29
|
+
uv run mcp-kb-server --transport stdio --transport http
|
30
|
+
```
|
31
|
+
|
32
|
+
Use `--host` and `--port` to bind HTTP/SSE transports to specific interfaces:
|
33
|
+
|
34
|
+
```bash
|
35
|
+
uv run mcp-kb-server --transport http --host 0.0.0.0 --port 9000
|
36
|
+
```
|
37
|
+
|
38
|
+
On first launch the server copies a bundled `KNOWLEDBASE_DOC.md` into the
|
39
|
+
`.docs/` directory if it is missing so that every deployment starts with a
|
40
|
+
baseline usage guide.
|
41
|
+
|
42
|
+
## Optional ChromaDB Mirroring
|
43
|
+
|
44
|
+
The CLI can mirror knowledge base changes into a Chroma collection without
|
45
|
+
exposing raw Chroma operations as MCP tools. Mirroring is enabled by default via
|
46
|
+
the `persistent` client, which stores data under `<root>/chroma`. Choose a
|
47
|
+
different backend with `--chroma-client` (choices: `ephemeral`, `persistent`,
|
48
|
+
`http`, `cloud`). Example:
|
49
|
+
|
50
|
+
```bash
|
51
|
+
uv run mcp-kb-server \
|
52
|
+
--root /path/to/knowledgebase \
|
53
|
+
--chroma-client ephemeral \
|
54
|
+
--chroma-collection local-kb \
|
55
|
+
--chroma-embedding default
|
56
|
+
```
|
57
|
+
|
58
|
+
Persistent and remote clients accept additional flags:
|
59
|
+
|
60
|
+
- `--chroma-data-dir`: storage directory for the persistent client (defaults to
|
61
|
+
`<root>/chroma` when not supplied).
|
62
|
+
- `--chroma-host`, `--chroma-port`, `--chroma-ssl`, `--chroma-custom-auth`:
|
63
|
+
options for a self-hosted HTTP server.
|
64
|
+
- `--chroma-tenant`, `--chroma-database`, `--chroma-api-key`: credentials for
|
65
|
+
Chroma Cloud deployments.
|
66
|
+
- `--chroma-id-prefix`: custom document ID prefix (`kb::` by default).
|
67
|
+
|
68
|
+
Every flag has a matching environment variable (`MCP_KB_CHROMA_*`), so the
|
69
|
+
following snippet enables an HTTP client without modifying CLI commands:
|
70
|
+
|
71
|
+
```bash
|
72
|
+
export MCP_KB_CHROMA_CLIENT=http
|
73
|
+
export MCP_KB_CHROMA_HOST=chroma.internal
|
74
|
+
export MCP_KB_CHROMA_PORT=8001
|
75
|
+
export MCP_KB_CHROMA_CUSTOM_AUTH="username:password"
|
76
|
+
uv run mcp-kb-server --transport http
|
77
|
+
```
|
78
|
+
|
79
|
+
When enabled, any file creation, update, or soft deletion is synchronously
|
80
|
+
propagated to the configured Chroma collection, ensuring semantic search stays
|
81
|
+
in lockstep with the markdown knowledge base.
|
82
|
+
|
83
|
+
The `kb.search` MCP tool automatically queries Chroma when mirroring is active,
|
84
|
+
falling back to direct filesystem scans if the semantic index returns no hits.
|
85
|
+
|
86
|
+
## Reindexing
|
87
|
+
|
88
|
+
Use the standalone CLI to rebuild external indexes (e.g., Chroma) from the
|
89
|
+
current knowledge base. This command is not exposed as an MCP tool.
|
90
|
+
|
91
|
+
```bash
|
92
|
+
uv run mcp-kb-reindex --root /path/to/knowledgebase \
|
93
|
+
--chroma-client persistent \
|
94
|
+
--chroma-data-dir /path/to/chroma \
|
95
|
+
--chroma-collection knowledge-base \
|
96
|
+
--chroma-embedding default
|
97
|
+
```
|
98
|
+
|
99
|
+
- Honors the same `--chroma-*` flags and `MCP_KB_CHROMA_*` environment
|
100
|
+
variables as the server.
|
101
|
+
- Processes all non-deleted `*.md` files under the root and prints a summary:
|
102
|
+
`Reindexed N documents`.
|
103
|
+
|
104
|
+
## Testing
|
105
|
+
|
106
|
+
```bash
|
107
|
+
uv run pytest
|
108
|
+
```
|
109
|
+
|
110
|
+
## LLM Client Configuration
|
111
|
+
|
112
|
+
Below are sample configurations for popular MCP-capable LLM clients. All
|
113
|
+
examples assume this repository is cloned locally and that `uv` is installed.
|
114
|
+
|
115
|
+
### Claude Desktop
|
116
|
+
|
117
|
+
Add the following block to your Claude Desktop `claude_desktop_config.json`:
|
118
|
+
|
119
|
+
```json
|
120
|
+
{
|
121
|
+
"mcpServers": {
|
122
|
+
"local-kb": {
|
123
|
+
"server-name": "kb-server",
|
124
|
+
"command": "uv",
|
125
|
+
"args": [
|
126
|
+
"run",
|
127
|
+
"mcp-kb-server",
|
128
|
+
"--root",
|
129
|
+
"/absolute/path/to/.knowledgebase"
|
130
|
+
]
|
131
|
+
}
|
132
|
+
}
|
133
|
+
}
|
134
|
+
```
|
135
|
+
|
136
|
+
### Cursor AI
|
137
|
+
|
138
|
+
In Cursor's `cursor-settings.json`, register the server as a custom tool:
|
139
|
+
|
140
|
+
```json
|
141
|
+
{
|
142
|
+
"mcpServers": {
|
143
|
+
"local_knowledge_base": {
|
144
|
+
"id": "local-kb",
|
145
|
+
"title": "Local Knowledge Base",
|
146
|
+
"command": "uvx",
|
147
|
+
"args": [
|
148
|
+
" --from",
|
149
|
+
"~/cursor_projects/local_knowledge_base",
|
150
|
+
"mcp-kb-server"
|
151
|
+
]
|
152
|
+
}
|
153
|
+
}
|
154
|
+
}
|
155
|
+
```
|
156
|
+
|
157
|
+
### VS Code (Claude MCP Extension)
|
158
|
+
|
159
|
+
For the `Claude MCP` extension, add an entry to `settings.json`:
|
160
|
+
|
161
|
+
```json
|
162
|
+
{
|
163
|
+
"claudeMcp.servers": {
|
164
|
+
"local-kb": {
|
165
|
+
"command": "uv",
|
166
|
+
"args": ["run", "mcp-kb-server"],
|
167
|
+
"env": {
|
168
|
+
"MCP_KB_ROOT": "/absolute/path/to/.knowledgebase"
|
169
|
+
}
|
170
|
+
}
|
171
|
+
}
|
172
|
+
}
|
173
|
+
```
|
174
|
+
|
175
|
+
Adjust the `--root` flag or `MCP_KB_ROOT` environment variable to point at the
|
176
|
+
desired knowledge base directory for each client.
|
@@ -0,0 +1,26 @@
|
|
1
|
+
mcp_kb/__init__.py,sha256=Ry7qODhfFQF6u6p2m3bwGWhB0-BdWTQcHDJB7NBYAio,74
|
2
|
+
mcp_kb/config.py,sha256=snbGzbeUf-YXah_F4h2IzHzL_wII966Pf3LZWLKZ-uU,2506
|
3
|
+
mcp_kb/cli/__init__.py,sha256=dEIRWFycAfPkha1S1Bj_Y6zkvEZv4eF0qtbF9t74r60,67
|
4
|
+
mcp_kb/cli/args.py,sha256=0yU5lwjjUkgk91ksocqOdpqO_u5JU6xuCaayiOJ-5pQ,5371
|
5
|
+
mcp_kb/cli/main.py,sha256=07pxHS4FRfhNO4EXWe_9psF7PV6axrY92U7kpZZHkA0,3864
|
6
|
+
mcp_kb/cli/reindex.py,sha256=WxGCTX35ngXO2AjCXSP4TAUJDGcbCzEOIVl6NIFwVu8,2963
|
7
|
+
mcp_kb/data/KNOWLEDBASE_DOC.md,sha256=jrjNdkXNZUIOBZYy9X9ZnRcRWoARJwCKh2pmpiI0oNw,1639
|
8
|
+
mcp_kb/data/__init__.py,sha256=UYYuO_n2ikjpwkPSykgleiifYvC0V8_O-atUaRBQUm4,70
|
9
|
+
mcp_kb/ingest/__init__.py,sha256=8obrvfa8nLNLYPbi1MHlFUqfoFHgK9YfdryPzAXQ6kU,77
|
10
|
+
mcp_kb/ingest/chroma.py,sha256=P3IrPZW3SK3HVayTzyR3KNe_e8aPGiLDfpZswaLmMbE,21849
|
11
|
+
mcp_kb/knowledge/__init__.py,sha256=W_dtRbtnQlrDJ_425vWR8BcoZGJ8gC5-wg1De1E654s,76
|
12
|
+
mcp_kb/knowledge/bootstrap.py,sha256=DitA1x7i4ZMb9IZyWyw1oPh78iHz9VkHe03sBF9042U,1202
|
13
|
+
mcp_kb/knowledge/events.py,sha256=A7CfD7U5bxo6mCCIic83yE7VPixAN05ssw_HKRF2zxw,3549
|
14
|
+
mcp_kb/knowledge/search.py,sha256=_hfN89GPoJn-Y1TEEfnYawkgOGxOn_3-f7-lzdAqbMA,5901
|
15
|
+
mcp_kb/knowledge/store.py,sha256=JP8_vGMzm6HYxg2Y2LUB1fnguIWYokuO1yCRh2pLym4,9598
|
16
|
+
mcp_kb/security/__init__.py,sha256=lF8_XAjzpwhAFresuskXMo0u9v7KFiTJId88wqOAM4Y,62
|
17
|
+
mcp_kb/security/path_validation.py,sha256=lhyL1WUVCb4ypxmJx8drGmR7y_b7nNohz_JFRWJ25MQ,3617
|
18
|
+
mcp_kb/server/__init__.py,sha256=j9TmxW_WLCoibyQvCsDT1MIuUqSL8sRh2h4u0M4eU0c,74
|
19
|
+
mcp_kb/server/app.py,sha256=GnI2z_6C0wwbJd1r-GheQMn1nc4xj71A51_xKLyCUoU,7070
|
20
|
+
mcp_kb/utils/__init__.py,sha256=lKhRsjgnbhye1sSlch1_wsAI3eWKE1M6RVIiNlnsvLI,71
|
21
|
+
mcp_kb/utils/filesystem.py,sha256=Uyo_lHXF35qRxNXsyDkCs6NC0pDqwDt-D6dw0xtYZQE,2632
|
22
|
+
mcp_kb-0.1.0.dist-info/METADATA,sha256=KCfsCIxMSzOzsE7HXtvSmb9d8ouK7ILbab4XNqZjP2Y,5103
|
23
|
+
mcp_kb-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
24
|
+
mcp_kb-0.1.0.dist-info/entry_points.txt,sha256=qwJkR3vV7ZeydfS_IYMiDwLv4BdTkrOf4-5neWj25g0,96
|
25
|
+
mcp_kb-0.1.0.dist-info/top_level.txt,sha256=IBiz3TNE3FF3TwkbCZpC1kkk6ohTwtBQNSPJNV3-qGA,7
|
26
|
+
mcp_kb-0.1.0.dist-info/RECORD,,
|
@@ -0,0 +1 @@
|
|
1
|
+
mcp_kb
|