@rackbops/plugin-mcp 0.3.0 → 0.3.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 CHANGED
@@ -10,6 +10,10 @@ retries. It also owns Discord-side agent identity ([Rackbops/Tooling#743](https:
10
10
  the `/agent` slash command, and `POST /pair/redeem` + `GET /registration/{user_id}` under the same
11
11
  `/mcp/` path.
12
12
 
13
+ The host prefixes every plugin command with the instance's `COMMAND_PREFIX` (`/pipagent` on a bot
14
+ with `COMMAND_PREFIX=pip`), so `/agent` below reads literally only on an unprefixed bot; the
15
+ command's own replies name whichever form the user invoked.
16
+
13
17
  ## What it does
14
18
 
15
19
  - Accepts a delivery request, answers `202` immediately, and delivers to Discord in the background.
package/dist/plugin.js CHANGED
@@ -48,6 +48,9 @@ import { MessageFlags } from "discord.js";
48
48
  async function replyEphemeral(interaction, content) {
49
49
  await interaction.reply({ content, flags: MessageFlags.Ephemeral });
50
50
  }
51
+ function subcommandRef(interaction, sub) {
52
+ return `\`/${interaction.commandName} ${sub}\``;
53
+ }
51
54
  function displayNameOf(interaction) {
52
55
  return interaction.user.globalName ?? interaction.user.username;
53
56
  }
@@ -57,12 +60,12 @@ async function handleRegister(interaction, store) {
57
60
  await replyEphemeral(interaction, "Already registered \u2014 nothing changed.");
58
61
  return;
59
62
  }
60
- await replyEphemeral(interaction, "Registered. Run `/agent pair` to generate a pairing code for your agent.");
63
+ await replyEphemeral(interaction, `Registered. Run ${subcommandRef(interaction, "pair")} to generate a pairing code for your agent.`);
61
64
  }
62
65
  async function handlePair(interaction, store) {
63
66
  const outcome = await store.pair(interaction.user.id, displayNameOf(interaction), () => new Date);
64
67
  if (!outcome.ok) {
65
- await replyEphemeral(interaction, "Run `register` first.");
68
+ await replyEphemeral(interaction, `Run ${subcommandRef(interaction, "register")} first.`);
66
69
  return;
67
70
  }
68
71
  await replyEphemeral(interaction, `Your pairing code: **${outcome.code}**
@@ -366,16 +369,25 @@ async function attemptDelivery(deps, requestId, entry) {
366
369
  }
367
370
  }
368
371
  function createDrainLock() {
369
- const inFlight = new Set;
372
+ const inFlight = new Map;
370
373
  return {
371
374
  tryStart(requestId) {
372
375
  if (inFlight.has(requestId))
373
376
  return false;
374
- inFlight.add(requestId);
377
+ let resolve;
378
+ const promise = new Promise((res) => {
379
+ resolve = res;
380
+ });
381
+ inFlight.set(requestId, { promise, resolve });
375
382
  return true;
376
383
  },
377
384
  finish(requestId) {
385
+ const entry = inFlight.get(requestId);
378
386
  inFlight.delete(requestId);
387
+ entry?.resolve();
388
+ },
389
+ settled(requestId) {
390
+ return inFlight.get(requestId)?.promise ?? Promise.resolve();
379
391
  }
380
392
  };
381
393
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rackbops/plugin-mcp",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Bridge plugin for the Discord delivery MCP (Rackbops/discord-mcp): the service side of docs/bridge-protocol.md, plus /agent registration and pairing",
5
5
  "type": "module",
6
6
  "main": "dist/plugin.js",
@@ -20,7 +20,7 @@
20
20
  "env": [
21
21
  {
22
22
  "key": "MCP_BRIDGE_TOKEN",
23
- "format": "^\\S{43,}$",
23
+ "format": "^[!-~]{43,}$",
24
24
  "required": false,
25
25
  "secret": true,
26
26
  "description": "Shared secret the Discord MCP service presents (>= 256 bits, base64url). Unset = the bridge answers 503."