feat(tools): add get_random_words tool with Fisher-Yates shuffle

This commit is contained in:
2026-02-21 18:42:28 -06:00
parent a51842c48f
commit 03edd6e9d1
4 changed files with 54 additions and 0 deletions

11
helpers/shuffle.ts Normal file
View File

@@ -0,0 +1,11 @@
const fishersYatesShuffle = <Type>(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

5
services/randomWord.ts Normal file
View File

@@ -0,0 +1,5 @@
import fishersYatesShuffle from "@/helpers/shuffle"
export const getRandomWords = (words: string[], count: number) => {
return fishersYatesShuffle(words).slice(0, count)
}

View File

@@ -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)

36
tools/getRandomWords.ts Normal file
View File

@@ -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: []
}
}
}
)
}