@phenomenalorg/mcp 0.2.0 → 0.4.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 +31 -7
- package/dist/cli.d.ts +8 -3
- package/dist/cli.js +52 -4
- package/dist/skill.d.ts +21 -0
- package/dist/skill.js +45 -0
- package/package.json +4 -2
- package/skill/SKILL.md +56 -0
- package/skill/references/mutations.md +247 -0
- package/skill/references/schema.md +38 -0
- package/skill/references/starting-doc.md +92 -0
- package/skill/references/tools.md +512 -0
package/README.md
CHANGED
|
@@ -67,15 +67,16 @@ Point it somewhere else with a URL:
|
|
|
67
67
|
## Command line
|
|
68
68
|
|
|
69
69
|
```
|
|
70
|
-
npx @phenomenalorg/mcp [<url>] [--url <url>] [--logout] [--version] [--help]
|
|
70
|
+
npx @phenomenalorg/mcp [<url>] [--url <url>] [--skill [dir]] [--logout] [--version] [--help]
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
| Flag
|
|
74
|
-
|
|
|
75
|
-
| `--url`
|
|
76
|
-
| `--
|
|
77
|
-
| `--
|
|
78
|
-
| `--
|
|
73
|
+
| Flag | What it does |
|
|
74
|
+
| --------------- | --------------------------------------------------------------------- |
|
|
75
|
+
| `--url` | The Phenomenal MCP endpoint. Default `https://api.phenomenal.org/mcp` |
|
|
76
|
+
| `--skill [dir]` | Install the Phenomenal agent skill (see below) |
|
|
77
|
+
| `--logout` | Forget the saved sign-in for that server and exit |
|
|
78
|
+
| `--version` | Print the version and exit |
|
|
79
|
+
| `--help` | Print usage and exit |
|
|
79
80
|
|
|
80
81
|
Sign out of one server:
|
|
81
82
|
|
|
@@ -84,6 +85,29 @@ npx @phenomenalorg/mcp --logout
|
|
|
84
85
|
npx @phenomenalorg/mcp --logout --url https://api.ph-dev.org/mcp
|
|
85
86
|
```
|
|
86
87
|
|
|
88
|
+
## The agent skill
|
|
89
|
+
|
|
90
|
+
Connecting gives your assistant the tools. The **skill** gives it the working
|
|
91
|
+
habits that go with them: call `list_my_orgs` before anything else, draft →
|
|
92
|
+
preview → publish, never confirm a send on its own initiative, keep member
|
|
93
|
+
details out of anything public.
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npx @phenomenalorg/mcp --skill .claude/skills # install it into a project
|
|
97
|
+
npx @phenomenalorg/mcp --skill # install into ./.claude/skills if it
|
|
98
|
+
# exists, else print SKILL.md
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`--skill <dir>` writes a `phenomenal/` folder into the directory you name:
|
|
102
|
+
`SKILL.md` plus `references/` — the full tool catalog, the `run_mutation` long
|
|
103
|
+
tail, and how to read the GraphQL schema. An existing install is replaced; the
|
|
104
|
+
skill is generated from the server's own tool registry, so there is nothing in
|
|
105
|
+
it worth keeping across an update.
|
|
106
|
+
|
|
107
|
+
For a client with no skills feature, point it at
|
|
108
|
+
<https://phenomenal.org/agents> instead — the same briefing, plus the install
|
|
109
|
+
recipes, as one plain-text page it can fetch.
|
|
110
|
+
|
|
87
111
|
## Where your sign-in is kept
|
|
88
112
|
|
|
89
113
|
`~/.phenomenal/mcp/<server>.json`, one file per server, written `0600` inside a
|
package/dist/cli.d.ts
CHANGED
|
@@ -5,13 +5,18 @@ export interface CliOptions {
|
|
|
5
5
|
logout: boolean;
|
|
6
6
|
version: boolean;
|
|
7
7
|
help: boolean;
|
|
8
|
+
/** `--skill` was given, with or without a directory. */
|
|
9
|
+
skill: boolean;
|
|
10
|
+
/** The directory named after `--skill`, or `null` for "decide for me". */
|
|
11
|
+
skillDir: string | null;
|
|
8
12
|
}
|
|
9
13
|
export declare class CliUsageError extends Error {
|
|
10
14
|
}
|
|
11
15
|
/**
|
|
12
|
-
* `--url <u>`, `--url=<u>` or a bare positional URL; `--
|
|
13
|
-
* `--help`. Anything else is a usage error rather than
|
|
14
|
-
* flag — an MCP client config typo should say so, not
|
|
16
|
+
* `--url <u>`, `--url=<u>` or a bare positional URL; `--skill [dir]`,
|
|
17
|
+
* `--logout`, `--version`, `--help`. Anything else is a usage error rather than
|
|
18
|
+
* a silently ignored flag — an MCP client config typo should say so, not
|
|
19
|
+
* connect somewhere else.
|
|
15
20
|
*/
|
|
16
21
|
export declare function parseArgs(argv: readonly string[]): CliOptions;
|
|
17
22
|
export declare function usage(version: string): string;
|
package/dist/cli.js
CHANGED
|
@@ -9,14 +9,16 @@ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/
|
|
|
9
9
|
import { ensureAuthorized } from './auth.js';
|
|
10
10
|
import { startBridge } from './bridge.js';
|
|
11
11
|
import { clearSession, storePath } from './store.js';
|
|
12
|
+
import { defaultInstallDir, installSkill, readSkillMarkdown } from './skill.js';
|
|
12
13
|
import { readPackageVersion } from './version.js';
|
|
13
14
|
export const DEFAULT_SERVER_URL = 'https://api.phenomenal.org/mcp';
|
|
14
15
|
export class CliUsageError extends Error {
|
|
15
16
|
}
|
|
16
17
|
/**
|
|
17
|
-
* `--url <u>`, `--url=<u>` or a bare positional URL; `--
|
|
18
|
-
* `--help`. Anything else is a usage error rather than
|
|
19
|
-
* flag — an MCP client config typo should say so, not
|
|
18
|
+
* `--url <u>`, `--url=<u>` or a bare positional URL; `--skill [dir]`,
|
|
19
|
+
* `--logout`, `--version`, `--help`. Anything else is a usage error rather than
|
|
20
|
+
* a silently ignored flag — an MCP client config typo should say so, not
|
|
21
|
+
* connect somewhere else.
|
|
20
22
|
*/
|
|
21
23
|
export function parseArgs(argv) {
|
|
22
24
|
const options = {
|
|
@@ -24,6 +26,8 @@ export function parseArgs(argv) {
|
|
|
24
26
|
logout: false,
|
|
25
27
|
version: false,
|
|
26
28
|
help: false,
|
|
29
|
+
skill: false,
|
|
30
|
+
skillDir: null,
|
|
27
31
|
};
|
|
28
32
|
let urlSeen = false;
|
|
29
33
|
for (let i = 0; i < argv.length; i += 1) {
|
|
@@ -45,6 +49,24 @@ export function parseArgs(argv) {
|
|
|
45
49
|
urlSeen = true;
|
|
46
50
|
i += 1;
|
|
47
51
|
}
|
|
52
|
+
else if (arg === '--skill') {
|
|
53
|
+
options.skill = true;
|
|
54
|
+
/**
|
|
55
|
+
* The directory is OPTIONAL, so the value is only consumed when the next
|
|
56
|
+
* argument is not itself a flag. `--skill --url x` has to keep meaning
|
|
57
|
+
* what it says; swallowing `--url` as a directory would install the skill
|
|
58
|
+
* into a folder called `--url` and then connect to the default server.
|
|
59
|
+
*/
|
|
60
|
+
const value = argv[i + 1];
|
|
61
|
+
if (value !== undefined && !value.startsWith('-')) {
|
|
62
|
+
options.skillDir = value;
|
|
63
|
+
i += 1;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else if (arg.startsWith('--skill=')) {
|
|
67
|
+
options.skill = true;
|
|
68
|
+
options.skillDir = arg.slice('--skill='.length) || null;
|
|
69
|
+
}
|
|
48
70
|
else if (arg.startsWith('--url=')) {
|
|
49
71
|
options.url = validUrl(arg.slice('--url='.length));
|
|
50
72
|
urlSeen = true;
|
|
@@ -77,10 +99,13 @@ export function usage(version) {
|
|
|
77
99
|
`phenomenal-mcp ${version} — connect an MCP client to Phenomenal over stdio.`,
|
|
78
100
|
'',
|
|
79
101
|
'Usage:',
|
|
80
|
-
' npx @phenomenalorg/mcp [<url>] [--url <url>] [--
|
|
102
|
+
' npx @phenomenalorg/mcp [<url>] [--url <url>] [--skill [dir]] [--logout]',
|
|
81
103
|
'',
|
|
82
104
|
'Options:',
|
|
83
105
|
` --url <url> The Phenomenal MCP endpoint (default ${DEFAULT_SERVER_URL})`,
|
|
106
|
+
' --skill [dir] Install the Phenomenal skill into dir/phenomenal/. With no',
|
|
107
|
+
' dir it installs into .claude/skills/ when that folder is',
|
|
108
|
+
' already here, and prints SKILL.md to stdout otherwise.',
|
|
84
109
|
' --logout Forget the saved sign-in for that server and exit',
|
|
85
110
|
' --version Print the version and exit',
|
|
86
111
|
' --help Print this and exit',
|
|
@@ -113,6 +138,9 @@ export async function run(argv, io = defaultIo) {
|
|
|
113
138
|
io.out(version);
|
|
114
139
|
return 0;
|
|
115
140
|
}
|
|
141
|
+
if (options.skill) {
|
|
142
|
+
return installOrPrintSkill(options, io);
|
|
143
|
+
}
|
|
116
144
|
if (options.logout) {
|
|
117
145
|
const had = clearSession(options.url);
|
|
118
146
|
io.err(had
|
|
@@ -130,6 +158,26 @@ export async function run(argv, io = defaultIo) {
|
|
|
130
158
|
await handle.done;
|
|
131
159
|
return 0;
|
|
132
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* `--skill`, in one place: install when a directory is known, print otherwise.
|
|
163
|
+
*
|
|
164
|
+
* The rule is "do the obvious thing and say what you did". A named directory is
|
|
165
|
+
* an explicit ask. An unnamed one installs only into a `.claude/skills/` that
|
|
166
|
+
* ALREADY exists — standing in a project that reads skills is itself the ask —
|
|
167
|
+
* and otherwise falls back to stdout, which writes nothing anywhere. Every
|
|
168
|
+
* branch reports its outcome on stderr, so nobody has to guess which one ran.
|
|
169
|
+
*/
|
|
170
|
+
function installOrPrintSkill(options, io) {
|
|
171
|
+
const target = options.skillDir ?? defaultInstallDir(process.cwd());
|
|
172
|
+
if (!target) {
|
|
173
|
+
io.out(readSkillMarkdown());
|
|
174
|
+
io.err('Printed the Phenomenal skill. Pass a directory to install it: --skill <dir>');
|
|
175
|
+
return 0;
|
|
176
|
+
}
|
|
177
|
+
const written = installSkill(target);
|
|
178
|
+
io.err(`Installed the Phenomenal skill into ${written}.`);
|
|
179
|
+
return 0;
|
|
180
|
+
}
|
|
133
181
|
// `import.meta.url` is the built dist/cli.js when npm runs the bin; the guard
|
|
134
182
|
// keeps `run` importable from tests without starting a session.
|
|
135
183
|
const invokedDirectly = process.argv[1] !== undefined && import.meta.url.endsWith('/cli.js');
|
package/dist/skill.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** The skill package inside this npm package. `dist/cli.js` → `../skill/`. */
|
|
2
|
+
export declare function skillSourceDir(): string;
|
|
3
|
+
/**
|
|
4
|
+
* The conventional skills directory of the project you are standing in.
|
|
5
|
+
*
|
|
6
|
+
* Only when it ALREADY exists. Creating `.claude/skills/` in whatever directory
|
|
7
|
+
* a person happened to be in would be a command that reshapes a project as a
|
|
8
|
+
* side effect of asking to read something.
|
|
9
|
+
*/
|
|
10
|
+
export declare function defaultInstallDir(cwd: string): string | null;
|
|
11
|
+
/** `SKILL.md`, for printing. */
|
|
12
|
+
export declare function readSkillMarkdown(): string;
|
|
13
|
+
/**
|
|
14
|
+
* Copy the whole `phenomenal/` folder into a skills directory.
|
|
15
|
+
*
|
|
16
|
+
* The folder is named for the skill, not for the package, because that is what
|
|
17
|
+
* an Agent Skills client keys on. An existing install is overwritten: the skill
|
|
18
|
+
* is generated, so the copy on disk has no edits worth keeping, and a command
|
|
19
|
+
* that refused would leave people on a stale skill with no obvious way forward.
|
|
20
|
+
*/
|
|
21
|
+
export declare function installSkill(targetDir: string): string;
|
package/dist/skill.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `--skill`: hand the Phenomenal Agent Skill to a client that reads skills.
|
|
3
|
+
*
|
|
4
|
+
* The skill is generated from the server's own tool registry and copied into
|
|
5
|
+
* this package at build time (`scripts/copy-skill.mjs`), so what a customer
|
|
6
|
+
* installs on their laptop is the same text the server would have told the
|
|
7
|
+
* model — and nothing here reads the source repo at run time, because on a
|
|
8
|
+
* customer's machine there is no source repo.
|
|
9
|
+
*/
|
|
10
|
+
import { cpSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
11
|
+
import { join, resolve } from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
/** The skill package inside this npm package. `dist/cli.js` → `../skill/`. */
|
|
14
|
+
export function skillSourceDir() {
|
|
15
|
+
return fileURLToPath(new URL('../skill/', import.meta.url));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The conventional skills directory of the project you are standing in.
|
|
19
|
+
*
|
|
20
|
+
* Only when it ALREADY exists. Creating `.claude/skills/` in whatever directory
|
|
21
|
+
* a person happened to be in would be a command that reshapes a project as a
|
|
22
|
+
* side effect of asking to read something.
|
|
23
|
+
*/
|
|
24
|
+
export function defaultInstallDir(cwd) {
|
|
25
|
+
const candidate = join(cwd, '.claude', 'skills');
|
|
26
|
+
return existsSync(candidate) ? candidate : null;
|
|
27
|
+
}
|
|
28
|
+
/** `SKILL.md`, for printing. */
|
|
29
|
+
export function readSkillMarkdown() {
|
|
30
|
+
return readFileSync(join(skillSourceDir(), 'SKILL.md'), 'utf8');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Copy the whole `phenomenal/` folder into a skills directory.
|
|
34
|
+
*
|
|
35
|
+
* The folder is named for the skill, not for the package, because that is what
|
|
36
|
+
* an Agent Skills client keys on. An existing install is overwritten: the skill
|
|
37
|
+
* is generated, so the copy on disk has no edits worth keeping, and a command
|
|
38
|
+
* that refused would leave people on a stale skill with no obvious way forward.
|
|
39
|
+
*/
|
|
40
|
+
export function installSkill(targetDir) {
|
|
41
|
+
const destination = resolve(targetDir, 'phenomenal');
|
|
42
|
+
mkdirSync(destination, { recursive: true });
|
|
43
|
+
cpSync(skillSourceDir(), destination, { recursive: true });
|
|
44
|
+
return destination;
|
|
45
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phenomenalorg/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Phenomenal MCP bridge — connects a stdio-only MCP client to the Phenomenal MCP server over Streamable HTTP, with browser sign-in.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"files": [
|
|
27
27
|
"dist",
|
|
28
|
+
"skill",
|
|
28
29
|
"README.md"
|
|
29
30
|
],
|
|
30
31
|
"exports": {
|
|
@@ -34,7 +35,7 @@
|
|
|
34
35
|
}
|
|
35
36
|
},
|
|
36
37
|
"scripts": {
|
|
37
|
-
"build": "tsc -p tsconfig.build.json && chmod +x dist/cli.js",
|
|
38
|
+
"build": "node scripts/copy-skill.mjs && tsc -p tsconfig.build.json && chmod +x dist/cli.js",
|
|
38
39
|
"typecheck": "tsc --noEmit",
|
|
39
40
|
"test": "pnpm run build && vitest run"
|
|
40
41
|
},
|
|
@@ -43,6 +44,7 @@
|
|
|
43
44
|
"open": "^11.0.0"
|
|
44
45
|
},
|
|
45
46
|
"devDependencies": {
|
|
47
|
+
"@ptopro/mcp-tools": "workspace:*",
|
|
46
48
|
"@types/node": "^22.10.0",
|
|
47
49
|
"typescript": "^5.6.0",
|
|
48
50
|
"vitest": "^2.1.0"
|
package/skill/SKILL.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: phenomenal
|
|
3
|
+
description: Use when the user wants to manage a PTO, school or club in Phenomenal — the public site and its pages, members and invites, events and tickets, announcements and email, forms, store and ticket orders, tasks, or asking what the organization already knows. Requires the Phenomenal MCP server to be connected.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Phenomenal
|
|
7
|
+
|
|
8
|
+
<!-- Generated from the Phenomenal tool registry. Do not edit by hand: a drift
|
|
9
|
+
gate fails when these files are not what the registry currently says. -->
|
|
10
|
+
|
|
11
|
+
_Tool surface: 39 tools · 163 actions · 5 prompts · fingerprint `fef338e5`._
|
|
12
|
+
|
|
13
|
+
You are connected to Phenomenal, the platform for this PTO's site, members, events, tickets, email, forms, store and money.
|
|
14
|
+
|
|
15
|
+
Start with list_my_orgs. Every organization id comes from it; never guess or invent one. Name the selected organization; ask if ambiguous.
|
|
16
|
+
|
|
17
|
+
Say whether you are drafting, saving or publishing. draft_page saves nothing. draft_broadcast saves a draft and returns its id; it sends nothing. update_page_draft saves privately. publish_page publishes; send_broadcast sends to families.
|
|
18
|
+
|
|
19
|
+
For any tool with confirm, first call WITHOUT confirm. Present the returned action, target and effect to the user, then END THE TURN. Wait for a NEW explicit user message approving that exact preview; only then use confirm: true for the same action/target. The initial request and client/native tool-permission approval do not approve a later preview. Never self-confirm. “Nothing has happened yet” is a successful no-effect preview, not an error or retry signal.
|
|
20
|
+
|
|
21
|
+
Mail and money are one-way. Slow down before sending, refunding or paying out.
|
|
22
|
+
|
|
23
|
+
Keep member names, addresses and form answers in your answer to the officer; never copy them into public pages or broadcasts. Write US English, plainly and warmly, for parents on phones. On FORBIDDEN, explain the role limit and stop; never hunt for another route.
|
|
24
|
+
|
|
25
|
+
Publish a page: list_pages → get_page → draft_page → update_page_draft (saved privately) → preview publish_page → ask → publish_page with confirm: true.
|
|
26
|
+
|
|
27
|
+
For other work: list_mutations → describe_mutation → run_mutation. Read arguments; never guess. query_graphql is read-only.
|
|
28
|
+
|
|
29
|
+
## Worked sequences
|
|
30
|
+
|
|
31
|
+
Draft the weekly newsletter for my organization (call list_my_orgs first): org_overview → list_events for the next three weeks → list_pages → draft_broadcast. Report the saved draft and audience; use US English for parents. If a test is requested: send_broadcast_test without confirm → present its action/target/effect → end the turn → wait for a NEW explicit user message approving that preview → confirm the same action/target. Repeat the entire sequence separately for send_broadcast; test approval never approves the full send.
|
|
32
|
+
|
|
33
|
+
New event for my organization (call list_my_orgs first): . Ask for missing dates, location and ticket details. list_events → create_event → update_event for event details only. For tickets: list_mutations({ area: "events" }) → describe_mutation({ name: "createTicketType" }) → run_mutation with its exact input schema. For ticket changes, describe_mutation({ name: "updateTicketType" }) first. Leave the event unpublished; preview set_event_published and ask before confirming.
|
|
34
|
+
|
|
35
|
+
Membership review for my organization (call list_my_orgs first): list_members (follow cursors) → list_groups → list_group_members. Report pending or suspended members and officer roles. Recommend changes but make none; keep names and addresses in your answer to me.
|
|
36
|
+
|
|
37
|
+
Month-end money for my organization (call list_my_orgs first): payout_status → list_orders. Report holds, failures, possible refunds and available funds. Propose refund_ticket_order, cancel_order or start_payout only when needed; each needs its own preview and yes. Move no money yet.
|
|
38
|
+
|
|
39
|
+
## References
|
|
40
|
+
|
|
41
|
+
Read one of these when you need the detail, not before:
|
|
42
|
+
|
|
43
|
+
- `references/tools.md` — every tool, its arguments, and whether it needs `confirm`.
|
|
44
|
+
- `references/mutations.md` — the `run_mutation` long tail, by area.
|
|
45
|
+
- `references/schema.md` — `query_graphql` and `get_schema`, and the limits they enforce.
|
|
46
|
+
- `references/starting-doc.md` — this briefing plus the install recipes, as published online.
|
|
47
|
+
|
|
48
|
+
Online: https://phenomenal.org/agents (and `https://phenomenal.org/agents/tools`, `/mutations`, `/schema`).
|
|
49
|
+
|
|
50
|
+
## When this file and the server disagree
|
|
51
|
+
|
|
52
|
+
This file is a copy. It ships separately from the server and can lag it.
|
|
53
|
+
|
|
54
|
+
Read `phenomenal://instructions` and compare its `Tool surface fingerprint` with the fingerprint above. A different value means this copy is out of date: use the live instructions, schemas and confirmation requirements. If the resource has no fingerprint (an older server), freshness is unknown; inspect live tools and describe mutations before acting. This fingerprint is a compatibility hint, not an integrity check, and is not compared with the product version.
|
|
55
|
+
|
|
56
|
+
`initialize` reports the live server's version as `serverInfo.version`, and `tools/list` reports exactly which tools it has — **those are the authority.** If a tool named here is missing from the live list, or the server offers one this file does not name, go by the live list and say plainly that your copy of the guide is out of date. Do not guess an argument, and do not invent a tool because this file mentions it.
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# Phenomenal actions (the `run_mutation` long tail)
|
|
2
|
+
|
|
3
|
+
<!-- Generated from the Phenomenal tool registry. Do not edit by hand: a drift
|
|
4
|
+
gate fails when these files are not what the registry currently says. -->
|
|
5
|
+
|
|
6
|
+
_Tool surface: 39 tools · 163 actions · 5 prompts · fingerprint `fef338e5`._
|
|
7
|
+
|
|
8
|
+
The curated tools in `references/tools.md` cover the work an officer does most days. Everything else Phenomenal can do is reachable by name:
|
|
9
|
+
|
|
10
|
+
1. `list_mutations({ area, search })` — the index, filtered.
|
|
11
|
+
2. `describe_mutation(name)` — the exact arguments, as a JSON Schema. **Read this; do not guess an argument name.**
|
|
12
|
+
3. `run_mutation(name, input, confirm?)` — run it.
|
|
13
|
+
|
|
14
|
+
Prefer a curated tool when one covers what you need: it is one call instead of three, and it resolves names for you.
|
|
15
|
+
|
|
16
|
+
**(confirm)** marks an action that sends mail, moves money, publishes something publicly, deletes something, changes who can do what, or changes the organization's web address. Those change nothing until a person has said yes in words. Every action is subject to your role in the organization regardless; the confirm gate is about being asked, not about being allowed.
|
|
17
|
+
|
|
18
|
+
Areas: account, brand, broadcasts, connections, domains, drive, email-preferences, events, forms, groups, knowledge, looks, media, meetings, members, money, orders, organization, pages, store, tasks, tickets.
|
|
19
|
+
|
|
20
|
+
## account
|
|
21
|
+
|
|
22
|
+
- `updateMyProfile` — Change your own name and preferred language.
|
|
23
|
+
|
|
24
|
+
## brand
|
|
25
|
+
|
|
26
|
+
- `activateBrandKit` **(confirm)** — Make a saved brand kit the organization's live one.
|
|
27
|
+
- `createBrandKit` — Save a new brand kit for the organization.
|
|
28
|
+
- `generateBrandKit` — Generate a brand kit from the school's existing website or logo.
|
|
29
|
+
- `readSiteContent` — Read an existing website's pages so a brand kit or starter content can be built from them.
|
|
30
|
+
- `updateBrandKit` — Replace a saved brand kit.
|
|
31
|
+
|
|
32
|
+
## broadcasts
|
|
33
|
+
|
|
34
|
+
- `createBroadcastDraft` — Prefer the `draft_broadcast` tool. Create an unsent email draft for the organization, with its audience.
|
|
35
|
+
- `retryFailedDeliveries` **(confirm)** — Re-send a broadcast to the recipients whose delivery failed.
|
|
36
|
+
- `sendBroadcast` **(confirm)** — Prefer the `send_broadcast` tool. Send a broadcast to its audience.
|
|
37
|
+
- `sendBroadcastTest` **(confirm)** — Prefer the `send_broadcast_test` tool. Send one test copy of a broadcast to a single address.
|
|
38
|
+
- `translateBroadcast` — Fill in a broadcast's missing translations for the organization's languages.
|
|
39
|
+
- `updateBroadcastDraft` — Prefer the `draft_broadcast` tool. Replace an unsent broadcast draft, including its audience.
|
|
40
|
+
|
|
41
|
+
## connections
|
|
42
|
+
|
|
43
|
+
- `revokeAgentGrant` **(confirm)** — Disconnect an AI assistant this person connected to Phenomenal — possibly the one you are running in, which would end this conversation.
|
|
44
|
+
|
|
45
|
+
## domains
|
|
46
|
+
|
|
47
|
+
- `addDomain` **(confirm)** — Register a school-owned domain name for the organization and return the DNS records to publish.
|
|
48
|
+
- `claimSubdomain` **(confirm)** — Claim a phenomenal.org web address for the organization.
|
|
49
|
+
- `disableDomainSending` **(confirm)** — Stop sending email from a custom domain.
|
|
50
|
+
- `refreshDomainSending` **(confirm)** — Re-check the DNS records for sending email from a custom domain and update its status.
|
|
51
|
+
- `releaseSubdomain` **(confirm)** — Give up the organization's phenomenal.org web address.
|
|
52
|
+
- `removeDomain` **(confirm)** — Remove a custom domain from the organization.
|
|
53
|
+
- `startDomainSending` **(confirm)** — Start sending organization email from a custom domain and return the DKIM records to publish.
|
|
54
|
+
- `verifyDomain` **(confirm)** — Advance a custom domain through verification — first ownership, then DNS.
|
|
55
|
+
|
|
56
|
+
## drive
|
|
57
|
+
|
|
58
|
+
- `disconnectGoogleDrive` — Disconnect the organization's Google Drive.
|
|
59
|
+
- `exportDriveCsv` — Export a Google Drive spreadsheet as CSV text for import.
|
|
60
|
+
- `importDriveFiles` — Import chosen Google Drive files into the knowledge base at a classification and scope.
|
|
61
|
+
- `importDriveFolder` — Import a whole Google Drive folder into the knowledge base, optionally including subfolders.
|
|
62
|
+
|
|
63
|
+
## email-preferences
|
|
64
|
+
|
|
65
|
+
- `setMyEmailStream` — Change your own subscription to one of an organization's email streams.
|
|
66
|
+
- `setMyPreferredLanguage` — Set the language you want Phenomenal to write to you in.
|
|
67
|
+
- `unsubscribeMeFromOrg` — Unsubscribe yourself from all of an organization's email.
|
|
68
|
+
|
|
69
|
+
## events
|
|
70
|
+
|
|
71
|
+
- `createEvent` — Prefer the `create_event` tool. Create an event.
|
|
72
|
+
- `createTicketType` — Add a ticket type (price, capacity) to an event.
|
|
73
|
+
- `deleteEvent` **(confirm)** — Delete an event and its ticket types.
|
|
74
|
+
- `deleteTicketType` **(confirm)** — Delete a ticket type from an event.
|
|
75
|
+
- `setEventPublished` **(confirm)** — Prefer the `set_event_published` tool. Publish or unpublish an event.
|
|
76
|
+
- `setEventVisibility` **(confirm)** — Set who can see an event — everyone, members, or one group.
|
|
77
|
+
- `translateEvent` — Fill in an event's missing translations for the organization's languages.
|
|
78
|
+
- `updateEvent` — Prefer the `update_event` tool. Change an event — time, place, description, page content.
|
|
79
|
+
- `updateTicketType` — Change a ticket type's name, price, capacity or availability.
|
|
80
|
+
|
|
81
|
+
## forms
|
|
82
|
+
|
|
83
|
+
- `createForm` — Create a form (sign-ups, RSVPs, volunteer slots) as a draft.
|
|
84
|
+
- `deleteForm` **(confirm)** — Delete a form.
|
|
85
|
+
- `publishForm` **(confirm)** — Publish a form so people can fill it in.
|
|
86
|
+
- `renameForm` — Change a form's title.
|
|
87
|
+
- `setFormSubmissionStatus` — Mark a form submission new, in review, or handled.
|
|
88
|
+
- `unpublishForm` **(confirm)** — Take a form off the site.
|
|
89
|
+
- `updateFormDraft` — Replace a form draft.
|
|
90
|
+
|
|
91
|
+
## groups
|
|
92
|
+
|
|
93
|
+
- `createGroup` — Create a group — a class, a committee, a team.
|
|
94
|
+
- `createGroupPage` — Create a group's own landing page.
|
|
95
|
+
- `deleteGroup` **(confirm)** — Delete a group.
|
|
96
|
+
- `joinGroup` — Join an open group yourself.
|
|
97
|
+
- `leaveGroup` — Leave a group yourself.
|
|
98
|
+
- `removeGroupMembership` **(confirm)** — Take a member out of one group.
|
|
99
|
+
- `setGroupJoinPolicy` **(confirm)** — Set whether people can join a group themselves or only an admin can add them.
|
|
100
|
+
- `setGroupMembership` **(confirm)** — Put a member in a group with a relation, or change the relation they are in it with.
|
|
101
|
+
- `setGroupMemberStatus` **(confirm)** — Mark a member active or inactive in one group.
|
|
102
|
+
- `setGroupMemberTitle` — Set a member's display title in one group (Teacher, Room Parent).
|
|
103
|
+
- `setGroupParent` — Move a group underneath another group, or to the top level.
|
|
104
|
+
- `translateGroup` — Fill in a group's missing name translations.
|
|
105
|
+
- `updateGroup` — Change a group's name or description.
|
|
106
|
+
|
|
107
|
+
## knowledge
|
|
108
|
+
|
|
109
|
+
- `addDocument` — Add a document to the organization's knowledge base so the assistant can answer from it.
|
|
110
|
+
- `askOrg` — Prefer the `ask_org` tool. Ask a question and get an answer drawn from the organization's own documents, with citations.
|
|
111
|
+
- `deleteDocument` **(confirm)** — Delete a document from the organization's knowledge base.
|
|
112
|
+
- `importUploadedDocument` — Import a document from pasted text into the knowledge base.
|
|
113
|
+
- `learnAgain` — Re-index one knowledge source so the assistant picks up its current contents.
|
|
114
|
+
- `reclassifyDocument` **(confirm)** — Change who a knowledge document can be shown to.
|
|
115
|
+
- `relearnKnowledge` — Bring a retired knowledge source back into the assistant's answers.
|
|
116
|
+
- `unlearnKnowledge` **(confirm)** — Retire a knowledge source from the assistant's answers, with a reason.
|
|
117
|
+
- `updateDocument` — Change a knowledge document's title, kind or body.
|
|
118
|
+
|
|
119
|
+
## looks
|
|
120
|
+
|
|
121
|
+
- `deleteLook` **(confirm)** — Delete a saved visual preset.
|
|
122
|
+
- `setSurfaceLook` — Apply a saved visual preset to a page, event, form or broadcast.
|
|
123
|
+
- `suggestLook` — Suggest a visual preset for an occasion.
|
|
124
|
+
- `upsertLook` — Create or replace a saved visual preset.
|
|
125
|
+
|
|
126
|
+
## media
|
|
127
|
+
|
|
128
|
+
- `deleteAsset` **(confirm)** — Delete an uploaded photo or file.
|
|
129
|
+
- `discardEditedImage` — Throw away an AI image edit that was never kept.
|
|
130
|
+
- `editAsset` — Edit a photo with AI from a plain-language instruction.
|
|
131
|
+
- `generateLibraryImage` — Generate a new image for the organization's media library from an instruction.
|
|
132
|
+
- `keepEditedImage` — Save an AI image edit into the organization's media library as a new asset.
|
|
133
|
+
- `keepLibraryImage` — Save a generated image into the organization's media library.
|
|
134
|
+
- `learnAsset` — Index a file's contents so the assistant can answer from it.
|
|
135
|
+
- `redescribeAsset` — Regenerate a file's AI description and alt text.
|
|
136
|
+
- `setAssetAudience` **(confirm)** — Change who can see an uploaded file — the public, or members only.
|
|
137
|
+
- `updateAsset` — Change an uploaded file's title, alt text, classification or scope.
|
|
138
|
+
|
|
139
|
+
## meetings
|
|
140
|
+
|
|
141
|
+
- `addAgendaItem` — Add an item to a meeting's agenda.
|
|
142
|
+
- `adjournMeeting` **(confirm)** — End a live meeting.
|
|
143
|
+
- `appendTranscript` — Append transcript segments to a live meeting's record.
|
|
144
|
+
- `approveItemMinutes` **(confirm)** — Approve the minutes text for one agenda item.
|
|
145
|
+
- `cancelPrompt` — Discard a live vote without recording it.
|
|
146
|
+
- `closePrompt` **(confirm)** — Close a live vote and record its result in the meeting's minutes and ledger.
|
|
147
|
+
- `compileMinutesDraft` — Compile and AI-clean an adjourned meeting's minutes into the working draft.
|
|
148
|
+
- `createMeeting` — Create a meeting, optionally scheduled.
|
|
149
|
+
- `draftItemMinutes` — Suggest minutes text for one agenda item from the transcript.
|
|
150
|
+
- `generateItemMinutes` — Auto-draft and save an agenda item's minutes from the transcript and its recorded motions, marking the item done.
|
|
151
|
+
- `openPrompt` — Open a live vote in a meeting with its question and options.
|
|
152
|
+
- `publishMinutes` **(confirm)** — Publish an adjourned meeting's minutes as a page and email every active member their action items.
|
|
153
|
+
- `raiseQuestion` — Raise a question to the floor of a live meeting so the chair sees it.
|
|
154
|
+
- `recordMotion` **(confirm)** — Record a motion in the minutes of a live meeting, with who moved and seconded it.
|
|
155
|
+
- `removeAgendaItem` **(confirm)** — Delete an agenda item and renumber the rest of the meeting's agenda.
|
|
156
|
+
- `reorderAgendaItems` — Set the order of a meeting's agenda items by listing their ids in the order you want.
|
|
157
|
+
- `resolveQuestion` — Mark a question raised to the floor answered or dismissed.
|
|
158
|
+
- `respondToPrompt` **(confirm)** — Cast your own vote in a live meeting prompt.
|
|
159
|
+
- `saveMinutesDraft` — Save the Secretary's edited minutes draft.
|
|
160
|
+
- `setActiveItem` — Make an agenda item the one the live meeting is on.
|
|
161
|
+
- `setAttendance` — Record whether a member is present at a meeting.
|
|
162
|
+
- `startMeeting` **(confirm)** — Start a meeting.
|
|
163
|
+
- `suggestPoll` — Suggest a poll question and options from the recent meeting transcript.
|
|
164
|
+
- `suggestPollOptions` — Suggest options for a poll question from the recent transcript.
|
|
165
|
+
- `suggestTasks` — Suggest follow-up tasks for an agenda item.
|
|
166
|
+
- `translateMeeting` — Fill in a meeting title's missing translations.
|
|
167
|
+
- `triageWindow` — Classify a window of live meeting transcript into suggested governance decisions.
|
|
168
|
+
- `updateAgendaItem` — Change an agenda item's title, kind or detail.
|
|
169
|
+
- `updateMeeting` — Change a meeting's title or scheduled time.
|
|
170
|
+
|
|
171
|
+
## members
|
|
172
|
+
|
|
173
|
+
- `acceptInvite` — Accept an invitation to join an organization using the token from the invite link.
|
|
174
|
+
- `assignMemberRole` **(confirm)** — Give a member an additional named role (Treasurer, Room Parent).
|
|
175
|
+
- `confirmMemberImport` **(confirm)** — Commit a member import that `previewMemberImport` has already checked.
|
|
176
|
+
- `createInvite` **(confirm)** — Prefer the `invite_member` tool. Invite someone to the organization by email at a chosen role.
|
|
177
|
+
- `previewMemberImport` — Check a CSV of members and report what would happen, without writing anything.
|
|
178
|
+
- `removeMember` **(confirm)** — Prefer the `remove_member` tool. Remove someone from the organization entirely.
|
|
179
|
+
- `revokeInvite` **(confirm)** — Cancel a pending invitation.
|
|
180
|
+
- `setMemberRole` **(confirm)** — Prefer the `set_member_role` tool. Change a member's role in the organization.
|
|
181
|
+
- `setMemberStatus` **(confirm)** — Suspend or reactivate a member.
|
|
182
|
+
- `unassignMemberRole` **(confirm)** — Take a named role away from a member.
|
|
183
|
+
|
|
184
|
+
## money
|
|
185
|
+
|
|
186
|
+
- `startPayout` **(confirm)** — Prefer the `start_payout` tool. Pay the available Stripe balance out to the organization's bank account.
|
|
187
|
+
- `startStripeOnboarding` **(confirm)** — Begin Stripe onboarding for the organization and return the link to finish it.
|
|
188
|
+
|
|
189
|
+
## orders
|
|
190
|
+
|
|
191
|
+
- `cancelOrder` **(confirm)** — Prefer the `cancel_order` tool. Cancel a store order and, when asked, refund the buyer.
|
|
192
|
+
- `retryOrder` **(confirm)** — Retry fulfillment for a store order that failed.
|
|
193
|
+
|
|
194
|
+
## organization
|
|
195
|
+
|
|
196
|
+
- `createOrg` — Create a new organization with you as its owner.
|
|
197
|
+
- `setOrgDefaultLanguage` **(confirm)** — Set the organization's default site language.
|
|
198
|
+
- `setOrgJoinPolicy` **(confirm)** — Set whether people can request to join the organization themselves.
|
|
199
|
+
- `setOrgLanguages` **(confirm)** — Set which languages the site is offered in, as a comma-separated list.
|
|
200
|
+
- `suggestOrgTheme` — Suggest theme colors and fonts from a description.
|
|
201
|
+
- `updateOrg` **(confirm)** — Change the organization's name, contact email, postal address or home page.
|
|
202
|
+
- `updateOrgChrome` — Replace the site's header and footer content.
|
|
203
|
+
- `updateOrgDesignSystem` — Replace the organization's design system.
|
|
204
|
+
- `updateOrgNav` — Replace the site navigation.
|
|
205
|
+
- `updateOrgTheme` — Change the organization's colors, fonts and logo.
|
|
206
|
+
|
|
207
|
+
## pages
|
|
208
|
+
|
|
209
|
+
- `createGroupSubpage` — Create a page underneath a group's landing page.
|
|
210
|
+
- `createPage` — Create a new, empty page.
|
|
211
|
+
- `deletePage` **(confirm)** — Delete a page, published or not.
|
|
212
|
+
- `draftPageBlocks` — Prefer the `draft_page` tool. Draft page content from a plain-language instruction and return the blocks.
|
|
213
|
+
- `generateBlockImage` — Generate an image for one content block from an instruction.
|
|
214
|
+
- `generateSitePages` **(confirm)** — Generate and publish a set of starter pages for the site from a description.
|
|
215
|
+
- `movePage` — Change a page's URL slug.
|
|
216
|
+
- `publishPage` **(confirm)** — Prefer the `publish_page` tool. Publish a page draft to the live site.
|
|
217
|
+
- `renamePage` — Change a page's title, optionally for one language only.
|
|
218
|
+
- `rewriteBlockText` — Rewrite one content block's text from a plain-language instruction.
|
|
219
|
+
- `setPageEditPolicy` **(confirm)** — Set who may edit a page — organization admins, or a group's stewards too.
|
|
220
|
+
- `setPageGroupSlug` — Change a page's path segment underneath its group.
|
|
221
|
+
- `setPageMediaAudience` **(confirm)** — Change who can see the images on a page.
|
|
222
|
+
- `setPageVisibility` **(confirm)** — Set who can see a page — everyone, members, or one group.
|
|
223
|
+
- `translateDocument` — Translate a document's text into the organization's languages.
|
|
224
|
+
- `translatePage` — Fill in a page's missing translations, for one block or the whole page.
|
|
225
|
+
- `unpublishPage` **(confirm)** — Prefer the `unpublish_page` tool. Take a page off the live site.
|
|
226
|
+
- `updatePageDraft` — Prefer the `update_page_draft` tool. Replace a page draft with new blocks.
|
|
227
|
+
|
|
228
|
+
## store
|
|
229
|
+
|
|
230
|
+
- `createOrgProduct` — Add a product to the store from a catalog blank at a retail price.
|
|
231
|
+
- `deleteOrgProduct` **(confirm)** — Remove a product from the store.
|
|
232
|
+
- `deleteProductGroup` **(confirm)** — Delete a product group and leave its individual products in place.
|
|
233
|
+
- `setOrgProductEnabled` **(confirm)** — Show or hide a store product.
|
|
234
|
+
- `updateOrgProduct` — Change a store product's title or retail price.
|
|
235
|
+
- `upsertProductGroup` — Create or replace a product group and its variants.
|
|
236
|
+
|
|
237
|
+
## tasks
|
|
238
|
+
|
|
239
|
+
- `createTask` — Prefer the `create_task` tool. Create a follow-up task, optionally assigned to a member and tied to a meeting.
|
|
240
|
+
- `setTaskStatus` — Prefer the `set_task_status` tool. Mark a task open or done.
|
|
241
|
+
|
|
242
|
+
## tickets
|
|
243
|
+
|
|
244
|
+
- `checkInTicket` — Check a ticket in at the door by its code.
|
|
245
|
+
- `compTickets` **(confirm)** — Issue free tickets to someone for an event.
|
|
246
|
+
- `refundTicketOrder` **(confirm)** — Prefer the `refund_ticket_order` tool. Refund a ticket order in full and void its tickets.
|
|
247
|
+
- `undoCheckIn` — Undo a ticket check-in at the door.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Reading Phenomenal's schema
|
|
2
|
+
|
|
3
|
+
<!-- Generated from the Phenomenal tool registry. Do not edit by hand: a drift
|
|
4
|
+
gate fails when these files are not what the registry currently says. -->
|
|
5
|
+
|
|
6
|
+
_Tool surface: 39 tools · 163 actions · 5 prompts · fingerprint `fef338e5`._
|
|
7
|
+
|
|
8
|
+
Two tools answer questions no curated tool anticipated.
|
|
9
|
+
|
|
10
|
+
## `get_schema(typeName?)`
|
|
11
|
+
|
|
12
|
+
Returns the named GraphQL type plus one level of the types it references. With no argument it returns the whole schema, which is large — name a type when you can.
|
|
13
|
+
|
|
14
|
+
The same text is also a resource: `phenomenal://schema.graphql`. Reading a resource costs no tool call, so prefer it when your client supports resources.
|
|
15
|
+
|
|
16
|
+
## `query_graphql(query, variables?)`
|
|
17
|
+
|
|
18
|
+
Runs a **read-only** GraphQL query against the same schema, as you, in your own transaction. Use it for a shape no tool returns — a count across events, a field a list tool omits, one page's blocks alongside its status.
|
|
19
|
+
|
|
20
|
+
It is not a way around anything. It executes through exactly the path `/graphql` serves, with your role and the same row-level rules, so a query for something you may not read comes back refused, not empty-and-silent.
|
|
21
|
+
|
|
22
|
+
### What it will refuse
|
|
23
|
+
|
|
24
|
+
- **Anything that is not a query.** A mutation, a subscription, or a document with several operations and no `operationName`. Mutations go through `run_mutation`.
|
|
25
|
+
- **Introspection.** `__schema` and `__type` are blocked, because `get_schema` and the `phenomenal://schema.graphql` resource are the cheaper, complete answer.
|
|
26
|
+
- **Depth over 8.** Nested selections deeper than that are rejected before they run.
|
|
27
|
+
- **More than 30 aliases** in one document.
|
|
28
|
+
- **A cost over 1000.** Cost weights list fields' children, so a wide selection under several lists trips it. Ask for the fields you need.
|
|
29
|
+
|
|
30
|
+
A refused query says which limit it hit. Narrow the selection rather than retrying it unchanged.
|
|
31
|
+
|
|
32
|
+
## Working with it
|
|
33
|
+
|
|
34
|
+
1. `get_schema("Query")` to see what can be asked for.
|
|
35
|
+
2. `get_schema("Event")` (or whichever type) for its fields.
|
|
36
|
+
3. `query_graphql` with a small selection, then widen if you need to.
|
|
37
|
+
|
|
38
|
+
Most queries take an `orgId`. It comes from `list_my_orgs`, like everywhere else — never invent one.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Phenomenal for agents
|
|
2
|
+
|
|
3
|
+
<!-- Generated from the Phenomenal tool registry. Do not edit by hand: a drift
|
|
4
|
+
gate fails when these files are not what the registry currently says. -->
|
|
5
|
+
|
|
6
|
+
_Tool surface: 39 tools · 163 actions · 5 prompts · fingerprint `fef338e5`._
|
|
7
|
+
|
|
8
|
+
Phenomenal runs a school's PTO: its public website, its member roster, its events and tickets, its email to families, its forms, its store and its money. It exposes all of that over the Model Context Protocol, so an assistant an officer already uses can do the work with them.
|
|
9
|
+
|
|
10
|
+
**If you are an assistant reading this on someone's behalf:** connect with one of the recipes below, then follow the guidance in "How to work in Phenomenal" further down. It combines the standing instructions and workflows from the live registry.
|
|
11
|
+
|
|
12
|
+
## Connect
|
|
13
|
+
|
|
14
|
+
The server is at `https://api.phenomenal.org/mcp`. Signing in happens in a browser: the person picks which organizations the connection may act for, and the connection can never do more than their own role allows.
|
|
15
|
+
|
|
16
|
+
**Claude Code**
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
claude mcp add --transport http phenomenal https://api.phenomenal.org/mcp
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Codex CLI**
|
|
23
|
+
|
|
24
|
+
Run the add command first. If it opens sign-in, finish in the browser. If it hangs after saying the server was added, press Ctrl+C; the configuration is already saved. Then run the login command separately to finish or retry sign-in.
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
codex mcp add phenomenal --url https://api.phenomenal.org/mcp
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
codex mcp login phenomenal
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Claude Desktop**
|
|
35
|
+
|
|
36
|
+
Settings → Connectors → Add custom connector, then paste `https://api.phenomenal.org/mcp`.
|
|
37
|
+
|
|
38
|
+
**Anything that only speaks stdio**
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
npx @phenomenalorg/mcp
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Node 20 or newer.
|
|
45
|
+
|
|
46
|
+
## Install the skill package
|
|
47
|
+
|
|
48
|
+
A client that reads [Agent Skills](https://code.claude.com/docs/en/skills) can hold the briefing below as a file, so it loads only when it is needed:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
npx @phenomenalorg/mcp --skill <dir>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
That writes a `phenomenal/` folder — `SKILL.md` plus its reference sheets — into the directory you name. With no directory it installs into `.claude/skills/` when that folder is already there, and prints `SKILL.md` to stdout when it is not.
|
|
55
|
+
|
|
56
|
+
## How to work in Phenomenal
|
|
57
|
+
|
|
58
|
+
You are connected to Phenomenal, the platform for this PTO's site, members, events, tickets, email, forms, store and money.
|
|
59
|
+
|
|
60
|
+
Start with list_my_orgs. Every organization id comes from it; never guess or invent one. Name the selected organization; ask if ambiguous.
|
|
61
|
+
|
|
62
|
+
Say whether you are drafting, saving or publishing. draft_page saves nothing. draft_broadcast saves a draft and returns its id; it sends nothing. update_page_draft saves privately. publish_page publishes; send_broadcast sends to families.
|
|
63
|
+
|
|
64
|
+
For any tool with confirm, first call WITHOUT confirm. Present the returned action, target and effect to the user, then END THE TURN. Wait for a NEW explicit user message approving that exact preview; only then use confirm: true for the same action/target. The initial request and client/native tool-permission approval do not approve a later preview. Never self-confirm. “Nothing has happened yet” is a successful no-effect preview, not an error or retry signal.
|
|
65
|
+
|
|
66
|
+
Mail and money are one-way. Slow down before sending, refunding or paying out.
|
|
67
|
+
|
|
68
|
+
Keep member names, addresses and form answers in your answer to the officer; never copy them into public pages or broadcasts. Write US English, plainly and warmly, for parents on phones. On FORBIDDEN, explain the role limit and stop; never hunt for another route.
|
|
69
|
+
|
|
70
|
+
Publish a page: list_pages → get_page → draft_page → update_page_draft (saved privately) → preview publish_page → ask → publish_page with confirm: true.
|
|
71
|
+
|
|
72
|
+
For other work: list_mutations → describe_mutation → run_mutation. Read arguments; never guess. query_graphql is read-only.
|
|
73
|
+
|
|
74
|
+
## Worked sequences
|
|
75
|
+
|
|
76
|
+
Draft the weekly newsletter for my organization (call list_my_orgs first): org_overview → list_events for the next three weeks → list_pages → draft_broadcast. Report the saved draft and audience; use US English for parents. If a test is requested: send_broadcast_test without confirm → present its action/target/effect → end the turn → wait for a NEW explicit user message approving that preview → confirm the same action/target. Repeat the entire sequence separately for send_broadcast; test approval never approves the full send.
|
|
77
|
+
|
|
78
|
+
New event for my organization (call list_my_orgs first): . Ask for missing dates, location and ticket details. list_events → create_event → update_event for event details only. For tickets: list_mutations({ area: "events" }) → describe_mutation({ name: "createTicketType" }) → run_mutation with its exact input schema. For ticket changes, describe_mutation({ name: "updateTicketType" }) first. Leave the event unpublished; preview set_event_published and ask before confirming.
|
|
79
|
+
|
|
80
|
+
Membership review for my organization (call list_my_orgs first): list_members (follow cursors) → list_groups → list_group_members. Report pending or suspended members and officer roles. Recommend changes but make none; keep names and addresses in your answer to me.
|
|
81
|
+
|
|
82
|
+
Month-end money for my organization (call list_my_orgs first): payout_status → list_orders. Report holds, failures, possible refunds and available funds. Propose refund_ticket_order, cancel_order or start_payout only when needed; each needs its own preview and yes. Move no money yet.
|
|
83
|
+
|
|
84
|
+
## Reference
|
|
85
|
+
|
|
86
|
+
- https://phenomenal.org/agents/tools — every tool, its arguments, and whether it needs `confirm`.
|
|
87
|
+
- https://phenomenal.org/agents/mutations — the `run_mutation` long tail, by area.
|
|
88
|
+
- https://phenomenal.org/agents/schema — `query_graphql` and `get_schema`, and the limits they enforce.
|
|
89
|
+
|
|
90
|
+
## When this page and the server disagree
|
|
91
|
+
|
|
92
|
+
This page is a copy of the server's own registry, published from it. Read `phenomenal://instructions` and compare its `Tool surface fingerprint` with the fingerprint above. If they differ, say this guide is out of date and use live instructions, schemas and confirmation requirements. If the resource has no fingerprint, freshness is unknown. Do not compare this fingerprint with the product version. `initialize` reports the live server's version as `serverInfo.version`, and `tools/list` reports exactly which tools it has — **those are the authority.** If a tool named here is missing from the live list, go by the live list and say plainly that the published guide is out of date.
|
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
# Phenomenal tools
|
|
2
|
+
|
|
3
|
+
<!-- Generated from the Phenomenal tool registry. Do not edit by hand: a drift
|
|
4
|
+
gate fails when these files are not what the registry currently says. -->
|
|
5
|
+
|
|
6
|
+
_Tool surface: 39 tools · 163 actions · 5 prompts · fingerprint `fef338e5`._
|
|
7
|
+
|
|
8
|
+
Every tool the Phenomenal MCP server offers, in the order a client lists them. `list_my_orgs` is first because every other tool needs an organization id from it.
|
|
9
|
+
|
|
10
|
+
**Confirm** means the tool changes nothing until a person has said yes in words and you pass `confirm: true`. Called without it, the tool returns a preview of what would happen. See `SKILL.md`.
|
|
11
|
+
|
|
12
|
+
**Hints** are the MCP annotations a client shows before it calls: _read-only_ (no write of any kind), _writes_, _destructive_ (it can destroy something a person would miss), _idempotent_ (calling twice is the same as once). They are hints, not a fence — what you are allowed to do is decided by your role in the organization.
|
|
13
|
+
|
|
14
|
+
### `list_my_orgs`
|
|
15
|
+
|
|
16
|
+
List the organizations you can act for in Phenomenal, with your role in each. Call this first: every other tool needs an organization id from this list.
|
|
17
|
+
|
|
18
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
19
|
+
|
|
20
|
+
**Arguments**
|
|
21
|
+
|
|
22
|
+
- none
|
|
23
|
+
|
|
24
|
+
### `org_overview`
|
|
25
|
+
|
|
26
|
+
A one-call summary of an organization in Phenomenal: its name and web address, how many members it has, its most recent pages, events, groups and broadcasts, and where its money stands. Sections your role cannot read are listed under "unavailable" rather than left out.
|
|
27
|
+
|
|
28
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
29
|
+
|
|
30
|
+
**Arguments**
|
|
31
|
+
|
|
32
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
33
|
+
|
|
34
|
+
### `list_members`
|
|
35
|
+
|
|
36
|
+
The people in a Phenomenal organization, with each person's role and status. Use the membershipId from here for set_member_role and remove_member — never a user id.
|
|
37
|
+
|
|
38
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
39
|
+
|
|
40
|
+
**Arguments**
|
|
41
|
+
|
|
42
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
43
|
+
- `status` (string (active | pending | suspended)) — Only members in this state. Leave it out for everyone.
|
|
44
|
+
- `limit` (integer) — How many to return (1–200, default 50).
|
|
45
|
+
- `cursor` (string) — The nextCursor from a previous call.
|
|
46
|
+
|
|
47
|
+
### `invite_member`
|
|
48
|
+
|
|
49
|
+
Invite someone to a Phenomenal organization by email at a chosen role. An invitation email goes out immediately, so this needs confirm: true. You cannot invite at a role above your own.
|
|
50
|
+
|
|
51
|
+
**Hints:** destructive. **Confirm:** required — without it you get a preview and nothing changes.
|
|
52
|
+
|
|
53
|
+
**Arguments**
|
|
54
|
+
|
|
55
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
56
|
+
- `email` (string, required) — The invitee’s email address.
|
|
57
|
+
- `role` (string (owner | admin | editor | member), required) — The role they join at. Most people are "member"; officers are "admin".
|
|
58
|
+
- `confirm` (boolean) — First call without confirm. Present the returned action, target and effect, END THE TURN, and wait for a NEW explicit user message approving that exact preview. Only then set true for the same action/target. Initial requests and client/native tool-permission approvals do not count.
|
|
59
|
+
|
|
60
|
+
### `set_member_role`
|
|
61
|
+
|
|
62
|
+
Change a member's role in a Phenomenal organization. This changes what they can do, so it needs confirm: true. You cannot grant a role above your own, only an owner may change an owner, and the last active owner cannot be demoted.
|
|
63
|
+
|
|
64
|
+
**Hints:** destructive. **Confirm:** required — without it you get a preview and nothing changes.
|
|
65
|
+
|
|
66
|
+
**Arguments**
|
|
67
|
+
|
|
68
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
69
|
+
- `membershipId` (string, required) — From list_members — not a user id.
|
|
70
|
+
- `role` (string (owner | admin | editor | member), required) — The role to move them to.
|
|
71
|
+
- `confirm` (boolean) — First call without confirm. Present the returned action, target and effect, END THE TURN, and wait for a NEW explicit user message approving that exact preview. Only then set true for the same action/target. Initial requests and client/native tool-permission approvals do not count.
|
|
72
|
+
|
|
73
|
+
### `remove_member`
|
|
74
|
+
|
|
75
|
+
Remove someone from a Phenomenal organization entirely. They lose access immediately, so this needs confirm: true. Suspending them instead keeps the record — ask the person which they meant.
|
|
76
|
+
|
|
77
|
+
**Hints:** destructive. **Confirm:** required — without it you get a preview and nothing changes.
|
|
78
|
+
|
|
79
|
+
**Arguments**
|
|
80
|
+
|
|
81
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
82
|
+
- `membershipId` (string, required) — From list_members — not a user id.
|
|
83
|
+
- `confirm` (boolean) — First call without confirm. Present the returned action, target and effect, END THE TURN, and wait for a NEW explicit user message approving that exact preview. Only then set true for the same action/target. Initial requests and client/native tool-permission approvals do not count.
|
|
84
|
+
|
|
85
|
+
### `list_pages`
|
|
86
|
+
|
|
87
|
+
The pages on a Phenomenal organization's site, with each page's slug and whether it is published. Use the id from here with get_page, update_page_draft and publish_page.
|
|
88
|
+
|
|
89
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
90
|
+
|
|
91
|
+
**Arguments**
|
|
92
|
+
|
|
93
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
94
|
+
- `status` (string (draft | published | published_changes)) — Only pages in this state. "published_changes" means it is live but the draft has moved on.
|
|
95
|
+
|
|
96
|
+
### `get_page`
|
|
97
|
+
|
|
98
|
+
One page from Phenomenal with its current draft content, as the array of blocks you would edit. Read this before changing anything: update_page_draft replaces the whole draft.
|
|
99
|
+
|
|
100
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
101
|
+
|
|
102
|
+
**Arguments**
|
|
103
|
+
|
|
104
|
+
- `pageId` (string, required) — From list_pages.
|
|
105
|
+
|
|
106
|
+
### `draft_page`
|
|
107
|
+
|
|
108
|
+
Draft content for a Phenomenal page from a plain-language instruction and return the blocks. It SAVES NOTHING — show the result to the person, then save it with update_page_draft. This counts against the organization's AI budget, exactly as drafting from the admin app does.
|
|
109
|
+
|
|
110
|
+
**Hints:** writes. **Confirm:** not required.
|
|
111
|
+
|
|
112
|
+
**Arguments**
|
|
113
|
+
|
|
114
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
115
|
+
- `pageId` (string, required) — The page being drafted, from list_pages.
|
|
116
|
+
- `instruction` (string, required) — What the page should say, in plain language — "a fall festival page with the date, the volunteer sign-up and a photo".
|
|
117
|
+
|
|
118
|
+
### `update_page_draft`
|
|
119
|
+
|
|
120
|
+
Save a page's draft in Phenomenal. Replaces the WHOLE draft, so send the full block array — read the current one with get_page first. The live page does not change until publish_page.
|
|
121
|
+
|
|
122
|
+
**Hints:** writes, idempotent. **Confirm:** not required.
|
|
123
|
+
|
|
124
|
+
**Arguments**
|
|
125
|
+
|
|
126
|
+
- `pageId` (string, required) — From list_pages.
|
|
127
|
+
- `blocks` (array, required) — The page draft as an array of Phenomenal content blocks — objects with "id", "type" and "props". Replaces the whole draft, so read the current one with get_page and send it back changed. Plain text you send in a translatable prop comes back as {"en":"…"}; that is the site storing it per language, not your save failing. Read phenomenal://block-vocabulary for the generated property names of every leaf block and section kind.
|
|
128
|
+
|
|
129
|
+
### `publish_page`
|
|
130
|
+
|
|
131
|
+
Publish a page's draft to the live Phenomenal site. Everyone can see it immediately, so this needs confirm: true.
|
|
132
|
+
|
|
133
|
+
**Hints:** writes. **Confirm:** required — without it you get a preview and nothing changes.
|
|
134
|
+
|
|
135
|
+
**Arguments**
|
|
136
|
+
|
|
137
|
+
- `pageId` (string, required) — From list_pages.
|
|
138
|
+
- `confirm` (boolean) — First call without confirm. Present the returned action, target and effect, END THE TURN, and wait for a NEW explicit user message approving that exact preview. Only then set true for the same action/target. Initial requests and client/native tool-permission approvals do not count.
|
|
139
|
+
|
|
140
|
+
### `unpublish_page`
|
|
141
|
+
|
|
142
|
+
Take a page off the live Phenomenal site. The draft is kept, but every link anyone has shared to it stops working — so this needs confirm: true.
|
|
143
|
+
|
|
144
|
+
**Hints:** destructive. **Confirm:** required — without it you get a preview and nothing changes.
|
|
145
|
+
|
|
146
|
+
**Arguments**
|
|
147
|
+
|
|
148
|
+
- `pageId` (string, required) — From list_pages.
|
|
149
|
+
- `confirm` (boolean) — First call without confirm. Present the returned action, target and effect, END THE TURN, and wait for a NEW explicit user message approving that exact preview. Only then set true for the same action/target. Initial requests and client/native tool-permission approvals do not count.
|
|
150
|
+
|
|
151
|
+
### `list_events`
|
|
152
|
+
|
|
153
|
+
The events on a Phenomenal organization's calendar, soonest first, with whether each one is published.
|
|
154
|
+
|
|
155
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
156
|
+
|
|
157
|
+
**Arguments**
|
|
158
|
+
|
|
159
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
160
|
+
- `from` (string) — Only events starting on or after this date (YYYY-MM-DD).
|
|
161
|
+
- `to` (string) — Only events starting on or before this date (YYYY-MM-DD).
|
|
162
|
+
|
|
163
|
+
### `create_event`
|
|
164
|
+
|
|
165
|
+
Create an event in Phenomenal. It starts UNPUBLISHED — nobody outside the organization sees it until set_event_published.
|
|
166
|
+
|
|
167
|
+
**Hints:** writes. **Confirm:** not required.
|
|
168
|
+
|
|
169
|
+
**Arguments**
|
|
170
|
+
|
|
171
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
172
|
+
- `title` (string, required) — What the event is called.
|
|
173
|
+
- `startsAt` (string, required) — When it starts, as an ISO 8601 date-time — "2026-10-17T18:00:00Z".
|
|
174
|
+
- `endsAt` (string) — When it ends, ISO 8601. Optional.
|
|
175
|
+
- `location` (string) — Where it is. Optional.
|
|
176
|
+
- `description` (string) — A short description for the page. Optional.
|
|
177
|
+
- `slug` (string) — The URL segment. Optional — one is derived from the title.
|
|
178
|
+
|
|
179
|
+
### `update_event`
|
|
180
|
+
|
|
181
|
+
Change an event in Phenomenal — its title, time, place or description. Only the fields you pass are changed. If the event is already published, the site changes at once.
|
|
182
|
+
|
|
183
|
+
**Hints:** writes, idempotent. **Confirm:** not required.
|
|
184
|
+
|
|
185
|
+
**Arguments**
|
|
186
|
+
|
|
187
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
188
|
+
- `eventId` (string, required) — From list_events.
|
|
189
|
+
- `title` (string) — A new title.
|
|
190
|
+
- `startsAt` (string) — A new start, ISO 8601.
|
|
191
|
+
- `endsAt` (string) — A new end, ISO 8601.
|
|
192
|
+
- `location` (string) — A new location.
|
|
193
|
+
- `description` (string) — A new description.
|
|
194
|
+
|
|
195
|
+
### `set_event_published`
|
|
196
|
+
|
|
197
|
+
Publish or unpublish an event in Phenomenal. Publishing puts it in front of everyone, so this needs confirm: true.
|
|
198
|
+
|
|
199
|
+
**Hints:** writes. **Confirm:** required — without it you get a preview and nothing changes.
|
|
200
|
+
|
|
201
|
+
**Arguments**
|
|
202
|
+
|
|
203
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
204
|
+
- `eventId` (string, required) — From list_events.
|
|
205
|
+
- `published` (boolean, required) — true to publish, false to take it down.
|
|
206
|
+
- `confirm` (boolean) — First call without confirm. Present the returned action, target and effect, END THE TURN, and wait for a NEW explicit user message approving that exact preview. Only then set true for the same action/target. Initial requests and client/native tool-permission approvals do not count.
|
|
207
|
+
|
|
208
|
+
### `list_groups`
|
|
209
|
+
|
|
210
|
+
The groups in a Phenomenal organization — classes, committees, teams — with how people get into each one. Use the groupId from here with list_group_members, and when addressing a broadcast.
|
|
211
|
+
|
|
212
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
213
|
+
|
|
214
|
+
**Arguments**
|
|
215
|
+
|
|
216
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
217
|
+
|
|
218
|
+
### `list_group_members`
|
|
219
|
+
|
|
220
|
+
Who is in one Phenomenal group, with each person's relation to it (member, steward) and whether they are still active.
|
|
221
|
+
|
|
222
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
223
|
+
|
|
224
|
+
**Arguments**
|
|
225
|
+
|
|
226
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
227
|
+
- `groupId` (string, required) — From list_groups.
|
|
228
|
+
- `status` (string (active | inactive)) — Only people in this state. Default is active only.
|
|
229
|
+
|
|
230
|
+
### `list_broadcasts`
|
|
231
|
+
|
|
232
|
+
The email broadcasts of a Phenomenal organization — drafts and sent ones — with how many people each reached.
|
|
233
|
+
|
|
234
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
235
|
+
|
|
236
|
+
**Arguments**
|
|
237
|
+
|
|
238
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
239
|
+
- `status` (string) — Only broadcasts in this state, e.g. "draft" or "sent".
|
|
240
|
+
|
|
241
|
+
### `draft_broadcast`
|
|
242
|
+
|
|
243
|
+
Write an email broadcast draft for a Phenomenal organization and choose who it would go to. SENDS NOTHING — it creates a draft and tells you how many people it would reach.
|
|
244
|
+
|
|
245
|
+
**Hints:** writes. **Confirm:** not required.
|
|
246
|
+
|
|
247
|
+
**Arguments**
|
|
248
|
+
|
|
249
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
250
|
+
- `subject` (string, required) — The subject line families will see.
|
|
251
|
+
- `body` (string, required) — The message, in Markdown. Write it the way a parent would want to read it — short, warm, and clear about dates and what to do.
|
|
252
|
+
- `audience` (object) — Who it goes to. Leave it out entirely to address every member of the organization.
|
|
253
|
+
- `replyTo` (string) — Where replies go. Optional — the organization's contact address is used otherwise.
|
|
254
|
+
|
|
255
|
+
### `send_broadcast_test`
|
|
256
|
+
|
|
257
|
+
Send ONE test copy of a Phenomenal broadcast to a single address, so a person can read it before it goes out. This is still real email to a real inbox, so it needs confirm: true.
|
|
258
|
+
|
|
259
|
+
**Hints:** destructive. **Confirm:** required — without it you get a preview and nothing changes.
|
|
260
|
+
|
|
261
|
+
**Arguments**
|
|
262
|
+
|
|
263
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
264
|
+
- `broadcastId` (string, required) — From list_broadcasts or draft_broadcast.
|
|
265
|
+
- `toEmail` (string, required) — The single address to send the test to.
|
|
266
|
+
- `confirm` (boolean) — First call without confirm. Present the returned action, target and effect, END THE TURN, and wait for a NEW explicit user message approving that exact preview. Only then set true for the same action/target. Initial requests and client/native tool-permission approvals do not count.
|
|
267
|
+
|
|
268
|
+
### `send_broadcast`
|
|
269
|
+
|
|
270
|
+
Send a Phenomenal broadcast to its whole audience. Real email leaves immediately and CANNOT be recalled, so this needs confirm: true — and the person, not you, decides.
|
|
271
|
+
|
|
272
|
+
**Hints:** destructive. **Confirm:** required — without it you get a preview and nothing changes.
|
|
273
|
+
|
|
274
|
+
**Arguments**
|
|
275
|
+
|
|
276
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
277
|
+
- `broadcastId` (string, required) — From list_broadcasts or draft_broadcast.
|
|
278
|
+
- `confirm` (boolean) — First call without confirm. Present the returned action, target and effect, END THE TURN, and wait for a NEW explicit user message approving that exact preview. Only then set true for the same action/target. Initial requests and client/native tool-permission approvals do not count.
|
|
279
|
+
|
|
280
|
+
### `list_orders`
|
|
281
|
+
|
|
282
|
+
Store orders in a Phenomenal organization, newest first, with each buyer and what they paid. Orders needing attention have onHold set or a status of fulfillment_failed.
|
|
283
|
+
|
|
284
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
285
|
+
|
|
286
|
+
**Arguments**
|
|
287
|
+
|
|
288
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
289
|
+
- `status` (string (pending | paid | submitted | shipped | delivered | fulfillment_failed | canceled | refunded)) — Only orders in this state.
|
|
290
|
+
- `limit` (integer) — How many to return (1–100, default 25).
|
|
291
|
+
- `cursor` (string) — The nextCursor from a previous call.
|
|
292
|
+
|
|
293
|
+
### `cancel_order`
|
|
294
|
+
|
|
295
|
+
Cancel a store order in Phenomenal and refund the buyer. Money moves and the buyer is emailed, so this needs confirm: true. The reason is shown to the buyer.
|
|
296
|
+
|
|
297
|
+
**Hints:** destructive. **Confirm:** required — without it you get a preview and nothing changes.
|
|
298
|
+
|
|
299
|
+
**Arguments**
|
|
300
|
+
|
|
301
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
302
|
+
- `orderId` (string, required) — From list_orders.
|
|
303
|
+
- `reason` (string, required) — Why it is being canceled, in a sentence the buyer will read (3–500 characters).
|
|
304
|
+
- `confirm` (boolean) — First call without confirm. Present the returned action, target and effect, END THE TURN, and wait for a NEW explicit user message approving that exact preview. Only then set true for the same action/target. Initial requests and client/native tool-permission approvals do not count.
|
|
305
|
+
|
|
306
|
+
### `refund_ticket_order`
|
|
307
|
+
|
|
308
|
+
Refund an event ticket purchase in Phenomenal in full and void its tickets. Money moves and the buyer is emailed, so this needs confirm: true. Ticket purchases are separate from store orders — this is the ticket one.
|
|
309
|
+
|
|
310
|
+
**Hints:** destructive. **Confirm:** required — without it you get a preview and nothing changes.
|
|
311
|
+
|
|
312
|
+
**Arguments**
|
|
313
|
+
|
|
314
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
315
|
+
- `purchaseId` (string, required) — The ticket order id.
|
|
316
|
+
- `eventId` (string) — The event the purchase belongs to, from list_events. Optional, and worth passing: with it the preview can name the buyer and the amount.
|
|
317
|
+
- `reason` (string) — Why it is being refunded, in a sentence the buyer will read.
|
|
318
|
+
- `confirm` (boolean) — First call without confirm. Present the returned action, target and effect, END THE TURN, and wait for a NEW explicit user message approving that exact preview. Only then set true for the same action/target. Initial requests and client/native tool-permission approvals do not count.
|
|
319
|
+
|
|
320
|
+
### `payout_status`
|
|
321
|
+
|
|
322
|
+
Where a Phenomenal organization's money stands: what is available to pay out, what is still settling, and the recent payouts.
|
|
323
|
+
|
|
324
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
325
|
+
|
|
326
|
+
**Arguments**
|
|
327
|
+
|
|
328
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
329
|
+
|
|
330
|
+
### `start_payout`
|
|
331
|
+
|
|
332
|
+
Pay a Phenomenal organization's available Stripe balance out to its bank account. Money leaves, so this needs confirm: true.
|
|
333
|
+
|
|
334
|
+
**Hints:** destructive. **Confirm:** required — without it you get a preview and nothing changes.
|
|
335
|
+
|
|
336
|
+
**Arguments**
|
|
337
|
+
|
|
338
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
339
|
+
- `confirm` (boolean) — First call without confirm. Present the returned action, target and effect, END THE TURN, and wait for a NEW explicit user message approving that exact preview. Only then set true for the same action/target. Initial requests and client/native tool-permission approvals do not count.
|
|
340
|
+
|
|
341
|
+
### `list_tasks`
|
|
342
|
+
|
|
343
|
+
The follow-up tasks in a Phenomenal organization — who owes what, and by when.
|
|
344
|
+
|
|
345
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
346
|
+
|
|
347
|
+
**Arguments**
|
|
348
|
+
|
|
349
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
350
|
+
- `status` (string (open | done)) — Only tasks in this state.
|
|
351
|
+
|
|
352
|
+
### `create_task`
|
|
353
|
+
|
|
354
|
+
Create a follow-up task in Phenomenal, optionally assigned to a member and due on a date.
|
|
355
|
+
|
|
356
|
+
**Hints:** writes. **Confirm:** not required.
|
|
357
|
+
|
|
358
|
+
**Arguments**
|
|
359
|
+
|
|
360
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
361
|
+
- `title` (string, required) — What needs doing, in a short sentence.
|
|
362
|
+
- `dueDate` (string) — When it is due (YYYY-MM-DD). Optional.
|
|
363
|
+
- `assigneeMembershipId` (string) — Who owes it, from list_members. Optional.
|
|
364
|
+
|
|
365
|
+
### `set_task_status`
|
|
366
|
+
|
|
367
|
+
Mark a Phenomenal task open or done. Closing one is how a meeting’s follow-ups stop showing on the assignee’s list.
|
|
368
|
+
|
|
369
|
+
**Hints:** writes, idempotent. **Confirm:** not required.
|
|
370
|
+
|
|
371
|
+
**Arguments**
|
|
372
|
+
|
|
373
|
+
- `taskId` (string, required) — From list_tasks.
|
|
374
|
+
- `status` (string (open | done), required) — The state to move it to.
|
|
375
|
+
|
|
376
|
+
### `list_forms`
|
|
377
|
+
|
|
378
|
+
The forms in a Phenomenal organization — sign-ups, RSVPs, volunteer slots — with how many submissions each has.
|
|
379
|
+
|
|
380
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
381
|
+
|
|
382
|
+
**Arguments**
|
|
383
|
+
|
|
384
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
385
|
+
|
|
386
|
+
### `form_submissions`
|
|
387
|
+
|
|
388
|
+
The answers people have submitted to a Phenomenal form, newest first. These carry family names and email addresses — keep them inside your answer to the officer and do not repeat them elsewhere.
|
|
389
|
+
|
|
390
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
391
|
+
|
|
392
|
+
**Arguments**
|
|
393
|
+
|
|
394
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
395
|
+
- `formId` (string) — From list_forms. Leave it out for every form.
|
|
396
|
+
- `status` (string) — Only submissions in this state, e.g. "new".
|
|
397
|
+
- `limit` (integer) — How many to return (1–100, default 25).
|
|
398
|
+
- `cursor` (string) — The nextCursor from a previous call.
|
|
399
|
+
|
|
400
|
+
### `find_media`
|
|
401
|
+
|
|
402
|
+
Find photos and files in a Phenomenal organization's media library by what is in them. Returns the STORED PATH of each file, which is what page blocks and events refer to — not a public link, and not something to paste into a message.
|
|
403
|
+
|
|
404
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
405
|
+
|
|
406
|
+
**Arguments**
|
|
407
|
+
|
|
408
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
409
|
+
- `query` (string, required) — What you are looking for — "fall festival pumpkins", "school logo".
|
|
410
|
+
- `kind` (string) — Narrow to one kind, e.g. "image" or "document".
|
|
411
|
+
- `limit` (integer) — How many to return (1–50, default 20).
|
|
412
|
+
|
|
413
|
+
### `ask_org`
|
|
414
|
+
|
|
415
|
+
Ask a question and get an answer drawn from a Phenomenal organization's own documents and knowledge, with citations. Use this before guessing at anything about how a particular school does things.
|
|
416
|
+
|
|
417
|
+
**Hints:** read-only. **Confirm:** not required.
|
|
418
|
+
|
|
419
|
+
**Arguments**
|
|
420
|
+
|
|
421
|
+
- `orgId` (string) — The organization to act for — an id from list_my_orgs. Never invent one; if you are unsure which, ask the person.
|
|
422
|
+
- `question` (string, required) — The question, in plain language.
|
|
423
|
+
|
|
424
|
+
### `list_mutations`
|
|
425
|
+
|
|
426
|
+
Every action Phenomenal can take that the curated tools do not already cover, as a short index. Filter by area or search by word, then read one with describe_mutation and run it with run_mutation. Reach for a curated tool first when one fits — they are shorter and they resolve names for you.
|
|
427
|
+
|
|
428
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
429
|
+
|
|
430
|
+
**Arguments**
|
|
431
|
+
|
|
432
|
+
- `area` (string (account | brand | broadcasts | connections | domains | drive | email-preferences | events | forms | groups | knowledge | looks | media | meetings | members | money | orders | organization | pages | store | tasks | tickets)) — Only actions in this part of Phenomenal.
|
|
433
|
+
- `search` (string) — Only actions whose name or summary contains this word.
|
|
434
|
+
|
|
435
|
+
### `describe_mutation`
|
|
436
|
+
|
|
437
|
+
What one Phenomenal action does and exactly what arguments it takes, as a JSON Schema. Read this before run_mutation — do not guess an argument name.
|
|
438
|
+
|
|
439
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
440
|
+
|
|
441
|
+
**Arguments**
|
|
442
|
+
|
|
443
|
+
- `name` (string, required) — From list_mutations.
|
|
444
|
+
|
|
445
|
+
### `run_mutation`
|
|
446
|
+
|
|
447
|
+
Run any Phenomenal action by name, with the arguments describe_mutation lists. Actions that send mail, move money, publish, delete, change permissions or change addressing show a preview and change nothing until confirm: true. Prefer a curated tool when one covers what you need.
|
|
448
|
+
|
|
449
|
+
**Hints:** writes. **Confirm:** required — without it you get a preview and nothing changes.
|
|
450
|
+
|
|
451
|
+
**Arguments**
|
|
452
|
+
|
|
453
|
+
- `name` (string, required) — The action name, from list_mutations.
|
|
454
|
+
- `input` (object) — The arguments, exactly as describe_mutation names them. Most take an orgId from list_my_orgs.
|
|
455
|
+
- `confirm` (boolean) — First call without confirm. Present the returned action, target and effect, END THE TURN, and wait for a NEW explicit user message approving that exact preview. Only then set true for the same action/target. Initial requests and client/native tool-permission approvals do not count.
|
|
456
|
+
|
|
457
|
+
### `query_graphql`
|
|
458
|
+
|
|
459
|
+
Read anything in Phenomenal with a GraphQL query. Read-only: only `query` operations are accepted, one per call. Use get_schema first to see the fields, and prefer a curated tool when one already answers the question.
|
|
460
|
+
|
|
461
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
462
|
+
|
|
463
|
+
**Arguments**
|
|
464
|
+
|
|
465
|
+
- `query` (string, required) — One GraphQL query operation. Most reads start from org(id: $orgId) — pass the id as a variable.
|
|
466
|
+
- `variables` (object) — Values for the query’s variables.
|
|
467
|
+
|
|
468
|
+
### `get_schema`
|
|
469
|
+
|
|
470
|
+
Phenomenal's GraphQL schema. Give a type name to see that type and the types its fields mention; give none for the list of type names. Use this before writing a query_graphql query.
|
|
471
|
+
|
|
472
|
+
**Hints:** read-only, idempotent. **Confirm:** not required.
|
|
473
|
+
|
|
474
|
+
**Arguments**
|
|
475
|
+
|
|
476
|
+
- `typeName` (string) — A type name — "Org", "Page", "Event". Leave it out to list every type.
|
|
477
|
+
|
|
478
|
+
## Workflows
|
|
479
|
+
|
|
480
|
+
### weekly_newsletter
|
|
481
|
+
|
|
482
|
+
Draft this week’s newsletter from what is actually happening, and stop before sending.
|
|
483
|
+
|
|
484
|
+
Draft the weekly newsletter for my organization (call list_my_orgs first): org_overview → list_events for the next three weeks → list_pages → draft_broadcast. Report the saved draft and audience; use US English for parents. If a test is requested: send_broadcast_test without confirm → present its action/target/effect → end the turn → wait for a NEW explicit user message approving that preview → confirm the same action/target. Repeat the entire sequence separately for send_broadcast; test approval never approves the full send.
|
|
485
|
+
|
|
486
|
+
### new_event
|
|
487
|
+
|
|
488
|
+
Set up an event and its tickets, and leave it unpublished.
|
|
489
|
+
|
|
490
|
+
New event for my organization (call list_my_orgs first): . Ask for missing dates, location and ticket details. list_events → create_event → update_event for event details only. For tickets: list_mutations({ area: "events" }) → describe_mutation({ name: "createTicketType" }) → run_mutation with its exact input schema. For ticket changes, describe_mutation({ name: "updateTicketType" }) first. Leave the event unpublished; preview set_event_published and ask before confirming.
|
|
491
|
+
|
|
492
|
+
### membership_review
|
|
493
|
+
|
|
494
|
+
Review the roster: who is waiting, who holds what, and what looks wrong.
|
|
495
|
+
|
|
496
|
+
Membership review for my organization (call list_my_orgs first): list_members (follow cursors) → list_groups → list_group_members. Report pending or suspended members and officer roles. Recommend changes but make none; keep names and addresses in your answer to me.
|
|
497
|
+
|
|
498
|
+
### site_health
|
|
499
|
+
|
|
500
|
+
Check the public site for stale, missing and unpublished things.
|
|
501
|
+
|
|
502
|
+
Check the health of my organization (call list_my_orgs first)'s Phenomenal site.
|
|
503
|
+
|
|
504
|
+
Call org_overview, list_pages and list_events. Tell me: pages that are drafts and probably should not be, pages published a long time ago whose content sounds out of date, events in the past that are still on the calendar, and whether the web address and custom domain are set up.
|
|
505
|
+
|
|
506
|
+
Give me a short list in priority order. Change nothing.
|
|
507
|
+
|
|
508
|
+
### month_end_money
|
|
509
|
+
|
|
510
|
+
Close out the month: orders needing attention, refunds outstanding, what can be paid out.
|
|
511
|
+
|
|
512
|
+
Month-end money for my organization (call list_my_orgs first): payout_status → list_orders. Report holds, failures, possible refunds and available funds. Propose refund_ticket_order, cancel_order or start_payout only when needed; each needs its own preview and yes. Move no money yet.
|