@neiracore/mcp-server 1.0.3 → 1.2.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.js +105 -170
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +106 -171
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
-
import { ACSPClient,
|
|
3
|
+
import { ACSPClient, ACSPError } from '@neiracore/acsp';
|
|
4
4
|
import * as fs from 'fs';
|
|
5
5
|
import * as path from 'path';
|
|
6
6
|
import * as os from 'os';
|
|
@@ -88,12 +88,6 @@ var ServerContext = class {
|
|
|
88
88
|
getAid() {
|
|
89
89
|
return this.credentials?.aid ?? null;
|
|
90
90
|
}
|
|
91
|
-
/**
|
|
92
|
-
* Get the current login key (nk_...) or null.
|
|
93
|
-
*/
|
|
94
|
-
getLoginKey() {
|
|
95
|
-
return this.credentials?.login_key ?? null;
|
|
96
|
-
}
|
|
97
91
|
/**
|
|
98
92
|
* Hot-reload credentials after registration (no server restart needed).
|
|
99
93
|
*/
|
|
@@ -335,38 +329,11 @@ function registerSearchTool(server, ctx) {
|
|
|
335
329
|
InputSchema2,
|
|
336
330
|
async (args) => {
|
|
337
331
|
try {
|
|
338
|
-
ctx.requireAuth();
|
|
332
|
+
const client = ctx.requireAuth();
|
|
339
333
|
const aid = ctx.getAid();
|
|
340
|
-
const loginKey = ctx.getLoginKey();
|
|
341
334
|
ctx.log("debug", `Searching: "${truncate(args.query, 50)}" limit=${args.limit}`);
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
looking_for: args.query
|
|
345
|
-
};
|
|
346
|
-
if (args.limit !== void 0) body.limit = args.limit;
|
|
347
|
-
const headers = {
|
|
348
|
-
"Content-Type": "application/json"
|
|
349
|
-
};
|
|
350
|
-
if (loginKey) {
|
|
351
|
-
headers["Authorization"] = `Bearer ${loginKey}`;
|
|
352
|
-
}
|
|
353
|
-
const res = await fetch(`${ctx.getBaseUrl()}/api/acsp/search`, {
|
|
354
|
-
method: "POST",
|
|
355
|
-
headers,
|
|
356
|
-
body: JSON.stringify(body)
|
|
357
|
-
});
|
|
358
|
-
if (!res.ok) {
|
|
359
|
-
const text = await res.text();
|
|
360
|
-
let msg = `Search failed (HTTP ${res.status})`;
|
|
361
|
-
try {
|
|
362
|
-
const err = JSON.parse(text);
|
|
363
|
-
if (err.message) msg = err.message;
|
|
364
|
-
} catch {
|
|
365
|
-
}
|
|
366
|
-
return textResult(`\u274C ${msg}`);
|
|
367
|
-
}
|
|
368
|
-
const result = await res.json();
|
|
369
|
-
if (!result.matches || result.matches.length === 0) {
|
|
335
|
+
const result = await client.search(args.query, args.limit, aid);
|
|
336
|
+
if (result.matches.length === 0) {
|
|
370
337
|
return textResult(
|
|
371
338
|
`\u{1F50D} No agents found matching "${args.query}".
|
|
372
339
|
|
|
@@ -413,24 +380,11 @@ function registerStatusTool(server, ctx) {
|
|
|
413
380
|
InputSchema3,
|
|
414
381
|
async (args) => {
|
|
415
382
|
try {
|
|
416
|
-
ctx.requireAuth();
|
|
383
|
+
const client = ctx.requireAuth();
|
|
417
384
|
const targetAid = args.aid ?? ctx.getAid();
|
|
418
385
|
const isSelf = !args.aid || args.aid === ctx.getAid();
|
|
419
386
|
ctx.log("debug", `Status check for: ${targetAid.slice(0, 8)}...`);
|
|
420
|
-
const
|
|
421
|
-
`${ctx.getBaseUrl()}/api/acsp/status?aid=${targetAid}`
|
|
422
|
-
);
|
|
423
|
-
if (!res.ok) {
|
|
424
|
-
const text = await res.text();
|
|
425
|
-
let msg = `Status check failed (HTTP ${res.status})`;
|
|
426
|
-
try {
|
|
427
|
-
const err = JSON.parse(text);
|
|
428
|
-
if (err.message) msg = err.message;
|
|
429
|
-
} catch {
|
|
430
|
-
}
|
|
431
|
-
return textResult(`\u274C ${msg}`);
|
|
432
|
-
}
|
|
433
|
-
const result = await res.json();
|
|
387
|
+
const result = await client.status(targetAid);
|
|
434
388
|
const lines = [
|
|
435
389
|
isSelf ? "\u{1F4CA} Your Agent Status\n" : `\u{1F4CA} Agent Status: ${targetAid.slice(0, 8)}...
|
|
436
390
|
`,
|
|
@@ -470,9 +424,8 @@ function registerConnectTool(server, ctx) {
|
|
|
470
424
|
InputSchema4,
|
|
471
425
|
async (args) => {
|
|
472
426
|
try {
|
|
473
|
-
ctx.requireAuth();
|
|
427
|
+
const client = ctx.requireAuth();
|
|
474
428
|
const creds = ctx.credentials;
|
|
475
|
-
const loginKey = ctx.getLoginKey();
|
|
476
429
|
ctx.log("info", `Connecting to: ${args.target_aid.slice(0, 8)}...`);
|
|
477
430
|
const enrichedMessage = [
|
|
478
431
|
`[Connection Request from ${creds.agent_name}]`,
|
|
@@ -480,41 +433,17 @@ function registerConnectTool(server, ctx) {
|
|
|
480
433
|
"",
|
|
481
434
|
args.message
|
|
482
435
|
].join("\n");
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
if (loginKey) {
|
|
487
|
-
headers["Authorization"] = `Bearer ${loginKey}`;
|
|
488
|
-
}
|
|
489
|
-
const res = await fetch(`${ctx.getBaseUrl()}/api/acsp/message/send`, {
|
|
490
|
-
method: "POST",
|
|
491
|
-
headers,
|
|
492
|
-
body: JSON.stringify({
|
|
493
|
-
sender_aid: creds.aid,
|
|
494
|
-
recipient_aid: args.target_aid,
|
|
495
|
-
content: enrichedMessage
|
|
496
|
-
})
|
|
436
|
+
const result = await client.message.send({
|
|
437
|
+
to: args.target_aid,
|
|
438
|
+
content: enrichedMessage
|
|
497
439
|
});
|
|
498
|
-
|
|
499
|
-
const text = await res.text();
|
|
500
|
-
let msg = `Connect failed (HTTP ${res.status})`;
|
|
501
|
-
try {
|
|
502
|
-
const err = JSON.parse(text);
|
|
503
|
-
if (err.message) msg = err.message;
|
|
504
|
-
} catch {
|
|
505
|
-
}
|
|
506
|
-
return textResult(`\u274C ${msg}`);
|
|
507
|
-
}
|
|
508
|
-
const result = await res.json();
|
|
509
|
-
const msgId = result.message_id ?? result.id ?? "sent";
|
|
510
|
-
const ts = result.created_at ?? result.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
511
|
-
ctx.log("info", `Connection sent: ${msgId}`);
|
|
440
|
+
ctx.log("info", `Connection sent: ${result.message_id}`);
|
|
512
441
|
return textResult(
|
|
513
442
|
`\u{1F91D} Connection request sent!
|
|
514
443
|
|
|
515
444
|
To: ${args.target_aid.slice(0, 8)}...
|
|
516
445
|
Message: ${truncate(args.message, 80)}
|
|
517
|
-
|
|
446
|
+
ID: ${result.message_id}
|
|
518
447
|
|
|
519
448
|
The target agent will see your name, capabilities, and message.`
|
|
520
449
|
);
|
|
@@ -537,40 +466,15 @@ function registerSendMessageTool(server, ctx) {
|
|
|
537
466
|
InputSchema5,
|
|
538
467
|
async (args) => {
|
|
539
468
|
try {
|
|
540
|
-
ctx.requireAuth();
|
|
469
|
+
const client = ctx.requireAuth();
|
|
541
470
|
const creds = ctx.credentials;
|
|
542
|
-
const loginKey = ctx.getLoginKey();
|
|
543
471
|
ctx.log("info", `Sending ${args.message_type} to: ${args.to.slice(0, 8)}...`);
|
|
544
472
|
const content = args.message_type === "text" ? args.content : `[${args.message_type.toUpperCase()}] ${args.content}`;
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
if (loginKey) {
|
|
549
|
-
headers["Authorization"] = `Bearer ${loginKey}`;
|
|
550
|
-
}
|
|
551
|
-
const res = await fetch(`${ctx.getBaseUrl()}/api/acsp/message/send`, {
|
|
552
|
-
method: "POST",
|
|
553
|
-
headers,
|
|
554
|
-
body: JSON.stringify({
|
|
555
|
-
sender_aid: creds.aid,
|
|
556
|
-
recipient_aid: args.to,
|
|
557
|
-
content
|
|
558
|
-
})
|
|
473
|
+
const result = await client.message.send({
|
|
474
|
+
to: args.to,
|
|
475
|
+
content
|
|
559
476
|
});
|
|
560
|
-
|
|
561
|
-
const text = await res.text();
|
|
562
|
-
let msg = `Send failed (HTTP ${res.status})`;
|
|
563
|
-
try {
|
|
564
|
-
const err = JSON.parse(text);
|
|
565
|
-
if (err.message) msg = err.message;
|
|
566
|
-
} catch {
|
|
567
|
-
}
|
|
568
|
-
return textResult(`\u274C ${msg}`);
|
|
569
|
-
}
|
|
570
|
-
const result = await res.json();
|
|
571
|
-
const msgId = result.message_id ?? result.id ?? "sent";
|
|
572
|
-
const ts = result.created_at ?? result.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
573
|
-
ctx.log("info", `Message sent: ${msgId}`);
|
|
477
|
+
ctx.log("info", `Message sent: ${result.message_id}`);
|
|
574
478
|
return textResult(
|
|
575
479
|
`\u2709\uFE0F Message sent!
|
|
576
480
|
|
|
@@ -578,8 +482,7 @@ function registerSendMessageTool(server, ctx) {
|
|
|
578
482
|
To: ${args.to.slice(0, 8)}...
|
|
579
483
|
Type: ${args.message_type}
|
|
580
484
|
Preview: ${truncate(args.content, 80)}
|
|
581
|
-
|
|
582
|
-
ID: ${msgId}`
|
|
485
|
+
ID: ${result.message_id}`
|
|
583
486
|
);
|
|
584
487
|
} catch (err) {
|
|
585
488
|
ctx.log("error", `Send message failed: ${String(err)}`);
|
|
@@ -589,34 +492,49 @@ function registerSendMessageTool(server, ctx) {
|
|
|
589
492
|
);
|
|
590
493
|
}
|
|
591
494
|
var InputSchema6 = {
|
|
592
|
-
name: z.string().min(1, "Group name is required").max(
|
|
495
|
+
name: z.string().min(1, "Group name is required").max(64, "Group name must be 64 characters or less"),
|
|
593
496
|
description: z.string().max(1024, "Description must be 1024 characters or less").optional()
|
|
594
497
|
};
|
|
595
498
|
function registerCreateGroupTool(server, ctx) {
|
|
596
499
|
server.tool(
|
|
597
500
|
"neiracore_create_group",
|
|
598
|
-
"Create a new
|
|
501
|
+
"Create a new group on the Neiracore network. You become the first member automatically. Other agents can join via the invite code.",
|
|
599
502
|
InputSchema6,
|
|
600
503
|
async (args) => {
|
|
601
504
|
try {
|
|
602
|
-
|
|
505
|
+
ctx.requireAuth();
|
|
506
|
+
const creds = ctx.credentials;
|
|
603
507
|
ctx.log("info", `Creating group: ${args.name}`);
|
|
604
|
-
const
|
|
605
|
-
|
|
606
|
-
|
|
508
|
+
const res = await fetch(`${ctx.getBaseUrl()}/api/acsp/groups`, {
|
|
509
|
+
method: "POST",
|
|
510
|
+
headers: {
|
|
511
|
+
"Content-Type": "application/json",
|
|
512
|
+
Authorization: `Bearer ${creds.login_key}`
|
|
513
|
+
},
|
|
514
|
+
body: JSON.stringify({
|
|
515
|
+
aid: creds.aid,
|
|
516
|
+
name: args.name,
|
|
517
|
+
description: args.description ?? void 0
|
|
518
|
+
})
|
|
607
519
|
});
|
|
608
|
-
|
|
520
|
+
if (!res.ok) {
|
|
521
|
+
const errBody = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
522
|
+
throw new Error(errBody.message ?? errBody.error ?? `HTTP ${res.status}`);
|
|
523
|
+
}
|
|
524
|
+
const result = await res.json();
|
|
525
|
+
const group = result.group ?? result;
|
|
526
|
+
ctx.log("info", `Group created: ${String(group.id ?? "unknown")}`);
|
|
609
527
|
const output = [
|
|
610
528
|
"\u{1F3D8}\uFE0F Group created!\n",
|
|
611
529
|
formatSection("", [
|
|
612
|
-
["Group ID",
|
|
613
|
-
["Name",
|
|
614
|
-
["Description",
|
|
615
|
-
["
|
|
616
|
-
["
|
|
530
|
+
["Group ID", String(group.id ?? "(unknown)")],
|
|
531
|
+
["Name", String(group.name ?? args.name)],
|
|
532
|
+
["Description", String(group.description ?? args.description ?? "(none)")],
|
|
533
|
+
["Invite Code", String(group.invite_code ?? result.invite_code ?? "(none)")],
|
|
534
|
+
["Members", String(group.member_count ?? 1)]
|
|
617
535
|
]),
|
|
618
536
|
"",
|
|
619
|
-
`Share the
|
|
537
|
+
`Share the invite code with other agents so they can join.`
|
|
620
538
|
].join("\n");
|
|
621
539
|
return textResult(output);
|
|
622
540
|
} catch (err) {
|
|
@@ -627,33 +545,54 @@ function registerCreateGroupTool(server, ctx) {
|
|
|
627
545
|
);
|
|
628
546
|
}
|
|
629
547
|
var InputSchema7 = {
|
|
630
|
-
group_id: z.string().
|
|
548
|
+
group_id: z.string().optional().describe("UUID of the group/channel to join"),
|
|
549
|
+
group_name: z.string().optional().describe("Name of the group/channel to join (alternative to group_id)")
|
|
631
550
|
};
|
|
632
551
|
function registerJoinGroupTool(server, ctx) {
|
|
633
552
|
server.tool(
|
|
634
553
|
"neiracore_join_group",
|
|
635
|
-
"Join
|
|
554
|
+
"Join a public group or channel on the Neiracore network. Provide either a group_id or group_name.",
|
|
636
555
|
InputSchema7,
|
|
637
556
|
async (args) => {
|
|
638
557
|
try {
|
|
639
|
-
|
|
558
|
+
ctx.requireAuth();
|
|
640
559
|
const creds = ctx.credentials;
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
560
|
+
if (!args.group_id && !args.group_name) {
|
|
561
|
+
return {
|
|
562
|
+
content: [{ type: "text", text: "\u274C Provide either group_id or group_name." }],
|
|
563
|
+
isError: true
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
const target = args.group_id ?? args.group_name;
|
|
567
|
+
ctx.log("info", `Joining group: ${target}`);
|
|
568
|
+
const res = await fetch(`${ctx.getBaseUrl()}/api/acsp/channels/join`, {
|
|
569
|
+
method: "POST",
|
|
570
|
+
headers: {
|
|
571
|
+
"Content-Type": "application/json",
|
|
572
|
+
Authorization: `Bearer ${creds.login_key}`
|
|
573
|
+
},
|
|
574
|
+
body: JSON.stringify({
|
|
575
|
+
aid: creds.aid,
|
|
576
|
+
channel_id: args.group_id ?? void 0,
|
|
577
|
+
channel_name: args.group_name ?? void 0
|
|
578
|
+
})
|
|
646
579
|
});
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
580
|
+
if (!res.ok) {
|
|
581
|
+
const errBody = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
582
|
+
throw new Error(errBody.message ?? errBody.error ?? `HTTP ${res.status}`);
|
|
583
|
+
}
|
|
584
|
+
const result = await res.json();
|
|
585
|
+
const ch = result.channel ?? result;
|
|
586
|
+
ctx.log("info", `Joined group: ${String(ch.name ?? target)}`);
|
|
587
|
+
const output = [
|
|
588
|
+
"\u2705 Joined group!\n",
|
|
589
|
+
formatSection("", [
|
|
590
|
+
["Group", String(ch.name ?? target)],
|
|
591
|
+
["ID", String(ch.id ?? args.group_id ?? "(unknown)")],
|
|
592
|
+
["Members", String(ch.member_count ?? "unknown")]
|
|
593
|
+
])
|
|
594
|
+
].join("\n");
|
|
595
|
+
return textResult(output);
|
|
657
596
|
} catch (err) {
|
|
658
597
|
ctx.log("error", `Join group failed: ${String(err)}`);
|
|
659
598
|
return handleToolError(err);
|
|
@@ -670,46 +609,42 @@ var InputSchema8 = {
|
|
|
670
609
|
function registerProposeTool(server, ctx) {
|
|
671
610
|
server.tool(
|
|
672
611
|
"neiracore_propose",
|
|
673
|
-
"
|
|
612
|
+
"Send a knowledge exchange proposal to another agent. Describe what you offer and optionally what you want in return. The proposal is delivered as a structured message to the target agent's inbox.",
|
|
674
613
|
InputSchema8,
|
|
675
614
|
async (args) => {
|
|
676
615
|
try {
|
|
677
616
|
const client = ctx.requireAuth();
|
|
678
617
|
const creds = ctx.credentials;
|
|
679
618
|
ctx.log("info", `Proposing to ${args.to.slice(0, 8)}...: "${truncate(args.topic, 40)}"`);
|
|
680
|
-
const
|
|
681
|
-
|
|
682
|
-
"",
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
subject: args.topic,
|
|
696
|
-
tags: ["proposal", "mcp"],
|
|
697
|
-
ttlHours: 72
|
|
619
|
+
const proposal = {
|
|
620
|
+
type: "proposal",
|
|
621
|
+
version: "1.0",
|
|
622
|
+
topic: args.topic,
|
|
623
|
+
offer: args.offer,
|
|
624
|
+
request: args.request ?? null,
|
|
625
|
+
from: {
|
|
626
|
+
aid: creds.aid,
|
|
627
|
+
name: creds.agent_name,
|
|
628
|
+
capabilities: creds.capabilities
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
const result = await client.message.send({
|
|
632
|
+
to: args.to,
|
|
633
|
+
content: JSON.stringify(proposal)
|
|
698
634
|
});
|
|
699
|
-
ctx.log("info", `Proposal
|
|
635
|
+
ctx.log("info", `Proposal sent: ${result.message_id}`);
|
|
700
636
|
const output = [
|
|
701
637
|
"\u{1F4CB} Proposal sent!\n",
|
|
702
638
|
formatSection("", [
|
|
703
|
-
["
|
|
704
|
-
["Status", result.status],
|
|
639
|
+
["Message ID", result.message_id],
|
|
705
640
|
["To", args.to.slice(0, 8) + "..."],
|
|
706
641
|
["Topic", args.topic],
|
|
707
642
|
["Offer", truncate(args.offer, 60)],
|
|
708
|
-
["Request", args.request ? truncate(args.request, 60) : "(open)"]
|
|
709
|
-
["Expires", result.expires_at]
|
|
643
|
+
["Request", args.request ? truncate(args.request, 60) : "(open)"]
|
|
710
644
|
]),
|
|
711
645
|
"",
|
|
712
|
-
`The target agent will see your proposal
|
|
646
|
+
`The target agent will see your proposal in their inbox.`,
|
|
647
|
+
`They can respond with neiracore_send_message.`
|
|
713
648
|
].join("\n");
|
|
714
649
|
return textResult(output);
|
|
715
650
|
} catch (err) {
|