atabey-mcp 0.0.7 → 0.0.9

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 (49) hide show
  1. package/{src/constants.ts → dist/constants.js} +3 -17
  2. package/dist/framework-mcp/src/resources/index.js +2 -2
  3. package/dist/framework-mcp/src/utils/errors.js +68 -0
  4. package/dist/framework-mcp/src/utils/memory.js +74 -0
  5. package/dist/framework-mcp/src/utils/storage.js +207 -0
  6. package/dist/framework-mcp/src/utils/types.js +12 -0
  7. package/{src/index.ts → dist/index.js} +31 -59
  8. package/{src/resources/index.ts → dist/resources/index.js} +4 -11
  9. package/dist/src/cli/adapters/core.js +12 -19
  10. package/dist/src/shared/constants.js +1 -0
  11. package/{src/tools/control_plane/locking.ts → dist/tools/control_plane/locking.js} +11 -18
  12. package/{src/tools/control_plane/registry.ts → dist/tools/control_plane/registry.js} +5 -9
  13. package/{src/tools/definitions.ts → dist/tools/definitions.js} +2 -4
  14. package/{src/tools/file_system/batch_surgical_edit.ts → dist/tools/file_system/batch_surgical_edit.js} +9 -32
  15. package/{src/tools/file_system/patch_file.ts → dist/tools/file_system/patch_file.js} +2 -14
  16. package/{src/tools/file_system/read_file.ts → dist/tools/file_system/read_file.js} +6 -13
  17. package/{src/tools/file_system/replace_text.ts → dist/tools/file_system/replace_text.js} +6 -17
  18. package/{src/tools/file_system/write_file.ts → dist/tools/file_system/write_file.js} +5 -14
  19. package/{src/tools/framework/audit_deps.ts → dist/tools/framework/audit_deps.js} +8 -16
  20. package/{src/tools/framework/get_status.ts → dist/tools/framework/get_status.js} +1 -3
  21. package/{src/tools/framework/orchestrate.ts → dist/tools/framework/orchestrate.js} +1 -3
  22. package/{src/tools/framework/run_tests.ts → dist/tools/framework/run_tests.js} +8 -11
  23. package/{src/tools/framework/submit_plan.ts → dist/tools/framework/submit_plan.js} +1 -14
  24. package/{src/tools/framework/update_contract_hash.ts → dist/tools/framework/update_contract_hash.js} +1 -3
  25. package/{src/tools/framework/update_memory.ts → dist/tools/framework/update_memory.js} +1 -3
  26. package/{src/tools/index.ts → dist/tools/index.js} +3 -7
  27. package/{src/tools/memory/get_insights.ts → dist/tools/memory/get_insights.js} +3 -10
  28. package/{src/tools/memory/read_memory.ts → dist/tools/memory/read_memory.js} +3 -6
  29. package/{src/tools/messaging/log_action.ts → dist/tools/messaging/log_action.js} +1 -7
  30. package/{src/tools/messaging/send_message.ts → dist/tools/messaging/send_message.js} +14 -17
  31. package/{src/tools/observability/check_ports.ts → dist/tools/observability/check_ports.js} +6 -10
  32. package/{src/tools/observability/get_health.ts → dist/tools/observability/get_health.js} +1 -6
  33. package/{src/tools/quality/check_lint.ts → dist/tools/quality/check_lint.js} +1 -7
  34. package/{src/tools/search/get_gaps.ts → dist/tools/search/get_gaps.js} +12 -18
  35. package/{src/tools/search/get_map.ts → dist/tools/search/get_map.js} +14 -19
  36. package/{src/tools/search/grep_search.ts → dist/tools/search/grep_search.js} +23 -23
  37. package/{src/tools/search/list_dir.ts → dist/tools/search/list_dir.js} +4 -10
  38. package/{src/tools/shell/run_command.ts → dist/tools/shell/run_command.js} +1 -11
  39. package/dist/tools/types.js +1 -0
  40. package/{src/utils/cli.ts → dist/utils/cli.js} +25 -19
  41. package/{src/utils/compliance.ts → dist/utils/compliance.js} +34 -74
  42. package/{src/utils/fs.ts → dist/utils/fs.js} +9 -10
  43. package/{src/utils/metrics.ts → dist/utils/metrics.js} +11 -28
  44. package/{src/utils/permissions.ts → dist/utils/permissions.js} +11 -28
  45. package/{src/utils/security.ts → dist/utils/security.js} +9 -15
  46. package/package.json +9 -1
  47. package/src/declarations.d.ts +0 -19
  48. package/src/tools/types.ts +0 -89
  49. package/tsconfig.json +0 -13
@@ -1,12 +1,9 @@
1
1
  import path from "path";
2
-
3
2
  /**
4
3
  * Agent Atabey — Single Source of Truth for framework constants.
5
4
  * Import from here instead of hardcoding paths, phases, or directory names.
6
5
  */
7
-
8
6
  // ─── Framework identity ───────────────────────────────────────────────────
9
-
10
7
  export const FRAMEWORK = {
11
8
  NAME: "Agent Atabey",
12
9
  CORE_DIR: ".atabey",
@@ -17,7 +14,6 @@ export const FRAMEWORK = {
17
14
  // This is where all skills are stored
18
15
  SKILLS_DIR: "skills",
19
16
  };
20
-
21
17
  export const FRAMEWORK_SUBDIRS = {
22
18
  AGENTS: "agents",
23
19
  SKILLS: "skills",
@@ -28,26 +24,22 @@ export const FRAMEWORK_SUBDIRS = {
28
24
  LOGS: "logs",
29
25
  CONFIG: "config",
30
26
  };
31
-
32
27
  export const ROOT_CONFIG_FILES = {
33
28
  MCP: "mcp.json",
34
29
  NATIVE_MODULES: "native-modules.json",
35
30
  TSCONFIG: "tsconfig.json",
36
31
  ESLINT: "eslint.config.js",
37
32
  };
38
-
39
33
  export const MCP = {
40
34
  // Environment variable used by MCP to identify project root
41
35
  PROJECT_ROOT_ENV: "ATABEY_PROJECT_ROOT",
42
36
  // Environment variable for test mode
43
37
  TEST_DIR_ENV: "ATABEY_TEST_DIR",
44
38
  };
45
-
46
39
  export const MEMORY_FILES = {
47
40
  STATE: "state.json",
48
41
  SHARED_FACTS: "shared_facts.json",
49
42
  };
50
-
51
43
  export const NATIVE_AGENT_PATHS = {
52
44
  gemini: ".gemini/agents",
53
45
  claude: ".claude/agents",
@@ -56,23 +48,17 @@ export const NATIVE_AGENT_PATHS = {
56
48
  grok: ".grok",
57
49
  "antigravity-cli": ".agents/agents",
58
50
  };
59
-
60
51
  // ─── Backward-compatible aliases ──────────────────────────────────────────
61
-
62
52
  export const CORE_FRAMEWORK_DIR = FRAMEWORK.CORE_DIR;
63
53
  export const UNIFIED_HUB_DIR = FRAMEWORK.UNIFIED_HUB_DIR;
64
54
  export const SKILLS_HUB_PATH = pathJoin(UNIFIED_HUB_DIR, FRAMEWORK_SUBDIRS.SKILLS);
65
-
66
55
  // ─── Path Helpers ─────────────────────────────────────────────────────────
67
-
68
- function pathJoin(...args: string[]): string {
56
+ function pathJoin(...args) {
69
57
  return path.join(...args);
70
58
  }
71
-
72
- function corePath(subdir: string, filename: string): string {
59
+ function corePath(subdir, filename) {
73
60
  return pathJoin(FRAMEWORK.CORE_DIR, subdir, filename);
74
61
  }
75
-
76
- export function knowledgePath(filename: string): string {
62
+ export function knowledgePath(filename) {
77
63
  return corePath(FRAMEWORK_SUBDIRS.KNOWLEDGE, filename);
78
64
  }
@@ -1,4 +1,4 @@
1
- import { Storage } from "../../../src/shared/storage.js";
1
+ import { Storage } from "../utils/storage.js";
2
2
  /**
3
3
  * [DATA] MCP Resource Definitions
4
4
  */
@@ -43,7 +43,7 @@ export async function handleReadResource(uri) {
43
43
  if (uri === "atabey://memory/project") {
44
44
  const fs = await import("fs");
45
45
  const path = await import("path");
46
- const { getFrameworkDir } = await import("../../../src/cli/utils/memory.js");
46
+ const { getFrameworkDir } = await import("../utils/memory.js");
47
47
  const projectRoot = process.env.ATABEY_PROJECT_ROOT || process.cwd();
48
48
  const fwDir = getFrameworkDir();
49
49
  const p = path.isAbsolute(fwDir)
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Enterprise Base Error class for the Agent Atabey Framework.
3
+ */
4
+ export class AtabeyBaseError extends Error {
5
+ code;
6
+ timestamp;
7
+ details;
8
+ solution;
9
+ constructor(message, code = "ATABEY_INTERNAL_ERROR", details, solution) {
10
+ super(message);
11
+ this.name = this.constructor.name;
12
+ this.code = code;
13
+ this.timestamp = new Date();
14
+ this.details = details;
15
+ this.solution = solution;
16
+ // Ensure proper prototype chain and capture stack trace
17
+ Object.setPrototypeOf(this, new.target.prototype);
18
+ if (Error.captureStackTrace) {
19
+ Error.captureStackTrace(this, this.constructor);
20
+ }
21
+ }
22
+ /**
23
+ * Converts the error into a structured JSON log format.
24
+ */
25
+ toJSON() {
26
+ return {
27
+ name: this.name,
28
+ message: this.message,
29
+ code: this.code,
30
+ timestamp: this.timestamp.toISOString(),
31
+ details: this.details,
32
+ solution: this.solution,
33
+ stack: this.stack,
34
+ };
35
+ }
36
+ }
37
+ /**
38
+ * Thrown when configuration loading or validation fails.
39
+ */
40
+ export class ConfigurationError extends AtabeyBaseError {
41
+ constructor(message, details, solution) {
42
+ super(message, "CONFIGURATION_ERROR", details, solution);
43
+ }
44
+ }
45
+ /**
46
+ * Thrown when data schema or payload validation fails.
47
+ */
48
+ export class ValidationError extends AtabeyBaseError {
49
+ constructor(message, details, solution) {
50
+ super(message, "VALIDATION_ERROR", details, solution);
51
+ }
52
+ }
53
+ /**
54
+ * Thrown when adapter initialization or execution fails.
55
+ */
56
+ export class AdapterError extends AtabeyBaseError {
57
+ constructor(message, adapterId, details, solution) {
58
+ super(`Adapter '${adapterId}' failure: ${message}`, "ADAPTER_ERROR", details, solution);
59
+ }
60
+ }
61
+ /**
62
+ * Thrown when orchestration or agent communication fails.
63
+ */
64
+ export class OrchestrationError extends AtabeyBaseError {
65
+ constructor(message, details, solution) {
66
+ super(message, "ORCHESTRATION_ERROR", details, solution);
67
+ }
68
+ }
@@ -0,0 +1,74 @@
1
+ import fs from "fs";
2
+ import os from "os";
3
+ import path from "path";
4
+ const CWD = process.cwd();
5
+ const HOME = os.homedir();
6
+ const FRAMEWORK = {
7
+ CORE_DIR: ".atabey",
8
+ };
9
+ const FRAMEWORK_DIR_CANDIDATES = [
10
+ ".atabey",
11
+ ".agents",
12
+ ".claude",
13
+ ".gemini",
14
+ ".grok",
15
+ ".cursor",
16
+ ];
17
+ const MCP = {
18
+ TEST_DIR_ENV: "ATABEY_TEST_DIR",
19
+ };
20
+ function findFrameworkDir(basePath) {
21
+ try {
22
+ const pkgPath = path.join(basePath, "package.json");
23
+ if (fs.existsSync(pkgPath)) {
24
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
25
+ if (pkg.atabey && typeof pkg.atabey.frameworkDir === "string") {
26
+ const customDir = path.join(basePath, pkg.atabey.frameworkDir);
27
+ if (fs.existsSync(customDir))
28
+ return customDir;
29
+ }
30
+ }
31
+ }
32
+ catch {
33
+ // ignore
34
+ }
35
+ return null;
36
+ }
37
+ export function isFrameworkDevelopmentRepo() {
38
+ try {
39
+ const pkgPath = path.join(CWD, "package.json");
40
+ if (fs.existsSync(pkgPath)) {
41
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
42
+ if (pkg.name === "atabey") {
43
+ return true;
44
+ }
45
+ }
46
+ }
47
+ catch {
48
+ // ignore
49
+ }
50
+ return false;
51
+ }
52
+ export function getConfigDir() {
53
+ const localDir = findFrameworkDir(CWD);
54
+ if (localDir)
55
+ return localDir;
56
+ // Check for standard local directories if package.json doesn't specify
57
+ const localCandidates = [...FRAMEWORK_DIR_CANDIDATES, ".agent"];
58
+ for (const cand of localCandidates) {
59
+ const p = path.join(CWD, cand);
60
+ if (fs.existsSync(p))
61
+ return p;
62
+ }
63
+ // In dev repo, don't fall back to global dir. Point to local default.
64
+ if (isFrameworkDevelopmentRepo()) {
65
+ return path.join(CWD, FRAMEWORK.CORE_DIR);
66
+ }
67
+ return path.join(HOME, FRAMEWORK.CORE_DIR);
68
+ }
69
+ export function getFrameworkDir() {
70
+ const testDir = process.env[MCP.TEST_DIR_ENV];
71
+ if (testDir)
72
+ return testDir;
73
+ return getConfigDir();
74
+ }
@@ -0,0 +1,207 @@
1
+ import Database from "better-sqlite3";
2
+ import path from "path";
3
+ import fs from "fs";
4
+ import { getFrameworkDir } from "./memory.js";
5
+ /**
6
+ * [DB] Atabey Storage Engine
7
+ * Central SQLite database for enterprise-scale agent state management.
8
+ */
9
+ export class Storage {
10
+ static db = null;
11
+ static getDB() {
12
+ if (!this.db) {
13
+ const frameworkDir = getFrameworkDir();
14
+ if (!fs.existsSync(frameworkDir)) {
15
+ fs.mkdirSync(frameworkDir, { recursive: true });
16
+ }
17
+ const dbPath = path.join(frameworkDir, "atabey.db");
18
+ this.db = new Database(dbPath);
19
+ this.initializeSchema();
20
+ }
21
+ return this.db;
22
+ }
23
+ static initializeSchema() {
24
+ const db = this.db;
25
+ // Agents Table
26
+ db.exec(`
27
+ CREATE TABLE IF NOT EXISTS agents (
28
+ name TEXT PRIMARY KEY,
29
+ state TEXT DEFAULT 'READY',
30
+ task TEXT DEFAULT 'Idle',
31
+ last_updated DATETIME DEFAULT CURRENT_TIMESTAMP
32
+ )
33
+ `);
34
+ // Messages (Hermes) Table
35
+ db.exec(`
36
+ CREATE TABLE IF NOT EXISTS messages (
37
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
38
+ timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
39
+ sender TEXT,
40
+ receiver TEXT,
41
+ category TEXT,
42
+ content TEXT,
43
+ trace_id TEXT,
44
+ parent_id TEXT,
45
+ status TEXT DEFAULT 'PENDING',
46
+ priority TEXT DEFAULT 'NORMAL',
47
+ requires_approval BOOLEAN DEFAULT 0
48
+ )
49
+ `);
50
+ // Tasks Table
51
+ db.exec(`
52
+ CREATE TABLE IF NOT EXISTS tasks (
53
+ id TEXT PRIMARY KEY,
54
+ trace_id TEXT,
55
+ description TEXT,
56
+ agent TEXT,
57
+ status TEXT DEFAULT 'PENDING',
58
+ priority TEXT DEFAULT 'NORMAL',
59
+ dependencies TEXT, -- JSON Array
60
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
61
+ )
62
+ `);
63
+ // Logs Table
64
+ db.exec(`
65
+ CREATE TABLE IF NOT EXISTS logs (
66
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
67
+ timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
68
+ agent TEXT,
69
+ action TEXT,
70
+ trace_id TEXT,
71
+ status TEXT,
72
+ summary TEXT,
73
+ findings TEXT
74
+ )
75
+ `);
76
+ // Metadata (State) Table
77
+ db.exec(`
78
+ CREATE TABLE IF NOT EXISTS metadata (
79
+ key TEXT PRIMARY KEY,
80
+ value TEXT
81
+ )
82
+ `);
83
+ }
84
+ // --- Agent Operations ---
85
+ static updateAgentStatus(name, state, task, lastUpdated) {
86
+ const db = this.getDB();
87
+ const cleanName = name.replace("@", "");
88
+ const timestamp = lastUpdated || new Date().toISOString();
89
+ db.prepare(`
90
+ INSERT INTO agents (name, state, task, last_updated)
91
+ VALUES (?, ?, ?, ?)
92
+ ON CONFLICT(name) DO UPDATE SET
93
+ state = excluded.state,
94
+ task = excluded.task,
95
+ last_updated = excluded.last_updated
96
+ `).run(cleanName, state, task, timestamp);
97
+ }
98
+ static getAllAgents() {
99
+ return this.getDB().prepare("SELECT * FROM agents").all();
100
+ }
101
+ // --- Message Operations ---
102
+ static saveMessage(msg) {
103
+ const db = this.getDB();
104
+ db.prepare(`
105
+ INSERT INTO messages (sender, receiver, category, content, trace_id, parent_id, status, priority, requires_approval)
106
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
107
+ `).run(msg.from, msg.to, msg.category, msg.content, msg.traceId, msg.parentId || null, msg.status || "PENDING", msg.priority || "NORMAL", msg.requiresApproval ? 1 : 0);
108
+ }
109
+ static getPendingMessages() {
110
+ const rows = this.getDB().prepare("SELECT * FROM messages WHERE status IN ('PENDING', 'APPROVED') ORDER BY priority DESC, timestamp ASC").all();
111
+ return rows.map(r => ({
112
+ id: r.id,
113
+ timestamp: r.timestamp,
114
+ from: r.sender,
115
+ to: r.receiver,
116
+ category: r.category,
117
+ content: r.content,
118
+ traceId: r.trace_id,
119
+ parentId: r.parent_id || undefined,
120
+ status: r.status,
121
+ priority: r.priority,
122
+ requiresApproval: r.requires_approval === 1
123
+ }));
124
+ }
125
+ static updateMessageStatus(id, status) {
126
+ this.getDB().prepare("UPDATE messages SET status = ? WHERE id = ?").run(status, id);
127
+ }
128
+ // --- Task Operations ---
129
+ static saveTask(task) {
130
+ const db = this.getDB();
131
+ db.prepare(`
132
+ INSERT INTO tasks (id, trace_id, description, agent, status, priority, dependencies)
133
+ VALUES (?, ?, ?, ?, ?, ?, ?)
134
+ ON CONFLICT(id) DO UPDATE SET
135
+ status = excluded.status,
136
+ description = excluded.description
137
+ `).run(task.id, task.traceId, task.description, task.agent, task.status, task.priority, JSON.stringify(task.dependencies || []));
138
+ }
139
+ static getTasks(traceId) {
140
+ const db = this.getDB();
141
+ let rows;
142
+ if (traceId) {
143
+ rows = db.prepare("SELECT * FROM tasks WHERE trace_id = ?").all(traceId);
144
+ }
145
+ else {
146
+ rows = db.prepare("SELECT * FROM tasks").all();
147
+ }
148
+ return rows.map(r => {
149
+ let deps = [];
150
+ try {
151
+ const parsed = JSON.parse(r.dependencies || "[]");
152
+ // Handle cases where dependencies might be double-stringified or are raw JSON strings
153
+ deps = Array.isArray(parsed) ? parsed : JSON.parse(parsed);
154
+ }
155
+ catch {
156
+ // Keep empty array
157
+ }
158
+ return {
159
+ id: r.id,
160
+ traceId: r.trace_id,
161
+ description: r.description,
162
+ agent: r.agent,
163
+ status: r.status,
164
+ priority: r.priority,
165
+ dependencies: deps
166
+ };
167
+ });
168
+ }
169
+ static getLogs(agentName) {
170
+ const db = this.getDB();
171
+ let rows;
172
+ const cleanName = agentName ? agentName.replace("@", "") : undefined;
173
+ if (cleanName) {
174
+ rows = db.prepare("SELECT * FROM logs WHERE agent = ? ORDER BY timestamp DESC").all(cleanName);
175
+ }
176
+ else {
177
+ rows = db.prepare("SELECT * FROM logs ORDER BY timestamp DESC").all();
178
+ }
179
+ return rows.map(r => ({
180
+ id: r.id,
181
+ timestamp: r.timestamp,
182
+ agent: r.agent,
183
+ action: r.action,
184
+ trace_id: r.trace_id || undefined,
185
+ status: r.status,
186
+ summary: r.summary,
187
+ findings: r.findings || undefined
188
+ }));
189
+ }
190
+ // --- Metadata Operations ---
191
+ static setMetadata(key, value) {
192
+ this.getDB().prepare(`
193
+ INSERT INTO metadata (key, value) VALUES (?, ?)
194
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value
195
+ `).run(key, value);
196
+ }
197
+ static getMetadata(key) {
198
+ const row = this.getDB().prepare("SELECT value FROM metadata WHERE key = ?").get(key);
199
+ return row ? row.value : null;
200
+ }
201
+ static reset() {
202
+ if (this.db) {
203
+ this.db.close();
204
+ this.db = null;
205
+ }
206
+ }
207
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Agent Atabey Framework — Internal Branded Types
3
+ * Used to enforce absolute type safety within the core orchestration logic.
4
+ */
5
+ /**
6
+ * Casts a raw string to a Branded Type.
7
+ * Use this only at the boundaries of the system.
8
+ */
9
+ export function asTraceID(val) { return val; }
10
+ export function asAgentID(val) { return val; }
11
+ export function asPhaseID(val) { return val; }
12
+ export function asProjectPath(val) { return val; }
@@ -4,55 +4,39 @@ import path from "path";
4
4
  import { fileURLToPath } from "url";
5
5
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
6
6
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
- import {
8
- CallToolRequestSchema,
9
- ListToolsRequestSchema,
10
- ListResourcesRequestSchema,
11
- ReadResourceRequestSchema,
12
- } from "@modelcontextprotocol/sdk/types.js";
13
-
14
-
7
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
15
8
  import { TOOLS, toolHandlers } from "./tools/index.js";
16
9
  import { RESOURCES, handleReadResource } from "./resources/index.js";
17
-
18
-
19
10
  // ─── Server Setup ─────────────────────────────────────────────────
20
-
21
11
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
22
-
23
12
  // Robustly find package.json by walking up from __dirname
24
- function findPackageJson(startDir: string): string {
13
+ function findPackageJson(startDir) {
25
14
  let currentDir = startDir;
26
15
  while (currentDir !== path.parse(currentDir).root) {
27
16
  const pkgPath = path.join(currentDir, "package.json");
28
- if (fs.existsSync(pkgPath)) return pkgPath;
17
+ if (fs.existsSync(pkgPath))
18
+ return pkgPath;
29
19
  currentDir = path.dirname(currentDir);
30
20
  }
31
21
  throw new Error("Could not find package.json for atabey-mcp");
32
22
  }
33
-
34
23
  const pkgPath = findPackageJson(__dirname);
35
24
  const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
36
25
  const serverVersion = pkg.version;
37
-
38
- const server = new Server(
39
- {
40
- name: "atabey-mcp",
41
- version: serverVersion,
26
+ const server = new Server({
27
+ name: "atabey-mcp",
28
+ version: serverVersion,
29
+ }, {
30
+ capabilities: {
31
+ tools: {},
32
+ resources: {},
42
33
  },
43
- {
44
- capabilities: {
45
- tools: {},
46
- resources: {},
47
- },
48
- }
49
- );
50
-
34
+ });
51
35
  // Basic Schema Validator for Required Fields
52
- function validateArgs(toolName: string, args: Record<string, unknown>): string | null {
36
+ function validateArgs(toolName, args) {
53
37
  const definition = TOOLS.find(t => t.name === toolName);
54
- if (!definition) return `Unknown tool: ${toolName}`;
55
-
38
+ if (!definition)
39
+ return `Unknown tool: ${toolName}`;
56
40
  const required = definition.inputSchema.required || [];
57
41
  for (const field of required) {
58
42
  if (args[field] === undefined || args[field] === null || args[field] === "") {
@@ -61,22 +45,19 @@ function validateArgs(toolName: string, args: Record<string, unknown>): string |
61
45
  }
62
46
  return null;
63
47
  }
64
-
65
48
  server.setRequestHandler(ListToolsRequestSchema, async (request) => {
66
49
  // 2026 Stateless Spec: Log client info from metadata if available
67
- const meta = (request as { _meta?: { client?: { name?: string; version?: string } } })._meta;
50
+ const meta = request._meta;
68
51
  if (meta) {
69
52
  process.stderr.write(`[MCP] Stateless ListTools from ${meta.client?.name || "unknown"} v${meta.client?.version || "?.?"}\n`);
70
53
  }
71
54
  return { tools: TOOLS };
72
55
  });
73
-
74
56
  server.setRequestHandler(ListResourcesRequestSchema, async () => {
75
57
  return { resources: RESOURCES };
76
58
  });
77
-
78
59
  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
79
- const uri = (request as { params: { uri: string } }).params.uri;
60
+ const uri = request.params.uri;
80
61
  try {
81
62
  const content = await handleReadResource(uri);
82
63
  return {
@@ -88,84 +69,75 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
88
69
  },
89
70
  ],
90
71
  };
91
- } catch (error: unknown) {
72
+ }
73
+ catch (error) {
92
74
  const message = error instanceof Error ? error.message : String(error);
93
75
  throw new Error(`Failed to read resource: ${message}`, { cause: error });
94
76
  }
95
77
  });
96
-
97
78
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
98
- const req = request as { params: { name: string, arguments?: Record<string, unknown> } };
79
+ const req = request;
99
80
  const { name, arguments: args } = req.params;
100
- const meta = (request as { _meta?: { client?: { name?: string; version?: string } } })._meta;
101
-
81
+ const meta = request._meta;
102
82
  // 2026 Stateless Spec: Prioritize metadata-driven context
103
83
  if (meta) {
104
84
  process.stderr.write(`[MCP] Stateless CallTool: ${name} (Client: ${meta.client?.name || "unknown"})\n`);
105
85
  }
106
-
107
86
  const projectRoot = process.env.ATABEY_PROJECT_ROOT || process.cwd();
108
-
109
87
  try {
110
88
  const handler = toolHandlers[name];
111
89
  if (!handler) {
112
90
  return {
113
91
  isError: true,
114
- content: [{ type: "text" as const, text: `[ERROR] Unknown tool: ${name}` }],
92
+ content: [{ type: "text", text: `[ERROR] Unknown tool: ${name}` }],
115
93
  };
116
94
  }
117
-
118
95
  // [SECURITY] Runtime Validation
119
96
  const validationError = validateArgs(name, args || {});
120
97
  if (validationError) {
121
98
  return {
122
99
  isError: true,
123
- content: [{ type: "text" as const, text: `[ERROR] Validation Error: ${validationError}` }],
100
+ content: [{ type: "text", text: `[ERROR] Validation Error: ${validationError}` }],
124
101
  };
125
102
  }
126
-
127
103
  return await handler(projectRoot, args || {});
128
- } catch (error: unknown) {
104
+ }
105
+ catch (error) {
129
106
  const message = error instanceof Error ? error.message : "Unknown error occurred";
130
107
  return {
131
108
  isError: true,
132
- content: [{ type: "text" as const, text: `[ERROR] Execution failed: ${message}` }],
109
+ content: [{ type: "text", text: `[ERROR] Execution failed: ${message}` }],
133
110
  };
134
111
  }
135
112
  });
136
-
137
113
  // ─── Graceful Startup & Shutdown ──────────────────────────────────
138
-
139
114
  async function run() {
140
115
  const transport = new StdioServerTransport();
141
-
142
116
  // Prevent unhandled errors from crashing the MCP stream
143
- process.on("uncaughtException", (error: Error) => {
117
+ process.on("uncaughtException", (error) => {
144
118
  process.stderr.write(`[atabey-mcp] Uncaught exception: ${error.message}
145
119
  `);
146
120
  });
147
- process.on("unhandledRejection", (reason: unknown) => {
121
+ process.on("unhandledRejection", (reason) => {
148
122
  const message = reason instanceof Error ? reason.message : String(reason);
149
123
  process.stderr.write(`[atabey-mcp] Unhandled rejection: ${message}
150
124
  `);
151
125
  });
152
-
153
126
  // Graceful shutdown on SIGINT/SIGTERM
154
127
  const shutdown = async () => {
155
128
  try {
156
129
  await server.close();
157
- } catch {
130
+ }
131
+ catch {
158
132
  // Already closed or failed — safe to ignore
159
133
  }
160
134
  process.exit(0);
161
135
  };
162
136
  process.on("SIGINT", shutdown);
163
137
  process.on("SIGTERM", shutdown);
164
-
165
138
  await server.connect(transport);
166
139
  }
167
-
168
- run().catch((error: Error) => {
140
+ run().catch((error) => {
169
141
  process.stderr.write(`[atabey-mcp] Fatal startup error: ${error.message}
170
142
  `);
171
143
  process.exit(1);