Add documentation for creating in-memory MCP servers
- Explain how to create and register in-memory servers - Provide examples using the Server class and tool() method - Include best practices and debugging tips - Document limitations of in-memory servers - Add complete calculator server example
This commit is contained in:
parent
e53be9ec42
commit
e746c42f8d
1 changed files with 249 additions and 0 deletions
249
docs/adding_local_servers.md
Normal file
249
docs/adding_local_servers.md
Normal file
|
|
@ -0,0 +1,249 @@
|
||||||
|
# Adding In-Memory MCP Servers
|
||||||
|
|
||||||
|
This guide explains how to add in-memory MCP servers that run within the browser, using the InMemoryTransport from the MCP SDK.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
In-memory servers are useful for:
|
||||||
|
- Testing MCP functionality without external servers
|
||||||
|
- Providing demo capabilities
|
||||||
|
- Development and debugging
|
||||||
|
- Offline functionality
|
||||||
|
|
||||||
|
These servers run in the same JavaScript process as the client and communicate via the InMemoryTransport, eliminating network overhead and CORS issues.
|
||||||
|
|
||||||
|
## Creating an In-Memory Server
|
||||||
|
|
||||||
|
### 1. Create Your Server Implementation
|
||||||
|
|
||||||
|
Create a new file in `src/mcp/servers/your-server/index.ts`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export function createServer() {
|
||||||
|
// Create an MCP server instance
|
||||||
|
const server = new Server({
|
||||||
|
name: "your-server-name",
|
||||||
|
version: "1.0.0"
|
||||||
|
}, {
|
||||||
|
capabilities: {
|
||||||
|
tools: {} // Enable tools capability
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Register tools using the McpFunction helper
|
||||||
|
server.tool(
|
||||||
|
"tool_name",
|
||||||
|
"Tool description",
|
||||||
|
{
|
||||||
|
// Zod schema for input validation
|
||||||
|
param1: z.string().describe("Parameter description"),
|
||||||
|
param2: z.number().optional()
|
||||||
|
},
|
||||||
|
async ({ param1, param2 }) => {
|
||||||
|
// Tool implementation
|
||||||
|
return {
|
||||||
|
content: [{
|
||||||
|
type: "text",
|
||||||
|
text: `Result: ${param1}`
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Register Your Server
|
||||||
|
|
||||||
|
Add your server to the available servers list in `src/mcp/servers/index.ts`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { createServer as createTestServer } from "./test";
|
||||||
|
import { createServer as createYourServer } from "./your-server";
|
||||||
|
import type { MCPServerConfig } from "@/types/mcp";
|
||||||
|
|
||||||
|
export const availableServers: MCPServerConfig[] = [
|
||||||
|
{
|
||||||
|
name: "In-Memory Test Server",
|
||||||
|
url: "local",
|
||||||
|
localServer: createTestServer
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Your Server Name",
|
||||||
|
url: "local",
|
||||||
|
localServer: createYourServer
|
||||||
|
}
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
## Server Implementation Details
|
||||||
|
|
||||||
|
### Tool Registration
|
||||||
|
|
||||||
|
The MCP SDK provides a convenient `tool()` method for registering tools:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
server.tool(
|
||||||
|
"tool_name", // Tool identifier
|
||||||
|
"Tool description", // Human-readable description
|
||||||
|
{ // Zod schema for parameters
|
||||||
|
param: z.string()
|
||||||
|
},
|
||||||
|
async (args) => { // Implementation function
|
||||||
|
// Tool logic here
|
||||||
|
return {
|
||||||
|
content: [{
|
||||||
|
type: "text",
|
||||||
|
text: "Result"
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Available Content Types
|
||||||
|
|
||||||
|
Tools can return different content types:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Text content
|
||||||
|
return {
|
||||||
|
content: [{
|
||||||
|
type: "text",
|
||||||
|
text: "Hello, world!"
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
// Error content
|
||||||
|
return {
|
||||||
|
content: [{
|
||||||
|
type: "text",
|
||||||
|
text: "Error: Something went wrong"
|
||||||
|
}],
|
||||||
|
isError: true
|
||||||
|
};
|
||||||
|
|
||||||
|
// Multiple content blocks
|
||||||
|
return {
|
||||||
|
content: [
|
||||||
|
{ type: "text", text: "Line 1" },
|
||||||
|
{ type: "text", text: "Line 2" }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Resources and Prompts
|
||||||
|
|
||||||
|
You can also implement resources and prompts:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Resources
|
||||||
|
server.resource(
|
||||||
|
"resource_uri",
|
||||||
|
"Resource name",
|
||||||
|
"Resource description",
|
||||||
|
async () => ({
|
||||||
|
content: [{
|
||||||
|
type: "text",
|
||||||
|
text: "Resource content"
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Prompts
|
||||||
|
server.prompt(
|
||||||
|
"prompt_name",
|
||||||
|
"Prompt description",
|
||||||
|
{
|
||||||
|
param: z.string()
|
||||||
|
},
|
||||||
|
async ({ param }) => ({
|
||||||
|
messages: [{
|
||||||
|
role: "user",
|
||||||
|
content: { type: "text", text: `Prompt with ${param}` }
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Naming**: Use descriptive names for your servers and tools
|
||||||
|
2. **Error Handling**: Always handle errors gracefully and return meaningful error messages
|
||||||
|
3. **Validation**: Use Zod schemas to validate input parameters
|
||||||
|
4. **Documentation**: Include clear descriptions for tools and parameters
|
||||||
|
5. **Testing**: Test your server implementation before adding it to the production list
|
||||||
|
|
||||||
|
## Example: Calculator Server
|
||||||
|
|
||||||
|
Here's a complete example of a calculator server:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export function createServer() {
|
||||||
|
const server = new Server({
|
||||||
|
name: "calculator",
|
||||||
|
version: "1.0.0"
|
||||||
|
}, {
|
||||||
|
capabilities: {
|
||||||
|
tools: {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.tool(
|
||||||
|
"add",
|
||||||
|
"Add two numbers",
|
||||||
|
{
|
||||||
|
a: z.number().describe("First number"),
|
||||||
|
b: z.number().describe("Second number")
|
||||||
|
},
|
||||||
|
async ({ a, b }) => ({
|
||||||
|
content: [{
|
||||||
|
type: "text",
|
||||||
|
text: `${a} + ${b} = ${a + b}`
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
server.tool(
|
||||||
|
"multiply",
|
||||||
|
"Multiply two numbers",
|
||||||
|
{
|
||||||
|
a: z.number().describe("First number"),
|
||||||
|
b: z.number().describe("Second number")
|
||||||
|
},
|
||||||
|
async ({ a, b }) => ({
|
||||||
|
content: [{
|
||||||
|
type: "text",
|
||||||
|
text: `${a} × ${b} = ${a * b}`
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
To debug your server:
|
||||||
|
1. Check the browser console for connection errors
|
||||||
|
2. Use the MCP message monitor to see tool calls and responses
|
||||||
|
3. Add console.log statements in your tool implementations
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
- In-memory servers are cleared when the page refreshes
|
||||||
|
- They cannot persist data between sessions
|
||||||
|
- They run in the browser's JavaScript environment, so they cannot access filesystem or system resources
|
||||||
|
- Performance is limited by the browser's capabilities
|
||||||
|
|
||||||
|
For production use cases requiring persistence or system access, use external MCP servers instead.
|
||||||
Loading…
Reference in a new issue