cognitive-modules 0.3.0__py3-none-any.whl → 0.5.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.
- cognitive/__init__.py +1 -1
- cognitive/cli.py +371 -14
- cognitive/loader.py +180 -14
- cognitive/mcp_server.py +245 -0
- cognitive/migrate.py +624 -0
- cognitive/registry.py +325 -11
- cognitive/runner.py +409 -80
- cognitive/server.py +294 -0
- cognitive/validator.py +380 -122
- cognitive_modules-0.5.0.dist-info/METADATA +431 -0
- cognitive_modules-0.5.0.dist-info/RECORD +18 -0
- cognitive_modules-0.5.0.dist-info/entry_points.txt +2 -0
- cognitive_modules-0.3.0.dist-info/METADATA +0 -418
- cognitive_modules-0.3.0.dist-info/RECORD +0 -15
- cognitive_modules-0.3.0.dist-info/entry_points.txt +0 -2
- {cognitive_modules-0.3.0.dist-info → cognitive_modules-0.5.0.dist-info}/WHEEL +0 -0
- {cognitive_modules-0.3.0.dist-info → cognitive_modules-0.5.0.dist-info}/licenses/LICENSE +0 -0
- {cognitive_modules-0.3.0.dist-info → cognitive_modules-0.5.0.dist-info}/top_level.txt +0 -0
cognitive/loader.py
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Module Loader - Load cognitive modules in all formats.
|
|
3
3
|
|
|
4
|
-
Format v2 (
|
|
4
|
+
Format v2.2 (latest):
|
|
5
|
+
- module.yaml (machine-readable manifest with tier, overflow, enums, compat)
|
|
6
|
+
- prompt.md (human-readable prompt)
|
|
7
|
+
- schema.json (meta + input + data + error)
|
|
8
|
+
- tests/ (golden tests)
|
|
9
|
+
|
|
10
|
+
Format v2/v2.1 (supported):
|
|
5
11
|
- module.yaml (machine-readable manifest)
|
|
6
12
|
- prompt.md (human-readable prompt)
|
|
7
13
|
- schema.json (input + output + error)
|
|
@@ -21,11 +27,24 @@ Format v0 (old, deprecated):
|
|
|
21
27
|
|
|
22
28
|
import json
|
|
23
29
|
from pathlib import Path
|
|
24
|
-
from typing import Optional
|
|
30
|
+
from typing import Optional, Literal
|
|
25
31
|
|
|
26
32
|
import yaml
|
|
27
33
|
|
|
28
34
|
|
|
35
|
+
# =============================================================================
|
|
36
|
+
# Type Definitions (v2.2)
|
|
37
|
+
# =============================================================================
|
|
38
|
+
|
|
39
|
+
ModuleTier = Literal["exec", "decision", "exploration"]
|
|
40
|
+
SchemaStrictness = Literal["high", "medium", "low"]
|
|
41
|
+
EnumStrategy = Literal["strict", "extensible"]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# =============================================================================
|
|
45
|
+
# Format Detection
|
|
46
|
+
# =============================================================================
|
|
47
|
+
|
|
29
48
|
def detect_format(module_path: Path) -> str:
|
|
30
49
|
"""Detect module format: 'v2', 'v1', or 'v0'."""
|
|
31
50
|
if (module_path / "module.yaml").exists():
|
|
@@ -38,6 +57,22 @@ def detect_format(module_path: Path) -> str:
|
|
|
38
57
|
raise FileNotFoundError(f"No module.yaml, MODULE.md, or module.md found in {module_path}")
|
|
39
58
|
|
|
40
59
|
|
|
60
|
+
def detect_v2_version(manifest: dict) -> str:
|
|
61
|
+
"""Detect v2.x version from manifest content."""
|
|
62
|
+
# v2.2 indicators
|
|
63
|
+
if manifest.get("tier") or manifest.get("overflow") or manifest.get("enums"):
|
|
64
|
+
return "v2.2"
|
|
65
|
+
# v2.1 indicators
|
|
66
|
+
if manifest.get("policies") or manifest.get("failure"):
|
|
67
|
+
return "v2.1"
|
|
68
|
+
# Default v2.0
|
|
69
|
+
return "v2.0"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# =============================================================================
|
|
73
|
+
# Frontmatter Parsing
|
|
74
|
+
# =============================================================================
|
|
75
|
+
|
|
41
76
|
def parse_frontmatter(content: str) -> tuple[dict, str]:
|
|
42
77
|
"""Parse YAML frontmatter from markdown content."""
|
|
43
78
|
if not content.startswith('---'):
|
|
@@ -52,12 +87,19 @@ def parse_frontmatter(content: str) -> tuple[dict, str]:
|
|
|
52
87
|
return frontmatter, body
|
|
53
88
|
|
|
54
89
|
|
|
90
|
+
# =============================================================================
|
|
91
|
+
# v2.2 Loader
|
|
92
|
+
# =============================================================================
|
|
93
|
+
|
|
55
94
|
def load_v2_format(module_path: Path) -> dict:
|
|
56
|
-
"""Load module in v2 format (module.yaml + prompt.md + schema.json)."""
|
|
95
|
+
"""Load module in v2.x format (module.yaml + prompt.md + schema.json)."""
|
|
57
96
|
# Load module.yaml
|
|
58
97
|
with open(module_path / "module.yaml", 'r', encoding='utf-8') as f:
|
|
59
98
|
manifest = yaml.safe_load(f)
|
|
60
99
|
|
|
100
|
+
# Detect version
|
|
101
|
+
version_str = detect_v2_version(manifest)
|
|
102
|
+
|
|
61
103
|
# Load prompt.md
|
|
62
104
|
prompt_path = module_path / "prompt.md"
|
|
63
105
|
if prompt_path.exists():
|
|
@@ -71,13 +113,28 @@ def load_v2_format(module_path: Path) -> dict:
|
|
|
71
113
|
if schema_path.exists():
|
|
72
114
|
with open(schema_path, 'r', encoding='utf-8') as f:
|
|
73
115
|
schema = json.load(f)
|
|
116
|
+
|
|
74
117
|
input_schema = schema.get("input", {})
|
|
75
|
-
|
|
118
|
+
|
|
119
|
+
# Support both "data" (v2.2) and "output" (v2.1) aliases
|
|
120
|
+
compat = manifest.get("compat", {})
|
|
121
|
+
if compat.get("schema_output_alias") == "data" or "data" in schema:
|
|
122
|
+
data_schema = schema.get("data", schema.get("output", {}))
|
|
123
|
+
output_schema = data_schema # Keep for backward compat
|
|
124
|
+
else:
|
|
125
|
+
output_schema = schema.get("output", {})
|
|
126
|
+
data_schema = output_schema
|
|
127
|
+
|
|
76
128
|
error_schema = schema.get("error", {})
|
|
129
|
+
meta_schema = schema.get("meta", {})
|
|
130
|
+
defs = schema.get("$defs", {})
|
|
77
131
|
else:
|
|
78
132
|
input_schema = {}
|
|
79
133
|
output_schema = {}
|
|
134
|
+
data_schema = {}
|
|
80
135
|
error_schema = {}
|
|
136
|
+
meta_schema = {}
|
|
137
|
+
defs = {}
|
|
81
138
|
|
|
82
139
|
# Extract constraints (supports both old and new format)
|
|
83
140
|
constraints_raw = manifest.get("constraints", {})
|
|
@@ -98,42 +155,91 @@ def load_v2_format(module_path: Path) -> dict:
|
|
|
98
155
|
"behavior_equivalence_false_max_confidence": constraints_raw.get("behavior_equivalence_false_max_confidence", 0.7),
|
|
99
156
|
}
|
|
100
157
|
|
|
101
|
-
# Extract
|
|
158
|
+
# Extract v2.1 fields
|
|
102
159
|
policies = manifest.get("policies", {})
|
|
103
|
-
|
|
104
|
-
# Extract tools policy
|
|
105
160
|
tools = manifest.get("tools", {})
|
|
106
|
-
|
|
107
|
-
# Extract output contract
|
|
108
161
|
output_contract = manifest.get("output", {})
|
|
109
|
-
|
|
110
|
-
# Extract failure contract
|
|
111
162
|
failure_contract = manifest.get("failure", {})
|
|
112
|
-
|
|
113
|
-
# Extract runtime requirements
|
|
114
163
|
runtime_requirements = manifest.get("runtime_requirements", {})
|
|
115
164
|
|
|
165
|
+
# Extract v2.2 fields
|
|
166
|
+
tier: Optional[ModuleTier] = manifest.get("tier")
|
|
167
|
+
schema_strictness: SchemaStrictness = manifest.get("schema_strictness", "medium")
|
|
168
|
+
|
|
169
|
+
overflow = manifest.get("overflow", {
|
|
170
|
+
"enabled": False,
|
|
171
|
+
"recoverable": True,
|
|
172
|
+
"max_items": 5,
|
|
173
|
+
"require_suggested_mapping": True
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
enums = manifest.get("enums", {
|
|
177
|
+
"strategy": "extensible" if tier in ("decision", "exploration") else "strict",
|
|
178
|
+
"unknown_tag": "custom"
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
compat = manifest.get("compat", {
|
|
182
|
+
"accepts_v21_payload": True,
|
|
183
|
+
"runtime_auto_wrap": True,
|
|
184
|
+
"schema_output_alias": "data"
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
io_config = manifest.get("io", {})
|
|
188
|
+
tests = manifest.get("tests", [])
|
|
189
|
+
|
|
116
190
|
return {
|
|
191
|
+
# Core identity
|
|
117
192
|
"name": manifest.get("name", module_path.name),
|
|
118
193
|
"version": manifest.get("version", "1.0.0"),
|
|
119
194
|
"responsibility": manifest.get("responsibility", ""),
|
|
120
195
|
"excludes": manifest.get("excludes", []),
|
|
196
|
+
|
|
197
|
+
# Path and format info
|
|
121
198
|
"path": module_path,
|
|
122
199
|
"format": "v2",
|
|
200
|
+
"format_version": version_str,
|
|
201
|
+
|
|
202
|
+
# Raw manifest
|
|
123
203
|
"metadata": manifest,
|
|
204
|
+
|
|
205
|
+
# Schemas
|
|
124
206
|
"input_schema": input_schema,
|
|
125
|
-
"output_schema": output_schema,
|
|
207
|
+
"output_schema": output_schema, # v2.1 compat
|
|
208
|
+
"data_schema": data_schema, # v2.2
|
|
126
209
|
"error_schema": error_schema,
|
|
210
|
+
"meta_schema": meta_schema, # v2.2
|
|
211
|
+
"schema_defs": defs,
|
|
212
|
+
|
|
213
|
+
# Constraints and policies
|
|
127
214
|
"constraints": constraints,
|
|
128
215
|
"policies": policies,
|
|
129
216
|
"tools": tools,
|
|
217
|
+
|
|
218
|
+
# Contracts
|
|
130
219
|
"output_contract": output_contract,
|
|
131
220
|
"failure_contract": failure_contract,
|
|
221
|
+
|
|
222
|
+
# Runtime
|
|
132
223
|
"runtime_requirements": runtime_requirements,
|
|
224
|
+
|
|
225
|
+
# v2.2 specific
|
|
226
|
+
"tier": tier,
|
|
227
|
+
"schema_strictness": schema_strictness,
|
|
228
|
+
"overflow": overflow,
|
|
229
|
+
"enums": enums,
|
|
230
|
+
"compat": compat,
|
|
231
|
+
"io": io_config,
|
|
232
|
+
"tests": tests,
|
|
233
|
+
|
|
234
|
+
# Prompt
|
|
133
235
|
"prompt": prompt,
|
|
134
236
|
}
|
|
135
237
|
|
|
136
238
|
|
|
239
|
+
# =============================================================================
|
|
240
|
+
# v1 Loader (Legacy)
|
|
241
|
+
# =============================================================================
|
|
242
|
+
|
|
137
243
|
def load_v1_format(module_path: Path) -> dict:
|
|
138
244
|
"""Load module in v1 format (MODULE.md + schema.json)."""
|
|
139
245
|
# Load MODULE.md
|
|
@@ -173,14 +279,26 @@ def load_v1_format(module_path: Path) -> dict:
|
|
|
173
279
|
"excludes": metadata.get("excludes", []),
|
|
174
280
|
"path": module_path,
|
|
175
281
|
"format": "v1",
|
|
282
|
+
"format_version": "v1.0",
|
|
176
283
|
"metadata": metadata,
|
|
177
284
|
"input_schema": input_schema,
|
|
178
285
|
"output_schema": output_schema,
|
|
286
|
+
"data_schema": output_schema, # Alias for v2.2 compat
|
|
179
287
|
"constraints": constraints,
|
|
180
288
|
"prompt": prompt,
|
|
289
|
+
# v2.2 defaults for v1 modules
|
|
290
|
+
"tier": None,
|
|
291
|
+
"schema_strictness": "medium",
|
|
292
|
+
"overflow": {"enabled": False},
|
|
293
|
+
"enums": {"strategy": "strict"},
|
|
294
|
+
"compat": {"accepts_v21_payload": True, "runtime_auto_wrap": True},
|
|
181
295
|
}
|
|
182
296
|
|
|
183
297
|
|
|
298
|
+
# =============================================================================
|
|
299
|
+
# v0 Loader (Deprecated)
|
|
300
|
+
# =============================================================================
|
|
301
|
+
|
|
184
302
|
def load_v0_format(module_path: Path) -> dict:
|
|
185
303
|
"""Load module in v0 format (old 6-file format)."""
|
|
186
304
|
# Load module.md
|
|
@@ -211,14 +329,26 @@ def load_v0_format(module_path: Path) -> dict:
|
|
|
211
329
|
"excludes": [],
|
|
212
330
|
"path": module_path,
|
|
213
331
|
"format": "v0",
|
|
332
|
+
"format_version": "v0.0",
|
|
214
333
|
"metadata": metadata,
|
|
215
334
|
"input_schema": input_schema,
|
|
216
335
|
"output_schema": output_schema,
|
|
336
|
+
"data_schema": output_schema, # Alias
|
|
217
337
|
"constraints": constraints,
|
|
218
338
|
"prompt": prompt,
|
|
339
|
+
# v2.2 defaults
|
|
340
|
+
"tier": None,
|
|
341
|
+
"schema_strictness": "medium",
|
|
342
|
+
"overflow": {"enabled": False},
|
|
343
|
+
"enums": {"strategy": "strict"},
|
|
344
|
+
"compat": {"accepts_v21_payload": True, "runtime_auto_wrap": True},
|
|
219
345
|
}
|
|
220
346
|
|
|
221
347
|
|
|
348
|
+
# =============================================================================
|
|
349
|
+
# Main Loader
|
|
350
|
+
# =============================================================================
|
|
351
|
+
|
|
222
352
|
def load_module(module_path: Path) -> dict:
|
|
223
353
|
"""Load a module, auto-detecting format."""
|
|
224
354
|
fmt = detect_format(module_path)
|
|
@@ -230,6 +360,10 @@ def load_module(module_path: Path) -> dict:
|
|
|
230
360
|
return load_v0_format(module_path)
|
|
231
361
|
|
|
232
362
|
|
|
363
|
+
# =============================================================================
|
|
364
|
+
# Module Discovery
|
|
365
|
+
# =============================================================================
|
|
366
|
+
|
|
233
367
|
def find_module(name: str, search_paths: list[Path]) -> Optional[dict]:
|
|
234
368
|
"""Find and load a module by name from search paths."""
|
|
235
369
|
for base_path in search_paths:
|
|
@@ -256,3 +390,35 @@ def list_modules(search_paths: list[Path]) -> list[dict]:
|
|
|
256
390
|
except FileNotFoundError:
|
|
257
391
|
continue
|
|
258
392
|
return modules
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
# =============================================================================
|
|
396
|
+
# Utility Functions
|
|
397
|
+
# =============================================================================
|
|
398
|
+
|
|
399
|
+
def get_module_tier(module: dict) -> Optional[ModuleTier]:
|
|
400
|
+
"""Get module tier (exec, decision, exploration)."""
|
|
401
|
+
return module.get("tier")
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
def get_schema_strictness(module: dict) -> SchemaStrictness:
|
|
405
|
+
"""Get schema strictness level."""
|
|
406
|
+
return module.get("schema_strictness", "medium")
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def is_overflow_enabled(module: dict) -> bool:
|
|
410
|
+
"""Check if overflow (extensions.insights) is enabled."""
|
|
411
|
+
overflow = module.get("overflow", {})
|
|
412
|
+
return overflow.get("enabled", False)
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
def get_enum_strategy(module: dict) -> EnumStrategy:
|
|
416
|
+
"""Get enum extension strategy."""
|
|
417
|
+
enums = module.get("enums", {})
|
|
418
|
+
return enums.get("strategy", "strict")
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
def should_auto_wrap(module: dict) -> bool:
|
|
422
|
+
"""Check if runtime should auto-wrap v2.1 to v2.2."""
|
|
423
|
+
compat = module.get("compat", {})
|
|
424
|
+
return compat.get("runtime_auto_wrap", True)
|
cognitive/mcp_server.py
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Cognitive Modules MCP Server
|
|
3
|
+
|
|
4
|
+
提供 MCP (Model Context Protocol) 接口,让 Claude Code、Cursor 等工具可以使用 Cognitive Modules。
|
|
5
|
+
|
|
6
|
+
启动方式:
|
|
7
|
+
cogn mcp
|
|
8
|
+
|
|
9
|
+
或直接运行:
|
|
10
|
+
python -m cognitive.mcp_server
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from typing import Optional, Any
|
|
14
|
+
import json
|
|
15
|
+
import os
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
from mcp.server.fastmcp import FastMCP
|
|
19
|
+
except ImportError:
|
|
20
|
+
raise ImportError(
|
|
21
|
+
"MCP dependencies not installed. "
|
|
22
|
+
"Install with: pip install cognitive-modules[mcp]"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
from .registry import list_modules, find_module
|
|
26
|
+
from .loader import load_module
|
|
27
|
+
from .runner import run_module as execute_module
|
|
28
|
+
|
|
29
|
+
# ============================================================
|
|
30
|
+
# MCP Server Setup
|
|
31
|
+
# ============================================================
|
|
32
|
+
|
|
33
|
+
mcp = FastMCP(
|
|
34
|
+
"Cognitive Modules",
|
|
35
|
+
description="可验证的结构化 AI 任务规范 - 提供代码审查、任务排序等模块",
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# ============================================================
|
|
40
|
+
# Tools
|
|
41
|
+
# ============================================================
|
|
42
|
+
|
|
43
|
+
@mcp.tool()
|
|
44
|
+
def cognitive_run(
|
|
45
|
+
module: str,
|
|
46
|
+
args: str,
|
|
47
|
+
provider: Optional[str] = None,
|
|
48
|
+
model: Optional[str] = None,
|
|
49
|
+
) -> dict[str, Any]:
|
|
50
|
+
"""
|
|
51
|
+
运行 Cognitive Module,获取结构化的 AI 分析结果。
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
module: 模块名称,如 "code-reviewer", "task-prioritizer"
|
|
55
|
+
args: 输入参数,如代码片段或任务列表
|
|
56
|
+
provider: LLM 提供商(可选),如 "openai", "anthropic"
|
|
57
|
+
model: 模型名称(可选),如 "gpt-4o", "claude-3-5-sonnet-20241022"
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
结构化结果,包含分析内容、confidence(置信度)和 rationale(推理过程)
|
|
61
|
+
|
|
62
|
+
Example:
|
|
63
|
+
cognitive_run("code-reviewer", "def login(u,p): return db.query(f'SELECT * FROM users WHERE name={u}')")
|
|
64
|
+
|
|
65
|
+
返回:
|
|
66
|
+
{
|
|
67
|
+
"ok": true,
|
|
68
|
+
"data": {
|
|
69
|
+
"issues": [{"type": "security", "severity": "critical", "description": "SQL 注入"}],
|
|
70
|
+
"confidence": 0.95,
|
|
71
|
+
"rationale": "检测到字符串拼接 SQL"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
"""
|
|
75
|
+
# 检查模块是否存在
|
|
76
|
+
module_path = find_module(module)
|
|
77
|
+
if not module_path:
|
|
78
|
+
return {"ok": False, "error": f"Module '{module}' not found"}
|
|
79
|
+
|
|
80
|
+
# 设置 provider(如果指定)
|
|
81
|
+
original_provider = os.environ.get("LLM_PROVIDER")
|
|
82
|
+
original_model = os.environ.get("LLM_MODEL")
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
if provider:
|
|
86
|
+
os.environ["LLM_PROVIDER"] = provider
|
|
87
|
+
if model:
|
|
88
|
+
os.environ["LLM_MODEL"] = model
|
|
89
|
+
|
|
90
|
+
# 执行模块
|
|
91
|
+
result = execute_module(module, args=args)
|
|
92
|
+
|
|
93
|
+
return {"ok": True, "data": result, "module": module}
|
|
94
|
+
except Exception as e:
|
|
95
|
+
return {"ok": False, "error": str(e), "module": module}
|
|
96
|
+
finally:
|
|
97
|
+
# 恢复原始环境变量
|
|
98
|
+
if original_provider:
|
|
99
|
+
os.environ["LLM_PROVIDER"] = original_provider
|
|
100
|
+
elif "LLM_PROVIDER" in os.environ and provider:
|
|
101
|
+
del os.environ["LLM_PROVIDER"]
|
|
102
|
+
|
|
103
|
+
if original_model:
|
|
104
|
+
os.environ["LLM_MODEL"] = original_model
|
|
105
|
+
elif "LLM_MODEL" in os.environ and model:
|
|
106
|
+
del os.environ["LLM_MODEL"]
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@mcp.tool()
|
|
110
|
+
def cognitive_list() -> dict[str, Any]:
|
|
111
|
+
"""
|
|
112
|
+
列出所有已安装的 Cognitive Modules。
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
模块列表,包含名称、位置和格式信息
|
|
116
|
+
|
|
117
|
+
Example:
|
|
118
|
+
cognitive_list()
|
|
119
|
+
|
|
120
|
+
返回:
|
|
121
|
+
{
|
|
122
|
+
"modules": [
|
|
123
|
+
{"name": "code-reviewer", "location": "builtin", "format": "v1"},
|
|
124
|
+
{"name": "task-prioritizer", "location": "builtin", "format": "v1"}
|
|
125
|
+
],
|
|
126
|
+
"count": 2
|
|
127
|
+
}
|
|
128
|
+
"""
|
|
129
|
+
modules = list_modules()
|
|
130
|
+
return {
|
|
131
|
+
"modules": [
|
|
132
|
+
{"name": m["name"], "location": m["location"], "format": m["format"]}
|
|
133
|
+
for m in modules
|
|
134
|
+
],
|
|
135
|
+
"count": len(modules),
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@mcp.tool()
|
|
140
|
+
def cognitive_info(module: str) -> dict[str, Any]:
|
|
141
|
+
"""
|
|
142
|
+
获取 Cognitive Module 的详细信息。
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
module: 模块名称
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
模块详情,包含名称、描述、输入输出格式等
|
|
149
|
+
|
|
150
|
+
Example:
|
|
151
|
+
cognitive_info("code-reviewer")
|
|
152
|
+
|
|
153
|
+
返回:
|
|
154
|
+
{
|
|
155
|
+
"name": "code-reviewer",
|
|
156
|
+
"version": "1.0.0",
|
|
157
|
+
"description": "代码安全和质量审查",
|
|
158
|
+
"responsibility": "分析代码并识别潜在问题"
|
|
159
|
+
}
|
|
160
|
+
"""
|
|
161
|
+
module_path = find_module(module)
|
|
162
|
+
if not module_path:
|
|
163
|
+
return {"ok": False, "error": f"Module '{module}' not found"}
|
|
164
|
+
|
|
165
|
+
try:
|
|
166
|
+
m = load_module(module)
|
|
167
|
+
meta = m.get("meta", {})
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
"ok": True,
|
|
171
|
+
"name": meta.get("name", module),
|
|
172
|
+
"version": meta.get("version"),
|
|
173
|
+
"description": meta.get("description") or meta.get("responsibility"),
|
|
174
|
+
"responsibility": meta.get("responsibility"),
|
|
175
|
+
"input_schema": m.get("input_schema"),
|
|
176
|
+
"output_schema": m.get("output_schema"),
|
|
177
|
+
}
|
|
178
|
+
except Exception as e:
|
|
179
|
+
return {"ok": False, "error": str(e)}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
# ============================================================
|
|
183
|
+
# Resources
|
|
184
|
+
# ============================================================
|
|
185
|
+
|
|
186
|
+
@mcp.resource("cognitive://modules")
|
|
187
|
+
def get_modules_resource() -> str:
|
|
188
|
+
"""获取所有模块列表(资源形式)"""
|
|
189
|
+
modules = list_modules()
|
|
190
|
+
return json.dumps([m["name"] for m in modules], indent=2)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
@mcp.resource("cognitive://module/{name}")
|
|
194
|
+
def get_module_resource(name: str) -> str:
|
|
195
|
+
"""获取单个模块的 prompt 内容"""
|
|
196
|
+
module_path = find_module(name)
|
|
197
|
+
if not module_path:
|
|
198
|
+
return f"Module '{name}' not found"
|
|
199
|
+
|
|
200
|
+
try:
|
|
201
|
+
m = load_module(name)
|
|
202
|
+
return m.get("prompt", "")
|
|
203
|
+
except Exception as e:
|
|
204
|
+
return f"Error: {e}"
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
# ============================================================
|
|
208
|
+
# Prompts
|
|
209
|
+
# ============================================================
|
|
210
|
+
|
|
211
|
+
@mcp.prompt()
|
|
212
|
+
def code_review_prompt(code: str) -> str:
|
|
213
|
+
"""生成代码审查提示"""
|
|
214
|
+
return f"""请使用 cognitive_run 工具审查以下代码:
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
{code}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
调用: cognitive_run("code-reviewer", "{code[:100]}...")
|
|
221
|
+
"""
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
@mcp.prompt()
|
|
225
|
+
def task_prioritize_prompt(tasks: str) -> str:
|
|
226
|
+
"""生成任务排序提示"""
|
|
227
|
+
return f"""请使用 cognitive_run 工具对以下任务进行优先级排序:
|
|
228
|
+
|
|
229
|
+
{tasks}
|
|
230
|
+
|
|
231
|
+
调用: cognitive_run("task-prioritizer", "{tasks}")
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
# ============================================================
|
|
236
|
+
# 启动入口
|
|
237
|
+
# ============================================================
|
|
238
|
+
|
|
239
|
+
def serve():
|
|
240
|
+
"""启动 MCP 服务器"""
|
|
241
|
+
mcp.run(transport="stdio")
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
if __name__ == "__main__":
|
|
245
|
+
serve()
|