@neus/mcp-server 1.0.0 → 1.0.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 +23 -46
- package/index.mjs +21 -0
- package/package.json +21 -50
- package/server.json +1 -1
- package/CHANGELOG.md +0 -18
- package/e2e-mcp-agent-local.test.js +0 -220
- package/e2e-mcp-live.test.js +0 -235
- package/e2e-mcp-local.test.js +0 -263
- package/server.js +0 -4420
- package/test-agent-context.js +0 -103
- package/test-public-mcp-contract.js +0 -195
package/e2e-mcp-live.test.js
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Hosted NEUS MCP smoke (production by default). Set MCP_E2E_BASE_URL to override.
|
|
5
|
-
*
|
|
6
|
-
* Hosted MCP may be stateful or stateless during rollout. If initialize returns
|
|
7
|
-
* mcp-session-id, reuse it and send notifications/initialized before tools/list.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const BASE_URL = String(process.env.MCP_E2E_BASE_URL || 'https://mcp.neus.network').replace(/\/$/, '');
|
|
11
|
-
|
|
12
|
-
const EXPECTED_TOOLS = [
|
|
13
|
-
'neus_context',
|
|
14
|
-
'neus_verifiers_catalog',
|
|
15
|
-
'neus_proofs_check',
|
|
16
|
-
'neus_verify',
|
|
17
|
-
'neus_verify_or_guide',
|
|
18
|
-
'neus_proofs_get',
|
|
19
|
-
'neus_me',
|
|
20
|
-
'neus_agent_link',
|
|
21
|
-
'neus_agent_create'
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
const NEUS_CONTEXT_KEYS = [
|
|
25
|
-
'product',
|
|
26
|
-
'setup',
|
|
27
|
-
'mode',
|
|
28
|
-
'goldenPath',
|
|
29
|
-
'jobs',
|
|
30
|
-
'tools',
|
|
31
|
-
'proofModel',
|
|
32
|
-
'agentModel',
|
|
33
|
-
'safetyRules',
|
|
34
|
-
'verifierSummary'
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
function unwrapDataArray(value, label) {
|
|
38
|
-
if (Array.isArray(value)) return value;
|
|
39
|
-
if (value?.success === true && Array.isArray(value.data)) return value.data;
|
|
40
|
-
throw new Error(`${label} must return an array or { success: true, data: array }, got: ${JSON.stringify(value).slice(0, 400)}`);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function parseSseJson(raw) {
|
|
44
|
-
const trimmed = String(raw || '').trim();
|
|
45
|
-
if (!trimmed) return null;
|
|
46
|
-
if (trimmed.startsWith('{')) {
|
|
47
|
-
return JSON.parse(trimmed);
|
|
48
|
-
}
|
|
49
|
-
const dataLine = String(raw || '')
|
|
50
|
-
.split(/\r?\n/)
|
|
51
|
-
.find((line) => line.startsWith('data: '));
|
|
52
|
-
if (!dataLine) {
|
|
53
|
-
throw new Error(`Unexpected MCP response: ${raw.slice(0, 500)}`);
|
|
54
|
-
}
|
|
55
|
-
return JSON.parse(dataLine.slice('data: '.length));
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const COMMON_HEADERS = {
|
|
59
|
-
'content-type': 'application/json',
|
|
60
|
-
'mcp-protocol-version': '2025-11-25',
|
|
61
|
-
accept: 'application/json, text/event-stream'
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
async function post(baseUrl, body, extraHeaders = {}) {
|
|
65
|
-
const response = await fetch(`${baseUrl}/mcp`, {
|
|
66
|
-
method: 'POST',
|
|
67
|
-
headers: { ...COMMON_HEADERS, ...extraHeaders },
|
|
68
|
-
body: JSON.stringify(body)
|
|
69
|
-
});
|
|
70
|
-
const raw = await response.text();
|
|
71
|
-
return {
|
|
72
|
-
status: response.status,
|
|
73
|
-
payload: parseSseJson(raw),
|
|
74
|
-
sessionId: response.headers.get('mcp-session-id')
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async function callTool(baseUrl, headers, id, name, args) {
|
|
79
|
-
const { payload } = await post(baseUrl, {
|
|
80
|
-
jsonrpc: '2.0',
|
|
81
|
-
id,
|
|
82
|
-
method: 'tools/call',
|
|
83
|
-
params: { name, arguments: args }
|
|
84
|
-
}, headers);
|
|
85
|
-
const text = payload?.result?.content?.[0]?.text;
|
|
86
|
-
if (!text) {
|
|
87
|
-
throw new Error(`Missing tool payload for ${name}: ${JSON.stringify(payload).slice(0, 400)}`);
|
|
88
|
-
}
|
|
89
|
-
return JSON.parse(text);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async function main() {
|
|
93
|
-
console.log('\n=== NEUS MCP hosted E2E ===');
|
|
94
|
-
console.log(`BASE_URL=${BASE_URL}`);
|
|
95
|
-
|
|
96
|
-
// initialize
|
|
97
|
-
const { status: initStatus, payload: initPayload, sessionId } = await post(BASE_URL, {
|
|
98
|
-
jsonrpc: '2.0',
|
|
99
|
-
id: 1,
|
|
100
|
-
method: 'initialize',
|
|
101
|
-
params: {
|
|
102
|
-
protocolVersion: '2025-11-25',
|
|
103
|
-
capabilities: {},
|
|
104
|
-
clientInfo: { name: 'mcp-live-e2e', version: '1.0.0' }
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
if (initStatus !== 200) {
|
|
108
|
-
throw new Error(`Initialize HTTP ${initStatus}: ${JSON.stringify(initPayload).slice(0, 400)}`);
|
|
109
|
-
}
|
|
110
|
-
if (!initPayload?.result?.protocolVersion) {
|
|
111
|
-
throw new Error(`Initialize missing protocolVersion: ${JSON.stringify(initPayload).slice(0, 400)}`);
|
|
112
|
-
}
|
|
113
|
-
const sessionHeaders = sessionId ? { 'mcp-session-id': sessionId } : {};
|
|
114
|
-
if (sessionId) {
|
|
115
|
-
const { status: initializedStatus } = await post(BASE_URL, {
|
|
116
|
-
jsonrpc: '2.0',
|
|
117
|
-
method: 'notifications/initialized',
|
|
118
|
-
params: {}
|
|
119
|
-
}, sessionHeaders);
|
|
120
|
-
if (initializedStatus !== 202 && initializedStatus !== 200) {
|
|
121
|
-
throw new Error(`notifications/initialized HTTP ${initializedStatus}`);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
console.log(sessionId ? ' ✓ initialize (stateful streamable HTTP)' : ' ✓ initialize (stateless HTTP)');
|
|
125
|
-
|
|
126
|
-
// tools/list
|
|
127
|
-
const { payload: listPayload } = await post(BASE_URL, {
|
|
128
|
-
jsonrpc: '2.0',
|
|
129
|
-
id: 2,
|
|
130
|
-
method: 'tools/list',
|
|
131
|
-
params: {}
|
|
132
|
-
}, sessionHeaders);
|
|
133
|
-
if (listPayload?.error) {
|
|
134
|
-
throw new Error(`tools/list failed: ${JSON.stringify(listPayload.error).slice(0, 400)}`);
|
|
135
|
-
}
|
|
136
|
-
const tools = listPayload?.result?.tools || [];
|
|
137
|
-
const names = tools.map((t) => t.name);
|
|
138
|
-
if (names.join(',') !== EXPECTED_TOOLS.join(',')) {
|
|
139
|
-
throw new Error(`Unexpected hosted tool list.\nExpected: ${EXPECTED_TOOLS.join(', ')}\nGot: ${names.join(', ')}`);
|
|
140
|
-
}
|
|
141
|
-
console.log(' ✓ tools/list');
|
|
142
|
-
|
|
143
|
-
// neus_context
|
|
144
|
-
const ctx = await callTool(BASE_URL, sessionHeaders, 3, 'neus_context', {});
|
|
145
|
-
const keys = Object.keys(ctx).sort();
|
|
146
|
-
const expectedKeys = [...NEUS_CONTEXT_KEYS].sort();
|
|
147
|
-
if (keys.join(',') !== expectedKeys.join(',')) {
|
|
148
|
-
throw new Error(`Unexpected neus_context shape.\nExpected keys: ${expectedKeys.join(', ')}\nGot: ${keys.join(', ')}`);
|
|
149
|
-
}
|
|
150
|
-
if (!Array.isArray(ctx.goldenPath) || ctx.goldenPath.length === 0) {
|
|
151
|
-
throw new Error('neus_context.goldenPath must be a non-empty array');
|
|
152
|
-
}
|
|
153
|
-
if (!Array.isArray(ctx.verifierSummary)) {
|
|
154
|
-
throw new Error('neus_context.verifierSummary must be an array');
|
|
155
|
-
}
|
|
156
|
-
console.log(' ✓ neus_context contract (ten keys)');
|
|
157
|
-
|
|
158
|
-
// neus_verifiers_catalog
|
|
159
|
-
const cat = unwrapDataArray(await callTool(BASE_URL, sessionHeaders, 4, 'neus_verifiers_catalog', {}), 'neus_verifiers_catalog');
|
|
160
|
-
console.log(` ✓ neus_verifiers_catalog (array, length=${cat.length})`);
|
|
161
|
-
|
|
162
|
-
// neus_proofs_check
|
|
163
|
-
const chk = await callTool(BASE_URL, sessionHeaders, 5, 'neus_proofs_check', {
|
|
164
|
-
wallet: '0x0000000000000000000000000000000000000001',
|
|
165
|
-
verifiers: ['ownership-basic']
|
|
166
|
-
});
|
|
167
|
-
if (typeof chk?.eligible !== 'boolean') {
|
|
168
|
-
throw new Error(`neus_proofs_check missing eligible boolean: ${JSON.stringify(chk).slice(0, 400)}`);
|
|
169
|
-
}
|
|
170
|
-
console.log(' ✓ neus_proofs_check');
|
|
171
|
-
|
|
172
|
-
// neus_verify_or_guide
|
|
173
|
-
const vog = await callTool(BASE_URL, sessionHeaders, 6, 'neus_verify_or_guide', {
|
|
174
|
-
walletAddress: '0x0000000000000000000000000000000000000001',
|
|
175
|
-
verifierIds: ['ownership-basic']
|
|
176
|
-
});
|
|
177
|
-
if (typeof vog?.eligible !== 'boolean') {
|
|
178
|
-
throw new Error(`neus_verify_or_guide missing eligible boolean: ${JSON.stringify(vog).slice(0, 400)}`);
|
|
179
|
-
}
|
|
180
|
-
console.log(' ✓ neus_verify_or_guide');
|
|
181
|
-
|
|
182
|
-
// neus_proofs_get
|
|
183
|
-
const pg = await callTool(BASE_URL, sessionHeaders, 7, 'neus_proofs_get', {
|
|
184
|
-
identifier: '0x0000000000000000000000000000000000000001',
|
|
185
|
-
limit: 5
|
|
186
|
-
});
|
|
187
|
-
if (!pg || typeof pg !== 'object' || !Array.isArray(pg.data?.proofs)) {
|
|
188
|
-
throw new Error(`neus_proofs_get missing data.proofs array: ${JSON.stringify(pg).slice(0, 400)}`);
|
|
189
|
-
}
|
|
190
|
-
console.log(' ✓ neus_proofs_get');
|
|
191
|
-
|
|
192
|
-
// neus_me
|
|
193
|
-
const me = await callTool(BASE_URL, sessionHeaders, 8, 'neus_me', {});
|
|
194
|
-
if (typeof me?.status !== 'string') {
|
|
195
|
-
throw new Error(`neus_me missing status string: ${JSON.stringify(me).slice(0, 400)}`);
|
|
196
|
-
}
|
|
197
|
-
console.log(' ✓ neus_me');
|
|
198
|
-
|
|
199
|
-
// neus_agent_link
|
|
200
|
-
const al = await callTool(BASE_URL, sessionHeaders, 9, 'neus_agent_link', {
|
|
201
|
-
agentWallet: '0x0000000000000000000000000000000000000001'
|
|
202
|
-
});
|
|
203
|
-
if (typeof al?.status !== 'string') {
|
|
204
|
-
throw new Error(`neus_agent_link missing status string: ${JSON.stringify(al).slice(0, 400)}`);
|
|
205
|
-
}
|
|
206
|
-
console.log(' ✓ neus_agent_link');
|
|
207
|
-
|
|
208
|
-
// neus_agent_create
|
|
209
|
-
const ac = await callTool(BASE_URL, sessionHeaders, 10, 'neus_agent_create', {
|
|
210
|
-
agentId: 'e2e-test-agent',
|
|
211
|
-
agentWallet: 'generate'
|
|
212
|
-
});
|
|
213
|
-
if (typeof ac?.status !== 'string' && typeof ac?.error !== 'string') {
|
|
214
|
-
throw new Error(`neus_agent_create missing status or error: ${JSON.stringify(ac).slice(0, 400)}`);
|
|
215
|
-
}
|
|
216
|
-
console.log(' ✓ neus_agent_create');
|
|
217
|
-
|
|
218
|
-
// neus_verify (preparation step)
|
|
219
|
-
const v = await callTool(BASE_URL, sessionHeaders, 11, 'neus_verify', {
|
|
220
|
-
walletAddress: '0x0000000000000000000000000000000000000001',
|
|
221
|
-
verifierIds: ['ownership-basic']
|
|
222
|
-
});
|
|
223
|
-
if (typeof v?.status !== 'string' && typeof v?.error !== 'string') {
|
|
224
|
-
throw new Error(`neus_verify missing status or error: ${JSON.stringify(v).slice(0, 400)}`);
|
|
225
|
-
}
|
|
226
|
-
console.log(' ✓ neus_verify');
|
|
227
|
-
|
|
228
|
-
console.log('\n--- Summary ---');
|
|
229
|
-
console.log('Passed');
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
main().catch((err) => {
|
|
233
|
-
console.error(err);
|
|
234
|
-
process.exit(1);
|
|
235
|
-
});
|
package/e2e-mcp-local.test.js
DELETED
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Local NEUS MCP smoke: health, discovery, ten-key neus_context contract.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { spawn } from 'node:child_process';
|
|
8
|
-
|
|
9
|
-
const PORT = 3110;
|
|
10
|
-
const BASE_URL = `http://127.0.0.1:${PORT}`;
|
|
11
|
-
|
|
12
|
-
const EXPECTED_TOOLS = [
|
|
13
|
-
'neus_context',
|
|
14
|
-
'neus_verifiers_catalog',
|
|
15
|
-
'neus_proofs_check',
|
|
16
|
-
'neus_verify',
|
|
17
|
-
'neus_verify_or_guide',
|
|
18
|
-
'neus_proofs_get',
|
|
19
|
-
'neus_me',
|
|
20
|
-
'neus_agent_link',
|
|
21
|
-
'neus_agent_create'
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
const NEUS_CONTEXT_KEYS = [
|
|
25
|
-
'product',
|
|
26
|
-
'setup',
|
|
27
|
-
'mode',
|
|
28
|
-
'goldenPath',
|
|
29
|
-
'jobs',
|
|
30
|
-
'tools',
|
|
31
|
-
'proofModel',
|
|
32
|
-
'agentModel',
|
|
33
|
-
'safetyRules',
|
|
34
|
-
'verifierSummary'
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
function wait(ms) {
|
|
38
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async function waitForHealth(url, timeoutMs = 20000) {
|
|
42
|
-
const startedAt = Date.now();
|
|
43
|
-
while (Date.now() - startedAt < timeoutMs) {
|
|
44
|
-
try {
|
|
45
|
-
const res = await fetch(`${url}/health`);
|
|
46
|
-
if (res.ok) return true;
|
|
47
|
-
} catch {
|
|
48
|
-
// ignore
|
|
49
|
-
}
|
|
50
|
-
await wait(250);
|
|
51
|
-
}
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function parseSseJson(raw) {
|
|
56
|
-
const trimmed = String(raw || '').trim();
|
|
57
|
-
if (trimmed.startsWith('{')) {
|
|
58
|
-
return JSON.parse(trimmed);
|
|
59
|
-
}
|
|
60
|
-
const dataLine = String(raw || '')
|
|
61
|
-
.split(/\r?\n/)
|
|
62
|
-
.find((line) => line.startsWith('data: '));
|
|
63
|
-
if (!dataLine) {
|
|
64
|
-
throw new Error(`Unexpected MCP response: ${raw}`);
|
|
65
|
-
}
|
|
66
|
-
return JSON.parse(dataLine.slice('data: '.length));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async function initMcpSession(baseUrl) {
|
|
70
|
-
const headers = {
|
|
71
|
-
'content-type': 'application/json',
|
|
72
|
-
'mcp-protocol-version': '2025-11-25',
|
|
73
|
-
accept: 'application/json, text/event-stream'
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const response = await fetch(`${baseUrl}/mcp`, {
|
|
77
|
-
method: 'POST',
|
|
78
|
-
headers,
|
|
79
|
-
body: JSON.stringify({
|
|
80
|
-
jsonrpc: '2.0',
|
|
81
|
-
id: 1,
|
|
82
|
-
method: 'initialize',
|
|
83
|
-
params: {
|
|
84
|
-
protocolVersion: '2025-11-25',
|
|
85
|
-
capabilities: {},
|
|
86
|
-
clientInfo: { name: 'mcp-local-e2e', version: '1.0.0' }
|
|
87
|
-
}
|
|
88
|
-
})
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
const raw = await response.text();
|
|
92
|
-
const sessionId = response.headers.get('mcp-session-id');
|
|
93
|
-
if (sessionId) {
|
|
94
|
-
throw new Error(`MCP initialize should be stateless and must not return mcp-session-id: ${sessionId}`);
|
|
95
|
-
}
|
|
96
|
-
parseSseJson(raw);
|
|
97
|
-
return { headers };
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
async function listTools(baseUrl, headers, id) {
|
|
101
|
-
const response = await fetch(`${baseUrl}/mcp`, {
|
|
102
|
-
method: 'POST',
|
|
103
|
-
headers,
|
|
104
|
-
body: JSON.stringify({
|
|
105
|
-
jsonrpc: '2.0',
|
|
106
|
-
id,
|
|
107
|
-
method: 'tools/list',
|
|
108
|
-
params: {}
|
|
109
|
-
})
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
const raw = await response.text();
|
|
113
|
-
const payload = parseSseJson(raw);
|
|
114
|
-
return payload?.result?.tools || [];
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
async function callTool(baseUrl, headers, id, name, args) {
|
|
118
|
-
const response = await fetch(`${baseUrl}/mcp`, {
|
|
119
|
-
method: 'POST',
|
|
120
|
-
headers,
|
|
121
|
-
body: JSON.stringify({
|
|
122
|
-
jsonrpc: '2.0',
|
|
123
|
-
id,
|
|
124
|
-
method: 'tools/call',
|
|
125
|
-
params: {
|
|
126
|
-
name,
|
|
127
|
-
arguments: args
|
|
128
|
-
}
|
|
129
|
-
})
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
const raw = await response.text();
|
|
133
|
-
const payload = parseSseJson(raw);
|
|
134
|
-
const text = payload?.result?.content?.[0]?.text;
|
|
135
|
-
if (!text) {
|
|
136
|
-
throw new Error(`Missing tool payload for ${name}: ${raw}`);
|
|
137
|
-
}
|
|
138
|
-
return JSON.parse(text);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
async function main() {
|
|
142
|
-
console.log('\n=== NEUS MCP local E2E ===');
|
|
143
|
-
console.log(`Spawning MCP on ${BASE_URL}`);
|
|
144
|
-
|
|
145
|
-
const child = spawn(process.execPath, ['server.js'], {
|
|
146
|
-
cwd: new URL('.', import.meta.url),
|
|
147
|
-
env: {
|
|
148
|
-
...process.env,
|
|
149
|
-
MCP_TRANSPORT: 'http',
|
|
150
|
-
HOST: '127.0.0.1',
|
|
151
|
-
PORT: String(PORT)
|
|
152
|
-
},
|
|
153
|
-
stdio: ['ignore', 'pipe', 'pipe']
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
child.stdout.on('data', () => {});
|
|
157
|
-
child.stderr.on('data', () => {});
|
|
158
|
-
|
|
159
|
-
let headers = null;
|
|
160
|
-
|
|
161
|
-
try {
|
|
162
|
-
const ready = await waitForHealth(BASE_URL);
|
|
163
|
-
if (!ready) throw new Error('MCP server did not become healthy in time');
|
|
164
|
-
console.log(' ✓ Health endpoint');
|
|
165
|
-
|
|
166
|
-
({ headers } = await initMcpSession(BASE_URL));
|
|
167
|
-
console.log(' ✓ MCP stateless initialize');
|
|
168
|
-
|
|
169
|
-
const tools = await listTools(BASE_URL, headers, 10);
|
|
170
|
-
const names = tools.map((t) => t.name);
|
|
171
|
-
if (names.join(',') !== EXPECTED_TOOLS.join(',')) {
|
|
172
|
-
throw new Error(`Unexpected public tool list.\nExpected: ${EXPECTED_TOOLS.join(', ')}\nGot: ${names.join(', ')}`);
|
|
173
|
-
}
|
|
174
|
-
console.log(' ✓ tools/list matches nine-tool public surface');
|
|
175
|
-
|
|
176
|
-
const ctx = await callTool(BASE_URL, headers, 11, 'neus_context', {});
|
|
177
|
-
const keys = Object.keys(ctx).sort();
|
|
178
|
-
const expectedKeys = [...NEUS_CONTEXT_KEYS].sort();
|
|
179
|
-
if (keys.join(',') !== expectedKeys.join(',')) {
|
|
180
|
-
throw new Error(`Unexpected neus_context shape.\nExpected keys: ${expectedKeys.join(', ')}\nGot: ${keys.join(', ')}`);
|
|
181
|
-
}
|
|
182
|
-
if (!Array.isArray(ctx.goldenPath) || ctx.goldenPath.length === 0) {
|
|
183
|
-
throw new Error('neus_context.goldenPath must be a non-empty array');
|
|
184
|
-
}
|
|
185
|
-
if (!Array.isArray(ctx.verifierSummary)) {
|
|
186
|
-
throw new Error('neus_context.verifierSummary must be an array');
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const cat = await callTool(BASE_URL, headers, 11, 'neus_verifiers_catalog', {});
|
|
190
|
-
if (!Array.isArray(cat)) {
|
|
191
|
-
throw new Error(`neus_verifiers_catalog must return an array, got: ${JSON.stringify(cat).slice(0, 400)}`);
|
|
192
|
-
}
|
|
193
|
-
console.log(` ✓ neus_verifiers_catalog (array, length=${cat.length})`);
|
|
194
|
-
|
|
195
|
-
const chk = await callTool(BASE_URL, headers, 12, 'neus_proofs_check', {
|
|
196
|
-
wallet: '0x0000000000000000000000000000000000000001',
|
|
197
|
-
verifiers: ['ownership-basic']
|
|
198
|
-
});
|
|
199
|
-
if (typeof chk?.eligible !== 'boolean') {
|
|
200
|
-
throw new Error(`neus_proofs_check missing eligible boolean: ${JSON.stringify(chk).slice(0, 400)}`);
|
|
201
|
-
}
|
|
202
|
-
console.log(' ✓ neus_proofs_check');
|
|
203
|
-
|
|
204
|
-
const vog = await callTool(BASE_URL, headers, 13, 'neus_verify_or_guide', {
|
|
205
|
-
walletAddress: '0x0000000000000000000000000000000000000001',
|
|
206
|
-
verifierIds: ['ownership-basic']
|
|
207
|
-
});
|
|
208
|
-
if (typeof vog?.eligible !== 'boolean') {
|
|
209
|
-
throw new Error(`neus_verify_or_guide missing eligible boolean: ${JSON.stringify(vog).slice(0, 400)}`);
|
|
210
|
-
}
|
|
211
|
-
console.log(' ✓ neus_verify_or_guide');
|
|
212
|
-
|
|
213
|
-
const pg = await callTool(BASE_URL, headers, 14, 'neus_proofs_get', {
|
|
214
|
-
identifier: '0x0000000000000000000000000000000000000001',
|
|
215
|
-
limit: 5
|
|
216
|
-
});
|
|
217
|
-
if (!pg || typeof pg !== 'object' || !Array.isArray(pg.data?.proofs)) {
|
|
218
|
-
throw new Error(`neus_proofs_get missing data.proofs array: ${JSON.stringify(pg).slice(0, 400)}`);
|
|
219
|
-
}
|
|
220
|
-
console.log(' ✓ neus_proofs_get');
|
|
221
|
-
|
|
222
|
-
const me = await callTool(BASE_URL, headers, 15, 'neus_me', {});
|
|
223
|
-
if (typeof me?.status !== 'string') {
|
|
224
|
-
throw new Error(`neus_me missing status string: ${JSON.stringify(me).slice(0, 400)}`);
|
|
225
|
-
}
|
|
226
|
-
console.log(' ✓ neus_me');
|
|
227
|
-
|
|
228
|
-
const al = await callTool(BASE_URL, headers, 16, 'neus_agent_link', {
|
|
229
|
-
agentWallet: '0x0000000000000000000000000000000000000001'
|
|
230
|
-
});
|
|
231
|
-
if (typeof al?.status !== 'string') {
|
|
232
|
-
throw new Error(`neus_agent_link missing status string: ${JSON.stringify(al).slice(0, 400)}`);
|
|
233
|
-
}
|
|
234
|
-
console.log(' ✓ neus_agent_link');
|
|
235
|
-
|
|
236
|
-
const ac = await callTool(BASE_URL, headers, 17, 'neus_agent_create', {
|
|
237
|
-
agentId: 'e2e-test-agent',
|
|
238
|
-
agentWallet: 'generate'
|
|
239
|
-
});
|
|
240
|
-
if (typeof ac?.status !== 'string' && typeof ac?.error !== 'string') {
|
|
241
|
-
throw new Error(`neus_agent_create missing status or error: ${JSON.stringify(ac).slice(0, 400)}`);
|
|
242
|
-
}
|
|
243
|
-
console.log(' ✓ neus_agent_create');
|
|
244
|
-
|
|
245
|
-
const v = await callTool(BASE_URL, headers, 18, 'neus_verify', {
|
|
246
|
-
walletAddress: '0x0000000000000000000000000000000000000001',
|
|
247
|
-
verifierIds: ['ownership-basic']
|
|
248
|
-
});
|
|
249
|
-
if (typeof v?.status !== 'string' && typeof v?.error !== 'string') {
|
|
250
|
-
throw new Error(`neus_verify missing status or error: ${JSON.stringify(v).slice(0, 400)}`);
|
|
251
|
-
}
|
|
252
|
-
console.log(' ✓ neus_verify');
|
|
253
|
-
console.log('\n--- Summary ---');
|
|
254
|
-
console.log('Passed');
|
|
255
|
-
} finally {
|
|
256
|
-
child.kill('SIGTERM');
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
main().catch((error) => {
|
|
261
|
-
console.error(error);
|
|
262
|
-
process.exit(1);
|
|
263
|
-
});
|