@pitcher/cli-scripts 3.0.1 → 3.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/README.md +2 -2
- package/dist/src/commands/scaffolds.js +0 -6
- package/dist/src/core/pitcherAuth.d.ts +12 -1
- package/dist/src/core/pitcherAuth.js +16 -5
- package/dist/src/mcp/hosted.d.ts +15 -0
- package/dist/src/mcp/hosted.js +35 -2
- package/dist/src/mcp/index.d.ts +1 -1
- package/dist/src/mcp/index.js +1 -1
- package/dist/src/mcp/local.d.ts +1 -1
- package/dist/src/mcp/local.js +1 -1
- package/dist/src/mcp/prompts/analytics.js +4 -0
- package/dist/src/mcp/prompts/types.d.ts +1 -0
- package/dist/src/mcp/tools/types.d.ts +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Releases are published to npm automatically: a merge to `main` that bumps `versi
|
|
|
6
6
|
|
|
7
7
|
> ⚠️ **Breaking changes in 3.0.0**
|
|
8
8
|
>
|
|
9
|
-
> 1. **Local `p mcp` now serves ONLY 3 tools** (`pitcher_dev_sync`, `pitcher_dev_sync_revert`, `pitcher_publish_app`), down from 124. Everything else is the hosted server `https://
|
|
9
|
+
> 1. **Local `p mcp` now serves ONLY 3 tools** (`pitcher_dev_sync`, `pitcher_dev_sync_revert`, `pitcher_publish_app`), down from 124. Everything else is the hosted server `https://mcp.pitcher.com/mcp`. `p mcp` no longer reads `NG_API_KEY`/`NG_ORG`/`NG_URL`/`NG_ENV`; run `p login` once (`--domain` or `PITCHER_DOMAIN` when logged in to several orgs).
|
|
10
10
|
> 2. **Every other command uses your `p login` session.** `--api-key` (automation) still wins when passed; `NG_API_KEY` is used only when you have NO `p login` session, and is otherwise ignored with a notice. `--org` no longer defaults to `dev` on the session path: the session's org is the target. `--domain` cannot be combined with `--api-key` or `--org`.
|
|
11
11
|
> 3. **The Claude Desktop `.mcpb` extension is retired.** Claude Desktop adds the remote URL natively.
|
|
12
12
|
> 4. **`p analytics kpi` requires `--type`** (one of the 12 KPI types listed in `p analytics kpi --help`). The old default `all` always returned a 500.
|
|
@@ -44,7 +44,7 @@ Pitcher's MCP tools come from two places:
|
|
|
44
44
|
|
|
45
45
|
| Server | Tools | Add it with |
|
|
46
46
|
|---|---|---|
|
|
47
|
-
| **Hosted** (OAuth; Claude Code, Claude Desktop, claude.ai, ChatGPT) | everything: content, canvases, DSRs, analytics, L&D, users, … (121 tools, prompts, resources) | `claude mcp add --transport http pitcher https://
|
|
47
|
+
| **Hosted** (OAuth; Claude Code, Claude Desktop, claude.ai, ChatGPT) | everything: content, canvases, DSRs, analytics, L&D, users, … (121 tools, prompts, resources) | `claude mcp add --transport http pitcher https://mcp.pitcher.com/mcp` — Claude Desktop: Settings → Connectors → Add custom connector, same URL |
|
|
48
48
|
| **Local** `p mcp` (stdio) | only `pitcher_dev_sync`, `pitcher_dev_sync_revert`, `pitcher_publish_app` (they zip a folder on YOUR machine) | `claude mcp add pitcher-local -- p mcp` |
|
|
49
49
|
|
|
50
50
|
Claude Code users add both. The local server runs on your `p login` session (no API key, no env block); the domain is fixed when it starts. Signed in to several orgs? Add one entry per org:
|
|
@@ -205,7 +205,6 @@ const METADATA_TEMPLATE_SCAFFOLD_DATA = [
|
|
|
205
205
|
is_required: true,
|
|
206
206
|
is_filterable: true,
|
|
207
207
|
is_sortable: true,
|
|
208
|
-
is_pitch_master: false,
|
|
209
208
|
help_text: 'Marketed product name',
|
|
210
209
|
default: '',
|
|
211
210
|
},
|
|
@@ -216,7 +215,6 @@ const METADATA_TEMPLATE_SCAFFOLD_DATA = [
|
|
|
216
215
|
is_required: false,
|
|
217
216
|
is_filterable: true,
|
|
218
217
|
is_sortable: true,
|
|
219
|
-
is_pitch_master: false,
|
|
220
218
|
},
|
|
221
219
|
{
|
|
222
220
|
name: 'therapeutic_area',
|
|
@@ -225,7 +223,6 @@ const METADATA_TEMPLATE_SCAFFOLD_DATA = [
|
|
|
225
223
|
is_required: false,
|
|
226
224
|
is_filterable: true,
|
|
227
225
|
is_sortable: false,
|
|
228
|
-
is_pitch_master: false,
|
|
229
226
|
options: [
|
|
230
227
|
{ label: 'Cardiology', value: 'cardiology' },
|
|
231
228
|
{ label: 'Oncology', value: 'oncology' },
|
|
@@ -239,7 +236,6 @@ const METADATA_TEMPLATE_SCAFFOLD_DATA = [
|
|
|
239
236
|
is_required: false,
|
|
240
237
|
is_filterable: true,
|
|
241
238
|
is_sortable: false,
|
|
242
|
-
is_pitch_master: false,
|
|
243
239
|
options: [
|
|
244
240
|
{ label: 'HCP', value: 'hcp' },
|
|
245
241
|
{ label: 'Payer', value: 'payer' },
|
|
@@ -253,7 +249,6 @@ const METADATA_TEMPLATE_SCAFFOLD_DATA = [
|
|
|
253
249
|
is_required: false,
|
|
254
250
|
is_filterable: false,
|
|
255
251
|
is_sortable: true,
|
|
256
|
-
is_pitch_master: false,
|
|
257
252
|
default: 0,
|
|
258
253
|
},
|
|
259
254
|
{
|
|
@@ -263,7 +258,6 @@ const METADATA_TEMPLATE_SCAFFOLD_DATA = [
|
|
|
263
258
|
is_required: false,
|
|
264
259
|
is_filterable: true,
|
|
265
260
|
is_sortable: false,
|
|
266
|
-
is_pitch_master: false,
|
|
267
261
|
default: false,
|
|
268
262
|
},
|
|
269
263
|
],
|
|
@@ -28,6 +28,8 @@ export declare function orgSubdomain(domain: string): string;
|
|
|
28
28
|
* in step when a tenant is added.
|
|
29
29
|
*/
|
|
30
30
|
export declare const AUTH0_NATIVE_CLIENT_IDS: Readonly<Record<string, string>>;
|
|
31
|
+
/** The hosted MCP connector's access for an org (`pitcher_organization.settings.mcp.access`, PIT-9768). */
|
|
32
|
+
export type McpAccess = 'off' | 'read_only' | 'full';
|
|
31
33
|
export interface OrgConfig {
|
|
32
34
|
/** The Auth0 CUSTOM domain (`auth0.test-eu.pitcher.com`) — the key into the client-id maps. */
|
|
33
35
|
auth0Domain: string;
|
|
@@ -36,6 +38,11 @@ export interface OrgConfig {
|
|
|
36
38
|
organization: string | null;
|
|
37
39
|
/** `'test' | 'production'`. OPTIONAL upstream: treat unknown as production. */
|
|
38
40
|
environment?: string;
|
|
41
|
+
/**
|
|
42
|
+
* undefined = UNKNOWN: next-core's org lookup failed, or that region's next-core predates the field. Never
|
|
43
|
+
* read it as "off" and never as "on" — the hosted server retries or refuses (`mcp-server` `src/oauth/access.ts`).
|
|
44
|
+
*/
|
|
45
|
+
mcpAccess?: McpAccess;
|
|
39
46
|
}
|
|
40
47
|
export interface Auth0Tokens {
|
|
41
48
|
access_token: string;
|
|
@@ -65,7 +72,11 @@ export declare function buildAuthorizeUrl(p: {
|
|
|
65
72
|
state: string;
|
|
66
73
|
codeChallenge: string;
|
|
67
74
|
}): string;
|
|
68
|
-
/**
|
|
75
|
+
/**
|
|
76
|
+
* null = the domain is not a Pitcher org (404, or no auth0 block). Throws an UpstreamError on a network error or
|
|
77
|
+
* any other status: a 400 or a 429 says nothing about the org, and the hosted server reads null as "this token's
|
|
78
|
+
* org is gone" (401, sign in again) where an upstream error is a retryable 503.
|
|
79
|
+
*/
|
|
69
80
|
export declare function fetchOrgConfig(domain: string, opts?: HttpOpts): Promise<OrgConfig | null>;
|
|
70
81
|
export declare function exchangeCode(p: {
|
|
71
82
|
auth0Domain: string;
|
|
@@ -35,7 +35,10 @@ export function orgSubdomain(domain) {
|
|
|
35
35
|
export const AUTH0_NATIVE_CLIENT_IDS = {
|
|
36
36
|
'auth0.test-eu.pitcher.com': 'EvXiukSFA9LmxkoMyGfGrX6tk5eZdJFu',
|
|
37
37
|
'auth0.eu.pitcher.com': 'cJpAajaha7dWc2mnGy3GZSMBm3kzX370',
|
|
38
|
+
'auth0.test-us.pitcher.com': 'sd6biLE9qGBwUfSzl2uRC1p5JdhKY06N',
|
|
39
|
+
'auth0.us.pitcher.com': 'k6BgMI2Oy26RnyucUsWiL81JOeaufECm',
|
|
38
40
|
};
|
|
41
|
+
const MCP_ACCESS = new Set(['off', 'read_only', 'full']);
|
|
39
42
|
export function createUpstreamError(kind, message) {
|
|
40
43
|
return Object.assign(new Error(message), { isUpstreamError: true, kind });
|
|
41
44
|
}
|
|
@@ -60,10 +63,16 @@ export function buildAuthorizeUrl(p) {
|
|
|
60
63
|
}).toString();
|
|
61
64
|
return u.href;
|
|
62
65
|
}
|
|
63
|
-
/**
|
|
66
|
+
/**
|
|
67
|
+
* null = the domain is not a Pitcher org (404, or no auth0 block). Throws an UpstreamError on a network error or
|
|
68
|
+
* any other status: a 400 or a 429 says nothing about the org, and the hosted server reads null as "this token's
|
|
69
|
+
* org is gone" (401, sign in again) where an upstream error is a retryable 503.
|
|
70
|
+
*/
|
|
64
71
|
export async function fetchOrgConfig(domain, opts = {}) {
|
|
65
72
|
const doFetch = opts.fetch ?? globalThis.fetch;
|
|
66
|
-
|
|
73
|
+
// No `org_subdomain` param: the edge sets `x-original-domain` from the host, which names the same org, and
|
|
74
|
+
// next-core reports every request carrying the param to Sentry as deprecated.
|
|
75
|
+
const url = `https://${domain}/core/api/org-config`;
|
|
67
76
|
let res;
|
|
68
77
|
try {
|
|
69
78
|
res = await doFetch(url, {
|
|
@@ -76,10 +85,10 @@ export async function fetchOrgConfig(domain, opts = {}) {
|
|
|
76
85
|
catch {
|
|
77
86
|
throw createUpstreamError('upstream', 'org-config unreachable');
|
|
78
87
|
}
|
|
79
|
-
if (res.status
|
|
80
|
-
throw createUpstreamError('upstream', `org-config returned ${res.status}`);
|
|
81
|
-
if (res.status !== 200)
|
|
88
|
+
if (res.status === 404)
|
|
82
89
|
return null;
|
|
90
|
+
if (res.status !== 200)
|
|
91
|
+
throw createUpstreamError('upstream', `org-config returned ${res.status}`);
|
|
83
92
|
const json = await res.json().catch(() => null);
|
|
84
93
|
const a = json?.auth0;
|
|
85
94
|
if (!a || typeof a.domain !== 'string' || typeof a.audience !== 'string')
|
|
@@ -89,6 +98,8 @@ export async function fetchOrgConfig(domain, opts = {}) {
|
|
|
89
98
|
audience: a.audience,
|
|
90
99
|
organization: typeof a.organization === 'string' && a.organization ? a.organization : null,
|
|
91
100
|
environment: typeof json.environment === 'string' ? json.environment : undefined,
|
|
101
|
+
// A value outside the three is a newer next-core than this code: refuse it like "off", not like unknown.
|
|
102
|
+
mcpAccess: typeof json.mcp?.access === 'string' ? (MCP_ACCESS.has(json.mcp.access) ? json.mcp.access : 'off') : undefined,
|
|
92
103
|
};
|
|
93
104
|
}
|
|
94
105
|
async function postJson(url, body, opts) {
|
package/dist/src/mcp/hosted.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PromptDescriptor } from './prompts/types.js';
|
|
1
2
|
import type { BuildServerOptions } from './server.js';
|
|
2
3
|
import type { ToolDescriptor } from './tools/types.js';
|
|
3
4
|
/**
|
|
@@ -16,6 +17,20 @@ export declare const LOCAL_ONLY: ReadonlySet<string>;
|
|
|
16
17
|
* exposes today (`questionFile`, `answersFile`, `canvasFile`, `assessmentsFile`, `contentHtmlFile`).
|
|
17
18
|
*/
|
|
18
19
|
export declare const FILE_KEY: RegExp;
|
|
20
|
+
/**
|
|
21
|
+
* An id-shaped input (`id`, `instanceId`, `courseIds`, …). Many commands interpolate ids straight into the
|
|
22
|
+
* request PATH (`/api/v1/files/${id}`, the L&D `/admin/courses/${id}`), so a value like `../users/1` or `1?x=`
|
|
23
|
+
* would retarget the call to another endpoint on the same host with the caller's token. Hosted accepts only
|
|
24
|
+
* plain tokens (letters, digits, `_`, `-`; comma-separated lists for string list inputs).
|
|
25
|
+
*/
|
|
26
|
+
export declare const ID_KEY: RegExp;
|
|
19
27
|
/** Build options every hosted server uses: a write always asks the client to confirm. */
|
|
20
28
|
export declare const HOSTED_BUILD_OPTIONS: Readonly<BuildServerOptions>;
|
|
21
29
|
export declare const hostedTools: ToolDescriptor[];
|
|
30
|
+
/**
|
|
31
|
+
* Read-only mode (the org's `settings.mcp.access` is `read_only`, PIT-9768): only the hosted tools that read.
|
|
32
|
+
* A write tool is never registered, so calling one is "unknown tool", not a refused write.
|
|
33
|
+
*/
|
|
34
|
+
export declare const hostedReadOnlyTools: ToolDescriptor[];
|
|
35
|
+
/** The prompts a read-only server serves: only those flagged `readOnly` (the rest drive a write tool). */
|
|
36
|
+
export declare const readOnlyPrompts: PromptDescriptor[];
|
package/dist/src/mcp/hosted.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { fail } from '../core/envelope.js';
|
|
2
2
|
import { createCliError } from '../core/errors.js';
|
|
3
|
+
import { allPrompts } from './prompts/registry.js';
|
|
3
4
|
import { allTools } from './registry.js';
|
|
4
5
|
/**
|
|
5
6
|
* The tool set served by the hosted (remote, OAuth) MCP server — PIT-8912.
|
|
@@ -21,6 +22,26 @@ export const LOCAL_ONLY = new Set([
|
|
|
21
22
|
* exposes today (`questionFile`, `answersFile`, `canvasFile`, `assessmentsFile`, `contentHtmlFile`).
|
|
22
23
|
*/
|
|
23
24
|
export const FILE_KEY = /File$|^filePath$/;
|
|
25
|
+
/**
|
|
26
|
+
* An id-shaped input (`id`, `instanceId`, `courseIds`, …). Many commands interpolate ids straight into the
|
|
27
|
+
* request PATH (`/api/v1/files/${id}`, the L&D `/admin/courses/${id}`), so a value like `../users/1` or `1?x=`
|
|
28
|
+
* would retarget the call to another endpoint on the same host with the caller's token. Hosted accepts only
|
|
29
|
+
* plain tokens (letters, digits, `_`, `-`; comma-separated lists for string list inputs).
|
|
30
|
+
*/
|
|
31
|
+
export const ID_KEY = /^(id|ids|.+Id|.+Ids)$/;
|
|
32
|
+
const ID_TOKEN = /^[A-Za-z0-9_-]{1,200}$/;
|
|
33
|
+
function isSafeIdValue(v) {
|
|
34
|
+
// '' is "absent" to every command (falsy) and reaches no path
|
|
35
|
+
if (v === undefined || v === null || v === '' || typeof v === 'boolean')
|
|
36
|
+
return true;
|
|
37
|
+
if (typeof v === 'number')
|
|
38
|
+
return Number.isSafeInteger(v);
|
|
39
|
+
if (typeof v === 'string')
|
|
40
|
+
return v.split(',').every((part) => ID_TOKEN.test(part.trim()));
|
|
41
|
+
if (Array.isArray(v))
|
|
42
|
+
return v.every((x) => (typeof x === 'number' ? Number.isSafeInteger(x) : ID_TOKEN.test(String(x))));
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
24
45
|
/** Build options every hosted server uses: a write always asks the client to confirm. */
|
|
25
46
|
export const HOSTED_BUILD_OPTIONS = Object.freeze({ destructiveWrites: true });
|
|
26
47
|
// Tool descriptions rewritten without the local-file wording (the stdio text is kept for p mcp).
|
|
@@ -67,16 +88,28 @@ function toHosted(t) {
|
|
|
67
88
|
...t,
|
|
68
89
|
description: HOSTED_DESCRIPTIONS[t.name] ?? t.description,
|
|
69
90
|
inputShape: hostedShape(t),
|
|
70
|
-
// Runtime
|
|
91
|
+
// Runtime guards, independent of the schema: the stripped keys are invisible to a well-behaved
|
|
71
92
|
// client, but this refuses any file-path key however it arrives (a schema that grows a new
|
|
72
|
-
// xFile key, a caller bypassing validation, a command-layer key no schema declares)
|
|
93
|
+
// xFile key, a caller bypassing validation, a command-layer key no schema declares), and any
|
|
94
|
+
// id that is not a plain token (ID_KEY).
|
|
73
95
|
run: (opts, deps) => {
|
|
74
96
|
const bad = Object.keys(opts).filter((k) => FILE_KEY.test(k) && opts[k] !== undefined);
|
|
75
97
|
if (bad.length) {
|
|
76
98
|
return Promise.resolve(fail(createCliError('VALIDATION', `not supported on the hosted server (no local files): ${bad.join(', ')}`)));
|
|
77
99
|
}
|
|
100
|
+
const badIds = Object.keys(opts).filter((k) => ID_KEY.test(k) && !isSafeIdValue(opts[k]));
|
|
101
|
+
if (badIds.length) {
|
|
102
|
+
return Promise.resolve(fail(createCliError('VALIDATION', `not a valid id (letters, digits, "_" and "-" only): ${badIds.join(', ')}`)));
|
|
103
|
+
}
|
|
78
104
|
return t.run(opts, deps);
|
|
79
105
|
},
|
|
80
106
|
};
|
|
81
107
|
}
|
|
82
108
|
export const hostedTools = allTools.filter((t) => !LOCAL_ONLY.has(t.name)).map(toHosted);
|
|
109
|
+
/**
|
|
110
|
+
* Read-only mode (the org's `settings.mcp.access` is `read_only`, PIT-9768): only the hosted tools that read.
|
|
111
|
+
* A write tool is never registered, so calling one is "unknown tool", not a refused write.
|
|
112
|
+
*/
|
|
113
|
+
export const hostedReadOnlyTools = hostedTools.filter((t) => t.readOnly && !t.write && !t.alwaysDestructive);
|
|
114
|
+
/** The prompts a read-only server serves: only those flagged `readOnly` (the rest drive a write tool). */
|
|
115
|
+
export const readOnlyPrompts = allPrompts.filter((p) => p.readOnly === true);
|
package/dist/src/mcp/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { buildServer, type McpRunContext, type BuildServerOptions } from './server.js';
|
|
2
|
-
export { hostedTools, LOCAL_ONLY, FILE_KEY, HOSTED_BUILD_OPTIONS } from './hosted.js';
|
|
2
|
+
export { hostedTools, hostedReadOnlyTools, readOnlyPrompts, LOCAL_ONLY, FILE_KEY, ID_KEY, HOSTED_BUILD_OPTIONS, } from './hosted.js';
|
|
3
3
|
export { allTools } from './registry.js';
|
|
4
4
|
export { allPrompts } from './prompts/registry.js';
|
|
5
5
|
export { allResources } from './resources/registry.js';
|
package/dist/src/mcp/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Public entry `@pitcher/cli-scripts/mcp` — what the hosted MCP server (web/packages/mcp-server) consumes.
|
|
2
2
|
export { buildServer } from './server.js';
|
|
3
|
-
export { hostedTools, LOCAL_ONLY, FILE_KEY, HOSTED_BUILD_OPTIONS } from './hosted.js';
|
|
3
|
+
export { hostedTools, hostedReadOnlyTools, readOnlyPrompts, LOCAL_ONLY, FILE_KEY, ID_KEY, HOSTED_BUILD_OPTIONS, } from './hosted.js';
|
|
4
4
|
export { allTools } from './registry.js';
|
|
5
5
|
export { allPrompts } from './prompts/registry.js';
|
|
6
6
|
export { allResources } from './resources/registry.js';
|
package/dist/src/mcp/local.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The tool set of LOCAL `p mcp` (PIT-8943): only the three disk-bound tools (`dev_sync`, `dev_sync_revert`,
|
|
3
3
|
* `publish_app`), which zip a folder on this machine and so cannot run hosted. Everything else is the hosted
|
|
4
|
-
* server (`https://
|
|
4
|
+
* server (`https://mcp.pitcher.com/mcp`).
|
|
5
5
|
*/
|
|
6
6
|
export declare const localTools: import("./index.js").ToolDescriptor[];
|
package/dist/src/mcp/local.js
CHANGED
|
@@ -3,6 +3,6 @@ import { allTools } from './registry.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* The tool set of LOCAL `p mcp` (PIT-8943): only the three disk-bound tools (`dev_sync`, `dev_sync_revert`,
|
|
5
5
|
* `publish_app`), which zip a folder on this machine and so cannot run hosted. Everything else is the hosted
|
|
6
|
-
* server (`https://
|
|
6
|
+
* server (`https://mcp.pitcher.com/mcp`).
|
|
7
7
|
*/
|
|
8
8
|
export const localTools = allTools.filter((t) => LOCAL_ONLY.has(t.name));
|
|
@@ -7,6 +7,7 @@ import { instanceLine, readSafetyNote } from './shared.js';
|
|
|
7
7
|
export const analyticsPrompts = [
|
|
8
8
|
{
|
|
9
9
|
name: 'top_content',
|
|
10
|
+
readOnly: true,
|
|
10
11
|
title: 'Top-performing content',
|
|
11
12
|
description: 'Rank an instance’s most-viewed canvases (and optionally files) over a window.',
|
|
12
13
|
argsSchema: {
|
|
@@ -34,6 +35,7 @@ export const analyticsPrompts = [
|
|
|
34
35
|
},
|
|
35
36
|
{
|
|
36
37
|
name: 'content_engagement_summary',
|
|
38
|
+
readOnly: true,
|
|
37
39
|
title: 'Content engagement summary',
|
|
38
40
|
description: 'Summarize per-content/DSR engagement for an instance over a window.',
|
|
39
41
|
argsSchema: {
|
|
@@ -59,6 +61,7 @@ export const analyticsPrompts = [
|
|
|
59
61
|
},
|
|
60
62
|
{
|
|
61
63
|
name: 'who_viewed_canvas',
|
|
64
|
+
readOnly: true,
|
|
62
65
|
title: 'Who viewed a DSR canvas',
|
|
63
66
|
description: 'List the viewers of a specific DSR canvas, then drill into one viewer’s session timeline.',
|
|
64
67
|
argsSchema: {
|
|
@@ -89,6 +92,7 @@ export const analyticsPrompts = [
|
|
|
89
92
|
},
|
|
90
93
|
{
|
|
91
94
|
name: 'adoption_snapshot',
|
|
95
|
+
readOnly: true,
|
|
92
96
|
title: 'Adoption snapshot',
|
|
93
97
|
description: 'Combine active-user stats and KPIs into a short adoption snapshot for an instance.',
|
|
94
98
|
argsSchema: {
|
|
@@ -6,7 +6,7 @@ export interface ToolDescriptor {
|
|
|
6
6
|
name: string;
|
|
7
7
|
title: string;
|
|
8
8
|
description: string;
|
|
9
|
-
inputShape: z.
|
|
9
|
+
inputShape: Record<string, z.ZodType>;
|
|
10
10
|
run: (opts: Record<string, unknown> & InjectedAuth, deps?: any) => Promise<Envelope<unknown>>;
|
|
11
11
|
wraps?: (...a: any[]) => unknown;
|
|
12
12
|
readOnly: boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pitcher/cli-scripts",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "The Pitcher CLI for various tasks in its ecosystem.",
|
|
5
5
|
"author": "Pitcher AG",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,6 +57,6 @@
|
|
|
57
57
|
"chokidar": "^5.0.0",
|
|
58
58
|
"commander": "^15.0.0",
|
|
59
59
|
"form-data": "^4.0.6",
|
|
60
|
-
"zod": "^
|
|
60
|
+
"zod": "^4.6.7"
|
|
61
61
|
}
|
|
62
62
|
}
|