vector-task-mcp 1.0.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.
- main.py +913 -0
- src/__init__.py +44 -0
- src/embeddings.py +68 -0
- src/models.py +162 -0
- src/security.py +712 -0
- src/task_store.py +1021 -0
- vector_task_mcp-1.0.0.dist-info/METADATA +640 -0
- vector_task_mcp-1.0.0.dist-info/RECORD +12 -0
- vector_task_mcp-1.0.0.dist-info/WHEEL +5 -0
- vector_task_mcp-1.0.0.dist-info/entry_points.txt +2 -0
- vector_task_mcp-1.0.0.dist-info/licenses/LICENSE +21 -0
- vector_task_mcp-1.0.0.dist-info/top_level.txt +2 -0
src/__init__.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Vector Task MCP Server - Core Package
|
|
3
|
+
======================================
|
|
4
|
+
|
|
5
|
+
This package provides vector-based task management capabilities for Claude Desktop
|
|
6
|
+
using sqlite-vec and sentence-transformers.
|
|
7
|
+
|
|
8
|
+
Modules:
|
|
9
|
+
models: Data models and type definitions
|
|
10
|
+
security: Security utilities and validation
|
|
11
|
+
embeddings: Sentence transformer wrapper (requires sentence-transformers)
|
|
12
|
+
task_store: SQLite-vec operations and task storage (requires sqlite-vec)
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
__version__ = "1.0.0"
|
|
16
|
+
__author__ = "Vector Task MCP Server"
|
|
17
|
+
|
|
18
|
+
# Core modules that don't require external dependencies
|
|
19
|
+
from .models import Task, TaskStatus, Priority, TaskStats, Config
|
|
20
|
+
from .security import SecurityError, validate_working_dir, sanitize_input
|
|
21
|
+
|
|
22
|
+
# Optional imports that require external dependencies
|
|
23
|
+
def get_embedding_model(model_name: str):
|
|
24
|
+
"""Get embedding model (requires sentence-transformers)"""
|
|
25
|
+
from .embeddings import get_embedding_model as _get_model
|
|
26
|
+
return _get_model(model_name)
|
|
27
|
+
|
|
28
|
+
def get_task_store(db_path, embedding_model_name=None):
|
|
29
|
+
"""Get task store (requires sqlite-vec)"""
|
|
30
|
+
from .task_store import TaskStore
|
|
31
|
+
return TaskStore(db_path, embedding_model_name)
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
"Task",
|
|
35
|
+
"TaskStatus",
|
|
36
|
+
"Priority",
|
|
37
|
+
"TaskStats",
|
|
38
|
+
"Config",
|
|
39
|
+
"SecurityError",
|
|
40
|
+
"validate_working_dir",
|
|
41
|
+
"sanitize_input",
|
|
42
|
+
"get_embedding_model",
|
|
43
|
+
"get_task_store"
|
|
44
|
+
]
|
src/embeddings.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Embedding Model Module
|
|
3
|
+
======================
|
|
4
|
+
|
|
5
|
+
Provides sentence transformer embedding functionality for semantic task search.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import List, Union
|
|
9
|
+
import numpy as np
|
|
10
|
+
from sentence_transformers import SentenceTransformer
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class EmbeddingModel:
|
|
14
|
+
"""Wrapper for sentence transformer embedding model."""
|
|
15
|
+
|
|
16
|
+
def __init__(self, model_name: str):
|
|
17
|
+
"""
|
|
18
|
+
Initialize embedding model.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
model_name: HuggingFace model name (e.g., 'sentence-transformers/all-MiniLM-L6-v2')
|
|
22
|
+
"""
|
|
23
|
+
self.model_name = model_name
|
|
24
|
+
self.model = SentenceTransformer(model_name)
|
|
25
|
+
|
|
26
|
+
def encode(self, text: Union[str, List[str]]) -> np.ndarray:
|
|
27
|
+
"""
|
|
28
|
+
Encode text to embedding vector(s).
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
text: Single text string or list of texts
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Numpy array of embeddings (1D for single text, 2D for list)
|
|
35
|
+
"""
|
|
36
|
+
embeddings = self.model.encode(text, convert_to_numpy=True)
|
|
37
|
+
|
|
38
|
+
# Ensure float32 for sqlite-vec compatibility
|
|
39
|
+
return embeddings.astype(np.float32)
|
|
40
|
+
|
|
41
|
+
def encode_single(self, text: str) -> np.ndarray:
|
|
42
|
+
"""
|
|
43
|
+
Encode single text to embedding vector.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
text: Single text string
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Numpy array of embedding (1D float32)
|
|
50
|
+
"""
|
|
51
|
+
return self.encode(text)
|
|
52
|
+
|
|
53
|
+
def get_embedding_dim(self) -> int:
|
|
54
|
+
"""Get embedding dimension."""
|
|
55
|
+
return self.model.get_sentence_embedding_dimension()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def get_embedding_model(model_name: str) -> EmbeddingModel:
|
|
59
|
+
"""
|
|
60
|
+
Factory function to get embedding model instance.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
model_name: HuggingFace model name
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
Initialized EmbeddingModel instance
|
|
67
|
+
"""
|
|
68
|
+
return EmbeddingModel(model_name)
|
src/models.py
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Data Models and Type Definitions
|
|
3
|
+
================================
|
|
4
|
+
|
|
5
|
+
Defines the core data structures used throughout the vector task system.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from enum import Enum
|
|
11
|
+
from typing import List, Optional, Dict, Any
|
|
12
|
+
import json
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TaskStatus(Enum):
|
|
16
|
+
"""Task status values for task management"""
|
|
17
|
+
PENDING = "pending"
|
|
18
|
+
IN_PROGRESS = "in_progress"
|
|
19
|
+
COMPLETED = "completed"
|
|
20
|
+
STOPPED = "stopped"
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def list_values(cls) -> List[str]:
|
|
24
|
+
"""Get list of all status values"""
|
|
25
|
+
return [status.value for status in cls]
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def is_valid(cls, value: str) -> bool:
|
|
29
|
+
"""Check if a value is a valid status"""
|
|
30
|
+
return value in cls.list_values()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class Priority(Enum):
|
|
34
|
+
"""Task priority levels for task management"""
|
|
35
|
+
LOW = "low"
|
|
36
|
+
MEDIUM = "medium"
|
|
37
|
+
HIGH = "high"
|
|
38
|
+
CRITICAL = "critical"
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def list_values(cls) -> List[str]:
|
|
42
|
+
"""Get list of all priority values"""
|
|
43
|
+
return [priority.value for priority in cls]
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def is_valid(cls, value: str) -> bool:
|
|
47
|
+
"""Check if a value is a valid priority"""
|
|
48
|
+
return value in cls.list_values()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass
|
|
52
|
+
class Task:
|
|
53
|
+
"""Represents a task entry"""
|
|
54
|
+
id: Optional[int] = None
|
|
55
|
+
parent_id: Optional[int] = None
|
|
56
|
+
status: str = TaskStatus.PENDING.value
|
|
57
|
+
priority: str = Priority.MEDIUM.value
|
|
58
|
+
title: str = ""
|
|
59
|
+
content: str = ""
|
|
60
|
+
comment: Optional[str] = None
|
|
61
|
+
created_at: Optional[datetime] = None
|
|
62
|
+
start_at: Optional[datetime] = None
|
|
63
|
+
finish_at: Optional[datetime] = None
|
|
64
|
+
content_hash: Optional[str] = None
|
|
65
|
+
tags: List[str] = None
|
|
66
|
+
|
|
67
|
+
def __post_init__(self):
|
|
68
|
+
"""Initialize default values"""
|
|
69
|
+
if self.tags is None:
|
|
70
|
+
self.tags = []
|
|
71
|
+
if self.created_at is None:
|
|
72
|
+
self.created_at = datetime.utcnow()
|
|
73
|
+
|
|
74
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
75
|
+
"""Convert to dictionary for JSON serialization"""
|
|
76
|
+
return {
|
|
77
|
+
"id": self.id,
|
|
78
|
+
"parent_id": self.parent_id,
|
|
79
|
+
"status": self.status,
|
|
80
|
+
"priority": self.priority,
|
|
81
|
+
"title": self.title,
|
|
82
|
+
"content": self.content,
|
|
83
|
+
"comment": self.comment,
|
|
84
|
+
"created_at": self.created_at.isoformat() if self.created_at else None,
|
|
85
|
+
"start_at": self.start_at.isoformat() if self.start_at else None,
|
|
86
|
+
"finish_at": self.finish_at.isoformat() if self.finish_at else None,
|
|
87
|
+
"content_hash": self.content_hash,
|
|
88
|
+
"tags": self.tags
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@classmethod
|
|
92
|
+
def from_db_row(cls, row: tuple) -> 'Task':
|
|
93
|
+
"""Create Task from database row"""
|
|
94
|
+
return cls(
|
|
95
|
+
id=row[0],
|
|
96
|
+
parent_id=row[1] if len(row) > 1 else None,
|
|
97
|
+
status=row[2] if len(row) > 2 else TaskStatus.PENDING.value,
|
|
98
|
+
priority=row[3] if len(row) > 3 else Priority.MEDIUM.value,
|
|
99
|
+
title=row[4] if len(row) > 4 else "",
|
|
100
|
+
content=row[5] if len(row) > 5 else "",
|
|
101
|
+
comment=row[6] if len(row) > 6 else None,
|
|
102
|
+
tags=json.loads(row[7]) if len(row) > 7 and row[7] else [],
|
|
103
|
+
created_at=datetime.fromisoformat(row[8]) if len(row) > 8 and row[8] else None,
|
|
104
|
+
start_at=datetime.fromisoformat(row[9]) if len(row) > 9 and row[9] else None,
|
|
105
|
+
finish_at=datetime.fromisoformat(row[10]) if len(row) > 10 and row[10] else None,
|
|
106
|
+
content_hash=row[11] if len(row) > 11 else None
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@dataclass
|
|
111
|
+
class TaskStats:
|
|
112
|
+
"""Task statistics and breakdown by status"""
|
|
113
|
+
total_tasks: int = 0
|
|
114
|
+
by_status: Dict[str, int] = None
|
|
115
|
+
pending_count: int = 0
|
|
116
|
+
in_progress_count: int = 0
|
|
117
|
+
completed_count: int = 0
|
|
118
|
+
stopped_count: int = 0
|
|
119
|
+
with_subtasks: int = 0
|
|
120
|
+
|
|
121
|
+
def __post_init__(self):
|
|
122
|
+
"""Initialize default values"""
|
|
123
|
+
if self.by_status is None:
|
|
124
|
+
self.by_status = {}
|
|
125
|
+
|
|
126
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
127
|
+
"""Convert to dictionary for JSON serialization"""
|
|
128
|
+
return {
|
|
129
|
+
"total_tasks": self.total_tasks,
|
|
130
|
+
"by_status": self.by_status,
|
|
131
|
+
"pending_count": self.pending_count,
|
|
132
|
+
"in_progress_count": self.in_progress_count,
|
|
133
|
+
"completed_count": self.completed_count,
|
|
134
|
+
"stopped_count": self.stopped_count,
|
|
135
|
+
"with_subtasks": self.with_subtasks
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# Configuration constants
|
|
140
|
+
class Config:
|
|
141
|
+
"""Configuration constants"""
|
|
142
|
+
|
|
143
|
+
# Server configuration
|
|
144
|
+
SERVER_NAME = "Vector Task MCP Server"
|
|
145
|
+
SERVER_VERSION = "1.0.0"
|
|
146
|
+
|
|
147
|
+
# Content limits
|
|
148
|
+
MAX_MEMORY_LENGTH = 10000 # Maximum length for content and comments (10K chars)
|
|
149
|
+
MAX_TAG_LENGTH = 50 # Maximum length for single tag
|
|
150
|
+
MAX_TAGS_PER_MEMORY = 10 # Maximum number of tags per task
|
|
151
|
+
|
|
152
|
+
# Search limits
|
|
153
|
+
MAX_MEMORIES_PER_SEARCH = 50 # Maximum results per search/list operation
|
|
154
|
+
|
|
155
|
+
# Bulk operation limits
|
|
156
|
+
MAX_BULK_CREATE = 50 # Maximum tasks per bulk create operation
|
|
157
|
+
MAX_BULK_DELETE = 100 # Maximum task IDs per bulk delete operation
|
|
158
|
+
|
|
159
|
+
# Database configuration
|
|
160
|
+
DB_NAME = "vector_tasks.db"
|
|
161
|
+
EMBEDDING_MODEL = "sentence-transformers/all-MiniLM-L6-v2"
|
|
162
|
+
EMBEDDING_DIM = 384
|