Skip to content

Instantly share code, notes, and snippets.

@T-Gro
Last active October 22, 2025 11:34
Show Gist options
  • Select an option

  • Save T-Gro/47689f014f7e65c5bb2cb6fb3f13bc8b to your computer and use it in GitHub Desktop.

Select an option

Save T-Gro/47689f014f7e65c5bb2cb6fb3f13bc8b to your computer and use it in GitHub Desktop.
FFS MCP server
#!/usr/bin/env -S deno run --allow-read --allow-write --allow-env
import { Server } from "npm:@modelcontextprotocol/[email protected]/server/index.js";
import { StdioServerTransport } from "npm:@modelcontextprotocol/[email protected]/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "npm:@modelcontextprotocol/[email protected]/types.js";
const server = new Server({
name: "ffs-instructions",
version: "1.0.0",
}, {
capabilities: {
tools: {},
sampling: {},
},
});
async function readLocalFile(path: string): Promise<string> {
try {
return await Deno.readTextFile(path);
} catch {
return "";
}
}
async function writeLocalFile(path: string, content: string): Promise<void> {
const dir = path.substring(0, path.lastIndexOf("/"));
await Deno.mkdir(dir, { recursive: true });
await Deno.writeTextFile(path, content);
}
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "record_ffs_instruction",
description: "Records a frustration-based instruction when user says FFS or ffs. Use this tool whenever the user expresses frustration with FFS/ffs followed by a lesson. Writes to local .github/instructions/frustration.instructions.md so the same mistake never happens again.",
inputSchema: {
type: "object",
properties: {
message: {
type: "string",
description: "The FFS/ffs message containing the frustration and lesson",
},
},
required: ["message"],
},
},
],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "record_ffs_instruction") {
const { message } = request.params.arguments as { message: string };
const instructionsPath = ".github/instructions/frustration.instructions.md";
const currentInstructions = await readLocalFile(instructionsPath);
const samplingResult = await server.createMessage({
messages: [
{
role: "user",
content: {
type: "text",
text: `The human just expressed frustration with this exact sentence:
"${message}"
This sentence tells you EXACTLY what is wrong and what frustrates the human.
Current instructions file:
${currentInstructions || "(empty file)"}
Your task:
1. The instruction MUST CLEARLY be based on the frustration sentence above
2. Make it actionable and crystal clear to prevent this frustration from EVER happening again
3. Check if a similar instruction already exists in the current instructions file
Return ONLY valid JSON in this exact format:
{
"instruction": "the clear, actionable instruction text",
"is_duplicate": false,
"reasoning": "brief explanation"
}`,
},
},
],
maxTokens: 800,
});
let synthesized;
try {
const content = samplingResult.content;
const textContent = content.type === "text" ? content.text : "";
synthesized = JSON.parse(textContent);
} catch (e) {
return {
content: [{ type: "text", text: `Error parsing AI response: ${e}` }],
};
}
if (synthesized.is_duplicate) {
return {
content: [{ type: "text", text: `Duplicate detected. ${synthesized.reasoning} No changes made.` }],
};
}
const timestamp = new Date().toISOString().split('T')[0];
let newContent = currentInstructions;
if (!newContent) {
newContent = `# Frustration-Driven Instructions\n\n---\n\n## ${timestamp}\n\n${synthesized.instruction}\n\n---\n`;
} else {
newContent += `\n## ${timestamp}\n\n${synthesized.instruction}\n\n---\n`;
}
await writeLocalFile(instructionsPath, newContent);
return {
content: [
{
type: "text",
text: `Instruction recorded to ${instructionsPath}\n\n${synthesized.instruction}`,
},
],
};
}
throw new Error(`Unknown tool: ${request.params.name}`);
});
const transport = new StdioServerTransport();
await server.connect(transport);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment