ccs-mcp-server 1.0.0 → 1.1.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.
Files changed (3) hide show
  1. package/README.md +83 -62
  2. package/package.json +7 -3
  3. package/src/index.js +141 -1
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, ChatGPT apps, and more.
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, and issues **tamper-evident evidence records** for every call (allowed and denied).
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
- > **This is a runtime enforcement layer, not a static scanner.** It runs on every live tool call not once on source code.
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 @correctover/ccs-mcp-server
12
+ npx -y ccs-mcp-server
23
13
  ```
24
14
 
25
- ### Claude Desktop / Cursor configuration
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", "@correctover/ccs-mcp-server"]
22
+ "args": ["-y", "ccs-mcp-server"]
35
23
  }
36
24
  }
37
25
  }
38
26
  ```
39
27
 
40
- ## What it detects
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
- - **Command injection**: shell metacharacters, `$()`, backticks, dangerous commands
43
- - **Path traversal**: `../`, `/etc/passwd`, `/proc/self/`, Windows system paths
44
- - **SSRF**: localhost, link-local (169.254.x.x), private IP ranges
45
- - **Prompt injection**: "ignore previous instructions", system prompt extraction, special tokens
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
- ## Evidence format
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
- Every call produces evidence like:
50
+ ### Example: amount drift
56
51
 
57
52
  ```json
53
+ // Intent declared by planner
58
54
  {
59
- "evidence_type": "ccs.tool_call.verification",
60
- "evidence_id": "uuid-v4",
61
- "tool": "shell.exec",
62
- "caller": "agent-001",
63
- "verdict": "denied",
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
- "semantic_analysis": {
76
- "attack_chains": [{"chain": "exfil_chain", "severity": "critical"}],
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
- The dual-hash design (`content_hash` + `evidence_hash`) means any tampering is detectable by any third party.
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
- ## About CCS
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
- CCS (Correctover Conformance Shape) is a 7-dimension runtime verification standard for AI agent tool calls:
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, prompt injection, SQL injection
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 (warn)
95
- 7. **Cost** — cost budget (warn)
111
+ 6. **Latency** — execution time budget
112
+ 7. **Cost** — cost budget
113
+
114
+ ## Protocol Context
96
115
 
97
- Plus: semantic intent analysis (attack chains, obfuscation signals, privilege escalation) and mathematical verification (overflow, NaN, DoS).
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/@correctover/ccs-mcp-server
102
- - Website: https://correctover.com
103
- - IETF Draft: https://www.ietf.org/archive/id/draft-correctover-ccs-05.txt
104
- - SkillHub: https://skillhub.cn
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,13 +1,17 @@
1
1
  {
2
2
  "name": "ccs-mcp-server",
3
- "version": "1.0.0",
4
- "description": "CCS Runtime Evidence MCP Server — verify AI agent tool calls, issue tamper-evident evidence, audit MCP configs. For Claude Desktop, Cursor, Windsurf, and any MCP client.",
3
+ "version": "1.1.1",
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": {
7
7
  "ccs-mcp-server": "src/index.js"
8
8
  },
9
9
  "main": "src/index.js",
10
- "files": ["src", "README.md", "LICENSE"],
10
+ "files": [
11
+ "src",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
11
15
  "keywords": [
12
16
  "mcp",
13
17
  "model-context-protocol",
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.0.0";
34
+ const CCS_VERSION = "1.1.1";
35
35
 
36
36
  const DEFAULT_POLICY = {
37
37
  mode: "block",
@@ -307,6 +307,91 @@ function auditMcpConfig(config) {
307
307
  issues.length ? "medium" : "low" };
308
308
  }
309
309
 
310
+ // ---------------------------------------------------------------------------
311
+ // Intent Binding (L4) — zero-LLM, deterministic, microsecond
312
+ // ---------------------------------------------------------------------------
313
+ // Agent framework declares structured intent before tool execution.
314
+ // CCS verifies actual args match declared intent with zero tolerance.
315
+ // This catches cross-model amount drift (planner says 100, executor writes 10000)
316
+ // without any NLP or LLM call.
317
+
318
+ function deepEqual(a, b) {
319
+ if (a === b) return true;
320
+ if (typeof a !== typeof b) {
321
+ // numeric normalization: 100 == 100.0 == 1e2
322
+ if (typeof a === "number" && typeof b === "string") {
323
+ const n = Number(b);
324
+ return Number.isFinite(n) && a === n;
325
+ }
326
+ if (typeof b === "number" && typeof a === "string") {
327
+ const n = Number(a);
328
+ return Number.isFinite(n) && b === n;
329
+ }
330
+ return false;
331
+ }
332
+ if (typeof a !== "object" || a === null || b === null) return false;
333
+ if (Array.isArray(a) !== Array.isArray(b)) return false;
334
+ const ka = Object.keys(a), kb = Object.keys(b);
335
+ if (ka.length !== kb.length) return false;
336
+ return ka.every((k) => deepEqual(a[k], b[k]));
337
+ }
338
+
339
+ function verifyIntentBinding(intent, toolName, toolArgs, now = Date.now()) {
340
+ const intentHash = crypto.createHash("sha256").update(canonical(intent)).digest("hex");
341
+ const argsHash = crypto.createHash("sha256").update(canonical(toolArgs)).digest("hex");
342
+
343
+ // 1. TTL check
344
+ if (intent.ttl_ms != null && now - intent.issued_at > intent.ttl_ms) {
345
+ return {
346
+ allowed: false,
347
+ reason: { type: "intent_expired", expected: intent.issued_at + intent.ttl_ms, actual: now },
348
+ intent_hash: intentHash,
349
+ args_hash: argsHash,
350
+ tool: toolName,
351
+ };
352
+ }
353
+
354
+ // 2. Field-by-field comparison
355
+ const fields = intent.fields || {};
356
+ for (const [field, spec] of Object.entries(fields)) {
357
+ const actual = toolArgs[field];
358
+ const expected = spec.value;
359
+ const mode = spec.binding_mode || "exact";
360
+ let match = false;
361
+ if (mode === "exact") {
362
+ match = deepEqual(expected, actual);
363
+ } else if (mode === "numeric_tolerance") {
364
+ if (typeof expected === "number" && typeof actual === "number") {
365
+ match = Math.abs(expected - actual) <= (spec.tolerance || 0);
366
+ }
367
+ } else if (mode === "pattern") {
368
+ if (typeof actual === "string") {
369
+ try { match = new RegExp(spec.pattern).test(actual); } catch { match = false; }
370
+ }
371
+ }
372
+ if (!match) {
373
+ return {
374
+ allowed: false,
375
+ reason: {
376
+ type: "intent_arg_mismatch",
377
+ field, binding_mode: mode,
378
+ expected, actual,
379
+ },
380
+ intent_hash: intentHash,
381
+ args_hash: argsHash,
382
+ tool: toolName,
383
+ };
384
+ }
385
+ }
386
+
387
+ return {
388
+ allowed: true,
389
+ intent_hash: intentHash,
390
+ args_hash: argsHash,
391
+ tool: toolName,
392
+ };
393
+ }
394
+
310
395
  // ---------------------------------------------------------------------------
311
396
  // MCP Protocol (stdio JSON-RPC 2.0)
312
397
  // ---------------------------------------------------------------------------
@@ -357,6 +442,44 @@ const TOOLS = [
357
442
  required: ["config"],
358
443
  },
359
444
  },
445
+ {
446
+ name: "verify_intent_binding",
447
+ description: "Verify that actual tool call arguments match a declared intent with zero tolerance. Catches cross-model parameter drift (planner says amount=100, executor writes amount=10000). No LLM needed — pure deterministic comparison. Supports exact match, numeric tolerance, and regex pattern binding modes.",
448
+ inputSchema: {
449
+ type: "object",
450
+ properties: {
451
+ intent: {
452
+ type: "object",
453
+ description: "Structured intent declaration from the agent framework",
454
+ properties: {
455
+ intent_id: { type: "string", description: "Unique intent identifier (UUID v7 recommended)" },
456
+ intent_type: { type: "string", description: "e.g. payment, file_write, api_call" },
457
+ fields: {
458
+ type: "object",
459
+ description: "Map of field name to binding specification",
460
+ additionalProperties: {
461
+ type: "object",
462
+ properties: {
463
+ value: { description: "Expected value" },
464
+ binding_mode: { type: "string", enum: ["exact", "numeric_tolerance", "pattern"] },
465
+ tolerance: { type: "number", description: "Tolerance for numeric_tolerance mode" },
466
+ pattern: { type: "string", description: "Regex for pattern mode" },
467
+ },
468
+ required: ["value"],
469
+ },
470
+ },
471
+ issued_at: { type: "integer", description: "Unix ms when intent was issued" },
472
+ ttl_ms: { type: "integer", description: "Time-to-live in ms (default 30000)" },
473
+ evidence_ref: { type: "string", description: "Optional hash of external evidence (invoice, authorization VC)" },
474
+ },
475
+ required: ["intent_id", "intent_type", "fields", "issued_at"],
476
+ },
477
+ tool: { type: "string", description: "Tool being called, e.g. payments.send" },
478
+ arguments: { type: "object", description: "Actual tool call arguments", additionalProperties: true },
479
+ },
480
+ required: ["intent", "tool", "arguments"],
481
+ },
482
+ },
360
483
  ];
361
484
 
362
485
  function handleRequest(req) {
@@ -396,6 +519,23 @@ function handleRequest(req) {
396
519
  } else if (name === "audit_mcp_config") {
397
520
  const report = auditMcpConfig(args.config || {});
398
521
  result = { content: [{ type: "text", text: JSON.stringify(report, null, 2) }] };
522
+ } else if (name === "verify_intent_binding") {
523
+ const verdict = verifyIntentBinding(args.intent, args.tool, args.arguments || {});
524
+ result = {
525
+ content: [{ type: "text", text: JSON.stringify({
526
+ allowed: verdict.allowed,
527
+ intent_id: args.intent.intent_id,
528
+ intent_hash: verdict.intent_hash,
529
+ args_hash: verdict.args_hash,
530
+ tool: args.tool,
531
+ ...(verdict.reason ? { reason: verdict.reason } : {}),
532
+ blocked: !verdict.allowed,
533
+ message: verdict.allowed
534
+ ? "Intent binding verified — actual arguments match declared intent"
535
+ : `Intent binding DENIED: ${verdict.reason?.type}`,
536
+ }, null, 2) }],
537
+ isError: !verdict.allowed,
538
+ };
399
539
  } else {
400
540
  result = { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
401
541
  }