# In-Memory MCP Server in ChatMCP: Architecture and Built-in Services

> Discover the in-memory MCP server in ChatMCP. This built-in JSON-RPC 2.0 server offers zero-latency access to essential tools directly within the Dart VM.

- Repository: [刀刀/chatmcp](https://github.com/daodao97/chatmcp)
- Tags: architecture
- Published: 2026-02-28

---

**The in-memory MCP server in ChatMCP is a built-in JSON-RPC 2.0 server that runs directly in the Dart VM, providing zero-latency access to mathematical utilities and artifact instruction tools without external processes or network calls.**

ChatMCP is an open-source client implementation for the Model Context Protocol (MCP) that enables AI assistants to interact with external data sources and tools. While the application supports remote MCP servers via SSE, Streamable, and STDIO transports, it also ships with a lightweight **in-memory MCP server** that runs entirely within the application process. This embedded server provides self-contained utilities that function without network dependencies or external binaries.

## What Is the In-Memory MCP Server?

The in-memory MCP server is a specialized transport implementation that instantiates server logic directly within the Dart virtual machine. Unlike STDIO servers that spawn external processes or SSE servers that establish HTTP connections, the in-memory variant operates through direct method invocation.

In `lib/mcp/mcp.dart`, the `initializeMcpServer` function detects in-memory configurations via the `"type": "inmemory"` property and routes initialization through `MemoryServerFactory.createMemoryServer`. The factory, defined in `lib/mcp/inmemory_server/factory.dart`, maps command strings like `"math"` or `"artifact_instructions"` to concrete server implementations.

The resulting server instance is wrapped in an `InMemoryClient` (`lib/mcp/inmemory/client.dart`), which implements the standard `McpClient` interface. This design allows the UI and provider layers to interact with in-memory servers using the same API as remote transports, ensuring seamless integration.

### Core Architecture and Instantiation

The `McpServerProvider` class (`lib/provider/mcp_server_provider.dart`) maintains the registry of available in-memory servers through its `defaultInMemoryServers` list. When the application initializes, the provider iterates through configured servers and invokes the factory pattern:

1. Configuration entries specify `"type": "inmemory"` and a `"command"` key
2. `MemoryServerFactory.createMemoryServer` instantiates the appropriate subclass of `MemoryServer`
3. `InMemoryClient` wraps the server and exposes `sendMessage` methods
4. The client registers with the provider's server pool for lifecycle management

Because the server runs in the same isolate as the UI, message passing occurs through direct function calls rather than serialization overhead, resulting in microsecond-level latency for tool invocations.

## Built-in Services and Tools

ChatMCP ships with two default in-memory servers that provide immediate utility without external dependencies: the MathServer for computational operations and the ArtifactServer for UI rendering guidance.

### MathServer: Arithmetic and Trigonometric Operations

The `MathServer` class (`lib/mcp/inmemory_server/math.dart`) exposes a comprehensive mathematical toolkit through the `tools/list` endpoint. The server registers twenty distinct operations:

**Arithmetic and Algebraic Functions:**
- `add`, `subtract`, `multiply`, `divide` – Basic binary operations
- `power` – Exponentiation (base, exponent)
- `sqrt`, `cbrt` – Square and cube roots
- `abs` – Absolute value
- `mod` – Modulo operation
- `factorial` – Factorial calculation for positive integers

**Trigonometric and Logarithmic Functions:**
- `sin`, `cos`, `tan` – Standard trigonometric functions (radian input)
- `log` – Natural logarithm

**Aggregation Functions:**
- `max`, `min` – Binary maximum and minimum
- `round`, `ceil`, `floor` – Rounding operations

When the client invokes `tools/call` with a tool name and arguments, `MathServer.onToolCall` dispatches to the appropriate Dart math implementation and returns the computed result in the JSON-RPC response.

### ArtifactServer: UI Rendering Instructions

The `ArtifactServer` (`lib/mcp/inmemory_server/artifact_instructions.dart`) provides a single tool, `get_artifact_instructions`, which returns a structured prompt describing how the ChatMCP interface should render artifact content.

Artifacts in ChatMCP represent distinct content blocks that the AI assistant generates—such as code snippets, SVG graphics, Mermaid diagrams, or React components. The `get_artifact_instructions` tool returns a comprehensive system prompt that guides the model on:

- When to create artifacts (distinct, self-contained content)
- Formatting requirements for artifact XML tags
- Supported artifact types and their specific constraints
- Update and deletion patterns for existing artifacts

This server ensures that the client UI and the AI assistant share a consistent protocol for rich content rendering without requiring external API calls.

## Technical Implementation Details

The in-memory server architecture relies on a carefully designed class hierarchy that abstracts JSON-RPC handling while allowing concrete servers to define specific tool logic.

### The MemoryServer Base Class

`MemoryServer` (`lib/mcp/inmemory/memory_server.dart`) extends `McpServer` and implements the core JSON-RPC message routing required by the MCP specification. It maintains an internal map of method handlers and provides default implementations for protocol-level operations:

**Lifecycle Methods:**
- `initialize` – Returns `InitializeResult` containing protocol version, server name, and capabilities (prompts, resources, tools)
- `ping` – Empty response for connection keep-alive

**Resource Management (Stubbed):**
- `resources/list`, `resources/read`, `resources/subscribe`, `resources/unsubscribe` – Return empty structures as the base class does not implement persistent resources

**Prompt Management (Stubbed):**
- `prompts/list`, `prompts/get` – Return empty lists; concrete servers may override

**Tool Execution:**
- `tools/list` – Returns the list of `Tool` objects registered by the concrete server via the abstract `tools` getter
- `tools/call` – Dispatches to `onToolCall`, which concrete subclasses must implement to handle specific tool invocations

**Logging and Completion:**
- `logging/setLevel` – No-op implementation
- `completion/complete` – Stubbed empty response

The class uses Dart's `jsonrpc2` package for message parsing and constructs `JSONRPCMessage` objects for responses.

### Client Interface: InMemoryClient

`InMemoryClient` (`lib/mcp/inmemory/client.dart`) implements the `McpClient` interface, providing a unified API for both in-memory and remote servers. It maintains a reference to a `MemoryServer` instance and forwards JSON-RPC requests:

- `sendMessage` – Directly invokes `MemoryServer.onmessage` and returns the resulting `JSONRPCMessage`
- `sendToolList` – Wraps `tools/list` method call
- `sendToolCall` – Wraps `tools/call` with tool name and arguments

Because there is no network serialization or process spawning, tool calls execute synchronously within the Dart event loop, providing immediate results.

## Configuration and Usage

In-memory servers are configured through the same JSON schema as external servers, typically in [`assets/mcp_server.json`](https://github.com/daodao97/chatmcp/blob/main/assets/mcp_server.json) or via the provider API:

```json
{
  "name": "Math",
  "type": "inmemory",
  "command": "math",
  "env": {},
  "args": []
}

```

The `command` field maps to server implementations via `MemoryServerFactory`. Valid values are `math` and `artifact_instructions`.

To initialize programmatically:

```dart
import 'package:chatmcp/mcp/mcp.dart';

final config = {
  'name': 'Math',
  'type': 'inmemory',
  'command': 'math',
  'env': {},
  'args': [],
};

final client = await initializeMcpServer(config);
await client?.initialize();

```

## Summary

- The **in-memory MCP server** is an embedded JSON-RPC 2.0 server that runs directly in the ChatMCP Dart VM, eliminating network overhead and external process dependencies.
- It is instantiated via `MemoryServerFactory.createMemoryServer` in `lib/mcp/inmemory_server/factory.dart` and wrapped by `InMemoryClient` to provide a standard `McpClient` interface.
- The architecture extends `MemoryServer` from `lib/mcp/inmemory/memory_server.dart`, which implements protocol-level MCP methods (initialize, ping, tools/list, tools/call) while leaving tool logic to concrete subclasses.
- Two built-in servers ship with ChatMCP: **MathServer** (`lib/mcp/inmemory_server/math.dart`) providing 20 mathematical tools, and **ArtifactServer** (`lib/mcp/inmemory_server/artifact_instructions.dart`) providing UI rendering guidance.
- Configuration uses standard JSON with `"type": "inmemory"`, making in-memory servers interchangeable with remote transports from the application's perspective.

## Frequently Asked Questions

### How does the in-memory MCP server differ from STDIO or SSE servers?

The in-memory MCP server runs inside the ChatMCP process within the Dart VM, while STDIO servers spawn external child processes and SSE servers establish HTTP connections to remote hosts. In `lib/mcp/mcp.dart`, the `initializeMcpServer` function routes in-memory configs to `MemoryServerFactory`, creating an `InMemoryClient` that directly invokes Dart methods rather than serializing JSON over streams or sockets. This eliminates process spawning overhead and network latency, making tool calls synchronous and instantaneous.

### What mathematical operations does the MathServer provide?

The `MathServer` class in `lib/mcp/inmemory_server/math.dart` exposes 20 distinct tools through the `tools/list` endpoint: `add`, `subtract`, `multiply`, `divide`, `power`, `sqrt`, `cbrt`, `abs`, `sin`, `cos`, `tan`, `log`, `max`, `min`, `round`, `ceil`, `floor`, `mod`, and `factorial`. When `tools/call` is invoked, the `onToolCall` method dispatches to the appropriate Dart math implementation and returns the computed integer result in the JSON-RPC response.

### Can I add custom in-memory servers to ChatMCP?

Yes, you can extend the in-memory server system by creating a new class that inherits from `MemoryServer` in `lib/mcp/inmemory/memory_server.dart`, implementing the `tools` getter and `onToolCall` method. You must then register the server in `MemoryServerFactory.createMemoryServer` in `lib/mcp/inmemory_server/factory.dart` by mapping a command string to your class constructor. Finally, add a configuration entry with `"type": "inmemory"` and your custom command to [`assets/mcp_server.json`](https://github.com/daodao97/chatmcp/blob/main/assets/mcp_server.json) or register it programmatically via `McpServerProvider.addMcpServer`.

### Where is the in-memory MCP server configuration stored?

Default in-memory server configurations reside in [`assets/mcp_server.json`](https://github.com/daodao97/chatmcp/blob/main/assets/mcp_server.json), which ships with entries for the `math` and `artifact_instructions` servers. At runtime, the `McpServerProvider` class in `lib/provider/mcp_server_provider.dart` loads these configurations and maintains the `defaultInMemoryServers` list. Users can modify the JSON file directly or use the provider's `addMcpServer` method to register additional in-memory servers dynamically during application execution.