ccs-mcp-server 1.1.0 → 1.1.2
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 +83 -62
- package/package.json +1 -1
- package/src/index.js +14 -4
package/README.md
CHANGED
|
@@ -1,107 +1,128 @@
|
|
|
1
1
|
# CCS Runtime Evidence MCP Server
|
|
2
2
|
|
|
3
|
-
A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that brings **CCS runtime verification** to any MCP-compatible client — Claude Desktop, Cursor, Windsurf,
|
|
3
|
+
A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that brings **CCS runtime verification** to any MCP-compatible client — Claude Desktop, Cursor, Windsurf, and more.
|
|
4
4
|
|
|
5
|
-
It verifies AI agent tool calls at runtime, blocks unsafe ones by default,
|
|
5
|
+
It verifies AI agent tool calls at runtime, blocks unsafe ones by default, issues **tamper-evident evidence records** for every decision, and verifies that actual tool arguments match the agent's declared intent — catching cross-model parameter drift.
|
|
6
6
|
|
|
7
|
-
> **
|
|
8
|
-
|
|
9
|
-
## Tools
|
|
10
|
-
|
|
11
|
-
| Tool | What it does |
|
|
12
|
-
|---|---|
|
|
13
|
-
| `verify_tool_call` | Verify a tool call across 7 CCS dimensions + semantic attack-chain analysis + math overflow detection. Returns `verdict: allowed/denied`. **Blocks by default.** |
|
|
14
|
-
| `issue_evidence` | Issue a cryptographically bound CCS evidence record (`content_hash` + `evidence_hash`) for a call. Independently verifiable. |
|
|
15
|
-
| `audit_mcp_config` | Audit an MCP configuration JSON for security risks: plain HTTP, weak secrets, disabled TLS, missing commands. |
|
|
7
|
+
> **Runtime evidence layer, not a static scanner.** Every decision is enforced at call time and produces independently verifiable cryptographic evidence.
|
|
16
8
|
|
|
17
9
|
## Quick Start
|
|
18
10
|
|
|
19
|
-
### Install and run with npx
|
|
20
|
-
|
|
21
11
|
```bash
|
|
22
|
-
npx
|
|
12
|
+
npx -y ccs-mcp-server
|
|
23
13
|
```
|
|
24
14
|
|
|
25
|
-
###
|
|
26
|
-
|
|
27
|
-
Add to your MCP client settings:
|
|
15
|
+
### MCP Client Configuration
|
|
28
16
|
|
|
29
17
|
```json
|
|
30
18
|
{
|
|
31
19
|
"mcpServers": {
|
|
32
20
|
"ccs-runtime-evidence": {
|
|
33
21
|
"command": "npx",
|
|
34
|
-
"args": ["-y", "
|
|
22
|
+
"args": ["-y", "ccs-mcp-server"]
|
|
35
23
|
}
|
|
36
24
|
}
|
|
37
25
|
}
|
|
38
26
|
```
|
|
39
27
|
|
|
40
|
-
|
|
28
|
+
Zero dependencies. 28KB. Pure Node.js stdlib. No install scripts.
|
|
29
|
+
|
|
30
|
+
## Tools
|
|
31
|
+
|
|
32
|
+
| Tool | Purpose |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `verify_tool_call` | 7-dimension runtime verification (Structure/Schema/Security/Identity/Integrity/Latency/Cost) + semantic attack-chain analysis + math overflow detection. **Blocks by default.** |
|
|
35
|
+
| `issue_evidence` | Issue a tamper-evident evidence record (`content_hash` + `evidence_hash`, chainable). Produced for allowed AND denied calls. |
|
|
36
|
+
| `audit_mcp_config` | Audit MCP configuration JSON for security risks. |
|
|
37
|
+
| `verify_intent_binding` | **(v1.1.0)** Verify actual tool arguments match a declared intent — zero tolerance, zero LLM calls. Catches cross-model parameter drift (planner says `amount: 100`, executor writes `amount: 10000` → DENIED). |
|
|
38
|
+
|
|
39
|
+
## Intent Binding — Cross-Model Drift Detection
|
|
40
|
+
|
|
41
|
+
Agent planners (Claude, GPT) declare one thing; executors (Qwen, DeepSeek) sometimes write another. No existing protocol verifies that actual tool call arguments match the agent's declared intent:
|
|
41
42
|
|
|
42
|
-
- **
|
|
43
|
-
- **
|
|
44
|
-
- **
|
|
45
|
-
- **
|
|
46
|
-
- **SQL injection**: UNION SELECT, `OR 1=1`, `DROP TABLE`
|
|
47
|
-
- **Attack chains**: multi-step combinations (e.g. path traversal + SSRF = exfiltration chain)
|
|
48
|
-
- **Math safety**: integer overflow (>2^53-1), NaN/Infinity, DoS strings
|
|
49
|
-
- **Caller identity**: agent ID verification against allowlist
|
|
50
|
-
- **Schema violations**: type, enum, range, required field checks
|
|
51
|
-
- **MCP config risks**: plain HTTP, weak secrets, `--insecure`, disabled TLS
|
|
43
|
+
- **AP2** signs human authorization — not LLM intent
|
|
44
|
+
- **AgentPay** does baseline tolerance (1%) — not zero-tolerance equivalence
|
|
45
|
+
- **ACS** runs policy decisions — not argument-level equivalence
|
|
46
|
+
- **VAP** (draft-samal-vap-00) explicitly excludes argument semantics from its wire schema
|
|
52
47
|
|
|
53
|
-
|
|
48
|
+
CCS Intent Binding fills this layer. The agent framework declares a structured intent before execution; CCS verifies actual arguments against it in sub-millisecond, zero-LLM time.
|
|
54
49
|
|
|
55
|
-
|
|
50
|
+
### Example: amount drift
|
|
56
51
|
|
|
57
52
|
```json
|
|
53
|
+
// Intent declared by planner
|
|
58
54
|
{
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
"mode": "block",
|
|
65
|
-
"params_hash": "sha256:...",
|
|
66
|
-
"policy_hash": "sha256:...",
|
|
67
|
-
"content_hash": "sha256:...",
|
|
68
|
-
"evidence_hash": "sha256:...",
|
|
69
|
-
"dimensions": {
|
|
70
|
-
"Structure": {"status": "pass"},
|
|
71
|
-
"Schema": {"status": "pass"},
|
|
72
|
-
"Security": {"status": "fail", "reason": "cmd: command_injection; cmd: path_traversal; cmd: ssrf"},
|
|
73
|
-
"Identity": {"status": "pass"}
|
|
55
|
+
"intent_id": "int-001",
|
|
56
|
+
"intent_type": "payment",
|
|
57
|
+
"fields": {
|
|
58
|
+
"amount": { "value": 100, "binding_mode": "exact" },
|
|
59
|
+
"recipient": { "value": "Alice", "binding_mode": "exact" }
|
|
74
60
|
},
|
|
75
|
-
"
|
|
76
|
-
|
|
77
|
-
"semantic_severity": "critical"
|
|
78
|
-
},
|
|
79
|
-
"issued_at": "2026-08-22T12:00:00.000Z"
|
|
61
|
+
"issued_at": 1755000000000,
|
|
62
|
+
"ttl_ms": 30000
|
|
80
63
|
}
|
|
64
|
+
|
|
65
|
+
// Actual arguments from executor
|
|
66
|
+
{ "amount": 10000, "recipient": "Alice" }
|
|
67
|
+
|
|
68
|
+
// Result: DENIED — intent_arg_mismatch
|
|
69
|
+
// field: amount, expected: 100, actual: 10000
|
|
81
70
|
```
|
|
82
71
|
|
|
83
|
-
|
|
72
|
+
### Three binding modes
|
|
73
|
+
|
|
74
|
+
| Mode | Behavior | Example |
|
|
75
|
+
|------|----------|---------|
|
|
76
|
+
| `exact` | Deep equality with math normalization | `100`, `100.0`, `1e2` all match; `10000` does not |
|
|
77
|
+
| `numeric_tolerance` | Absolute tolerance | `100 ± 0.01` matches `100.005` |
|
|
78
|
+
| `pattern` | Regex match on string fields | `^[A-Z]{3}$` matches `"USD"` |
|
|
79
|
+
|
|
80
|
+
No intent declared? Falls through to standard 7-dimension verification. Zero breaking changes.
|
|
81
|
+
|
|
82
|
+
## What It Detects
|
|
84
83
|
|
|
85
|
-
|
|
84
|
+
- **Command injection**: shell metacharacters, `curl|sh`, `rm -rf`, `eval()`
|
|
85
|
+
- **Path traversal**: `../`, `/etc/passwd`, `/proc/self/`
|
|
86
|
+
- **SSRF**: `169.254.169.254` (cloud metadata), localhost, private ranges — across any tool
|
|
87
|
+
- **Cross-tool attack chains**: read sensitive file → network exfil = `exfil_chain`
|
|
88
|
+
- **Environment variable exfiltration**: API keys, secrets, credentials
|
|
89
|
+
- **Obfuscation**: hex encoding, base64, privilege escalation signals
|
|
90
|
+
- **Math safety**: integer overflow (>2^53-1), NaN/Infinity
|
|
91
|
+
- **MCP config risks**: plain HTTP, weak secrets, `--insecure`, TLS disabled
|
|
86
92
|
|
|
87
|
-
|
|
93
|
+
## Evidence Chain
|
|
94
|
+
|
|
95
|
+
Every decision produces evidence with dual hashes (`content_hash` + `evidence_hash`) and chain linkage (`parent_evidence_hash`). Any third party can independently verify that evidence has not been tampered with — without trusting the operator.
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
evidence 1: allowed (fs.read_file) parent: null
|
|
99
|
+
evidence 2: denied (shell.exec curl|sh) parent: ev1
|
|
100
|
+
evidence 3: denied (http.fetch SSRF) parent: ev2
|
|
101
|
+
evidence 4: denied (fs + curl exfil) parent: ev3
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## The 7 CCS Dimensions
|
|
88
105
|
|
|
89
106
|
1. **Structure** — valid tool name, argument format, nesting depth, payload size
|
|
90
107
|
2. **Schema** — type, required fields, enums, ranges, string lengths
|
|
91
|
-
3. **Security** — injection, traversal, SSRF,
|
|
108
|
+
3. **Security** — injection, traversal, SSRF, env exfiltration, obfuscation + semantic attack chains
|
|
92
109
|
4. **Identity** — caller agent ID verification
|
|
93
110
|
5. **Integrity** — request hash validation
|
|
94
|
-
6. **Latency** — execution time budget
|
|
95
|
-
7. **Cost** — cost budget
|
|
111
|
+
6. **Latency** — execution time budget
|
|
112
|
+
7. **Cost** — cost budget
|
|
113
|
+
|
|
114
|
+
## Protocol Context
|
|
96
115
|
|
|
97
|
-
|
|
116
|
+
- **IETF**: [draft-correctover-ccs-06](https://datatracker.ietf.org/doc/draft-correctover-ccs/) (Experimental) — RT#55620 submitted
|
|
117
|
+
- **Complements**: [VAP draft-samal-vap-00](https://datatracker.ietf.org/doc/draft-samal-vap/) (scope/budget/purpose), [Microsoft ACS](https://github.com/microsoft/agent-governance-toolkit) (policy decisions), AP2 (human authorization)
|
|
118
|
+
- **Does not replace**: authentication, payment networks, policy engines
|
|
98
119
|
|
|
99
120
|
## Links
|
|
100
121
|
|
|
101
|
-
- npm: https://www.npmjs.com/package
|
|
102
|
-
-
|
|
103
|
-
- IETF Draft: https://
|
|
104
|
-
-
|
|
122
|
+
- npm: https://www.npmjs.com/package/ccs-mcp-server
|
|
123
|
+
- GitHub: https://github.com/Correctover/ccs-mcp-server
|
|
124
|
+
- IETF Draft: https://datatracker.ietf.org/doc/draft-correctover-ccs/
|
|
125
|
+
- PyPI (full verifier): https://pypi.org/project/ccs-verifier/
|
|
105
126
|
|
|
106
127
|
## License
|
|
107
128
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccs-mcp-server",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "CCS Runtime Evidence MCP Server — verify AI agent tool calls, issue tamper-evident evidence, audit MCP configs, and bind execution to declared intent (cross-model amount drift protection). For Claude Desktop, Cursor, Windsurf, and any MCP client.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"bin": {
|
package/src/index.js
CHANGED
|
@@ -31,7 +31,7 @@ const readline = require("readline");
|
|
|
31
31
|
// CCS Verifier Core (pure stdlib Node.js)
|
|
32
32
|
// ---------------------------------------------------------------------------
|
|
33
33
|
|
|
34
|
-
const CCS_VERSION = "1.1.
|
|
34
|
+
const CCS_VERSION = "1.1.2";
|
|
35
35
|
|
|
36
36
|
const DEFAULT_POLICY = {
|
|
37
37
|
mode: "block",
|
|
@@ -337,12 +337,17 @@ function deepEqual(a, b) {
|
|
|
337
337
|
}
|
|
338
338
|
|
|
339
339
|
function verifyIntentBinding(intent, toolName, toolArgs, now = Date.now()) {
|
|
340
|
+
const intentHash = "sha256:" + crypto.createHash("sha256").update(canonical(intent)).digest("hex");
|
|
341
|
+
const argsHash = "sha256:" + crypto.createHash("sha256").update(canonical(toolArgs)).digest("hex");
|
|
342
|
+
|
|
340
343
|
// 1. TTL check
|
|
341
344
|
if (intent.ttl_ms != null && now - intent.issued_at > intent.ttl_ms) {
|
|
342
345
|
return {
|
|
343
346
|
allowed: false,
|
|
344
347
|
reason: { type: "intent_expired", expected: intent.issued_at + intent.ttl_ms, actual: now },
|
|
345
|
-
intent_hash:
|
|
348
|
+
intent_hash: intentHash,
|
|
349
|
+
args_hash: argsHash,
|
|
350
|
+
tool: toolName,
|
|
346
351
|
};
|
|
347
352
|
}
|
|
348
353
|
|
|
@@ -372,14 +377,18 @@ function verifyIntentBinding(intent, toolName, toolArgs, now = Date.now()) {
|
|
|
372
377
|
field, binding_mode: mode,
|
|
373
378
|
expected, actual,
|
|
374
379
|
},
|
|
375
|
-
intent_hash:
|
|
380
|
+
intent_hash: intentHash,
|
|
381
|
+
args_hash: argsHash,
|
|
382
|
+
tool: toolName,
|
|
376
383
|
};
|
|
377
384
|
}
|
|
378
385
|
}
|
|
379
386
|
|
|
380
387
|
return {
|
|
381
388
|
allowed: true,
|
|
382
|
-
intent_hash:
|
|
389
|
+
intent_hash: intentHash,
|
|
390
|
+
args_hash: argsHash,
|
|
391
|
+
tool: toolName,
|
|
383
392
|
};
|
|
384
393
|
}
|
|
385
394
|
|
|
@@ -517,6 +526,7 @@ function handleRequest(req) {
|
|
|
517
526
|
allowed: verdict.allowed,
|
|
518
527
|
intent_id: args.intent.intent_id,
|
|
519
528
|
intent_hash: verdict.intent_hash,
|
|
529
|
+
args_hash: verdict.args_hash,
|
|
520
530
|
tool: args.tool,
|
|
521
531
|
...(verdict.reason ? { reason: verdict.reason } : {}),
|
|
522
532
|
blocked: !verdict.allowed,
|