@prmichaelsen/acp-mcp 0.7.1 → 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/CHANGELOG.md +57 -0
- package/README.md +121 -41
- package/agent/progress.yaml +29 -5
- package/dist/server-factory.js +2 -496
- package/dist/server-factory.js.map +4 -4
- package/dist/server.js +2 -496
- package/dist/server.js.map +4 -4
- package/dist/utils/ssh-connection.d.ts +0 -40
- package/package.json +1 -1
- package/src/server-factory.ts +2 -12
- package/src/server.ts +2 -11
- package/src/utils/ssh-connection.ts +1 -304
- package/dist/tools/acp-remote-list-files.d.ts +0 -16
- package/dist/tools/acp-remote-read-file.d.ts +0 -16
- package/dist/tools/acp-remote-write-file.d.ts +0 -16
- package/dist/types/file-entry.d.ts +0 -88
- package/src/tools/acp-remote-list-files.ts +0 -100
- package/src/tools/acp-remote-read-file.ts +0 -94
- package/src/tools/acp-remote-write-file.ts +0 -107
- package/src/types/file-entry.ts +0 -123
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import { SSHConnectionManager } from '../utils/ssh-connection.js';
|
|
3
|
-
import { logger } from '../utils/logger.js';
|
|
4
|
-
|
|
5
|
-
export const acpRemoteWriteFileTool: Tool = {
|
|
6
|
-
name: 'acp_remote_write_file',
|
|
7
|
-
description: 'Write file contents to the remote machine via SSH',
|
|
8
|
-
inputSchema: {
|
|
9
|
-
type: 'object',
|
|
10
|
-
properties: {
|
|
11
|
-
path: {
|
|
12
|
-
type: 'string',
|
|
13
|
-
description: 'Absolute path to file',
|
|
14
|
-
},
|
|
15
|
-
content: {
|
|
16
|
-
type: 'string',
|
|
17
|
-
description: 'File contents to write',
|
|
18
|
-
},
|
|
19
|
-
encoding: {
|
|
20
|
-
type: 'string',
|
|
21
|
-
description: 'File encoding (default: utf-8)',
|
|
22
|
-
default: 'utf-8',
|
|
23
|
-
},
|
|
24
|
-
createDirs: {
|
|
25
|
-
type: 'boolean',
|
|
26
|
-
description: 'Create parent directories if they don\'t exist (default: false)',
|
|
27
|
-
default: false,
|
|
28
|
-
},
|
|
29
|
-
backup: {
|
|
30
|
-
type: 'boolean',
|
|
31
|
-
description: 'Backup existing file before overwriting (default: false)',
|
|
32
|
-
default: false,
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
required: ['path', 'content'],
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
interface WriteFileArgs {
|
|
40
|
-
path: string;
|
|
41
|
-
content: string;
|
|
42
|
-
encoding?: string;
|
|
43
|
-
createDirs?: boolean;
|
|
44
|
-
backup?: boolean;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
interface WriteFileResult {
|
|
48
|
-
success: boolean;
|
|
49
|
-
bytesWritten: number;
|
|
50
|
-
backupPath?: string;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Handle the acp_remote_write_file tool invocation
|
|
55
|
-
* Writes file contents to the remote machine via SSH
|
|
56
|
-
*
|
|
57
|
-
* @param args - Tool arguments containing path, content, and options
|
|
58
|
-
* @param sshConnection - SSH connection manager for remote operations
|
|
59
|
-
*/
|
|
60
|
-
export async function handleAcpRemoteWriteFile(
|
|
61
|
-
args: any,
|
|
62
|
-
sshConnection: SSHConnectionManager
|
|
63
|
-
): Promise<{ content: Array<{ type: string; text: string }> }> {
|
|
64
|
-
const { path, content, encoding = 'utf-8', createDirs = false, backup = false } = args as WriteFileArgs;
|
|
65
|
-
|
|
66
|
-
logger.debug('Writing remote file', { path, contentSize: content.length, encoding, createDirs, backup });
|
|
67
|
-
|
|
68
|
-
try {
|
|
69
|
-
const result = await sshConnection.writeFile(path, content, {
|
|
70
|
-
encoding,
|
|
71
|
-
createDirs,
|
|
72
|
-
backup,
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
logger.debug('File write successful', { path, bytesWritten: result.bytesWritten, backupPath: result.backupPath });
|
|
76
|
-
|
|
77
|
-
const output: WriteFileResult = {
|
|
78
|
-
success: result.success,
|
|
79
|
-
bytesWritten: result.bytesWritten,
|
|
80
|
-
backupPath: result.backupPath,
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
content: [
|
|
85
|
-
{
|
|
86
|
-
type: 'text',
|
|
87
|
-
text: JSON.stringify(output, null, 2),
|
|
88
|
-
},
|
|
89
|
-
],
|
|
90
|
-
};
|
|
91
|
-
} catch (error) {
|
|
92
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
93
|
-
logger.error('File write error', { path, error: errorMessage });
|
|
94
|
-
return {
|
|
95
|
-
content: [
|
|
96
|
-
{
|
|
97
|
-
type: 'text',
|
|
98
|
-
text: JSON.stringify({
|
|
99
|
-
success: false,
|
|
100
|
-
bytesWritten: 0,
|
|
101
|
-
error: errorMessage,
|
|
102
|
-
}, null, 2),
|
|
103
|
-
},
|
|
104
|
-
],
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
}
|
package/src/types/file-entry.ts
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Comprehensive file entry with metadata
|
|
3
|
-
*/
|
|
4
|
-
export interface FileEntry {
|
|
5
|
-
/** Filename (without path) */
|
|
6
|
-
name: string;
|
|
7
|
-
|
|
8
|
-
/** Absolute path to file */
|
|
9
|
-
path: string;
|
|
10
|
-
|
|
11
|
-
/** File type */
|
|
12
|
-
type: 'file' | 'directory' | 'symlink' | 'other';
|
|
13
|
-
|
|
14
|
-
/** File size in bytes */
|
|
15
|
-
size: number;
|
|
16
|
-
|
|
17
|
-
/** File permissions */
|
|
18
|
-
permissions: {
|
|
19
|
-
/** Octal mode (e.g., 0o644) */
|
|
20
|
-
mode: number;
|
|
21
|
-
|
|
22
|
-
/** Human-readable string (e.g., "rw-r--r--") */
|
|
23
|
-
string: string;
|
|
24
|
-
|
|
25
|
-
/** Owner permissions */
|
|
26
|
-
owner: {
|
|
27
|
-
read: boolean;
|
|
28
|
-
write: boolean;
|
|
29
|
-
execute: boolean;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
/** Group permissions */
|
|
33
|
-
group: {
|
|
34
|
-
read: boolean;
|
|
35
|
-
write: boolean;
|
|
36
|
-
execute: boolean;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
/** Others permissions */
|
|
40
|
-
others: {
|
|
41
|
-
read: boolean;
|
|
42
|
-
write: boolean;
|
|
43
|
-
execute: boolean;
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
/** File ownership */
|
|
48
|
-
owner: {
|
|
49
|
-
/** User ID */
|
|
50
|
-
uid: number;
|
|
51
|
-
|
|
52
|
-
/** Group ID */
|
|
53
|
-
gid: number;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
/** File timestamps */
|
|
57
|
-
timestamps: {
|
|
58
|
-
/** Last access time (ISO 8601) */
|
|
59
|
-
accessed: string;
|
|
60
|
-
|
|
61
|
-
/** Last modification time (ISO 8601) */
|
|
62
|
-
modified: string;
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Convert Unix mode to human-readable permission string
|
|
68
|
-
* @param mode - Unix file mode (e.g., 33188 for -rw-r--r--)
|
|
69
|
-
* @returns Permission string (e.g., "rw-r--r--")
|
|
70
|
-
*/
|
|
71
|
-
export function modeToPermissionString(mode: number): string {
|
|
72
|
-
const perms = [
|
|
73
|
-
(mode & 0o400) ? 'r' : '-',
|
|
74
|
-
(mode & 0o200) ? 'w' : '-',
|
|
75
|
-
(mode & 0o100) ? 'x' : '-',
|
|
76
|
-
(mode & 0o040) ? 'r' : '-',
|
|
77
|
-
(mode & 0o020) ? 'w' : '-',
|
|
78
|
-
(mode & 0o010) ? 'x' : '-',
|
|
79
|
-
(mode & 0o004) ? 'r' : '-',
|
|
80
|
-
(mode & 0o002) ? 'w' : '-',
|
|
81
|
-
(mode & 0o001) ? 'x' : '-',
|
|
82
|
-
];
|
|
83
|
-
return perms.join('');
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Parse Unix mode into structured permissions object
|
|
88
|
-
* @param mode - Unix file mode
|
|
89
|
-
* @returns Structured permissions object
|
|
90
|
-
*/
|
|
91
|
-
export function parsePermissions(mode: number) {
|
|
92
|
-
return {
|
|
93
|
-
mode,
|
|
94
|
-
string: modeToPermissionString(mode),
|
|
95
|
-
owner: {
|
|
96
|
-
read: (mode & 0o400) !== 0,
|
|
97
|
-
write: (mode & 0o200) !== 0,
|
|
98
|
-
execute: (mode & 0o100) !== 0,
|
|
99
|
-
},
|
|
100
|
-
group: {
|
|
101
|
-
read: (mode & 0o040) !== 0,
|
|
102
|
-
write: (mode & 0o020) !== 0,
|
|
103
|
-
execute: (mode & 0o010) !== 0,
|
|
104
|
-
},
|
|
105
|
-
others: {
|
|
106
|
-
read: (mode & 0o004) !== 0,
|
|
107
|
-
write: (mode & 0o002) !== 0,
|
|
108
|
-
execute: (mode & 0o001) !== 0,
|
|
109
|
-
},
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Determine file type from SFTP stats
|
|
115
|
-
* @param stats - SFTP file stats
|
|
116
|
-
* @returns File type string
|
|
117
|
-
*/
|
|
118
|
-
export function getFileType(stats: any): 'file' | 'directory' | 'symlink' | 'other' {
|
|
119
|
-
if (stats.isDirectory()) return 'directory';
|
|
120
|
-
if (stats.isFile()) return 'file';
|
|
121
|
-
if (stats.isSymbolicLink()) return 'symlink';
|
|
122
|
-
return 'other';
|
|
123
|
-
}
|