mcp-architector 1.0.0

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.
package/src/storage.ts ADDED
@@ -0,0 +1,203 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import os from 'node:os';
4
+ import type { ProjectArchitecture, ModuleDetails, ScriptDocumentation } from './types.js';
5
+
6
+ const STORAGE_BASE_DIR = path.join(os.homedir(), '.mcp-architector');
7
+
8
+ /**
9
+ * Get the storage directory for a specific project
10
+ */
11
+ export function getProjectDir(projectId: string): string {
12
+ return path.join(STORAGE_BASE_DIR, projectId);
13
+ }
14
+
15
+ /**
16
+ * Get the path to the project architecture file
17
+ */
18
+ export function getArchitectureFile(projectId: string): string {
19
+ return path.join(getProjectDir(projectId), 'architecture.json');
20
+ }
21
+
22
+ /**
23
+ * Get the path to a module details file
24
+ */
25
+ export function getModuleFile(projectId: string, moduleId: string): string {
26
+ return path.join(getProjectDir(projectId), 'modules', `${moduleId}.json`);
27
+ }
28
+
29
+ /**
30
+ * Ensure the storage directory structure exists
31
+ */
32
+ async function ensureDirectoryExists(dir: string): Promise<void> {
33
+ try {
34
+ await fs.access(dir);
35
+ } catch {
36
+ await fs.mkdir(dir, { recursive: true });
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Initialize storage for a project
42
+ */
43
+ export async function initializeProjectStorage(projectId: string): Promise<void> {
44
+ const projectDir = getProjectDir(projectId);
45
+ await ensureDirectoryExists(projectDir);
46
+ await ensureDirectoryExists(path.join(projectDir, 'modules'));
47
+ }
48
+
49
+ /**
50
+ * Read project architecture from storage
51
+ */
52
+ export async function readArchitecture(projectId: string): Promise<ProjectArchitecture | null> {
53
+ try {
54
+ const filePath = getArchitectureFile(projectId);
55
+ const content = await fs.readFile(filePath, 'utf-8');
56
+ return JSON.parse(content) as ProjectArchitecture;
57
+ } catch (error) {
58
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
59
+ return null;
60
+ }
61
+ throw error;
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Write project architecture to storage
67
+ */
68
+ export async function writeArchitecture(
69
+ projectId: string,
70
+ architecture: ProjectArchitecture
71
+ ): Promise<void> {
72
+ await initializeProjectStorage(projectId);
73
+ const filePath = getArchitectureFile(projectId);
74
+ await fs.writeFile(filePath, JSON.stringify(architecture, null, 2), 'utf-8');
75
+ }
76
+
77
+ /**
78
+ * Read module details from storage
79
+ */
80
+ export async function readModule(projectId: string, moduleId: string): Promise<ModuleDetails | null> {
81
+ try {
82
+ const filePath = getModuleFile(projectId, moduleId);
83
+ const content = await fs.readFile(filePath, 'utf-8');
84
+ return JSON.parse(content) as ModuleDetails;
85
+ } catch (error) {
86
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
87
+ return null;
88
+ }
89
+ throw error;
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Write module details to storage
95
+ */
96
+ export async function writeModule(
97
+ projectId: string,
98
+ moduleDetails: ModuleDetails
99
+ ): Promise<void> {
100
+ await initializeProjectStorage(projectId);
101
+ const filePath = getModuleFile(projectId, moduleDetails.moduleId);
102
+ await fs.writeFile(filePath, JSON.stringify(moduleDetails, null, 2), 'utf-8');
103
+ }
104
+
105
+ /**
106
+ * List all modules in a project
107
+ */
108
+ export async function listModules(projectId: string): Promise<string[]> {
109
+ try {
110
+ const modulesDir = path.join(getProjectDir(projectId), 'modules');
111
+ const files = await fs.readdir(modulesDir);
112
+ return files
113
+ .filter(file => file.endsWith('.json'))
114
+ .map(file => file.replace('.json', ''));
115
+ } catch (error) {
116
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
117
+ return [];
118
+ }
119
+ throw error;
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Delete a module
125
+ */
126
+ export async function deleteModule(projectId: string, moduleId: string): Promise<void> {
127
+ const filePath = getModuleFile(projectId, moduleId);
128
+ try {
129
+ await fs.unlink(filePath);
130
+ } catch (error) {
131
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
132
+ throw error;
133
+ }
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Get the path to a script documentation file
139
+ */
140
+ export function getScriptFile(projectId: string, scriptId: string): string {
141
+ return path.join(getProjectDir(projectId), 'scripts', `${scriptId}.json`);
142
+ }
143
+
144
+ /**
145
+ * Read script documentation from storage
146
+ */
147
+ export async function readScript(projectId: string, scriptId: string): Promise<ScriptDocumentation | null> {
148
+ try {
149
+ const filePath = getScriptFile(projectId, scriptId);
150
+ const content = await fs.readFile(filePath, 'utf-8');
151
+ return JSON.parse(content) as ScriptDocumentation;
152
+ } catch (error) {
153
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
154
+ return null;
155
+ }
156
+ throw error;
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Write script documentation to storage
162
+ */
163
+ export async function writeScript(
164
+ projectId: string,
165
+ scriptDoc: ScriptDocumentation
166
+ ): Promise<void> {
167
+ await initializeProjectStorage(projectId);
168
+ // Ensure scripts directory exists
169
+ await ensureDirectoryExists(path.join(getProjectDir(projectId), 'scripts'));
170
+ const filePath = getScriptFile(projectId, scriptDoc.scriptId);
171
+ await fs.writeFile(filePath, JSON.stringify(scriptDoc, null, 2), 'utf-8');
172
+ }
173
+
174
+ /**
175
+ * List all scripts in a project
176
+ */
177
+ export async function listScripts(projectId: string): Promise<string[]> {
178
+ try {
179
+ const scriptsDir = path.join(getProjectDir(projectId), 'scripts');
180
+ const files = await fs.readdir(scriptsDir);
181
+ return files
182
+ .filter(file => file.endsWith('.json'))
183
+ .map(file => file.replace('.json', ''));
184
+ } catch (error) {
185
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
186
+ return [];
187
+ }
188
+ throw error;
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Normalize project ID from workdir or user input
194
+ */
195
+ export function normalizeProjectId(workdir?: string): string {
196
+ if (!workdir || workdir === '') {
197
+ throw new Error('Project ID is required (workdir context)');
198
+ }
199
+
200
+ // Use workdir as project ID, normalized for filesystem
201
+ return workdir.replace(/[^a-zA-Z0-9_-]/g, '_');
202
+ }
203
+
package/src/types.ts ADDED
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Type definitions for MCP Architector
3
+ */
4
+
5
+ export interface DataFlow {
6
+ [moduleName: string]: {
7
+ dependsOn?: string[];
8
+ providesTo?: string[];
9
+ dataTransformation?: string;
10
+ };
11
+ }
12
+
13
+ export interface ProjectArchitecture {
14
+ projectId: string;
15
+ description: string;
16
+ modules: ModuleSummary[];
17
+ dataFlow?: DataFlow;
18
+ createdAt: string;
19
+ updatedAt: string;
20
+ }
21
+
22
+ export interface ModuleSummary {
23
+ id: string;
24
+ name: string;
25
+ description: string;
26
+ inputs?: string;
27
+ outputs?: string;
28
+ createdAt: string;
29
+ updatedAt: string;
30
+ }
31
+
32
+ export interface UsageExample {
33
+ title: string;
34
+ description?: string;
35
+ command?: string;
36
+ input?: string;
37
+ output?: string;
38
+ notes?: string;
39
+ }
40
+
41
+ export interface ScriptDocumentation {
42
+ scriptId: string;
43
+ scriptName: string;
44
+ description: string;
45
+ usage: string;
46
+ examples: string[];
47
+ parameters: Record<string, string>; // parameter name -> description
48
+ notes?: string;
49
+ createdAt: string;
50
+ updatedAt: string;
51
+ }
52
+
53
+ export interface ModuleDetails {
54
+ moduleId: string;
55
+ name: string;
56
+ description: string;
57
+ inputs: string;
58
+ outputs: string;
59
+ dependencies?: string[];
60
+ files?: string[];
61
+ usageExamples?: UsageExample[];
62
+ notes?: string;
63
+ createdAt: string;
64
+ updatedAt: string;
65
+ }
66
+
package/tsconfig.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "Node16",
5
+ "lib": ["ES2022", "DOM"],
6
+ "moduleResolution": "Node16",
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "declaration": true,
15
+ "declarationMap": true,
16
+ "sourceMap": true
17
+ },
18
+ "include": ["src/**/*"],
19
+ "exclude": ["node_modules", "dist"]
20
+ }
21
+