soulprint-mcp 0.1.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/dist/index.d.ts +79 -0
- package/dist/index.js +149 -0
- package/package.json +51 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { SoulprintToken, TrustLevel, CredentialType } from "soulprint-core";
|
|
2
|
+
export interface SoulprintOptions {
|
|
3
|
+
/** Trust score minimum (0-100). Default: 40 */
|
|
4
|
+
minScore?: number;
|
|
5
|
+
/** Required trust level. If set, overrides minScore for level check. */
|
|
6
|
+
minLevel?: TrustLevel;
|
|
7
|
+
/** Required credentials. All must be present. */
|
|
8
|
+
require?: CredentialType | CredentialType[];
|
|
9
|
+
/** Custom rejection message */
|
|
10
|
+
rejectMessage?: string;
|
|
11
|
+
/** Called when a valid token is found (for logging, analytics, etc.) */
|
|
12
|
+
onVerified?: (token: SoulprintToken) => void;
|
|
13
|
+
/** Called when a request is rejected */
|
|
14
|
+
onRejected?: (reason: string) => void;
|
|
15
|
+
}
|
|
16
|
+
export declare function verifySPT(spt: string | undefined | null, opts?: SoulprintOptions): {
|
|
17
|
+
allowed: boolean;
|
|
18
|
+
token?: SoulprintToken;
|
|
19
|
+
reason?: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* soulprint() — MCP middleware for identity verification.
|
|
23
|
+
*
|
|
24
|
+
* USAGE (MCP Server SDK):
|
|
25
|
+
*
|
|
26
|
+
* ```typescript
|
|
27
|
+
* import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
28
|
+
* import { soulprint } from "soulprint-mcp";
|
|
29
|
+
*
|
|
30
|
+
* const server = new McpServer({ name: "my-server", version: "1.0" });
|
|
31
|
+
* server.use(soulprint({ minScore: 60 }));
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* The token is read from the MCP client's capabilities:
|
|
35
|
+
* ```json
|
|
36
|
+
* { "capabilities": { "identity": { "soulprint": "<SPT>" } } }
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* Or from the HTTP header: X-Soulprint: <SPT>
|
|
40
|
+
*/
|
|
41
|
+
export declare function soulprint(opts?: SoulprintOptions): {
|
|
42
|
+
onCallTool(context: MCPContext, next: () => Promise<any>): Promise<any>;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* verifyRequest() — verify a Soulprint token from any MCP request object.
|
|
46
|
+
* Use this if you prefer manual verification over middleware.
|
|
47
|
+
*
|
|
48
|
+
* ```typescript
|
|
49
|
+
* const identity = verifyRequest(request, { minScore: 60 });
|
|
50
|
+
* if (!identity) return { error: "Unverified bot" };
|
|
51
|
+
* console.log(identity.score, identity.nullifier);
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare function verifyRequest(request: {
|
|
55
|
+
meta?: any;
|
|
56
|
+
clientCapabilities?: any;
|
|
57
|
+
}, opts?: SoulprintOptions): SoulprintToken | null;
|
|
58
|
+
/**
|
|
59
|
+
* getSoulprint() — get the verified token from context (after middleware ran).
|
|
60
|
+
*
|
|
61
|
+
* ```typescript
|
|
62
|
+
* server.tool("my-tool", async (args, context) => {
|
|
63
|
+
* const identity = getSoulprint(context);
|
|
64
|
+
* console.log(identity.nullifier); // unique per human
|
|
65
|
+
* });
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare function getSoulprint(context: any): SoulprintToken | undefined;
|
|
69
|
+
interface MCPContext {
|
|
70
|
+
clientCapabilities?: {
|
|
71
|
+
identity?: {
|
|
72
|
+
soulprint?: string;
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
meta?: {
|
|
76
|
+
headers?: Record<string, string>;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
export { decodeToken, SoulprintToken, TrustLevel, CredentialType } from "soulprint-core";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decodeToken = void 0;
|
|
4
|
+
exports.verifySPT = verifySPT;
|
|
5
|
+
exports.soulprint = soulprint;
|
|
6
|
+
exports.verifyRequest = verifyRequest;
|
|
7
|
+
exports.getSoulprint = getSoulprint;
|
|
8
|
+
const soulprint_core_1 = require("soulprint-core");
|
|
9
|
+
const LEVEL_SCORES = {
|
|
10
|
+
Unverified: 0,
|
|
11
|
+
EmailVerified: 10,
|
|
12
|
+
PhoneVerified: 25,
|
|
13
|
+
KYCLite: 45,
|
|
14
|
+
KYCFull: 80,
|
|
15
|
+
};
|
|
16
|
+
// ── Core verification logic ───────────────────────────────────────────────────
|
|
17
|
+
function verifySPT(spt, opts = {}) {
|
|
18
|
+
if (!spt) {
|
|
19
|
+
const r = { allowed: false, reason: "No Soulprint token provided" };
|
|
20
|
+
opts.onRejected?.(r.reason);
|
|
21
|
+
return r;
|
|
22
|
+
}
|
|
23
|
+
const token = (0, soulprint_core_1.decodeToken)(spt);
|
|
24
|
+
if (!token) {
|
|
25
|
+
const r = { allowed: false, reason: "Invalid or expired Soulprint token" };
|
|
26
|
+
opts.onRejected?.(r.reason);
|
|
27
|
+
return r;
|
|
28
|
+
}
|
|
29
|
+
const minScore = opts.minScore ?? 40;
|
|
30
|
+
if (token.score < minScore) {
|
|
31
|
+
const r = { allowed: false, reason: `Trust score too low: ${token.score} < ${minScore}` };
|
|
32
|
+
opts.onRejected?.(r.reason);
|
|
33
|
+
return r;
|
|
34
|
+
}
|
|
35
|
+
if (opts.minLevel) {
|
|
36
|
+
const required = LEVEL_SCORES[opts.minLevel] ?? 0;
|
|
37
|
+
const actual = LEVEL_SCORES[token.level] ?? 0;
|
|
38
|
+
if (actual < required) {
|
|
39
|
+
const r = { allowed: false, reason: `Trust level too low: ${token.level} < ${opts.minLevel}` };
|
|
40
|
+
opts.onRejected?.(r.reason);
|
|
41
|
+
return r;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (opts.require) {
|
|
45
|
+
const required = Array.isArray(opts.require) ? opts.require : [opts.require];
|
|
46
|
+
const missing = required.filter(c => !token.credentials.includes(c));
|
|
47
|
+
if (missing.length > 0) {
|
|
48
|
+
const r = { allowed: false, reason: `Missing credentials: ${missing.join(", ")}` };
|
|
49
|
+
opts.onRejected?.(r.reason);
|
|
50
|
+
return r;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
opts.onVerified?.(token);
|
|
54
|
+
return { allowed: true, token };
|
|
55
|
+
}
|
|
56
|
+
// ── MCP Middleware ────────────────────────────────────────────────────────────
|
|
57
|
+
/**
|
|
58
|
+
* soulprint() — MCP middleware for identity verification.
|
|
59
|
+
*
|
|
60
|
+
* USAGE (MCP Server SDK):
|
|
61
|
+
*
|
|
62
|
+
* ```typescript
|
|
63
|
+
* import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
64
|
+
* import { soulprint } from "soulprint-mcp";
|
|
65
|
+
*
|
|
66
|
+
* const server = new McpServer({ name: "my-server", version: "1.0" });
|
|
67
|
+
* server.use(soulprint({ minScore: 60 }));
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* The token is read from the MCP client's capabilities:
|
|
71
|
+
* ```json
|
|
72
|
+
* { "capabilities": { "identity": { "soulprint": "<SPT>" } } }
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* Or from the HTTP header: X-Soulprint: <SPT>
|
|
76
|
+
*/
|
|
77
|
+
function soulprint(opts = {}) {
|
|
78
|
+
return {
|
|
79
|
+
// MCP SDK hook — called before each tool invocation
|
|
80
|
+
async onCallTool(context, next) {
|
|
81
|
+
const spt = extractSPT(context);
|
|
82
|
+
const result = verifySPT(spt, opts);
|
|
83
|
+
if (!result.allowed) {
|
|
84
|
+
opts.onRejected?.(result.reason);
|
|
85
|
+
throw new MCPError(opts.rejectMessage ?? `Soulprint identity required: ${result.reason}`, "FORBIDDEN", { minScore: opts.minScore ?? 40, require: opts.require });
|
|
86
|
+
}
|
|
87
|
+
opts.onVerified?.(result.token);
|
|
88
|
+
// Attach token to context for downstream use
|
|
89
|
+
context._soulprint = result.token;
|
|
90
|
+
return next();
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function extractSPT(context) {
|
|
95
|
+
// 1. From MCP capabilities
|
|
96
|
+
const cap = context?.clientCapabilities?.identity?.soulprint;
|
|
97
|
+
if (cap)
|
|
98
|
+
return cap;
|
|
99
|
+
// 2. From meta/headers
|
|
100
|
+
const headers = context?.meta?.headers;
|
|
101
|
+
if (headers?.["x-soulprint"])
|
|
102
|
+
return headers["x-soulprint"];
|
|
103
|
+
if (headers?.["X-Soulprint"])
|
|
104
|
+
return headers["X-Soulprint"];
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
// ── Standalone verifier ───────────────────────────────────────────────────────
|
|
108
|
+
/**
|
|
109
|
+
* verifyRequest() — verify a Soulprint token from any MCP request object.
|
|
110
|
+
* Use this if you prefer manual verification over middleware.
|
|
111
|
+
*
|
|
112
|
+
* ```typescript
|
|
113
|
+
* const identity = verifyRequest(request, { minScore: 60 });
|
|
114
|
+
* if (!identity) return { error: "Unverified bot" };
|
|
115
|
+
* console.log(identity.score, identity.nullifier);
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
function verifyRequest(request, opts = {}) {
|
|
119
|
+
const spt = extractSPT(request);
|
|
120
|
+
const result = verifySPT(spt, opts);
|
|
121
|
+
return result.allowed ? result.token : null;
|
|
122
|
+
}
|
|
123
|
+
// ── Helper: get token from current MCP context ────────────────────────────────
|
|
124
|
+
/**
|
|
125
|
+
* getSoulprint() — get the verified token from context (after middleware ran).
|
|
126
|
+
*
|
|
127
|
+
* ```typescript
|
|
128
|
+
* server.tool("my-tool", async (args, context) => {
|
|
129
|
+
* const identity = getSoulprint(context);
|
|
130
|
+
* console.log(identity.nullifier); // unique per human
|
|
131
|
+
* });
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
function getSoulprint(context) {
|
|
135
|
+
return context?._soulprint;
|
|
136
|
+
}
|
|
137
|
+
class MCPError extends Error {
|
|
138
|
+
code;
|
|
139
|
+
details;
|
|
140
|
+
constructor(message, code, details) {
|
|
141
|
+
super(message);
|
|
142
|
+
this.name = "MCPError";
|
|
143
|
+
this.code = code;
|
|
144
|
+
this.details = details;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// ── Re-exports ────────────────────────────────────────────────────────────────
|
|
148
|
+
var soulprint_core_2 = require("soulprint-core");
|
|
149
|
+
Object.defineProperty(exports, "decodeToken", { enumerable: true, get: function () { return soulprint_core_2.decodeToken; } });
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "soulprint-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Soulprint MCP middleware — protect any MCP server with 3 lines: server.use(soulprint({ minScore: 60 }))",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/manuelariasfz/soulprint",
|
|
17
|
+
"directory": "packages/mcp"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/manuelariasfz/soulprint#readme",
|
|
20
|
+
"keywords": [
|
|
21
|
+
"soulprint",
|
|
22
|
+
"mcp",
|
|
23
|
+
"model-context-protocol",
|
|
24
|
+
"kyc",
|
|
25
|
+
"middleware",
|
|
26
|
+
"ai-agents",
|
|
27
|
+
"identity"
|
|
28
|
+
],
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"soulprint-core": "0.1.0"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@modelcontextprotocol/sdk": ">=1.0.0"
|
|
35
|
+
},
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"@modelcontextprotocol/sdk": {
|
|
38
|
+
"optional": true
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"typescript": "^5.4.0",
|
|
43
|
+
"@types/node": "^20.0.0"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=18.0.0"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc"
|
|
50
|
+
}
|
|
51
|
+
}
|