Skip to main content
Glama
README.md
# SOR MCP Server - Context Efficiency Testing

A sample MCP server designed to test context efficiency with LLM clients. Contains **174 backend SOR (System of Record) CRUD tools** but exposes only **3 meta-tools** to clients.

## The Problem

When you expose many tools to an LLM, each tool's name, description, and schema consumes context tokens. With 174 tools and complex schemas, this could easily be **50,000+ tokens** just for tool definitions.

## The Solution

Instead of exposing all 174 tools directly, this server exposes only **3 meta-tools**:

| Tool | Purpose |
|------|---------|
| `search_tools` | Search through tools, returns only relevant ones with filtered schemas |
| `execute_tool` | Execute any tool by name with parameters |
| `get_tool_schema` | Get detailed schema for a specific tool |

**Result: ~98% context reduction** (~1,000 tokens vs ~50,000 tokens)

---

## Quick Start

### 1. Install dependencies
```bash
npm install
```

### 2. Add to Claude Desktop

**macOS:** Edit `~/Library/Application Support/Claude/claude_desktop_config.json`

**Windows:** Edit `%APPDATA%\Claude\claude_desktop_config.json`

Add this to the `mcpServers` object:

```json
{
  "mcpServers": {
    "sor-mcp-server": {
      "command": "node",
      "args": ["/FULL/PATH/TO/mcp-test/src/index.js"]
    }
  }
}
```

> **Important:** Replace `/FULL/PATH/TO/` with the actual absolute path to this repo.

### 3. Restart Claude Desktop
- Quit Claude completely (Cmd+Q / Alt+F4)
- Reopen Claude Desktop
- You should see the MCP server connected with 3 tools

---

## How It Works

### Search Algorithm

1. **Pre-built Index:** Each tool has searchable text combining name + description + tags
2. **Keyword Scoring:** Query terms are matched against the index
   - +1.0 for partial match
   - +0.5 bonus for exact word boundary match
3. **Schema Filtering:** Only schema fields relevant to your query are returned

**Example:**
```
Query: "assign ticket user"

Results:
1. ticket_assign (score: 4.5) ← matches all 3 terms
2. ticket_add_watcher (score: 3.0)
3. user_create (score: 1.5)
```

### Schema Filtering

Instead of returning a 60-field ticket schema, it returns only fields matching your query:

```
Query: "create ticket with priority"

Returns only: id, title, type, status, priority, description
(not: sla, environment, watchers, attachments, etc.)
```

---

## The 3 Exposed Tools

### 1. `search_tools`

Search through 174 backend tools with natural language.

```json
{
  "query": "create user with email",
  "limit": 5,
  "include_schema": true,
  "category": "user",
  "operation": "create"
}
```

**Parameters:**
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `query` | string | Yes | Natural language search |
| `limit` | number | No | Max results (default: 5) |
| `include_schema` | boolean | No | Include filtered schemas (default: true) |
| `category` | string | No | Filter by entity type |
| `operation` | string | No | Filter by: create, read, update, delete, auth, execute |

---

### 2. `execute_tool`

Execute any backend tool by name.

```json
{
  "tool_name": "user_create",
  "params": {
    "email": "john@example.com",
    "first_name": "John",
    "last_name": "Doe"
  }
}
```

**Parameters:**
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `tool_name` | string | Yes | Exact tool name |
| `params` | object | Yes | Tool parameters |

---

### 3. `get_tool_schema`

Get complete or filtered schema for a specific tool.

```json
{
  "tool_name": "ticket_create",
  "query": "priority status"
}
```

**Parameters:**
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `tool_name` | string | Yes | Exact tool name |
| `query` | string | No | Filter to relevant fields only |

---

## Backend Tools (174 total)

### CRUD Operations (8 per entity × 18 entities = 144 tools)

| Operation | Description |
|-----------|-------------|
| `{entity}_create` | Create a new record |
| `{entity}_get` | Get by ID |
| `{entity}_list` | List/search with pagination |
| `{entity}_update` | Update a record |
| `{entity}_delete` | Delete (soft by default) |
| `{entity}_batch_create` | Bulk create |
| `{entity}_batch_update` | Bulk update |
| `{entity}_batch_delete` | Bulk delete |

### Entities (18)

| Category | Entities |
|----------|----------|
| Core | User, Organization, Project |
| Work | Ticket, Comment, Sprint |
| Config | Workflow, Webhook, SLA Policy |
| System | Notification, Audit Log, API Key |
| Extensions | Integration, Custom Field, Tag |
| Content | Attachment, Report, Time Entry |

### Special Tools (30 additional)

| Category | Tools |
|----------|-------|
| Auth | `user_authenticate`, `user_change_password`, `user_reset_password`, `user_enable_2fa`, `user_invite` |
| Org | `organization_add_member`, `organization_remove_member`, `organization_list_members` |
| Project | `project_add_member`, `project_remove_member`, `project_get_metrics` |
| Ticket | `ticket_assign`, `ticket_transition`, `ticket_add_watcher`, `ticket_link`, `ticket_log_time`, `ticket_get_history` |
| Sprint | `sprint_start`, `sprint_complete`, `sprint_add_issue`, `sprint_remove_issue`, `sprint_get_burndown` |
| Reports | `report_run`, `report_export`, `audit_log_search`, `audit_log_export` |
| Webhook | `webhook_test`, `webhook_get_deliveries` |
| Notification | `notification_mark_read`, `notification_get_unread_count` |

---

## Schema Complexity

Intentionally complex schemas for realistic testing:

| Entity | Fields | Nested Objects |
|--------|--------|----------------|
| User | 24+ | preferences, metadata, billing_info |
| Organization | 18+ | settings, compliance, billing, limits |
| Ticket | 40+ | customer, environment, sla, attachments, linked_issues |
| Workflow | 15+ | statuses[], transitions[], automations[] |

---

## Context Efficiency Comparison

| Approach | Est. Tokens | Tools Available |
|----------|-------------|-----------------|
| All 174 tools exposed | ~50,000+ | 174 |
| 3 meta-tools | ~1,000 | 174 (via search) |
| **Savings** | **~98%** | Same functionality |

---

## Testing

### Run the server directly
```bash
npm start
```

### Test search locally
```bash
node -e "
import { allTools, toolIndex, toolCount } from './src/tools.js';
console.log('Total tools:', toolCount);
"
```

---

## File Structure

```
mcp-test/
├── src/
│   ├── index.js      # MCP server, exposes 3 tools
│   ├── tools.js      # 174 backend tool definitions
│   └── schemas.js    # Complex entity schemas
├── package.json
└── README.md
```

---

## License

MIT

TDQS

A4.1/5.0

Scored across 3 tools

Disambiguation5/5

Each tool has a clearly distinct role: search_tools is for discovery, get_tool_schema is for inspecting a known tool's schema, and execute_tool is for running the selected tool. The overlap between search_tools returning schema fields and get_tool_schema providing full schema is managed well by the descriptions.

Naming Consistency5/5

All tool names follow a consistent lowercase verb_noun pattern: search_tools, execute_tool, get_tool_schema. This makes the tool set predictable and easy to navigate.

Tool Count5/5

Although only 3 tools are exposed, this is appropriate for a meta-server that dynamically accesses 174 underlying CRUD tools. Each tool earns its place in the discover-schema-execute workflow, so the count is well-scoped rather than thin.

Completeness4/5

The set covers the full meta-workflow: discover tools, inspect schemas, and execute operations. A minor gap is the lack of an explicit list-all-tools operation, though search_tools likely covers discovery if used with a broad query.

Maintenance

ActivityInactive
ResponsivenessNo issues