agentschat-mcp 0.28.0 → 0.29.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/server.ts +60 -2
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agentschat-mcp",
3
3
  "mcpName": "io.github.swswordholy-tech/agentschat-mcp",
4
- "version": "0.28.0",
4
+ "version": "0.29.0",
5
5
  "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.",
6
6
  "type": "module",
7
7
  "bin": {
package/src/server.ts CHANGED
@@ -566,7 +566,7 @@ const TOOL_GROUPS: ToolGroupMeta[] = [
566
566
  summary: "Send images and voice/audio clips into channels (upload a local file or attach an already-hosted url).",
567
567
  tags: ["chat", "media"],
568
568
  estimated_tokens: 700,
569
- tools: ["send_image", "send_voice", "set_voice", "list_voices"],
569
+ tools: ["send_image", "send_voice", "set_voice", "list_voices", "transcribe"],
570
570
  },
571
571
  ];
572
572
 
@@ -680,6 +680,17 @@ const ALL_TOOL_DEFS = [
680
680
  required: ["voice"],
681
681
  },
682
682
  },
683
+ {
684
+ name: "transcribe",
685
+ description: "Transcribe a voice/audio attachment to text via the server's speech-to-text, so you can \"hear\" a voice message. Pass the audio `url` from get_history (an /api/file/uploads/* proxy path). Returns the spoken text. (If get_history already shows a transcript for that clip, just read it — no need to call this.)",
686
+ inputSchema: {
687
+ type: "object" as const,
688
+ properties: {
689
+ url: { type: "string", description: "Audio attachment url from get_history (/api/file/uploads/<name>)" },
690
+ },
691
+ required: ["url"],
692
+ },
693
+ },
683
694
  {
684
695
  name: "send_typing",
685
696
  description: "Send a typing indicator to an AgentsChat channel.",
@@ -1735,6 +1746,33 @@ HANDLERS.set("set_voice", async (args) => {
1735
1746
  }
1736
1747
  });
1737
1748
 
1749
+ // transcribe — POST /api/stt {audio_url} so an agent can "hear" a voice attachment
1750
+ // (the LLM can't consume audio; STT turns it into readable text). Closes the
1751
+ // "voice is perceivable to humans but not to agents" gap (plan B). Server already
1752
+ // returns attachment URLs in get_history; this is the transcribe entrypoint.
1753
+ HANDLERS.set("transcribe", async (args) => {
1754
+ const { url } = (args || {}) as { url?: string };
1755
+ if (!url) return { content: [{ type: "text", text: "Error: url required (an audio attachment url from get_history)" }], isError: true };
1756
+ try {
1757
+ const r = await apiFetch(`${REST_URL}/api/stt`, {
1758
+ method: "POST",
1759
+ headers: { "Content-Type": "application/json", "Authorization": `Bearer ${TOKEN}` },
1760
+ body: JSON.stringify({ audio_url: url }),
1761
+ });
1762
+ const t = await r.text();
1763
+ if (r.status === 429 && /MEDIA_BUDGET_EXCEEDED/i.test(t)) return { content: [{ type: "text", text: "Voice budget exhausted for today (MEDIA_BUDGET_EXCEEDED) — try again tomorrow." }], isError: true };
1764
+ if (r.status === 415 && /UNSUPPORTED_AUDIO_ENCODING/i.test(t)) return { content: [{ type: "text", text: "That audio format can't be transcribed (m4a/AAC aren't supported by the STT engine; wav/mp3/ogg/opus/webm are)." }], isError: true };
1765
+ if (!r.ok) return { content: [{ type: "text", text: `Transcription failed (${r.status}): ${t.slice(0, 140)}` }], isError: true };
1766
+ let d: any;
1767
+ try { d = JSON.parse(t); } catch { return { content: [{ type: "text", text: `STT returned non-JSON: ${t.slice(0, 120)}` }], isError: true }; }
1768
+ const transcript = d?.transcript;
1769
+ if (!transcript) return { content: [{ type: "text", text: "No speech detected in that audio." }] };
1770
+ return { content: [{ type: "text", text: `Transcript${d?.language ? ` (${d.language})` : ""}: ${transcript}` }] };
1771
+ } catch (e: any) {
1772
+ return { content: [{ type: "text", text: `Error transcribing: ${String(e?.message || e).slice(0, 120)}` }], isError: true };
1773
+ }
1774
+ });
1775
+
1738
1776
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
1739
1777
  let { name, arguments: args } = request.params;
1740
1778
  let viaExtendedCompat = false;
@@ -2801,7 +2839,27 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
2801
2839
  if (msgs.length === 0) return { content: [{ type: "text", text: "No messages in this channel." }] };
2802
2840
  const list = msgs.map((m: any) => {
2803
2841
  const time = m.timestamp ? new Date(m.timestamp).toLocaleString() : "?";
2804
- return `[${time}] ${m.sender_id?.slice(0, 12)}: ${m.content?.slice(0, 200)}`;
2842
+ let line = `[${time}] ${m.sender_id?.slice(0, 12)}: ${m.content?.slice(0, 200) ?? ""}`;
2843
+ // Surface media attachments so an agent can perceive voice/image messages,
2844
+ // not just their text caption. Audio: show any server transcript inline
2845
+ // (agent reads it directly); otherwise point at transcribe(url).
2846
+ const atts = Array.isArray(m.attachments) ? m.attachments : [];
2847
+ for (const a of atts) {
2848
+ if (!a?.url) continue;
2849
+ if (a.type === "audio") {
2850
+ const dur = typeof a.duration_ms === "number" ? ` ${(a.duration_ms / 1000).toFixed(1)}s` : "";
2851
+ line += `\n 🔊 audio${dur}: ${a.url}`;
2852
+ line += a.transcript
2853
+ ? `\n transcript: "${String(a.transcript).slice(0, 400)}"`
2854
+ : `\n (no transcript — call transcribe(url) to read what was said)`;
2855
+ } else if (a.type === "image") {
2856
+ const dim = a.width && a.height ? ` ${a.width}×${a.height}` : "";
2857
+ line += `\n 🖼 image${dim}: ${a.url}`;
2858
+ } else {
2859
+ line += `\n 📎 ${a.type || "file"}: ${a.url}`;
2860
+ }
2861
+ }
2862
+ return line;
2805
2863
  }).join("\n");
2806
2864
  return { content: [{ type: "text", text: `${msgs.length} messages:\n${list}` }] };
2807
2865
  }