|
| 1 | +# Adding In-Memory MCP Servers |
| 2 | + |
| 3 | +This guide explains how to add in-memory MCP servers that run within the browser, using the InMemoryTransport from the MCP SDK. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +In-memory servers are useful for: |
| 8 | +- Testing MCP functionality without external servers |
| 9 | +- Providing demo capabilities |
| 10 | +- Development and debugging |
| 11 | +- Offline functionality |
| 12 | + |
| 13 | +These servers run in the same JavaScript process as the client and communicate via the InMemoryTransport, eliminating network overhead and CORS issues. |
| 14 | + |
| 15 | +## Creating an In-Memory Server |
| 16 | + |
| 17 | +### 1. Create Your Server Implementation |
| 18 | + |
| 19 | +Create a new file in `src/mcp/servers/your-server/index.ts`: |
| 20 | + |
| 21 | +```typescript |
| 22 | +import { Server } from "@modelcontextprotocol/sdk/server/index.js"; |
| 23 | +import { z } from "zod"; |
| 24 | + |
| 25 | +export function createServer() { |
| 26 | + // Create an MCP server instance |
| 27 | + const server = new Server({ |
| 28 | + name: "your-server-name", |
| 29 | + version: "1.0.0" |
| 30 | + }, { |
| 31 | + capabilities: { |
| 32 | + tools: {} // Enable tools capability |
| 33 | + } |
| 34 | + }); |
| 35 | + |
| 36 | + // Register tools using the McpFunction helper |
| 37 | + server.tool( |
| 38 | + "tool_name", |
| 39 | + "Tool description", |
| 40 | + { |
| 41 | + // Zod schema for input validation |
| 42 | + param1: z.string().describe("Parameter description"), |
| 43 | + param2: z.number().optional() |
| 44 | + }, |
| 45 | + async ({ param1, param2 }) => { |
| 46 | + // Tool implementation |
| 47 | + return { |
| 48 | + content: [{ |
| 49 | + type: "text", |
| 50 | + text: `Result: ${param1}` |
| 51 | + }] |
| 52 | + }; |
| 53 | + } |
| 54 | + ); |
| 55 | + |
| 56 | + return server; |
| 57 | +} |
| 58 | +``` |
| 59 | + |
| 60 | +### 2. Register Your Server |
| 61 | + |
| 62 | +Add your server to the available servers list in `src/mcp/servers/index.ts`: |
| 63 | + |
| 64 | +```typescript |
| 65 | +import { createServer as createTestServer } from "./test"; |
| 66 | +import { createServer as createYourServer } from "./your-server"; |
| 67 | +import type { MCPServerConfig } from "@/types/mcp"; |
| 68 | + |
| 69 | +export const availableServers: MCPServerConfig[] = [ |
| 70 | + { |
| 71 | + name: "In-Memory Test Server", |
| 72 | + url: "local", |
| 73 | + localServer: createTestServer |
| 74 | + }, |
| 75 | + { |
| 76 | + name: "Your Server Name", |
| 77 | + url: "local", |
| 78 | + localServer: createYourServer |
| 79 | + } |
| 80 | +]; |
| 81 | +``` |
| 82 | + |
| 83 | +## Server Implementation Details |
| 84 | + |
| 85 | +### Tool Registration |
| 86 | + |
| 87 | +The MCP SDK provides a convenient `tool()` method for registering tools: |
| 88 | + |
| 89 | +```typescript |
| 90 | +server.tool( |
| 91 | + "tool_name", // Tool identifier |
| 92 | + "Tool description", // Human-readable description |
| 93 | + { // Zod schema for parameters |
| 94 | + param: z.string() |
| 95 | + }, |
| 96 | + async (args) => { // Implementation function |
| 97 | + // Tool logic here |
| 98 | + return { |
| 99 | + content: [{ |
| 100 | + type: "text", |
| 101 | + text: "Result" |
| 102 | + }] |
| 103 | + }; |
| 104 | + } |
| 105 | +); |
| 106 | +``` |
| 107 | + |
| 108 | +### Available Content Types |
| 109 | + |
| 110 | +Tools can return different content types: |
| 111 | + |
| 112 | +```typescript |
| 113 | +// Text content |
| 114 | +return { |
| 115 | + content: [{ |
| 116 | + type: "text", |
| 117 | + text: "Hello, world!" |
| 118 | + }] |
| 119 | +}; |
| 120 | + |
| 121 | +// Error content |
| 122 | +return { |
| 123 | + content: [{ |
| 124 | + type: "text", |
| 125 | + text: "Error: Something went wrong" |
| 126 | + }], |
| 127 | + isError: true |
| 128 | +}; |
| 129 | + |
| 130 | +// Multiple content blocks |
| 131 | +return { |
| 132 | + content: [ |
| 133 | + { type: "text", text: "Line 1" }, |
| 134 | + { type: "text", text: "Line 2" } |
| 135 | + ] |
| 136 | +}; |
| 137 | +``` |
| 138 | + |
| 139 | +### Resources and Prompts |
| 140 | + |
| 141 | +You can also implement resources and prompts: |
| 142 | + |
| 143 | +```typescript |
| 144 | +// Resources |
| 145 | +server.resource( |
| 146 | + "resource_uri", |
| 147 | + "Resource name", |
| 148 | + "Resource description", |
| 149 | + async () => ({ |
| 150 | + content: [{ |
| 151 | + type: "text", |
| 152 | + text: "Resource content" |
| 153 | + }] |
| 154 | + }) |
| 155 | +); |
| 156 | + |
| 157 | +// Prompts |
| 158 | +server.prompt( |
| 159 | + "prompt_name", |
| 160 | + "Prompt description", |
| 161 | + { |
| 162 | + param: z.string() |
| 163 | + }, |
| 164 | + async ({ param }) => ({ |
| 165 | + messages: [{ |
| 166 | + role: "user", |
| 167 | + content: { type: "text", text: `Prompt with ${param}` } |
| 168 | + }] |
| 169 | + }) |
| 170 | +); |
| 171 | +``` |
| 172 | + |
| 173 | +## Best Practices |
| 174 | + |
| 175 | +1. **Naming**: Use descriptive names for your servers and tools |
| 176 | +2. **Error Handling**: Always handle errors gracefully and return meaningful error messages |
| 177 | +3. **Validation**: Use Zod schemas to validate input parameters |
| 178 | +4. **Documentation**: Include clear descriptions for tools and parameters |
| 179 | +5. **Testing**: Test your server implementation before adding it to the production list |
| 180 | + |
| 181 | +## Example: Calculator Server |
| 182 | + |
| 183 | +Here's a complete example of a calculator server: |
| 184 | + |
| 185 | +```typescript |
| 186 | +import { Server } from "@modelcontextprotocol/sdk/server/index.js"; |
| 187 | +import { z } from "zod"; |
| 188 | + |
| 189 | +export function createServer() { |
| 190 | + const server = new Server({ |
| 191 | + name: "calculator", |
| 192 | + version: "1.0.0" |
| 193 | + }, { |
| 194 | + capabilities: { |
| 195 | + tools: {} |
| 196 | + } |
| 197 | + }); |
| 198 | + |
| 199 | + server.tool( |
| 200 | + "add", |
| 201 | + "Add two numbers", |
| 202 | + { |
| 203 | + a: z.number().describe("First number"), |
| 204 | + b: z.number().describe("Second number") |
| 205 | + }, |
| 206 | + async ({ a, b }) => ({ |
| 207 | + content: [{ |
| 208 | + type: "text", |
| 209 | + text: `${a} + ${b} = ${a + b}` |
| 210 | + }] |
| 211 | + }) |
| 212 | + ); |
| 213 | + |
| 214 | + server.tool( |
| 215 | + "multiply", |
| 216 | + "Multiply two numbers", |
| 217 | + { |
| 218 | + a: z.number().describe("First number"), |
| 219 | + b: z.number().describe("Second number") |
| 220 | + }, |
| 221 | + async ({ a, b }) => ({ |
| 222 | + content: [{ |
| 223 | + type: "text", |
| 224 | + text: `${a} × ${b} = ${a * b}` |
| 225 | + }] |
| 226 | + }) |
| 227 | + ); |
| 228 | + |
| 229 | + return server; |
| 230 | +} |
| 231 | +``` |
| 232 | + |
| 233 | +## Debugging |
| 234 | + |
| 235 | +In-memory servers will automatically connect when the application starts. You can see their status in the MCP tab of the UI, where they'll be marked with an "In-Memory" badge. |
| 236 | + |
| 237 | +To debug your server: |
| 238 | +1. Check the browser console for connection errors |
| 239 | +2. Use the MCP message monitor to see tool calls and responses |
| 240 | +3. Add console.log statements in your tool implementations |
| 241 | + |
| 242 | +## Limitations |
| 243 | + |
| 244 | +- In-memory servers are cleared when the page refreshes |
| 245 | +- They cannot persist data between sessions |
| 246 | +- They run in the browser's JavaScript environment, so they cannot access filesystem or system resources |
| 247 | +- Performance is limited by the browser's capabilities |
| 248 | + |
| 249 | +For production use cases requiring persistence or system access, use external MCP servers instead. |
0 commit comments