@polygraphso/litmus 0.8.0 → 0.8.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/README.md +17 -4
- package/dist/{chunk-LBXHFQN3.js → chunk-BPS4YCDL.js} +59 -28
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1 -1
- package/dist/mcp.js +1 -1
- package/package.json +4 -5
package/README.md
CHANGED
|
@@ -61,9 +61,9 @@ MCP-capable client. It exposes two tools:
|
|
|
61
61
|
It also registers two **prompts** that show up as slash commands — in Claude Code,
|
|
62
62
|
`/mcp__polygraph-litmus__grade <server_ref>` (run a fresh grade) and
|
|
63
63
|
`/mcp__polygraph-litmus__check <server_ref>` (read a published grade); other
|
|
64
|
-
clients surface the same prompts in their own UI.
|
|
65
|
-
Claude Code
|
|
66
|
-
|
|
64
|
+
clients surface the same prompts in their own UI. For a cleaner pair of commands
|
|
65
|
+
in Claude Code — `/polygraph:grade` and `/polygraph:check` — install the plugin
|
|
66
|
+
(below), which wires up this server and both commands in one step.
|
|
67
67
|
|
|
68
68
|
**Prerequisites:** Node ≥ 18. Docker is optional (without it, C-02 egress is
|
|
69
69
|
skipped and the grade caps at B). Set `POLYGRAPH_API_URL=https://polygraph.so` so
|
|
@@ -73,7 +73,20 @@ skipped and the grade caps at B). Set `POLYGRAPH_API_URL=https://polygraph.so` s
|
|
|
73
73
|
> commonly returns `not_available` today — that means *unevaluated*, not a failing
|
|
74
74
|
> grade. To grade a server right now, use `run_litmus`.
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
### Claude Code: one-click plugin (recommended)
|
|
77
|
+
|
|
78
|
+
The plugin bundles this MCP server **and** adds the `/polygraph:grade` and
|
|
79
|
+
`/polygraph:check` commands — one install does everything:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
/plugin marketplace add polygraphso/litmus
|
|
83
|
+
/plugin install polygraph@polygraphso
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Then just run `/polygraph:grade npm/@modelcontextprotocol/server-filesystem`.
|
|
87
|
+
|
|
88
|
+
Prefer to wire the server up by hand, or using another client? Add it once, then
|
|
89
|
+
just talk to your agent.
|
|
77
90
|
|
|
78
91
|
**Claude Code** — one command:
|
|
79
92
|
|
|
@@ -38,16 +38,43 @@ function rpcUrl(net = selectedNetwork()) {
|
|
|
38
38
|
return override && override.length > 0 ? override : NETWORKS[net].rpc;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
// ../onchain/src/eas-sdk.ts
|
|
42
|
-
import { createRequire } from "module";
|
|
43
|
-
var require2 = createRequire(import.meta.url);
|
|
44
|
-
var sdk = require2(
|
|
45
|
-
"@ethereum-attestation-service/eas-sdk"
|
|
46
|
-
);
|
|
47
|
-
var { EAS, SchemaEncoder, SchemaRegistry } = sdk;
|
|
48
|
-
|
|
49
41
|
// ../onchain/src/eas.ts
|
|
42
|
+
import { AbiCoder } from "ethers";
|
|
50
43
|
var LITMUS_SCHEMA = "string serverRef,bytes32 toolDefsFingerprint,uint8 gradeC01,uint8 gradeC02,uint8 gradeC03,string overallGrade,string reportCID,string methodologyVersion,uint64 ranAt,string resolvedVersion";
|
|
44
|
+
var LITMUS_ABI_TYPES = [
|
|
45
|
+
"string",
|
|
46
|
+
// serverRef
|
|
47
|
+
"bytes32",
|
|
48
|
+
// toolDefsFingerprint
|
|
49
|
+
"uint8",
|
|
50
|
+
// gradeC01
|
|
51
|
+
"uint8",
|
|
52
|
+
// gradeC02
|
|
53
|
+
"uint8",
|
|
54
|
+
// gradeC03
|
|
55
|
+
"string",
|
|
56
|
+
// overallGrade
|
|
57
|
+
"string",
|
|
58
|
+
// reportCID
|
|
59
|
+
"string",
|
|
60
|
+
// methodologyVersion
|
|
61
|
+
"uint64",
|
|
62
|
+
// ranAt
|
|
63
|
+
"string"
|
|
64
|
+
// resolvedVersion
|
|
65
|
+
];
|
|
66
|
+
var LITMUS_ABI_NAMES = [
|
|
67
|
+
"serverRef",
|
|
68
|
+
"toolDefsFingerprint",
|
|
69
|
+
"gradeC01",
|
|
70
|
+
"gradeC02",
|
|
71
|
+
"gradeC03",
|
|
72
|
+
"overallGrade",
|
|
73
|
+
"reportCID",
|
|
74
|
+
"methodologyVersion",
|
|
75
|
+
"ranAt",
|
|
76
|
+
"resolvedVersion"
|
|
77
|
+
];
|
|
51
78
|
function categoryUint8(bundle, code) {
|
|
52
79
|
const status = bundle.categories.find((c) => c.code === code)?.status;
|
|
53
80
|
return status ? CATEGORY_STATUS_UINT8[status] : CATEGORY_STATUS_UINT8.skipped;
|
|
@@ -68,31 +95,36 @@ function litmusFields(bundle, reportCID) {
|
|
|
68
95
|
}
|
|
69
96
|
function encodeLitmusAttestation(bundle, reportCID) {
|
|
70
97
|
const f = litmusFields(bundle, reportCID);
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
98
|
+
return AbiCoder.defaultAbiCoder().encode(
|
|
99
|
+
[...LITMUS_ABI_TYPES],
|
|
100
|
+
[
|
|
101
|
+
f.serverRef,
|
|
102
|
+
f.toolDefsFingerprint,
|
|
103
|
+
f.gradeC01,
|
|
104
|
+
f.gradeC02,
|
|
105
|
+
f.gradeC03,
|
|
106
|
+
f.overallGrade,
|
|
107
|
+
f.reportCID,
|
|
108
|
+
f.methodologyVersion,
|
|
109
|
+
f.ranAt,
|
|
110
|
+
f.resolvedVersion
|
|
111
|
+
]
|
|
112
|
+
);
|
|
84
113
|
}
|
|
85
114
|
function decodeLitmusAttestation(encoded) {
|
|
86
|
-
const
|
|
115
|
+
const values = AbiCoder.defaultAbiCoder().decode([...LITMUS_ABI_TYPES], encoded);
|
|
87
116
|
const out = {};
|
|
88
|
-
|
|
89
|
-
out[
|
|
90
|
-
}
|
|
117
|
+
LITMUS_ABI_NAMES.forEach((name, i) => {
|
|
118
|
+
out[name] = values[i];
|
|
119
|
+
});
|
|
91
120
|
return out;
|
|
92
121
|
}
|
|
93
122
|
|
|
94
123
|
// ../onchain/src/read.ts
|
|
95
|
-
import { JsonRpcProvider, ZeroHash } from "ethers";
|
|
124
|
+
import { Contract, JsonRpcProvider, ZeroHash } from "ethers";
|
|
125
|
+
var EAS_ABI = [
|
|
126
|
+
"function getAttestation(bytes32 uid) view returns ((bytes32 uid, bytes32 schema, uint64 time, uint64 expirationTime, uint64 revocationTime, bytes32 refUID, address recipient, address attester, bool revocable, bytes data))"
|
|
127
|
+
];
|
|
96
128
|
function litmusSchemaUID() {
|
|
97
129
|
const uid = process.env.NEXT_PUBLIC_EAS_SCHEMA_UID;
|
|
98
130
|
if (!uid) throw new Error("NEXT_PUBLIC_EAS_SCHEMA_UID is required \u2014 register the schema first.");
|
|
@@ -101,8 +133,7 @@ function litmusSchemaUID() {
|
|
|
101
133
|
async function readAttestation(uid) {
|
|
102
134
|
const cfg = networkConfig();
|
|
103
135
|
const provider = new JsonRpcProvider(rpcUrl(), cfg.chainId);
|
|
104
|
-
const eas = new
|
|
105
|
-
eas.connect(provider);
|
|
136
|
+
const eas = new Contract(cfg.eas, EAS_ABI, provider);
|
|
106
137
|
const att = await eas.getAttestation(uid);
|
|
107
138
|
if (!att || att.uid === ZeroHash) return null;
|
|
108
139
|
if (String(att.schema).toLowerCase() !== litmusSchemaUID().toLowerCase()) return null;
|
package/dist/index.d.ts
CHANGED
|
@@ -494,7 +494,10 @@ declare function decodeLitmusAttestation(encoded: string): Record<string, unknow
|
|
|
494
494
|
* §7). Needs an RPC + a registered schema; the agent-gate calls this, then
|
|
495
495
|
* re-checks the live fingerprint before paying.
|
|
496
496
|
*
|
|
497
|
-
*
|
|
497
|
+
* The read is a single EAS `getAttestation` view call. We hit the contract
|
|
498
|
+
* directly through a minimal ethers ABI fragment (below) rather than the
|
|
499
|
+
* eas-sdk `EAS` class — same on-chain struct, one fewer dependency (eas-sdk
|
|
500
|
+
* dragged hardhat into the production tree).
|
|
498
501
|
*/
|
|
499
502
|
/** The registered litmus schema UID for the selected network (from env). */
|
|
500
503
|
declare function litmusSchemaUID(): string;
|
package/dist/index.js
CHANGED
package/dist/mcp.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polygraphso/litmus",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Behavioral litmus harness for MCP servers — grade a server A–F (tool-output injection, egress, sensitive-data, adversarial-input) with reproducible, content-addressed evidence. Ships a CLI and an MCP server with a run_litmus tool for AI agents.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://polygraph.so",
|
|
@@ -52,7 +52,6 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
55
|
-
"@ethereum-attestation-service/eas-sdk": "^2.9.1",
|
|
56
55
|
"ethers": "^6.16.0",
|
|
57
56
|
"zod": "^3.23.8",
|
|
58
57
|
"tsx": "^4.19.0"
|
|
@@ -63,11 +62,11 @@
|
|
|
63
62
|
"typescript": "^5.9.3",
|
|
64
63
|
"vitest": "^2.1.0",
|
|
65
64
|
"@polygraph/core": "0.0.0",
|
|
66
|
-
"@polygraph/probes": "0.0.0",
|
|
67
65
|
"@polygraph/onchain": "0.0.0",
|
|
66
|
+
"@polygraph/agent": "0.0.0",
|
|
67
|
+
"@polygraph/probes": "0.0.0",
|
|
68
68
|
"@polygraph/mcp": "0.0.0",
|
|
69
|
-
"@polygraph/cli": "0.0.0"
|
|
70
|
-
"@polygraph/agent": "0.0.0"
|
|
69
|
+
"@polygraph/cli": "0.0.0"
|
|
71
70
|
},
|
|
72
71
|
"publishConfig": {
|
|
73
72
|
"access": "public"
|