Skip to main content
Glama

Remote MCP Server on Cloudflare

by SANKARAMDAS
index.ts9.44 kB
import { McpAgent } from "agents/mcp"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import { todo } from "node:test"; interface Project{ id: string; name: string; description: string; createdAt: string; updatedAt: string; } interface Todo { id: string; projectId: string; title: string; description: string; status: 'pending' | 'in_progress' | 'completed'; priority: 'low' | 'medium' | 'high'; createdAt: string; updatedAt: string; } // Define our MCP agent with tools export class MyMCP extends McpAgent { server = new McpServer({ name: "Planning Assistant", version: "1.0.0", }); private get kv(): KVNamespace { return (this.env as Env).PLANNING_PROJECT_STORE; } private async getProjectList(): Promise<Project[]> { const listDate = await this.kv.get('project:list'); return listDate ? JSON.parse(listDate) : []; } private async getTodoList(projectId: string): Promise<Project[]> { const listDate = await this.kv.get('project:todos'); return listDate ? JSON.parse(listDate) : []; } private async getTodosListByProject(projectId: string): Promise<Todo[]> { const todoList = await this.getTodoList(projectId); const todos: Todo[] = []; for (const todoId of todoList) { const todoData = await this.kv.get(`todo:${todoId}`); if (todoData) { todos.push(JSON.parse(todoData)); } } return todos; } async init() { this.server.tool('create_project', 'Create a new project',{ name: z.string().describe("The name of the project"), description: z.string().optional().describe("A brief description of the project"), }, async ({name,description}) => { const projectId = crypto.randomUUID(); // const now = new Date().toISOString(); const project: Project = { id: projectId, name, description: description || "", createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; await this.kv.put( `project:${projectId}`, JSON.stringify(project) ); const projectList = await this.getProjectList(); projectList.push(projectId); await this.kv.put('project:list', JSON.stringify(projectList)); return { content: [ { type: "text", text: JSON.stringify(project, null, 2) } ] } }); this.server.tool('list_projects', 'List all projects', {}, async () => { const projectList = await this.getProjectList(); const projects: Project[] = []; for (const projectId of projectList) { const projectData = await this.kv.get(`project:${projectId}`); if (projectData) { projects.push(JSON.parse(projectData)); } } return { content: [ { type: "text", text: JSON.stringify(projects, null, 2) } ] } }); this.server.tool('get_project', 'Get a specific project by ID', { project_id: z.string().describe("The ID of the project"), }, async ({project_id}) => { const projectData = await this.kv.get(`project:${project_id}`); if (!projectData) { throw new Error(`Project with ID ${project_id} does not exist.`); } const project: Project = JSON.parse(projectData); const todos = await this.getTodosListByProject(project_id); return { content: [ { type: "text", text: JSON.stringify({project,todos}, null, 2) } ] } }); this.server.tool('delete_project', 'Delete a project and all its todos', { project_id: z.string().describe("The ID of the project"), }, async ({project_id}) => { const projectData = await this.kv.get(`project:${project_id}`); if (!projectData) { throw new Error(`Project with ID ${project_id} does not exist.`); } //Delete all todos associated with the project const todos = await this.getTodosListByProject(project_id); for (const todo of todos) { await this.kv.delete(`todo:${todo.id}`); } //Delete project todo list await this.kv.delete(`project:${project_id}:todos`); //Delete project await this.kv.delete(`project:${project_id}`); //Remove projects from the project list const projectList = await this.getProjectList(); const updatedProjectList = projectList.filter((id) => id !== project_id); await this.kv.put('project:list', JSON.stringify(updatedProjectList)); return { content: [ { type: "text", text: `Project with ID ${project_id} and all its todos have been deleted`, } ] } }); this.server.tool('create_todo', 'Create a new todo item',{ project_id: z.string().describe("The ID of the project"), title: z.string().describe("The title of the todo item"), description: z.string().optional().describe("A brief description of the todo item"), priority: z.enum(['low', 'medium', 'high']).optional().describe("The priority level of the todo item"), }, async ({project_id, title, description, priority}) => { const projectData = await this.kv.get(`project:${project_id}`); if (!projectData) { throw new Error(`Project with ID ${project_id} does not exist.`); } const todoId = crypto.randomUUID(); const todo: Todo = { id: todoId, projectId: project_id, title, description: description || "", status: 'pending', priority: priority || 'medium', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; await this.kv.put(`todo:${todoId}`, JSON.stringify(todo)); const todoList = await this.getTodoList(project_id); todoList.push(todoId); await this.kv.put(`project:${project_id}:todos`, JSON.stringify(todoList)); return { content: [ { type: "text", text: JSON.stringify(todo, null, 2) } ] } } ); this.server.tool('update_todo', 'Update a todo list',{ todo_id: z.string().describe("The ID of the project"), title: z.string().optional().describe("The title of the new todo item"), description: z.string().optional().optional().describe("A brief description of the new todo item"), status: z.enum(['pending', 'in_progress', 'completed']).optional().describe("The status of the new todo item"), priority: z.enum(['low', 'medium', 'high']).optional().describe("The priority level of the new todo item"), }, async ({todo_id, title, status, description, priority}) => { const todoData = await this.kv.get(`todo:${todo_id}`); if (!todoData) { throw new Error(`Todo with ID ${todo_id} does not exist.`); } const todo: Todo = JSON.parse(todoData); if (title !== undefined) todo.title = title; if (description !== undefined) todo.description = description; if (status !== undefined) todo.status = status; if (priority !== undefined) todo.priority = priority; todo.updatedAt = new Date().toISOString(); await this.kv.put(`todo:${todo_id}`, JSON.stringify(todo)); return { content: [ { type: "text", text: JSON.stringify(todo, null, 2) } ] } } ); this.server.tool('get_todo', 'Get a specific todo by Id',{ todo_id: z.string().describe("The ID of the project"), }, async ({todo_id,}) => { const todoData = await this.kv.get(`todo:${todo_id}`); if (!todoData) { throw new Error(`Todo with ID ${todo_id} does not exist.`); } const todo: Todo = JSON.parse(todoData); return { content: [ { type: "text", text: JSON.stringify(todo, null, 2), } ] } } ); this.server.tool('list_todos', 'List of all todos in a project',{ project_id: z.string().describe("The ID of the project"), status: z.enum(['pending', 'in_progress', 'completed']).optional().describe("Filter todos by status"), }, async ({project_id, status}) => { const projectData = await this.kv.get(`todo:${project_id}`); if (!projectData) { throw new Error(`Todo with ID ${project_id} does not exist.`); } let todos = await this.getTodosListByProject(project_id); if (status && status !=="all") { todos = todos.filter((todo) => todo.status === status); } return { content: [ { type: "text", text: JSON.stringify(todos, null, 2), } ] } } ); this.server.tool('delete_todo', 'Delete todo from a project',{ todo_id: z.string().describe("The ID of the project"), }, async ({todo_id,}) => { const todoData = await this.kv.get(`todo:${todo_id}`); if (!todoData) { throw new Error(`Todo with ID ${todo_id} does not exist.`); } const todo: Todo = JSON.parse(todoData); //Remove todo from project's todo list const todoList = await this.getTodoList(todo.projectId); const updatedTodoList = todoList.filter((id) => id !== todo_id); await this.kv.put(`project:${todo.projectId}:todos`, JSON.stringify(updatedTodoList)); //Delete the todo item await this.kv.delete(`todo:${todo_id}`); return { content: [ { type: "text", text: `Todo with ID ${todo_id} has been deleted`, } ] } } ); } } export default { fetch(request: Request, env: Env, ctx: ExecutionContext) { const url = new URL(request.url); if (url.pathname === "/sse" || url.pathname === "/sse/message") { return MyMCP.serveSSE("/sse").fetch(request, env, ctx); } if (url.pathname === "/mcp") { return MyMCP.serve("/mcp").fetch(request, env, ctx); } return new Response("Not found", { status: 404 }); }, };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/SANKARAMDAS/planningmcpproject'

If you have feedback or need assistance with the MCP directory API, please join our Discord server