Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 278 lines 7.1 kB view raw
1// MCP Server for aesthetic.computer 2// Exposes tools, resources, and prompts for publishing and exploring pieces 3 4import { Server } from "@modelcontextprotocol/sdk/server/index.js"; 5import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; 6import { 7 CallToolRequestSchema, 8 ListResourcesRequestSchema, 9 ListToolsRequestSchema, 10 ReadResourceRequestSchema, 11 ListPromptsRequestSchema, 12 GetPromptRequestSchema, 13} from "@modelcontextprotocol/sdk/types.js"; 14 15// Import tools 16import { publishPieceTool, publishPiece } from "./tools/publish-piece.js"; 17import { publishKidLispTool, publishKidLisp } from "./tools/publish-kidlisp.js"; 18import { publishClockTool, publishClock } from "./tools/publish-clock.js"; 19import { getAPIInfoTool, getAPIInfo } from "./tools/get-api-info.js"; 20import { 21 previewKidLispTool, 22 previewKidLisp, 23} from "./tools/preview-kidlisp.js"; 24 25// Import resources 26import { 27 pieceTemplateResource, 28 getPieceTemplate, 29} from "./resources/piece-template.js"; 30import { 31 kidlispReferenceResource, 32 getKidLispReference, 33} from "./resources/kidlisp-reference.js"; 34import { 35 pieceExamplesResource, 36 getPieceExamples, 37} from "./resources/piece-examples.js"; 38 39// Import prompts 40import { 41 createPiecePrompt, 42 getCreatePiecePrompt, 43} from "./prompts/create-piece.js"; 44import { 45 createKidLispPrompt, 46 getCreateKidLispPrompt, 47} from "./prompts/create-kidlisp.js"; 48 49export class AestheticComputerServer { 50 private server: Server; 51 private token?: string; 52 53 constructor(token?: string) { 54 this.token = token; 55 this.server = new Server( 56 { 57 name: "aesthetic-computer", 58 version: "1.1.0", 59 }, 60 { 61 capabilities: { 62 tools: {}, 63 resources: {}, 64 prompts: {}, 65 }, 66 } 67 ); 68 69 this.setupHandlers(); 70 } 71 72 private setupHandlers() { 73 // List available tools 74 this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ 75 tools: [ 76 publishPieceTool, 77 publishKidLispTool, 78 publishClockTool, 79 getAPIInfoTool, 80 previewKidLispTool, 81 ], 82 })); 83 84 // Handle tool calls 85 this.server.setRequestHandler(CallToolRequestSchema, async (request) => { 86 const { name, arguments: args } = request.params; 87 88 try { 89 switch (name) { 90 case "publish_piece": 91 return { 92 content: [ 93 { 94 type: "text", 95 text: JSON.stringify( 96 await publishPiece( 97 args as { source: string; name?: string }, 98 this.token 99 ), 100 null, 101 2 102 ), 103 }, 104 ], 105 }; 106 107 case "publish_kidlisp": 108 return { 109 content: [ 110 { 111 type: "text", 112 text: JSON.stringify( 113 await publishKidLisp(args as { source: string }, this.token), 114 null, 115 2 116 ), 117 }, 118 ], 119 }; 120 121 case "publish_clock": 122 return { 123 content: [ 124 { 125 type: "text", 126 text: JSON.stringify( 127 await publishClock(args as { source: string }, this.token), 128 null, 129 2 130 ), 131 }, 132 ], 133 }; 134 135 case "get_api_info": 136 return { 137 content: [ 138 { 139 type: "text", 140 text: JSON.stringify(await getAPIInfo(), null, 2), 141 }, 142 ], 143 }; 144 145 case "preview_kidlisp": 146 return { 147 content: [ 148 { 149 type: "text", 150 text: JSON.stringify( 151 await previewKidLisp(args as { source: string }), 152 null, 153 2 154 ), 155 }, 156 ], 157 }; 158 159 default: 160 throw new Error(`Unknown tool: ${name}`); 161 } 162 } catch (error) { 163 return { 164 content: [ 165 { 166 type: "text", 167 text: `Error: ${error instanceof Error ? error.message : String(error)}`, 168 }, 169 ], 170 isError: true, 171 }; 172 } 173 }); 174 175 // List available resources 176 this.server.setRequestHandler(ListResourcesRequestSchema, async () => ({ 177 resources: [ 178 pieceTemplateResource, 179 kidlispReferenceResource, 180 pieceExamplesResource, 181 ], 182 })); 183 184 // Read resource content 185 this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => { 186 const { uri } = request.params; 187 188 switch (uri) { 189 case "aesthetic-computer://piece-template": 190 return { 191 contents: [ 192 { 193 uri, 194 mimeType: "text/javascript", 195 text: getPieceTemplate(), 196 }, 197 ], 198 }; 199 200 case "aesthetic-computer://kidlisp-reference": 201 return { 202 contents: [ 203 { 204 uri, 205 mimeType: "text/markdown", 206 text: getKidLispReference(), 207 }, 208 ], 209 }; 210 211 case "aesthetic-computer://piece-examples": 212 return { 213 contents: [ 214 { 215 uri, 216 mimeType: "text/markdown", 217 text: getPieceExamples(), 218 }, 219 ], 220 }; 221 222 default: 223 throw new Error(`Unknown resource: ${uri}`); 224 } 225 }); 226 227 // List available prompts 228 this.server.setRequestHandler(ListPromptsRequestSchema, async () => ({ 229 prompts: [createPiecePrompt, createKidLispPrompt], 230 })); 231 232 // Get prompt content 233 this.server.setRequestHandler(GetPromptRequestSchema, async (request) => { 234 const { name, arguments: args } = request.params; 235 236 switch (name) { 237 case "create-piece": 238 return { 239 messages: [ 240 { 241 role: "user", 242 content: { 243 type: "text", 244 text: getCreatePiecePrompt( 245 args as { name: string; description: string } 246 ), 247 }, 248 }, 249 ], 250 }; 251 252 case "create-kidlisp": 253 return { 254 messages: [ 255 { 256 role: "user", 257 content: { 258 type: "text", 259 text: getCreateKidLispPrompt( 260 args as { description: string } 261 ), 262 }, 263 }, 264 ], 265 }; 266 267 default: 268 throw new Error(`Unknown prompt: ${name}`); 269 } 270 }); 271 } 272 273 async run() { 274 const transport = new StdioServerTransport(); 275 await this.server.connect(transport); 276 console.error("Aesthetic Computer MCP server running on stdio"); 277 } 278}