@ebowwa/claude-code-config-mcp 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/.claude/CLAUDE.md +3 -0
- package/README.md +237 -0
- package/bun.lock +206 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1744 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +197 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +51 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/errors.d.ts +63 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +156 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/file.d.ts +32 -0
- package/dist/utils/file.d.ts.map +1 -0
- package/dist/utils/file.js +146 -0
- package/dist/utils/file.js.map +1 -0
- package/dist/utils/path.d.ts +59 -0
- package/dist/utils/path.d.ts.map +1 -0
- package/dist/utils/path.js +146 -0
- package/dist/utils/path.js.map +1 -0
- package/lmdb.db +0 -0
- package/lmdb.db-lock +0 -0
- package/package.json +43 -0
- package/src/index.js +2171 -0
- package/src/index.ts +1981 -0
- package/src/types.js +53 -0
- package/src/types.ts +237 -0
- package/src/utils/errors.js +231 -0
- package/src/utils/errors.ts +210 -0
- package/src/utils/file.js +251 -0
- package/src/utils/file.ts +174 -0
- package/src/utils/path.js +169 -0
- package/src/utils/path.ts +173 -0
- package/test/test.js +136 -0
- package/test/test.ts +79 -0
- package/test/write-test.js +153 -0
- package/test/write-test.ts +102 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// Path Utilities - Cross-platform path handling for Claude Code config
|
|
4
|
+
// ============================================================================
|
|
5
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
6
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
7
|
+
if (ar || !(i in from)) {
|
|
8
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
9
|
+
ar[i] = from[i];
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.getHomeDir = getHomeDir;
|
|
16
|
+
exports.getClaudeConfigDir = getClaudeConfigDir;
|
|
17
|
+
exports.getClaudeAppConfigDir = getClaudeAppConfigDir;
|
|
18
|
+
exports.getClaudeCliConfigPath = getClaudeCliConfigPath;
|
|
19
|
+
exports.getProjectClaudeDir = getProjectClaudeDir;
|
|
20
|
+
exports.getConfigPaths = getConfigPaths;
|
|
21
|
+
exports.validatePath = validatePath;
|
|
22
|
+
exports.pathExists = pathExists;
|
|
23
|
+
exports.getDisplayPath = getDisplayPath;
|
|
24
|
+
exports.getMCPConfigPaths = getMCPConfigPaths;
|
|
25
|
+
var node_path_1 = require("node:path");
|
|
26
|
+
var node_os_1 = require("node:os");
|
|
27
|
+
var node_fs_1 = require("node:fs");
|
|
28
|
+
/**
|
|
29
|
+
* Get home directory cross-platform
|
|
30
|
+
*/
|
|
31
|
+
function getHomeDir() {
|
|
32
|
+
return (0, node_os_1.homedir)();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get Claude Code global config directory (~/.claude)
|
|
36
|
+
*/
|
|
37
|
+
function getClaudeConfigDir() {
|
|
38
|
+
return (0, node_path_1.join)(getHomeDir(), '.claude');
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get Claude Code app config directory (~/.config/claude-code)
|
|
42
|
+
* This is where MCP servers are configured for the Claude Code app
|
|
43
|
+
*/
|
|
44
|
+
function getClaudeAppConfigDir() {
|
|
45
|
+
return (0, node_path_1.join)(getHomeDir(), '.config', 'claude-code');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get Claude CLI config file path (~/.claude.json)
|
|
49
|
+
* This is where MCP servers are configured for the claude CLI
|
|
50
|
+
*/
|
|
51
|
+
function getClaudeCliConfigPath() {
|
|
52
|
+
return (0, node_path_1.join)(getHomeDir(), '.claude.json');
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get project-local Claude Code config directory (.claude)
|
|
56
|
+
*/
|
|
57
|
+
function getProjectClaudeDir(cwd) {
|
|
58
|
+
if (cwd === void 0) { cwd = process.cwd(); }
|
|
59
|
+
return (0, node_path_1.join)(cwd, '.claude');
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Resolve Claude config file paths
|
|
63
|
+
*/
|
|
64
|
+
function getConfigPaths(cwd) {
|
|
65
|
+
if (cwd === void 0) { cwd = process.cwd(); }
|
|
66
|
+
var claudeDir = getClaudeConfigDir();
|
|
67
|
+
var claudeAppDir = getClaudeAppConfigDir();
|
|
68
|
+
var projectClaudeDir = getProjectClaudeDir(cwd);
|
|
69
|
+
return {
|
|
70
|
+
// Global config files
|
|
71
|
+
globalClaudeMd: (0, node_path_1.join)(claudeDir, 'CLAUDE.md'),
|
|
72
|
+
keybindings: (0, node_path_1.join)(claudeDir, 'keybindings.json'),
|
|
73
|
+
settings: (0, node_path_1.join)(claudeDir, 'settings.json'),
|
|
74
|
+
claudeJson: (0, node_path_1.join)(claudeDir, 'claude.json'),
|
|
75
|
+
mcpServers: (0, node_path_1.join)(claudeDir, 'mcp_servers.json'),
|
|
76
|
+
hooksDir: (0, node_path_1.join)(claudeDir, 'hooks'),
|
|
77
|
+
pluginsDir: (0, node_path_1.join)(claudeDir, 'plugins'),
|
|
78
|
+
// App config file (where MCP servers are actually configured)
|
|
79
|
+
appConfig: (0, node_path_1.join)(claudeAppDir, 'config.json'),
|
|
80
|
+
// Project-local config files
|
|
81
|
+
projectClaudeMd: (0, node_path_1.join)(projectClaudeDir, 'CLAUDE.md'),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Allowed base paths for security (whitelist)
|
|
86
|
+
*/
|
|
87
|
+
var ALLOWED_BASES = [
|
|
88
|
+
getClaudeConfigDir(),
|
|
89
|
+
getProjectClaudeDir(),
|
|
90
|
+
getClaudeAppConfigDir(),
|
|
91
|
+
getClaudeCliConfigPath(),
|
|
92
|
+
];
|
|
93
|
+
/**
|
|
94
|
+
* Validate and sanitize a file path
|
|
95
|
+
* Prevents path traversal attacks and ensures path is within allowed directories
|
|
96
|
+
*/
|
|
97
|
+
function validatePath(userPath, cwd) {
|
|
98
|
+
if (cwd === void 0) { cwd = process.cwd(); }
|
|
99
|
+
// Normalize path
|
|
100
|
+
var normalized = (0, node_path_1.normalize)(userPath.replace(/\0/g, ''));
|
|
101
|
+
// Resolve to absolute path
|
|
102
|
+
var absolute = (0, node_path_1.isAbsolute)(normalized)
|
|
103
|
+
? (0, node_path_1.resolve)(normalized)
|
|
104
|
+
: (0, node_path_1.resolve)(cwd, normalized);
|
|
105
|
+
// Check for path traversal attempts
|
|
106
|
+
if (normalized.includes('..')) {
|
|
107
|
+
throw new Error('Path traversal detected');
|
|
108
|
+
}
|
|
109
|
+
// Build allowed bases including the current project directory
|
|
110
|
+
var allowedBases = __spreadArray(__spreadArray([], ALLOWED_BASES, true), [
|
|
111
|
+
getClaudeConfigDir(),
|
|
112
|
+
getProjectClaudeDir(cwd),
|
|
113
|
+
], false);
|
|
114
|
+
// Check if path is within allowed bases
|
|
115
|
+
// For files that don't exist yet, check the parent directory
|
|
116
|
+
var checkPath = absolute;
|
|
117
|
+
while (checkPath !== '/' && checkPath !== cwd && checkPath !== getHomeDir()) {
|
|
118
|
+
var isAllowed = allowedBases.some(function (base) {
|
|
119
|
+
var resolvedBase = (0, node_path_1.resolve)(base);
|
|
120
|
+
return (checkPath === resolvedBase ||
|
|
121
|
+
checkPath.startsWith(resolvedBase + '/') ||
|
|
122
|
+
resolvedBase.startsWith(checkPath + '/'));
|
|
123
|
+
});
|
|
124
|
+
if (isAllowed) {
|
|
125
|
+
return absolute;
|
|
126
|
+
}
|
|
127
|
+
// Move up one directory to check
|
|
128
|
+
checkPath = (0, node_path_1.dirname)(checkPath);
|
|
129
|
+
}
|
|
130
|
+
// If we get here, the path is not allowed
|
|
131
|
+
throw new Error("Path not allowed: ".concat(userPath));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Check if a path exists
|
|
135
|
+
*/
|
|
136
|
+
function pathExists(filePath) {
|
|
137
|
+
try {
|
|
138
|
+
return (0, node_fs_1.existsSync)(filePath);
|
|
139
|
+
}
|
|
140
|
+
catch (_a) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get relative path from home directory for display
|
|
146
|
+
*/
|
|
147
|
+
function getDisplayPath(filePath) {
|
|
148
|
+
var home = getHomeDir();
|
|
149
|
+
if (filePath.startsWith(home)) {
|
|
150
|
+
return filePath.replace(home, '~');
|
|
151
|
+
}
|
|
152
|
+
return filePath;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Get MCP config file paths based on target
|
|
156
|
+
* @param target - Which config(s) to get ('cli', 'app', or 'both')
|
|
157
|
+
* @returns Object with the requested config paths
|
|
158
|
+
*/
|
|
159
|
+
function getMCPConfigPaths(target) {
|
|
160
|
+
if (target === void 0) { target = 'both'; }
|
|
161
|
+
var result = {};
|
|
162
|
+
if (target === 'cli' || target === 'both') {
|
|
163
|
+
result.cli = getClaudeCliConfigPath();
|
|
164
|
+
}
|
|
165
|
+
if (target === 'app' || target === 'both') {
|
|
166
|
+
result.app = getConfigPaths().appConfig;
|
|
167
|
+
}
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Path Utilities - Cross-platform path handling for Claude Code config
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import { resolve, normalize, isAbsolute, join, dirname } from 'node:path';
|
|
6
|
+
import { homedir } from 'node:os';
|
|
7
|
+
import { existsSync, realpathSync } from 'node:fs';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Get home directory cross-platform
|
|
11
|
+
*/
|
|
12
|
+
export function getHomeDir(): string {
|
|
13
|
+
return homedir();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get Claude Code global config directory (~/.claude)
|
|
18
|
+
*/
|
|
19
|
+
export function getClaudeConfigDir(): string {
|
|
20
|
+
return join(getHomeDir(), '.claude');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get Claude Code app config directory (~/.config/claude-code)
|
|
25
|
+
* This is where MCP servers are configured for the Claude Code app
|
|
26
|
+
*/
|
|
27
|
+
export function getClaudeAppConfigDir(): string {
|
|
28
|
+
return join(getHomeDir(), '.config', 'claude-code');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Get Claude CLI config file path (~/.claude.json)
|
|
33
|
+
* This is where MCP servers are configured for the claude CLI
|
|
34
|
+
*/
|
|
35
|
+
export function getClaudeCliConfigPath(): string {
|
|
36
|
+
return join(getHomeDir(), '.claude.json');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get project-local Claude Code config directory (.claude)
|
|
41
|
+
*/
|
|
42
|
+
export function getProjectClaudeDir(cwd: string = process.cwd()): string {
|
|
43
|
+
return join(cwd, '.claude');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Resolve Claude config file paths
|
|
48
|
+
*/
|
|
49
|
+
export function getConfigPaths(cwd: string = process.cwd()) {
|
|
50
|
+
const claudeDir = getClaudeConfigDir();
|
|
51
|
+
const claudeAppDir = getClaudeAppConfigDir();
|
|
52
|
+
const projectClaudeDir = getProjectClaudeDir(cwd);
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
// Global config files
|
|
56
|
+
globalClaudeMd: join(claudeDir, 'CLAUDE.md'),
|
|
57
|
+
keybindings: join(claudeDir, 'keybindings.json'),
|
|
58
|
+
settings: join(claudeDir, 'settings.json'),
|
|
59
|
+
claudeJson: join(claudeDir, 'claude.json'),
|
|
60
|
+
mcpServers: join(claudeDir, 'mcp_servers.json'),
|
|
61
|
+
hooksDir: join(claudeDir, 'hooks'),
|
|
62
|
+
pluginsDir: join(claudeDir, 'plugins'),
|
|
63
|
+
|
|
64
|
+
// App config file (where MCP servers are actually configured)
|
|
65
|
+
appConfig: join(claudeAppDir, 'config.json'),
|
|
66
|
+
|
|
67
|
+
// Project-local config files
|
|
68
|
+
projectClaudeMd: join(projectClaudeDir, 'CLAUDE.md'),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Allowed base paths for security (whitelist)
|
|
74
|
+
*/
|
|
75
|
+
const ALLOWED_BASES = [
|
|
76
|
+
getClaudeConfigDir(),
|
|
77
|
+
getProjectClaudeDir(),
|
|
78
|
+
getClaudeAppConfigDir(),
|
|
79
|
+
getClaudeCliConfigPath(),
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Validate and sanitize a file path
|
|
84
|
+
* Prevents path traversal attacks and ensures path is within allowed directories
|
|
85
|
+
*/
|
|
86
|
+
export function validatePath(userPath: string, cwd: string = process.cwd()): string {
|
|
87
|
+
// Normalize path
|
|
88
|
+
const normalized = normalize(userPath.replace(/\0/g, ''));
|
|
89
|
+
|
|
90
|
+
// Resolve to absolute path
|
|
91
|
+
const absolute = isAbsolute(normalized)
|
|
92
|
+
? resolve(normalized)
|
|
93
|
+
: resolve(cwd, normalized);
|
|
94
|
+
|
|
95
|
+
// Check for path traversal attempts
|
|
96
|
+
if (normalized.includes('..')) {
|
|
97
|
+
throw new Error('Path traversal detected');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Build allowed bases including the current project directory
|
|
101
|
+
const allowedBases = [
|
|
102
|
+
...ALLOWED_BASES,
|
|
103
|
+
getClaudeConfigDir(),
|
|
104
|
+
getProjectClaudeDir(cwd),
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
// Check if path is within allowed bases
|
|
108
|
+
// For files that don't exist yet, check the parent directory
|
|
109
|
+
let checkPath = absolute;
|
|
110
|
+
while (checkPath !== '/' && checkPath !== cwd && checkPath !== getHomeDir()) {
|
|
111
|
+
const isAllowed = allowedBases.some(base => {
|
|
112
|
+
const resolvedBase = resolve(base);
|
|
113
|
+
return (
|
|
114
|
+
checkPath === resolvedBase ||
|
|
115
|
+
checkPath.startsWith(resolvedBase + '/') ||
|
|
116
|
+
resolvedBase.startsWith(checkPath + '/')
|
|
117
|
+
);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (isAllowed) {
|
|
121
|
+
return absolute;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Move up one directory to check
|
|
125
|
+
checkPath = dirname(checkPath);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// If we get here, the path is not allowed
|
|
129
|
+
throw new Error(`Path not allowed: ${userPath}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Check if a path exists
|
|
134
|
+
*/
|
|
135
|
+
export function pathExists(filePath: string): boolean {
|
|
136
|
+
try {
|
|
137
|
+
return existsSync(filePath);
|
|
138
|
+
} catch {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Get relative path from home directory for display
|
|
145
|
+
*/
|
|
146
|
+
export function getDisplayPath(filePath: string): string {
|
|
147
|
+
const home = getHomeDir();
|
|
148
|
+
if (filePath.startsWith(home)) {
|
|
149
|
+
return filePath.replace(home, '~');
|
|
150
|
+
}
|
|
151
|
+
return filePath;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Get MCP config file paths based on target
|
|
156
|
+
* @param target - Which config(s) to get ('cli', 'app', or 'both')
|
|
157
|
+
* @returns Object with the requested config paths
|
|
158
|
+
*/
|
|
159
|
+
export function getMCPConfigPaths(target: 'cli' | 'app' | 'both' = 'both'): {
|
|
160
|
+
cli?: string;
|
|
161
|
+
app?: string;
|
|
162
|
+
} {
|
|
163
|
+
const result: { cli?: string; app?: string } = {};
|
|
164
|
+
|
|
165
|
+
if (target === 'cli' || target === 'both') {
|
|
166
|
+
result.cli = getClaudeCliConfigPath();
|
|
167
|
+
}
|
|
168
|
+
if (target === 'app' || target === 'both') {
|
|
169
|
+
result.app = getConfigPaths().appConfig;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return result;
|
|
173
|
+
}
|
package/test/test.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
"use strict";
|
|
3
|
+
// Test script for Claude Code Config MCP Server
|
|
4
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
5
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
6
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
7
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
8
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
9
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
10
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
14
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
15
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
16
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
17
|
+
function step(op) {
|
|
18
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
19
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
20
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
21
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
22
|
+
switch (op[0]) {
|
|
23
|
+
case 0: case 1: t = op; break;
|
|
24
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
25
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
26
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
27
|
+
default:
|
|
28
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
29
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
30
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
31
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
32
|
+
if (t[2]) _.ops.pop();
|
|
33
|
+
_.trys.pop(); continue;
|
|
34
|
+
}
|
|
35
|
+
op = body.call(thisArg, _);
|
|
36
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
37
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
var index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
42
|
+
var stdio_js_1 = require("@modelcontextprotocol/sdk/client/stdio.js");
|
|
43
|
+
function main() {
|
|
44
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
45
|
+
var transport, client, listResult, readResult, content, paths, _i, paths_1, pathType, pathResult, data, hooksResult, hooks, error_1;
|
|
46
|
+
var _a, _b, _c;
|
|
47
|
+
return __generator(this, function (_d) {
|
|
48
|
+
switch (_d.label) {
|
|
49
|
+
case 0:
|
|
50
|
+
console.log('Starting Claude Code Config MCP Server test...\n');
|
|
51
|
+
transport = new stdio_js_1.StdioClientTransport({
|
|
52
|
+
command: 'bun',
|
|
53
|
+
args: ['run', 'src/index.ts'],
|
|
54
|
+
cwd: '/Users/ebowwa/Desktop/codespaces/MCP/packages/claude-code-config',
|
|
55
|
+
});
|
|
56
|
+
client = new index_js_1.Client({ name: 'test-client', version: '1.0.0' }, { capabilities: {} });
|
|
57
|
+
_d.label = 1;
|
|
58
|
+
case 1:
|
|
59
|
+
_d.trys.push([1, 10, 11, 13]);
|
|
60
|
+
// Connect to server
|
|
61
|
+
return [4 /*yield*/, client.connect(transport)];
|
|
62
|
+
case 2:
|
|
63
|
+
// Connect to server
|
|
64
|
+
_d.sent();
|
|
65
|
+
console.log('✅ Connected to server\n');
|
|
66
|
+
// Test 1: List config files
|
|
67
|
+
console.log('📋 Test 1: List config files');
|
|
68
|
+
return [4 /*yield*/, client.callTool({
|
|
69
|
+
name: 'list_config_files',
|
|
70
|
+
arguments: { includeProject: true },
|
|
71
|
+
})];
|
|
72
|
+
case 3:
|
|
73
|
+
listResult = _d.sent();
|
|
74
|
+
console.log(JSON.stringify(listResult, null, 2));
|
|
75
|
+
console.log('');
|
|
76
|
+
// Test 2: Read global CLAUDE.md
|
|
77
|
+
console.log('📄 Test 2: Read global CLAUDE.md');
|
|
78
|
+
return [4 /*yield*/, client.callTool({
|
|
79
|
+
name: 'read_global_claude_md',
|
|
80
|
+
arguments: {},
|
|
81
|
+
})];
|
|
82
|
+
case 4:
|
|
83
|
+
readResult = _d.sent();
|
|
84
|
+
content = (_a = readResult.content[0]) === null || _a === void 0 ? void 0 : _a.text;
|
|
85
|
+
console.log("Content preview (".concat(content.length, " chars):"));
|
|
86
|
+
console.log(content.substring(0, 200) + '...\n');
|
|
87
|
+
// Test 3: Get config paths
|
|
88
|
+
console.log('🔍 Test 3: Get config paths');
|
|
89
|
+
paths = ['CLAUDE_MD_GLOBAL', 'KEYBINDINGS', 'SETTINGS'];
|
|
90
|
+
_i = 0, paths_1 = paths;
|
|
91
|
+
_d.label = 5;
|
|
92
|
+
case 5:
|
|
93
|
+
if (!(_i < paths_1.length)) return [3 /*break*/, 8];
|
|
94
|
+
pathType = paths_1[_i];
|
|
95
|
+
return [4 /*yield*/, client.callTool({
|
|
96
|
+
name: 'get_config_path',
|
|
97
|
+
arguments: { fileType: pathType },
|
|
98
|
+
})];
|
|
99
|
+
case 6:
|
|
100
|
+
pathResult = _d.sent();
|
|
101
|
+
data = JSON.parse((_b = pathResult.content[0]) === null || _b === void 0 ? void 0 : _b.text);
|
|
102
|
+
console.log(" ".concat(pathType, ": ").concat(data.path, " (exists: ").concat(data.exists, ")"));
|
|
103
|
+
_d.label = 7;
|
|
104
|
+
case 7:
|
|
105
|
+
_i++;
|
|
106
|
+
return [3 /*break*/, 5];
|
|
107
|
+
case 8:
|
|
108
|
+
console.log('');
|
|
109
|
+
// Test 4: List hooks
|
|
110
|
+
console.log('🪝 Test 4: List hooks');
|
|
111
|
+
return [4 /*yield*/, client.callTool({
|
|
112
|
+
name: 'list_hooks',
|
|
113
|
+
arguments: {},
|
|
114
|
+
})];
|
|
115
|
+
case 9:
|
|
116
|
+
hooksResult = _d.sent();
|
|
117
|
+
hooks = JSON.parse((_c = hooksResult.content[0]) === null || _c === void 0 ? void 0 : _c.text);
|
|
118
|
+
console.log(" Found ".concat(hooks.length, " hooks"));
|
|
119
|
+
console.log('');
|
|
120
|
+
console.log('✅ All tests passed!');
|
|
121
|
+
return [3 /*break*/, 13];
|
|
122
|
+
case 10:
|
|
123
|
+
error_1 = _d.sent();
|
|
124
|
+
console.error('❌ Test failed:', error_1);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
return [3 /*break*/, 13];
|
|
127
|
+
case 11: return [4 /*yield*/, client.close()];
|
|
128
|
+
case 12:
|
|
129
|
+
_d.sent();
|
|
130
|
+
return [7 /*endfinally*/];
|
|
131
|
+
case 13: return [2 /*return*/];
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
main();
|
package/test/test.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// Test script for Claude Code Config MCP Server
|
|
3
|
+
|
|
4
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
5
|
+
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
6
|
+
|
|
7
|
+
async function main() {
|
|
8
|
+
console.log('Starting Claude Code Config MCP Server test...\n');
|
|
9
|
+
|
|
10
|
+
// Create client
|
|
11
|
+
const transport = new StdioClientTransport({
|
|
12
|
+
command: 'bun',
|
|
13
|
+
args: ['run', 'src/index.ts'],
|
|
14
|
+
cwd: '/Users/ebowwa/Desktop/codespaces/MCP/packages/claude-code-config',
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const client = new Client(
|
|
18
|
+
{ name: 'test-client', version: '1.0.0' },
|
|
19
|
+
{ capabilities: {} }
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
// Connect to server
|
|
24
|
+
await client.connect(transport);
|
|
25
|
+
console.log('✅ Connected to server\n');
|
|
26
|
+
|
|
27
|
+
// Test 1: List config files
|
|
28
|
+
console.log('📋 Test 1: List config files');
|
|
29
|
+
const listResult = await client.callTool({
|
|
30
|
+
name: 'list_config_files',
|
|
31
|
+
arguments: { includeProject: true },
|
|
32
|
+
});
|
|
33
|
+
console.log(JSON.stringify(listResult, null, 2));
|
|
34
|
+
console.log('');
|
|
35
|
+
|
|
36
|
+
// Test 2: Read global CLAUDE.md
|
|
37
|
+
console.log('📄 Test 2: Read global CLAUDE.md');
|
|
38
|
+
const readResult = await client.callTool({
|
|
39
|
+
name: 'read_global_claude_md',
|
|
40
|
+
arguments: {},
|
|
41
|
+
});
|
|
42
|
+
const content = readResult.content[0]?.text as string;
|
|
43
|
+
console.log(`Content preview (${content.length} chars):`);
|
|
44
|
+
console.log(content.substring(0, 200) + '...\n');
|
|
45
|
+
|
|
46
|
+
// Test 3: Get config paths
|
|
47
|
+
console.log('🔍 Test 3: Get config paths');
|
|
48
|
+
const paths = ['CLAUDE_MD_GLOBAL', 'KEYBINDINGS', 'SETTINGS'] as const;
|
|
49
|
+
for (const pathType of paths) {
|
|
50
|
+
const pathResult = await client.callTool({
|
|
51
|
+
name: 'get_config_path',
|
|
52
|
+
arguments: { fileType: pathType },
|
|
53
|
+
});
|
|
54
|
+
const data = JSON.parse(pathResult.content[0]?.text as string);
|
|
55
|
+
console.log(` ${pathType}: ${data.path} (exists: ${data.exists})`);
|
|
56
|
+
}
|
|
57
|
+
console.log('');
|
|
58
|
+
|
|
59
|
+
// Test 4: List hooks
|
|
60
|
+
console.log('🪝 Test 4: List hooks');
|
|
61
|
+
const hooksResult = await client.callTool({
|
|
62
|
+
name: 'list_hooks',
|
|
63
|
+
arguments: {},
|
|
64
|
+
});
|
|
65
|
+
const hooks = JSON.parse(hooksResult.content[0]?.text as string);
|
|
66
|
+
console.log(` Found ${hooks.length} hooks`);
|
|
67
|
+
console.log('');
|
|
68
|
+
|
|
69
|
+
console.log('✅ All tests passed!');
|
|
70
|
+
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error('❌ Test failed:', error);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
} finally {
|
|
75
|
+
await client.close();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
main();
|