@voidly/mcp-server 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/dist/index.js +90 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -187,6 +187,72 @@ async function getActiveIncidents() {
|
|
|
187
187
|
result += `URL: https://voidly.ai/censorship-index\n`;
|
|
188
188
|
return result;
|
|
189
189
|
}
|
|
190
|
+
async function verifyClaim(claim, requireEvidence = false) {
|
|
191
|
+
const data = await fetchJson(`${VOIDLY_API}/v1/verify-claim?claim=${encodeURIComponent(claim)}&require_evidence=${requireEvidence}`);
|
|
192
|
+
let result = `# Claim Verification\n\n`;
|
|
193
|
+
result += `**Claim:** "${data.claim}"\n\n`;
|
|
194
|
+
// Verdict with emoji
|
|
195
|
+
const verdictEmoji = {
|
|
196
|
+
confirmed: '✅',
|
|
197
|
+
likely: '🟡',
|
|
198
|
+
unconfirmed: '❓',
|
|
199
|
+
no_data: '⚪',
|
|
200
|
+
insufficient_data: '⚠️',
|
|
201
|
+
};
|
|
202
|
+
result += `## Verdict: ${verdictEmoji[data.verdict] || ''} ${data.verdict.toUpperCase()}\n\n`;
|
|
203
|
+
result += `**Confidence:** ${(data.confidence * 100).toFixed(0)}%\n`;
|
|
204
|
+
result += `**Reason:** ${data.reason}\n\n`;
|
|
205
|
+
// Parsed components
|
|
206
|
+
result += `## Parsed Claim\n`;
|
|
207
|
+
if (data.parsed.country) {
|
|
208
|
+
result += `- Country: ${data.parsed.country} (${data.parsed.country_code})\n`;
|
|
209
|
+
}
|
|
210
|
+
if (data.parsed.service) {
|
|
211
|
+
result += `- Service: ${data.parsed.service}\n`;
|
|
212
|
+
}
|
|
213
|
+
if (data.parsed.date) {
|
|
214
|
+
result += `- Date: ${data.parsed.date}\n`;
|
|
215
|
+
}
|
|
216
|
+
if (data.parsed.date_range) {
|
|
217
|
+
result += `- Date Range: ${data.parsed.date_range.start} to ${data.parsed.date_range.end}\n`;
|
|
218
|
+
}
|
|
219
|
+
result += '\n';
|
|
220
|
+
// Matching incidents
|
|
221
|
+
if (data.incidents && data.incidents.length > 0) {
|
|
222
|
+
result += `## Supporting Incidents\n\n`;
|
|
223
|
+
data.incidents.forEach((inc, i) => {
|
|
224
|
+
result += `### ${i + 1}. ${inc.title}\n`;
|
|
225
|
+
result += `- ID: ${inc.id}\n`;
|
|
226
|
+
result += `- Status: ${inc.status}\n`;
|
|
227
|
+
result += `- Severity: ${inc.severity}\n`;
|
|
228
|
+
result += `- Confidence: ${(inc.confidence * 100).toFixed(0)}%\n`;
|
|
229
|
+
result += `- Started: ${inc.startTime.slice(0, 10)}\n`;
|
|
230
|
+
result += `- Permalink: ${inc.permalink}\n\n`;
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
// Evidence if requested
|
|
234
|
+
if (data.evidence && data.evidence.length > 0) {
|
|
235
|
+
result += `## Evidence Chain\n\n`;
|
|
236
|
+
data.evidence.forEach((ev, i) => {
|
|
237
|
+
result += `${i + 1}. **${ev.source.toUpperCase()}** (${ev.kind})\n`;
|
|
238
|
+
result += ` - Observed: ${ev.observedAt.slice(0, 10)}\n`;
|
|
239
|
+
result += ` - Confidence: ${(ev.confidence * 100).toFixed(0)}%\n`;
|
|
240
|
+
if (ev.permalink) {
|
|
241
|
+
result += ` - Verify: ${ev.permalink}\n`;
|
|
242
|
+
}
|
|
243
|
+
result += '\n';
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
// Citation
|
|
247
|
+
if (data.citation) {
|
|
248
|
+
result += `## Citation\n\n`;
|
|
249
|
+
result += `${data.citation}\n\n`;
|
|
250
|
+
}
|
|
251
|
+
result += `## Source\n`;
|
|
252
|
+
result += `Data: Voidly Research Claim Verification API\n`;
|
|
253
|
+
result += `License: CC BY 4.0\n`;
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
190
256
|
// Create MCP server
|
|
191
257
|
const server = new Server({
|
|
192
258
|
name: 'voidly-censorship-index',
|
|
@@ -264,6 +330,24 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
264
330
|
required: [],
|
|
265
331
|
},
|
|
266
332
|
},
|
|
333
|
+
{
|
|
334
|
+
name: 'verify_claim',
|
|
335
|
+
description: 'Verify a censorship claim with evidence. Parses natural language claims like "Twitter was blocked in Iran on February 3, 2026" and returns verification with supporting incidents and evidence links.',
|
|
336
|
+
inputSchema: {
|
|
337
|
+
type: 'object',
|
|
338
|
+
properties: {
|
|
339
|
+
claim: {
|
|
340
|
+
type: 'string',
|
|
341
|
+
description: 'Natural language censorship claim to verify (e.g., "Is YouTube blocked in China?", "Twitter was blocked in Iran on February 3, 2026")',
|
|
342
|
+
},
|
|
343
|
+
require_evidence: {
|
|
344
|
+
type: 'boolean',
|
|
345
|
+
description: 'Whether to include detailed evidence chain with source links (default: false)',
|
|
346
|
+
},
|
|
347
|
+
},
|
|
348
|
+
required: ['claim'],
|
|
349
|
+
},
|
|
350
|
+
},
|
|
267
351
|
],
|
|
268
352
|
}));
|
|
269
353
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
@@ -293,6 +377,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
293
377
|
case 'get_active_incidents':
|
|
294
378
|
result = await getActiveIncidents();
|
|
295
379
|
break;
|
|
380
|
+
case 'verify_claim':
|
|
381
|
+
if (!args?.claim) {
|
|
382
|
+
throw new Error('claim is required');
|
|
383
|
+
}
|
|
384
|
+
result = await verifyClaim(args.claim, args?.require_evidence || false);
|
|
385
|
+
break;
|
|
296
386
|
default:
|
|
297
387
|
throw new Error(`Unknown tool: ${name}`);
|
|
298
388
|
}
|
package/package.json
CHANGED