# How to turn Any JavaScript Function Into a MCP Tool

4 min read
Table of Contents

In today’s guide, we explain how to use microfn to turn any JavaScript or TypeScript function into a MCP tool that can be plugged into your favorite agent.

Getting started

First, let’s figure out what our new MCP tool should do. For this guide, I thought it would be interesting to create a tool that can store memory for the agent in the cloud, so we can use the same memory storage across differnt agents.

Let’s scaffold something quick. We can also ask AI directly to do this for us using the microfn MCP.

import kv from "@microfn/kv";
const MEMORY_KEY = "mcp-memory";
// Helper to get all memories from the KV store
async function getMemories(): Promise<Record<string, any>> {
const memories = await kv.get<Record<string, any>>(MEMORY_KEY);
return memories || {};
}
// Helper to save all memories to the KV store
async function saveMemories(memories: Record<string, any>) {
await kv.set(MEMORY_KEY, memories);
}
// --- Command Functions ---
async function listAllMemories() {
console.log("Fetching all memories.");
const memories = await getMemories();
console.log(`Found ${Object.keys(memories).length} memories.`);
return memories;
}
async function createOrUpdateMemory(key: string, value: any) {
console.log(`Creating/updating memory for key: '${key}'.`);
const memories = await getMemories();
memories[key] = value;
await saveMemories(memories);
console.log(`Memory for '${key}' successfully saved.`);
return { success: true, message: `Memory '${key}' has been created/updated.` };
}
async function deleteMemory(key: string) {
console.log(`Attempting to delete memory with key: '${key}'.`);
const memories = await getMemories();
if (key in memories) {
delete memories[key];
await saveMemories(memories);
console.log(`Memory for '${key}' was deleted.`);
return { success: true, message: `Memory '${key}' has been deleted.` };
} else {
console.log(`Memory with key '${key}' not found.`);
return { success: false, message: `Memory '${key}' not found.` };
}
}
// --- Main Handler ---
export async function main(input: { command: "list" | "create" | "delete", key?: string, value?: any }) {
const { command, key, value } = input;
console.log(`Command: '${command}'`);
switch (command) {
case "list":
return await listAllMemories();
case "create":
if (!key || value === undefined) {
throw new Error("The 'key' and 'value' parameters are required for the 'create' command.");
}
return await createOrUpdateMemory(key, value);
case "delete":
if (!key) {
throw new Error("The 'key' parameter is required for the 'delete' command.");
}
return await deleteMemory(key);
default:
// This part should be unreachable given the TypeScript type, but it's good practice
// to have a default case for robustness.
const exhaustiveCheck: never = command;
throw new Error(`Unhandled command: ${exhaustiveCheck}`);
}
}

This function

  • takes a command, whether to list, create, or delete a memory
  • persists the memory to kv storage

Because we need some kind of persistence, we’ll be using @microfn/kv for this (docs here)

Now let’s turn this function into a MCP tool

Deploying the function

If the AI agent hasn’t already done it, let’s deploy this to the microfn platform and create a new function. We’ll call this memory-store

Create Function Dialog

In the editor, paste the code from above and hit save, this will deploy the function onto microfn

Microfn Editor

Once deployed, we can already play with our new memory store through cURL:

❯ curl -X POST https://microfn.dev/run/david/memory-store -d '{ "command": "list" }'
{}
❯ curl -X POST https://microfn.dev/run/david/memory-store -d '{ "command": "create", "key": "my name", "value": "microfn" }'
{"success":true,"message":"Memory 'my name' has been created/updated."}
❯ curl -X POST https://microfn.dev/run/david/memory-store -d '{ "command": "list" }'
{"my name":"microfn"}

Using our new function through MCP

Setting up the microfn MCP is easy. For most clients we can just do

{
"mcpServers": {
"microfn": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://mcp.microfn.dev/sse"]
}
}
}

For clients that support remote-mcp directly, we can also just use mcp.microfn.dev/sse without mcp-remote. Check out https://microfn.dev/mcp for more info

Once setup, let’s ask cloud to use the new store:

Claude using microfn Neat!

Teaching Claude to use the new memory store is also super easy:

Claude using microfn functions

We can do even better

Currently an agent needs to execute the tool through the executeFunction MCP tool, but we can do better.

Head over to settings and enable “Expose as direct MCP tool”

Expose as direct MCP tool

This will turn our new function into a direct MCP tool, so next time you ask Claude something, it can directly call the function:

Direct Tool Call

Under the hood, microfn created a new function within the MCP server

Internal Tool

Give microfn a try

Microfn is available to use for free with a paid plan. Check it out over at https://microfn.dev and let us know what you think!

https://microfn.dev - deploy JavaScript functions into the cloud in seconds


Comments