@forcedream/mcp-server 0.7.0 → 0.8.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.
@@ -0,0 +1,91 @@
1
+ import { z } from 'zod';
2
+ const FD_API = process.env.FD_API_BASE || 'https://api.forcedream.ai';
3
+ function authHeader() {
4
+ const key = process.env.FD_API_KEY || '';
5
+ return key ? { Authorization: `Bearer ${key}` } : {};
6
+ }
7
+ async function postJson(url, body) {
8
+ const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', ...authHeader() }, body: JSON.stringify(body) });
9
+ let json = null;
10
+ try {
11
+ json = await res.json();
12
+ }
13
+ catch { }
14
+ return { status: res.status, json };
15
+ }
16
+ // --- forcedream_check_fraud ---
17
+ export const checkFraudSchema = {
18
+ ip: z.string().optional().describe('Optional IP address to check against AbuseIPDB reputation data.'),
19
+ };
20
+ /**
21
+ * Real, direct fraud risk assessment -- a single, synchronous call, no polling. SPENDS
22
+ * your balance -- requires FD_API_KEY. Uses real AbuseIPDB reputation data when an IP is
23
+ * provided.
24
+ * @param args.ip - Optional IP address to check.
25
+ */
26
+ export async function checkFraud(args) {
27
+ if (process.env.FD_MOCK_MODE === 'true') {
28
+ return { status: 'completed', risk_score: 0, signals: {}, verdict: 'allow', ip_reputation: { abuseipdb_score: null }, mock: true, message: 'MOCK MODE ACTIVE (FD_MOCK_MODE=true): no real balance was spent, no real AbuseIPDB lookup was made.' };
29
+ }
30
+ if (!process.env.FD_API_KEY) {
31
+ return { status: 'error', message: 'FD_API_KEY is required (this tool spends your balance). Set it in the MCP server env.' };
32
+ }
33
+ const res = await postJson(`${FD_API}/v1/tools/check-fraud`, { ip: args.ip || '' });
34
+ if (res.status === 401)
35
+ return { status: 'error', message: 'Invalid FD_API_KEY (401).' };
36
+ if (res.status === 402)
37
+ return { status: 'error', message: `Insufficient balance: ${JSON.stringify(res.json)}` };
38
+ if (res.status !== 200 || !res.json)
39
+ return { status: 'error', message: `Request failed (HTTP ${res.status}): ${JSON.stringify(res.json)}` };
40
+ return { status: 'completed', ...res.json };
41
+ }
42
+ // --- forcedream_generate_embedding ---
43
+ export const generateEmbeddingSchema = {
44
+ text: z.string().describe('Text to embed (max ~32000 chars).'),
45
+ input_type: z.string().optional().describe('Optional: "query" or "document".'),
46
+ };
47
+ /**
48
+ * Real, direct text embedding via Voyage voyage-3.5 -- a single, synchronous call, no
49
+ * polling. SPENDS your balance (per-token charge) -- requires FD_API_KEY.
50
+ * @param args.text - Text to embed.
51
+ * @param args.input_type - Optional "query" or "document".
52
+ */
53
+ export async function generateEmbedding(args) {
54
+ if (process.env.FD_MOCK_MODE === 'true') {
55
+ return { status: 'completed', dimensions: 1024, tokens: 0, embedding: [], cost_pence: 0, mock: true, message: 'MOCK MODE ACTIVE (FD_MOCK_MODE=true): no real balance was spent, no real embedding was generated.' };
56
+ }
57
+ if (!process.env.FD_API_KEY) {
58
+ return { status: 'error', message: 'FD_API_KEY is required (this tool spends your balance). Set it in the MCP server env.' };
59
+ }
60
+ const res = await postJson(`${FD_API}/v1/embeddings`, { text: args.text, input_type: args.input_type });
61
+ if (res.status === 401)
62
+ return { status: 'error', message: 'Invalid FD_API_KEY (401).' };
63
+ if (res.status !== 200 || !res.json)
64
+ return { status: 'error', message: `Request failed (HTTP ${res.status}): ${JSON.stringify(res.json)}` };
65
+ return { status: 'completed', ...res.json };
66
+ }
67
+ // --- forcedream_market_quote ---
68
+ export const marketQuoteSchema = {
69
+ symbol: z.string().describe('Ticker symbol, e.g. "AAPL", "IBM".'),
70
+ };
71
+ /**
72
+ * Real, direct, live market quote via Alpha Vantage -- a single, synchronous call, no
73
+ * polling. SPENDS your balance -- requires FD_API_KEY. Hard-cached server-side.
74
+ * @param args.symbol - Ticker symbol, e.g. "AAPL".
75
+ */
76
+ export async function marketQuote(args) {
77
+ if (process.env.FD_MOCK_MODE === 'true') {
78
+ return { status: 'completed', symbol: args.symbol, price: 0, change_percent: 0, volume: 0, mock: true, message: 'MOCK MODE ACTIVE (FD_MOCK_MODE=true): no real balance was spent, no real market data was fetched.' };
79
+ }
80
+ if (!process.env.FD_API_KEY) {
81
+ return { status: 'error', message: 'FD_API_KEY is required (this tool spends your balance). Set it in the MCP server env.' };
82
+ }
83
+ const res = await postJson(`${FD_API}/v1/tools/market-quote`, { symbol: args.symbol });
84
+ if (res.status === 401)
85
+ return { status: 'error', message: 'Invalid FD_API_KEY (401).' };
86
+ if (res.status === 402)
87
+ return { status: 'error', message: `Insufficient balance: ${JSON.stringify(res.json)}` };
88
+ if (res.status !== 200 || !res.json)
89
+ return { status: 'error', message: `Request failed (HTTP ${res.status}): ${JSON.stringify(res.json)}` };
90
+ return { status: 'completed', ...res.json };
91
+ }
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ import { searchAgents, searchAgentsSchema } from './search_agents.js';
7
7
  import { invokeAgent, invokeAgentSchema } from './invoke_agent.js';
8
8
  import { securityScan, securityScanSchema } from './security_scan.js';
9
9
  import { extractData, extractDataSchema } from './extract_data.js';
10
+ import { checkFraud, checkFraudSchema, generateEmbedding, generateEmbeddingSchema, marketQuote, marketQuoteSchema } from './direct_tools.js';
10
11
  import { searchReliability, searchReliabilitySchema } from './search_reliability.js';
11
12
  import { searchCosts, searchCostsSchema } from './search_costs.js';
12
13
  import { searchProviders } from './search_providers.js';
@@ -109,6 +110,54 @@ server.registerTool('forcedream_extract_data', {
109
110
  return { content: [{ type: 'text', text: JSON.stringify({ status: 'error', error: e.message }, null, 2) }], isError: true };
110
111
  }
111
112
  });
113
+ // forcedream_check_fraud — real, direct, synchronous call (no polling). Spends balance
114
+ // (needs FD_API_KEY). Uses the new, dedicated fd_live_-accepting backend endpoint.
115
+ server.registerTool('forcedream_check_fraud', {
116
+ title: 'Check IP / account fraud risk',
117
+ description: 'Real fraud risk assessment using AbuseIPDB IP reputation data. SPENDS your balance — requires FD_API_KEY. ' +
118
+ 'Returns risk_score, signals, and an allow/review/block verdict, WORM-sealed.',
119
+ inputSchema: checkFraudSchema,
120
+ }, async ({ ip }) => {
121
+ try {
122
+ const result = await checkFraud({ ip });
123
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
124
+ }
125
+ catch (e) {
126
+ return { content: [{ type: 'text', text: JSON.stringify({ status: 'error', error: e.message }, null, 2) }], isError: true };
127
+ }
128
+ });
129
+ // forcedream_generate_embedding — real, direct, synchronous call (no polling). Spends
130
+ // balance (needs FD_API_KEY, per-token charge).
131
+ server.registerTool('forcedream_generate_embedding', {
132
+ title: 'Generate a text embedding',
133
+ description: 'Real 1024-dim vector embedding via Voyage voyage-3.5, retrieval-optimised. SPENDS your balance ' +
134
+ '(per-token charge) — requires FD_API_KEY. Returns the vector, dimensions, token count, WORM-sealed.',
135
+ inputSchema: generateEmbeddingSchema,
136
+ }, async ({ text, input_type }) => {
137
+ try {
138
+ const result = await generateEmbedding({ text, input_type });
139
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
140
+ }
141
+ catch (e) {
142
+ return { content: [{ type: 'text', text: JSON.stringify({ status: 'error', error: e.message }, null, 2) }], isError: true };
143
+ }
144
+ });
145
+ // forcedream_market_quote — real, direct, synchronous call (no polling). Spends balance
146
+ // (needs FD_API_KEY). Hard-cached server-side.
147
+ server.registerTool('forcedream_market_quote', {
148
+ title: 'Get a live market quote',
149
+ description: 'Real, live market quote for a stock symbol via Alpha Vantage: price, change %, volume, day high/low, ' +
150
+ 'liquidity score. SPENDS your balance — requires FD_API_KEY. Hard-cached, WORM-sealed.',
151
+ inputSchema: marketQuoteSchema,
152
+ }, async ({ symbol }) => {
153
+ try {
154
+ const result = await marketQuote({ symbol });
155
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
156
+ }
157
+ catch (e) {
158
+ return { content: [{ type: 'text', text: JSON.stringify({ status: 'error', error: e.message }, null, 2) }], isError: true };
159
+ }
160
+ });
112
161
  // forcedream_search_reliability — keyless. Real, system-measured reliability per agent.
113
162
  server.registerTool('forcedream_search_reliability', {
114
163
  title: 'Search agent reliability data',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forcedream/mcp-server",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "mcpName": "io.github.forcedreamai/mcp-server",
5
5
  "description": "Discover, invoke, and trustlessly verify ForceDream AI agents with cryptographic proofs. ForceDream is a paid, verifiable agent marketplace reachable over MCP, every successful call is billed and split with the agent's developer, and every result is Ed25519-signed and independently verifiable in your own process.",
6
6
  "type": "module",