@pitcher/cli-scripts 2.8.0 → 2.9.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.
Files changed (61) hide show
  1. package/README.md +37 -0
  2. package/dist/index.js +2 -0
  3. package/dist/src/commands/mcp.d.ts +2 -0
  4. package/dist/src/commands/mcp.js +18 -0
  5. package/dist/src/mcp/env.d.ts +7 -0
  6. package/dist/src/mcp/env.js +13 -0
  7. package/dist/src/mcp/registry.d.ts +2 -0
  8. package/dist/src/mcp/registry.js +46 -0
  9. package/dist/src/mcp/result.d.ts +13 -0
  10. package/dist/src/mcp/result.js +20 -0
  11. package/dist/src/mcp/serve.d.ts +1 -0
  12. package/dist/src/mcp/serve.js +13 -0
  13. package/dist/src/mcp/server.d.ts +3 -0
  14. package/dist/src/mcp/server.js +41 -0
  15. package/dist/src/mcp/tools/analytics.d.ts +2 -0
  16. package/dist/src/mcp/tools/analytics.js +20 -0
  17. package/dist/src/mcp/tools/announcements.d.ts +2 -0
  18. package/dist/src/mcp/tools/announcements.js +32 -0
  19. package/dist/src/mcp/tools/canvases.d.ts +2 -0
  20. package/dist/src/mcp/tools/canvases.js +30 -0
  21. package/dist/src/mcp/tools/devSync.d.ts +2 -0
  22. package/dist/src/mcp/tools/devSync.js +53 -0
  23. package/dist/src/mcp/tools/dsr.d.ts +2 -0
  24. package/dist/src/mcp/tools/dsr.js +47 -0
  25. package/dist/src/mcp/tools/dsrLanding.d.ts +2 -0
  26. package/dist/src/mcp/tools/dsrLanding.js +45 -0
  27. package/dist/src/mcp/tools/emailTemplate.d.ts +2 -0
  28. package/dist/src/mcp/tools/emailTemplate.js +47 -0
  29. package/dist/src/mcp/tools/files.d.ts +2 -0
  30. package/dist/src/mcp/tools/files.js +65 -0
  31. package/dist/src/mcp/tools/folders.d.ts +2 -0
  32. package/dist/src/mcp/tools/folders.js +56 -0
  33. package/dist/src/mcp/tools/groups.d.ts +2 -0
  34. package/dist/src/mcp/tools/groups.js +60 -0
  35. package/dist/src/mcp/tools/instances.d.ts +2 -0
  36. package/dist/src/mcp/tools/instances.js +28 -0
  37. package/dist/src/mcp/tools/invitations.d.ts +2 -0
  38. package/dist/src/mcp/tools/invitations.js +23 -0
  39. package/dist/src/mcp/tools/memberships.d.ts +2 -0
  40. package/dist/src/mcp/tools/memberships.js +47 -0
  41. package/dist/src/mcp/tools/metadataTemplate.d.ts +2 -0
  42. package/dist/src/mcp/tools/metadataTemplate.js +42 -0
  43. package/dist/src/mcp/tools/org.d.ts +2 -0
  44. package/dist/src/mcp/tools/org.js +12 -0
  45. package/dist/src/mcp/tools/publishApp.d.ts +2 -0
  46. package/dist/src/mcp/tools/publishApp.js +39 -0
  47. package/dist/src/mcp/tools/roles.d.ts +2 -0
  48. package/dist/src/mcp/tools/roles.js +15 -0
  49. package/dist/src/mcp/tools/search.d.ts +2 -0
  50. package/dist/src/mcp/tools/search.js +16 -0
  51. package/dist/src/mcp/tools/sharedLinks.d.ts +2 -0
  52. package/dist/src/mcp/tools/sharedLinks.js +27 -0
  53. package/dist/src/mcp/tools/tags.d.ts +2 -0
  54. package/dist/src/mcp/tools/tags.js +20 -0
  55. package/dist/src/mcp/tools/themes.d.ts +2 -0
  56. package/dist/src/mcp/tools/themes.js +28 -0
  57. package/dist/src/mcp/tools/types.d.ts +15 -0
  58. package/dist/src/mcp/tools/types.js +1 -0
  59. package/dist/src/mcp/tools/users.d.ts +2 -0
  60. package/dist/src/mcp/tools/users.js +31 -0
  61. package/package.json +4 -2
package/README.md CHANGED
@@ -10,6 +10,43 @@ p --help
10
10
  p command --help
11
11
  ```
12
12
 
13
+ ## MCP server
14
+
15
+ Run `p mcp` to start a stdio [MCP](https://modelcontextprotocol.io) server that exposes this CLI's commands as tools to an MCP-capable host (Claude Desktop, Claude Code, etc). It wraps 50 tools, one per CLI `run*` function: every command above (including `dsr create` + `dsr bind-landing`) except the five local `scaffold` subcommands (which just print/write a starter file and make no request). `dev-sync` is exposed as a one-shot sync only; the continuous `watch` mode is not available as a tool.
16
+
17
+ ```bash
18
+ p mcp
19
+ # or without a global install
20
+ npx @pitcher/cli-scripts mcp
21
+ ```
22
+
23
+ ### Environment variables
24
+
25
+ Auth and org scope are resolved once at boot from environment variables. They are never tool inputs, so the model cannot change org or credentials mid-session.
26
+
27
+ - `NG_API_KEY` (required, secret): the API key the server authenticates as.
28
+ - `NG_ORG` (default `dev`): organization subdomain, or set `NG_URL` directly for a full origin.
29
+ - `NG_ENV` (`prod` or `test`): controls the destructive-hint guard on write tools (see below). Defaults to a guess based on `NG_ORG` when unset.
30
+
31
+ One config entry = one org, because the API key is org-specific. To work against multiple orgs, add multiple entries (e.g. `pitcher-dev`, `pitcher-prod`) with different env blocks; do not try to pass org per tool call.
32
+
33
+ ### Host config example (Claude Desktop / `.mcp.json`)
34
+
35
+ ```jsonc
36
+ "pitcher": {
37
+ "command": "npx",
38
+ "args": ["-y", "@pitcher/cli-scripts", "mcp"],
39
+ "env": { "NG_API_KEY": "<key>", "NG_ORG": "dev" }
40
+ }
41
+ ```
42
+
43
+ ### Tool annotations
44
+
45
+ - Read commands are marked `readOnlyHint`. `dev-sync` counts as a write (it mutates remote dev-override state).
46
+ - `publish-app` is always marked `destructiveHint` (it creates a live, org-visible release). Other write tools get `destructiveHint` only when the resolved environment is production (`NG_ENV=prod`, or `NG_ORG` other than `dev` with `NG_ENV` unset). This steers hosts toward requiring extra confirmation before mutating a production org.
47
+
48
+ This section is a reference only. For app-development conventions (modules, settings, mount points, SFDC), see the `pitcher-apps` skill, not this README.
49
+
13
50
  ## To run the `publish-app` command:
14
51
 
15
52
  ```bash
package/dist/index.js CHANGED
@@ -25,6 +25,7 @@ import { createGroupsCommand } from './src/commands/groups.js';
25
25
  import { createRolesCommand } from './src/commands/roles.js';
26
26
  import { createMetadataTemplateCommand } from './src/commands/metadataTemplate.js';
27
27
  import { createDsrCommand } from './src/commands/dsr.js';
28
+ import { createMcpCommand } from './src/commands/mcp.js';
28
29
  const __filename = fileURLToPath(import.meta.url);
29
30
  const __dirname = dirname(__filename);
30
31
  const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
@@ -57,4 +58,5 @@ program.addCommand(createMetadataTemplateCommand());
57
58
  program.addCommand(createDsrCommand());
58
59
  program.addCommand(createOrgCommand());
59
60
  program.addCommand(createAnalyticsCommand());
61
+ program.addCommand(createMcpCommand());
60
62
  program.parseAsync(process.argv);
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function createMcpCommand(): Command;
@@ -0,0 +1,18 @@
1
+ import { Command } from 'commander';
2
+ import { runMcpServe } from '../mcp/serve.js';
3
+ import { isCliError } from '../core/errors.js';
4
+ export function createMcpCommand() {
5
+ return new Command('mcp')
6
+ .description('Run the Pitcher MCP server over stdio (reads NG_API_KEY, NG_ORG/NG_URL, NG_ENV from env)')
7
+ .action(async () => {
8
+ try {
9
+ await runMcpServe();
10
+ }
11
+ catch (e) {
12
+ const message = isCliError(e) ? e.message : e instanceof Error ? e.message : String(e);
13
+ console.error(`[pitcher-mcp] failed to start: ${message}`);
14
+ process.exitCode = isCliError(e) ? e.exitCode : 1;
15
+ return;
16
+ }
17
+ });
18
+ }
@@ -0,0 +1,7 @@
1
+ export interface McpEnv {
2
+ apiKey: string;
3
+ org?: string;
4
+ url?: string;
5
+ prod: boolean;
6
+ }
7
+ export declare function resolveMcpEnv(env?: NodeJS.ProcessEnv): McpEnv;
@@ -0,0 +1,13 @@
1
+ import { createCliError } from '../core/errors.js';
2
+ export function resolveMcpEnv(env = process.env) {
3
+ const apiKey = env.NG_API_KEY?.trim();
4
+ if (!apiKey) {
5
+ throw createCliError('AUTH', 'NG_API_KEY is required to run the MCP server (set it in the host config env).');
6
+ }
7
+ const org = env.NG_ORG?.trim() || 'dev';
8
+ const url = env.NG_URL?.trim() || undefined;
9
+ const ngEnv = env.NG_ENV?.trim();
10
+ const isDevHost = url ? /\/\/dev\.my\.pitcher\.com(\/|$)/.test(url) : org === 'dev';
11
+ const prod = ngEnv === 'prod' ? true : ngEnv === 'test' ? false : !isDevHost;
12
+ return { apiKey, org, url, prod };
13
+ }
@@ -0,0 +1,2 @@
1
+ import type { ToolDescriptor } from './tools/types.js';
2
+ export declare const allTools: ToolDescriptor[];
@@ -0,0 +1,46 @@
1
+ import { analyticsTools } from './tools/analytics.js';
2
+ import { announcementsTools } from './tools/announcements.js';
3
+ import { canvasesTools } from './tools/canvases.js';
4
+ import { devSyncTools } from './tools/devSync.js';
5
+ import { dsrTools } from './tools/dsr.js';
6
+ import { dsrLandingTools } from './tools/dsrLanding.js';
7
+ import { emailTemplateTools } from './tools/emailTemplate.js';
8
+ import { filesTools } from './tools/files.js';
9
+ import { foldersTools } from './tools/folders.js';
10
+ import { groupsTools } from './tools/groups.js';
11
+ import { instancesTools } from './tools/instances.js';
12
+ import { invitationsTools } from './tools/invitations.js';
13
+ import { membershipsTools } from './tools/memberships.js';
14
+ import { metadataTemplateTools } from './tools/metadataTemplate.js';
15
+ import { orgTools } from './tools/org.js';
16
+ import { publishAppTools } from './tools/publishApp.js';
17
+ import { rolesTools } from './tools/roles.js';
18
+ import { searchTools } from './tools/search.js';
19
+ import { sharedLinksTools } from './tools/sharedLinks.js';
20
+ import { tagsTools } from './tools/tags.js';
21
+ import { themesTools } from './tools/themes.js';
22
+ import { usersTools } from './tools/users.js';
23
+ export const allTools = [
24
+ ...canvasesTools,
25
+ ...filesTools,
26
+ ...foldersTools,
27
+ ...searchTools,
28
+ ...instancesTools,
29
+ ...sharedLinksTools,
30
+ ...tagsTools,
31
+ ...announcementsTools,
32
+ ...dsrLandingTools,
33
+ ...dsrTools,
34
+ ...emailTemplateTools,
35
+ ...themesTools,
36
+ ...usersTools,
37
+ ...invitationsTools,
38
+ ...rolesTools,
39
+ ...orgTools,
40
+ ...analyticsTools,
41
+ ...membershipsTools,
42
+ ...groupsTools,
43
+ ...metadataTemplateTools,
44
+ ...devSyncTools,
45
+ ...publishAppTools,
46
+ ];
@@ -0,0 +1,13 @@
1
+ import type { Envelope } from '../core/envelope.js';
2
+ export interface ToolTextContent {
3
+ type: 'text';
4
+ text: string;
5
+ }
6
+ export interface CallToolResultShape {
7
+ content: ToolTextContent[];
8
+ structuredContent?: Record<string, unknown>;
9
+ isError: boolean;
10
+ [key: string]: unknown;
11
+ }
12
+ export declare function toErrorResult(code: string, message: string): CallToolResultShape;
13
+ export declare function envelopeToToolResult(env: Envelope<unknown>): CallToolResultShape;
@@ -0,0 +1,20 @@
1
+ function isPlainObject(v) {
2
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
3
+ }
4
+ export function toErrorResult(code, message) {
5
+ return { content: [{ type: 'text', text: `${code}: ${message}` }], isError: true };
6
+ }
7
+ export function envelopeToToolResult(env) {
8
+ if (!env.ok) {
9
+ return toErrorResult(env.error?.code ?? 'UNKNOWN', env.error?.message ?? 'unknown error');
10
+ }
11
+ const text = env.data === undefined ? 'null' : JSON.stringify(env.data);
12
+ const content = [{ type: 'text', text }];
13
+ for (const w of env.warnings ?? [])
14
+ content.push({ type: 'text', text: `warning: ${w}` });
15
+ const result = { content, isError: false };
16
+ // structuredContent must be an object; omit for arrays/primitives (text still carries the data).
17
+ if (isPlainObject(env.data))
18
+ result.structuredContent = env.data;
19
+ return result;
20
+ }
@@ -0,0 +1 @@
1
+ export declare function runMcpServe(env?: NodeJS.ProcessEnv): Promise<void>;
@@ -0,0 +1,13 @@
1
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
2
+ import { resolveMcpEnv } from './env.js';
3
+ import { buildServer } from './server.js';
4
+ import { allTools } from './registry.js';
5
+ // Resolves auth/env, builds the server, connects stdio. Never writes to stdout except protocol frames.
6
+ export async function runMcpServe(env = process.env) {
7
+ const mcpEnv = resolveMcpEnv(env);
8
+ const server = buildServer(mcpEnv);
9
+ const transport = new StdioServerTransport();
10
+ await server.connect(transport);
11
+ const target = mcpEnv.url ?? `https://${mcpEnv.org}.my.pitcher.com`;
12
+ console.error(`[pitcher-mcp] serving ${allTools.length} tools against ${target}${mcpEnv.prod ? ' (prod: destructive-hints on)' : ''}`);
13
+ }
@@ -0,0 +1,3 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { McpEnv } from './env.js';
3
+ export declare function buildServer(env: McpEnv): McpServer;
@@ -0,0 +1,41 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { readFileSync } from 'fs';
3
+ import { dirname, join } from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ import { allTools } from './registry.js';
6
+ import { envelopeToToolResult, toErrorResult } from './result.js';
7
+ import { isCliError } from '../core/errors.js';
8
+ const version = (() => {
9
+ try {
10
+ const dir = dirname(fileURLToPath(import.meta.url));
11
+ return JSON.parse(readFileSync(join(dir, '..', '..', '..', 'package.json'), 'utf8')).version ?? '0.0.0';
12
+ }
13
+ catch {
14
+ // cosmetic server version; fall back if package.json is unreadable
15
+ return '0.0.0';
16
+ }
17
+ })();
18
+ export function buildServer(env) {
19
+ const server = new McpServer({ name: 'pitcher', version });
20
+ for (const tool of allTools) {
21
+ const destructive = tool.alwaysDestructive === true || (tool.write === true && env.prod);
22
+ server.registerTool(tool.name, {
23
+ title: tool.title,
24
+ description: tool.description,
25
+ inputSchema: tool.inputShape,
26
+ annotations: { readOnlyHint: tool.readOnly, destructiveHint: destructive },
27
+ }, async (args) => {
28
+ try {
29
+ // spread args FIRST so injected auth/env always wins — never reorder to { apiKey, ...args }
30
+ const envelope = await tool.run({ ...args, apiKey: env.apiKey, org: env.org, url: env.url });
31
+ return envelopeToToolResult(envelope);
32
+ }
33
+ catch (e) {
34
+ const code = isCliError(e) ? e.code : 'UNKNOWN';
35
+ const message = isCliError(e) ? e.message : e instanceof Error ? e.message : String(e);
36
+ return toErrorResult(code, message);
37
+ }
38
+ });
39
+ }
40
+ return server;
41
+ }
@@ -0,0 +1,2 @@
1
+ import type { ToolDescriptor } from './types.js';
2
+ export declare const analyticsTools: ToolDescriptor[];
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ import { runAnalyticsOrg, runAnalyticsInstance } from '../../commands/analytics.js';
3
+ export const analyticsTools = [
4
+ {
5
+ name: 'pitcher_analytics_org',
6
+ title: 'Org analytics rollups',
7
+ description: 'Read organization-wide analytics rollup totals. Requires an org-admin API key.',
8
+ inputShape: {},
9
+ run: runAnalyticsOrg,
10
+ readOnly: true,
11
+ },
12
+ {
13
+ name: 'pitcher_analytics_instance',
14
+ title: 'Instance analytics rollups',
15
+ description: 'Read analytics rollup totals for a single instance. Requires an instance-admin or org-admin API key.',
16
+ inputShape: { instanceId: z.string().describe('Instance ID (required)') },
17
+ run: runAnalyticsInstance,
18
+ readOnly: true,
19
+ },
20
+ ];
@@ -0,0 +1,2 @@
1
+ import type { ToolDescriptor } from './types.js';
2
+ export declare const announcementsTools: ToolDescriptor[];
@@ -0,0 +1,32 @@
1
+ import { z } from 'zod';
2
+ import { runAnnouncementsCreate, runAnnouncementsList } from '../../commands/announcements.js';
3
+ export const announcementsTools = [
4
+ {
5
+ name: 'pitcher_announcements_create',
6
+ title: 'Create an announcement',
7
+ description: 'Create a wa-announcements appsDB record (title/body, optional media, CTA link, scheduling, group targeting). ' +
8
+ 'Requires either fromFile (a JSON object with the announcement data) or both title and body. Additive.',
9
+ inputShape: {
10
+ instanceId: z.string().describe('Instance ID (required)'),
11
+ fromFile: z.string().optional().describe('Path to a JSON file with the announcement data object'),
12
+ title: z.string().optional().describe('Announcement title (overrides a matching fromFile key)'),
13
+ body: z.string().optional().describe('Announcement body HTML (overrides a matching fromFile key)'),
14
+ priority: z.string().optional().describe("Priority, e.g. 'normal' or 'important' (overrides a matching fromFile key)"),
15
+ },
16
+ run: runAnnouncementsCreate,
17
+ readOnly: false,
18
+ write: true,
19
+ },
20
+ {
21
+ name: 'pitcher_announcements_list',
22
+ title: 'List announcements',
23
+ description: 'List wa-announcements appsDB records for an instance.',
24
+ inputShape: {
25
+ instanceId: z.string().describe('Instance ID (required)'),
26
+ limit: z.number().int().optional(),
27
+ offset: z.number().int().optional(),
28
+ },
29
+ run: runAnnouncementsList,
30
+ readOnly: true,
31
+ },
32
+ ];
@@ -0,0 +1,2 @@
1
+ import type { ToolDescriptor } from './types.js';
2
+ export declare const canvasesTools: ToolDescriptor[];
@@ -0,0 +1,30 @@
1
+ import { z } from 'zod';
2
+ import { runCanvasesList, runCanvasesGet } from '../../commands/canvases.js';
3
+ export const canvasesTools = [
4
+ {
5
+ name: 'pitcher_canvases_list',
6
+ title: 'List canvases',
7
+ description: 'List canvases (presentations, sections, blocks) in an instance. Use to discover canvas IDs before sharing or reading. Blocks are hidden unless isBlock is true.',
8
+ inputShape: {
9
+ instanceId: z.string().describe('Instance ID (required)'),
10
+ isTemplate: z.boolean().optional().describe('Only templates'),
11
+ isSection: z.boolean().optional().describe('Only sections'),
12
+ isBlock: z.boolean().optional().describe('Only blocks (hidden unless set)'),
13
+ tags: z.string().optional().describe('Comma-separated tags'),
14
+ idIn: z.string().optional().describe('Comma-separated canvas IDs'),
15
+ accessType: z.enum(['public', 'restricted', 'personal']).optional(),
16
+ page: z.number().int().optional(),
17
+ pageSize: z.number().int().optional().describe('Page size (max 500)'),
18
+ },
19
+ run: runCanvasesList,
20
+ readOnly: true,
21
+ },
22
+ {
23
+ name: 'pitcher_canvases_get',
24
+ title: 'Get a canvas',
25
+ description: 'Retrieve a single canvas by its ID.',
26
+ inputShape: { id: z.string().describe('Canvas ID') },
27
+ run: runCanvasesGet,
28
+ readOnly: true,
29
+ },
30
+ ];
@@ -0,0 +1,2 @@
1
+ import type { ToolDescriptor } from './types.js';
2
+ export declare const devSyncTools: ToolDescriptor[];
@@ -0,0 +1,53 @@
1
+ import { z } from 'zod';
2
+ import { runDevSync, runRevert } from '../../commands/devSync.js';
3
+ import { fail } from '../../core/envelope.js';
4
+ import { createCliError } from '../../core/errors.js';
5
+ // devSync.ts is legacy-shaped: `DevSyncOptions.fileId` is a required (non-optional)
6
+ // string, unlike every other command's `CommonOpts & { field?: ... }` + in-run
7
+ // VALIDATION-throw pattern. That mismatch means `runDevSync`/`runRevert` cannot be
8
+ // assigned directly to `ToolDescriptor.run` (typed `Record<string, unknown> &
9
+ // InjectedAuth`) — TS reports `fileId` as missing. These thin wrappers narrow the
10
+ // runtime value (the MCP zod schema already guarantees it's a string) and forward
11
+ // a properly-typed object literal, instead of casting the whole `opts` blob.
12
+ function requireFileId(opts) {
13
+ return typeof opts.fileId === 'string' ? opts.fileId : undefined;
14
+ }
15
+ export const devSyncTools = [
16
+ {
17
+ name: 'pitcher_dev_sync',
18
+ title: 'Dev-sync an app (one-shot)',
19
+ description: 'One-time sync of a local app build (a folder with app.json, on the MCP server host — cwd or ./dist) ' +
20
+ 'to S3 as a live dev override for an installed app file, for testing without publishing. ' +
21
+ 'This is a single sync, not the continuous watcher — call again to re-sync after further changes. ' +
22
+ 'Reversible with pitcher_dev_sync_revert.',
23
+ inputShape: {
24
+ fileId: z.string().describe('File ID of the installed app (pitcher_file.id) to override'),
25
+ },
26
+ run: (opts, deps) => {
27
+ const fileId = requireFileId(opts);
28
+ if (!fileId)
29
+ return Promise.resolve(fail(createCliError('VALIDATION', 'fileId is required')));
30
+ return runDevSync({ fileId, apiKey: opts.apiKey, org: opts.org }, deps);
31
+ },
32
+ wraps: runDevSync,
33
+ readOnly: false,
34
+ write: true,
35
+ },
36
+ {
37
+ name: 'pitcher_dev_sync_revert',
38
+ title: 'Revert a dev-sync override',
39
+ description: 'Revert a dev-sync override on an installed app file, restoring its original published version.',
40
+ inputShape: {
41
+ fileId: z.string().describe('File ID of the installed app (pitcher_file.id) to revert'),
42
+ },
43
+ run: (opts, deps) => {
44
+ const fileId = requireFileId(opts);
45
+ if (!fileId)
46
+ return Promise.resolve(fail(createCliError('VALIDATION', 'fileId is required')));
47
+ return runRevert({ fileId, apiKey: opts.apiKey, org: opts.org }, deps);
48
+ },
49
+ wraps: runRevert,
50
+ readOnly: false,
51
+ write: true,
52
+ },
53
+ ];
@@ -0,0 +1,2 @@
1
+ import type { ToolDescriptor } from './types.js';
2
+ export declare const dsrTools: ToolDescriptor[];
@@ -0,0 +1,47 @@
1
+ import { z } from 'zod';
2
+ import { runDsrCreate, runDsrBindLanding } from '../../commands/dsr.js';
3
+ const AUTH_STRATEGIES = [
4
+ 'none', 'any_email', 'specified_emails', 'specified_domains', 'verified_emails', 'verified_domains',
5
+ ];
6
+ export const dsrTools = [
7
+ {
8
+ name: 'pitcher_dsr_create',
9
+ title: 'Create and share a DSR',
10
+ description: 'Create a Digital Sales Room (a canvas share link) and get a clickable link back. Source is a canvas (canvasId) OR files (shareboxFileIds) - exactly one. Optional email/domain gating and a bound landing-page template. Never hard-fails once a link exists: a failed landing bind returns the link with a warning. Additive.',
11
+ inputShape: {
12
+ instanceId: z.string().optional().describe('Instance ID (required for the shareboxFileIds source)'),
13
+ canvasId: z.string().optional().describe('Canvas to share (exactly one of canvasId / shareboxFileIds)'),
14
+ shareboxFileIds: z.array(z.string()).optional().describe('File IDs to build a share from (exactly one of canvasId / shareboxFileIds)'),
15
+ canvasName: z.string().optional().describe('Name for the ShareBox-built canvas'),
16
+ accountId: z.string().optional(),
17
+ templateId: z.string().optional(),
18
+ authStrategy: z.enum(AUTH_STRATEGIES).optional().describe('Access gating (server default any_email)'),
19
+ allowedEmails: z.array(z.string()).optional().describe('Required for specified_emails / verified_emails'),
20
+ allowedDomains: z.array(z.string()).optional().describe('Required for specified_domains / verified_domains'),
21
+ validUntil: z.string().optional().describe('Expiry, ISO datetime'),
22
+ allowForward: z.boolean().optional(),
23
+ allowDownload: z.boolean().optional(),
24
+ tags: z.array(z.string()).optional(),
25
+ landingTemplateId: z.string().optional().describe('Bind a landing-page template (discover via pitcher_dsr_landing_list)'),
26
+ landingContext: z.string().optional().describe('Landing-page merge fields, a JSON object as a string'),
27
+ configFile: z.string().optional().describe('Path on the MCP server host to a full {source,security,landing} spec JSON; mutually exclusive with the individual flags'),
28
+ },
29
+ run: runDsrCreate,
30
+ readOnly: false,
31
+ write: true,
32
+ },
33
+ {
34
+ name: 'pitcher_dsr_bind_landing',
35
+ title: 'Bind a DSR landing page',
36
+ description: 'Attach, re-brand, or unbind a landing-page template on an existing DSR share. Use landingTemplateId "none" to unbind. Requires an editor-level key (hard-fails AUTH otherwise).',
37
+ inputShape: {
38
+ id: z.string().describe('Shared-link ID'),
39
+ landingTemplateId: z.string().describe('Landing template ID, or "none" to unbind'),
40
+ landingContext: z.string().optional().describe('Landing-page merge fields, a JSON object as a string'),
41
+ instanceId: z.string().optional(),
42
+ },
43
+ run: runDsrBindLanding,
44
+ readOnly: false,
45
+ write: true,
46
+ },
47
+ ];
@@ -0,0 +1,2 @@
1
+ import type { ToolDescriptor } from './types.js';
2
+ export declare const dsrLandingTools: ToolDescriptor[];
@@ -0,0 +1,45 @@
1
+ import { z } from 'zod';
2
+ import { runDsrLandingCreate, runDsrLandingSetDefault, runDsrLandingList } from '../../commands/dsrLanding.js';
3
+ export const dsrLandingTools = [
4
+ {
5
+ name: 'pitcher_dsr_landing_create',
6
+ title: 'Create a DSR landing template',
7
+ description: 'Create a DSR (Digital Sales Room) landing-page template from HTML (must contain the data-pitcher-email-gate ' +
8
+ 'marker) and optional CSS/merge-schema/thumbnail. Optionally set it as the instance default in the same call. Additive.',
9
+ inputShape: {
10
+ instanceId: z.string().describe('Instance ID (required)'),
11
+ name: z.string().describe('Template name (required)'),
12
+ htmlFile: z.string().describe('Path to the landing HTML (required; must contain data-pitcher-email-gate)'),
13
+ cssFile: z.string().optional().describe('Path to a CSS file for the template'),
14
+ mergeSchema: z.string().optional().describe('Merge schema JSON array as a string'),
15
+ thumbnailUrl: z.string().optional().describe('Thumbnail image URL'),
16
+ language: z.string().optional().describe('Language code (max 10 chars)'),
17
+ default: z.boolean().optional().describe('Also set this template as the instance-scope default after creating it'),
18
+ },
19
+ run: runDsrLandingCreate,
20
+ readOnly: false,
21
+ write: true,
22
+ },
23
+ {
24
+ name: 'pitcher_dsr_landing_set_default',
25
+ title: 'Set default DSR landing template',
26
+ description: 'Set an existing DSR landing-page template as the instance-scope default.',
27
+ inputShape: {
28
+ instanceId: z.string().describe('Instance ID (required)'),
29
+ id: z.string().describe('Template ID (required)'),
30
+ },
31
+ run: runDsrLandingSetDefault,
32
+ readOnly: false,
33
+ write: true,
34
+ },
35
+ {
36
+ name: 'pitcher_dsr_landing_list',
37
+ title: 'List DSR landing templates',
38
+ description: 'List DSR (Digital Sales Room) landing-page templates in an instance.',
39
+ inputShape: {
40
+ instanceId: z.string().describe('Instance ID (required)'),
41
+ },
42
+ run: runDsrLandingList,
43
+ readOnly: true,
44
+ },
45
+ ];
@@ -0,0 +1,2 @@
1
+ import type { ToolDescriptor } from './types.js';
2
+ export declare const emailTemplateTools: ToolDescriptor[];
@@ -0,0 +1,47 @@
1
+ import { z } from 'zod';
2
+ import { runEmailTemplateCreate, runEmailTemplateList, runEmailTemplateGet } from '../../commands/emailTemplate.js';
3
+ export const emailTemplateTools = [
4
+ {
5
+ name: 'pitcher_email_template_create',
6
+ title: 'Create an email template',
7
+ description: 'Create an HTML email template for the emails app (Rep Triggered Emails). Additive.',
8
+ inputShape: {
9
+ instanceId: z.string().describe('Instance ID (required)'),
10
+ name: z.string().describe('Template name (required)'),
11
+ bodyFile: z.string().optional().describe('Path to an HTML file (inline CSS) used as the template body'),
12
+ subject: z.string().optional().describe('Email subject (supports {{tokens}})'),
13
+ tags: z.string().optional().describe('Tags JSON object as a string'),
14
+ metadata: z.string().optional().describe('Metadata JSON object as a string'),
15
+ },
16
+ run: runEmailTemplateCreate,
17
+ readOnly: false,
18
+ write: true,
19
+ },
20
+ {
21
+ name: 'pitcher_email_template_list',
22
+ title: 'List email templates',
23
+ description: 'List HTML email templates for the emails app in an instance. Filter by name, status, category, or target.',
24
+ inputShape: {
25
+ instanceId: z.string().describe('Instance ID (required)'),
26
+ name: z.string().optional().describe('Case-insensitive substring filter, matched against name OR subject'),
27
+ status: z.string().optional().describe('Status filter'),
28
+ category: z.string().optional().describe('Category filter'),
29
+ target: z.string().optional().describe('Target filter'),
30
+ limit: z.number().int().optional(),
31
+ offset: z.number().int().optional(),
32
+ },
33
+ run: runEmailTemplateList,
34
+ readOnly: true,
35
+ },
36
+ {
37
+ name: 'pitcher_email_template_get',
38
+ title: 'Get an email template',
39
+ description: 'Retrieve a single HTML email template by its ID.',
40
+ inputShape: {
41
+ instanceId: z.string().describe('Instance ID (required)'),
42
+ id: z.string().describe('Template ID (required)'),
43
+ },
44
+ run: runEmailTemplateGet,
45
+ readOnly: true,
46
+ },
47
+ ];
@@ -0,0 +1,2 @@
1
+ import type { ToolDescriptor } from './types.js';
2
+ export declare const filesTools: ToolDescriptor[];
@@ -0,0 +1,65 @@
1
+ import { z } from 'zod';
2
+ import { runFilesList, runFilesGet, runFilesCreate, runFilesUpdate } from '../../commands/files.js';
3
+ export const filesTools = [
4
+ {
5
+ name: 'pitcher_files_list',
6
+ title: 'List files',
7
+ description: 'List content files in an instance. Filter by tags or specific IDs.',
8
+ inputShape: {
9
+ instanceId: z.string().describe('Instance ID (required)'),
10
+ idIn: z.string().optional().describe('Comma-separated file IDs'),
11
+ tags: z.string().optional().describe('Comma-separated tags'),
12
+ page: z.number().int().optional(),
13
+ pageSize: z.number().int().optional(),
14
+ },
15
+ run: runFilesList,
16
+ readOnly: true,
17
+ },
18
+ {
19
+ name: 'pitcher_files_get',
20
+ title: 'Get a file',
21
+ description: 'Retrieve a single file by its ID.',
22
+ inputShape: { id: z.string().describe('File ID') },
23
+ run: runFilesGet,
24
+ readOnly: true,
25
+ },
26
+ {
27
+ name: 'pitcher_files_create',
28
+ title: 'Create a file',
29
+ description: 'Create a content file in an instance, from a local file path (on the server host) or a source URL. Additive.',
30
+ inputShape: {
31
+ instanceId: z.string().describe('Instance ID (required)'),
32
+ name: z.string().optional().describe('File name'),
33
+ folderId: z.string().optional().describe('Destination folder'),
34
+ filePath: z.string().optional().describe('Local file path to upload (on the MCP server host)'),
35
+ sourceUrl: z.string().optional().describe('Link/WEB file source URL'),
36
+ accessType: z.enum(['public', 'restricted', 'personal']).optional(),
37
+ tags: z.string().optional().describe('Comma-separated tags'),
38
+ metadata: z.string().optional().describe('metadata JSON object as a string'),
39
+ appMetadata: z.string().optional().describe('app_metadata JSON object as a string'),
40
+ },
41
+ run: runFilesCreate,
42
+ readOnly: false,
43
+ write: true,
44
+ },
45
+ {
46
+ name: 'pitcher_files_update',
47
+ title: 'Update a file',
48
+ description: 'Update a file by ID (name, folder, access, tags, metadata). filePath or sourceUrl replaces/overwrites the file binary; metadata is deep-merged.',
49
+ inputShape: {
50
+ id: z.string().describe('File ID'),
51
+ instanceId: z.string().optional().describe('Instance ID (required only with filePath)'),
52
+ name: z.string().optional(),
53
+ folderId: z.string().optional(),
54
+ filePath: z.string().optional().describe('Local file path to replace the binary (on the MCP server host)'),
55
+ sourceUrl: z.string().optional(),
56
+ accessType: z.enum(['public', 'restricted', 'personal']).optional(),
57
+ tags: z.string().optional().describe('Comma-separated tags'),
58
+ metadata: z.string().optional().describe('metadata JSON object as a string (deep-merged)'),
59
+ appMetadata: z.string().optional().describe('app_metadata JSON object as a string (deep-merged)'),
60
+ },
61
+ run: runFilesUpdate,
62
+ readOnly: false,
63
+ write: true,
64
+ },
65
+ ];
@@ -0,0 +1,2 @@
1
+ import type { ToolDescriptor } from './types.js';
2
+ export declare const foldersTools: ToolDescriptor[];