afk-ask-mcp 0.1.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/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # afk-ask-mcp
2
+
3
+ An MCP server that sends questions to users via Discord and waits for their replies.
4
+
5
+ ## Environment Variables
6
+
7
+ | Variable | Description |
8
+ | -------------------------------- | ---------------------------- |
9
+ | `AFK_ASK_MCP_DISCORD_TOKEN` | Discord Bot token |
10
+ | `AFK_ASK_MCP_DISCORD_CHANNEL_ID` | Channel ID to send questions |
11
+
12
+ ## Usage
13
+
14
+ ```bash
15
+ claude mcp add afk-ask \
16
+ --env AFK_ASK_MCP_DISCORD_TOKEN=your-bot-token \
17
+ --env AFK_ASK_MCP_DISCORD_CHANNEL_ID=your-channel-id \
18
+ -- npx -y afk-ask-mcp
19
+ ```
20
+
21
+ ## Tool
22
+
23
+ ### `afk_ask`
24
+
25
+ Sends a question to the configured Discord channel and waits for a reply.
26
+
27
+ **Parameters:**
28
+
29
+ - `question` (string): The question to ask the user
30
+
31
+ **Returns:** The content of the reply message
32
+
33
+ ## Discord Bot Setup
34
+
35
+ 1. Create a bot at [Discord Developer Portal](https://discord.com/developers/applications)
36
+ 2. Enable **MESSAGE CONTENT INTENT** under Bot settings (Privileged Gateway Intents)
37
+ 3. Invite the bot to your server with the following permissions:
38
+ - Send Messages
39
+ - Read Message History
40
+ - View Channel
41
+
42
+ ## License
43
+
44
+ MIT
@@ -0,0 +1 @@
1
+ export declare function askQuestion(question: string): Promise<string>;
@@ -0,0 +1,32 @@
1
+ import { getDiscordClient, getTargetChannel } from "./discord.js";
2
+ export async function askQuestion(question) {
3
+ const client = await getDiscordClient();
4
+ const channel = await getTargetChannel();
5
+ // 質問メッセージを送信
6
+ const sentMessage = await channel.send(question);
7
+ // リプライを待機
8
+ const answer = await waitForReply(client, sentMessage);
9
+ return answer;
10
+ }
11
+ function waitForReply(client, targetMessage) {
12
+ return new Promise((resolve) => {
13
+ const handler = (message) => {
14
+ // リプライかどうかを確認
15
+ if (!message.reference) {
16
+ return;
17
+ }
18
+ // 送信したメッセージへのリプライかを確認
19
+ if (message.reference.messageId !== targetMessage.id) {
20
+ return;
21
+ }
22
+ // Bot 自身のメッセージは無視
23
+ if (message.author.bot) {
24
+ return;
25
+ }
26
+ // リスナーを解除して結果を返す
27
+ client.off("messageCreate", handler);
28
+ resolve(message.content);
29
+ };
30
+ client.on("messageCreate", handler);
31
+ });
32
+ }
@@ -0,0 +1,3 @@
1
+ import { Client, TextChannel } from "discord.js";
2
+ export declare function getDiscordClient(): Promise<Client>;
3
+ export declare function getTargetChannel(): Promise<TextChannel>;
@@ -0,0 +1,33 @@
1
+ import { Client, GatewayIntentBits } from "discord.js";
2
+ let client = null;
3
+ function getEnvVar(name) {
4
+ const value = process.env[name];
5
+ if (!value) {
6
+ throw new Error(`環境変数 ${name} が設定されていません`);
7
+ }
8
+ return value;
9
+ }
10
+ export async function getDiscordClient() {
11
+ if (client) {
12
+ return client;
13
+ }
14
+ const token = getEnvVar("AFK_ASK_MCP_DISCORD_TOKEN");
15
+ client = new Client({
16
+ intents: [
17
+ GatewayIntentBits.Guilds,
18
+ GatewayIntentBits.GuildMessages,
19
+ GatewayIntentBits.MessageContent,
20
+ ],
21
+ });
22
+ await client.login(token);
23
+ return client;
24
+ }
25
+ export async function getTargetChannel() {
26
+ const channelId = getEnvVar("AFK_ASK_MCP_DISCORD_CHANNEL_ID");
27
+ const discordClient = await getDiscordClient();
28
+ const channel = await discordClient.channels.fetch(channelId);
29
+ if (!channel || !channel.isTextBased()) {
30
+ throw new Error(`チャンネル ${channelId} が見つからないか、テキストチャンネルではありません`);
31
+ }
32
+ return channel;
33
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { createServer } from "./server.js";
4
+ async function main() {
5
+ const server = createServer();
6
+ const transport = new StdioServerTransport();
7
+ await server.connect(transport);
8
+ }
9
+ main().catch((error) => {
10
+ console.error("Failed to start MCP server:", error);
11
+ process.exit(1);
12
+ });
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function createServer(): McpServer;
package/dist/server.js ADDED
@@ -0,0 +1,18 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { z } from "zod";
3
+ import { askQuestion } from "./askQuestion.js";
4
+ export function createServer() {
5
+ const server = new McpServer({
6
+ name: "afk-ask-mcp",
7
+ version: "1.0.0",
8
+ });
9
+ server.tool("afk_ask", "ユーザーに質問を送信し、Discord 経由で応答を待つ", {
10
+ question: z.string().describe("ユーザーへの質問内容"),
11
+ }, async ({ question }) => {
12
+ const answer = await askQuestion(question);
13
+ return {
14
+ content: [{ type: "text", text: answer }],
15
+ };
16
+ });
17
+ return server;
18
+ }
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "afk-ask-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for asking questions via Discord",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "afk-ask-mcp": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsx src/index.ts",
16
+ "fix": "prettier --write .",
17
+ "lint": "tsc --noEmit",
18
+ "prepublishOnly": "npm run build"
19
+ },
20
+ "keywords": [
21
+ "mcp",
22
+ "discord",
23
+ "model-context-protocol"
24
+ ],
25
+ "license": "MIT",
26
+ "dependencies": {
27
+ "@modelcontextprotocol/sdk": "^1.0.0",
28
+ "discord.js": "^14.0.0",
29
+ "zod": "^3.25.0"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^22.0.0",
33
+ "prettier": "^3.7.4",
34
+ "tsx": "^4.0.0",
35
+ "typescript": "^5.0.0"
36
+ },
37
+ "engines": {
38
+ "node": ">=20"
39
+ }
40
+ }