Skip to main content
Glama
README.md
# MCP Server Ollama - Decoupled Architecture

This repository contains a small blog-style application with two working flows, both using **decoupled architecture with JSON-RPC**:

1. **AI Chatbot Flow** (recommended for production): Natural language requests are converted to JSON-RPC by the AI, then executed through the MCP protocol.
2. **MCP Client Flow**: An MCP-compatible client directly calls the MCP endpoint with JSON-RPC requests.

The project is split into two services:

- **Main REST API server**: server.js
- **MCP server with Ollama integration**: mcp-server/server.js

## What the app does

The main API stores and manages posts and comments in MongoDB.

- Posts contain: title, author, category, body, createdAt
- Comments belong to a post and contain: postId, text, commenter, createdAt

The MCP server adds two higher-level interaction paths on top of that REST API.

---
## Architecture: Decoupled via JSON-RPC

### Flow 1: AI Chatbot -> JSON-RPC -> MCP -> REST API -> MongoDB

This is the **decoupled, production-recommended** flow used when a user talks to the chatbot interface or sends a request to the AI endpoint.

**Why this architecture?**
- **AI Layer** (Ollama): Focuses ONLY on understanding user intent and generating JSON-RPC requests. Does NOT know about backend details.
- **MCP Layer**: Acts as middleware to execute JSON-RPC requests using the standard MCP protocol.
- **Backend Layer**: REST API and database remain isolated from AI logic.

**Flow Steps:**
1. A user sends a message such as "Create a new post..." to the chatbot UI or to the `/ai-chatbot` endpoint.
2. The MCP server sends the message to Ollama.
3. **Ollama understands the intent and generates a JSON-RPC 2.0 request** to call the appropriate MCP tool (e.g., `create_post`).
4. The **MCP client executes that JSON-RPC request** through the MCP protocol.
5. The appropriate MCP tool is invoked, which calls the REST API.
6. The REST API updates MongoDB and returns the result.

**Separation of Concerns:**
```
User Message
    ↓
[AI Layer] Ollama 
  → Understands intent 
  → Generates JSON-RPC request
    ↓
[MCP Layer] MCP Client 
  → Sends JSON-RPC to MCP Server 
  → Executes tool
    ↓
[Backend Layer] REST API 
  → MongoDB
```

This path is used by:
- the chatbot page at `public/chatbot.html`
- the endpoint `POST /ai-chatbot` on the MCP server

### Flow 2: MCP Client -> /mcp -> MCP Tools -> REST API -> MongoDB

This flow is used when an MCP-compatible client connects to the MCP server directly.

1. The MCP client sends a JSON-RPC request to `POST /mcp`.
2. The MCP server handles initialization and tool calls.
3. The server invokes registered tools such as create_post, list_posts, update_post, delete_post, add_comment, and list_comments.
4. Each tool calls the main REST API.
5. The REST API performs the action in MongoDB.

This is the path used by MCP-compatible clients.

---
## Key Differences: Tight Coupling vs. Decoupled

| Aspect | Before (Tight Coupling) | After (Decoupled) |
|--------|----------------------|------------------|
| **AI Responsibility** | Directly calls REST API endpoints | Only understands intent, generates JSON-RPC |
| **Coupling** | AI tightly bound to backend structure | AI and backend completely decoupled |
| **Protocol** | Direct HTTP calls | Standard JSON-RPC 2.0 protocol |
| **Middleware** | None | MCP layer acts as middleware |
| **Scalability** | Difficult to replace AI or backend | Easy to swap AI model or backend service |
| **Production Ready** | Not recommended ❌ | ✓ Production-ready ✓ |
| **Standard Compliance** | Proprietary | JSON-RPC 2.0 + MCP Standard |

---
## How JSON-RPC Decoupling Works

### Example: User says "Create a tech post about AI"

**Step 1: AI generates JSON-RPC request (not direct execution)**
```json
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "create_post",
    "arguments": {
      "title": "Understanding AI",
      "author": "John Doe",
      "category": "tech",
      "body": "Artificial Intelligence is transforming how we work and live..."
    }
  },
  "id": 1
}
```

**Key Point:** Ollama ONLY generates this JSON-RPC request. It does NOT execute it directly.

**Step 2: MCP Client sends this JSON-RPC to MCP Server**
The MCP client (in the MCP server itself) sends this JSON-RPC request to the `/mcp` endpoint.

**Step 3: MCP Server executes the tool**
The MCP server routes the `create_post` tool call, which validates the input and calls the REST API.

**Step 4: REST API persists to MongoDB**
```
POST /posts → Validation → MongoDB.insert() → Returns created post
```

**Step 5: Result flows back**
```
MCP Server → MCP Client → Chatbot UI → User sees the created post
```

---
## Benefits of This Architecture

### 1. **Loose Coupling**
You can independently:
- Replace Ollama with another AI model (GPT, Claude, etc.) without changing backend
- Switch backend from REST API to gRPC without changing AI
- Deploy AI and backend in different regions or cloud providers
- Use different programming languages for each layer

### 2. **Scalability**
- Load balance MCP layer independently from AI and backend
- Cache AI responses without affecting backend performance
- Implement retry logic and circuit breakers at MCP level
- Scale AI horizontally without scaling backend

### 3. **Testability**
- AI layer testable independently (mock MCP)
- MCP layer testable independently (mock REST API)
- Backend testable independently (mock MCP layer)
- Clear unit test boundaries

### 4. **Standards Compliance**
- Uses standard **JSON-RPC 2.0 protocol** (not proprietary)
- Compatible with any **MCP-compliant client**
- Follows **Model Context Protocol specification**
- Can integrate with other MCP servers

### 5. **Production Ready**
- Proper separation of concerns
- Clear error boundaries and logging
- Middleware pattern enables monitoring at MCP level
- Request tracing across layers
- No tight coupling risks

### 6. **Maintainability**
- Changes to backend don't affect AI logic
- Updates to AI model don't require backend changes
- Clear interfaces between layers (JSON-RPC)
- Easier debugging with layer isolation

---
## Available MCP Tools

The MCP server exposes the following tools:

- **create_post**: `{title, author, category, body}` - Creates a new post
- **list_posts**: `{}` - Lists all posts
- **get_post**: `{postId}` - Gets a single post by ID
- **update_post**: `{postId, title, author, category, body}` - Updates an existing post
- **delete_post**: `{postId}` - Deletes a post (WARNING: deletes post and ALL comments)
- **add_comment**: `{postId, text, commenter}` - Adds a comment to a post
- **list_comments**: `{postId}` - Lists all comments for a post

---
## Implementation Details

### AI Layer (`processUserMessage`)
- Receives user message and context
- Sends to Ollama with system prompt focused on intent understanding
- **Ollama generates a JSON-RPC 2.0 request** (not action plan)
- Returns JSON-RPC request WITHOUT executing it

### MCP Layer (`executeMcpToolViaJsonRpc`)
- Receives JSON-RPC request from AI layer
- Validates tool name and arguments
- Executes appropriate tool logic
- Returns JSON-RPC 2.0 response

### Backend Layer (`/posts` endpoints)
- Handles REST API requests from MCP layer
- Performs MongoDB operations
- Returns results to MCP layer

### Endpoints
- **POST /ai-chatbot**: Accepts user message, returns AI-generated JSON-RPC + execution result
- **POST /mcp**: Standard MCP protocol endpoint for MCP clients
- **GET /health**: Health check endpoint

---
## Response Format from /ai-chatbot

```json
{
  "success": true,
  "jsonRpcRequest": {
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": {
      "name": "create_post",
      "arguments": {...}
    },
    "id": 1
  },
  "jsonRpcResponse": {
    "jsonrpc": "2.0",
    "result": {...},
    "id": 1
  },
  "executionTime": "245ms"
}
```

This response shows:
1. The JSON-RPC request AI generated
2. The JSON-RPC response from tool execution
3. Execution time for monitoring