codepage-bridge-mcp 0.1.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-plugin/marketplace.json +19 -0
- package/.claude-plugin/plugin.json +15 -0
- package/.mcp.json +11 -0
- package/LICENSE +21 -0
- package/README.md +990 -0
- package/README_CN.md +781 -0
- package/dist/src/core.d.ts +56 -0
- package/dist/src/core.js +166 -0
- package/dist/src/core.js.map +1 -0
- package/dist/src/diff.d.ts +8 -0
- package/dist/src/diff.js +11 -0
- package/dist/src/diff.js.map +1 -0
- package/dist/src/encoding/codec.d.ts +5 -0
- package/dist/src/encoding/codec.js +75 -0
- package/dist/src/encoding/codec.js.map +1 -0
- package/dist/src/encoding/index.d.ts +3 -0
- package/dist/src/encoding/index.js +4 -0
- package/dist/src/encoding/index.js.map +1 -0
- package/dist/src/encoding/rules.d.ts +4 -0
- package/dist/src/encoding/rules.js +70 -0
- package/dist/src/encoding/rules.js.map +1 -0
- package/dist/src/encoding/types.d.ts +22 -0
- package/dist/src/encoding/types.js +2 -0
- package/dist/src/encoding/types.js.map +1 -0
- package/dist/src/filesystem/atomic.d.ts +6 -0
- package/dist/src/filesystem/atomic.js +91 -0
- package/dist/src/filesystem/atomic.js.map +1 -0
- package/dist/src/filesystem/cache.d.ts +21 -0
- package/dist/src/filesystem/cache.js +40 -0
- package/dist/src/filesystem/cache.js.map +1 -0
- package/dist/src/filesystem/index.d.ts +4 -0
- package/dist/src/filesystem/index.js +5 -0
- package/dist/src/filesystem/index.js.map +1 -0
- package/dist/src/filesystem/mutex.d.ts +5 -0
- package/dist/src/filesystem/mutex.js +23 -0
- package/dist/src/filesystem/mutex.js.map +1 -0
- package/dist/src/filesystem/path.d.ts +9 -0
- package/dist/src/filesystem/path.js +53 -0
- package/dist/src/filesystem/path.js.map +1 -0
- package/dist/src/media/errors.d.ts +14 -0
- package/dist/src/media/errors.js +29 -0
- package/dist/src/media/errors.js.map +1 -0
- package/dist/src/media/image.d.ts +11 -0
- package/dist/src/media/image.js +81 -0
- package/dist/src/media/image.js.map +1 -0
- package/dist/src/media/index.d.ts +5 -0
- package/dist/src/media/index.js +6 -0
- package/dist/src/media/index.js.map +1 -0
- package/dist/src/media/notebook.d.ts +47 -0
- package/dist/src/media/notebook.js +122 -0
- package/dist/src/media/notebook.js.map +1 -0
- package/dist/src/media/pdf.d.ts +25 -0
- package/dist/src/media/pdf.js +104 -0
- package/dist/src/media/pdf.js.map +1 -0
- package/dist/src/media/types.d.ts +14 -0
- package/dist/src/media/types.js +2 -0
- package/dist/src/media/types.js.map +1 -0
- package/dist/src/prompts.d.ts +8 -0
- package/dist/src/prompts.js +46 -0
- package/dist/src/prompts.js.map +1 -0
- package/dist/src/schemas.d.ts +138 -0
- package/dist/src/schemas.js +81 -0
- package/dist/src/schemas.js.map +1 -0
- package/dist/src/server.d.ts +159 -0
- package/dist/src/server.js +98 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/toolTypes.d.ts +31 -0
- package/dist/src/toolTypes.js +2 -0
- package/dist/src/toolTypes.js.map +1 -0
- package/dist/src/tools/edit.d.ts +3 -0
- package/dist/src/tools/edit.js +168 -0
- package/dist/src/tools/edit.js.map +1 -0
- package/dist/src/tools/grep.d.ts +21 -0
- package/dist/src/tools/grep.js +192 -0
- package/dist/src/tools/grep.js.map +1 -0
- package/dist/src/tools/read.d.ts +3 -0
- package/dist/src/tools/read.js +137 -0
- package/dist/src/tools/read.js.map +1 -0
- package/dist/src/tools/write.d.ts +3 -0
- package/dist/src/tools/write.js +80 -0
- package/dist/src/tools/write.js.map +1 -0
- package/dist/src/validation.d.ts +6 -0
- package/dist/src/validation.js +42 -0
- package/dist/src/validation.js.map +1 -0
- package/examples/claude-config/settings.fragment.json +17 -0
- package/examples/minimal-project/.encoding-rules +10 -0
- package/examples/minimal-project/.mcp.json +11 -0
- package/examples/minimal-project/CLAUDE.md +15 -0
- package/install/download-release-unix.sh +72 -0
- package/install/download-release-windows.ps1 +61 -0
- package/install/install-from-release-unix.sh +18 -0
- package/install/install-from-release-windows.ps1 +19 -0
- package/install/install-from-source-unix.sh +44 -0
- package/install/install-from-source-windows.ps1 +45 -0
- package/install/install-this-release-unix.sh +37 -0
- package/install/install-this-release-windows.ps1 +36 -0
- package/package.json +64 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { mkdir, stat } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { encodeText } from '../encoding/index.js';
|
|
4
|
+
import { getProjectFileContext, encodeSnapshotText, readDecodedFile, readRegistry } from '../core.js';
|
|
5
|
+
import { createStructuredPatch } from '../diff.js';
|
|
6
|
+
import { atomicWriteBuffer } from '../filesystem/index.js';
|
|
7
|
+
import { assertObject, rejectUnknown, requiredString } from '../validation.js';
|
|
8
|
+
export function parseWriteInput(value) {
|
|
9
|
+
assertObject(value);
|
|
10
|
+
rejectUnknown(value, ['file_path', 'content']);
|
|
11
|
+
return {
|
|
12
|
+
file_path: requiredString(value, 'file_path'),
|
|
13
|
+
content: requiredString(value, 'content'),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export async function executeWrite(input) {
|
|
17
|
+
const context = await getProjectFileContext(input.file_path);
|
|
18
|
+
let exists = true;
|
|
19
|
+
try {
|
|
20
|
+
await stat(context.absolutePath);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (error.code !== 'ENOENT')
|
|
24
|
+
throw error;
|
|
25
|
+
exists = false;
|
|
26
|
+
}
|
|
27
|
+
await mkdir(path.dirname(context.absolutePath), { recursive: true });
|
|
28
|
+
if (!exists) {
|
|
29
|
+
const buffer = encodeText(input.content, context.encoding);
|
|
30
|
+
await atomicWriteBuffer(context.root, context.absolutePath, buffer);
|
|
31
|
+
const info = await stat(context.absolutePath);
|
|
32
|
+
const snapshot = {
|
|
33
|
+
absolutePath: context.absolutePath,
|
|
34
|
+
root: context.root,
|
|
35
|
+
encoding: context.encoding,
|
|
36
|
+
text: '',
|
|
37
|
+
bom: null,
|
|
38
|
+
newline: null,
|
|
39
|
+
mtimeMs: 0,
|
|
40
|
+
size: 0,
|
|
41
|
+
hash: '',
|
|
42
|
+
complete: true,
|
|
43
|
+
};
|
|
44
|
+
readRegistry.updateAfterWrite(snapshot, input.content, buffer, info.mtimeMs);
|
|
45
|
+
return {
|
|
46
|
+
content: [{ type: 'text', text: `File created successfully at: ${context.absolutePath}` }],
|
|
47
|
+
structuredContent: {
|
|
48
|
+
type: 'create',
|
|
49
|
+
filePath: context.absolutePath,
|
|
50
|
+
content: input.content,
|
|
51
|
+
structuredPatch: createStructuredPatch(context.absolutePath, '', input.content),
|
|
52
|
+
originalFile: null,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const readSnapshot = readRegistry.get(context.absolutePath);
|
|
57
|
+
if (!readSnapshot)
|
|
58
|
+
throw new Error('File has not been read. Read it before attempting to write it.');
|
|
59
|
+
const current = await readDecodedFile(context);
|
|
60
|
+
if ((current.hash !== readSnapshot.hash || current.mtimeMs !== readSnapshot.mtimeMs) && current.text !== readSnapshot.text) {
|
|
61
|
+
throw new Error('File has been unexpectedly modified. Read it again before attempting to write it.');
|
|
62
|
+
}
|
|
63
|
+
const buffer = encodeSnapshotText(current, input.content, false);
|
|
64
|
+
await atomicWriteBuffer(context.root, context.absolutePath, buffer, {
|
|
65
|
+
expected: { mtimeMs: current.mtimeMs, hash: current.hash },
|
|
66
|
+
});
|
|
67
|
+
const info = await stat(context.absolutePath);
|
|
68
|
+
readRegistry.updateAfterWrite(current, input.content, buffer, info.mtimeMs);
|
|
69
|
+
return {
|
|
70
|
+
content: [{ type: 'text', text: `The file ${context.absolutePath} has been updated successfully.` }],
|
|
71
|
+
structuredContent: {
|
|
72
|
+
type: 'update',
|
|
73
|
+
filePath: context.absolutePath,
|
|
74
|
+
content: input.content,
|
|
75
|
+
structuredPatch: createStructuredPatch(context.absolutePath, current.text, input.content),
|
|
76
|
+
originalFile: current.text,
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/tools/write.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function assertObject(value: unknown): asserts value is Record<string, unknown>;
|
|
2
|
+
export declare function rejectUnknown(input: Record<string, unknown>, allowed: readonly string[]): void;
|
|
3
|
+
export declare function requiredString(input: Record<string, unknown>, key: string): string;
|
|
4
|
+
export declare function optionalString(input: Record<string, unknown>, key: string): string | undefined;
|
|
5
|
+
export declare function optionalInteger(input: Record<string, unknown>, key: string, minimum: number): number | undefined;
|
|
6
|
+
export declare function optionalBoolean(input: Record<string, unknown>, key: string): boolean | undefined;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export function assertObject(value) {
|
|
2
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
3
|
+
throw new Error('Tool input must be an object');
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
export function rejectUnknown(input, allowed) {
|
|
7
|
+
const unknown = Object.keys(input).filter(key => !allowed.includes(key));
|
|
8
|
+
if (unknown.length > 0)
|
|
9
|
+
throw new Error(`Unknown input field(s): ${unknown.join(', ')}`);
|
|
10
|
+
}
|
|
11
|
+
export function requiredString(input, key) {
|
|
12
|
+
const value = input[key];
|
|
13
|
+
if (typeof value !== 'string')
|
|
14
|
+
throw new Error(`${key} must be a string`);
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
export function optionalString(input, key) {
|
|
18
|
+
const value = input[key];
|
|
19
|
+
if (value === undefined)
|
|
20
|
+
return undefined;
|
|
21
|
+
if (typeof value !== 'string')
|
|
22
|
+
throw new Error(`${key} must be a string`);
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
export function optionalInteger(input, key, minimum) {
|
|
26
|
+
const value = input[key];
|
|
27
|
+
if (value === undefined)
|
|
28
|
+
return undefined;
|
|
29
|
+
if (!Number.isInteger(value) || value < minimum) {
|
|
30
|
+
throw new Error(`${key} must be an integer greater than or equal to ${minimum}`);
|
|
31
|
+
}
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
export function optionalBoolean(input, key) {
|
|
35
|
+
const value = input[key];
|
|
36
|
+
if (value === undefined)
|
|
37
|
+
return undefined;
|
|
38
|
+
if (typeof value !== 'boolean')
|
|
39
|
+
throw new Error(`${key} must be a boolean`);
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/validation.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;IACjD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAA8B,EAAE,OAA0B;IACtF,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAA;IACxE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AAC1F,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAA8B,EAAE,GAAW;IACxE,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;IACxB,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,mBAAmB,CAAC,CAAA;IACzE,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAA8B,EAAE,GAAW;IACxE,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;IACxB,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IACzC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,mBAAmB,CAAC,CAAA;IACzE,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,KAA8B,EAC9B,GAAW,EACX,OAAe;IAEf,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;IACxB,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IACzC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAK,KAAgB,GAAG,OAAO,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,gDAAgD,OAAO,EAAE,CAAC,CAAA;IAClF,CAAC;IACD,OAAO,KAAe,CAAA;AACxB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAA8B,EAAE,GAAW;IACzE,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;IACxB,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IACzC,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,oBAAoB,CAAC,CAAA;IAC3E,OAAO,KAAK,CAAA;AACd,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"mcp__codepage-bridge__Read",
|
|
5
|
+
"mcp__codepage-bridge__Grep",
|
|
6
|
+
"mcp__codepage-bridge__Edit",
|
|
7
|
+
"mcp__codepage-bridge__Write"
|
|
8
|
+
],
|
|
9
|
+
"deny": [
|
|
10
|
+
"Read",
|
|
11
|
+
"Grep",
|
|
12
|
+
"Edit",
|
|
13
|
+
"Write",
|
|
14
|
+
"NotebookEdit"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
## File encoding policy
|
|
2
|
+
|
|
3
|
+
Use Codepage Bridge for all project file content operations:
|
|
4
|
+
|
|
5
|
+
- Read with `mcp__codepage-bridge__Read`.
|
|
6
|
+
- Search with `mcp__codepage-bridge__Grep`.
|
|
7
|
+
- Edit with `mcp__codepage-bridge__Edit`.
|
|
8
|
+
- Create or completely rewrite with `mcp__codepage-bridge__Write`.
|
|
9
|
+
|
|
10
|
+
Do not use built-in Read, Grep, Edit, Write, NotebookEdit, shell commands,
|
|
11
|
+
PowerShell commands, or scripts as substitutes for project file content access.
|
|
12
|
+
Glob may only be used to discover paths.
|
|
13
|
+
|
|
14
|
+
Do not manually transcode files or normalize line endings. `.encoding-rules`
|
|
15
|
+
is the source of truth.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
VERSION="${1:-latest}"
|
|
5
|
+
SERVER_NAME="${SERVER_NAME:-codepage-bridge}"
|
|
6
|
+
SCOPE="${SCOPE:-user}"
|
|
7
|
+
REPO="skyispainted/codepage-bridge-mcp"
|
|
8
|
+
INSTALL_ROOT="${HOME}/.codepage-bridge"
|
|
9
|
+
RELEASE_ROOT="${INSTALL_ROOT}/releases"
|
|
10
|
+
|
|
11
|
+
require_command() {
|
|
12
|
+
command -v "$1" >/dev/null 2>&1 || {
|
|
13
|
+
echo "Required command not found: $1" >&2
|
|
14
|
+
exit 1
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
require_command node
|
|
19
|
+
require_command claude
|
|
20
|
+
require_command curl
|
|
21
|
+
require_command tar
|
|
22
|
+
require_command uname
|
|
23
|
+
|
|
24
|
+
mkdir -p "$RELEASE_ROOT"
|
|
25
|
+
|
|
26
|
+
platform="$(uname -s)"
|
|
27
|
+
arch="$(uname -m)"
|
|
28
|
+
case "$platform" in
|
|
29
|
+
Linux) os="linux" ;;
|
|
30
|
+
Darwin) os="darwin" ;;
|
|
31
|
+
*) echo "Unsupported platform: $platform" >&2; exit 1 ;;
|
|
32
|
+
esac
|
|
33
|
+
case "$arch" in
|
|
34
|
+
x86_64|amd64) cpu="x64" ;;
|
|
35
|
+
arm64|aarch64) cpu="arm64" ;;
|
|
36
|
+
*) echo "Unsupported architecture: $arch" >&2; exit 1 ;;
|
|
37
|
+
esac
|
|
38
|
+
|
|
39
|
+
if [ "$VERSION" = "latest" ]; then
|
|
40
|
+
api_url="https://api.github.com/repos/$REPO/releases/latest"
|
|
41
|
+
else
|
|
42
|
+
api_url="https://api.github.com/repos/$REPO/releases/tags/$VERSION"
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
release_json="$(curl -fsSL -H 'User-Agent: codepage-bridge-installer' "$api_url")"
|
|
46
|
+
tag="$(printf '%s' "$release_json" | node -e "const fs=require('fs'); const data=JSON.parse(fs.readFileSync(0,'utf8')); process.stdout.write(data.tag_name)")"
|
|
47
|
+
asset_name="codepage-bridge-${tag}-${os}-${cpu}.tar.gz"
|
|
48
|
+
asset_url="$(printf '%s' "$release_json" | node -e "const fs=require('fs'); const data=JSON.parse(fs.readFileSync(0,'utf8')); const asset=data.assets.find(a=>a.name===process.argv[1]); if(!asset){process.exit(2)} process.stdout.write(asset.browser_download_url)" "$asset_name")" || {
|
|
49
|
+
echo "Release asset not found: $asset_name" >&2
|
|
50
|
+
exit 1
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
archive="$INSTALL_ROOT/$asset_name"
|
|
54
|
+
target_dir="$RELEASE_ROOT/$tag"
|
|
55
|
+
rm -rf "$target_dir"
|
|
56
|
+
mkdir -p "$target_dir"
|
|
57
|
+
|
|
58
|
+
echo "[1/3] Downloading $asset_name ..."
|
|
59
|
+
curl -fsSL -H 'User-Agent: codepage-bridge-installer' "$asset_url" -o "$archive"
|
|
60
|
+
|
|
61
|
+
echo "[2/3] Extracting release ..."
|
|
62
|
+
tar -xzf "$archive" -C "$target_dir"
|
|
63
|
+
rm -f "$archive"
|
|
64
|
+
|
|
65
|
+
package_root="$target_dir/codepage-bridge-${tag}-${os}-${cpu}"
|
|
66
|
+
if [ ! -d "$package_root" ]; then
|
|
67
|
+
echo "Expected extracted package directory not found: $package_root" >&2
|
|
68
|
+
exit 1
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
echo "[3/3] Installing extracted release package ..."
|
|
72
|
+
bash "$package_root/install/install-this-release-unix.sh" "$SERVER_NAME"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[string]$Version = 'latest',
|
|
3
|
+
[string]$ServerName = 'codepage-bridge',
|
|
4
|
+
[string]$Scope = 'user'
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
$ErrorActionPreference = 'Stop'
|
|
8
|
+
|
|
9
|
+
function Require-Command($name) {
|
|
10
|
+
if (-not (Get-Command $name -ErrorAction SilentlyContinue)) {
|
|
11
|
+
throw "Required command not found: $name"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
Require-Command node
|
|
16
|
+
Require-Command claude
|
|
17
|
+
Require-Command powershell
|
|
18
|
+
|
|
19
|
+
$Repo = 'skyispainted/codepage-bridge-mcp'
|
|
20
|
+
$InstallRoot = Join-Path $env:USERPROFILE '.codepage-bridge'
|
|
21
|
+
$ReleaseRoot = Join-Path $InstallRoot 'releases'
|
|
22
|
+
New-Item -ItemType Directory -Force -Path $ReleaseRoot | Out-Null
|
|
23
|
+
|
|
24
|
+
function Get-ReleaseInfo {
|
|
25
|
+
param([string]$Version)
|
|
26
|
+
if ($Version -eq 'latest') {
|
|
27
|
+
$url = "https://api.github.com/repos/$Repo/releases/latest"
|
|
28
|
+
} else {
|
|
29
|
+
$url = "https://api.github.com/repos/$Repo/releases/tags/$Version"
|
|
30
|
+
}
|
|
31
|
+
Invoke-RestMethod -Uri $url -Headers @{ 'User-Agent' = 'codepage-bridge-installer' }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
$release = Get-ReleaseInfo -Version $Version
|
|
35
|
+
$tag = $release.tag_name
|
|
36
|
+
$assetName = "codepage-bridge-$tag-win32-x64.zip"
|
|
37
|
+
$asset = $release.assets | Where-Object { $_.name -eq $assetName } | Select-Object -First 1
|
|
38
|
+
if (-not $asset) {
|
|
39
|
+
throw "Release asset not found: $assetName"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
$zipPath = Join-Path $InstallRoot $assetName
|
|
43
|
+
$targetDir = Join-Path $ReleaseRoot $tag
|
|
44
|
+
if (Test-Path $targetDir) {
|
|
45
|
+
Remove-Item -Recurse -Force $targetDir
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Write-Host "[1/3] Downloading $assetName ..."
|
|
49
|
+
Invoke-WebRequest -Uri $asset.browser_download_url -OutFile $zipPath -Headers @{ 'User-Agent' = 'codepage-bridge-installer' }
|
|
50
|
+
|
|
51
|
+
Write-Host "[2/3] Extracting release ..."
|
|
52
|
+
Expand-Archive -Path $zipPath -DestinationPath $targetDir -Force
|
|
53
|
+
Remove-Item -Force $zipPath
|
|
54
|
+
|
|
55
|
+
$packageRoot = Join-Path $targetDir "codepage-bridge-$tag-win32-x64"
|
|
56
|
+
if (-not (Test-Path $packageRoot)) {
|
|
57
|
+
throw "Expected extracted package directory not found: $packageRoot"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
Write-Host "[3/3] Installing extracted release package ..."
|
|
61
|
+
& (Join-Path $packageRoot 'install\install-this-release-windows.ps1') -ServerName $ServerName -Scope $Scope
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
VERSION="${1:-latest}"
|
|
5
|
+
SERVER_NAME="${SERVER_NAME:-codepage-bridge}"
|
|
6
|
+
SCOPE="${SCOPE:-user}"
|
|
7
|
+
|
|
8
|
+
PACKAGE_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
9
|
+
ENTRY="$PACKAGE_ROOT/dist/src/server.js"
|
|
10
|
+
|
|
11
|
+
if [ -f "$ENTRY" ]; then
|
|
12
|
+
echo "Detected an extracted release package in the current directory. Installing from local files..."
|
|
13
|
+
bash "$PACKAGE_ROOT/install/install-this-release-unix.sh" "$SERVER_NAME"
|
|
14
|
+
exit 0
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
echo "No local extracted release package detected. Downloading from GitHub Release..."
|
|
18
|
+
SCOPE="$SCOPE" SERVER_NAME="$SERVER_NAME" bash "$PACKAGE_ROOT/install/download-release-unix.sh" "$VERSION"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[string]$Version = 'latest',
|
|
3
|
+
[string]$ServerName = 'codepage-bridge',
|
|
4
|
+
[string]$Scope = 'user'
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
$ErrorActionPreference = 'Stop'
|
|
8
|
+
|
|
9
|
+
$packageRoot = Split-Path -Parent $PSScriptRoot
|
|
10
|
+
$entry = Join-Path $packageRoot 'dist\src\server.js'
|
|
11
|
+
|
|
12
|
+
if (Test-Path $entry) {
|
|
13
|
+
Write-Host 'Detected an extracted release package in the current directory. Installing from local files...'
|
|
14
|
+
& (Join-Path $PSScriptRoot 'install-this-release-windows.ps1') -ServerName $ServerName -Scope $Scope
|
|
15
|
+
exit 0
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
Write-Host 'No local extracted release package detected. Downloading from GitHub Release...'
|
|
19
|
+
& (Join-Path $PSScriptRoot 'download-release-windows.ps1') -Version $Version -ServerName $ServerName -Scope $Scope
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SERVER_NAME="${1:-codepage-bridge}"
|
|
5
|
+
SCOPE="${SCOPE:-user}"
|
|
6
|
+
|
|
7
|
+
require_command() {
|
|
8
|
+
command -v "$1" >/dev/null 2>&1 || {
|
|
9
|
+
echo "Required command not found: $1" >&2
|
|
10
|
+
exit 1
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
require_command node
|
|
15
|
+
require_command npm
|
|
16
|
+
require_command claude
|
|
17
|
+
|
|
18
|
+
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
19
|
+
ENTRY="$REPO_ROOT/dist/src/server.js"
|
|
20
|
+
|
|
21
|
+
echo "[1/4] Installing npm dependencies..."
|
|
22
|
+
npm --prefix "$REPO_ROOT" install
|
|
23
|
+
|
|
24
|
+
echo "[2/4] Building Codepage Bridge..."
|
|
25
|
+
npm --prefix "$REPO_ROOT" run build
|
|
26
|
+
|
|
27
|
+
if [ ! -f "$ENTRY" ]; then
|
|
28
|
+
echo "Build did not produce $ENTRY" >&2
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
echo "[3/4] Registering Claude Code MCP..."
|
|
33
|
+
claude mcp remove "$SERVER_NAME" --scope "$SCOPE" >/dev/null 2>&1 || true
|
|
34
|
+
claude mcp add --scope "$SCOPE" "$SERVER_NAME" -- node "$ENTRY"
|
|
35
|
+
|
|
36
|
+
echo "[4/4] Verifying MCP connection..."
|
|
37
|
+
claude mcp get "$SERVER_NAME"
|
|
38
|
+
|
|
39
|
+
echo
|
|
40
|
+
echo "Next required steps:"
|
|
41
|
+
echo "1. Merge examples/claude-config/settings.fragment.json into ~/.claude/settings.json"
|
|
42
|
+
echo "2. Add examples/minimal-project/CLAUDE.md to your project or ~/.claude/CLAUDE.md"
|
|
43
|
+
echo "3. Add a .encoding-rules file to each legacy-encoded project"
|
|
44
|
+
echo "4. Start a new Claude Code session and verify it uses mcp__codepage-bridge__Read/Grep/Edit/Write"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[string]$ServerName = "codepage-bridge",
|
|
3
|
+
[string]$Scope = "user"
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
$ErrorActionPreference = "Stop"
|
|
7
|
+
|
|
8
|
+
function Require-Command($name) {
|
|
9
|
+
if (-not (Get-Command $name -ErrorAction SilentlyContinue)) {
|
|
10
|
+
throw "Required command not found: $name"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
Require-Command node
|
|
15
|
+
Require-Command npm
|
|
16
|
+
Require-Command claude
|
|
17
|
+
|
|
18
|
+
$repoRoot = Split-Path -Parent $PSScriptRoot
|
|
19
|
+
$entry = Join-Path $repoRoot "dist\src\server.js"
|
|
20
|
+
|
|
21
|
+
Write-Host "[1/4] Installing npm dependencies..."
|
|
22
|
+
npm --prefix $repoRoot install
|
|
23
|
+
|
|
24
|
+
Write-Host "[2/4] Building Codepage Bridge..."
|
|
25
|
+
npm --prefix $repoRoot run build
|
|
26
|
+
|
|
27
|
+
if (-not (Test-Path $entry)) {
|
|
28
|
+
throw "Build did not produce $entry"
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
Write-Host "[3/4] Registering Claude Code MCP..."
|
|
32
|
+
try {
|
|
33
|
+
claude mcp remove $ServerName --scope $Scope | Out-Null
|
|
34
|
+
} catch {}
|
|
35
|
+
claude mcp add --scope $Scope $ServerName -- node $entry
|
|
36
|
+
|
|
37
|
+
Write-Host "[4/4] Verifying MCP connection..."
|
|
38
|
+
claude mcp get $ServerName
|
|
39
|
+
|
|
40
|
+
Write-Host ""
|
|
41
|
+
Write-Host "Next required steps:" -ForegroundColor Yellow
|
|
42
|
+
Write-Host "1. Merge examples/claude-config/settings.fragment.json into ~/.claude/settings.json"
|
|
43
|
+
Write-Host "2. Add examples/minimal-project/CLAUDE.md to your project or ~/.claude/CLAUDE.md"
|
|
44
|
+
Write-Host "3. Add a .encoding-rules file to each legacy-encoded project"
|
|
45
|
+
Write-Host "4. Start a new Claude Code session and verify it uses mcp__codepage-bridge__Read/Grep/Edit/Write"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SERVER_NAME="${1:-codepage-bridge}"
|
|
5
|
+
SCOPE="${SCOPE:-user}"
|
|
6
|
+
|
|
7
|
+
require_command() {
|
|
8
|
+
command -v "$1" >/dev/null 2>&1 || {
|
|
9
|
+
echo "Required command not found: $1" >&2
|
|
10
|
+
exit 1
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
require_command node
|
|
15
|
+
require_command claude
|
|
16
|
+
|
|
17
|
+
PACKAGE_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
18
|
+
ENTRY="$PACKAGE_ROOT/dist/src/server.js"
|
|
19
|
+
|
|
20
|
+
if [ ! -f "$ENTRY" ]; then
|
|
21
|
+
echo "This directory does not look like an extracted Codepage Bridge release package. Missing: $ENTRY" >&2
|
|
22
|
+
exit 1
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
echo "[1/2] Registering Claude Code MCP from this release package..."
|
|
26
|
+
claude mcp remove "$SERVER_NAME" --scope "$SCOPE" >/dev/null 2>&1 || true
|
|
27
|
+
claude mcp add --scope "$SCOPE" "$SERVER_NAME" -- node "$ENTRY"
|
|
28
|
+
|
|
29
|
+
echo "[2/2] Verifying MCP connection..."
|
|
30
|
+
claude mcp get "$SERVER_NAME"
|
|
31
|
+
|
|
32
|
+
echo
|
|
33
|
+
echo "Installed $SERVER_NAME from the current extracted release package."
|
|
34
|
+
echo "Next required steps:"
|
|
35
|
+
echo "1. Merge examples/claude-config/settings.fragment.json into ~/.claude/settings.json"
|
|
36
|
+
echo "2. Add CLAUDE.md policy from examples/minimal-project/CLAUDE.md"
|
|
37
|
+
echo "3. Add a .encoding-rules file to each legacy-encoded project"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[string]$ServerName = 'codepage-bridge',
|
|
3
|
+
[string]$Scope = 'user'
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
$ErrorActionPreference = 'Stop'
|
|
7
|
+
|
|
8
|
+
function Require-Command($name) {
|
|
9
|
+
if (-not (Get-Command $name -ErrorAction SilentlyContinue)) {
|
|
10
|
+
throw "Required command not found: $name"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
Require-Command node
|
|
15
|
+
Require-Command claude
|
|
16
|
+
|
|
17
|
+
$packageRoot = Split-Path -Parent $PSScriptRoot
|
|
18
|
+
$entry = Join-Path $packageRoot 'dist\src\server.js'
|
|
19
|
+
|
|
20
|
+
if (-not (Test-Path $entry)) {
|
|
21
|
+
throw "This directory does not look like an extracted Codepage Bridge release package. Missing: $entry"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
Write-Host "[1/2] Registering Claude Code MCP from this release package..."
|
|
25
|
+
try { claude mcp remove $ServerName --scope $Scope | Out-Null } catch {}
|
|
26
|
+
claude mcp add --scope $Scope $ServerName -- node $entry
|
|
27
|
+
|
|
28
|
+
Write-Host "[2/2] Verifying MCP connection..."
|
|
29
|
+
claude mcp get $ServerName
|
|
30
|
+
|
|
31
|
+
Write-Host ""
|
|
32
|
+
Write-Host "Installed $ServerName from the current extracted release package." -ForegroundColor Green
|
|
33
|
+
Write-Host "Next required steps:" -ForegroundColor Yellow
|
|
34
|
+
Write-Host "1. Merge examples/claude-config/settings.fragment.json into ~/.claude/settings.json"
|
|
35
|
+
Write-Host "2. Add CLAUDE.md policy from examples/minimal-project/CLAUDE.md"
|
|
36
|
+
Write-Host "3. Add a .encoding-rules file to each legacy-encoded project"
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "codepage-bridge-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Encoding-transparent MCP file tools for legacy codepages in Claude Code",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"codepage-bridge-mcp": "dist/src/server.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/src/",
|
|
12
|
+
"LICENSE",
|
|
13
|
+
"README.md",
|
|
14
|
+
"README_CN.md",
|
|
15
|
+
"examples/",
|
|
16
|
+
"install/",
|
|
17
|
+
".claude-plugin/",
|
|
18
|
+
".mcp.json"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"clean": "node -e \"const fs=require('fs'); fs.rmSync('dist',{recursive:true,force:true})\"",
|
|
22
|
+
"build": "tsc -p tsconfig.json",
|
|
23
|
+
"check": "tsc -p tsconfig.json --noEmit",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"start": "node dist/src/server.js",
|
|
26
|
+
"prepublishOnly": "npm run check && npm test && npm run build"
|
|
27
|
+
},
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git+https://github.com/skyispainted/codepage-bridge-mcp.git"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/skyispainted/codepage-bridge-mcp#readme",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/skyispainted/codepage-bridge-mcp/issues"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"claude-code",
|
|
38
|
+
"mcp",
|
|
39
|
+
"encoding",
|
|
40
|
+
"gbk",
|
|
41
|
+
"legacy-codepage",
|
|
42
|
+
"grep",
|
|
43
|
+
"read",
|
|
44
|
+
"edit",
|
|
45
|
+
"write"
|
|
46
|
+
],
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=20"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@modelcontextprotocol/sdk": "^1.17.0",
|
|
52
|
+
"diff": "^8.0.2",
|
|
53
|
+
"iconv-lite": "^0.6.3",
|
|
54
|
+
"picomatch": "^4.0.3",
|
|
55
|
+
"sharp": "^0.34.3"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@types/diff": "^7.0.2",
|
|
59
|
+
"@types/node": "^24.0.15",
|
|
60
|
+
"@types/picomatch": "^4.0.2",
|
|
61
|
+
"typescript": "^5.8.3",
|
|
62
|
+
"vitest": "^3.2.4"
|
|
63
|
+
}
|
|
64
|
+
}
|