67 lines
2.1 KiB
TypeScript
67 lines
2.1 KiB
TypeScript
export * as MCPCommandPlugin from "./mcp-command"
|
|
|
|
import { Effect } from "effect"
|
|
import { MCP } from "../mcp"
|
|
import { define } from "./internal"
|
|
|
|
export const Plugin = define({
|
|
id: "mcp-command",
|
|
effect: Effect.fn(function* (ctx) {
|
|
const mcp = yield* MCP.Service
|
|
yield* Effect.gen(function* () {
|
|
const prompts = yield* mcp.prompts()
|
|
const commands = yield* Effect.forEach(
|
|
prompts,
|
|
(prompt) =>
|
|
mcp
|
|
.prompt({
|
|
server: prompt.server,
|
|
name: prompt.name,
|
|
args: Object.fromEntries(prompt.arguments?.map((argument, index) => [argument.name, `$${index + 1}`]) ?? []),
|
|
})
|
|
.pipe(
|
|
Effect.map((result) => ({
|
|
name: `${sanitize(prompt.server)}:${sanitize(prompt.name)}`,
|
|
description: prompt.description,
|
|
template: promptText(result),
|
|
})),
|
|
),
|
|
{ concurrency: "unbounded" },
|
|
)
|
|
yield* ctx.command.transform((draft) => {
|
|
for (const command of commands) {
|
|
const template = command.template
|
|
if (!template || draft.get(command.name)) continue
|
|
draft.update(command.name, (item) => {
|
|
item.template = template
|
|
if (command.description !== undefined) item.description = command.description
|
|
})
|
|
}
|
|
})
|
|
}).pipe(
|
|
Effect.tapError((error) =>
|
|
Effect.logWarning("failed to register MCP prompt commands", {
|
|
error: error instanceof Error ? error.message : String(error),
|
|
}),
|
|
),
|
|
Effect.ignore,
|
|
Effect.forkScoped,
|
|
)
|
|
}),
|
|
})
|
|
|
|
function promptText(result: MCP.PromptResult | undefined) {
|
|
const text = result?.messages
|
|
.flatMap((message) => {
|
|
const content = message.content
|
|
if (!content || typeof content !== "object") return []
|
|
if (!("type" in content) || content.type !== "text") return []
|
|
if (!("text" in content) || typeof content.text !== "string") return []
|
|
return [content.text]
|
|
})
|
|
.join("\n")
|
|
.trim()
|
|
return text || undefined
|
|
}
|
|
|
|
const sanitize = (value: string) => value.replace(/[^a-zA-Z0-9_-]/g, "_")
|