@tellzm/register-oauth-client 0.1.0-beta.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/README.md +44 -0
- package/dist/cli.js +120 -0
- package/package.json +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @axon/register-oauth-client
|
|
2
|
+
|
|
3
|
+
One-shot CLI: register an OAuthClient row on the [Axon](https://tellzm.com) platform so an n8n install (or any other MCP client) can be authorized for a workspace.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @axon/register-oauth-client \
|
|
9
|
+
--token <workspace-admin-access-token> \
|
|
10
|
+
--redirect-uri http://localhost:5678/rest/oauth2-credential/callback \
|
|
11
|
+
--name "My n8n install"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The CLI prints:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
client_id = mcp_7acf7a681f5baf20264f89f7cf8134f0
|
|
18
|
+
name = My n8n install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Paste the `client_id` into your n8n credential.
|
|
22
|
+
|
|
23
|
+
## Flags
|
|
24
|
+
|
|
25
|
+
| Flag | Required | Default | Description |
|
|
26
|
+
|---|---|---|---|
|
|
27
|
+
| `--token` | yes | — | Workspace-admin access token (must belong to a user with `OWNER` or `ADMIN` role). |
|
|
28
|
+
| `--redirect-uri` | yes | — | OAuth callback URL. Repeat for multiple. n8n self-hosted: `<host>/rest/oauth2-credential/callback`. |
|
|
29
|
+
| `--name` | no | `n8n-<timestamp>` | Human-readable label. |
|
|
30
|
+
| `--api-base` | no | `https://api.tellzm.com` | API base URL. Override for UAT (`https://api.uat.tellzm.com`). |
|
|
31
|
+
| `--confidential` | no | (off) | Create a confidential client (secret-bearing). Default is public/PKCE. |
|
|
32
|
+
| `-h`, `--help` | no | — | Show help. |
|
|
33
|
+
|
|
34
|
+
## Troubleshooting
|
|
35
|
+
|
|
36
|
+
| HTTP status | Cause | Fix |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| 401 | Token expired or invalid | Get a fresh token from `tellzm.com/profile`. |
|
|
39
|
+
| 403 | User isn't `OWNER`/`ADMIN` in any workspace | Use a token from a user with the right role. |
|
|
40
|
+
| 400 | Validation error (invalid URI, missing field) | Check the printed error body. |
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
|
|
44
|
+
MIT.
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
// One-shot CLI for registering an OAuthClient row on the Axon platform.
|
|
4
|
+
// Full behavior + tests land in T024–T026. This skeleton parses args and
|
|
5
|
+
// validates them so the binary is executable from day one.
|
|
6
|
+
function parseArgs(argv) {
|
|
7
|
+
const args = {
|
|
8
|
+
redirectUri: [],
|
|
9
|
+
apiBase: "https://api.tellzm.com",
|
|
10
|
+
isPublic: true,
|
|
11
|
+
help: false,
|
|
12
|
+
};
|
|
13
|
+
for (let i = 0; i < argv.length; i++) {
|
|
14
|
+
const a = argv[i];
|
|
15
|
+
switch (a) {
|
|
16
|
+
case "--token":
|
|
17
|
+
args.token = argv[++i];
|
|
18
|
+
break;
|
|
19
|
+
case "--redirect-uri":
|
|
20
|
+
args.redirectUri.push(argv[++i]);
|
|
21
|
+
break;
|
|
22
|
+
case "--name":
|
|
23
|
+
args.name = argv[++i];
|
|
24
|
+
break;
|
|
25
|
+
case "--api-base":
|
|
26
|
+
args.apiBase = argv[++i];
|
|
27
|
+
break;
|
|
28
|
+
case "--confidential":
|
|
29
|
+
args.isPublic = false;
|
|
30
|
+
break;
|
|
31
|
+
case "-h":
|
|
32
|
+
case "--help":
|
|
33
|
+
args.help = true;
|
|
34
|
+
break;
|
|
35
|
+
default:
|
|
36
|
+
if (a.startsWith("--")) {
|
|
37
|
+
process.stderr.write(`Unknown flag: ${a}\n`);
|
|
38
|
+
process.exit(2);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return args;
|
|
43
|
+
}
|
|
44
|
+
function printHelp() {
|
|
45
|
+
process.stdout.write(`
|
|
46
|
+
@axon/register-oauth-client — register an OAuthClient on the Axon platform.
|
|
47
|
+
|
|
48
|
+
USAGE
|
|
49
|
+
npx @axon/register-oauth-client --token <admin-token> --redirect-uri <url> [options]
|
|
50
|
+
|
|
51
|
+
REQUIRED
|
|
52
|
+
--token <token> Workspace-admin access token (OWNER or ADMIN role).
|
|
53
|
+
--redirect-uri <url> n8n callback URL, e.g. http://localhost:5678/rest/oauth2-credential/callback.
|
|
54
|
+
May be repeated for multiple URIs.
|
|
55
|
+
|
|
56
|
+
OPTIONAL
|
|
57
|
+
--name <label> Human-readable label. Defaults to "n8n-<timestamp>".
|
|
58
|
+
--api-base <url> API base URL. Defaults to https://api.tellzm.com.
|
|
59
|
+
--confidential Create a confidential (secret-bearing) client. Default is PKCE/public.
|
|
60
|
+
-h, --help Show this help.
|
|
61
|
+
|
|
62
|
+
EXAMPLE
|
|
63
|
+
npx @axon/register-oauth-client \\
|
|
64
|
+
--token "..." \\
|
|
65
|
+
--redirect-uri http://localhost:5678/rest/oauth2-credential/callback \\
|
|
66
|
+
--name "My local n8n"
|
|
67
|
+
`);
|
|
68
|
+
}
|
|
69
|
+
async function main() {
|
|
70
|
+
const args = parseArgs(process.argv.slice(2));
|
|
71
|
+
if (args.help) {
|
|
72
|
+
printHelp();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (!args.token) {
|
|
76
|
+
process.stderr.write("Error: --token is required.\n");
|
|
77
|
+
process.exit(2);
|
|
78
|
+
}
|
|
79
|
+
if (args.redirectUri.length === 0) {
|
|
80
|
+
process.stderr.write("Error: at least one --redirect-uri is required.\n");
|
|
81
|
+
process.exit(2);
|
|
82
|
+
}
|
|
83
|
+
const url = `${args.apiBase.replace(/\/$/, "")}/admin/oauth-clients`;
|
|
84
|
+
const body = {
|
|
85
|
+
name: args.name ?? `n8n-${new Date().toISOString()}`,
|
|
86
|
+
redirectUris: args.redirectUri,
|
|
87
|
+
isPublic: args.isPublic,
|
|
88
|
+
};
|
|
89
|
+
let res;
|
|
90
|
+
try {
|
|
91
|
+
res = await fetch(url, {
|
|
92
|
+
method: "POST",
|
|
93
|
+
headers: {
|
|
94
|
+
"content-type": "application/json",
|
|
95
|
+
authorization: `Bearer ${args.token}`,
|
|
96
|
+
},
|
|
97
|
+
body: JSON.stringify(body),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
process.stderr.write(`Network error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
const text = await res.text();
|
|
105
|
+
if (!res.ok) {
|
|
106
|
+
process.stderr.write(`HTTP ${res.status}: ${text}\n`);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
const data = JSON.parse(text);
|
|
110
|
+
process.stdout.write(`client_id = ${data.clientId}\n`);
|
|
111
|
+
if (data.clientSecret) {
|
|
112
|
+
process.stdout.write(`client_secret = ${data.clientSecret}\n`);
|
|
113
|
+
process.stdout.write("Save this secret — it will not be shown again.\n");
|
|
114
|
+
}
|
|
115
|
+
process.stdout.write(`name = ${data.name}\n`);
|
|
116
|
+
}
|
|
117
|
+
main().catch((err) => {
|
|
118
|
+
process.stderr.write(`Unexpected error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
119
|
+
process.exit(1);
|
|
120
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tellzm/register-oauth-client",
|
|
3
|
+
"version": "0.1.0-beta.0",
|
|
4
|
+
"description": "One-shot CLI: register an OAuthClient row on the Axon platform so an n8n install (or other MCP client) can be authorized for a workspace.",
|
|
5
|
+
"keywords": ["axon", "tellzm", "oauth", "cli", "n8n"],
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://docs.tellzm.com/n8n",
|
|
8
|
+
"author": { "name": "Axon", "url": "https://tellzm.com" },
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/syncaty/tellzm.git",
|
|
12
|
+
"directory": "packages/register-oauth-client"
|
|
13
|
+
},
|
|
14
|
+
"bin": {
|
|
15
|
+
"register-oauth-client": "dist/cli.js"
|
|
16
|
+
},
|
|
17
|
+
"main": "dist/cli.js",
|
|
18
|
+
"files": ["dist", "README.md"],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"dev": "tsc --watch",
|
|
22
|
+
"typecheck": "tsc --noEmit",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"prepublishOnly": "npm run build"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^20",
|
|
28
|
+
"typescript": "^5",
|
|
29
|
+
"vitest": "^1"
|
|
30
|
+
}
|
|
31
|
+
}
|