atabey-mcp 0.0.10 → 0.0.12

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.
Files changed (70) hide show
  1. package/README.md +96 -29
  2. package/dist/framework-mcp/src/constants.js +64 -0
  3. package/dist/framework-mcp/src/index.js +156 -0
  4. package/dist/framework-mcp/src/resources/index.js +58 -0
  5. package/dist/framework-mcp/src/tools/control_plane/locking.js +84 -0
  6. package/dist/framework-mcp/src/tools/control_plane/registry.js +35 -0
  7. package/dist/framework-mcp/src/tools/definitions.js +175 -0
  8. package/dist/framework-mcp/src/tools/file_system/batch_surgical_edit.js +64 -0
  9. package/dist/framework-mcp/src/tools/file_system/patch_file.js +34 -0
  10. package/dist/framework-mcp/src/tools/file_system/read_file.js +51 -0
  11. package/dist/framework-mcp/src/tools/file_system/replace_text.js +50 -0
  12. package/dist/framework-mcp/src/tools/file_system/write_file.js +55 -0
  13. package/dist/framework-mcp/src/tools/framework/audit_deps.js +41 -0
  14. package/dist/framework-mcp/src/tools/framework/get_status.js +5 -0
  15. package/dist/framework-mcp/src/tools/framework/orchestrate.js +5 -0
  16. package/dist/framework-mcp/src/tools/framework/run_tests.js +27 -0
  17. package/dist/framework-mcp/src/tools/framework/submit_plan.js +13 -0
  18. package/dist/framework-mcp/src/tools/framework/update_contract_hash.js +5 -0
  19. package/dist/framework-mcp/src/tools/framework/update_memory.js +8 -0
  20. package/dist/framework-mcp/src/tools/index.js +111 -0
  21. package/dist/framework-mcp/src/tools/memory/delete_knowledge.js +28 -0
  22. package/dist/framework-mcp/src/tools/memory/get_insights.js +22 -0
  23. package/dist/framework-mcp/src/tools/memory/read_memory.js +28 -0
  24. package/dist/framework-mcp/src/tools/memory/search_knowledge.js +48 -0
  25. package/dist/framework-mcp/src/tools/memory/store_knowledge.js +30 -0
  26. package/dist/framework-mcp/src/tools/messaging/ask_human.js +30 -0
  27. package/dist/framework-mcp/src/tools/messaging/log_action.js +22 -0
  28. package/dist/framework-mcp/src/tools/messaging/send_message.js +94 -0
  29. package/dist/framework-mcp/src/tools/observability/check_ports.js +26 -0
  30. package/dist/framework-mcp/src/tools/observability/get_health.js +19 -0
  31. package/dist/framework-mcp/src/tools/quality/check_lint.js +30 -0
  32. package/dist/framework-mcp/src/tools/schemas.js +153 -0
  33. package/dist/framework-mcp/src/tools/search/get_gaps.js +48 -0
  34. package/dist/framework-mcp/src/tools/search/get_map.js +43 -0
  35. package/dist/framework-mcp/src/tools/search/grep_search.js +78 -0
  36. package/dist/framework-mcp/src/tools/search/list_dir.js +28 -0
  37. package/dist/framework-mcp/src/tools/shell/run_command.js +121 -0
  38. package/dist/framework-mcp/src/tools/types.js +1 -0
  39. package/dist/framework-mcp/src/utils/cli.js +59 -0
  40. package/dist/framework-mcp/src/utils/compliance.js +292 -0
  41. package/dist/framework-mcp/src/utils/errors.js +68 -0
  42. package/dist/framework-mcp/src/utils/fs.js +47 -0
  43. package/dist/framework-mcp/src/utils/memory.js +74 -0
  44. package/dist/framework-mcp/src/utils/metrics.js +56 -0
  45. package/dist/framework-mcp/src/utils/permissions.js +71 -0
  46. package/dist/framework-mcp/src/utils/security.js +60 -0
  47. package/dist/framework-mcp/src/utils/storage.js +207 -0
  48. package/dist/framework-mcp/src/utils/types.js +16 -0
  49. package/dist/framework-mcp/src/utils/zod-to-mcp.js +79 -0
  50. package/dist/index.js +14 -2
  51. package/dist/src/cli/utils/memory.js +279 -0
  52. package/dist/src/cli/utils/time.js +27 -0
  53. package/dist/src/cli/utils/ui.js +100 -0
  54. package/dist/src/modules/memory/core.js +106 -0
  55. package/dist/src/modules/memory/types.js +1 -0
  56. package/dist/src/modules/memory/vector-store.js +74 -0
  57. package/dist/src/shared/constants.js +187 -0
  58. package/dist/src/shared/fs.js +51 -0
  59. package/dist/src/shared/logger.js +116 -0
  60. package/dist/src/shared/storage.js +209 -0
  61. package/dist/src/shared/types.js +16 -0
  62. package/dist/tools/definitions.js +79 -247
  63. package/dist/tools/file_system/read_file.js +7 -7
  64. package/dist/tools/file_system/write_file.js +12 -0
  65. package/dist/tools/index.js +37 -0
  66. package/dist/tools/memory/get_insights.js +9 -21
  67. package/dist/tools/schemas.js +133 -0
  68. package/dist/utils/types.js +4 -0
  69. package/dist/utils/zod-to-mcp.js +77 -0
  70. package/package.json +2 -2
package/README.md CHANGED
@@ -1,48 +1,115 @@
1
1
  # Agent Atabey — MCP Server (`atabey-mcp`)
2
2
 
3
- [![Version](https://img.shields.io/npm/v/atabey-mcp.svg)](https://npmjs.com/package/atabey-mcp)
3
+ [![Version](https://img.shields.io/npm/v/atabey-mcp.svg)](https://www.npmjs.com/package/atabey-mcp)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![npm](https://img.shields.io/npm/dt/atabey-mcp)](https://www.npmjs.com/package/atabey-mcp)
5
6
 
6
- The **Model Context Protocol (MCP)** server for [Agent Atabey](https://npmjs.com/package/atabey).
7
+ The **Model Context Protocol (MCP)** server for [Agent Atabey](https://www.npmjs.com/package/atabey).
7
8
 
8
- This package acts as the bridge between AI Assistants (like Claude Desktop, Cursor, or Antigravity CLI) and your local project environment. It provides a highly governed, type-safe set of tools that allow AI agents to interact with your codebase securely.
9
+ Bu paket, AI asistanları (Claude Code, Gemini CLI, Cursor, Antigravity CLI) ile yerel proje ortamınız arasında köprü görevi görür. 30+ araç ile güvenli, denetimli ve tip-güvenli bir etkileşim sağlar.
9
10
 
10
- ## 🚀 Features
11
+ ## 🚀 Özellikler / Features
11
12
 
12
- - **Strict Governance:** Enforces Zero Type Hole and Zero Console policies via AST parsing.
13
- - **Surgical Edits:** Uses `patch_file` and `replace_text` instead of full-file rewrites to save tokens and prevent context loss.
14
- - **Hermes Message Broker:** Facilitates asynchronous communication between specialized agents (`@manager`, `@architect`, `@security`, etc.).
15
- - **Memory Insights:** Provides agents with targeted, pruned context (last 5 actions, active trace) instead of dumping the entire project history.
16
- - **Risk Engine:** Automatically blocks or requires human approval for high-risk operations (e.g., deleting databases, touching `.env` files).
13
+ | Özellik | Açıklama |
14
+ |---------|----------|
15
+ | **Sıkı Yönetişim** | Zero Type Hole, Zero Console politikaları, AST analizi ile denetim |
16
+ | **Cerrahi Düzenleme** | `patch_file` ve `replace_text` ile tam dosya yeniden yazımı yerine satır bazlı düzenleme |
17
+ | **Hermes Message Broker** | Uzman ajanlar arası asenkron iletişim (`@manager`, `@architect`, `@security`, vb.) |
18
+ | **Bellek Yönetimi** | Proje geçmişinin tamamını dökmek yerine hedeflenmiş, budanmış bağlam |
19
+ | **Risk Engine** | Yüksek riskli işlemler için otomatik engelleme veya insan onayı |
17
20
 
18
- ## 📦 Installation
19
-
20
- Typically, you do not need to install this package manually. It is automatically installed and configured when you initialize an Atabey project:
21
+ ## 📦 Kurulum / Installation
21
22
 
22
23
  ```bash
23
- npx atabey init
24
- ```
24
+ # Global kurulum (genelde init ile otomatik gelir)
25
+ npm install -g atabey-mcp
25
26
 
26
- However, you can install it globally or locally if needed:
27
-
28
- ```bash
27
+ # Projeye ekleme
29
28
  npm install atabey-mcp
30
29
  ```
31
30
 
32
- ## 🛠️ Provided Tools
33
-
34
- The `atabey-mcp` server exposes over 25 specialized tools grouped into the following domains:
31
+ ## 🛠️ Sağlanan Araçlar / Provided Tools (30+)
32
+
33
+ ### 📁 Dosya Sistemi / File System
34
+ | Araç | Açıklama |
35
+ |------|---------|
36
+ | `read_file` | Dosya okuma |
37
+ | `write_file` | Dosya yazma |
38
+ | `replace_text` | Metin değiştirme |
39
+ | `patch_file` | Yama uygulama |
40
+ | `batch_surgical_edit` | Toplu cerrahi düzenleme |
41
+ | `list_dir` | Dizin listeleme |
42
+ | `grep_search` | Regex arama |
43
+
44
+ ### 🎛️ Kontrol Paneli / Control Plane
45
+ | Araç | Açıklama |
46
+ |------|---------|
47
+ | `acquire_lock` | Kaynak kilidi al |
48
+ | `release_lock` | Kaynak kilidini bırak |
49
+ | `register_agent` | Ajan kaydet |
50
+
51
+ ### 🔍 Arama & Haritalama / Search & Map
52
+ | Araç | Açıklama |
53
+ |------|---------|
54
+ | `get_project_map` | Proje haritası |
55
+ | `get_project_gaps` | Proje boşlukları |
56
+ | `search_knowledge` | Bilgi tabanında ara |
57
+ | `store_knowledge` | Bilgi tabanına ekle |
58
+
59
+ ### 📊 Kalite & Gözlem / Quality & Observability
60
+ | Araç | Açıklama |
61
+ |------|---------|
62
+ | `check_lint` | Lint kontrolü |
63
+ | `check_compliance` | Uyumluluk denetimi |
64
+ | `run_tests` | Test çalıştır |
65
+ | `get_system_health` | Sistem sağlığı |
66
+ | `check_active_ports` | Port denetimi |
67
+ | `audit_dependencies` | Bağımlılık denetimi |
68
+
69
+ ### 💬 Mesajlaşma / Messaging
70
+ | Araç | Açıklama |
71
+ |------|---------|
72
+ | `send_agent_message` | Ajanlar arası mesaj |
73
+ | `log_agent_action` | Ajan eylemlerini logla |
74
+
75
+ ### 🧠 Bellek & Framework / Memory & Framework
76
+ | Araç | Açıklama |
77
+ |------|---------|
78
+ | `read_project_memory` | Proje hafızasını oku |
79
+ | `update_project_memory` | Proje hafızasını güncelle |
80
+ | `get_memory_insights` | Bellek içgörüleri |
81
+ | `get_framework_status` | Framework durumu |
82
+
83
+ ### ⚡ Çalıştırma / Execution
84
+ | Araç | Açıklama |
85
+ |------|---------|
86
+ | `run_shell_command` | Shell komutu çalıştır |
87
+ | `run_tests` | Test çalıştır |
88
+
89
+ ## 🔧 Claude Code ile Kullanım
90
+
91
+ ```json
92
+ {
93
+ "mcpServers": {
94
+ "atabey": {
95
+ "command": "node",
96
+ "args": ["/path/to/atabey-mcp/dist/index.js"],
97
+ "env": {
98
+ "ATABEY_PROJECT_ROOT": "/path/to/your/project"
99
+ }
100
+ }
101
+ }
102
+ }
103
+ ```
35
104
 
36
- - **File System:** `read_file`, `write_file`, `replace_text`, `patch_file`, `batch_surgical_edit`
37
- - **Control Plane:** `acquire_lock`, `release_lock`, `register_agent`
38
- - **Framework & Orchestration:** `submit_plan`, `orchestrate_loop`, `update_project_memory`, `audit_dependencies`
39
- - **Search & Map:** `grep_search`, `list_dir`, `get_architectural_map`, `get_knowledge_gaps`
40
- - **Quality & Observability:** `check_lint`, `run_tests`, `get_system_health`, `check_ports`
41
- - **Messaging:** `send_agent_message`, `log_agent_action`
105
+ ## 📖 Daha Fazla Bilgi
42
106
 
43
- ## 📖 Learn More
107
+ Tüm dokümantasyon, mimari detaylar ve kurumsal iletişim için ana depoyu ziyaret edin:
44
108
 
45
- For full documentation, architecture details, and enterprise inquiries, please visit the main [Agent Atabey Repository](https://github.com/ysf-bkr/atabey).
109
+ - **Ana Paket:** [atabey](https://www.npmjs.com/package/atabey)
110
+ - **GitHub:** [github.com/ysf-bkr/atabey](https://github.com/ysf-bkr/atabey)
111
+ - **Enterprise:** ybekar@msn.com
46
112
 
47
113
  ---
48
- *Developed by Yusuf BEKAR*
114
+
115
+ *Developed by **Yusuf BEKAR** — "Order from Chaos"*
@@ -0,0 +1,64 @@
1
+ import path from "path";
2
+ /**
3
+ * Agent Atabey — Single Source of Truth for framework constants.
4
+ * Import from here instead of hardcoding paths, phases, or directory names.
5
+ */
6
+ // ─── Framework identity ───────────────────────────────────────────────────
7
+ export const FRAMEWORK = {
8
+ NAME: "Agent Atabey",
9
+ CORE_DIR: ".atabey",
10
+ // This is the hub for unified adapter layouts (e.g. .agents/gemini, .agents/claude)
11
+ UNIFIED_HUB_DIR: ".agents",
12
+ // This is the default directory to scaffold new apps into
13
+ APPS_DIR: "apps",
14
+ // This is where all skills are stored
15
+ SKILLS_DIR: "skills",
16
+ };
17
+ export const FRAMEWORK_SUBDIRS = {
18
+ AGENTS: "agents",
19
+ SKILLS: "skills",
20
+ KNOWLEDGE: "knowledge",
21
+ MESSAGES: "messages",
22
+ MEMORY: "memory",
23
+ MEMORY_GRAPH: "memory-graph",
24
+ LOGS: "logs",
25
+ CONFIG: "config",
26
+ };
27
+ export const ROOT_CONFIG_FILES = {
28
+ MCP: "mcp.json",
29
+ NATIVE_MODULES: "native-modules.json",
30
+ TSCONFIG: "tsconfig.json",
31
+ ESLINT: "eslint.config.js",
32
+ };
33
+ export const MCP = {
34
+ // Environment variable used by MCP to identify project root
35
+ PROJECT_ROOT_ENV: "ATABEY_PROJECT_ROOT",
36
+ // Environment variable for test mode
37
+ TEST_DIR_ENV: "ATABEY_TEST_DIR",
38
+ };
39
+ export const MEMORY_FILES = {
40
+ STATE: "state.json",
41
+ SHARED_FACTS: "shared_facts.json",
42
+ };
43
+ export const NATIVE_AGENT_PATHS = {
44
+ gemini: ".gemini/agents",
45
+ claude: ".claude/agents",
46
+ cursor: ".cursor/rules",
47
+ codex: ".agents/instructions",
48
+ grok: ".grok",
49
+ "antigravity-cli": ".agents/agents",
50
+ };
51
+ // ─── Backward-compatible aliases ──────────────────────────────────────────
52
+ export const CORE_FRAMEWORK_DIR = FRAMEWORK.CORE_DIR;
53
+ export const UNIFIED_HUB_DIR = FRAMEWORK.UNIFIED_HUB_DIR;
54
+ export const SKILLS_HUB_PATH = pathJoin(UNIFIED_HUB_DIR, FRAMEWORK_SUBDIRS.SKILLS);
55
+ // ─── Path Helpers ─────────────────────────────────────────────────────────
56
+ function pathJoin(...args) {
57
+ return path.join(...args);
58
+ }
59
+ function corePath(subdir, filename) {
60
+ return pathJoin(FRAMEWORK.CORE_DIR, subdir, filename);
61
+ }
62
+ export function knowledgePath(filename) {
63
+ return corePath(FRAMEWORK_SUBDIRS.KNOWLEDGE, filename);
64
+ }
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env node
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import { fileURLToPath } from "url";
5
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
6
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
8
+ import { TOOLS, toolHandlers, toolSchemas } from "./tools/index.js";
9
+ import { RESOURCES, handleReadResource } from "./resources/index.js";
10
+ // ─── Server Setup ─────────────────────────────────────────────────
11
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
+ // Robustly find package.json by walking up from __dirname
13
+ function findPackageJson(startDir) {
14
+ let currentDir = startDir;
15
+ while (currentDir !== path.parse(currentDir).root) {
16
+ const pkgPath = path.join(currentDir, "package.json");
17
+ if (fs.existsSync(pkgPath))
18
+ return pkgPath;
19
+ currentDir = path.dirname(currentDir);
20
+ }
21
+ throw new Error("Could not find package.json for atabey-mcp");
22
+ }
23
+ const pkgPath = findPackageJson(__dirname);
24
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
25
+ const serverVersion = pkg.version;
26
+ const server = new Server({
27
+ name: "atabey-mcp",
28
+ version: serverVersion,
29
+ }, {
30
+ capabilities: {
31
+ tools: {},
32
+ resources: {},
33
+ },
34
+ });
35
+ /**
36
+ * Validates tool arguments using Zod schemas for "Zero Type Hole" compliance.
37
+ * Falls back to basic presence check if no Zod schema is defined for the tool.
38
+ */
39
+ function validateArgs(toolName, args) {
40
+ const schema = toolSchemas[toolName];
41
+ if (schema) {
42
+ const result = schema.safeParse(args);
43
+ if (!result.success) {
44
+ return result.error.errors.map(e => `${e.path.join(".")}: ${e.message}`).join(", ");
45
+ }
46
+ return null;
47
+ }
48
+ // Fallback for tools without Zod schemas yet
49
+ const definition = TOOLS.find(t => t.name === toolName);
50
+ if (!definition)
51
+ return `Unknown tool: ${toolName}`;
52
+ const required = definition.inputSchema.required || [];
53
+ for (const field of required) {
54
+ if (args[field] === undefined || args[field] === null || args[field] === "") {
55
+ return `Missing required argument: '${field}' for tool '${toolName}'`;
56
+ }
57
+ }
58
+ return null;
59
+ }
60
+ server.setRequestHandler(ListToolsRequestSchema, async (request) => {
61
+ // 2026 Stateless Spec: Log client info from metadata if available
62
+ const meta = request._meta;
63
+ if (meta) {
64
+ process.stderr.write(`[MCP] Stateless ListTools from ${meta.client?.name || "unknown"} v${meta.client?.version || "?.?"}\n`);
65
+ }
66
+ return { tools: TOOLS };
67
+ });
68
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
69
+ return { resources: RESOURCES };
70
+ });
71
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
72
+ const uri = request.params.uri;
73
+ try {
74
+ const content = await handleReadResource(uri);
75
+ return {
76
+ contents: [
77
+ {
78
+ uri,
79
+ mimeType: "text/markdown",
80
+ text: content,
81
+ },
82
+ ],
83
+ };
84
+ }
85
+ catch (error) {
86
+ const message = error instanceof Error ? error.message : String(error);
87
+ throw new Error(`Failed to read resource: ${message}`, { cause: error });
88
+ }
89
+ });
90
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
91
+ const req = request;
92
+ const { name, arguments: args } = req.params;
93
+ const meta = request._meta;
94
+ // 2026 Stateless Spec: Prioritize metadata-driven context
95
+ if (meta) {
96
+ process.stderr.write(`[MCP] Stateless CallTool: ${name} (Client: ${meta.client?.name || "unknown"})\n`);
97
+ }
98
+ const projectRoot = process.env.ATABEY_PROJECT_ROOT || process.cwd();
99
+ try {
100
+ const handler = toolHandlers[name];
101
+ if (!handler) {
102
+ return {
103
+ isError: true,
104
+ content: [{ type: "text", text: `[ERROR] Unknown tool: ${name}` }],
105
+ };
106
+ }
107
+ // [SECURITY] Runtime Validation
108
+ const validationError = validateArgs(name, args || {});
109
+ if (validationError) {
110
+ return {
111
+ isError: true,
112
+ content: [{ type: "text", text: `[ERROR] Validation Error: ${validationError}` }],
113
+ };
114
+ }
115
+ return await handler(projectRoot, args || {});
116
+ }
117
+ catch (error) {
118
+ const message = error instanceof Error ? error.message : "Unknown error occurred";
119
+ return {
120
+ isError: true,
121
+ content: [{ type: "text", text: `[ERROR] Execution failed: ${message}` }],
122
+ };
123
+ }
124
+ });
125
+ // ─── Graceful Startup & Shutdown ──────────────────────────────────
126
+ async function run() {
127
+ const transport = new StdioServerTransport();
128
+ // Prevent unhandled errors from crashing the MCP stream
129
+ process.on("uncaughtException", (error) => {
130
+ process.stderr.write(`[atabey-mcp] Uncaught exception: ${error.message}
131
+ `);
132
+ });
133
+ process.on("unhandledRejection", (reason) => {
134
+ const message = reason instanceof Error ? reason.message : String(reason);
135
+ process.stderr.write(`[atabey-mcp] Unhandled rejection: ${message}
136
+ `);
137
+ });
138
+ // Graceful shutdown on SIGINT/SIGTERM
139
+ const shutdown = async () => {
140
+ try {
141
+ await server.close();
142
+ }
143
+ catch {
144
+ // Already closed or failed — safe to ignore
145
+ }
146
+ process.exit(0);
147
+ };
148
+ process.on("SIGINT", shutdown);
149
+ process.on("SIGTERM", shutdown);
150
+ await server.connect(transport);
151
+ }
152
+ run().catch((error) => {
153
+ process.stderr.write(`[atabey-mcp] Fatal startup error: ${error.message}
154
+ `);
155
+ process.exit(1);
156
+ });
@@ -0,0 +1,58 @@
1
+ import { Storage } from "../utils/storage.js";
2
+ /**
3
+ * [DATA] MCP Resource Definitions
4
+ */
5
+ export const RESOURCES = [
6
+ {
7
+ uri: "atabey://AL/status",
8
+ name: "AL Registry Status",
9
+ description: "Real-time state and active tasks of all specialized agents.",
10
+ mimeType: "text/markdown"
11
+ },
12
+ {
13
+ uri: "atabey://plan/active",
14
+ name: "Active Execution Plan",
15
+ description: "The current DAG of tasks and their completion status.",
16
+ mimeType: "text/markdown"
17
+ },
18
+ {
19
+ uri: "atabey://memory/project",
20
+ name: "Project Memory",
21
+ description: "The central source of truth for project context (PROJECT_MEMORY.md).",
22
+ mimeType: "text/markdown"
23
+ }
24
+ ];
25
+ export async function handleReadResource(uri) {
26
+ if (uri === "atabey://AL/status") {
27
+ const agents = Storage.getAllAgents();
28
+ let md = "# [AI] AL Registry Status\n\n| Agent | State | Active Task | Last Updated |\n| :--- | :--- | :--- | :--- |\n";
29
+ agents.forEach((a) => {
30
+ md += `| @${a.name} | ${a.state} | ${a.task} | ${a.last_updated} |\n`;
31
+ });
32
+ return md;
33
+ }
34
+ if (uri === "atabey://plan/active") {
35
+ const tasks = Storage.getTasks();
36
+ let md = "# [LIST] Active Execution Plan\n\n| ID | Task | Agent | Status | Dependencies |\n| :--- | :--- | :--- | :--- | :--- |\n";
37
+ tasks.forEach((t) => {
38
+ const deps = t.dependencies.join(", ") || "-";
39
+ md += `| ${t.id} | ${t.description} | ${t.agent} | ${t.status} | ${deps} |\n`;
40
+ });
41
+ return md;
42
+ }
43
+ if (uri === "atabey://memory/project") {
44
+ const fs = await import("fs");
45
+ const path = await import("path");
46
+ const { getFrameworkDir } = await import("../utils/memory.js");
47
+ const projectRoot = process.env.ATABEY_PROJECT_ROOT || process.cwd();
48
+ const fwDir = getFrameworkDir();
49
+ const p = path.isAbsolute(fwDir)
50
+ ? path.join(fwDir, "memory", "PROJECT_MEMORY.md")
51
+ : path.join(projectRoot, fwDir, "memory", "PROJECT_MEMORY.md");
52
+ if (fs.existsSync(p)) {
53
+ return fs.readFileSync(p, "utf8");
54
+ }
55
+ return "Project memory not found. Run 'atabey init' first.";
56
+ }
57
+ throw new Error(`Unknown resource URI: ${uri}`);
58
+ }
@@ -0,0 +1,84 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { resolveFrameworkDir } from "../../utils/security.js";
4
+ import { Metrics } from "../../utils/metrics.js";
5
+ /**
6
+ * Handles acquiring a stateful lock on a resource with Deadlock Resolution.
7
+ */
8
+ export async function handleAcquireLock(projectRoot, args) {
9
+ const { resource, agent, ttl = 300 } = args; // Default TTL 5 minutes to prevent deadlocks
10
+ const frameworkDir = resolveFrameworkDir(projectRoot);
11
+ const lockDir = path.join(projectRoot, frameworkDir, "locks");
12
+ const lockPath = path.join(lockDir, `${resource}.lock`);
13
+ try {
14
+ if (!fs.existsSync(lockDir))
15
+ fs.mkdirSync(lockDir, { recursive: true });
16
+ // Check for stale lock first (DEADLOCK RESOLUTION)
17
+ if (fs.existsSync(lockPath)) {
18
+ const stat = fs.statSync(lockPath);
19
+ const now = new Date().getTime();
20
+ const age = (now - stat.mtimeMs) / 1000;
21
+ if (age < ttl) {
22
+ return {
23
+ isError: true,
24
+ content: [{ type: "text", text: `[LOCKED] Resource '${resource}' is currently locked by another agent. Try again later.` }]
25
+ };
26
+ }
27
+ // Lock expired: Force Eviction
28
+ const oldLockData = JSON.parse(fs.readFileSync(lockPath, "utf8"));
29
+ Metrics.logError(projectRoot, "@mcp", "lock_eviction", `Forcefully evicted stale lock on '${resource}' held by ${oldLockData.agent} for ${Math.round(age)}s.`);
30
+ const tempLockPath = `${lockPath}.${Math.random().toString(36).substring(2)}.old`;
31
+ try {
32
+ fs.renameSync(lockPath, tempLockPath);
33
+ fs.unlinkSync(tempLockPath);
34
+ }
35
+ catch {
36
+ // Ignore if already evicted by race condition
37
+ }
38
+ }
39
+ // Use 'wx' flag for atomic file creation
40
+ const lockData = JSON.stringify({ agent, timestamp: new Date().toISOString() });
41
+ fs.writeFileSync(lockPath, lockData, { flag: "wx" });
42
+ return {
43
+ content: [{ type: "text", text: `[OK] Lock acquired for resource '${resource}' by ${agent}.` }]
44
+ };
45
+ }
46
+ catch (e) {
47
+ const error = e;
48
+ if (error.code === "EEXIST") {
49
+ return {
50
+ isError: true,
51
+ content: [{ type: "text", text: `[LOCKED] Resource '${resource}' was just acquired by another agent.` }]
52
+ };
53
+ }
54
+ return {
55
+ isError: true,
56
+ content: [{ type: "text", text: `Failed to acquire lock: ${String(e)}` }]
57
+ };
58
+ }
59
+ }
60
+ /**
61
+ * Handles releasing a lock.
62
+ */
63
+ export async function handleReleaseLock(projectRoot, args) {
64
+ const { resource, agent } = args;
65
+ const frameworkDir = resolveFrameworkDir(projectRoot);
66
+ const lockPath = path.join(projectRoot, frameworkDir, "locks", `${resource}.lock`);
67
+ try {
68
+ if (!fs.existsSync(lockPath)) {
69
+ return { content: [{ type: "text", text: `[INFO] No lock found for resource '${resource}'.` }] };
70
+ }
71
+ const lockData = JSON.parse(fs.readFileSync(lockPath, "utf8"));
72
+ if (lockData.agent !== agent) {
73
+ return {
74
+ isError: true,
75
+ content: [{ type: "text", text: `[ERROR] Denied: You do not own the lock for '${resource}'. Owned by ${lockData.agent}.` }]
76
+ };
77
+ }
78
+ fs.unlinkSync(lockPath);
79
+ return { content: [{ type: "text", text: `[OK] Lock released for resource '${resource}' by ${agent}.` }] };
80
+ }
81
+ catch (e) {
82
+ return { isError: true, content: [{ type: "text", text: `Failed to release lock: ${String(e)}` }] };
83
+ }
84
+ }
@@ -0,0 +1,35 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { resolveFrameworkDir } from "../../utils/security.js";
4
+ /**
5
+ * Handles agent registration with the Control Plane.
6
+ * This can be used to validate permissions and active status.
7
+ */
8
+ export async function handleRegisterAgent(projectRoot, args) {
9
+ const { agent, role, capability = 5, specialties } = args;
10
+ const frameworkDir = resolveFrameworkDir(projectRoot);
11
+ const registryDir = path.join(projectRoot, frameworkDir, "registry");
12
+ const agentFile = path.join(registryDir, `${agent.replace("@", "")}_active.json`);
13
+ try {
14
+ if (!fs.existsSync(registryDir))
15
+ fs.mkdirSync(registryDir, { recursive: true });
16
+ const agentData = {
17
+ agent,
18
+ role,
19
+ capability,
20
+ specialties,
21
+ last_seen: new Date().toISOString(),
22
+ status: "ACTIVE"
23
+ };
24
+ fs.writeFileSync(agentFile, JSON.stringify(agentData, null, 2));
25
+ return {
26
+ content: [{ type: "text", text: `[ATABEY] Agent ${agent} (${role}) registered successfully in the Atabey Control Plane.` }]
27
+ };
28
+ }
29
+ catch (e) {
30
+ return {
31
+ isError: true,
32
+ content: [{ type: "text", text: `Failed to register agent: ${String(e)}` }]
33
+ };
34
+ }
35
+ }