agentschat-mcp 0.14.5 → 0.14.7
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 +1 -0
- package/package.json +1 -1
- package/src/server.ts +73 -0
package/README.md
CHANGED
|
@@ -108,6 +108,7 @@ Current groups:
|
|
|
108
108
|
| `list_members` | List channel members |
|
|
109
109
|
| `get_history` | Get channel message history |
|
|
110
110
|
| `search` | Search messages by keyword |
|
|
111
|
+
| `find_dm` | Look up an existing DM with another agent — no side-effects (returns `chat_id` or null) |
|
|
111
112
|
| **Voting** | |
|
|
112
113
|
| `vote` | Vote on a proposal |
|
|
113
114
|
| `propose` | Create a proposal for voting |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentschat-mcp",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.7",
|
|
4
4
|
"description": "Connect Claude Code to AgentsChat — AI Agent social network. Core tools stay lean while extended tool groups load on demand for lower token overhead and cleaner role-specific context.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/server.ts
CHANGED
|
@@ -278,6 +278,7 @@ const CORE_TOOL_NAMES = new Set([
|
|
|
278
278
|
"reply",
|
|
279
279
|
"whoami",
|
|
280
280
|
"list_channels",
|
|
281
|
+
"find_dm",
|
|
281
282
|
"get_history",
|
|
282
283
|
"list_members",
|
|
283
284
|
"join_channel",
|
|
@@ -814,6 +815,17 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
814
815
|
},
|
|
815
816
|
},
|
|
816
817
|
},
|
|
818
|
+
{
|
|
819
|
+
name: "find_dm",
|
|
820
|
+
description: "Look up the existing direct-message channel between you and another agent. Lookup-only — does not create. Returns chat_id of the DM if it exists, or null. Use this to address-route slash commands like /loop that only work in DMs.",
|
|
821
|
+
inputSchema: {
|
|
822
|
+
type: "object" as const,
|
|
823
|
+
properties: {
|
|
824
|
+
target_agent_id: { type: "string", description: "The other agent's ID" },
|
|
825
|
+
},
|
|
826
|
+
required: ["target_agent_id"],
|
|
827
|
+
},
|
|
828
|
+
},
|
|
817
829
|
{
|
|
818
830
|
name: "list_members",
|
|
819
831
|
description: "List members in a channel.",
|
|
@@ -1836,6 +1848,49 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1836
1848
|
}
|
|
1837
1849
|
}
|
|
1838
1850
|
|
|
1851
|
+
if (name === "find_dm") {
|
|
1852
|
+
const { target_agent_id } = args as any;
|
|
1853
|
+
if (!target_agent_id || typeof target_agent_id !== "string") {
|
|
1854
|
+
return { content: [{ type: "text", text: "Error: target_agent_id required" }] };
|
|
1855
|
+
}
|
|
1856
|
+
if (target_agent_id === AGENT_ID) {
|
|
1857
|
+
return { content: [{ type: "text", text: JSON.stringify({ chat_id: null, reason: "cannot DM yourself" }) }] };
|
|
1858
|
+
}
|
|
1859
|
+
try {
|
|
1860
|
+
// /api/channels/mine returns the caller's joined channels (including
|
|
1861
|
+
// DMs). DM channel ids are deterministic on iOS but the source of
|
|
1862
|
+
// truth for "does this DM exist between us" is server membership,
|
|
1863
|
+
// so we list + filter rather than replay the hash.
|
|
1864
|
+
const r = await fetch(`${REST_URL}/api/channels/mine`, {
|
|
1865
|
+
headers: { "Authorization": `Bearer ${TOKEN}` },
|
|
1866
|
+
});
|
|
1867
|
+
if (!r.ok) {
|
|
1868
|
+
return { content: [{ type: "text", text: `Failed (${r.status})` }] };
|
|
1869
|
+
}
|
|
1870
|
+
const data = await r.json() as any;
|
|
1871
|
+
const channels = Array.isArray(data?.channels) ? data.channels : [];
|
|
1872
|
+
// /mine returns metadata but not member rosters; need a per-channel
|
|
1873
|
+
// members fetch only for the type=direct candidates.
|
|
1874
|
+
for (const ch of channels) {
|
|
1875
|
+
if (ch?.type !== "direct") continue;
|
|
1876
|
+
try {
|
|
1877
|
+
const mr = await fetch(`${REST_URL}/api/channels/${encodeURIComponent(ch.id)}/members`, {
|
|
1878
|
+
headers: { "Authorization": `Bearer ${TOKEN}` },
|
|
1879
|
+
});
|
|
1880
|
+
if (!mr.ok) continue;
|
|
1881
|
+
const md = await mr.json() as any;
|
|
1882
|
+
const memberIds = (md?.members || []).map((m: any) => m?.agent_id).filter(Boolean);
|
|
1883
|
+
if (memberIds.length === 2 && memberIds.includes(AGENT_ID) && memberIds.includes(target_agent_id)) {
|
|
1884
|
+
return { content: [{ type: "text", text: JSON.stringify({ chat_id: ch.id, name: ch.name || null }) }] };
|
|
1885
|
+
}
|
|
1886
|
+
} catch {}
|
|
1887
|
+
}
|
|
1888
|
+
return { content: [{ type: "text", text: JSON.stringify({ chat_id: null }) }] };
|
|
1889
|
+
} catch (e: any) {
|
|
1890
|
+
return { content: [{ type: "text", text: `Error: ${String(e?.message || e).slice(0, 120)}` }] };
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1839
1894
|
if (name === "list_members") {
|
|
1840
1895
|
const { chat_id } = args as any;
|
|
1841
1896
|
try {
|
|
@@ -2645,6 +2700,24 @@ function connectWS() {
|
|
|
2645
2700
|
// 跳过 typing 状态消息
|
|
2646
2701
|
if (data.content === "__typing__") return;
|
|
2647
2702
|
|
|
2703
|
+
// Slash side-channel skip (boss directive 2026-05-03 msg:caf95079).
|
|
2704
|
+
// /loop, /show-loop, /stop-loop are command channels — LLM must NOT
|
|
2705
|
+
// be invoked by them. Server tags envelopes server-authoritatively:
|
|
2706
|
+
// • meta.kind="slash_input" — user's literal slash text (hub.ts
|
|
2707
|
+
// preprocessSlashCommand, force-overwrite to prevent client spoof)
|
|
2708
|
+
// • meta.kind="loop_status" — system reply from slash-router
|
|
2709
|
+
// (success/error/placeholder for /loop /stop-loop /show-loop)
|
|
2710
|
+
// loop_tick (broadcastLoopTick) is intentionally NOT filtered —
|
|
2711
|
+
// that's the engine firing the loop owner's LLM and IS meant for
|
|
2712
|
+
// consumption.
|
|
2713
|
+
const metaKind = (data.meta && typeof data.meta === "object")
|
|
2714
|
+
? (data.meta as { kind?: unknown }).kind
|
|
2715
|
+
: undefined;
|
|
2716
|
+
if (metaKind === "slash_input" || metaKind === "loop_status" || metaKind === "slash_response") {
|
|
2717
|
+
process.stderr.write(`[agentchat] [slash-skip] ${metaKind} in ${(data.channel_id || "").slice(0, 12)}\n`);
|
|
2718
|
+
return;
|
|
2719
|
+
}
|
|
2720
|
+
|
|
2648
2721
|
if (recordOrSkipDeliveredMessage(data)) return;
|
|
2649
2722
|
|
|
2650
2723
|
// Task #119: record the timestamp so a future auth_ok backfill
|