sor-mcp-server
# 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
Scored across 3 tools
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.
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.
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.
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.