@miraigent/free-ai-ops-mcp 0.1.1
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/CHANGELOG.md +29 -0
- package/CONTRIBUTING.md +20 -0
- package/LAUNCH_FLOW.md +344 -0
- package/LICENSE +21 -0
- package/README.md +109 -0
- package/SECURITY.md +9 -0
- package/examples/human-review-gate/README.md +34 -0
- package/examples/human-review-gate/run-example.mjs +28 -0
- package/examples/human-review-gate/sample-decision-log.csv +2 -0
- package/examples/human-review-gate/sample-request.jsonl +1 -0
- package/mcp/free-ai-ops-server.mjs +216 -0
- package/package.json +44 -0
- package/scripts/secret-scan.mjs +38 -0
- package/scripts/smoke-test.mjs +102 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.1.1] - 2026-06-07
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Added FREE-004 Human Review Gate examples with JSON-RPC input, expected output,
|
|
8
|
+
and a sample decision log.
|
|
9
|
+
- Added an example npm script for the human_review_gate workflow.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- human_review_gate now returns a decision note and nextLogRow so users can copy
|
|
14
|
+
the result into the free Gumroad review-gate flow CSV.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Kept the MCP initialize server version aligned with the npm package version
|
|
19
|
+
and added smoke test coverage for that release metadata.
|
|
20
|
+
|
|
21
|
+
## [0.1.0] - 2026-06-06
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Added the first public alpha MCP server.
|
|
26
|
+
- Added human_review_gate, faq_candidate_review, and ai_safe_crm_note.
|
|
27
|
+
- Added prompt_risk_review for pre-AI prompt and task risk review.
|
|
28
|
+
- Added smoke tests, secret scan, GitHub Actions, and issue templates.
|
|
29
|
+
- Added LAUNCH_FLOW.md for free distribution, issue collection, and Miraigent / Agent Memories routing.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Public contributions should improve free MCP tools for reviewable AI operations.
|
|
4
|
+
|
|
5
|
+
Before opening a pull request:
|
|
6
|
+
|
|
7
|
+
- run npm run check
|
|
8
|
+
- run npm test
|
|
9
|
+
- avoid private customer data
|
|
10
|
+
- avoid credentials, tokens, cookies, or private keys
|
|
11
|
+
- avoid MIRAI Memory engine details
|
|
12
|
+
- avoid working memory MCP behavior
|
|
13
|
+
|
|
14
|
+
Good contributions include:
|
|
15
|
+
|
|
16
|
+
- clearer output fields
|
|
17
|
+
- safer review checklists
|
|
18
|
+
- better examples
|
|
19
|
+
- smoke-test coverage
|
|
20
|
+
- issue template improvements
|
package/LAUNCH_FLOW.md
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
# Launch Flow
|
|
2
|
+
|
|
3
|
+
This document defines the first public launch flow for Miraigent Free AI Ops MCP.
|
|
4
|
+
|
|
5
|
+
The goal is to distribute useful free MCP tools, collect public GitHub issues,
|
|
6
|
+
and guide interested users toward Miraigent and Agent Memories.
|
|
7
|
+
|
|
8
|
+
## Launch Position
|
|
9
|
+
|
|
10
|
+
Use this framing:
|
|
11
|
+
|
|
12
|
+
Free MCP tools for teams that want to use AI in customer operations without
|
|
13
|
+
losing human review.
|
|
14
|
+
|
|
15
|
+
Do not frame this as full automation.
|
|
16
|
+
|
|
17
|
+
The public promise is:
|
|
18
|
+
|
|
19
|
+
- start with review gates
|
|
20
|
+
- organize FAQ candidates
|
|
21
|
+
- keep CRM notes safer
|
|
22
|
+
- collect feedback in GitHub issues
|
|
23
|
+
- connect deeper implementation needs to Miraigent
|
|
24
|
+
- connect reusable operating lessons to Agent Memories
|
|
25
|
+
|
|
26
|
+
## First Three MCPs
|
|
27
|
+
|
|
28
|
+
### 1. Human Review Gate MCP
|
|
29
|
+
|
|
30
|
+
Primary hook:
|
|
31
|
+
|
|
32
|
+
Before an AI draft is sent to a customer, decide whether it can proceed, needs
|
|
33
|
+
human review, or should stop.
|
|
34
|
+
|
|
35
|
+
Why first:
|
|
36
|
+
|
|
37
|
+
- Easy to understand.
|
|
38
|
+
- Strong safety message.
|
|
39
|
+
- Connects directly to AI governance and support operations.
|
|
40
|
+
- Likely to generate issue feedback about missing risk flags and review fields.
|
|
41
|
+
|
|
42
|
+
Route:
|
|
43
|
+
|
|
44
|
+
GitHub free tool -> Issue feedback -> Miraigent free diagnosis for company
|
|
45
|
+
workflow design -> Agent Memories for reusable review lessons.
|
|
46
|
+
|
|
47
|
+
### 2. FAQ Candidate Review MCP
|
|
48
|
+
|
|
49
|
+
Primary hook:
|
|
50
|
+
|
|
51
|
+
Turn repeated inquiries into FAQ candidates before building a chatbot or AI
|
|
52
|
+
reply system.
|
|
53
|
+
|
|
54
|
+
Why second:
|
|
55
|
+
|
|
56
|
+
- Strong fit for small business support.
|
|
57
|
+
- Leads naturally to Miraigent's FAQ and inquiry-flow diagnosis.
|
|
58
|
+
- Generates practical issues about status names, fields, and review flows.
|
|
59
|
+
|
|
60
|
+
Route:
|
|
61
|
+
|
|
62
|
+
GitHub free tool -> Qiita/Zenn example -> Miraigent resource hub -> free
|
|
63
|
+
diagnosis -> Agent Memories for FAQ decision memory.
|
|
64
|
+
|
|
65
|
+
### 3. AI-Safe CRM Notes MCP
|
|
66
|
+
|
|
67
|
+
Primary hook:
|
|
68
|
+
|
|
69
|
+
Separate customer facts, AI suggestions, human decisions, and next actions in
|
|
70
|
+
CRM notes.
|
|
71
|
+
|
|
72
|
+
Why third:
|
|
73
|
+
|
|
74
|
+
- Easy to connect to sales and support.
|
|
75
|
+
- Useful without private integrations.
|
|
76
|
+
- Creates a bridge from free MCP to paid business workflow design.
|
|
77
|
+
|
|
78
|
+
Route:
|
|
79
|
+
|
|
80
|
+
GitHub free tool -> note article -> Miraigent free diagnosis -> Agent Memories
|
|
81
|
+
for repeated customer-operation lessons.
|
|
82
|
+
|
|
83
|
+
### 4. Prompt Risk Review MCP
|
|
84
|
+
|
|
85
|
+
Primary hook:
|
|
86
|
+
|
|
87
|
+
Before sending an operational prompt to AI, check whether the task includes
|
|
88
|
+
customer-facing output or sensitive data.
|
|
89
|
+
|
|
90
|
+
Why fourth:
|
|
91
|
+
|
|
92
|
+
- It connects naturally to AI safety and public issue feedback.
|
|
93
|
+
- It is useful before users connect the MCP to real workflows.
|
|
94
|
+
- It supports the message that free MCP tools are review helpers, not full
|
|
95
|
+
automation.
|
|
96
|
+
|
|
97
|
+
Route:
|
|
98
|
+
|
|
99
|
+
GitHub free tool -> Issue feedback about missing risk flags -> Miraigent free
|
|
100
|
+
diagnosis for data-handling and review-rule design.
|
|
101
|
+
|
|
102
|
+
## Second Wave Candidates
|
|
103
|
+
|
|
104
|
+
Publish after the first three tools have public examples and issue feedback.
|
|
105
|
+
|
|
106
|
+
- Customer Data Masking Checklist MCP
|
|
107
|
+
- Diagnosis Intake Log MCP
|
|
108
|
+
- Decision Log MCP
|
|
109
|
+
- Support Workflow Starter Map MCP
|
|
110
|
+
|
|
111
|
+
## Funnel Design
|
|
112
|
+
|
|
113
|
+
### Step 1: Free Distribution
|
|
114
|
+
|
|
115
|
+
Channels:
|
|
116
|
+
|
|
117
|
+
- GitHub repository
|
|
118
|
+
- npm after authentication is ready
|
|
119
|
+
- Qiita implementation article
|
|
120
|
+
- Zenn technical article
|
|
121
|
+
- note business-facing article
|
|
122
|
+
- X thread with one clear use case
|
|
123
|
+
|
|
124
|
+
CTA:
|
|
125
|
+
|
|
126
|
+
- Try the free MCP.
|
|
127
|
+
- Open an issue if output fields or review rules are missing.
|
|
128
|
+
- Use only synthetic or public-safe examples in issues.
|
|
129
|
+
|
|
130
|
+
### Step 2: Issue Collection
|
|
131
|
+
|
|
132
|
+
Issue types to encourage:
|
|
133
|
+
|
|
134
|
+
- Missing risk flag.
|
|
135
|
+
- Confusing output.
|
|
136
|
+
- Better checklist field.
|
|
137
|
+
- New workflow candidate.
|
|
138
|
+
- Public-safe real-world use case.
|
|
139
|
+
|
|
140
|
+
Do not collect:
|
|
141
|
+
|
|
142
|
+
- private customer records
|
|
143
|
+
- credentials
|
|
144
|
+
- company internal manuals
|
|
145
|
+
- MIRAI Memory engine details
|
|
146
|
+
- working memory MCP requests
|
|
147
|
+
|
|
148
|
+
### Step 3: Miraigent Route
|
|
149
|
+
|
|
150
|
+
When a user needs company-specific workflow design, route them to Miraigent.
|
|
151
|
+
|
|
152
|
+
CTA language:
|
|
153
|
+
|
|
154
|
+
If your team needs to adapt this to real support, CRM, or FAQ workflows, start
|
|
155
|
+
with Miraigent's free diagnosis.
|
|
156
|
+
|
|
157
|
+
Primary URL:
|
|
158
|
+
|
|
159
|
+
https://miraigent.com/diagnosis
|
|
160
|
+
|
|
161
|
+
Secondary URL:
|
|
162
|
+
|
|
163
|
+
https://miraigent.com/resources
|
|
164
|
+
|
|
165
|
+
### Step 4: Agent Memories Route
|
|
166
|
+
|
|
167
|
+
When a user wants repeated review lessons, decisions, and operating notes to be
|
|
168
|
+
reused, route them to Agent Memories.
|
|
169
|
+
|
|
170
|
+
CTA language:
|
|
171
|
+
|
|
172
|
+
If the same review decisions repeat, turn them into reusable operating memory
|
|
173
|
+
with Agent Memories.
|
|
174
|
+
|
|
175
|
+
Primary URL:
|
|
176
|
+
|
|
177
|
+
https://agentmemories.jp/
|
|
178
|
+
|
|
179
|
+
## Posting Plan
|
|
180
|
+
|
|
181
|
+
### Post 1: GitHub Launch
|
|
182
|
+
|
|
183
|
+
Goal:
|
|
184
|
+
|
|
185
|
+
Announce the repository and ask for issues.
|
|
186
|
+
|
|
187
|
+
Hook:
|
|
188
|
+
|
|
189
|
+
We published free MCP alpha tools for human-reviewed AI operations.
|
|
190
|
+
|
|
191
|
+
CTA:
|
|
192
|
+
|
|
193
|
+
Try them, and open an issue if a review field is missing.
|
|
194
|
+
|
|
195
|
+
### Post 2: Human Review Gate
|
|
196
|
+
|
|
197
|
+
Goal:
|
|
198
|
+
|
|
199
|
+
Explain the most understandable tool first.
|
|
200
|
+
|
|
201
|
+
Hook:
|
|
202
|
+
|
|
203
|
+
Do not start with auto-send. Start with a review gate.
|
|
204
|
+
|
|
205
|
+
CTA:
|
|
206
|
+
|
|
207
|
+
Use Human Review Gate MCP and tell us what risk flags are missing.
|
|
208
|
+
|
|
209
|
+
### Post 3: FAQ Candidate Review
|
|
210
|
+
|
|
211
|
+
Goal:
|
|
212
|
+
|
|
213
|
+
Connect to inquiry and FAQ pain.
|
|
214
|
+
|
|
215
|
+
Hook:
|
|
216
|
+
|
|
217
|
+
Before building an AI chatbot, decide which questions should become FAQ.
|
|
218
|
+
|
|
219
|
+
CTA:
|
|
220
|
+
|
|
221
|
+
Use FAQ Candidate Review MCP and suggest missing statuses or fields.
|
|
222
|
+
|
|
223
|
+
### Post 4: AI-Safe CRM Notes
|
|
224
|
+
|
|
225
|
+
Goal:
|
|
226
|
+
|
|
227
|
+
Connect sales/support operations to Miraigent.
|
|
228
|
+
|
|
229
|
+
Hook:
|
|
230
|
+
|
|
231
|
+
CRM notes should not mix facts, AI suggestions, and human decisions.
|
|
232
|
+
|
|
233
|
+
CTA:
|
|
234
|
+
|
|
235
|
+
Use AI-Safe CRM Notes MCP, then book a Miraigent free diagnosis for real
|
|
236
|
+
workflow design.
|
|
237
|
+
|
|
238
|
+
### Post 5: Prompt Risk Review
|
|
239
|
+
|
|
240
|
+
Goal:
|
|
241
|
+
|
|
242
|
+
Connect free MCP usage to AI safety before automation.
|
|
243
|
+
|
|
244
|
+
Hook:
|
|
245
|
+
|
|
246
|
+
Before sending a prompt into AI, check whether it touches customer-facing output
|
|
247
|
+
or sensitive data.
|
|
248
|
+
|
|
249
|
+
CTA:
|
|
250
|
+
|
|
251
|
+
Use Prompt Risk Review MCP and open an issue if a risk flag is missing.
|
|
252
|
+
|
|
253
|
+
### Post 6: Agent Memories Bridge
|
|
254
|
+
|
|
255
|
+
Goal:
|
|
256
|
+
|
|
257
|
+
Connect repeated decisions to Agent Memories.
|
|
258
|
+
|
|
259
|
+
Hook:
|
|
260
|
+
|
|
261
|
+
If the same AI review decision repeats, it should become reusable operating
|
|
262
|
+
memory.
|
|
263
|
+
|
|
264
|
+
CTA:
|
|
265
|
+
|
|
266
|
+
Try the free MCP tools, then use Agent Memories for repeated operating lessons.
|
|
267
|
+
|
|
268
|
+
## Suggested First Public Thread
|
|
269
|
+
|
|
270
|
+
Post 1:
|
|
271
|
+
|
|
272
|
+
Free MCP alpha tools are now public.
|
|
273
|
+
|
|
274
|
+
They help teams review AI operations before customer-facing automation:
|
|
275
|
+
|
|
276
|
+
- Human Review Gate
|
|
277
|
+
- FAQ Candidate Review
|
|
278
|
+
- AI-Safe CRM Notes
|
|
279
|
+
- Prompt Risk Review
|
|
280
|
+
|
|
281
|
+
GitHub:
|
|
282
|
+
https://github.com/Miraigent/miraigent-free-ai-ops-mcp
|
|
283
|
+
|
|
284
|
+
Post 2:
|
|
285
|
+
|
|
286
|
+
The first goal is not full automation.
|
|
287
|
+
|
|
288
|
+
The first goal is to decide:
|
|
289
|
+
|
|
290
|
+
- what AI may draft
|
|
291
|
+
- what humans must review
|
|
292
|
+
- what should stop
|
|
293
|
+
- what should be logged
|
|
294
|
+
|
|
295
|
+
Post 3:
|
|
296
|
+
|
|
297
|
+
If an output feels unclear, open an issue.
|
|
298
|
+
|
|
299
|
+
Useful issues:
|
|
300
|
+
|
|
301
|
+
- missing risk flag
|
|
302
|
+
- missing CRM field
|
|
303
|
+
- unclear FAQ status
|
|
304
|
+
- better public-safe example
|
|
305
|
+
|
|
306
|
+
Please do not include private customer data.
|
|
307
|
+
|
|
308
|
+
Post 4:
|
|
309
|
+
|
|
310
|
+
Prompt Risk Review MCP checks whether an operational prompt touches:
|
|
311
|
+
|
|
312
|
+
- customer-facing output
|
|
313
|
+
- personal data
|
|
314
|
+
- contracts or payments
|
|
315
|
+
- complaints or risk areas
|
|
316
|
+
|
|
317
|
+
Post 5:
|
|
318
|
+
|
|
319
|
+
For company-specific support, CRM, or FAQ workflow design, use Miraigent's free
|
|
320
|
+
diagnosis:
|
|
321
|
+
|
|
322
|
+
https://miraigent.com/diagnosis
|
|
323
|
+
|
|
324
|
+
Post 6:
|
|
325
|
+
|
|
326
|
+
For repeated review lessons and operating decisions, connect the workflow to
|
|
327
|
+
Agent Memories:
|
|
328
|
+
|
|
329
|
+
https://agentmemories.jp/
|
|
330
|
+
|
|
331
|
+
## Success Signals
|
|
332
|
+
|
|
333
|
+
Early signals:
|
|
334
|
+
|
|
335
|
+
- GitHub stars
|
|
336
|
+
- issue reports
|
|
337
|
+
- npm downloads after publication
|
|
338
|
+
- article views
|
|
339
|
+
- resource hub clicks
|
|
340
|
+
- free diagnosis clicks
|
|
341
|
+
- Agent Memories clicks
|
|
342
|
+
|
|
343
|
+
Do not over-optimize for stars only. Practical issues from real users are more
|
|
344
|
+
valuable.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Miraigent
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the Software), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Miraigent Free AI Ops MCP
|
|
2
|
+
|
|
3
|
+
Free public MCP tools for practical AI operations.
|
|
4
|
+
|
|
5
|
+
This repository starts with small alpha tools that help teams review AI usage
|
|
6
|
+
before they automate customer-facing work.
|
|
7
|
+
|
|
8
|
+
## Alpha Tools
|
|
9
|
+
|
|
10
|
+
- human_review_gate: decide whether an AI draft should be sent, reviewed, or stopped.
|
|
11
|
+
- faq_candidate_review: turn repeated inquiry patterns into FAQ candidates.
|
|
12
|
+
- ai_safe_crm_note: structure CRM notes without mixing facts, AI suggestions, and human decisions.
|
|
13
|
+
- prompt_risk_review: review an AI prompt or task before it is used in operations.
|
|
14
|
+
|
|
15
|
+
These tools are public alpha candidates. Please use GitHub issues for bugs,
|
|
16
|
+
unclear outputs, missing fields, and safe public use cases.
|
|
17
|
+
|
|
18
|
+
## Start With One Review Gate
|
|
19
|
+
|
|
20
|
+
The first practical use case is a review gate for AI-drafted customer replies.
|
|
21
|
+
Before a team lets an AI draft leave a help desk, inbox, form workflow, or CRM,
|
|
22
|
+
the tool separates three outcomes:
|
|
23
|
+
|
|
24
|
+
- auto_ok: low-risk internal or routine copy can continue.
|
|
25
|
+
- review_required: a human should review the draft before it is sent.
|
|
26
|
+
- stop: sensitive, legal, payment, complaint, privacy, or public-facing risks
|
|
27
|
+
should be handled by a person before AI-assisted sending continues.
|
|
28
|
+
|
|
29
|
+
### Quick MCP Example
|
|
30
|
+
|
|
31
|
+
Example input:
|
|
32
|
+
|
|
33
|
+
{
|
|
34
|
+
"draftType": "customer support reply",
|
|
35
|
+
"audience": "customer",
|
|
36
|
+
"riskFlags": ["refund", "complaint", "personal data"],
|
|
37
|
+
"reviewOwner": "support lead",
|
|
38
|
+
"sendMode": "manual"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
Expected result:
|
|
42
|
+
|
|
43
|
+
{
|
|
44
|
+
"gateStatus": "stop",
|
|
45
|
+
"reviewOwner": "support lead",
|
|
46
|
+
"boundary": "This tool is a review helper. It does not send messages."
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
Use this as a small public proof before building a larger AI support workflow.
|
|
50
|
+
|
|
51
|
+
See examples/human-review-gate/ for copy-ready JSON-RPC examples and a sample
|
|
52
|
+
decision log that match the free Gumroad kit.
|
|
53
|
+
|
|
54
|
+
## Launch Flow
|
|
55
|
+
|
|
56
|
+
See LAUNCH_FLOW.md for the first public posting plan, issue collection flow, and
|
|
57
|
+
routes toward Miraigent and Agent Memories.
|
|
58
|
+
|
|
59
|
+
## Run
|
|
60
|
+
|
|
61
|
+
npm run mcp
|
|
62
|
+
|
|
63
|
+
Run checks:
|
|
64
|
+
|
|
65
|
+
npm run check
|
|
66
|
+
npm test
|
|
67
|
+
|
|
68
|
+
Direct JSON-RPC smoke call:
|
|
69
|
+
|
|
70
|
+
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"human_review_gate","arguments":{"draftType":"customer support reply","audience":"customer","riskFlags":["refund","complaint","personal data"],"reviewOwner":"support lead","sendMode":"manual"}}}' | npm run mcp
|
|
71
|
+
|
|
72
|
+
Run the public FREE-004 example:
|
|
73
|
+
|
|
74
|
+
npm run example:human-review-gate
|
|
75
|
+
|
|
76
|
+
## npm Plan
|
|
77
|
+
|
|
78
|
+
Package name: @miraigent/free-ai-ops-mcp
|
|
79
|
+
|
|
80
|
+
Expected command after npm publication:
|
|
81
|
+
|
|
82
|
+
npx @miraigent/free-ai-ops-mcp
|
|
83
|
+
|
|
84
|
+
Publishing requires an authenticated npm account with access to the @miraigent
|
|
85
|
+
scope.
|
|
86
|
+
|
|
87
|
+
## Public Boundary
|
|
88
|
+
|
|
89
|
+
This repository may publish:
|
|
90
|
+
|
|
91
|
+
- free MCP tools for reviewable AI operations
|
|
92
|
+
- examples without private customer data
|
|
93
|
+
- tests and issue templates
|
|
94
|
+
|
|
95
|
+
This repository must not publish:
|
|
96
|
+
|
|
97
|
+
- credentials, tokens, cookies, or private keys
|
|
98
|
+
- customer records
|
|
99
|
+
- private company notes
|
|
100
|
+
- MIRAI Memory engine details
|
|
101
|
+
- working memory MCP behavior
|
|
102
|
+
- full paid product files
|
|
103
|
+
|
|
104
|
+
## Related Resources
|
|
105
|
+
|
|
106
|
+
- Resource hub: https://miraigent.com/resources.html
|
|
107
|
+
- Parent template repository: https://github.com/Miraigent/miraigent-ai-ops-templates
|
|
108
|
+
- Free template library: https://miraigent.com/en/free-ai-operations-templates.html
|
|
109
|
+
- Free Gumroad review kit: https://miraigent.gumroad.com/l/human-review-gate-ai-drafts
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
Do not report secrets, credentials, private customer data, or private company
|
|
4
|
+
notes in public issues.
|
|
5
|
+
|
|
6
|
+
For public issues, use small synthetic examples only.
|
|
7
|
+
|
|
8
|
+
This repository does not include MIRAI Memory engine behavior or working memory
|
|
9
|
+
MCPs.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Human Review Gate Example
|
|
2
|
+
|
|
3
|
+
This example shows how FREE-004 connects to the public human_review_gate MCP
|
|
4
|
+
tool.
|
|
5
|
+
|
|
6
|
+
Use it when an AI-drafted reply is ready but you still need a human review
|
|
7
|
+
decision before anything reaches a customer.
|
|
8
|
+
|
|
9
|
+
## Run
|
|
10
|
+
|
|
11
|
+
From the repository root:
|
|
12
|
+
|
|
13
|
+
npm run example:human-review-gate
|
|
14
|
+
|
|
15
|
+
The example sends sample-request.jsonl to the MCP server and prints the
|
|
16
|
+
human_review_gate result.
|
|
17
|
+
|
|
18
|
+
## What To Copy Into Your Log
|
|
19
|
+
|
|
20
|
+
Copy result.nextLogRow into review-gate-flow.csv or your own support log.
|
|
21
|
+
|
|
22
|
+
The sample uses synthetic data only. Do not use private customer data in public
|
|
23
|
+
issues, examples, or screenshots.
|
|
24
|
+
|
|
25
|
+
## Expected Decision
|
|
26
|
+
|
|
27
|
+
The sample includes refund, complaint, and personal data risk flags, so the tool
|
|
28
|
+
should return:
|
|
29
|
+
|
|
30
|
+
- gateStatus: stop
|
|
31
|
+
- reviewOwner: support lead
|
|
32
|
+
- boundary: this tool reviews and logs; it does not send messages
|
|
33
|
+
|
|
34
|
+
This is an operations helper, not legal or compliance advice.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
|
|
4
|
+
const child = spawn(process.execPath, ['mcp/free-ai-ops-server.mjs'], {
|
|
5
|
+
stdio: ['pipe', 'pipe', 'inherit']
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const request = fs.readFileSync('examples/human-review-gate/sample-request.jsonl', 'utf8');
|
|
9
|
+
let stdout = '';
|
|
10
|
+
|
|
11
|
+
child.stdout.on('data', (chunk) => {
|
|
12
|
+
stdout += chunk;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
child.stdin.write(request.trim() + '\n');
|
|
16
|
+
child.stdin.end();
|
|
17
|
+
|
|
18
|
+
await new Promise((resolve, reject) => {
|
|
19
|
+
child.on('error', reject);
|
|
20
|
+
child.on('close', (code) => {
|
|
21
|
+
if (code !== 0) reject(new Error('server exited with ' + code));
|
|
22
|
+
else resolve();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const response = JSON.parse(stdout.trim());
|
|
27
|
+
const payload = JSON.parse(response.result.content[0].text);
|
|
28
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"human_review_gate","arguments":{"draftType":"customer support reply","audience":"customer","riskFlags":["refund","complaint","personal data"],"reviewOwner":"support lead","sendMode":"manual"}}}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const serverInfo = { name: 'miraigent-free-ai-ops-mcp', version: '0.1.1' };
|
|
4
|
+
|
|
5
|
+
const tools = [
|
|
6
|
+
{
|
|
7
|
+
name: 'human_review_gate',
|
|
8
|
+
description: 'Decide whether an AI draft should be sent, reviewed, or stopped.',
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
draftType: { type: 'string' },
|
|
13
|
+
audience: { type: 'string' },
|
|
14
|
+
riskFlags: { type: 'array', items: { type: 'string' } },
|
|
15
|
+
reviewOwner: { type: 'string' },
|
|
16
|
+
sendMode: { type: 'string' }
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'faq_candidate_review',
|
|
22
|
+
description: 'Review whether an inquiry pattern should become a public FAQ, internal FAQ, human-review rule, or rejection.',
|
|
23
|
+
inputSchema: {
|
|
24
|
+
type: 'object',
|
|
25
|
+
properties: {
|
|
26
|
+
inquiryPattern: { type: 'string' },
|
|
27
|
+
frequency: { type: 'string' },
|
|
28
|
+
responseCost: { type: 'string' },
|
|
29
|
+
riskLevel: { type: 'string' },
|
|
30
|
+
currentAnswer: { type: 'string' }
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'ai_safe_crm_note',
|
|
36
|
+
description: 'Structure a CRM note by separating customer facts, AI suggestions, human decisions, and next actions.',
|
|
37
|
+
inputSchema: {
|
|
38
|
+
type: 'object',
|
|
39
|
+
properties: {
|
|
40
|
+
rawNoteSummary: { type: 'string' },
|
|
41
|
+
channel: { type: 'string' },
|
|
42
|
+
containsPersonalData: { type: 'boolean' },
|
|
43
|
+
nextAction: { type: 'string' },
|
|
44
|
+
owner: { type: 'string' }
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: 'prompt_risk_review',
|
|
50
|
+
description: 'Review an AI prompt or task before it is used in operations.',
|
|
51
|
+
inputSchema: {
|
|
52
|
+
type: 'object',
|
|
53
|
+
properties: {
|
|
54
|
+
operation: { type: 'string' },
|
|
55
|
+
promptSummary: { type: 'string' },
|
|
56
|
+
dataTypes: { type: 'array', items: { type: 'string' } },
|
|
57
|
+
customerFacing: { type: 'boolean' },
|
|
58
|
+
riskLevel: { type: 'string' }
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
function textContent(value) {
|
|
65
|
+
return [{ type: 'text', text: JSON.stringify(value, null, 2) }];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function normalizeRisk(value) {
|
|
69
|
+
return String(value || 'medium').toLowerCase();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function callTool(name, args = {}) {
|
|
73
|
+
if (name === 'human_review_gate') {
|
|
74
|
+
const flags = Array.isArray(args.riskFlags) ? args.riskFlags.map(String) : [];
|
|
75
|
+
const riskText = flags.join(' ').toLowerCase();
|
|
76
|
+
const highRisk = riskText.match(/legal|medical|payment|refund|contract|personal|privacy|complaint|public/);
|
|
77
|
+
const sendMode = String(args.sendMode || '').toLowerCase();
|
|
78
|
+
const gateStatus = highRisk ? 'stop' : sendMode.includes('auto') || flags.length ? 'review_required' : 'auto_ok';
|
|
79
|
+
const decisionNote =
|
|
80
|
+
gateStatus === 'stop'
|
|
81
|
+
? 'Stop before sending. Assign a human owner and confirm the source policy or data-handling rule.'
|
|
82
|
+
: gateStatus === 'review_required'
|
|
83
|
+
? 'Human review is required before this draft can be sent.'
|
|
84
|
+
: 'Light review is enough if the source facts and tone are current.';
|
|
85
|
+
return {
|
|
86
|
+
tool: name,
|
|
87
|
+
gateStatus,
|
|
88
|
+
reviewOwner: args.reviewOwner || 'human reviewer',
|
|
89
|
+
decisionNote,
|
|
90
|
+
checklist: [
|
|
91
|
+
'Confirm the draft does not include private customer data.',
|
|
92
|
+
'Confirm the source FAQ or policy is current.',
|
|
93
|
+
'Confirm the audience and send mode are appropriate.',
|
|
94
|
+
'Log the final human decision before sending.'
|
|
95
|
+
],
|
|
96
|
+
logFields: ['draft_type', 'audience', 'risk_flags', 'review_owner', 'gate_status', 'decision_note'],
|
|
97
|
+
nextLogRow: {
|
|
98
|
+
draft_type: args.draftType || 'unspecified draft',
|
|
99
|
+
audience: args.audience || 'unspecified audience',
|
|
100
|
+
risk_flags: flags.join('; ') || 'none',
|
|
101
|
+
review_owner: args.reviewOwner || 'human reviewer',
|
|
102
|
+
gate_status: gateStatus,
|
|
103
|
+
decision_note: decisionNote
|
|
104
|
+
},
|
|
105
|
+
boundary: 'This tool is a review helper. It does not send messages.'
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (name === 'faq_candidate_review') {
|
|
110
|
+
const risk = normalizeRisk(args.riskLevel);
|
|
111
|
+
const status = risk === 'high' ? 'human_review_rule' : risk === 'medium' ? 'internal_faq' : 'public_faq_candidate';
|
|
112
|
+
return {
|
|
113
|
+
tool: name,
|
|
114
|
+
recommendedStatus: status,
|
|
115
|
+
faqOutline: {
|
|
116
|
+
questionPattern: args.inquiryPattern || 'Describe the repeated question pattern.',
|
|
117
|
+
answerScope: args.currentAnswer ? 'Review and simplify the current answer.' : 'Draft a short answer outline before publication.',
|
|
118
|
+
owner: 'FAQ reviewer'
|
|
119
|
+
},
|
|
120
|
+
reviewSignals: {
|
|
121
|
+
frequency: args.frequency || 'unknown',
|
|
122
|
+
responseCost: args.responseCost || 'unknown',
|
|
123
|
+
riskLevel: risk
|
|
124
|
+
},
|
|
125
|
+
boundary: 'Separate public FAQ, internal FAQ, and human-review rules before automation.'
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (name === 'ai_safe_crm_note') {
|
|
130
|
+
return {
|
|
131
|
+
tool: name,
|
|
132
|
+
crmNote: {
|
|
133
|
+
channel: args.channel || 'unknown',
|
|
134
|
+
customerFacts: args.rawNoteSummary || 'Add factual summary only.',
|
|
135
|
+
aiSuggestion: 'Keep AI suggestions separate from confirmed facts.',
|
|
136
|
+
humanDecision: 'Add the final human decision here.',
|
|
137
|
+
nextAction: args.nextAction || 'Define next action.',
|
|
138
|
+
owner: args.owner || 'owner required'
|
|
139
|
+
},
|
|
140
|
+
maskingChecklist: args.containsPersonalData
|
|
141
|
+
? ['Mask names if not needed.', 'Remove contact details before AI use.', 'Avoid copying raw private text into external tools.']
|
|
142
|
+
: ['Confirm no personal data is included.', 'Keep synthetic examples in public issues.'],
|
|
143
|
+
logFields: ['channel', 'customer_facts', 'ai_suggestion', 'human_decision', 'next_action', 'owner'],
|
|
144
|
+
boundary: 'This tool structures notes. It is not an anonymizer and does not store data.'
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (name === 'prompt_risk_review') {
|
|
149
|
+
const dataTypes = Array.isArray(args.dataTypes) ? args.dataTypes.map(String) : [];
|
|
150
|
+
const risk = normalizeRisk(args.riskLevel);
|
|
151
|
+
const dataText = dataTypes.join(' ').toLowerCase();
|
|
152
|
+
const sensitiveData = dataText.match(/name|email|phone|address|payment|medical|legal|contract|personal|customer/);
|
|
153
|
+
const shouldStop = risk === 'high' || (args.customerFacing && sensitiveData);
|
|
154
|
+
return {
|
|
155
|
+
tool: name,
|
|
156
|
+
operation: args.operation || 'unspecified operation',
|
|
157
|
+
recommendation: shouldStop ? 'stop_before_ai_use' : args.customerFacing ? 'human_review_required' : 'review_checklist_required',
|
|
158
|
+
riskFlags: [
|
|
159
|
+
...(args.customerFacing ? ['customer_facing'] : []),
|
|
160
|
+
...(sensitiveData ? ['sensitive_data_possible'] : []),
|
|
161
|
+
...(risk === 'high' ? ['high_risk'] : [])
|
|
162
|
+
],
|
|
163
|
+
checklist: [
|
|
164
|
+
'Rewrite the prompt as a short task summary before sending it to AI.',
|
|
165
|
+
'Remove private customer data unless a reviewed policy allows it.',
|
|
166
|
+
'Confirm whether the output can affect a customer, payment, contract, or complaint.',
|
|
167
|
+
'Keep a human review note for the final decision.'
|
|
168
|
+
],
|
|
169
|
+
saferNextStep: shouldStop
|
|
170
|
+
? 'Stop and define a human-reviewed data handling rule before using this prompt.'
|
|
171
|
+
: 'Run the prompt only after documenting data handling and human review expectations.',
|
|
172
|
+
boundary: 'This tool is a prompt risk helper. It is not legal advice and does not call an AI API.'
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
throw new Error('Unknown tool: ' + name);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function handle(request) {
|
|
180
|
+
if (request.method === 'initialize') {
|
|
181
|
+
return {
|
|
182
|
+
protocolVersion: '2024-11-05',
|
|
183
|
+
capabilities: { tools: {} },
|
|
184
|
+
serverInfo
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (request.method === 'tools/list') {
|
|
189
|
+
return { tools };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (request.method === 'tools/call') {
|
|
193
|
+
const params = request.params || {};
|
|
194
|
+
return { content: textContent(callTool(params.name, params.arguments || {})) };
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
throw new Error('Unsupported method: ' + request.method);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
let buffer = '';
|
|
201
|
+
process.stdin.setEncoding('utf8');
|
|
202
|
+
process.stdin.on('data', (chunk) => {
|
|
203
|
+
buffer += chunk;
|
|
204
|
+
const lines = buffer.split('\n');
|
|
205
|
+
buffer = lines.pop() || '';
|
|
206
|
+
for (const line of lines) {
|
|
207
|
+
if (!line.trim()) continue;
|
|
208
|
+
const request = JSON.parse(line);
|
|
209
|
+
try {
|
|
210
|
+
const result = handle(request);
|
|
211
|
+
process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: request.id, result }) + '\n');
|
|
212
|
+
} catch (error) {
|
|
213
|
+
process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: request.id, error: { code: -32000, message: error.message } }) + '\n');
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@miraigent/free-ai-ops-mcp",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Free MCP tools for human-reviewed AI operations.",
|
|
5
|
+
"homepage": "https://github.com/Miraigent/miraigent-free-ai-ops-mcp",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"private": false,
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"files": [
|
|
10
|
+
"README.md",
|
|
11
|
+
"LAUNCH_FLOW.md",
|
|
12
|
+
"LICENSE",
|
|
13
|
+
"CHANGELOG.md",
|
|
14
|
+
"SECURITY.md",
|
|
15
|
+
"CONTRIBUTING.md",
|
|
16
|
+
"examples/",
|
|
17
|
+
"mcp/",
|
|
18
|
+
"scripts/"
|
|
19
|
+
],
|
|
20
|
+
"bin": {
|
|
21
|
+
"miraigent-free-ai-ops-mcp": "mcp/free-ai-ops-server.mjs"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"check": "node --check mcp/free-ai-ops-server.mjs && node --check scripts/smoke-test.mjs && node --check scripts/secret-scan.mjs && node scripts/secret-scan.mjs",
|
|
25
|
+
"test": "node scripts/smoke-test.mjs",
|
|
26
|
+
"example:human-review-gate": "node examples/human-review-gate/run-example.mjs",
|
|
27
|
+
"mcp": "node mcp/free-ai-ops-server.mjs"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"mcp",
|
|
31
|
+
"ai-operations",
|
|
32
|
+
"human-review",
|
|
33
|
+
"ai-safety",
|
|
34
|
+
"crm",
|
|
35
|
+
"faq"
|
|
36
|
+
],
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/Miraigent/miraigent-free-ai-ops-mcp.git"
|
|
40
|
+
},
|
|
41
|
+
"bugs": {
|
|
42
|
+
"url": "https://github.com/Miraigent/miraigent-free-ai-ops-mcp/issues"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
const root = process.cwd();
|
|
5
|
+
const ignoredDirs = new Set(['.git', 'node_modules']);
|
|
6
|
+
const patterns = [
|
|
7
|
+
/sk-[A-Za-z0-9_-]{20,}/,
|
|
8
|
+
/ghp_[A-Za-z0-9_]{20,}/,
|
|
9
|
+
/github_pat_[A-Za-z0-9_]{20,}/,
|
|
10
|
+
/xox[baprs]-[A-Za-z0-9-]{20,}/,
|
|
11
|
+
/-----BEGIN (RSA |OPENSSH |EC |DSA )?PRIVATE KEY-----/
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
function walk(dir) {
|
|
15
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
16
|
+
return entries.flatMap((entry) => {
|
|
17
|
+
if (ignoredDirs.has(entry.name)) return [];
|
|
18
|
+
const full = path.join(dir, entry.name);
|
|
19
|
+
if (entry.isDirectory()) return walk(full);
|
|
20
|
+
return [full];
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let failed = false;
|
|
25
|
+
for (const file of walk(root)) {
|
|
26
|
+
const rel = path.relative(root, file);
|
|
27
|
+
const ext = path.extname(file).toLowerCase();
|
|
28
|
+
if (!['.md', '.json', '.js', '.mjs', '.yml', '.yaml', '.txt', ''].includes(ext)) continue;
|
|
29
|
+
const body = fs.readFileSync(file, 'utf8');
|
|
30
|
+
for (const pattern of patterns) {
|
|
31
|
+
if (pattern.test(body)) {
|
|
32
|
+
console.error(rel + ': possible secret matched ' + pattern);
|
|
33
|
+
failed = true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (failed) process.exit(1);
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
|
|
5
|
+
const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
|
|
6
|
+
|
|
7
|
+
const child = spawn(process.execPath, ['mcp/free-ai-ops-server.mjs'], {
|
|
8
|
+
stdio: ['pipe', 'pipe', 'inherit']
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const requests = [
|
|
12
|
+
{ jsonrpc: '2.0', id: 1, method: 'initialize', params: {} },
|
|
13
|
+
{ jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} },
|
|
14
|
+
{
|
|
15
|
+
jsonrpc: '2.0',
|
|
16
|
+
id: 3,
|
|
17
|
+
method: 'tools/call',
|
|
18
|
+
params: {
|
|
19
|
+
name: 'human_review_gate',
|
|
20
|
+
arguments: {
|
|
21
|
+
draftType: 'support reply',
|
|
22
|
+
audience: 'customer',
|
|
23
|
+
riskFlags: ['privacy'],
|
|
24
|
+
reviewOwner: 'support lead',
|
|
25
|
+
sendMode: 'manual'
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
jsonrpc: '2.0',
|
|
31
|
+
id: 4,
|
|
32
|
+
method: 'tools/call',
|
|
33
|
+
params: {
|
|
34
|
+
name: 'faq_candidate_review',
|
|
35
|
+
arguments: {
|
|
36
|
+
inquiryPattern: 'pricing plan difference',
|
|
37
|
+
frequency: 'high',
|
|
38
|
+
responseCost: 'medium',
|
|
39
|
+
riskLevel: 'low'
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
jsonrpc: '2.0',
|
|
45
|
+
id: 5,
|
|
46
|
+
method: 'tools/call',
|
|
47
|
+
params: {
|
|
48
|
+
name: 'ai_safe_crm_note',
|
|
49
|
+
arguments: {
|
|
50
|
+
rawNoteSummary: 'Customer asked about setup timing.',
|
|
51
|
+
channel: 'form',
|
|
52
|
+
containsPersonalData: false,
|
|
53
|
+
nextAction: 'send setup checklist',
|
|
54
|
+
owner: 'sales'
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
jsonrpc: '2.0',
|
|
60
|
+
id: 6,
|
|
61
|
+
method: 'tools/call',
|
|
62
|
+
params: {
|
|
63
|
+
name: 'prompt_risk_review',
|
|
64
|
+
arguments: {
|
|
65
|
+
operation: 'support automation',
|
|
66
|
+
promptSummary: 'Draft a customer reply from inquiry details.',
|
|
67
|
+
dataTypes: ['customer email', 'inquiry body'],
|
|
68
|
+
customerFacing: true,
|
|
69
|
+
riskLevel: 'medium'
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
let stdout = '';
|
|
76
|
+
child.stdout.on('data', (chunk) => {
|
|
77
|
+
stdout += chunk;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
for (const request of requests) {
|
|
81
|
+
child.stdin.write(JSON.stringify(request) + '\n');
|
|
82
|
+
}
|
|
83
|
+
child.stdin.end();
|
|
84
|
+
|
|
85
|
+
await new Promise((resolve, reject) => {
|
|
86
|
+
child.on('error', reject);
|
|
87
|
+
child.on('close', (code) => {
|
|
88
|
+
if (code !== 0) reject(new Error('server exited with ' + code));
|
|
89
|
+
else resolve();
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const responses = stdout.trim().split('\n').map((line) => JSON.parse(line));
|
|
94
|
+
assert.equal(responses.length, requests.length);
|
|
95
|
+
assert.equal(responses[0].result.serverInfo.name, 'miraigent-free-ai-ops-mcp');
|
|
96
|
+
assert.equal(responses[0].result.serverInfo.version, packageJson.version);
|
|
97
|
+
assert.equal(responses[1].result.tools.length, 4);
|
|
98
|
+
assert.match(responses[2].result.content[0].text, /review_required|stop/);
|
|
99
|
+
assert.match(responses[2].result.content[0].text, /nextLogRow/);
|
|
100
|
+
assert.match(responses[3].result.content[0].text, /public_faq_candidate/);
|
|
101
|
+
assert.match(responses[4].result.content[0].text, /crmNote/);
|
|
102
|
+
assert.match(responses[5].result.content[0].text, /stop_before_ai_use|human_review_required/);
|