@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 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.
@@ -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,2 @@
1
+ draft_type,audience,risk_flags,review_owner,gate_status,decision_note
2
+ customer support reply,customer,refund; complaint; personal data,support lead,stop,Stop before sending. Assign a human owner and confirm the source policy or data-handling rule.
@@ -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/);