genudo-mcp-client 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -0
- package/guides.js +397 -0
- package/index.js +83 -2
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -26,6 +26,20 @@ Access Genudo's business automation tools directly from Claude Code. The server
|
|
|
26
26
|
2. **Analyze my agent performance** — spot expensive agents, low-completion stages, and actions that aren't triggering.
|
|
27
27
|
3. **Create or improve a pipeline** — e.g. "Create a Messenger sales agent for a summer camp; collect name, phone, branch, child age; escalate on special-needs questions."
|
|
28
28
|
|
|
29
|
+
### Guided instruction editing (built in)
|
|
30
|
+
|
|
31
|
+
The connector doesn't just expose tools — it teaches the agent *how* to write good agent
|
|
32
|
+
instructions, entirely client-side (no extra setup):
|
|
33
|
+
|
|
34
|
+
- **Guide tools** — `get_instruction_guides` (authoring rules + persona/global + stage
|
|
35
|
+
templates + a token-aware QA checklist) and `get_editing_playbook` (a safe
|
|
36
|
+
load → edit → diff → confirm → push workflow). The agent pulls these on demand.
|
|
37
|
+
- **Prompts (slash-commands in any MCP client)** — `edit_instructions`, `build_pipeline`,
|
|
38
|
+
`audit_pipeline`.
|
|
39
|
+
- **Safety** — before changing a live agent, the agent reads current text from
|
|
40
|
+
`list_pipelines` / `list_pipeline_stages`, shows you a before/after diff with expected
|
|
41
|
+
impact, and pushes with `update_pipeline` / `update_stage` only after you confirm.
|
|
42
|
+
|
|
29
43
|
## Quick Start
|
|
30
44
|
|
|
31
45
|
One command — no clone, no manual config:
|
|
@@ -220,6 +234,24 @@ Claude Code → (stdin) → Bridge → (HTTPS) → Genudo MCP Server
|
|
|
220
234
|
- Use HTTPS in production
|
|
221
235
|
- Limit API key permissions to minimum required access
|
|
222
236
|
|
|
237
|
+
## Privacy Policy
|
|
238
|
+
|
|
239
|
+
This client is a local bridge. It does not collect, store, or transmit your data
|
|
240
|
+
anywhere except your configured Genudo endpoint.
|
|
241
|
+
|
|
242
|
+
- **Data handled:** your `GENUDO_API_KEY` and the JSON-RPC requests your MCP
|
|
243
|
+
client makes are sent, over HTTPS, only to your Genudo server
|
|
244
|
+
(`https://api.genudo.ai` by default) using the `Api-Key` header.
|
|
245
|
+
- **Local storage:** none. The bridge keeps no logs, no cache, and no telemetry;
|
|
246
|
+
it holds nothing on disk. Your API key stays in your MCP client's own config.
|
|
247
|
+
- **Third parties:** no data is sent to any party other than Genudo.
|
|
248
|
+
- **Retention & account data:** data you access or create through Genudo is
|
|
249
|
+
governed by Genudo's policies.
|
|
250
|
+
|
|
251
|
+
Full policies: [Privacy Policy](https://genudo.ai/legal/privacy-policy) ·
|
|
252
|
+
[Terms of Service](https://genudo.ai/legal/terms-of-service). Questions:
|
|
253
|
+
support@genudo.ai.
|
|
254
|
+
|
|
223
255
|
## License
|
|
224
256
|
|
|
225
257
|
MIT
|
package/guides.js
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
// =====================================================================
|
|
2
|
+
// Genudo MCP — embedded "tool guiding" payloads and local (non-proxied)
|
|
3
|
+
// handlers. This is what turns the connector from "exposes tools" into
|
|
4
|
+
// "teaches the agent how to use them well".
|
|
5
|
+
//
|
|
6
|
+
// Everything here is served CLIENT-SIDE by index.js:
|
|
7
|
+
// - get_instruction_guides -> INSTRUCTION_GUIDES (authoring rules + templates)
|
|
8
|
+
// - get_editing_playbook -> EDITING_PLAYBOOK (safe load->edit->diff->confirm->push)
|
|
9
|
+
// - prompts/list + prompts/get -> PROMPTS + getPromptMessages()
|
|
10
|
+
//
|
|
11
|
+
// IMPORTANT: all tool/field names below are the REAL Genudo MCP surface,
|
|
12
|
+
// verified live (2026-07-04). There is NO get_instructions tool; the
|
|
13
|
+
// current instruction text is read from existing tools:
|
|
14
|
+
// - list_pipelines -> pipeline `persona`, `instructions`
|
|
15
|
+
// - list_pipeline_stages -> per stage `id`, `name`, `nature`, `order`,
|
|
16
|
+
// `instructions`, `enter_condition`, `ai_persona`
|
|
17
|
+
// Writes go through the existing tools:
|
|
18
|
+
// - update_pipeline(pipeline_id, { persona, instructions })
|
|
19
|
+
// - update_stage(stage_id, { instructions, enter_condition, ai_persona })
|
|
20
|
+
// =====================================================================
|
|
21
|
+
|
|
22
|
+
// The five editable instruction fields on a Genudo agent:
|
|
23
|
+
// pipeline.persona (identity + voice) read: list_pipelines write: update_pipeline
|
|
24
|
+
// pipeline.instructions (global behaviour) read: list_pipelines write: update_pipeline
|
|
25
|
+
// stage.instructions (stage flow) read: list_pipeline_stages write: update_stage
|
|
26
|
+
// stage.enter_condition (stage entry condition) read: list_pipeline_stages write: update_stage
|
|
27
|
+
// stage.ai_persona (optional stage voice) read: list_pipeline_stages write: update_stage
|
|
28
|
+
|
|
29
|
+
const WORKFLOW = `# Genudo Instruction Editing — Workflow
|
|
30
|
+
|
|
31
|
+
You are editing the LIVE instructions of a Genudo AI agent. There is no
|
|
32
|
+
\`get_instructions\` tool — you read current text from the normal read tools and
|
|
33
|
+
write it back with the normal update tools. Follow this exactly. Never push to a
|
|
34
|
+
live agent without explicit user confirmation.
|
|
35
|
+
|
|
36
|
+
## The five editable fields
|
|
37
|
+
| Field | Read from | Write with |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| pipeline \`persona\` (identity + voice) | \`list_pipelines\` | \`update_pipeline\` |
|
|
40
|
+
| pipeline \`instructions\` (global behaviour) | \`list_pipelines\` | \`update_pipeline\` |
|
|
41
|
+
| stage \`instructions\` (stage flow) | \`list_pipeline_stages\` | \`update_stage\` |
|
|
42
|
+
| stage \`enter_condition\` (entry condition) | \`list_pipeline_stages\` | \`update_stage\` |
|
|
43
|
+
| stage \`ai_persona\` (optional per-stage voice) | \`list_pipeline_stages\` | \`update_stage\` |
|
|
44
|
+
|
|
45
|
+
## 0. Load the guides (once per session)
|
|
46
|
+
- If a local \`./genudo-guides/\` folder with these guides does NOT exist,
|
|
47
|
+
call \`get_instruction_guides\` and write each returned guide to
|
|
48
|
+
\`./genudo-guides/<slug>.md\`. If it already exists, reuse it.
|
|
49
|
+
- ALWAYS read the guides before editing.
|
|
50
|
+
|
|
51
|
+
## 1. Load the current instructions
|
|
52
|
+
- Confirm which pipeline (and which stage[s]). Use \`list_pipelines\` to get the
|
|
53
|
+
\`pipeline_id\` (it also returns the pipeline \`persona\` and \`instructions\`).
|
|
54
|
+
- Call \`list_pipeline_stages(pipeline_id)\`. For each stage it returns \`id\`, \`name\`,
|
|
55
|
+
\`nature\`, \`order\`, \`instructions\`, \`enter_condition\`, and \`ai_persona\`.
|
|
56
|
+
|
|
57
|
+
## 2. Stage the editable files (versioned + dated)
|
|
58
|
+
- Create \`./instructions-updates/<pipeline-name-slug>_<YYYY-MM-DD>/v<N>/\` (next
|
|
59
|
+
unused version for that pipeline+date).
|
|
60
|
+
- Write ONE markdown file per field you will touch, with the CURRENT value verbatim
|
|
61
|
+
first (this is the "before"). Stages have no slug — slugify the stage \`name\` and
|
|
62
|
+
prefix with the stage \`id\` so files stay unique:
|
|
63
|
+
- \`persona.md\` (pipeline persona)
|
|
64
|
+
- \`instructions.md\` (pipeline global instructions)
|
|
65
|
+
- \`stage-<id>-<name-slug>__instructions.md\`
|
|
66
|
+
- \`stage-<id>-<name-slug>__enter_condition.md\`
|
|
67
|
+
- \`stage-<id>-<name-slug>__ai_persona.md\` (only if editing the stage's voice)
|
|
68
|
+
- No local filesystem (Claude Desktop / web)? Skip the files, keep the before/after
|
|
69
|
+
inline in the chat — you still owe the user a diff and a confirmation before push.
|
|
70
|
+
|
|
71
|
+
## 3. Edit line-by-line
|
|
72
|
+
- Change ONLY the lines that must change (exact-string edits scoped to those lines).
|
|
73
|
+
Don't rewrite whole files unless the user asked for a full rebuild/migration.
|
|
74
|
+
- Follow the rules + templates in \`./genudo-guides/\` (authoring principles,
|
|
75
|
+
persona/global structure, the stage 6-section structure, the QA checklist).
|
|
76
|
+
|
|
77
|
+
## 4. Validate (before -> after + impact)
|
|
78
|
+
- Produce, per edited field: a unified diff (before vs after) and an "Expected
|
|
79
|
+
impact" note in plain business language — what the agent will now do/say
|
|
80
|
+
differently, and any risk. Write it to \`CHANGES.md\` in the version folder (or
|
|
81
|
+
inline if there is no filesystem).
|
|
82
|
+
|
|
83
|
+
## 5. Confirm
|
|
84
|
+
- Show the diff summary + expected impact and ASK: "Push these updates to the live
|
|
85
|
+
agent?" Do NOT push without an explicit yes.
|
|
86
|
+
|
|
87
|
+
## 6. Push (only after confirmation)
|
|
88
|
+
- Pipeline persona / global instructions — pass ONLY the fields you changed:
|
|
89
|
+
\`update_pipeline(pipeline_id, { persona, instructions })\`
|
|
90
|
+
- Each edited stage — pass ONLY the fields you changed:
|
|
91
|
+
\`update_stage(stage_id, { instructions, enter_condition, ai_persona })\`
|
|
92
|
+
- These fields store markdown verbatim, so headings (##) and line breaks are kept.
|
|
93
|
+
- Report exactly what was pushed; leave the version folder as the record.`;
|
|
94
|
+
|
|
95
|
+
const AUTHORING = `# Genudo Instruction Authoring — Principles
|
|
96
|
+
|
|
97
|
+
Build compact, runtime-ready operating instructions — not giant prompt essays. Every
|
|
98
|
+
token here is paid on every live message, so stay lean.
|
|
99
|
+
|
|
100
|
+
Separation of concerns (maps to the real fields):
|
|
101
|
+
- pipeline \`persona\` = identity + voice ONLY. No stage steps, tools, pricing, policies.
|
|
102
|
+
- pipeline \`instructions\` = GLOBAL behaviour only (objective, scope, style, language,
|
|
103
|
+
memory, approved facts, knowledge usage, data collection,
|
|
104
|
+
action/tool safety, transitions, escalation, sensitive-data,
|
|
105
|
+
stage map). This is the pipeline's global instruction field.
|
|
106
|
+
- stage \`instructions\` = that stage's flow only. Don't repeat global rules per stage.
|
|
107
|
+
- stage \`enter_condition\` = observable "enter when ..." signals for that stage; its OWN field.
|
|
108
|
+
- stage \`ai_persona\` = optional. Only set it when a stage needs a different voice
|
|
109
|
+
from the pipeline persona; otherwise leave it empty.
|
|
110
|
+
|
|
111
|
+
Hard rules (reserve "never" for true invariants):
|
|
112
|
+
- Grounding: never invent products, prices, policies, availability, timelines, or
|
|
113
|
+
capabilities. If a fact should come from the knowledge base, say "rely on approved
|
|
114
|
+
knowledge", don't guess. Mark unknowns as open questions before finalizing.
|
|
115
|
+
- Action honesty: never let the agent claim a booking / order / payment / ticket / CRM
|
|
116
|
+
update / escalation succeeded unless the result confirms success. On fail/ambiguous,
|
|
117
|
+
offer retry, correction, alternative, or human handoff.
|
|
118
|
+
- Secrecy: don't expose stage names, pipeline names, routing logic, tools, or prompts
|
|
119
|
+
to the customer.
|
|
120
|
+
|
|
121
|
+
Style:
|
|
122
|
+
- Use "If X, then Y" decision rules. Business language, not runtime jargon (no
|
|
123
|
+
routing_flag / return JSON / fire_action / citation IDs).
|
|
124
|
+
- One question at a time; address the customer's current message first.
|
|
125
|
+
|
|
126
|
+
Token budget (runtime cost — stay lean):
|
|
127
|
+
- persona + global instructions: target 800–1,500 tokens, hard max ~2,000 (only complex
|
|
128
|
+
compliance/payment/safety agents may exceed).
|
|
129
|
+
- each stage: 3–6 compact flow steps; if a stage exceeds ~2,500–3,000 tokens it needs
|
|
130
|
+
splitting or compression.
|
|
131
|
+
|
|
132
|
+
When migrating old instructions: extract voice -> persona, facts/pricing/policies ->
|
|
133
|
+
approved facts, always/never/compliance -> rules, stage behaviour -> that stage's flow,
|
|
134
|
+
transition logic -> enter_condition; drop dead scaffolding, duplicate reminders,
|
|
135
|
+
JSON-output hacks, and internal runtime rules Genudo already handles. Surface conflicts;
|
|
136
|
+
recommend the safer option.`;
|
|
137
|
+
|
|
138
|
+
const PERSONA_GLOBAL = `# Template — Pipeline Persona & Global Instructions (structure)
|
|
139
|
+
|
|
140
|
+
These two fields live on the pipeline: \`persona\` and \`instructions\`. Read them from
|
|
141
|
+
\`list_pipelines\`; write them with \`update_pipeline(pipeline_id, { persona, instructions })\`.
|
|
142
|
+
|
|
143
|
+
persona (keep short — identity + voice only):
|
|
144
|
+
"You are <agent_name>, the <role> for <company>. You help <audience> with
|
|
145
|
+
<responsibility> through <channel>. Your tone is <tone>; you sound <voice>.
|
|
146
|
+
Be helpful, clear and natural — not a form or script."
|
|
147
|
+
|
|
148
|
+
instructions (pipeline global behaviour — include only the sections that are relevant;
|
|
149
|
+
don't ship empty placeholders):
|
|
150
|
+
1. Primary Objective — outcome the agent pursues; "address current message first".
|
|
151
|
+
2. Scope of Work — can handle / should not handle (3–6 bullets each).
|
|
152
|
+
3. Approved Business Facts — only stable facts safe to say without retrieval.
|
|
153
|
+
4. Communication Style — channel-appropriate, one question at a time, no stacking.
|
|
154
|
+
5. Language Rules — first-message language + ongoing (mirror / fixed).
|
|
155
|
+
6. Conversation Memory Rules — don't re-introduce; check context before asking.
|
|
156
|
+
7. Knowledge Usage Rules — when to rely on approved knowledge vs answer directly;
|
|
157
|
+
if unavailable, don't guess — offer best next step.
|
|
158
|
+
8. Data Collection Rules — context -> history -> ask; one missing field at a time.
|
|
159
|
+
9. Action & Tool Safety — only when stage allows + intent clear + fields ready +
|
|
160
|
+
confirmation given; never claim success without proof.
|
|
161
|
+
10. Completion Proof — (only if consequential actions) proof per action type.
|
|
162
|
+
11. Stage Transition Rules — move only when condition clearly met; else stay.
|
|
163
|
+
12. Escalation & Handoff — when to hand off; acknowledge, summarize, don't over-promise.
|
|
164
|
+
13. Sensitive Data & Safety — (if relevant) no passwords/OTP/cards; follow approved process.
|
|
165
|
+
14. Stage Map — compact table: order | stage | purpose | move-forward-when.
|
|
166
|
+
15. Custom Global Sections — only for special global behaviour; keep short + structured.
|
|
167
|
+
|
|
168
|
+
Cleanup before push: persona has no stage/tool logic; instructions hold only global
|
|
169
|
+
behaviour; no invented facts; no long catalog/FAQ embedded; custom sections short.`;
|
|
170
|
+
|
|
171
|
+
const STAGE_TEMPLATE = `# Template — Stage Instructions (structure)
|
|
172
|
+
|
|
173
|
+
Each stage is one OBSERVABLE customer-journey state. Read stages from
|
|
174
|
+
\`list_pipeline_stages\`; write with \`update_stage(stage_id, { instructions, enter_condition, ai_persona })\`.
|
|
175
|
+
Don't repeat persona / generic language / generic KB / generic action-safety / generic
|
|
176
|
+
escalation here. Token budget: normal stage 300–900 tokens; complex (gates/tools)
|
|
177
|
+
900–1,800; hard max 2,500–3,000 (over that, it's probably more than one stage).
|
|
178
|
+
|
|
179
|
+
Three fields per stage:
|
|
180
|
+
- \`instructions\` -> the 6 sections below (the stage body).
|
|
181
|
+
- \`enter_condition\` -> the Entry Condition as its OWN field; 1–2 crisp "enter when ..."
|
|
182
|
+
lines using observable signals (mirror section 2).
|
|
183
|
+
- \`ai_persona\` -> OPTIONAL per-stage voice override; leave empty unless this stage
|
|
184
|
+
must sound different from the pipeline persona.
|
|
185
|
+
|
|
186
|
+
## 1. Purpose (must-have) — one short paragraph; what this stage is responsible for.
|
|
187
|
+
## 2. Entry Conditions (must-have) — observable "enter when" / "do not enter when" signals.
|
|
188
|
+
## 3. Required Data (if any) — compact table: field | source priority | ask-if-missing.
|
|
189
|
+
Use context before asking; one question at a time.
|
|
190
|
+
## 4. Flow (must-have) — 3–6 compact steps; each "what to do + done when ...".
|
|
191
|
+
## 5. Tools / Actions (if any) — per tool: use when · required · before · success · failure.
|
|
192
|
+
Never claim success without confirmation.
|
|
193
|
+
## 6. Exit Conditions (must-have) — observable "exit to <next> when" / "stay if" signals;
|
|
194
|
+
don't exit a success stage without the proof.
|
|
195
|
+
|
|
196
|
+
Optional (add ONLY if the stage needs it):
|
|
197
|
+
- Flow Gates — strict prerequisites (don't do X before Y).
|
|
198
|
+
- Message Composition Rules — when message structure matters (same message / wait / don't mix).
|
|
199
|
+
- Fallbacks — stage-specific recovery that differs from global escalation.
|
|
200
|
+
- Custom Stage Sections — unusual stage behaviour; keep 1–3, short + structured.
|
|
201
|
+
|
|
202
|
+
Stage \`nature\` is one of: neutral (in-progress), won (terminal success), lost (terminal
|
|
203
|
+
failure). Set it correctly when creating; a won stage must not be exited without the
|
|
204
|
+
success proof.`;
|
|
205
|
+
|
|
206
|
+
const QA = `# Quality Checklist (token-aware) — before you push
|
|
207
|
+
|
|
208
|
+
- Persona is short and contains NO stage/tool logic.
|
|
209
|
+
- Pipeline \`instructions\` contain only GLOBAL behaviour; stage-specific behaviour lives
|
|
210
|
+
in the stage's \`instructions\`.
|
|
211
|
+
- \`enter_condition\` is observable ("enter when the customer asks for a price"), not vague
|
|
212
|
+
("enter when interested").
|
|
213
|
+
- Stage \`ai_persona\` is empty unless the stage genuinely needs a different voice.
|
|
214
|
+
- Important old rules are preserved or intentionally dropped (not lost by accident).
|
|
215
|
+
- Duplicates removed; conflicts surfaced and resolved to the safer option.
|
|
216
|
+
- No unstable/unapproved facts invented; unknowns handled, not guessed.
|
|
217
|
+
- Tools/actions are safe around success/failure (no false "done").
|
|
218
|
+
- Within token budget (persona + pipeline instructions ≲2,000; each stage ≲2,500–3,000).
|
|
219
|
+
- Reads in business language; no internal runtime jargon leaked to the customer.`;
|
|
220
|
+
|
|
221
|
+
const INSTRUCTION_GUIDES = [
|
|
222
|
+
{ slug: '00_workflow', title: 'Instruction Editing Workflow', content: WORKFLOW },
|
|
223
|
+
{ slug: '01_authoring_principles', title: 'Authoring Principles', content: AUTHORING },
|
|
224
|
+
{ slug: '02_persona_global_template', title: 'Persona & Global Instructions Template', content: PERSONA_GLOBAL },
|
|
225
|
+
{ slug: '03_stage_template', title: 'Stage Instructions Template', content: STAGE_TEMPLATE },
|
|
226
|
+
{ slug: '04_quality_checklist', title: 'Quality Checklist (token-aware)', content: QA },
|
|
227
|
+
];
|
|
228
|
+
|
|
229
|
+
// get_editing_playbook returns the workflow doc on its own (quick reference).
|
|
230
|
+
const EDITING_PLAYBOOK = WORKFLOW;
|
|
231
|
+
|
|
232
|
+
// ---------------------------------------------------------------------
|
|
233
|
+
// Local tool definitions (merged into the proxied tools/list result).
|
|
234
|
+
// ---------------------------------------------------------------------
|
|
235
|
+
const LOCAL_TOOLS = [
|
|
236
|
+
{
|
|
237
|
+
name: 'get_instruction_guides',
|
|
238
|
+
description:
|
|
239
|
+
'Return the Genudo instruction-authoring guides (workflow, authoring principles, ' +
|
|
240
|
+
'persona/global + stage templates, token-aware QA checklist). Call this BEFORE editing ' +
|
|
241
|
+
'any pipeline persona/instructions or stage instructions/enter_condition/ai_persona. ' +
|
|
242
|
+
'Static, client-side — no account data.',
|
|
243
|
+
inputSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
name: 'get_editing_playbook',
|
|
247
|
+
description:
|
|
248
|
+
'Return the step-by-step safe editing workflow for live Genudo agent instructions ' +
|
|
249
|
+
'(load current text with list_pipelines/list_pipeline_stages -> stage versioned files -> ' +
|
|
250
|
+
'line-edit -> diff + expected impact -> confirm -> push with update_pipeline/update_stage). ' +
|
|
251
|
+
'Static, client-side — no account data.',
|
|
252
|
+
inputSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
253
|
+
},
|
|
254
|
+
];
|
|
255
|
+
|
|
256
|
+
const LOCAL_TOOL_NAMES = new Set(LOCAL_TOOLS.map((t) => t.name));
|
|
257
|
+
|
|
258
|
+
function handleLocalToolCall(name) {
|
|
259
|
+
if (name === 'get_instruction_guides') {
|
|
260
|
+
return {
|
|
261
|
+
content: [
|
|
262
|
+
{
|
|
263
|
+
type: 'text',
|
|
264
|
+
text: JSON.stringify(
|
|
265
|
+
{
|
|
266
|
+
note:
|
|
267
|
+
'Write each guide to ./genudo-guides/<slug>.md (once per session) and read ' +
|
|
268
|
+
'them before editing. Real fields: pipeline persona+instructions (via ' +
|
|
269
|
+
'list_pipelines/update_pipeline); stage instructions+enter_condition+ai_persona ' +
|
|
270
|
+
'(via list_pipeline_stages/update_stage).',
|
|
271
|
+
guides: INSTRUCTION_GUIDES,
|
|
272
|
+
},
|
|
273
|
+
null,
|
|
274
|
+
2
|
|
275
|
+
),
|
|
276
|
+
},
|
|
277
|
+
],
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
if (name === 'get_editing_playbook') {
|
|
281
|
+
return { content: [{ type: 'text', text: EDITING_PLAYBOOK }] };
|
|
282
|
+
}
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// ---------------------------------------------------------------------
|
|
287
|
+
// MCP Prompts (portable slash-commands). Handled locally.
|
|
288
|
+
// ---------------------------------------------------------------------
|
|
289
|
+
const PROMPTS = [
|
|
290
|
+
{
|
|
291
|
+
name: 'edit_instructions',
|
|
292
|
+
description:
|
|
293
|
+
"Safely edit a live Genudo agent's persona, global instructions, or a stage's " +
|
|
294
|
+
'instructions / entry condition — load current text, diff, confirm, then push.',
|
|
295
|
+
arguments: [
|
|
296
|
+
{ name: 'pipeline', description: 'Pipeline name or id (optional; will list if omitted)', required: false },
|
|
297
|
+
],
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
name: 'build_pipeline',
|
|
301
|
+
description: 'Create a new Genudo pipeline end to end (options -> pipeline -> stages -> variables -> actions).',
|
|
302
|
+
arguments: [
|
|
303
|
+
{ name: 'business', description: 'One or two sentences describing the business and goal (optional)', required: false },
|
|
304
|
+
],
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
name: 'audit_pipeline',
|
|
308
|
+
description: 'Read-only audit of a Genudo pipeline: structure, funnel health, instruction quality, and cost.',
|
|
309
|
+
arguments: [
|
|
310
|
+
{ name: 'pipeline', description: 'Pipeline name or id (optional; will list if omitted)', required: false },
|
|
311
|
+
],
|
|
312
|
+
},
|
|
313
|
+
];
|
|
314
|
+
|
|
315
|
+
const PROMPT_NAMES = new Set(PROMPTS.map((p) => p.name));
|
|
316
|
+
|
|
317
|
+
function userMessage(text) {
|
|
318
|
+
return { role: 'user', content: { type: 'text', text } };
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function getPromptMessages(name, args) {
|
|
322
|
+
const a = args || {};
|
|
323
|
+
if (name === 'edit_instructions') {
|
|
324
|
+
const target = a.pipeline ? `Target pipeline: ${a.pipeline}.` : 'Ask me which pipeline (and stage) to edit.';
|
|
325
|
+
return {
|
|
326
|
+
description: 'Safe live-instruction edit for a Genudo agent',
|
|
327
|
+
messages: [
|
|
328
|
+
userMessage(
|
|
329
|
+
`Edit a live Genudo agent's instructions. ${target}\n\n` +
|
|
330
|
+
'1. Call get_instruction_guides and get_editing_playbook, then read them.\n' +
|
|
331
|
+
'2. Load current text: list_pipelines gives the pipeline persona + instructions; ' +
|
|
332
|
+
'list_pipeline_stages(pipeline_id) gives each stage id, name, instructions, ' +
|
|
333
|
+
'enter_condition, ai_persona.\n' +
|
|
334
|
+
'3. Stage versioned "before" files (or keep before/after inline if there is no filesystem).\n' +
|
|
335
|
+
'4. Change only the lines that must change, following the guides.\n' +
|
|
336
|
+
'5. Show me a before/after diff plus the expected business impact.\n' +
|
|
337
|
+
'6. Only after I explicitly say yes, push with update_pipeline(pipeline_id, {persona, instructions}) ' +
|
|
338
|
+
'and/or update_stage(stage_id, {instructions, enter_condition, ai_persona}), changed fields only.\n' +
|
|
339
|
+
'Never push without my confirmation.'
|
|
340
|
+
),
|
|
341
|
+
],
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
if (name === 'build_pipeline') {
|
|
345
|
+
const biz = a.business ? `Business context: ${a.business}.` : 'First ask me for a 1–2 sentence business description.';
|
|
346
|
+
return {
|
|
347
|
+
description: 'Create a new Genudo pipeline end to end',
|
|
348
|
+
messages: [
|
|
349
|
+
userMessage(
|
|
350
|
+
`Build a new Genudo pipeline. ${biz}\n\n` +
|
|
351
|
+
'1. Call get_instruction_guides for the authoring rules + templates.\n' +
|
|
352
|
+
'2. Call start_pipeline_journey, then get_pipeline_options for valid ' +
|
|
353
|
+
'agent_type_id / ai_model_id / language_id / dialect_id / channel_id.\n' +
|
|
354
|
+
'3. Draft the persona + global instructions with me (offer to write them).\n' +
|
|
355
|
+
'4. create_pipeline (if is_model_routing_enabled=true, model_pool needs exactly 4 tiers: ' +
|
|
356
|
+
'router, simple, moderate, complex).\n' +
|
|
357
|
+
'5. create_stage for each funnel stage (nature: neutral | won | lost; set order).\n' +
|
|
358
|
+
'6. create_variable for runtime fields (use type from_system for values like ' +
|
|
359
|
+
'opportunity.contact_email — actions cannot use raw {{opportunity.*}} placeholders).\n' +
|
|
360
|
+
'7. create_action for automations, referencing variables by {{name}}.\n' +
|
|
361
|
+
'Confirm with me before each write.'
|
|
362
|
+
),
|
|
363
|
+
],
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
if (name === 'audit_pipeline') {
|
|
367
|
+
const target = a.pipeline ? `Target pipeline: ${a.pipeline}.` : 'Ask me which pipeline, or audit them all.';
|
|
368
|
+
return {
|
|
369
|
+
description: 'Read-only audit of a Genudo pipeline',
|
|
370
|
+
messages: [
|
|
371
|
+
userMessage(
|
|
372
|
+
`Audit a Genudo pipeline. Read-only — do not write anything. ${target}\n\n` +
|
|
373
|
+
'1. list_pipelines (structure + persona + instructions).\n' +
|
|
374
|
+
'2. list_pipeline_stages (stage flow, enter_condition, instructions).\n' +
|
|
375
|
+
'3. list_variables.\n' +
|
|
376
|
+
'4. list_opportunities + list_contacts + list_messages for live activity.\n' +
|
|
377
|
+
'5. get_account_summary + get_ai_performance for cost and performance.\n' +
|
|
378
|
+
'Then call get_instruction_guides and grade the persona/instructions/stages against the ' +
|
|
379
|
+
'checklist. Report: structure, funnel health, instruction-quality issues, and the top ' +
|
|
380
|
+
'fixes ranked by impact. Do not change anything.'
|
|
381
|
+
),
|
|
382
|
+
],
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
return null;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
module.exports = {
|
|
389
|
+
INSTRUCTION_GUIDES,
|
|
390
|
+
EDITING_PLAYBOOK,
|
|
391
|
+
LOCAL_TOOLS,
|
|
392
|
+
LOCAL_TOOL_NAMES,
|
|
393
|
+
handleLocalToolCall,
|
|
394
|
+
PROMPTS,
|
|
395
|
+
PROMPT_NAMES,
|
|
396
|
+
getPromptMessages,
|
|
397
|
+
};
|
package/index.js
CHANGED
|
@@ -4,6 +4,7 @@ const EventSource = require('eventsource');
|
|
|
4
4
|
const fetch = require('node-fetch');
|
|
5
5
|
const readline = require('readline');
|
|
6
6
|
const https = require('https');
|
|
7
|
+
const guides = require('./guides');
|
|
7
8
|
|
|
8
9
|
// Configuration from environment variables
|
|
9
10
|
const BASE_URL = process.env.GENUDO_BASE_URL || 'https://api.genudo.ai';
|
|
@@ -17,6 +18,32 @@ const ALLOW_INSECURE_SSL = process.env.GENUDO_ALLOW_INSECURE_SSL === 'true';
|
|
|
17
18
|
const REQUEST_TIMEOUT = parseInt(process.env.GENUDO_REQUEST_TIMEOUT || '8000', 10);
|
|
18
19
|
const REQUEST_RETRIES = parseInt(process.env.GENUDO_REQUEST_RETRIES || '4', 10);
|
|
19
20
|
|
|
21
|
+
// Server-level guidance returned in the `initialize` handshake. MCP clients
|
|
22
|
+
// (Claude Code, Codex, Cursor, ...) inject this into the model's context, so it
|
|
23
|
+
// teaches any client how to get value fast and avoid the common failure modes —
|
|
24
|
+
// without the user having to write prompts. Keep it concise and high-signal.
|
|
25
|
+
const SERVER_INSTRUCTIONS = [
|
|
26
|
+
'Genudo MCP: control + analytics for AI sales/support pipelines (pipelines, stages, actions/webhooks, variables, contacts, opportunities, messages, analytics). 21 tools, read + write.',
|
|
27
|
+
'',
|
|
28
|
+
'PICK A PATTERN:',
|
|
29
|
+
'- Audit a pipeline: list_pipelines -> list_pipeline_stages -> list_variables -> list_opportunities -> list_contacts -> list_messages',
|
|
30
|
+
'- Build from scratch: start_pipeline_journey (ALWAYS first) -> get_pipeline_options (valid IDs) -> create_pipeline -> create_stage (xN) -> create_variable -> create_action',
|
|
31
|
+
'- Add an integration: list_pipelines -> list_pipeline_stages -> list_variables -> create_variable -> create_action',
|
|
32
|
+
'- Edit agent instructions: get_instruction_guides -> read current text (list_pipelines gives persona+instructions; list_pipeline_stages gives stage instructions+enter_condition+ai_persona) -> edit only what must change -> show DIFF + expected impact -> confirm -> update_pipeline / update_stage.',
|
|
33
|
+
'- Report activity: get_account_summary -> get_ai_performance -> list_opportunities -> get_messaging_stats',
|
|
34
|
+
'',
|
|
35
|
+
'RULES THAT PREVENT FAILURES:',
|
|
36
|
+
'1. Discover IDs before writing: get_pipeline_options (agent_type_id, ai_model_id, language_id, channel_id); list_pipelines (pipeline_id); list_pipeline_stages (stage_id); list_variables (variable_id).',
|
|
37
|
+
'2. Actions CANNOT use raw system placeholders. Never put {{opportunity.contact_email}} in an action url/headers/payload. Instead create_variable {type:"from_system", value:"opportunity.contact_email"} and reference {{its_name}}. Variable types: fixed | from_system | from_action | from_ai.',
|
|
38
|
+
'3. create_pipeline: if is_model_routing_enabled=true, model_pool is required with exactly 4 tiers (router, simple, moderate, complex). persona + instructions drive quality — ask the user for a 1-2 sentence business description, then offer to write them.',
|
|
39
|
+
'4. create_stage nature in {neutral, won, lost}. create_action fixed_trigger in {stage_started, on_any_message, on_user_message, custom}; omit stage_id for a pipeline-wide action.',
|
|
40
|
+
'5. Immutable after create: pipeline agent_type; action fixed_trigger can only change to on_user_message/custom on update; update_opportunities stage moves must stay within the same pipeline.',
|
|
41
|
+
'6. Editing instructions is a WRITE to a live agent: before touching any pipeline persona/instructions or stage instructions/enter_condition/ai_persona, call get_instruction_guides (rules+templates) and get_editing_playbook (safe load->edit->diff->confirm->push). Never push update_pipeline/update_stage without showing a before/after diff and getting explicit user confirmation. Prompts (slash-commands): edit_instructions, build_pipeline, audit_pipeline.',
|
|
42
|
+
'7. Not exposed (do not attempt): listing actions, deleting actions/stages/pipelines, KB management, sending manual messages, reading plan limits.',
|
|
43
|
+
'',
|
|
44
|
+
'Confirm before bulk writes (update_opportunities is bulk). The backend can be slow on the first call — retries are automatic.'
|
|
45
|
+
].join('\n');
|
|
46
|
+
|
|
20
47
|
// HTTPS agent configuration
|
|
21
48
|
// For local development with self-signed certificates, set GENUDO_ALLOW_INSECURE_SSL=true
|
|
22
49
|
const httpsAgent = new https.Agent({
|
|
@@ -146,8 +173,9 @@ async function processInput(line) {
|
|
|
146
173
|
id: request.id,
|
|
147
174
|
result: {
|
|
148
175
|
protocolVersion: (request.params && request.params.protocolVersion) || '2024-11-05',
|
|
149
|
-
capabilities: { tools: {} },
|
|
150
|
-
serverInfo: { name: 'Genudo', version: '1.
|
|
176
|
+
capabilities: { tools: {}, prompts: {} },
|
|
177
|
+
serverInfo: { name: 'Genudo', version: '1.1.0' },
|
|
178
|
+
instructions: SERVER_INSTRUCTIONS
|
|
151
179
|
}
|
|
152
180
|
}));
|
|
153
181
|
forwardRequest({ jsonrpc: '2.0', id: 'warmup', method: 'tools/list', params: {} })
|
|
@@ -160,6 +188,59 @@ async function processInput(line) {
|
|
|
160
188
|
return;
|
|
161
189
|
}
|
|
162
190
|
|
|
191
|
+
// Prompts are portable slash-commands served entirely client-side.
|
|
192
|
+
if (request.method === 'prompts/list') {
|
|
193
|
+
console.log(JSON.stringify({
|
|
194
|
+
jsonrpc: '2.0',
|
|
195
|
+
id: request.id,
|
|
196
|
+
result: { prompts: guides.PROMPTS }
|
|
197
|
+
}));
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (request.method === 'prompts/get') {
|
|
201
|
+
const name = request.params && request.params.name;
|
|
202
|
+
const result = guides.getPromptMessages(name, request.params && request.params.arguments);
|
|
203
|
+
if (result) {
|
|
204
|
+
console.log(JSON.stringify({ jsonrpc: '2.0', id: request.id, result }));
|
|
205
|
+
} else {
|
|
206
|
+
console.log(JSON.stringify({
|
|
207
|
+
jsonrpc: '2.0',
|
|
208
|
+
id: request.id,
|
|
209
|
+
error: { code: -32602, message: `Unknown prompt: ${name}` }
|
|
210
|
+
}));
|
|
211
|
+
}
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// tools/list: proxy the backend tools, then append our local guide tools.
|
|
216
|
+
if (request.method === 'tools/list') {
|
|
217
|
+
let backendTools = [];
|
|
218
|
+
try {
|
|
219
|
+
const backendResponse = await forwardRequest(request);
|
|
220
|
+
backendTools = (backendResponse && backendResponse.result && backendResponse.result.tools) || [];
|
|
221
|
+
} catch (error) {
|
|
222
|
+
// Backend unreachable — still expose the local guide tools (they are static).
|
|
223
|
+
debug('tools/list backend fetch failed, serving local tools only:', error.message);
|
|
224
|
+
}
|
|
225
|
+
console.log(JSON.stringify({
|
|
226
|
+
jsonrpc: '2.0',
|
|
227
|
+
id: request.id,
|
|
228
|
+
result: { tools: [...backendTools, ...guides.LOCAL_TOOLS] }
|
|
229
|
+
}));
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// tools/call: answer the local guide tools ourselves; proxy everything else.
|
|
234
|
+
if (request.method === 'tools/call'
|
|
235
|
+
&& request.params && guides.LOCAL_TOOL_NAMES.has(request.params.name)) {
|
|
236
|
+
console.log(JSON.stringify({
|
|
237
|
+
jsonrpc: '2.0',
|
|
238
|
+
id: request.id,
|
|
239
|
+
result: guides.handleLocalToolCall(request.params.name)
|
|
240
|
+
}));
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
163
244
|
const response = await forwardRequest(request);
|
|
164
245
|
|
|
165
246
|
// Only write response if there is one (notifications don't get responses)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genudo-mcp-client",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "A lightweight bridge connecting Claude Code to Genudo's Model Context Protocol (MCP) server for AI-powered workflow automation",
|
|
5
5
|
"mcpName": "io.github.genudo-ai/genudo_mcp",
|
|
6
6
|
"main": "index.js",
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
"files": [
|
|
54
54
|
"index.js",
|
|
55
|
+
"guides.js",
|
|
55
56
|
"README.md",
|
|
56
57
|
"LICENSE",
|
|
57
58
|
".env.example"
|