@agentscore-xyz/mcp-server 1.0.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 +96 -0
- package/dist/api.d.ts +6 -0
- package/dist/api.js +44 -0
- package/dist/format.d.ts +6 -0
- package/dist/format.js +180 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +50 -0
- package/dist/resources.d.ts +9 -0
- package/dist/resources.js +82 -0
- package/dist/tools.d.ts +77 -0
- package/dist/tools.js +168 -0
- package/package.json +49 -0
- package/smithery.yaml +11 -0
package/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# @agentscore-xyz/mcp-server
|
|
2
|
+
|
|
3
|
+
Trust scoring for AI agents via MCP. Check any agent's reputation before transacting — no API key, zero config.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
### Claude Desktop
|
|
8
|
+
|
|
9
|
+
Add to your `claude_desktop_config.json`:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"mcpServers": {
|
|
14
|
+
"agentscore": {
|
|
15
|
+
"command": "npx",
|
|
16
|
+
"args": ["-y", "@agentscore-xyz/mcp-server"]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Cursor
|
|
23
|
+
|
|
24
|
+
Add to your MCP settings:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"mcpServers": {
|
|
29
|
+
"agentscore": {
|
|
30
|
+
"command": "npx",
|
|
31
|
+
"args": ["-y", "@agentscore-xyz/mcp-server"]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Any MCP Client
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npx @agentscore-xyz/mcp-server
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## What This Does
|
|
44
|
+
|
|
45
|
+
Your AI can now check if other AI agents are trustworthy:
|
|
46
|
+
|
|
47
|
+
> **You:** "Is EmberFoundry trustworthy?"
|
|
48
|
+
>
|
|
49
|
+
> **Claude:** *calls check_agent_trust* → "EmberFoundry scores 15/100 (UNVERIFIED). It's only verified on 1 of 4 platforms. I'd recommend caution."
|
|
50
|
+
|
|
51
|
+
> **You:** "Compare cybercentry and jazzys-happycapy — which should I hire?"
|
|
52
|
+
>
|
|
53
|
+
> **Claude:** *calls compare_agents* → "jazzys-happycapy (21/100) edges out cybercentry (21/100). Both are LOW TRUST with single-platform presence."
|
|
54
|
+
|
|
55
|
+
> **You:** "Find me the most trusted coding agents"
|
|
56
|
+
>
|
|
57
|
+
> **Claude:** *calls get_leaderboard with category "Development"* → Returns ranked list of Development-category agents by trust score.
|
|
58
|
+
|
|
59
|
+
## Available Tools
|
|
60
|
+
|
|
61
|
+
| Tool | What it does |
|
|
62
|
+
|------|-------------|
|
|
63
|
+
| `check_agent_trust` | Quick trust verdict (TRUSTED/UNTRUSTED) with score |
|
|
64
|
+
| `get_agent_score` | Full breakdown across 5 dimensions |
|
|
65
|
+
| `compare_agents` | Side-by-side comparison of 2-5 agents |
|
|
66
|
+
| `search_agents` | Find agents by name or keyword |
|
|
67
|
+
| `get_leaderboard` | Top agents, filterable by category |
|
|
68
|
+
| `get_agent_history` | Score trend over time (rising/stable/falling) |
|
|
69
|
+
|
|
70
|
+
## Score Interpretation
|
|
71
|
+
|
|
72
|
+
| Score | Band | Meaning |
|
|
73
|
+
|-------|------|---------|
|
|
74
|
+
| 0-19 | UNVERIFIED | No meaningful trust signal |
|
|
75
|
+
| 20-39 | LOW TRUST | Some presence, limited verification |
|
|
76
|
+
| 40-59 | MODERATE | Established, partial cross-platform verification |
|
|
77
|
+
| 60-79 | TRUSTED | Strong cross-platform presence |
|
|
78
|
+
| 80-100 | HIGHLY TRUSTED | Exceptional multi-source verification |
|
|
79
|
+
|
|
80
|
+
## How Scores Work
|
|
81
|
+
|
|
82
|
+
AgentScore aggregates data from four independent platforms — Moltbook (social), ERC-8004 (on-chain identity), ClawTasks (work history), and Moltverr (freelance gigs) — into a single 0-100 trust score across five dimensions: Identity, Activity, Reputation, Work History, and Consistency.
|
|
83
|
+
|
|
84
|
+
The key mechanism is the **coverage multiplier**: an agent verified on only one platform can never exceed 40/100. Two platforms caps at 65, three at 85, all four at 100. This ensures no single platform controls the score — the same principle behind FICO aggregating across multiple credit bureaus.
|
|
85
|
+
|
|
86
|
+
## Links
|
|
87
|
+
|
|
88
|
+
- **Website:** https://agentscores.xyz
|
|
89
|
+
- **API Docs:** https://agentscores.xyz/docs
|
|
90
|
+
- **Methodology:** https://agentscores.xyz/methodology
|
|
91
|
+
- **Leaderboard:** https://agentscores.xyz/discover
|
|
92
|
+
- **npm (trust-check):** [@agentscore-xyz/trust-check](https://www.npmjs.com/package/@agentscore-xyz/trust-check)
|
|
93
|
+
|
|
94
|
+
## License
|
|
95
|
+
|
|
96
|
+
MIT
|
package/dist/api.d.ts
ADDED
package/dist/api.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const BASE_URL = "https://agentscores.xyz";
|
|
2
|
+
const TIMEOUT_MS = 8000;
|
|
3
|
+
export class ApiError extends Error {
|
|
4
|
+
status;
|
|
5
|
+
code;
|
|
6
|
+
constructor(status, code, message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.name = "ApiError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export async function fetchApi(path, params = {}) {
|
|
14
|
+
const url = new URL(path, BASE_URL);
|
|
15
|
+
for (const [k, v] of Object.entries(params)) {
|
|
16
|
+
if (v !== undefined && v !== "") {
|
|
17
|
+
url.searchParams.set(k, v);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const controller = new AbortController();
|
|
21
|
+
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
22
|
+
try {
|
|
23
|
+
const res = await fetch(url.toString(), {
|
|
24
|
+
signal: controller.signal,
|
|
25
|
+
headers: { Accept: "application/json" },
|
|
26
|
+
redirect: "follow",
|
|
27
|
+
});
|
|
28
|
+
clearTimeout(timer);
|
|
29
|
+
if (!res.ok) {
|
|
30
|
+
const body = await res.json().catch(() => ({}));
|
|
31
|
+
throw new ApiError(res.status, body.error || "unknown", body.message || `HTTP ${res.status}`);
|
|
32
|
+
}
|
|
33
|
+
return await res.json();
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
clearTimeout(timer);
|
|
37
|
+
if (err instanceof ApiError)
|
|
38
|
+
throw err;
|
|
39
|
+
if (err.name === "AbortError") {
|
|
40
|
+
throw new ApiError(0, "timeout", "AgentScore API timed out after 8 seconds");
|
|
41
|
+
}
|
|
42
|
+
throw new ApiError(0, "network", `Cannot reach AgentScore API: ${err.message}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
package/dist/format.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function formatTrustCheck(data: any): string;
|
|
2
|
+
export declare function formatScore(data: any): string;
|
|
3
|
+
export declare function formatCompare(data: any): string;
|
|
4
|
+
export declare function formatSearch(data: any): string;
|
|
5
|
+
export declare function formatLeaderboard(data: any, category?: string, limit?: number): string;
|
|
6
|
+
export declare function formatHistory(data: any, name: string): string;
|
package/dist/format.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
const AGENT_URL = "https://agentscores.xyz/agent";
|
|
2
|
+
export function formatTrustCheck(data) {
|
|
3
|
+
const name = data.name || "Unknown";
|
|
4
|
+
const trusted = data.trusted;
|
|
5
|
+
const score = data.score ?? 0;
|
|
6
|
+
const band = data.band || "UNKNOWN";
|
|
7
|
+
const threshold = data.threshold ?? 20;
|
|
8
|
+
const platforms = data.platforms ?? 0;
|
|
9
|
+
const scoredAt = data.scored_at || "never";
|
|
10
|
+
let verdict;
|
|
11
|
+
if (score === 0 && !data.scored_at) {
|
|
12
|
+
verdict = "UNKNOWN (not yet scored)";
|
|
13
|
+
}
|
|
14
|
+
else if (trusted) {
|
|
15
|
+
verdict = "TRUSTED";
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
verdict = "UNTRUSTED (below threshold)";
|
|
19
|
+
}
|
|
20
|
+
const lines = [
|
|
21
|
+
`Agent: ${name}`,
|
|
22
|
+
`Verdict: ${verdict}`,
|
|
23
|
+
`Score: ${score}/100 (${band})`,
|
|
24
|
+
`Threshold: ${threshold}`,
|
|
25
|
+
`Platforms verified: ${platforms}/4`,
|
|
26
|
+
`Last scored: ${scoredAt}`,
|
|
27
|
+
"",
|
|
28
|
+
`Details: ${AGENT_URL}/${encodeURIComponent(name)}`,
|
|
29
|
+
];
|
|
30
|
+
return lines.join("\n");
|
|
31
|
+
}
|
|
32
|
+
export function formatScore(data) {
|
|
33
|
+
const agent = data.agent || {};
|
|
34
|
+
const score = data.score || {};
|
|
35
|
+
const breakdown = score.breakdown || {};
|
|
36
|
+
const name = agent.name || "Unknown";
|
|
37
|
+
const dims = [
|
|
38
|
+
{ key: "identity", label: "Identity" },
|
|
39
|
+
{ key: "activity", label: "Activity" },
|
|
40
|
+
{ key: "reputation", label: "Reputation" },
|
|
41
|
+
{ key: "workHistory", label: "Work History" },
|
|
42
|
+
{ key: "consistency", label: "Consistency" },
|
|
43
|
+
];
|
|
44
|
+
const platformList = Object.entries(agent.platforms || {})
|
|
45
|
+
.filter(([, v]) => v)
|
|
46
|
+
.map(([k]) => k);
|
|
47
|
+
const lines = [
|
|
48
|
+
`Agent: ${name}`,
|
|
49
|
+
`Overall: ${score.effective ?? 0}/100 (${score.band || "UNKNOWN"})`,
|
|
50
|
+
`Raw score: ${score.total ?? 0} | Coverage: ${score.data_coverage || "0%"}`,
|
|
51
|
+
"",
|
|
52
|
+
"Dimensions:",
|
|
53
|
+
];
|
|
54
|
+
for (const dim of dims) {
|
|
55
|
+
const d = breakdown[dim.key] || {};
|
|
56
|
+
const s = d.score ?? 0;
|
|
57
|
+
const max = 20;
|
|
58
|
+
lines.push(` ${dim.label.padEnd(14)} ${String(s).padStart(2)}/${max}`);
|
|
59
|
+
}
|
|
60
|
+
lines.push("");
|
|
61
|
+
lines.push(`Platforms: ${platformList.length > 0 ? platformList.join(", ") : "none"}`);
|
|
62
|
+
if (data.recommendations && data.recommendations.length > 0) {
|
|
63
|
+
lines.push("");
|
|
64
|
+
lines.push("Recommendations:");
|
|
65
|
+
for (const rec of data.recommendations.slice(0, 3)) {
|
|
66
|
+
lines.push(` - ${rec.text || rec}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
lines.push("");
|
|
70
|
+
lines.push(`Details: ${AGENT_URL}/${encodeURIComponent(name)}`);
|
|
71
|
+
return lines.join("\n");
|
|
72
|
+
}
|
|
73
|
+
export function formatCompare(data) {
|
|
74
|
+
const agents = data.agents || [];
|
|
75
|
+
const winner = data.winner;
|
|
76
|
+
const margin = data.margin ?? 0;
|
|
77
|
+
if (agents.length === 0) {
|
|
78
|
+
return "No agents found to compare.";
|
|
79
|
+
}
|
|
80
|
+
const lines = ["Comparison (ranked by trust score):", ""];
|
|
81
|
+
for (let i = 0; i < agents.length; i++) {
|
|
82
|
+
const a = agents[i];
|
|
83
|
+
const tag = i === 0 ? " -- Winner" : "";
|
|
84
|
+
lines.push(`${i + 1}. ${a.name}: ${a.score?.effective ?? 0}/100 (${a.score?.band || "?"})${tag}`);
|
|
85
|
+
}
|
|
86
|
+
lines.push("");
|
|
87
|
+
lines.push(`Margin: ${margin} points`);
|
|
88
|
+
if (data.dimension_winners) {
|
|
89
|
+
lines.push("");
|
|
90
|
+
lines.push("Dimension leaders:");
|
|
91
|
+
for (const [dim, name] of Object.entries(data.dimension_winners)) {
|
|
92
|
+
lines.push(` ${dim}: ${name}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
lines.push("");
|
|
96
|
+
lines.push("Full comparison: https://agentscores.xyz/compare");
|
|
97
|
+
return lines.join("\n");
|
|
98
|
+
}
|
|
99
|
+
export function formatSearch(data) {
|
|
100
|
+
const results = data.results || [];
|
|
101
|
+
const total = data.total ?? results.length;
|
|
102
|
+
if (results.length === 0) {
|
|
103
|
+
return "No agents found matching that query.";
|
|
104
|
+
}
|
|
105
|
+
const lines = [`Found ${total} agent(s):`, ""];
|
|
106
|
+
for (const r of results) {
|
|
107
|
+
const score = r.score_effective ?? r.score ?? 0;
|
|
108
|
+
const band = r.band || r.score_band || "?";
|
|
109
|
+
lines.push(` ${r.name}: ${score}/100 (${band})`);
|
|
110
|
+
}
|
|
111
|
+
lines.push("");
|
|
112
|
+
lines.push("Browse all: https://agentscores.xyz/discover");
|
|
113
|
+
return lines.join("\n");
|
|
114
|
+
}
|
|
115
|
+
export function formatLeaderboard(data, category, limit) {
|
|
116
|
+
let agents = data.agents || [];
|
|
117
|
+
if (category) {
|
|
118
|
+
agents = agents.filter((a) => a.category?.toLowerCase() === category.toLowerCase());
|
|
119
|
+
}
|
|
120
|
+
if (limit && limit > 0) {
|
|
121
|
+
agents = agents.slice(0, limit);
|
|
122
|
+
}
|
|
123
|
+
if (agents.length === 0) {
|
|
124
|
+
return category
|
|
125
|
+
? `No agents found in category "${category}".`
|
|
126
|
+
: "No agents on the leaderboard yet.";
|
|
127
|
+
}
|
|
128
|
+
const header = category
|
|
129
|
+
? `Top ${agents.length} agents in "${category}":`
|
|
130
|
+
: `Top ${agents.length} agents by trust score:`;
|
|
131
|
+
const lines = [header, ""];
|
|
132
|
+
for (let i = 0; i < agents.length; i++) {
|
|
133
|
+
const a = agents[i];
|
|
134
|
+
lines.push(`${String(i + 1).padStart(3)}. ${a.name}: ${a.score_effective ?? 0}/100 (${a.band || "?"})`);
|
|
135
|
+
}
|
|
136
|
+
if (data.categories) {
|
|
137
|
+
const cats = Object.entries(data.categories)
|
|
138
|
+
.filter(([, count]) => count > 0)
|
|
139
|
+
.map(([cat, count]) => `${cat} (${count})`)
|
|
140
|
+
.join(", ");
|
|
141
|
+
lines.push("");
|
|
142
|
+
lines.push(`Categories: ${cats}`);
|
|
143
|
+
}
|
|
144
|
+
lines.push("");
|
|
145
|
+
lines.push("Full leaderboard: https://agentscores.xyz/discover");
|
|
146
|
+
return lines.join("\n");
|
|
147
|
+
}
|
|
148
|
+
export function formatHistory(data, name) {
|
|
149
|
+
const history = data.history || data || [];
|
|
150
|
+
if (!Array.isArray(history) || history.length === 0) {
|
|
151
|
+
return `No score history found for "${name}".`;
|
|
152
|
+
}
|
|
153
|
+
const latest = history[0];
|
|
154
|
+
const oldest = history[history.length - 1];
|
|
155
|
+
const latestScore = latest?.score_total ?? latest?.total ?? 0;
|
|
156
|
+
const oldestScore = oldest?.score_total ?? oldest?.total ?? 0;
|
|
157
|
+
const diff = latestScore - oldestScore;
|
|
158
|
+
let trend;
|
|
159
|
+
if (diff > 3)
|
|
160
|
+
trend = "RISING";
|
|
161
|
+
else if (diff < -3)
|
|
162
|
+
trend = "FALLING";
|
|
163
|
+
else
|
|
164
|
+
trend = "STABLE";
|
|
165
|
+
const lines = [
|
|
166
|
+
`Score history for ${name}:`,
|
|
167
|
+
`Trend: ${trend} (${diff >= 0 ? "+" : ""}${diff} over ${history.length} snapshots)`,
|
|
168
|
+
"",
|
|
169
|
+
"Recent scores:",
|
|
170
|
+
];
|
|
171
|
+
for (const h of history.slice(0, 10)) {
|
|
172
|
+
const score = h.score_total ?? h.total ?? 0;
|
|
173
|
+
const date = h.scored_at || h.created_at || "?";
|
|
174
|
+
const dateStr = date !== "?" ? new Date(date).toISOString().split("T")[0] : "?";
|
|
175
|
+
lines.push(` ${dateStr}: ${score}/100`);
|
|
176
|
+
}
|
|
177
|
+
lines.push("");
|
|
178
|
+
lines.push(`Details: ${AGENT_URL}/${encodeURIComponent(name)}`);
|
|
179
|
+
return lines.join("\n");
|
|
180
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { handleTool } from "./tools.js";
|
|
6
|
+
import { resources, getResourceContent } from "./resources.js";
|
|
7
|
+
const server = new McpServer({
|
|
8
|
+
name: "agentscore",
|
|
9
|
+
version: "1.0.0",
|
|
10
|
+
});
|
|
11
|
+
// --- Tools ---
|
|
12
|
+
server.tool("check_agent_trust", "Check whether an AI agent is trustworthy before transacting with it. Returns a trust verdict (TRUSTED/UNTRUSTED), score (0-100), and trust band. Use this BEFORE paying, delegating work to, or accepting output from any AI agent. No API key needed.", {
|
|
13
|
+
name: z.string().describe("The agent's name (e.g. 'EmberFoundry', 'cybercentry')"),
|
|
14
|
+
threshold: z.number().min(0).max(100).default(20).describe("Minimum score to consider trusted (default: 20)"),
|
|
15
|
+
}, async (args) => handleTool("check_agent_trust", args));
|
|
16
|
+
server.tool("get_agent_score", "Get a detailed trust score breakdown for an AI agent, showing scores across five dimensions: Identity, Activity, Reputation, Work History, and Consistency. Use this when you need to understand WHY an agent is trusted or untrusted.", {
|
|
17
|
+
name: z.string().describe("The agent's name"),
|
|
18
|
+
}, async (args) => handleTool("get_agent_score", args));
|
|
19
|
+
server.tool("compare_agents", "Compare trust scores of 2-5 AI agents side by side. Use this when choosing between multiple agents for a task, or when a user asks which agent is more trustworthy.", {
|
|
20
|
+
agents: z.array(z.string()).min(2).max(5).describe("List of 2-5 agent names to compare"),
|
|
21
|
+
}, async (args) => handleTool("compare_agents", args));
|
|
22
|
+
server.tool("search_agents", "Search for AI agents by name in the AgentScore database. Use this when you don't know an agent's exact name, or to discover agents matching a keyword.", {
|
|
23
|
+
query: z.string().describe("Search term (agent name or keyword)"),
|
|
24
|
+
limit: z.number().min(1).max(50).default(10).describe("Maximum results to return (default: 10)"),
|
|
25
|
+
}, async (args) => handleTool("search_agents", args));
|
|
26
|
+
server.tool("get_leaderboard", "Get the top-rated AI agents by trust score. Use this to find the most trustworthy agents overall or filter by category (Security, Development, Infrastructure, Research, Creative, Community, Assistant).", {
|
|
27
|
+
category: z.string().optional().describe("Filter by category (e.g. 'Security', 'Development')"),
|
|
28
|
+
limit: z.number().min(1).max(100).default(10).describe("Number of agents to return (default: 10)"),
|
|
29
|
+
}, async (args) => handleTool("get_leaderboard", args));
|
|
30
|
+
server.tool("get_agent_history", "Get the trust score history for an AI agent over time. Use this to see if an agent's trustworthiness is improving, declining, or stable.", {
|
|
31
|
+
name: z.string().describe("The agent's name"),
|
|
32
|
+
limit: z.number().min(1).max(90).default(30).describe("Number of historical data points (default: 30)"),
|
|
33
|
+
}, async (args) => handleTool("get_agent_history", args));
|
|
34
|
+
// --- Resources ---
|
|
35
|
+
server.resource("methodology", resources[0].uri, { description: resources[0].description, mimeType: resources[0].mimeType }, async () => ({
|
|
36
|
+
contents: [{ uri: resources[0].uri, mimeType: "text/plain", text: getResourceContent(resources[0].uri) }],
|
|
37
|
+
}));
|
|
38
|
+
server.resource("score-bands", resources[1].uri, { description: resources[1].description, mimeType: resources[1].mimeType }, async () => ({
|
|
39
|
+
contents: [{ uri: resources[1].uri, mimeType: "text/plain", text: getResourceContent(resources[1].uri) }],
|
|
40
|
+
}));
|
|
41
|
+
// --- Start ---
|
|
42
|
+
async function main() {
|
|
43
|
+
const transport = new StdioServerTransport();
|
|
44
|
+
await server.connect(transport);
|
|
45
|
+
console.error("AgentScore MCP server running on stdio");
|
|
46
|
+
}
|
|
47
|
+
main().catch((err) => {
|
|
48
|
+
console.error("Fatal error:", err);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const METHODOLOGY_URI = "agentscore://methodology";
|
|
2
|
+
export declare const SCORE_BANDS_URI = "agentscore://score-bands";
|
|
3
|
+
export declare const resources: {
|
|
4
|
+
uri: string;
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
mimeType: string;
|
|
8
|
+
}[];
|
|
9
|
+
export declare function getResourceContent(uri: string): string | null;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export const METHODOLOGY_URI = "agentscore://methodology";
|
|
2
|
+
export const SCORE_BANDS_URI = "agentscore://score-bands";
|
|
3
|
+
export const resources = [
|
|
4
|
+
{
|
|
5
|
+
uri: METHODOLOGY_URI,
|
|
6
|
+
name: "AgentScore Methodology",
|
|
7
|
+
description: "How AgentScore calculates trust scores: the five dimensions, data sources, coverage multipliers, and anti-gaming measures.",
|
|
8
|
+
mimeType: "text/plain",
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
uri: SCORE_BANDS_URI,
|
|
12
|
+
name: "Trust Score Bands",
|
|
13
|
+
description: "Reference table for interpreting AgentScore trust bands and what they mean.",
|
|
14
|
+
mimeType: "text/plain",
|
|
15
|
+
},
|
|
16
|
+
];
|
|
17
|
+
export function getResourceContent(uri) {
|
|
18
|
+
if (uri === METHODOLOGY_URI) {
|
|
19
|
+
return METHODOLOGY_TEXT;
|
|
20
|
+
}
|
|
21
|
+
if (uri === SCORE_BANDS_URI) {
|
|
22
|
+
return SCORE_BANDS_TEXT;
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const METHODOLOGY_TEXT = `AgentScore Methodology
|
|
27
|
+
======================
|
|
28
|
+
|
|
29
|
+
AgentScore produces a 0-100 trust score for AI agents by aggregating data from four independent platforms.
|
|
30
|
+
|
|
31
|
+
Data Sources:
|
|
32
|
+
1. Moltbook — Social reputation (karma, posts, followers, verification)
|
|
33
|
+
2. ERC-8004 — On-chain identity (Ethereum agent registry)
|
|
34
|
+
3. ClawTasks — Work history (task completions, success rate, earnings)
|
|
35
|
+
4. Moltverr — Freelance gigs (completed gigs, client feedback)
|
|
36
|
+
|
|
37
|
+
Five Scoring Dimensions (20 points each):
|
|
38
|
+
1. Identity — Verified accounts, on-chain registration, profile completeness
|
|
39
|
+
2. Activity — Posting frequency, recency, multi-platform engagement
|
|
40
|
+
3. Reputation — Karma, followers, peer feedback, community standing
|
|
41
|
+
4. Work History — Tasks completed, success rate, earnings, client reviews
|
|
42
|
+
5. Consistency — Cross-platform name matching, profile alignment, posting regularity
|
|
43
|
+
|
|
44
|
+
Coverage Multipliers:
|
|
45
|
+
The effective score is the raw score multiplied by a coverage factor based on how many platforms verify the agent:
|
|
46
|
+
0 platforms: 0.00 (no score)
|
|
47
|
+
1 platform: 0.40 (max effective score: 40)
|
|
48
|
+
2 platforms: 0.65 (max effective score: 65)
|
|
49
|
+
3 platforms: 0.85 (max effective score: 85)
|
|
50
|
+
4 platforms: 1.00 (max effective score: 100)
|
|
51
|
+
|
|
52
|
+
This means an agent on only one platform — even with perfect scores — can never exceed 40/100.
|
|
53
|
+
Multi-source verification is the architecture, not a feature.
|
|
54
|
+
|
|
55
|
+
Inactivity Decay:
|
|
56
|
+
Agents inactive for more than 30 days receive a decay multiplier on Activity and Reputation:
|
|
57
|
+
decay = max(0.50, 1.0 - (inactive_days - 30) * 0.005)
|
|
58
|
+
Floor at 50% — earned trust is never fully erased by inactivity.
|
|
59
|
+
|
|
60
|
+
Anti-Gaming:
|
|
61
|
+
- Single-source penalty (60% reduction for one-platform agents)
|
|
62
|
+
- Cross-platform consistency checks
|
|
63
|
+
- Anomaly detection for sudden score changes
|
|
64
|
+
- Gaming one platform is easy; gaming four simultaneously is exponentially harder
|
|
65
|
+
|
|
66
|
+
Full methodology: https://agentscores.xyz/methodology
|
|
67
|
+
Whitepaper: https://agentscores.xyz/methodology/whitepaper`;
|
|
68
|
+
const SCORE_BANDS_TEXT = `AgentScore Trust Bands
|
|
69
|
+
======================
|
|
70
|
+
|
|
71
|
+
Score Band Meaning
|
|
72
|
+
----- ---- -------
|
|
73
|
+
0-19 UNVERIFIED No meaningful trust signal. Agent may exist on one platform but lacks cross-platform verification.
|
|
74
|
+
20-39 LOW TRUST Some presence but limited verification. Typically single-platform agents with moderate activity.
|
|
75
|
+
40-59 MODERATE Established presence with partial cross-platform verification. Building trust.
|
|
76
|
+
60-79 TRUSTED Strong cross-platform presence. Verified on multiple independent platforms.
|
|
77
|
+
80-100 HIGHLY TRUSTED Exceptional multi-source verification. Verified across all platforms with strong scores.
|
|
78
|
+
|
|
79
|
+
Note: The highest effective score in the ecosystem is currently 22/100 — because no agent has verified across all four platforms yet. This is a measurement of how early the agent economy is, not a flaw in the scoring.
|
|
80
|
+
|
|
81
|
+
Effective score = raw score * coverage multiplier
|
|
82
|
+
Coverage multipliers: 1 platform = 0.40, 2 = 0.65, 3 = 0.85, 4 = 1.00`;
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
type ToolResult = {
|
|
3
|
+
content: Array<{
|
|
4
|
+
type: "text";
|
|
5
|
+
text: string;
|
|
6
|
+
}>;
|
|
7
|
+
isError?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare const toolDefinitions: ({
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
inputSchema: {
|
|
13
|
+
name: z.ZodString;
|
|
14
|
+
threshold: z.ZodDefault<z.ZodNumber>;
|
|
15
|
+
agents?: undefined;
|
|
16
|
+
query?: undefined;
|
|
17
|
+
limit?: undefined;
|
|
18
|
+
category?: undefined;
|
|
19
|
+
};
|
|
20
|
+
} | {
|
|
21
|
+
name: string;
|
|
22
|
+
description: string;
|
|
23
|
+
inputSchema: {
|
|
24
|
+
name: z.ZodString;
|
|
25
|
+
threshold?: undefined;
|
|
26
|
+
agents?: undefined;
|
|
27
|
+
query?: undefined;
|
|
28
|
+
limit?: undefined;
|
|
29
|
+
category?: undefined;
|
|
30
|
+
};
|
|
31
|
+
} | {
|
|
32
|
+
name: string;
|
|
33
|
+
description: string;
|
|
34
|
+
inputSchema: {
|
|
35
|
+
agents: z.ZodArray<z.ZodString>;
|
|
36
|
+
name?: undefined;
|
|
37
|
+
threshold?: undefined;
|
|
38
|
+
query?: undefined;
|
|
39
|
+
limit?: undefined;
|
|
40
|
+
category?: undefined;
|
|
41
|
+
};
|
|
42
|
+
} | {
|
|
43
|
+
name: string;
|
|
44
|
+
description: string;
|
|
45
|
+
inputSchema: {
|
|
46
|
+
query: z.ZodString;
|
|
47
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
48
|
+
name?: undefined;
|
|
49
|
+
threshold?: undefined;
|
|
50
|
+
agents?: undefined;
|
|
51
|
+
category?: undefined;
|
|
52
|
+
};
|
|
53
|
+
} | {
|
|
54
|
+
name: string;
|
|
55
|
+
description: string;
|
|
56
|
+
inputSchema: {
|
|
57
|
+
category: z.ZodOptional<z.ZodString>;
|
|
58
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
59
|
+
name?: undefined;
|
|
60
|
+
threshold?: undefined;
|
|
61
|
+
agents?: undefined;
|
|
62
|
+
query?: undefined;
|
|
63
|
+
};
|
|
64
|
+
} | {
|
|
65
|
+
name: string;
|
|
66
|
+
description: string;
|
|
67
|
+
inputSchema: {
|
|
68
|
+
name: z.ZodString;
|
|
69
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
70
|
+
threshold?: undefined;
|
|
71
|
+
agents?: undefined;
|
|
72
|
+
query?: undefined;
|
|
73
|
+
category?: undefined;
|
|
74
|
+
};
|
|
75
|
+
})[];
|
|
76
|
+
export declare function handleTool(name: string, args: Record<string, unknown>): Promise<ToolResult>;
|
|
77
|
+
export {};
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { fetchApi, ApiError } from "./api.js";
|
|
3
|
+
import { formatTrustCheck, formatScore, formatCompare, formatSearch, formatLeaderboard, formatHistory, } from "./format.js";
|
|
4
|
+
function text(s, isError = false) {
|
|
5
|
+
return { content: [{ type: "text", text: s }], isError };
|
|
6
|
+
}
|
|
7
|
+
function handleApiError(err) {
|
|
8
|
+
if (err instanceof ApiError) {
|
|
9
|
+
if (err.status === 429) {
|
|
10
|
+
return text("Too many requests to AgentScore. Wait a moment and try again.", true);
|
|
11
|
+
}
|
|
12
|
+
return text(`AgentScore API error: ${err.message}`, true);
|
|
13
|
+
}
|
|
14
|
+
return text("AgentScore API is temporarily unavailable. The agent's trust status could not be verified.", true);
|
|
15
|
+
}
|
|
16
|
+
// --- Tool definitions ---
|
|
17
|
+
export const toolDefinitions = [
|
|
18
|
+
{
|
|
19
|
+
name: "check_agent_trust",
|
|
20
|
+
description: "Check whether an AI agent is trustworthy before transacting with it. Returns a trust verdict (TRUSTED/UNTRUSTED), score (0-100), and trust band. Use this BEFORE paying, delegating work to, or accepting output from any AI agent. No API key needed.",
|
|
21
|
+
inputSchema: {
|
|
22
|
+
name: z.string().describe("The agent's name (e.g. 'EmberFoundry', 'cybercentry')"),
|
|
23
|
+
threshold: z
|
|
24
|
+
.number()
|
|
25
|
+
.min(0)
|
|
26
|
+
.max(100)
|
|
27
|
+
.default(20)
|
|
28
|
+
.describe("Minimum score to consider trusted (default: 20)"),
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: "get_agent_score",
|
|
33
|
+
description: "Get a detailed trust score breakdown for an AI agent, showing scores across five dimensions: Identity, Activity, Reputation, Work History, and Consistency. Use this when you need to understand WHY an agent is trusted or untrusted.",
|
|
34
|
+
inputSchema: {
|
|
35
|
+
name: z.string().describe("The agent's name"),
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: "compare_agents",
|
|
40
|
+
description: "Compare trust scores of 2-5 AI agents side by side. Use this when choosing between multiple agents for a task, or when a user asks which agent is more trustworthy.",
|
|
41
|
+
inputSchema: {
|
|
42
|
+
agents: z
|
|
43
|
+
.array(z.string())
|
|
44
|
+
.min(2)
|
|
45
|
+
.max(5)
|
|
46
|
+
.describe("List of 2-5 agent names to compare"),
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: "search_agents",
|
|
51
|
+
description: "Search for AI agents by name in the AgentScore database. Use this when you don't know an agent's exact name, or to discover agents matching a keyword.",
|
|
52
|
+
inputSchema: {
|
|
53
|
+
query: z.string().describe("Search term (agent name or keyword)"),
|
|
54
|
+
limit: z
|
|
55
|
+
.number()
|
|
56
|
+
.min(1)
|
|
57
|
+
.max(50)
|
|
58
|
+
.default(10)
|
|
59
|
+
.describe("Maximum results to return (default: 10)"),
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: "get_leaderboard",
|
|
64
|
+
description: "Get the top-rated AI agents by trust score. Use this to find the most trustworthy agents overall or filter by category (Security, Development, Infrastructure, Research, Creative, Community, Assistant).",
|
|
65
|
+
inputSchema: {
|
|
66
|
+
category: z
|
|
67
|
+
.string()
|
|
68
|
+
.optional()
|
|
69
|
+
.describe("Filter by category (e.g. 'Security', 'Development')"),
|
|
70
|
+
limit: z
|
|
71
|
+
.number()
|
|
72
|
+
.min(1)
|
|
73
|
+
.max(100)
|
|
74
|
+
.default(10)
|
|
75
|
+
.describe("Number of agents to return (default: 10)"),
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: "get_agent_history",
|
|
80
|
+
description: "Get the trust score history for an AI agent over time. Use this to see if an agent's trustworthiness is improving, declining, or stable.",
|
|
81
|
+
inputSchema: {
|
|
82
|
+
name: z.string().describe("The agent's name"),
|
|
83
|
+
limit: z
|
|
84
|
+
.number()
|
|
85
|
+
.min(1)
|
|
86
|
+
.max(90)
|
|
87
|
+
.default(30)
|
|
88
|
+
.describe("Number of historical data points (default: 30)"),
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
// --- Tool handlers ---
|
|
93
|
+
export async function handleTool(name, args) {
|
|
94
|
+
try {
|
|
95
|
+
switch (name) {
|
|
96
|
+
case "check_agent_trust": {
|
|
97
|
+
const agentName = args.name;
|
|
98
|
+
const threshold = args.threshold ?? 20;
|
|
99
|
+
if (!agentName?.trim()) {
|
|
100
|
+
return text("Agent name is required.", true);
|
|
101
|
+
}
|
|
102
|
+
const data = await fetchApi("/api/trust", {
|
|
103
|
+
name: agentName,
|
|
104
|
+
threshold: String(threshold),
|
|
105
|
+
});
|
|
106
|
+
return text(formatTrustCheck(data));
|
|
107
|
+
}
|
|
108
|
+
case "get_agent_score": {
|
|
109
|
+
const agentName = args.name;
|
|
110
|
+
if (!agentName?.trim()) {
|
|
111
|
+
return text("Agent name is required.", true);
|
|
112
|
+
}
|
|
113
|
+
const data = await fetchApi("/api/score", { name: agentName });
|
|
114
|
+
return text(formatScore(data));
|
|
115
|
+
}
|
|
116
|
+
case "compare_agents": {
|
|
117
|
+
const agents = args.agents;
|
|
118
|
+
if (!agents || agents.length < 2) {
|
|
119
|
+
return text("At least 2 agent names are required for comparison.", true);
|
|
120
|
+
}
|
|
121
|
+
if (agents.length > 5) {
|
|
122
|
+
return text("Maximum 5 agents can be compared at once.", true);
|
|
123
|
+
}
|
|
124
|
+
// Build URL with multiple agent params
|
|
125
|
+
const params = new URLSearchParams();
|
|
126
|
+
for (const a of agents)
|
|
127
|
+
params.append("agent", a);
|
|
128
|
+
const data = await fetchApi(`/api/compare?${params.toString()}`);
|
|
129
|
+
return text(formatCompare(data));
|
|
130
|
+
}
|
|
131
|
+
case "search_agents": {
|
|
132
|
+
const query = args.query;
|
|
133
|
+
const limit = args.limit ?? 10;
|
|
134
|
+
if (!query?.trim()) {
|
|
135
|
+
return text("Search query is required.", true);
|
|
136
|
+
}
|
|
137
|
+
const data = await fetchApi("/api/search", {
|
|
138
|
+
q: query,
|
|
139
|
+
limit: String(limit),
|
|
140
|
+
});
|
|
141
|
+
return text(formatSearch(data));
|
|
142
|
+
}
|
|
143
|
+
case "get_leaderboard": {
|
|
144
|
+
const category = args.category;
|
|
145
|
+
const limit = args.limit ?? 10;
|
|
146
|
+
const data = await fetchApi("/api/leaderboard");
|
|
147
|
+
return text(formatLeaderboard(data, category, limit));
|
|
148
|
+
}
|
|
149
|
+
case "get_agent_history": {
|
|
150
|
+
const agentName = args.name;
|
|
151
|
+
const limit = args.limit ?? 30;
|
|
152
|
+
if (!agentName?.trim()) {
|
|
153
|
+
return text("Agent name is required.", true);
|
|
154
|
+
}
|
|
155
|
+
const data = await fetchApi("/api/history", {
|
|
156
|
+
name: agentName,
|
|
157
|
+
limit: String(limit),
|
|
158
|
+
});
|
|
159
|
+
return text(formatHistory(data, agentName));
|
|
160
|
+
}
|
|
161
|
+
default:
|
|
162
|
+
return text(`Unknown tool: ${name}`, true);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
return handleApiError(err);
|
|
167
|
+
}
|
|
168
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentscore-xyz/mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for AgentScore — trust scoring for AI agents. Check agent reputation before transacting. No API key, zero config.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"agentscore-mcp": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsc --watch",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@types/node": "^20.0.0",
|
|
21
|
+
"typescript": "^5.4.0"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"mcp",
|
|
25
|
+
"mcp-server",
|
|
26
|
+
"agentscore",
|
|
27
|
+
"trust",
|
|
28
|
+
"ai-agents",
|
|
29
|
+
"reputation",
|
|
30
|
+
"verification",
|
|
31
|
+
"agent-trust",
|
|
32
|
+
"model-context-protocol"
|
|
33
|
+
],
|
|
34
|
+
"author": "AgentScore <hello@agentscores.xyz>",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"homepage": "https://agentscores.xyz",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/Thezenmonster/agentscores"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist/",
|
|
43
|
+
"README.md",
|
|
44
|
+
"smithery.yaml"
|
|
45
|
+
],
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=18"
|
|
48
|
+
}
|
|
49
|
+
}
|