@peektag-ai/cli 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/LICENSE +21 -0
- package/README.md +69 -0
- package/dist/arguments.d.ts +3 -0
- package/dist/arguments.js +18 -0
- package/dist/arguments.js.map +1 -0
- package/dist/auth.d.ts +14 -0
- package/dist/auth.js +202 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +145 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +14 -0
- package/dist/config.js +43 -0
- package/dist/config.js.map +1 -0
- package/dist/installer.d.ts +3 -0
- package/dist/installer.js +42 -0
- package/dist/installer.js.map +1 -0
- package/dist/mcp.d.ts +11 -0
- package/dist/mcp.js +54 -0
- package/dist/mcp.js.map +1 -0
- package/dist/output.d.ts +6 -0
- package/dist/output.js +12 -0
- package/dist/output.js.map +1 -0
- package/package.json +52 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PeekTag
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# PeekTag CLI
|
|
2
|
+
|
|
3
|
+
Official command-line client for PeekTag's remote MCP server. It uses the same tools as the PeekTag ChatGPT integration, keeps large IDs as strings, signs users in with OAuth Authorization Code + PKCE, and stores refresh tokens in the operating-system credential store.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
Node.js 20 or newer is required.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @peektag-ai/cli
|
|
11
|
+
peektag auth login
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
For local development:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install
|
|
18
|
+
npm run build
|
|
19
|
+
npm link
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Common commands
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
peektag auth status
|
|
26
|
+
peektag mcp tools
|
|
27
|
+
peektag mcp install claude-code
|
|
28
|
+
peektag mcp install cursor
|
|
29
|
+
peektag mcp install codex
|
|
30
|
+
|
|
31
|
+
peektag tag search "healthy lunch"
|
|
32
|
+
peektag tag resolve "My restaurant"
|
|
33
|
+
peektag tag ask "9007199254740993" "Suggest a light meal"
|
|
34
|
+
peektag tag templates --query menu
|
|
35
|
+
peektag tag draft build "9007199254740993" --note "Create a modern seasonal menu"
|
|
36
|
+
peektag tag draft refine "9007199254740993" draft.json --note "Use a warmer palette"
|
|
37
|
+
peektag tag create "9007199254740993" "Summer menu" draft.json --yes
|
|
38
|
+
|
|
39
|
+
peektag booking resources "9007199254740993"
|
|
40
|
+
peektag booking availability "9007199254740993" --from "2026-08-08T09:00:00Z"
|
|
41
|
+
peektag booking create "9007199254740993" "2026-08-08T10:00:00Z" --name "Sam" --email "sam@example.com" --yes
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Use `--json` for automation. `PEEKTAG_ACCESS_TOKEN` can supply a short-lived bearer token in CI without writing it to disk. Never put this value in source control or command history.
|
|
45
|
+
|
|
46
|
+
## Configuration
|
|
47
|
+
|
|
48
|
+
Defaults:
|
|
49
|
+
|
|
50
|
+
- MCP URL: `https://gateway.peektag.com/mcp`
|
|
51
|
+
- OAuth authority: `https://identity.peektag.com/realms/PeekTag`
|
|
52
|
+
- OAuth client ID: `peektag-cli`
|
|
53
|
+
- Scope: `openid profile email offline_access peektag.mcp`
|
|
54
|
+
|
|
55
|
+
Use `peektag config show` and `peektag config set`. Environment overrides are `PEEKTAG_MCP_URL`, `PEEKTAG_AUTHORITY`, `PEEKTAG_OAUTH_CLIENT_ID`, and `PEEKTAG_OAUTH_SCOPE`. Only non-secret configuration is written to the config file.
|
|
56
|
+
|
|
57
|
+
The Keycloak realm must contain a public `peektag-cli` client with Standard Flow and PKCE S256 enabled. Allow loopback redirects matching `http://127.0.0.1:*/callback`, map the `peektag.mcp` scope into access tokens, and include the API's accepted audience. Keep Direct Access Grants and client authentication disabled.
|
|
58
|
+
|
|
59
|
+
## Safety
|
|
60
|
+
|
|
61
|
+
Commands that create tags or bookings require `--yes`. Use an idempotency key when retrying a booking. Remote URLs must use HTTPS; plain HTTP is accepted only for loopback development endpoints.
|
|
62
|
+
|
|
63
|
+
## Development
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm run check
|
|
67
|
+
npm test
|
|
68
|
+
npm pack --dry-run
|
|
69
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function optional(key, value) {
|
|
2
|
+
return value === undefined ? {} : { [key]: value };
|
|
3
|
+
}
|
|
4
|
+
export function positiveInteger(value) {
|
|
5
|
+
if (!/^\d+$/.test(value))
|
|
6
|
+
throw new Error(`Expected a positive integer, received: ${value}`);
|
|
7
|
+
const parsed = Number(value);
|
|
8
|
+
if (!Number.isSafeInteger(parsed) || parsed < 1)
|
|
9
|
+
throw new Error(`Expected a positive integer, received: ${value}`);
|
|
10
|
+
return parsed;
|
|
11
|
+
}
|
|
12
|
+
export function jsonObject(value) {
|
|
13
|
+
const parsed = JSON.parse(value);
|
|
14
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
15
|
+
throw new Error("Arguments must be a JSON object.");
|
|
16
|
+
return parsed;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=arguments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arguments.js","sourceRoot":"","sources":["../src/arguments.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAI,GAAW,EAAE,KAAoB;IAC3D,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,KAAK,EAAE,CAAC,CAAC;IAC7F,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,KAAK,EAAE,CAAC,CAAC;IACpH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAY,CAAC;IAC5C,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACxH,OAAO,MAAiC,CAAC;AAC3C,CAAC"}
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CliConfig } from "./config.js";
|
|
2
|
+
export interface StoredTokens {
|
|
3
|
+
accessToken: string;
|
|
4
|
+
refreshToken?: string;
|
|
5
|
+
expiresAt: number;
|
|
6
|
+
scope?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function readStoredTokens(config: CliConfig): Promise<StoredTokens | undefined>;
|
|
9
|
+
export declare function getAccessToken(config: CliConfig): Promise<string>;
|
|
10
|
+
declare function openBrowser(url: string): void;
|
|
11
|
+
export declare function login(config: CliConfig, open?: typeof openBrowser): Promise<StoredTokens>;
|
|
12
|
+
export declare function logout(config: CliConfig): Promise<boolean>;
|
|
13
|
+
export declare function tokenIdentity(accessToken: string): Record<string, unknown>;
|
|
14
|
+
export {};
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { createServer } from "node:http";
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import { AsyncEntry } from "@napi-rs/keyring";
|
|
5
|
+
import { assertHttpsOrLoopback } from "./config.js";
|
|
6
|
+
const KEYRING_SERVICE = "com.peektag.cli";
|
|
7
|
+
const CALLBACK_TIMEOUT_MS = 180_000;
|
|
8
|
+
function keyring(config) {
|
|
9
|
+
return new AsyncEntry(KEYRING_SERVICE, `${config.authority}|${config.clientId}`);
|
|
10
|
+
}
|
|
11
|
+
async function discover(config) {
|
|
12
|
+
const authority = assertHttpsOrLoopback(config.authority, "OAuth authority");
|
|
13
|
+
const discoveryUrl = new URL(`${authority.pathname.replace(/\/$/, "")}/.well-known/openid-configuration`, authority);
|
|
14
|
+
const response = await fetch(discoveryUrl, { headers: { Accept: "application/json" } });
|
|
15
|
+
if (!response.ok)
|
|
16
|
+
throw new Error(`OAuth discovery failed (${response.status}).`);
|
|
17
|
+
const metadata = await response.json();
|
|
18
|
+
assertHttpsOrLoopback(metadata.authorization_endpoint, "OAuth authorization endpoint");
|
|
19
|
+
assertHttpsOrLoopback(metadata.token_endpoint, "OAuth token endpoint");
|
|
20
|
+
return metadata;
|
|
21
|
+
}
|
|
22
|
+
function toStoredTokens(response, previousRefreshToken) {
|
|
23
|
+
const refreshToken = response.refresh_token ?? previousRefreshToken;
|
|
24
|
+
return {
|
|
25
|
+
accessToken: response.access_token,
|
|
26
|
+
...(refreshToken ? { refreshToken } : {}),
|
|
27
|
+
expiresAt: Date.now() + Math.max(0, response.expires_in - 30) * 1000,
|
|
28
|
+
...(response.scope ? { scope: response.scope } : {}),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async function persist(config, tokens) {
|
|
32
|
+
try {
|
|
33
|
+
await keyring(config).setPassword(JSON.stringify(tokens));
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
throw new Error(`Could not store credentials in the operating-system keychain: ${error.message}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export async function readStoredTokens(config) {
|
|
40
|
+
try {
|
|
41
|
+
const value = await keyring(config).getPassword();
|
|
42
|
+
return value ? JSON.parse(value) : undefined;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (/NoEntry/i.test(error.message))
|
|
46
|
+
return undefined;
|
|
47
|
+
throw new Error(`Could not read credentials from the operating-system keychain: ${error.message}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async function tokenRequest(endpoint, fields) {
|
|
51
|
+
const response = await fetch(endpoint, {
|
|
52
|
+
method: "POST",
|
|
53
|
+
headers: { Accept: "application/json", "Content-Type": "application/x-www-form-urlencoded" },
|
|
54
|
+
body: new URLSearchParams(fields),
|
|
55
|
+
});
|
|
56
|
+
const body = await response.json().catch(() => ({}));
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
const detail = typeof body.error_description === "string" ? body.error_description : `HTTP ${response.status}`;
|
|
59
|
+
throw new Error(`OAuth token request failed: ${detail}`);
|
|
60
|
+
}
|
|
61
|
+
if (typeof body.access_token !== "string" || typeof body.expires_in !== "number") {
|
|
62
|
+
throw new Error("OAuth token response was invalid.");
|
|
63
|
+
}
|
|
64
|
+
return body;
|
|
65
|
+
}
|
|
66
|
+
export async function getAccessToken(config) {
|
|
67
|
+
const environmentToken = process.env.PEEKTAG_ACCESS_TOKEN;
|
|
68
|
+
if (environmentToken)
|
|
69
|
+
return environmentToken;
|
|
70
|
+
const tokens = await readStoredTokens(config);
|
|
71
|
+
if (!tokens)
|
|
72
|
+
throw new Error("Not signed in. Run `peektag auth login` or set PEEKTAG_ACCESS_TOKEN.");
|
|
73
|
+
if (tokens.expiresAt > Date.now())
|
|
74
|
+
return tokens.accessToken;
|
|
75
|
+
if (!tokens.refreshToken)
|
|
76
|
+
throw new Error("Your PeekTag session expired. Run `peektag auth login` again.");
|
|
77
|
+
const metadata = await discover(config);
|
|
78
|
+
const refreshed = await tokenRequest(metadata.token_endpoint, {
|
|
79
|
+
grant_type: "refresh_token",
|
|
80
|
+
client_id: config.clientId,
|
|
81
|
+
refresh_token: tokens.refreshToken,
|
|
82
|
+
scope: config.scope,
|
|
83
|
+
});
|
|
84
|
+
const stored = toStoredTokens(refreshed, tokens.refreshToken);
|
|
85
|
+
await persist(config, stored);
|
|
86
|
+
return stored.accessToken;
|
|
87
|
+
}
|
|
88
|
+
function base64Url(bytes) {
|
|
89
|
+
return bytes.toString("base64url");
|
|
90
|
+
}
|
|
91
|
+
function openBrowser(url) {
|
|
92
|
+
const command = process.platform === "win32" ? "cmd" : process.platform === "darwin" ? "open" : "xdg-open";
|
|
93
|
+
const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
94
|
+
const child = spawn(command, args, { detached: true, stdio: "ignore", windowsHide: true });
|
|
95
|
+
child.unref();
|
|
96
|
+
}
|
|
97
|
+
export async function login(config, open = openBrowser) {
|
|
98
|
+
const metadata = await discover(config);
|
|
99
|
+
const verifier = base64Url(randomBytes(48));
|
|
100
|
+
const challenge = base64Url(createHash("sha256").update(verifier).digest());
|
|
101
|
+
const expectedState = base64Url(randomBytes(24));
|
|
102
|
+
const callback = await new Promise((resolve, reject) => {
|
|
103
|
+
const server = createServer();
|
|
104
|
+
server.once("error", reject);
|
|
105
|
+
server.listen(0, "127.0.0.1", () => {
|
|
106
|
+
const address = server.address();
|
|
107
|
+
if (!address || typeof address === "string")
|
|
108
|
+
return reject(new Error("Could not start OAuth callback server."));
|
|
109
|
+
let settle;
|
|
110
|
+
let fail;
|
|
111
|
+
const code = new Promise((res, rej) => { settle = res; fail = rej; });
|
|
112
|
+
const timer = setTimeout(() => fail(new Error("OAuth login timed out.")), CALLBACK_TIMEOUT_MS);
|
|
113
|
+
server.on("request", (request, response) => {
|
|
114
|
+
const url = new URL(request.url ?? "/", `http://${request.headers.host}`);
|
|
115
|
+
const state = url.searchParams.get("state") ?? "";
|
|
116
|
+
const stateMatches = state.length === expectedState.length && timingSafeEqual(Buffer.from(state), Buffer.from(expectedState));
|
|
117
|
+
const error = url.searchParams.get("error_description") ?? url.searchParams.get("error");
|
|
118
|
+
const authorizationCode = url.searchParams.get("code");
|
|
119
|
+
const success = stateMatches && !error && authorizationCode;
|
|
120
|
+
response.writeHead(success ? 200 : 400, { "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-store" });
|
|
121
|
+
response.end(success ? "<h1>PeekTag connected</h1><p>You can close this window.</p>" : "<h1>PeekTag sign-in failed</h1><p>Return to the terminal.</p>");
|
|
122
|
+
clearTimeout(timer);
|
|
123
|
+
if (!stateMatches)
|
|
124
|
+
fail(new Error("OAuth state validation failed."));
|
|
125
|
+
else if (error)
|
|
126
|
+
fail(new Error(`OAuth login failed: ${error}`));
|
|
127
|
+
else if (!authorizationCode)
|
|
128
|
+
fail(new Error("OAuth callback did not include an authorization code."));
|
|
129
|
+
else
|
|
130
|
+
settle(authorizationCode);
|
|
131
|
+
});
|
|
132
|
+
resolve({ redirectUri: `http://127.0.0.1:${address.port}/callback`, code, close: () => server.close() });
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
try {
|
|
136
|
+
const authorizationUrl = new URL(metadata.authorization_endpoint);
|
|
137
|
+
authorizationUrl.search = new URLSearchParams({
|
|
138
|
+
response_type: "code",
|
|
139
|
+
client_id: config.clientId,
|
|
140
|
+
redirect_uri: callback.redirectUri,
|
|
141
|
+
scope: config.scope,
|
|
142
|
+
state: expectedState,
|
|
143
|
+
code_challenge: challenge,
|
|
144
|
+
code_challenge_method: "S256",
|
|
145
|
+
}).toString();
|
|
146
|
+
open(authorizationUrl.toString());
|
|
147
|
+
const code = await callback.code;
|
|
148
|
+
const tokenResponse = await tokenRequest(metadata.token_endpoint, {
|
|
149
|
+
grant_type: "authorization_code",
|
|
150
|
+
client_id: config.clientId,
|
|
151
|
+
redirect_uri: callback.redirectUri,
|
|
152
|
+
code,
|
|
153
|
+
code_verifier: verifier,
|
|
154
|
+
});
|
|
155
|
+
const stored = toStoredTokens(tokenResponse);
|
|
156
|
+
await persist(config, stored);
|
|
157
|
+
return stored;
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
callback.close();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
export async function logout(config) {
|
|
164
|
+
const tokens = await readStoredTokens(config);
|
|
165
|
+
if (tokens?.refreshToken) {
|
|
166
|
+
const metadata = await discover(config);
|
|
167
|
+
if (metadata.revocation_endpoint) {
|
|
168
|
+
await fetch(metadata.revocation_endpoint, {
|
|
169
|
+
method: "POST",
|
|
170
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
171
|
+
body: new URLSearchParams({ token: tokens.refreshToken, token_type_hint: "refresh_token", client_id: config.clientId }),
|
|
172
|
+
}).catch(() => undefined);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
return await keyring(config).deleteCredential();
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
if (/NoEntry/i.test(error.message))
|
|
180
|
+
return false;
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
export function tokenIdentity(accessToken) {
|
|
185
|
+
const payload = accessToken.split(".")[1];
|
|
186
|
+
if (!payload)
|
|
187
|
+
return {};
|
|
188
|
+
try {
|
|
189
|
+
const claims = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
|
|
190
|
+
return {
|
|
191
|
+
subject: claims.sub,
|
|
192
|
+
username: claims.preferred_username,
|
|
193
|
+
email: claims.email,
|
|
194
|
+
scope: claims.scope ?? claims.scp,
|
|
195
|
+
expiresAt: typeof claims.exp === "number" ? new Date(claims.exp * 1000).toISOString() : undefined,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
return {};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import { getAccessToken, login, logout, readStoredTokens, tokenIdentity } from "./auth.js";
|
|
5
|
+
import { jsonObject, optional, positiveInteger } from "./arguments.js";
|
|
6
|
+
import { loadConfig, saveConfig } from "./config.js";
|
|
7
|
+
import { installMcp } from "./installer.js";
|
|
8
|
+
import { PeekTagMcpClient } from "./mcp.js";
|
|
9
|
+
import { print, printToolResult } from "./output.js";
|
|
10
|
+
function context(command) {
|
|
11
|
+
const globals = command.optsWithGlobals();
|
|
12
|
+
return {
|
|
13
|
+
output: { json: Boolean(globals.json) },
|
|
14
|
+
timeoutMs: globals.timeout ? positiveInteger(globals.timeout) * 1000 : 60_000,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
async function call(command, name, args) {
|
|
18
|
+
const { output, timeoutMs } = context(command);
|
|
19
|
+
const client = new PeekTagMcpClient(await loadConfig(), timeoutMs);
|
|
20
|
+
try {
|
|
21
|
+
await client.connect();
|
|
22
|
+
printToolResult(await client.callTool(name, args), output);
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
await client.close();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function addSearchOptions(command) {
|
|
29
|
+
return command.option("--template <key>", "Filter by template key").option("--limit <count>", "Result limit", positiveInteger);
|
|
30
|
+
}
|
|
31
|
+
const program = new Command()
|
|
32
|
+
.name("peektag")
|
|
33
|
+
.description("Use PeekTag from the command line and MCP-compatible agents.")
|
|
34
|
+
.version("0.1.0")
|
|
35
|
+
.option("--json", "Print machine-readable JSON")
|
|
36
|
+
.option("--timeout <seconds>", "Request timeout in seconds", "60")
|
|
37
|
+
.showSuggestionAfterError();
|
|
38
|
+
const auth = program.command("auth").description("Sign in and manage the local PeekTag session");
|
|
39
|
+
auth.command("login").description("Sign in with OAuth Authorization Code + PKCE").action(async function () {
|
|
40
|
+
const config = await loadConfig();
|
|
41
|
+
process.stderr.write("Opening PeekTag sign-in in your browser…\n");
|
|
42
|
+
const tokens = await login(config);
|
|
43
|
+
print({ authenticated: true, ...tokenIdentity(tokens.accessToken) }, context(this).output);
|
|
44
|
+
});
|
|
45
|
+
auth.command("status").description("Show the active account without exposing tokens").action(async function () {
|
|
46
|
+
const config = await loadConfig();
|
|
47
|
+
const environmentToken = process.env.PEEKTAG_ACCESS_TOKEN;
|
|
48
|
+
const stored = environmentToken ? undefined : await readStoredTokens(config);
|
|
49
|
+
if (!environmentToken && !stored)
|
|
50
|
+
return print({ authenticated: false }, context(this).output);
|
|
51
|
+
const token = await getAccessToken(config);
|
|
52
|
+
print({ authenticated: true, source: environmentToken ? "environment" : "keychain", ...tokenIdentity(token) }, context(this).output);
|
|
53
|
+
});
|
|
54
|
+
auth.command("logout").description("Revoke and remove the local PeekTag session").action(async function () {
|
|
55
|
+
print({ authenticated: false, removed: await logout(await loadConfig()) }, context(this).output);
|
|
56
|
+
});
|
|
57
|
+
const mcp = program.command("mcp").description("Inspect or install the PeekTag MCP connection");
|
|
58
|
+
mcp.command("tools").description("List tools exposed by the configured MCP server").action(async function () {
|
|
59
|
+
const { output, timeoutMs } = context(this);
|
|
60
|
+
const client = new PeekTagMcpClient(await loadConfig(), timeoutMs);
|
|
61
|
+
try {
|
|
62
|
+
await client.connect();
|
|
63
|
+
print(await client.listTools(), output);
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
await client.close();
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
mcp.command("call").argument("<tool>").argument("[arguments]", "JSON object", "{}").description("Call any PeekTag MCP tool").action(async function (tool, args) {
|
|
70
|
+
await call(this, tool, jsonObject(args));
|
|
71
|
+
});
|
|
72
|
+
mcp.command("install").argument("<target>", "claude-code, cursor, or codex").description("Add PeekTag to an MCP-compatible coding agent").action(async function (target) {
|
|
73
|
+
if (!["claude-code", "cursor", "codex"].includes(target))
|
|
74
|
+
throw new Error(`Unsupported MCP target: ${target}`);
|
|
75
|
+
print(await installMcp(target, await loadConfig()), context(this).output);
|
|
76
|
+
});
|
|
77
|
+
const tag = program.command("tag").description("Find, ask, draft, and create PeekTags");
|
|
78
|
+
addSearchOptions(tag.command("search").argument("<query>").description("Discover public PeekTags"))
|
|
79
|
+
.action(async function (query, options) {
|
|
80
|
+
await call(this, "peektag_discover_tags", { query, ...optional("template", options.template), ...optional("limit", options.limit) });
|
|
81
|
+
});
|
|
82
|
+
addSearchOptions(tag.command("resolve").argument("<query>").description("Resolve a specific PeekTag"))
|
|
83
|
+
.action(async function (query, options) {
|
|
84
|
+
await call(this, "peektag_resolve_tag", { query, ...optional("template", options.template), ...optional("limit", options.limit) });
|
|
85
|
+
});
|
|
86
|
+
tag.command("ask").argument("<tag-id>").argument("<message>").option("--session <id>").option("--previous-state <state>")
|
|
87
|
+
.description("Ask a PeekTag a question").action(async function (tagId, message, options) {
|
|
88
|
+
await call(this, "peektag_answer", { tagId, message, ...optional("chatSessionId", options.session), ...optional("previousTagState", options.previousState) });
|
|
89
|
+
});
|
|
90
|
+
tag.command("templates").option("--query <text>").option("--template <key>").option("--editor-choice-only").option("--include-unavailable").option("--limit <count>", "Result limit", positiveInteger)
|
|
91
|
+
.description("List AI-build-ready experience templates").action(async function (options) {
|
|
92
|
+
await call(this, "peektag_tag_templates", { ...optional("query", options.query), ...optional("template", options.template), ...optional("editorChoiceOnly", options.editorChoiceOnly), ...optional("includeUnavailable", options.includeUnavailable), ...optional("limit", options.limit) });
|
|
93
|
+
});
|
|
94
|
+
const draft = tag.command("draft").description("Build and refine unsaved tag drafts");
|
|
95
|
+
draft.command("build").argument("<template-id>").option("--note <brief>").option("--attachment <name...>").option("--search-images").option("--extract-metadata").option("--experience-type <type>")
|
|
96
|
+
.description("Build an unsaved ProviderData draft").action(async function (templateId, options) {
|
|
97
|
+
await call(this, "peektag_tag_draft_build", { templateId, ...optional("userNote", options.note), ...optional("attachmentFileNames", options.attachment), ...optional("searchImages", options.searchImages), ...optional("extractMetadata", options.extractMetadata), ...optional("experienceType", options.experienceType) });
|
|
98
|
+
});
|
|
99
|
+
draft.command("refine").argument("<template-id>").argument("<draft-file>").requiredOption("--note <instruction>").option("--attachment <name...>").option("--search-images").option("--extract-metadata")
|
|
100
|
+
.description("Refine ProviderData JSON without saving it").action(async function (templateId, draftFile, options) {
|
|
101
|
+
const currentDataJson = await readFile(draftFile, "utf8");
|
|
102
|
+
JSON.parse(currentDataJson);
|
|
103
|
+
await call(this, "peektag_tag_draft_refine", { templateId, currentDataJson, userNote: options.note, ...optional("attachmentFileNames", options.attachment), ...optional("searchImages", options.searchImages), ...optional("extractMetadata", options.extractMetadata) });
|
|
104
|
+
});
|
|
105
|
+
tag.command("create").argument("<template-id>").argument("<title>").argument("<draft-file>").requiredOption("--yes", "Confirm creation after reviewing the draft").option("--icon <name>").option("--create-embedding").option("--experience-type <type>")
|
|
106
|
+
.description("Create a real tag from a reviewed ProviderData draft").action(async function (templateId, title, draftFile, options) {
|
|
107
|
+
if (!options.yes)
|
|
108
|
+
throw new Error("Review the draft, then pass --yes to create the tag.");
|
|
109
|
+
const dataJson = await readFile(draftFile, "utf8");
|
|
110
|
+
JSON.parse(dataJson);
|
|
111
|
+
await call(this, "peektag_tag_create", { templateId, title, dataJson, ...optional("icon", options.icon), ...optional("createEmbedding", options.createEmbedding), ...optional("experienceType", options.experienceType) });
|
|
112
|
+
});
|
|
113
|
+
const booking = program.command("booking").description("Inspect availability and create bookings");
|
|
114
|
+
booking.command("resources").argument("<tag-id>").action(async function (tagId) { await call(this, "peektag_booking_resources", { tagId }); });
|
|
115
|
+
booking.command("availability").argument("<tag-id>").option("--resource-id <id>").option("--resource-name <name>").option("--from <iso>").option("--to <iso>").option("--time-zone <zone>").option("--duration <minutes>", "Duration", positiveInteger).option("--include-unavailable")
|
|
116
|
+
.action(async function (tagId, options) {
|
|
117
|
+
await call(this, "peektag_booking_availability", { tagId, ...optional("resourceId", options.resourceId), ...optional("resourceName", options.resourceName), ...optional("from", options.from), ...optional("to", options.to), ...optional("timeZone", options.timeZone), ...optional("durationMinutes", options.duration), ...optional("includeUnavailable", options.includeUnavailable) });
|
|
118
|
+
});
|
|
119
|
+
booking.command("nearest").argument("<tag-id>").argument("<preferred-start>").option("--resource-id <id>").option("--resource-name <name>").option("--time-zone <zone>").option("--duration <minutes>", "Duration", positiveInteger).option("--days <count>", "Search window", positiveInteger)
|
|
120
|
+
.action(async function (tagId, preferredStart, options) {
|
|
121
|
+
await call(this, "peektag_booking_nearest", { tagId, preferredStart, ...optional("resourceId", options.resourceId), ...optional("resourceName", options.resourceName), ...optional("timeZone", options.timeZone), ...optional("durationMinutes", options.duration), ...optional("searchWindowDays", options.days) });
|
|
122
|
+
});
|
|
123
|
+
booking.command("create").argument("<tag-id>").argument("<starts-at>").requiredOption("--yes", "Confirm the booking").option("--resource-id <id>").option("--resource-name <name>").option("--ends-at <iso>").option("--time-zone <zone>").option("--duration <minutes>", "Duration", positiveInteger).option("--name <name>").option("--email <email>").option("--phone <phone>").option("--notes <text>").option("--idempotency-key <key>")
|
|
124
|
+
.action(async function (tagId, startsAt, options) {
|
|
125
|
+
if (!options.yes)
|
|
126
|
+
throw new Error("Review the booking details, then pass --yes.");
|
|
127
|
+
await call(this, "peektag_booking_create", { tagId, startsAt, ...optional("resourceId", options.resourceId), ...optional("resourceName", options.resourceName), ...optional("endsAt", options.endsAt), ...optional("timeZone", options.timeZone), ...optional("durationMinutes", options.duration), ...optional("customerName", options.name), ...optional("customerEmail", options.email), ...optional("customerPhone", options.phone), ...optional("notes", options.notes), ...optional("idempotencyKey", options.idempotencyKey) });
|
|
128
|
+
});
|
|
129
|
+
const config = program.command("config").description("View or change non-secret CLI configuration");
|
|
130
|
+
config.command("show").action(async function () { print(await loadConfig(), context(this).output); });
|
|
131
|
+
config.command("set").option("--mcp-url <url>").option("--authority <url>").option("--client-id <id>").option("--scope <scopes>")
|
|
132
|
+
.action(async function (options) {
|
|
133
|
+
const current = await loadConfig();
|
|
134
|
+
const next = { mcpUrl: options.mcpUrl ?? current.mcpUrl, authority: options.authority ?? current.authority, clientId: options.clientId ?? current.clientId, scope: options.scope ?? current.scope };
|
|
135
|
+
await saveConfig(next);
|
|
136
|
+
print(next, context(this).output);
|
|
137
|
+
});
|
|
138
|
+
program.configureOutput({ outputError: (message) => process.stderr.write(message) });
|
|
139
|
+
program.parseAsync().catch((error) => {
|
|
140
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
141
|
+
const json = process.argv.includes("--json");
|
|
142
|
+
process.stderr.write(json ? `${JSON.stringify({ error: { message } })}\n` : `Error: ${message}\n`);
|
|
143
|
+
process.exitCode = 1;
|
|
144
|
+
});
|
|
145
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const DEFAULT_MCP_URL = "https://gateway.peektag.com/mcp";
|
|
2
|
+
export declare const DEFAULT_AUTHORITY = "https://identity.peektag.com/realms/PeekTag";
|
|
3
|
+
export declare const DEFAULT_CLIENT_ID = "peektag-cli";
|
|
4
|
+
export declare const DEFAULT_SCOPE = "openid profile email offline_access peektag.mcp";
|
|
5
|
+
export interface CliConfig {
|
|
6
|
+
mcpUrl: string;
|
|
7
|
+
authority: string;
|
|
8
|
+
clientId: string;
|
|
9
|
+
scope: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function configPath(environment?: NodeJS.ProcessEnv): string;
|
|
12
|
+
export declare function loadConfig(environment?: NodeJS.ProcessEnv): Promise<CliConfig>;
|
|
13
|
+
export declare function saveConfig(config: CliConfig, environment?: NodeJS.ProcessEnv): Promise<void>;
|
|
14
|
+
export declare function assertHttpsOrLoopback(value: string, name: string): URL;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
export const DEFAULT_MCP_URL = "https://gateway.peektag.com/mcp";
|
|
5
|
+
export const DEFAULT_AUTHORITY = "https://identity.peektag.com/realms/PeekTag";
|
|
6
|
+
export const DEFAULT_CLIENT_ID = "peektag-cli";
|
|
7
|
+
export const DEFAULT_SCOPE = "openid profile email offline_access peektag.mcp";
|
|
8
|
+
export function configPath(environment = process.env) {
|
|
9
|
+
const base = process.platform === "win32"
|
|
10
|
+
? environment.APPDATA ?? join(homedir(), "AppData", "Roaming")
|
|
11
|
+
: environment.XDG_CONFIG_HOME ?? join(homedir(), ".config");
|
|
12
|
+
return join(base, "peektag", "config.json");
|
|
13
|
+
}
|
|
14
|
+
export async function loadConfig(environment = process.env) {
|
|
15
|
+
let stored = {};
|
|
16
|
+
try {
|
|
17
|
+
stored = JSON.parse(await readFile(configPath(environment), "utf8"));
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
if (error.code !== "ENOENT")
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
mcpUrl: environment.PEEKTAG_MCP_URL ?? stored.mcpUrl ?? DEFAULT_MCP_URL,
|
|
25
|
+
authority: environment.PEEKTAG_AUTHORITY ?? stored.authority ?? DEFAULT_AUTHORITY,
|
|
26
|
+
clientId: environment.PEEKTAG_OAUTH_CLIENT_ID ?? stored.clientId ?? DEFAULT_CLIENT_ID,
|
|
27
|
+
scope: environment.PEEKTAG_OAUTH_SCOPE ?? stored.scope ?? DEFAULT_SCOPE,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export async function saveConfig(config, environment = process.env) {
|
|
31
|
+
const path = configPath(environment);
|
|
32
|
+
await mkdir(dirname(path), { recursive: true });
|
|
33
|
+
await writeFile(path, `${JSON.stringify(config, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
|
|
34
|
+
}
|
|
35
|
+
export function assertHttpsOrLoopback(value, name) {
|
|
36
|
+
const url = new URL(value);
|
|
37
|
+
const loopback = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]";
|
|
38
|
+
if (url.protocol !== "https:" && !(url.protocol === "http:" && loopback)) {
|
|
39
|
+
throw new Error(`${name} must use HTTPS unless it points to localhost.`);
|
|
40
|
+
}
|
|
41
|
+
return url;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,CAAC,MAAM,eAAe,GAAG,iCAAiC,CAAC;AACjE,MAAM,CAAC,MAAM,iBAAiB,GAAG,6CAA6C,CAAC;AAC/E,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAC/C,MAAM,CAAC,MAAM,aAAa,GAAG,iDAAiD,CAAC;AAS/E,MAAM,UAAU,UAAU,CAAC,cAAiC,OAAO,CAAC,GAAG;IACrE,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO;QACvC,CAAC,CAAC,WAAW,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC;QAC9D,CAAC,CAAC,WAAW,CAAC,eAAe,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IAC9D,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,cAAiC,OAAO,CAAC,GAAG;IAC3E,IAAI,MAAM,GAAuB,EAAE,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,CAAuB,CAAC;IAC7F,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,KAAK,CAAC;IACtE,CAAC;IAED,OAAO;QACL,MAAM,EAAE,WAAW,CAAC,eAAe,IAAI,MAAM,CAAC,MAAM,IAAI,eAAe;QACvE,SAAS,EAAE,WAAW,CAAC,iBAAiB,IAAI,MAAM,CAAC,SAAS,IAAI,iBAAiB;QACjF,QAAQ,EAAE,WAAW,CAAC,uBAAuB,IAAI,MAAM,CAAC,QAAQ,IAAI,iBAAiB;QACrF,KAAK,EAAE,WAAW,CAAC,mBAAmB,IAAI,MAAM,CAAC,KAAK,IAAI,aAAa;KACxE,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAiB,EAAE,cAAiC,OAAO,CAAC,GAAG;IAC9F,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACrC,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACnG,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAa,EAAE,IAAY;IAC/D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3B,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,KAAK,WAAW,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,CAAC;IAC1G,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,QAAQ,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,gDAAgD,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { spawnSync } from "node:child_process";
|
|
5
|
+
import { assertHttpsOrLoopback } from "./config.js";
|
|
6
|
+
function run(command, args) {
|
|
7
|
+
const result = spawnSync(command, args, { stdio: "inherit", shell: process.platform === "win32" });
|
|
8
|
+
if (result.error)
|
|
9
|
+
throw new Error(`Could not run ${command}: ${result.error.message}`);
|
|
10
|
+
if (result.status !== 0)
|
|
11
|
+
throw new Error(`${command} exited with status ${result.status ?? "unknown"}.`);
|
|
12
|
+
}
|
|
13
|
+
async function mergeCursorConfig(url) {
|
|
14
|
+
const path = join(homedir(), ".cursor", "mcp.json");
|
|
15
|
+
let document = {};
|
|
16
|
+
try {
|
|
17
|
+
document = JSON.parse(await readFile(path, "utf8"));
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
if (error.code !== "ENOENT")
|
|
21
|
+
throw new Error(`Cursor MCP config is not valid JSON: ${path}`);
|
|
22
|
+
}
|
|
23
|
+
document.mcpServers = { ...document.mcpServers, peektag: { url } };
|
|
24
|
+
await mkdir(dirname(path), { recursive: true });
|
|
25
|
+
await writeFile(path, `${JSON.stringify(document, null, 2)}\n`, "utf8");
|
|
26
|
+
return path;
|
|
27
|
+
}
|
|
28
|
+
export async function installMcp(target, config) {
|
|
29
|
+
const mcpUrl = assertHttpsOrLoopback(config.mcpUrl, "MCP URL").toString();
|
|
30
|
+
if (process.platform === "win32" && /[&|<>"^]/.test(mcpUrl)) {
|
|
31
|
+
throw new Error("The MCP URL contains characters that cannot be passed safely to a Windows agent installer.");
|
|
32
|
+
}
|
|
33
|
+
if (target === "cursor")
|
|
34
|
+
return `PeekTag added to ${await mergeCursorConfig(mcpUrl)}.`;
|
|
35
|
+
if (target === "claude-code") {
|
|
36
|
+
run("claude", ["mcp", "add", "--transport", "http", "--scope", "user", "peektag", mcpUrl]);
|
|
37
|
+
return "PeekTag added to Claude Code. Run /mcp in Claude Code to sign in.";
|
|
38
|
+
}
|
|
39
|
+
run("codex", ["mcp", "add", "peektag", "--url", mcpUrl]);
|
|
40
|
+
return "PeekTag added to Codex. Run `codex mcp login peektag` to sign in.";
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.js","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAIpD,SAAS,GAAG,CAAC,OAAe,EAAE,IAAc;IAC1C,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC,CAAC;IACnG,IAAI,MAAM,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,OAAO,KAAK,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACvF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,uBAAuB,MAAM,CAAC,MAAM,IAAI,SAAS,GAAG,CAAC,CAAC;AAC3G,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,GAAW;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IACpD,IAAI,QAAQ,GAAqE,EAAE,CAAC;IACpF,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAoB,CAAC;IACzE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,EAAE,CAAC,CAAC;IAC1H,CAAC;IACD,QAAQ,CAAC,UAAU,GAAG,EAAE,GAAG,QAAQ,CAAC,UAAU,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC;IACnE,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAiB,EAAE,MAAiB;IACnE,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC1E,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,4FAA4F,CAAC,CAAC;IAChH,CAAC;IACD,IAAI,MAAM,KAAK,QAAQ;QAAE,OAAO,oBAAoB,MAAM,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC;IACvF,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;QAC7B,GAAG,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;QAC3F,OAAO,mEAAmE,CAAC;IAC7E,CAAC;IACD,GAAG,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IACzD,OAAO,mEAAmE,CAAC;AAC7E,CAAC"}
|
package/dist/mcp.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type CallToolResult } from "@modelcontextprotocol/client";
|
|
2
|
+
import type { CliConfig } from "./config.js";
|
|
3
|
+
export declare class PeekTagMcpClient {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(config: CliConfig, timeoutMs: number);
|
|
6
|
+
connect(): Promise<void>;
|
|
7
|
+
listTools(): Promise<unknown>;
|
|
8
|
+
callTool(name: string, args: Record<string, unknown>): Promise<CallToolResult>;
|
|
9
|
+
close(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export declare function resultPayload(result: CallToolResult): unknown;
|
package/dist/mcp.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Client, StreamableHTTPClientTransport } from "@modelcontextprotocol/client";
|
|
2
|
+
import { assertHttpsOrLoopback } from "./config.js";
|
|
3
|
+
import { getAccessToken } from "./auth.js";
|
|
4
|
+
export class PeekTagMcpClient {
|
|
5
|
+
#client = new Client({ name: "peektag-cli", version: "0.1.0" });
|
|
6
|
+
#config;
|
|
7
|
+
#timeoutMs;
|
|
8
|
+
#transport;
|
|
9
|
+
constructor(config, timeoutMs) {
|
|
10
|
+
this.#config = config;
|
|
11
|
+
this.#timeoutMs = timeoutMs;
|
|
12
|
+
}
|
|
13
|
+
async connect() {
|
|
14
|
+
const token = await getAccessToken(this.#config);
|
|
15
|
+
this.#transport = new StreamableHTTPClientTransport(assertHttpsOrLoopback(this.#config.mcpUrl, "MCP URL"), {
|
|
16
|
+
requestInit: { headers: { Authorization: `Bearer ${token}` } },
|
|
17
|
+
});
|
|
18
|
+
await this.#client.connect(this.#transport);
|
|
19
|
+
}
|
|
20
|
+
async listTools() {
|
|
21
|
+
return this.#client.listTools(undefined, { timeout: this.#timeoutMs });
|
|
22
|
+
}
|
|
23
|
+
async callTool(name, args) {
|
|
24
|
+
const result = await this.#client.callTool({ name, arguments: args }, { timeout: this.#timeoutMs });
|
|
25
|
+
if (result.isError) {
|
|
26
|
+
const message = result.content
|
|
27
|
+
.filter((item) => item.type === "text")
|
|
28
|
+
.map((item) => item.text)
|
|
29
|
+
.join("\n");
|
|
30
|
+
throw new Error(message || `PeekTag tool ${name} failed.`);
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
async close() {
|
|
35
|
+
await this.#transport?.close();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export function resultPayload(result) {
|
|
39
|
+
if (result.structuredContent)
|
|
40
|
+
return result.structuredContent;
|
|
41
|
+
const text = result.content
|
|
42
|
+
.filter((item) => item.type === "text")
|
|
43
|
+
.map((item) => item.text)
|
|
44
|
+
.join("\n");
|
|
45
|
+
if (!text)
|
|
46
|
+
return result.content;
|
|
47
|
+
try {
|
|
48
|
+
return JSON.parse(text);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return text;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=mcp.js.map
|
package/dist/mcp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,6BAA6B,EAAuB,MAAM,8BAA8B,CAAC;AAE1G,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,OAAO,gBAAgB;IAClB,OAAO,GAAG,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAChE,OAAO,CAAY;IACnB,UAAU,CAAS;IAC5B,UAAU,CAAiC;IAE3C,YAAY,MAAiB,EAAE,SAAiB;QAC9C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,UAAU,GAAG,IAAI,6BAA6B,CAAC,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE;YACzG,WAAW,EAAE,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,EAAE;SAC/D,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAY,EAAE,IAA6B;QACxD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QACpG,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO;iBAC3B,MAAM,CAAC,CAAC,IAAI,EAA0C,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;iBAC9E,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;iBACxB,IAAI,CAAC,IAAI,CAAC,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,gBAAgB,IAAI,UAAU,CAAC,CAAC;QAC7D,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC;IACjC,CAAC;CACF;AAED,MAAM,UAAU,aAAa,CAAC,MAAsB;IAClD,IAAI,MAAM,CAAC,iBAAiB;QAAE,OAAO,MAAM,CAAC,iBAAiB,CAAC;IAC9D,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO;SACxB,MAAM,CAAC,CAAC,IAAI,EAA0C,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;SAC9E,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;SACxB,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,IAAI,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC;IACjC,IAAI,CAAC;QAAC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;AACzD,CAAC"}
|
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CallToolResult } from "@modelcontextprotocol/client";
|
|
2
|
+
export interface OutputOptions {
|
|
3
|
+
json: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare function print(value: unknown, options: OutputOptions): void;
|
|
6
|
+
export declare function printToolResult(result: CallToolResult, options: OutputOptions): void;
|
package/dist/output.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { resultPayload } from "./mcp.js";
|
|
2
|
+
export function print(value, options) {
|
|
3
|
+
if (options.json || typeof value !== "string") {
|
|
4
|
+
process.stdout.write(`${JSON.stringify(value, null, options.json ? 0 : 2)}\n`);
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
process.stdout.write(`${value}\n`);
|
|
8
|
+
}
|
|
9
|
+
export function printToolResult(result, options) {
|
|
10
|
+
print(resultPayload(result), options);
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAMzC,MAAM,UAAU,KAAK,CAAC,KAAc,EAAE,OAAsB;IAC1D,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/E,OAAO;IACT,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAsB,EAAE,OAAsB;IAC5E,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;AACxC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@peektag-ai/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Official command-line client for PeekTag MCP tools.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"peektag": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"!dist/**/*.test.*",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc -p tsconfig.json",
|
|
17
|
+
"check": "tsc -p tsconfig.json --noEmit",
|
|
18
|
+
"test": "npm run build && node --test dist/**/*.test.js",
|
|
19
|
+
"start": "node dist/cli.js"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=20"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"peektag",
|
|
26
|
+
"mcp",
|
|
27
|
+
"cli"
|
|
28
|
+
],
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/PeekTag/server.git",
|
|
32
|
+
"directory": "tools/peektag-cli"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/PeekTag/server/tree/main/tools/peektag-cli#readme",
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/PeekTag/server/issues"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public",
|
|
40
|
+
"registry": "https://registry.npmjs.org/"
|
|
41
|
+
},
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@modelcontextprotocol/client": "2.0.0",
|
|
45
|
+
"@napi-rs/keyring": "1.3.0",
|
|
46
|
+
"commander": "14.0.3"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "22.18.0",
|
|
50
|
+
"typescript": "5.9.2"
|
|
51
|
+
}
|
|
52
|
+
}
|