autojs6-mcp-bridge 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/CHANGELOG.md +8 -0
- package/LICENSE +373 -0
- package/README-zh-Hans.md +147 -0
- package/README.md +163 -0
- package/dist/bridge.d.ts +65 -0
- package/dist/bridge.js +186 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +80 -0
- package/dist/errors.d.ts +7 -0
- package/dist/errors.js +62 -0
- package/dist/forward.d.ts +27 -0
- package/dist/forward.js +82 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/options.d.ts +39 -0
- package/dist/options.js +118 -0
- package/package.json +52 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { Bridge, DRAIN_TIMEOUT_MS, INITIALIZE_ATTEMPTS, INITIALIZE_RETRY_DELAY_MS, isRetryableConnectionError, type BridgeConfig } from './bridge.js';
|
|
2
|
+
export { AdbForward, AdbForwardError, spawnRunner, type CommandResult, type CommandRunner } from './forward.js';
|
|
3
|
+
export { BRIDGE_ERROR_CODE, describeError } from './errors.js';
|
|
4
|
+
export { ADB_ENV, DEFAULT_URL, OptionError, TOKEN_ENV, USAGE, endpointPort, isLoopback, parseOptions, type BridgeOptions, type ParsedCommand } from './options.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { Bridge, DRAIN_TIMEOUT_MS, INITIALIZE_ATTEMPTS, INITIALIZE_RETRY_DELAY_MS, isRetryableConnectionError } from './bridge.js';
|
|
2
|
+
export { AdbForward, AdbForwardError, spawnRunner } from './forward.js';
|
|
3
|
+
export { BRIDGE_ERROR_CODE, describeError } from './errors.js';
|
|
4
|
+
export { ADB_ENV, DEFAULT_URL, OptionError, TOKEN_ENV, USAGE, endpointPort, isLoopback, parseOptions } from './options.js';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command line and environment parsing for the bridge. The token is read from
|
|
3
|
+
* `AUTOJS6_MCP_TOKEN` first so that it never has to appear in process arguments;
|
|
4
|
+
* `--token` is accepted for one-off use and produces a warning.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DEFAULT_URL = "http://127.0.0.1:9637/mcp";
|
|
7
|
+
export declare const TOKEN_ENV = "AUTOJS6_MCP_TOKEN";
|
|
8
|
+
export declare const ADB_ENV = "AUTOJS6_MCP_ADB";
|
|
9
|
+
export interface BridgeOptions {
|
|
10
|
+
/** Streamable HTTP endpoint of the phone, for example `http://127.0.0.1:9637/mcp`. */
|
|
11
|
+
url: URL;
|
|
12
|
+
/** Bearer token copied from the plugin settings page. */
|
|
13
|
+
token: string;
|
|
14
|
+
/** `adb -s <serial>` target; implies `forward`. */
|
|
15
|
+
serial?: string;
|
|
16
|
+
/** Run `adb forward tcp:<port> tcp:<port>` before connecting and remove it on exit. */
|
|
17
|
+
forward: boolean;
|
|
18
|
+
/** adb executable; defaults to `adb` on the PATH. */
|
|
19
|
+
adb: string;
|
|
20
|
+
/** Protocol version to request from the phone instead of the one the client asked for. */
|
|
21
|
+
protocol?: string;
|
|
22
|
+
/** Warnings collected while parsing; printed to stderr by the CLI. */
|
|
23
|
+
warnings: string[];
|
|
24
|
+
}
|
|
25
|
+
export type ParsedCommand = {
|
|
26
|
+
kind: 'run';
|
|
27
|
+
options: BridgeOptions;
|
|
28
|
+
} | {
|
|
29
|
+
kind: 'help';
|
|
30
|
+
} | {
|
|
31
|
+
kind: 'version';
|
|
32
|
+
};
|
|
33
|
+
export declare class OptionError extends Error {
|
|
34
|
+
}
|
|
35
|
+
export declare const USAGE = "Usage: autojs6-mcp-bridge [options]\n\nBridges a stdio MCP client to the AutoJs6 MCP Server plugin over Streamable HTTP.\n\nOptions:\n --url <url> Endpoint of the phone (default: http://127.0.0.1:9637/mcp)\n --serial <serial> Run \"adb -s <serial> forward\" for the endpoint port and remove it on exit\n --forward Run \"adb forward\" without -s (single device or emulator)\n --adb <path> adb executable (default: adb on the PATH, or AUTOJS6_MCP_ADB)\n --protocol <date> Request this MCP protocol version from the phone instead of the client's\n --token <token> Bearer token; prefer the AUTOJS6_MCP_TOKEN environment variable\n -h, --help Show this help\n -v, --version Show the version\n\nEnvironment:\n AUTOJS6_MCP_TOKEN Bearer token from the plugin settings page (preferred over --token)\n AUTOJS6_MCP_ADB adb executable when it is not on the PATH\n";
|
|
36
|
+
export declare function parseOptions(argv: readonly string[], env: NodeJS.ProcessEnv): ParsedCommand;
|
|
37
|
+
export declare function isLoopback(hostname: string): boolean;
|
|
38
|
+
/** The TCP port of the endpoint, with the scheme default when the URL has none. */
|
|
39
|
+
export declare function endpointPort(url: URL): number;
|
package/dist/options.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command line and environment parsing for the bridge. The token is read from
|
|
3
|
+
* `AUTOJS6_MCP_TOKEN` first so that it never has to appear in process arguments;
|
|
4
|
+
* `--token` is accepted for one-off use and produces a warning.
|
|
5
|
+
*/
|
|
6
|
+
export const DEFAULT_URL = 'http://127.0.0.1:9637/mcp';
|
|
7
|
+
export const TOKEN_ENV = 'AUTOJS6_MCP_TOKEN';
|
|
8
|
+
export const ADB_ENV = 'AUTOJS6_MCP_ADB';
|
|
9
|
+
export class OptionError extends Error {
|
|
10
|
+
}
|
|
11
|
+
const FLAGS_WITH_VALUE = new Set(['--url', '--token', '--serial', '--adb', '--protocol']);
|
|
12
|
+
const FLAGS_WITHOUT_VALUE = new Set(['--forward', '--help', '-h', '--version', '-v']);
|
|
13
|
+
const PROTOCOL_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
14
|
+
export const USAGE = `Usage: autojs6-mcp-bridge [options]
|
|
15
|
+
|
|
16
|
+
Bridges a stdio MCP client to the AutoJs6 MCP Server plugin over Streamable HTTP.
|
|
17
|
+
|
|
18
|
+
Options:
|
|
19
|
+
--url <url> Endpoint of the phone (default: ${DEFAULT_URL})
|
|
20
|
+
--serial <serial> Run "adb -s <serial> forward" for the endpoint port and remove it on exit
|
|
21
|
+
--forward Run "adb forward" without -s (single device or emulator)
|
|
22
|
+
--adb <path> adb executable (default: adb on the PATH, or ${ADB_ENV})
|
|
23
|
+
--protocol <date> Request this MCP protocol version from the phone instead of the client's
|
|
24
|
+
--token <token> Bearer token; prefer the ${TOKEN_ENV} environment variable
|
|
25
|
+
-h, --help Show this help
|
|
26
|
+
-v, --version Show the version
|
|
27
|
+
|
|
28
|
+
Environment:
|
|
29
|
+
${TOKEN_ENV} Bearer token from the plugin settings page (preferred over --token)
|
|
30
|
+
${ADB_ENV} adb executable when it is not on the PATH
|
|
31
|
+
`;
|
|
32
|
+
export function parseOptions(argv, env) {
|
|
33
|
+
const values = new Map();
|
|
34
|
+
const flags = new Set();
|
|
35
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
36
|
+
const arg = argv[index];
|
|
37
|
+
const equals = arg.indexOf('=');
|
|
38
|
+
if (arg.startsWith('--') && equals > 0 && FLAGS_WITH_VALUE.has(arg.slice(0, equals))) {
|
|
39
|
+
values.set(arg.slice(0, equals), arg.slice(equals + 1));
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (FLAGS_WITH_VALUE.has(arg)) {
|
|
43
|
+
const value = argv[index + 1];
|
|
44
|
+
if (value === undefined || value.startsWith('--')) {
|
|
45
|
+
throw new OptionError(`${arg} needs a value`);
|
|
46
|
+
}
|
|
47
|
+
values.set(arg, value);
|
|
48
|
+
index += 1;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (FLAGS_WITHOUT_VALUE.has(arg)) {
|
|
52
|
+
flags.add(arg);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
throw new OptionError(`Unknown argument: ${arg}\n\n${USAGE}`);
|
|
56
|
+
}
|
|
57
|
+
if (flags.has('--help') || flags.has('-h')) {
|
|
58
|
+
return { kind: 'help' };
|
|
59
|
+
}
|
|
60
|
+
if (flags.has('--version') || flags.has('-v')) {
|
|
61
|
+
return { kind: 'version' };
|
|
62
|
+
}
|
|
63
|
+
const warnings = [];
|
|
64
|
+
const url = parseUrl(values.get('--url') ?? DEFAULT_URL);
|
|
65
|
+
const serial = values.get('--serial')?.trim() || undefined;
|
|
66
|
+
const forward = flags.has('--forward') || serial !== undefined;
|
|
67
|
+
if (forward && !isLoopback(url.hostname)) {
|
|
68
|
+
throw new OptionError(`--serial / --forward only make sense with a loopback URL; ${url.origin} is reached over the network directly`);
|
|
69
|
+
}
|
|
70
|
+
const envToken = env[TOKEN_ENV]?.trim();
|
|
71
|
+
const argToken = values.get('--token')?.trim();
|
|
72
|
+
if (argToken) {
|
|
73
|
+
warnings.push(`--token is visible to other processes; prefer the ${TOKEN_ENV} environment variable`);
|
|
74
|
+
}
|
|
75
|
+
if (envToken && argToken && envToken !== argToken) {
|
|
76
|
+
warnings.push(`both ${TOKEN_ENV} and --token are set; using ${TOKEN_ENV}`);
|
|
77
|
+
}
|
|
78
|
+
const token = envToken || argToken;
|
|
79
|
+
if (!token) {
|
|
80
|
+
throw new OptionError(`No token: set ${TOKEN_ENV} (copy it from the plugin settings page) or pass --token`);
|
|
81
|
+
}
|
|
82
|
+
if (!/^[A-Za-z0-9_-]{32,256}$/.test(token)) {
|
|
83
|
+
throw new OptionError('The token must be 32 to 256 characters of letters, digits, "-" or "_"; copy it again from the plugin settings page');
|
|
84
|
+
}
|
|
85
|
+
const protocol = values.get('--protocol')?.trim() || undefined;
|
|
86
|
+
if (protocol !== undefined && !PROTOCOL_PATTERN.test(protocol)) {
|
|
87
|
+
throw new OptionError(`--protocol expects a version date such as 2025-06-18, not "${protocol}"`);
|
|
88
|
+
}
|
|
89
|
+
const adb = values.get('--adb')?.trim() || env[ADB_ENV]?.trim() || 'adb';
|
|
90
|
+
return { kind: 'run', options: { url, token, serial, forward, adb, protocol, warnings } };
|
|
91
|
+
}
|
|
92
|
+
function parseUrl(text) {
|
|
93
|
+
let url;
|
|
94
|
+
try {
|
|
95
|
+
url = new URL(text);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
throw new OptionError(`--url is not a valid URL: "${text}"`);
|
|
99
|
+
}
|
|
100
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
101
|
+
throw new OptionError(`--url must start with http:// or https://, not ${url.protocol}`);
|
|
102
|
+
}
|
|
103
|
+
if (url.username || url.password) {
|
|
104
|
+
throw new OptionError('--url must not contain credentials; the token goes into the environment');
|
|
105
|
+
}
|
|
106
|
+
return url;
|
|
107
|
+
}
|
|
108
|
+
export function isLoopback(hostname) {
|
|
109
|
+
const host = hostname.replace(/^\[|\]$/g, '');
|
|
110
|
+
return host === 'localhost' || host === '::1' || /^127\.\d+\.\d+\.\d+$/.test(host);
|
|
111
|
+
}
|
|
112
|
+
/** The TCP port of the endpoint, with the scheme default when the URL has none. */
|
|
113
|
+
export function endpointPort(url) {
|
|
114
|
+
if (url.port) {
|
|
115
|
+
return Number(url.port);
|
|
116
|
+
}
|
|
117
|
+
return url.protocol === 'https:' ? 443 : 80;
|
|
118
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "autojs6-mcp-bridge",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "stdio to Streamable HTTP bridge for the AutoJs6 MCP Server plugin: lets stdio-only MCP clients such as Claude Desktop reach the phone",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"autojs6",
|
|
7
|
+
"mcp",
|
|
8
|
+
"model-context-protocol",
|
|
9
|
+
"android",
|
|
10
|
+
"stdio",
|
|
11
|
+
"bridge"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/SuperMonster003/AutoJs6-MCP-Bridge#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/SuperMonster003/AutoJs6-MCP-Bridge/issues"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/SuperMonster003/AutoJs6-MCP-Bridge.git"
|
|
20
|
+
},
|
|
21
|
+
"license": "MPL-2.0",
|
|
22
|
+
"author": "SuperMonster003",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "dist/index.js",
|
|
25
|
+
"types": "dist/index.d.ts",
|
|
26
|
+
"bin": {
|
|
27
|
+
"autojs6-mcp-bridge": "dist/cli.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"README.md",
|
|
32
|
+
"README-zh-Hans.md",
|
|
33
|
+
"CHANGELOG.md",
|
|
34
|
+
"LICENSE"
|
|
35
|
+
],
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=18"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsc -p tsconfig.json",
|
|
41
|
+
"test": "npm run build && node --test",
|
|
42
|
+
"prepack": "npm run build",
|
|
43
|
+
"pack:check": "npm pack --dry-run"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@modelcontextprotocol/sdk": "^1.30.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "^18.19.0",
|
|
50
|
+
"typescript": "^5.6.0"
|
|
51
|
+
}
|
|
52
|
+
}
|