@forcedream/mcp-server 0.1.2 → 0.3.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 +117 -17
- package/dist/cli-verify.js +23 -0
- package/dist/index.js +49 -1
- package/dist/search_costs.js +25 -0
- package/dist/search_providers.js +16 -0
- package/dist/search_reliability.js +23 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,20 +1,41 @@
|
|
|
1
1
|
# @forcedream/mcp-server
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@forcedream/mcp-server)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
|
|
3
7
|
An [MCP](https://modelcontextprotocol.io) server for **ForceDream** — discover AI agents, invoke them to do real work, and **verify the result cryptographically in your own process**. No trust in ForceDream required: every agent task produces an Ed25519-signed proof that this server checks locally.
|
|
4
8
|
|
|
9
|
+
Listed on the [official MCP Registry](https://registry.modelcontextprotocol.io) as `io.github.forcedreamai/mcp-server`.
|
|
10
|
+
|
|
11
|
+
## Two ways to connect
|
|
12
|
+
|
|
13
|
+
| | Local (npm) | Remote (hosted) |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| **Transport** | stdio, runs on your machine | Streamable HTTP, hosted by ForceDream |
|
|
16
|
+
| **Setup** | `npx -y @forcedream/mcp-server` | Point your client at `https://api.forcedream.ai/v1/mcp` |
|
|
17
|
+
| **Auth for invoking** | `FD_API_KEY` env var | OAuth 2.1 + PKCE (standard MCP auth flow) |
|
|
18
|
+
| **Tools available** | `search_agents`, `verify_proof`, `invoke_agent` | All of the above, plus `check_fraud`, `generate_embedding`, `market_quote` |
|
|
19
|
+
| **Best for** | Claude Desktop, local dev | Any client with native remote-MCP + OAuth support |
|
|
20
|
+
|
|
21
|
+
Both talk to the same real ForceDream API and the same real settlement system. Pick whichever fits your client.
|
|
22
|
+
|
|
5
23
|
## What it does
|
|
6
24
|
|
|
7
|
-
|
|
25
|
+
`search_agents` and `verify_proof` need no account. Tools that spend your balance need authentication.
|
|
8
26
|
|
|
9
27
|
| Tool | Auth | What it does |
|
|
10
28
|
|------|------|--------------|
|
|
11
|
-
| `search_agents` | none | Discover ForceDream agents and
|
|
12
|
-
| `verify_proof` | none | Independently verify a ForceDream proof by task ID.
|
|
13
|
-
| `invoke_agent` | key | Invoke an agent to do real work. Spends your balance.
|
|
29
|
+
| `search_agents` | none | Discover ForceDream agents, their real capabilities, and honest, system-derived metrics. |
|
|
30
|
+
| `verify_proof` | none | Independently verify a ForceDream proof by task ID. Checked locally against the published public key. |
|
|
31
|
+
| `invoke_agent` | key/OAuth | Invoke an agent to do real work. Spends your balance. Honest declines and failed charges cost nothing. |
|
|
32
|
+
| `check_fraud`\* | OAuth | Real-time fraud risk scoring using IP reputation and behavioural signals. |
|
|
33
|
+
| `generate_embedding`\* | OAuth | Real 1024-dim text embeddings via Voyage voyage-3.5. |
|
|
34
|
+
| `market_quote`\* | OAuth | Live stock quotes via Alpha Vantage, cached, WORM-sealed. |
|
|
14
35
|
|
|
15
|
-
|
|
36
|
+
\* remote server only.
|
|
16
37
|
|
|
17
|
-
## Quick start
|
|
38
|
+
## Quick start (local, npm)
|
|
18
39
|
|
|
19
40
|
### 1. Get a key
|
|
20
41
|
|
|
@@ -41,7 +62,7 @@ Edit your `claude_desktop_config.json`:
|
|
|
41
62
|
}
|
|
42
63
|
```
|
|
43
64
|
|
|
44
|
-
Restart Claude Desktop. You should see the
|
|
65
|
+
Restart Claude Desktop. You should see the ForceDream tools available.
|
|
45
66
|
|
|
46
67
|
> Omit `FD_API_KEY` to run discovery + verification only (no spending). Add it to enable `invoke_agent`.
|
|
47
68
|
|
|
@@ -53,25 +74,103 @@ In a new chat:
|
|
|
53
74
|
|
|
54
75
|
You'll watch discovery → invocation → trustless verification, end to end.
|
|
55
76
|
|
|
56
|
-
##
|
|
77
|
+
## Quick start (remote, OAuth)
|
|
57
78
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
79
|
+
For MCP clients with native remote-server support, add:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"mcpServers": {
|
|
84
|
+
"forcedream": {
|
|
85
|
+
"url": "https://api.forcedream.ai/v1/mcp"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Your client will handle the OAuth 2.1 + PKCE flow automatically the first time you invoke a billed tool.
|
|
92
|
+
|
|
93
|
+
## Examples
|
|
94
|
+
|
|
95
|
+
Real agents you can try, see search_agents for the full current list.
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
Invoke data-extract-v1 to pull structured fields from raw text.
|
|
99
|
+
Invoke translation-v1 to translate a passage.
|
|
100
|
+
Invoke summarization-v1 to summarise a document.
|
|
101
|
+
Invoke forecast-generation-v1 to generate a forecast from a data series.
|
|
102
|
+
```
|
|
62
103
|
|
|
63
|
-
##
|
|
104
|
+
## Architecture
|
|
64
105
|
|
|
65
|
-
|
|
106
|
+
```
|
|
107
|
+
ForceDream API (api.forcedream.ai)
|
|
108
|
+
- Agent marketplace and settlement (real billing, real payouts)
|
|
109
|
+
- Ed25519 proof signing
|
|
110
|
+
- Adaptive routing and provider intelligence
|
|
111
|
+
|
|
|
112
|
+
+--- this MCP server (stdio, local) --- Claude Desktop, Cursor, Cline
|
|
113
|
+
+--- remote MCP endpoint (OAuth) ------ any MCP client with remote support
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
This repository is a thin client. It calls the public API and speaks MCP -- it does not contain ForceDream's agent orchestration, routing, or settlement logic, which remain part of the private platform.
|
|
117
|
+
|
|
118
|
+
## Why ForceDream
|
|
119
|
+
|
|
120
|
+
Unlike a documentation-lookup or local-automation MCP server, ForceDream is a paid, verifiable agent marketplace reachable over MCP:
|
|
121
|
+
|
|
122
|
+
- Real settlement -- every successful call is billed and split with the agent's developer; nothing self-reported.
|
|
123
|
+
- Cryptographic proof -- every result is Ed25519-signed and independently verifiable, not just trusted.
|
|
124
|
+
- Honest declines -- an agent that cannot answer confidently declines rather than fabricates, and charges nothing.
|
|
125
|
+
- No double-charging -- timeouts and retries never bill you twice for the same task.
|
|
126
|
+
|
|
127
|
+
## Example workflows
|
|
128
|
+
|
|
129
|
+
Real prompts you can adapt, covering different real ways to use the tools together.
|
|
130
|
+
|
|
131
|
+
**Discover, then invoke, then verify**
|
|
132
|
+
> Search ForceDream for agents that do data extraction, invoke the best one on this text, then verify the proof it returns.
|
|
133
|
+
|
|
134
|
+
**Multi-step pipeline: extract, then translate**
|
|
135
|
+
> Extract the key fields from this document with data-extract-v1, then translate the result into Spanish with translation-v1.
|
|
136
|
+
|
|
137
|
+
**Summarize, then confirm authenticity**
|
|
138
|
+
> Summarize this report with summarization-v1, then verify the proof so I know it is genuinely ForceDream's unaltered output.
|
|
66
139
|
|
|
67
|
-
|
|
140
|
+
**Forecast from real data**
|
|
141
|
+
> Feed this sales history to forecast-generation-v1 and ask for a 3-month forecast.
|
|
68
142
|
|
|
69
|
-
|
|
143
|
+
**Fraud check before a sensitive action** (remote only)
|
|
144
|
+
> Before processing this withdrawal, run check_fraud on this user ID and IP address.
|
|
145
|
+
|
|
146
|
+
**Market-aware research** (remote only)
|
|
147
|
+
> Get a live quote for AAPL, then summarize what today's price move might mean for a tech-sector report.
|
|
148
|
+
|
|
149
|
+
**Embeddings for downstream search** (remote only)
|
|
150
|
+
> Generate an embedding for this paragraph so I can compare it against my existing document vectors.
|
|
151
|
+
|
|
152
|
+
**Chained verification across multiple tasks**
|
|
153
|
+
> Invoke summarization-v1 on these three documents one at a time, and after each one, verify its proof before moving to the next.
|
|
154
|
+
|
|
155
|
+
## What a proof proves -- and what it does not
|
|
156
|
+
|
|
157
|
+
A valid proof attests provenance and integrity: that ForceDream produced this exact output for this exact input, at this cost, and that nothing has been altered since. The signature is checked in your process, so you do not have to trust ForceDream's word.
|
|
158
|
+
|
|
159
|
+
A proof does not attest factual correctness. An agent's answer can still be wrong; the proof only guarantees it is the agent's genuine, unmodified work. Verify cited sources yourself.
|
|
160
|
+
|
|
161
|
+
You can also verify any proof in a browser at forcedream.com/proof.
|
|
162
|
+
|
|
163
|
+
## Configuration (local)
|
|
164
|
+
|
|
165
|
+
| Env var | Required | Default | Purpose |
|
|
166
|
+
|---------|----------|---------|---------|
|
|
167
|
+
| FD_API_KEY | only for invoke_agent | none | Your fd_live_ billing key. Spending happens against its balance. |
|
|
168
|
+
| FD_API_BASE | no | https://api.forcedream.ai | Override the API base (for testing). |
|
|
70
169
|
|
|
71
170
|
## Run it directly
|
|
72
171
|
|
|
73
172
|
```bash
|
|
74
|
-
npx -y @forcedream/mcp-server
|
|
173
|
+
npx -y @forcedream/mcp-server
|
|
75
174
|
```
|
|
76
175
|
|
|
77
176
|
It speaks MCP over stdio; point any MCP client at it.
|
|
@@ -80,6 +179,7 @@ It speaks MCP over stdio; point any MCP client at it.
|
|
|
80
179
|
|
|
81
180
|
- ForceDream: https://www.forcedream.com
|
|
82
181
|
- Verify a proof: https://www.forcedream.com/proof
|
|
182
|
+
- Official MCP Registry entry: https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.forcedreamai/mcp-server
|
|
83
183
|
- MCP: https://modelcontextprotocol.io
|
|
84
184
|
|
|
85
185
|
## License
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Real CLI verification tool: npx @forcedream/mcp-server verify <task_id>
|
|
3
|
+
// Wraps the exact same verifyProof() function the MCP tool itself uses --
|
|
4
|
+
// no separate verification logic, no hardcoded example proof.
|
|
5
|
+
import { verifyProof } from './verify_proof.js';
|
|
6
|
+
async function main() {
|
|
7
|
+
const taskId = process.argv[2];
|
|
8
|
+
if (!taskId) {
|
|
9
|
+
console.error('Usage: fd-verify <task_id>');
|
|
10
|
+
console.error('Example: fd-verify wtask_a3ff3b4f3a1f6bf7df1f');
|
|
11
|
+
process.exit(2);
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
const result = await verifyProof({ task_id: taskId });
|
|
15
|
+
console.log(JSON.stringify(result, null, 2));
|
|
16
|
+
process.exit(result.verified ? 0 : 1);
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
console.error('Error:', e?.message || String(e));
|
|
20
|
+
process.exit(2);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
main();
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,10 @@ import { z } from 'zod';
|
|
|
5
5
|
import { verifyProof } from './verify_proof.js';
|
|
6
6
|
import { searchAgents, searchAgentsSchema } from './search_agents.js';
|
|
7
7
|
import { invokeAgent, invokeAgentSchema } from './invoke_agent.js';
|
|
8
|
-
|
|
8
|
+
import { searchReliability, searchReliabilitySchema } from './search_reliability.js';
|
|
9
|
+
import { searchCosts, searchCostsSchema } from './search_costs.js';
|
|
10
|
+
import { searchProviders } from './search_providers.js';
|
|
11
|
+
const server = new McpServer({ name: 'forcedream', version: '0.3.0' });
|
|
9
12
|
// verify_proof — trustless, keyless. Verify a ForceDream proof's Ed25519 signature client-side.
|
|
10
13
|
server.registerTool('verify_proof', {
|
|
11
14
|
title: 'Verify a ForceDream proof',
|
|
@@ -57,5 +60,50 @@ server.registerTool('invoke_agent', {
|
|
|
57
60
|
return { content: [{ type: 'text', text: JSON.stringify({ status: 'error', error: e.message }, null, 2) }], isError: true };
|
|
58
61
|
}
|
|
59
62
|
});
|
|
63
|
+
// search_reliability — keyless. Real, system-measured reliability per agent.
|
|
64
|
+
server.registerTool('search_reliability', {
|
|
65
|
+
title: 'Search agent reliability data',
|
|
66
|
+
description: 'Real, system-measured reliability per agent: success_rate, avg_latency_ms, sample_size. No key needed. ' +
|
|
67
|
+
'Same real data as search_agents\' health field, exposed standalone for reliability-focused queries.',
|
|
68
|
+
inputSchema: searchReliabilitySchema,
|
|
69
|
+
}, async ({ agent_slug }) => {
|
|
70
|
+
try {
|
|
71
|
+
const result = await searchReliability({ agent_slug });
|
|
72
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
return { content: [{ type: 'text', text: JSON.stringify({ error: e.message }, null, 2) }], isError: true };
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
// search_costs — keyless. Real price_per_call_pence per agent.
|
|
79
|
+
server.registerTool('search_costs', {
|
|
80
|
+
title: 'Search agent pricing',
|
|
81
|
+
description: 'Real price_per_call_pence for every registered agent. No key needed. ' +
|
|
82
|
+
'Useful for budget-aware agent selection before invoking.',
|
|
83
|
+
inputSchema: searchCostsSchema,
|
|
84
|
+
}, async ({ max_price_pence }) => {
|
|
85
|
+
try {
|
|
86
|
+
const result = await searchCosts({ max_price_pence });
|
|
87
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
return { content: [{ type: 'text', text: JSON.stringify({ error: e.message }, null, 2) }], isError: true };
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
// search_providers — keyless. Real, live inference-provider health.
|
|
94
|
+
server.registerTool('search_providers', {
|
|
95
|
+
title: 'Search provider health',
|
|
96
|
+
description: 'Real, live inference-provider health: health_score, breaker_state, uptime_ratio, recent successes/failures. ' +
|
|
97
|
+
'The same real intelligence the platform\'s own adaptive routing uses internally. No key needed.',
|
|
98
|
+
inputSchema: {},
|
|
99
|
+
}, async () => {
|
|
100
|
+
try {
|
|
101
|
+
const result = await searchProviders();
|
|
102
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
return { content: [{ type: 'text', text: JSON.stringify({ error: e.message }, null, 2) }], isError: true };
|
|
106
|
+
}
|
|
107
|
+
});
|
|
60
108
|
const transport = new StdioServerTransport();
|
|
61
109
|
await server.connect(transport);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const FD_API = process.env.FD_API_BASE || 'https://api.forcedream.ai';
|
|
3
|
+
export const searchCostsSchema = {
|
|
4
|
+
max_price_pence: z.number().optional().describe('Optional: only return agents at or under this price.'),
|
|
5
|
+
};
|
|
6
|
+
async function fetchJson(url) {
|
|
7
|
+
const res = await fetch(url);
|
|
8
|
+
if (!res.ok)
|
|
9
|
+
throw new Error(`fetch ${url} -> HTTP ${res.status}`);
|
|
10
|
+
return res.json();
|
|
11
|
+
}
|
|
12
|
+
export async function searchCosts(args) {
|
|
13
|
+
const data = await fetchJson(`${FD_API}/v1/agents/list`);
|
|
14
|
+
const agents = Array.isArray(data?.agents) ? data.agents : [];
|
|
15
|
+
let priced = agents.map((a) => ({ slug: a.slug, name: a.name, price_per_call_pence: a.price_per_call_pence }));
|
|
16
|
+
if (typeof args.max_price_pence === 'number') {
|
|
17
|
+
const cap = args.max_price_pence;
|
|
18
|
+
priced = priced.filter((a) => (a.price_per_call_pence ?? Infinity) <= cap);
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
count: priced.length,
|
|
22
|
+
agents: priced,
|
|
23
|
+
note: 'Real price_per_call_pence per agent, useful for budget-aware selection before invoking.',
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const FD_API = process.env.FD_API_BASE || 'https://api.forcedream.ai';
|
|
2
|
+
async function fetchJson(url) {
|
|
3
|
+
const res = await fetch(url);
|
|
4
|
+
if (!res.ok)
|
|
5
|
+
throw new Error(`fetch ${url} -> HTTP ${res.status}`);
|
|
6
|
+
return res.json();
|
|
7
|
+
}
|
|
8
|
+
export async function searchProviders() {
|
|
9
|
+
const data = await fetchJson(`${FD_API}/v1/intelligence/status`);
|
|
10
|
+
const providers = Array.isArray(data?.providers) ? data.providers : [];
|
|
11
|
+
return {
|
|
12
|
+
count: providers.length,
|
|
13
|
+
providers,
|
|
14
|
+
note: 'Real, live provider health -- the same intelligence the platform\'s own adaptive routing uses internally.',
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const FD_API = process.env.FD_API_BASE || 'https://api.forcedream.ai';
|
|
3
|
+
export const searchReliabilitySchema = {
|
|
4
|
+
agent_slug: z.string().optional().describe('Optional: filter to one agent slug. Omit to return all.'),
|
|
5
|
+
};
|
|
6
|
+
async function fetchJson(url) {
|
|
7
|
+
const res = await fetch(url);
|
|
8
|
+
if (!res.ok)
|
|
9
|
+
throw new Error(`fetch ${url} -> HTTP ${res.status}`);
|
|
10
|
+
return res.json();
|
|
11
|
+
}
|
|
12
|
+
// Real, system-measured reliability per agent. Same real endpoint the remote MCP server uses.
|
|
13
|
+
export async function searchReliability(args) {
|
|
14
|
+
const data = await fetchJson(`${FD_API}/v1/agents/reliability`);
|
|
15
|
+
let agents = Array.isArray(data?.agents) ? data.agents : [];
|
|
16
|
+
if (args.agent_slug)
|
|
17
|
+
agents = agents.filter((a) => a.agent_slug === args.agent_slug);
|
|
18
|
+
return {
|
|
19
|
+
count: agents.length,
|
|
20
|
+
agents,
|
|
21
|
+
note: 'Real, system-measured reliability -- success_rate, avg_latency_ms, sample_size. Never self-reported.',
|
|
22
|
+
};
|
|
23
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forcedream/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"mcpName": "io.github.forcedreamai/mcp-server",
|
|
5
5
|
"description": "MCP server for ForceDream \u2014 discover, invoke, and trustlessly verify AI agents with cryptographic proofs.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
|
-
"fd-mcp": "dist/index.js"
|
|
8
|
+
"fd-mcp": "dist/index.js",
|
|
9
|
+
"fd-verify": "dist/cli-verify.js"
|
|
9
10
|
},
|
|
10
11
|
"main": "dist/index.js",
|
|
11
12
|
"scripts": {
|
|
@@ -46,8 +47,7 @@
|
|
|
46
47
|
"homepage": "https://www.forcedream.com",
|
|
47
48
|
"repository": {
|
|
48
49
|
"type": "git",
|
|
49
|
-
"url": "https://github.com/forcedreamai/forcedream.git"
|
|
50
|
-
"directory": "packages/mcp-server"
|
|
50
|
+
"url": "https://github.com/forcedreamai/forcedream-mcp.git"
|
|
51
51
|
},
|
|
52
52
|
"author": "ForceDream"
|
|
53
53
|
}
|