diff --git a/helpers/shuffle.ts b/helpers/shuffle.ts new file mode 100644 index 0000000..e06e693 --- /dev/null +++ b/helpers/shuffle.ts @@ -0,0 +1,11 @@ +const fishersYatesShuffle = (arr: Type[]): Type[] => { + const shuffled = [...arr] + for (let index = shuffled.length - 1; index > 0; index--) { + const secondIndex = Math.floor(Math.random() * (index + 1)) + // biome-ignore lint/style/noNonNullAssertion: indices are guaranteed to be valid in Fisher-Yates shuffle + ;[shuffled[index]!, shuffled[secondIndex]!] = [shuffled[secondIndex]!, shuffled[index]!] + } + return shuffled +} + +export default fishersYatesShuffle diff --git a/services/randomWord.ts b/services/randomWord.ts new file mode 100644 index 0000000..4355df0 --- /dev/null +++ b/services/randomWord.ts @@ -0,0 +1,5 @@ +import fishersYatesShuffle from "@/helpers/shuffle" + +export const getRandomWords = (words: string[], count: number) => { + return fishersYatesShuffle(words).slice(0, count) +} diff --git a/stdio.ts b/stdio.ts index 7ea9603..f29671d 100644 --- a/stdio.ts +++ b/stdio.ts @@ -1,6 +1,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" import { registerDictionariesFunctionality } from "@/resources/dictionaries" +import { addRandomWordsTool } from "./tools/getRandomWords" const server = new McpServer({ name: "writer-helpers", @@ -8,6 +9,7 @@ const server = new McpServer({ }) registerDictionariesFunctionality(server) +addRandomWordsTool(server) const transport = new StdioServerTransport() await server.connect(transport) diff --git a/tools/getRandomWords.ts b/tools/getRandomWords.ts new file mode 100644 index 0000000..9dcccec --- /dev/null +++ b/tools/getRandomWords.ts @@ -0,0 +1,36 @@ +import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" +import z from "zod" +import { readDictionary } from "@/services/dictionaries" +import { getRandomWords } from "@/services/randomWord" + +export const addRandomWordsTool = (server: McpServer) => { + server.registerTool( + "get_random_words", + { + title: "Get Random Words", + description: "Get a list of random words from a dictionary.", + inputSchema: z.object({ + dictionary: z.string(), + count: z.number().optional().default(1) + }) + }, + async (input) => { + try { + const words: string[] = (await readDictionary(input.dictionary)).split("\n") + + return { content: [{ type: "text", text: getRandomWords(words, input.count).join("\n") }] } + } catch (error) { + if (error instanceof Error) { + return { + isError: true, + content: [] + } + } + return { + isError: true, + content: [] + } + } + } + ) +}