npm package: @neoimpulse/cap-js-mcp
Description: A CDS plugin to trim string attributes automatically
Author: Neoimpulse GmbH
Latest version: 1.0.6

# CAP.js MCP Server

This plugin for the SAP Cloud Application Programming Model (CAP) provides a Model Context Protocol (MCP) server implementation. It enables AI assistants and other clients to interact with CAP applications through standardized tools, prompts, and resources.

## Features

- **MCP Tools**: Product catalog management with CRUD operations
- **MCP Prompts**: Template-based prompt system (extensible)
- **MCP Resources**: File and data resource access (extensible)
- **Authentication**: Configurable API key authentication
- **Logging**: Comprehensive request/response logging

## Installation

To install the plugin, add it to your CAP project.

```sh
npm add @neoimpulse/cap-js-mcp
```

## Configuration

Add the MCP configuration to your `package.json`:

```json
{
  "cds": {
    "requires": {
      "cap-js-mcp": {
        "apiKey": "YOUR_SECRET_API_KEY",
        "server": {
          "name": "cap-mcp-server",
          "version": "1.0.0"
        },
        "components": {
          "tools": {
            "path": "./srv/lib/mcp-tools"
          },
          "prompts": {
            "path": "./srv/lib/mcp-prompts"
          },
          "resources": {
            "path": "./srv/lib/mcp-resources"
          }
        },
        "authentication": true,
        "logging": true
      }
    }
  }
}
```

## Available Tools

### Standard CAP Tools (`mcp-tools-default.js`)

The plugin includes a **generic implementation** based on the official [SAP CAP MCP Server](https://github.com/cap-js/mcp-server). These tools work with **any CAP application** and use the compiled CDS model from the running application.

#### How It Works

The default tools leverage CAP's runtime model (`cds.model`) which is automatically compiled when your CAP application starts. This means:

- ✅ **No project path needed** - Tools use the running application's model
- ✅ **Automatic model updates** - Changes to your CDS files are reflected in the model
- ✅ **Service-aware** - Automatically detects services and their endpoints
- ✅ **Universal** - Works with any CAP project structure

#### Default Tools

1. **`search_model`** - Search for CDS definitions (entities, services, actions, etc.)
   - Fuzzy search by name
   - Filter by kind (entity, service, action, etc.)
   - Returns full CSN definitions with annotations and metadata

2. **`search_docs`** - Search CAP documentation
   - Searches code snippets and examples
   - Returns relevant documentation sections
   - *(Note: Currently a placeholder - full implementation would use vector embeddings)*

3. **`get_cds_model`** - Get the complete CDS model
   - Returns all services, entities, and definitions
   - Optional filtering of built-in types
   - Includes namespace and i18n information

4. **`get_service_endpoints`** - Get HTTP endpoints
   - Lists all OData and custom endpoints
   - Shows exposed entities per service
   - Optional filtering by service name

5. **`analyze_entity`** - Deep entity analysis
   - Element types and properties
   - Associations and compositions
   - Keys and annotations
   - Relationship mapping

6. **`execute_odata_query`** - Execute OData queries
   - Full OData v4 support ($filter, $select, $expand, etc.)
   - Direct query execution on entities
   - Service-aware query routing
   - Returns formatted JSON results

#### Using Default Tools with Extensions

You can **extend** the default tools with your custom implementations using the `extends` configuration:

```json
{
  "cds": {
    "requires": {
      "cap-js-mcp": {
        "components": {
          "tools": {
            "path": "./srv/lib/mcp-tools-example",
            "extends": "./srv/lib/mcp-tools-default"
          }
        }
      }
    }
  }
}
```

**How the Extension Mechanism Works:**

1. **Base Class Loading**: First loads the base class from `extends` path
2. **Main Class Loading**: Then loads your custom class from `path`
3. **Tool Merging**: Combines tools from both classes intelligently:
   - ✅ **Inherit**: Base tools not present in main class are added
   - 🔄 **Override**: Main class tools replace base tools with same name
   - 📦 **Combine**: Both sets of tools are available in the final instance

**Example Scenario:**

```javascript
// Base class (mcp-tools-default.js) provides:
- search_model
- search_docs
- get_cds_model
- analyze_entity
- execute_odata_query

// Your class (mcp-tools-example.js) provides:
- get_products
- create_product
- search_model (custom implementation)

// Result after merging:
- search_model         (from YOUR class - overridden)
- search_docs          (inherited from base)
- get_cds_model        (inherited from base)
- analyze_entity       (inherited from base)
- execute_odata_query  (inherited from base)
- get_products         (from YOUR class)
- create_product       (from YOUR class)
```

**Console Output During Loading:**
```
🔧 Loading tools from: ./srv/lib/mcp-tools-example
   ⬆️  Extends: ./srv/lib/mcp-tools-default
   📚 Loading base class from: ./srv/lib/mcp-tools-default
   ✅ Base class loaded successfully
   ✅ Main class loaded successfully
   🔗 Inheriting tool: search_docs
   🔗 Inheriting tool: get_cds_model
   🔗 Inheriting tool: analyze_entity
   🔗 Inheriting tool: execute_odata_query
   🔄 Overriding tool: search_model
✅ tools loaded successfully with inheritance
   📊 Total tools: 7
```

**Benefits:**
- ✅ **No Code Duplication**: Keep generic CAP functionality from base
- ✅ **Selective Override**: Replace only specific tools you need to customize
- ✅ **Composition**: Add domain-specific tools alongside generic ones
- ✅ **Maintainability**: Base updates don't break your custom code

#### Example: Using Default Tools

```javascript
// Search for all entities in the model
const entities = await mcpClient.callTool("search_model", {
  kind: "entity",
  topN: 10
});

// Find a specific service by name
const service = await mcpClient.callTool("search_model", {
  name: "CatalogService",
  kind: "service",
  topN: 1
});

// Analyze an entity structure
const bookAnalysis = await mcpClient.callTool("analyze_entity", {
  entityName: "CatalogService.Books"
});

// Get all service endpoints
const endpoints = await mcpClient.callTool("get_service_endpoints", {});

// Execute an OData query
const books = await mcpClient.callTool("execute_odata_query", {
  entityName: "CatalogService.Books",
  filter: "stock > 0",
  select: "ID,title,price",
  orderby: "price desc",
  top: 10
});

// Execute query with expand
const booksWithAuthor = await mcpClient.callTool("execute_odata_query", {
  entityName: "CatalogService.Books",
  select: "ID,title,price",
  expand: "author",
  filter: "price < 30"
});
```

---

### Product Management (Demo Tools)

⚠️ **Note**: The built-in product catalog tools are for demonstration and testing purposes only. They use in-memory data storage and are not intended for production use. In a real application, you would implement tools that interact with your actual CAP services and data models.

The MCP server comes with built-in product catalog management tools:

- `get_products` - Get all products from the catalog
- `get_product` - Get a single product by ID with full details
- `create_product` - Create a single product
- `create_products` - Create multiple products
- `change_product` - Update a single product
- `change_products` - Update multiple products
- `remove_product` - Remove a single product by ID
- `remove_products` - Remove multiple products by IDs

### Example Usage

```javascript
// Get all products from the catalog
const products = await mcpClient.callTool("get_products", {});

// Get a specific product by ID
const product = await mcpClient.callTool("get_product", { id: 1 });

// Create a new product
const newProduct = await mcpClient.callTool("create_product", {
  name: "MacBook Air M3",
  price: 1299.99,
  inStock: true,
  category: "Laptops",
  description: "Apple MacBook Air with M3 chip"
});

// Create multiple products at once
const multipleProducts = await mcpClient.callTool("create_products", {
  products: [
    {
      name: "iPad Pro",
      price: 999.99,
      inStock: true,
      category: "Tablets",
      description: "iPad Pro with M2 chip"
    },
    {
      name: "AirPods Pro",
      price: 279.99,
      inStock: false,
      category: "Audio",
      description: "Wireless earbuds with noise cancellation"
    }
  ]
});

// Update a single product
const updatedProduct = await mcpClient.callTool("change_product", {
  id: 1,
  price: 2799.99,
  inStock: false
});

// Update multiple products
const updatedProducts = await mcpClient.callTool("change_products", {
  products: [
    { id: 2, inStock: true },
    { id: 5, price: 299.99 }
  ]
});

// Remove a single product
const removedProduct = await mcpClient.callTool("remove_product", { id: 3 });

// Remove multiple products
const removedProducts = await mcpClient.callTool("remove_products", { 
  ids: [4, 5] 
});
```

## How It Works

The plugin automatically registers as a CDS plugin and exposes MCP endpoints:

1. **Tools**: Executable functions that perform operations
2. **Prompts**: Template-based text generation (extensible)
3. **Resources**: Access to files and data resources (extensible)

The server includes sample product data for testing:
- MacBook Pro 16 (€2999.00)
- Dell XPS 13 (€1299.99)
- iPhone 15 Pro (€1199.00)
- Samsung Galaxy S24 (€899.99)
- Sony WH-1000XM5 (€349.99)

**Important**: This demo data is stored in memory and will be reset when the server restarts. For production use, replace the demo tools with implementations that connect to your actual CAP services and persistent data storage.

## Architecture

```
srv/
├── lib/
│   ├── mcp-tools-default.js     # Generic CAP tools (base implementation)
│   ├── mcp-tools-example.js     # Demo product management tools (extends default)
│   ├── mcp-prompts-example.js   # Prompt templates (extensible)
│   └── mcp-resources-example.js # Resource handlers (extensible)
└── mcp-server.js                # Main MCP server with extension loader
```

### Extension Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                     cds-plugin.js                            │
│  ┌──────────────────────────────────────────────────────┐  │
│  │    loadComponentWithInheritance()                     │  │
│  │                                                        │  │
│  │  1. Load Base Class (if extends is configured)       │  │
│  │     ↓                                                  │  │
│  │  2. Instantiate Base → baseInstance                   │  │
│  │     ↓                                                  │  │
│  │  3. Load Main Class                                   │  │
│  │     ↓                                                  │  │
│  │  4. Instantiate Main → mainInstance                   │  │
│  │     ↓                                                  │  │
│  │  5. Merge: baseInstance.tools → mainInstance.tools   │  │
│  │     • Inherit: Tools not in main                      │  │
│  │     • Override: Tools in both (main wins)             │  │
│  │     ↓                                                  │  │
│  │  6. Return merged mainInstance                        │  │
│  └──────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────┐      ┌─────────────────────┐
│ mcp-tools-default   │      │ mcp-tools-example   │
├─────────────────────┤      ├─────────────────────┤
│ • search_model      │      │ • get_products      │
│ • search_docs       │  ←─  │ • get_product       │
│ • get_cds_model     │ extends │ • create_product    │
│ • analyze_entity    │      │ • change_product    │
│ • execute_odata_query│     │ • remove_product    │
│ • get_service_...   │      │ (+ inherits all →)  │
└─────────────────────┘      └─────────────────────┘
         ↓                            ↓
         └────────────────┬───────────┘
                          ↓
              ┌───────────────────────┐
              │   Merged Instance     │
              ├───────────────────────┤
              │ All 11+ tools         │
              │ available to clients  │
              └───────────────────────┘
```

### Configuration Flow

```json
// package.json
{
  "cds": {
    "requires": {
      "cap-js-mcp": {
        "components": {
          "tools": {
            "path": "./srv/lib/mcp-tools-example",
            "extends": "./srv/lib/mcp-tools-default"  ← Extension config
          }
        }
      }
    }
  }
}
```

**Loading Sequence:**
1. **Bootstrap**: `cds.on("bootstrap")` triggered
2. **Load Components**: `loadComponents()` called
3. **Extension Check**: Reads `extends` from config
4. **Base Loading**: Requires and instantiates base class
5. **Main Loading**: Requires and instantiates main class
6. **Merging**: Combines tools/prompts/resources intelligently
7. **Registration**: Registers all tools with MCP server
8. **Ready**: Server starts handling requests

### Component Structure

#### `mcp-tools-default.js` - Generic CAP Tools

This is the **core implementation** inspired by the official [@cap-js/mcp-server](https://github.com/cap-js/mcp-server). It provides:

**Key Features:**
- **Runtime Model Access**: Uses `cds.model` from the running CAP application
- **Fuzzy Search**: Modified Levenshtein distance algorithm for flexible name matching
- **Endpoint Discovery**: Automatically maps services to HTTP endpoints
- **OData Query Execution**: Direct query execution with full OData v4 support
- **Service Awareness**: Detects and connects to CAP services

**Technical Implementation:**
```javascript
class MCPToolsDefault {
  async _getModel() {
    // Uses cds.model if available (runtime)
    // Falls back to compiling from project if needed
    return cds.model;
  }
  
  _fuzzyTopN(searchTerm, list, n) {
    // Levenshtein distance with:
    // - 0.5 cost for insertions/deletions
    // - 1.0 cost for substitutions
    // - 0 cost for exact matches
  }
  
  _addEndpointInformation(compiled, serviceInfo) {
    // Enriches definitions with HTTP endpoints
    // Maps OData paths to entities
    // Handles auto-exposed entities
  }
}
```

#### `mcp-tools-example.js` - Demo Tools

Example implementation showing how to create custom domain-specific tools:
- In-memory data storage (for demo purposes)
- CRUD operations on product catalog
- Type-safe schemas with validation

#### Extension Pattern

The plugin supports **composition over inheritance** through a sophisticated merging mechanism:

**Configuration-Based Extension:**
```json
{
  "tools": {
    "path": "./srv/lib/my-tools",
    "extends": "./srv/lib/mcp-tools-default"
  }
}
```

**How It Works Internally:**

```javascript
// In cds-plugin.js - loadComponentWithInheritance()

function loadComponentWithInheritance(componentType, config, defaultPath) {
  // 1. Load main component class
  const MainComponentClass = require(config.path);
  
  // 2. If extends is specified, load base class
  if (config.extends) {
    const BaseComponentClass = require(config.extends);
    const baseInstance = new BaseComponentClass();
    const mainInstance = new MainComponentClass();
    
    // 3. Merge tools from base into main
    for (const [toolName, toolDef] of baseInstance.tools.entries()) {
      if (!mainInstance.tools.has(toolName)) {
        // Inherit: Tool not in main class
        mainInstance.tools.set(toolName, toolDef);
      } else {
        // Override: Tool exists in main class
        console.log(`🔄 Overriding tool: ${toolName}`);
      }
    }
    
    return mainInstance;
  }
  
  // 4. No inheritance - just return main instance
  return new MainComponentClass();
}
```

**Extension Strategies:**

1. **Pure Extension** (Recommended):
   ```javascript
   // Your custom-tools.js
   class CustomTools {
     constructor() {
       this.tools = new Map();
       this._initializeTools();
     }
     
     _initializeTools() {
       // Only define YOUR custom tools
       this.tools.set("custom_tool", { ... });
     }
   }
   ```
   **Result**: Base tools + Your tools (no conflicts)

2. **Selective Override**:
   ```javascript
   // Your custom-tools.js
   class CustomTools {
     _initializeTools() {
       // Override a specific tool
       this.tools.set("search_model", {
         // Your custom implementation
       });
       
       // Add new tools
       this.tools.set("custom_tool", { ... });
     }
   }
   ```
   **Result**: Your `search_model` replaces base's, other base tools inherited

3. **Full Override** (Not Recommended):
   ```javascript
   // Your custom-tools.js extends base
   class CustomTools extends MCPToolsDefault {
     _initializeTools() {
       super._initializeTools(); // Keep base tools
       
       // Add your tools
       this.tools.set("custom_tool", { ... });
     }
   }
   ```
   **Result**: Same as configuration-based extension, but harder to maintain

**Applies to All Components:**
- ✅ **Tools** (`tools.extends`)
- ✅ **Prompts** (`prompts.extends`)
- ✅ **Resources** (`resources.extends`)

**Multiple Levels of Extension:**
```json
{
  "tools": {
    "path": "./srv/lib/my-production-tools",
    "extends": "./srv/lib/my-base-tools"
  }
}
```
Where `my-base-tools` could also extend another base:
```javascript
// my-base-tools.js
class MyBaseTools extends MCPToolsDefault { ... }
```

## Extending the Server

### Recommended Approach: Combine Default + Custom Tools

The **best practice** is to use the default tools for generic CAP operations and add your own domain-specific tools:

```json
{
  "cds": {
    "requires": {
      "cap-js-mcp": {
        "components": {
          "tools": {
            "path": "./srv/lib/my-business-tools",
            "extends": "./srv/lib/mcp-tools-default"
          }
        }
      }
    }
  }
}
```

**Why this approach?**
- ✅ Keep generic CAP functionality (model search, entity analysis)
- ✅ Add business-specific operations (order processing, inventory management)
- ✅ No need to reimplement standard features
- ✅ AI assistants get both CAP knowledge and domain knowledge

### Debugging Extension Loading

**Check Health Endpoint:**
```bash
curl http://localhost:4004/mcp/health
```

**Response shows loaded components:**
```json
{
  "status": "healthy",
  "available": {
    "tools": [
      "search_model",
      "search_docs", 
      "get_cds_model",
      "analyze_entity",
      "execute_odata_query",
      "get_products",
      "create_product"
    ]
  },
  "config": {
    "components": {
      "tools": "./srv/lib/mcp-tools-example"
    }
  }
}
```

**Server Console Output:**
```
🔧 Loading tools from: ./srv/lib/mcp-tools-example
   ⬆️  Extends: ./srv/lib/mcp-tools-default
   📚 Loading base class from: ./srv/lib/mcp-tools-default
   ✅ Base class loaded successfully
🔧 Initialized 5 default MCP tools
   ✅ Main class loaded successfully
🔧 Initialized 10 MCP tools
   🔗 Inheriting tool: search_docs
   🔗 Inheriting tool: get_cds_model
   🔗 Inheriting tool: analyze_entity
   🔗 Inheriting tool: execute_odata_query
✅ tools loaded successfully with inheritance
   📊 Total tools: 15
```

**Reload Components at Runtime:**
```bash
curl -X POST http://localhost:4004/mcp/reload \
  -H "Authorization: Basic <your-api-key>"
```

This reloads all components without restarting the server - useful during development!

### Use Cases

#### 1. **Model Exploration for AI Assistants**
Use default tools to help AI understand your data model:
```javascript
// AI: "What entities are in the catalog service?"
search_model({ kind: "entity", name: "catalog" })

// AI: "Show me the structure of the Books entity"
analyze_entity({ entityName: "CatalogService.Books" })
```

#### 2. **Data Querying for AI Agents**
Enable AI to query your data:
```javascript
// AI: "Show me expensive books"
execute_odata_query({ 
  entityName: "CatalogService.Books",
  filter: "price > 50",
  orderby: "price desc"
})

// AI: "Find out-of-stock products"
execute_odata_query({
  entityName: "ProductService.Products",
  filter: "stock eq 0",
  select: "ID,name,category"
})
```

#### 3. **Custom Business Logic**
Add domain-specific tools alongside defaults:
```javascript
class BusinessTools extends MCPToolsDefault {
  _initializeTools() {
    super._initializeTools(); // Keep CAP tools
    
    // Add custom business operations
    this.tools.set("process_order", {
      definition: { /* ... */ },
      handler: async (args) => {
        // Your business logic
        const srv = await cds.connect.to('OrderService');
        return await srv.send('processOrder', args);
      }
    });
  }
}
```

### Using Custom Implementations

You can replace the demo components with your own implementations by changing the component paths in your configuration:

```json
{
  "cds": {
    "requires": {
      "cap-js-mcp": {
        "apiKey": "YOUR_SECRET_API_KEY",
        "components": {
          "tools": {
            "path": "./srv/lib/my-custom-tools"
          },
          "prompts": {
            "path": "./srv/lib/my-custom-prompts" 
          },
          "resources": {
            "path": "./srv/lib/my-custom-resources"
          }
        }
      }
    }
  }
}
```

This allows you to:
- **Replace demo tools** with production-ready implementations that interact with your CAP services
- **Add custom prompts** for your specific business domain
- **Provide custom resources** like files, documents, or other data sources

### Adding Custom Tools

Extend the `MCPTools` class to add your own tools:

```javascript
// In your custom tools file
class CustomTools extends MCPTools {
  _initializeTools() {
    super._initializeTools();
    
    this.tools.set("my_custom_tool", {
      definition: {
        name: "my_custom_tool",
        description: "My custom tool description",
        inputSchema: {
          type: "object",
          properties: {
            param: { type: "string" }
          },
          required: ["param"]
        }
      },
      handler: async (args) => {
        return `Custom result: ${args.param}`;
      }
    });
  }
}
```

### Adding Prompts and Resources

Similar patterns can be used to extend prompts and resources functionality.

## Connecting to MCP Clients

### FAQ & Troubleshooting

**Q: Why aren't my custom tools showing up?**

A: Check these points:
1. Verify your class exports correctly: `module.exports = MyTools;`
2. Check constructor initializes the `tools` Map: `this.tools = new Map();`
3. Implement required methods: `getToolDefinitions()`, `executeToolHandler()`, etc.
4. Check console output during startup for loading errors
5. Visit `/mcp/health` to see what tools are actually loaded

**Q: Can I use inheritance AND the extends configuration?**

A: Yes! Both work together:
```javascript
// my-tools.js - uses JavaScript inheritance
class MyTools extends MCPToolsDefault {
  _initializeTools() {
    super._initializeTools(); // Get base tools
    this.tools.set("my_tool", { ... }); // Add yours
  }
}
```
```json
// package.json - uses configuration extension
{
  "tools": {
    "path": "./srv/lib/my-tools",
    "extends": "./srv/lib/some-other-base"
  }
}
```
Result: `my-tools` inherits from `MCPToolsDefault` (code) AND `some-other-base` (config)

**Q: How do I override only specific tools?**

A: Define only the tools you want to override in your class:
```javascript
class MyTools {
  constructor() {
    this.tools = new Map();
    this._initializeTools();
  }
  
  _initializeTools() {
    // Override search_model only
    this.tools.set("search_model", {
      definition: { /* your definition */ },
      handler: async (args) => { /* your logic */ }
    });
    
    // Other base tools will be inherited automatically
  }
}
```

**Q: Can I extend multiple base classes?**

A: Not directly, but you can chain extensions:
```
Base1 → Base2 → YourClass
```
Configure: `YourClass` extends `Base2`, and `Base2` extends `Base1` in code.

**Q: Do I need to restart the server after changing my tools?**

A: No! Use the reload endpoint:
```bash
curl -X POST http://localhost:4004/mcp/reload \
  -H "Authorization: Basic <your-key>"
```

**Q: What happens if base and main have the same tool?**

A: Main class wins (override behavior). You'll see in console:
```
🔄 Overriding tool: search_model
```

### GitHub Copilot Integration

To connect your CAP.js MCP server to GitHub Copilot, add the server configuration to your MCP settings.

Create a file `.vscode/mcp.json` in your project root or workspace:

```json
{
  "servers": {
    "catalog": {
      "type": "http",
      "url": "https://your-app-domain.cfapps.region.hana.ondemand.com/mcp",
      "headers": {
        "Authorization": "Basic <base64-encoded-api-key>"
      }
    }
  }
}
```

### Generating the Authorization Header

The authorization header uses Basic authentication with your API key:

```bash
# Encode your API key (replace with your actual key)
echo -n "apiKey:YOUR_SECRET_API_KEY" | base64
```

Use the output as the Authorization header value: `Basic <base64-output>`

### Testing the Connection

Once configured, you can test the MCP tools in GitHub Copilot:

```
@catalog Can you show me all available products?
```

```
@catalog Create a new laptop product with the name "ThinkPad X1" priced at €1899
```

## License

This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for more details.

## Technical Details

### Quick Reference: Extension Configuration

```json
// No extension - standalone
{
  "tools": {
    "path": "./srv/lib/my-tools"
  }
}

// Simple extension - inherit from default
{
  "tools": {
    "path": "./srv/lib/my-tools",
    "extends": "./srv/lib/mcp-tools-default"
  }
}

// Chain extension - multiple levels
{
  "tools": {
    "path": "./srv/lib/production-tools",
    "extends": "./srv/lib/base-tools"
  }
}
// where base-tools.js also extends another class

// All components support extension
{
  "tools": {
    "path": "./srv/lib/my-tools",
    "extends": "./srv/lib/mcp-tools-default"
  },
  "prompts": {
    "path": "./srv/lib/my-prompts",
    "extends": "./srv/lib/base-prompts"
  },
  "resources": {
    "path": "./srv/lib/my-resources",
    "extends": "./srv/lib/base-resources"
  }
}
```

### Extension Behavior Matrix

| Scenario | Base Has | Main Has | Result | Logged As |
|----------|----------|----------|--------|-----------|
| Inherit | `tool_a` | - | `tool_a` from base | 🔗 Inheriting |
| Override | `tool_a` | `tool_a` | `tool_a` from main | 🔄 Overriding |
| Add New | - | `tool_b` | `tool_b` from main | ✨ (no log) |
| Combine | `tool_a`, `tool_b` | `tool_c` | All three | Mix of above |

### Default Tools Implementation

The `mcp-tools-default.js` implementation is inspired by the official [@cap-js/mcp-server](https://github.com/cap-js/mcp-server) and provides:

#### Fuzzy Search Algorithm
Uses a modified Levenshtein distance with weighted costs:
- **Insertions/Deletions**: 0.5 cost
- **Substitutions**: 1.0 cost
- **Exact matches**: 0 cost
- **Substring matches**: 0.1 cost

This allows flexible searching like:
- `"book"` → finds `"Books"`, `"Bookshop"`, `"BookService"`
- `"catalog"` → finds `"CatalogService"`, `"ProductCatalog"`

#### Model Compilation
The tools use CAP's model compilation chain:
1. `cds.resolve()` - Find all CDS files
2. `cds.load()` - Parse and load with docs/locations
3. `cds.compile.for.nodejs()` - Include drafts and effective types
4. `cds.compile.to.serviceinfo()` - Extract service metadata

#### OData Query Execution
Direct query execution using CDS Query Language (CQL):
- Translates OData parameters to CQL
- Service-aware routing (uses service instances if available)
- Fallback to local execution (`cds.run()`)
- Full support for: `$filter`, `$select`, `$expand`, `$orderby`, `$top`, `$skip`, `$count`

#### Endpoint Discovery
Automatically enriches the model with HTTP endpoints:
- Detects OData services and their paths
- Maps entities to endpoints (e.g., `/odata/v4/catalog/Books`)
- Filters auto-exposed entities
- Handles draft entities and contained entities

### Comparison: Default vs. Example Tools

| Feature | `mcp-tools-default.js` | `mcp-tools-example.js` |
|---------|------------------------|------------------------|
| **Purpose** | Generic CAP operations | Domain-specific demo |
| **Data Source** | CDS Model (`cds.model`) | In-memory array |
| **Production Ready** | ✅ Yes | ❌ Demo only |
| **Model Awareness** | ✅ Full CSN access | ❌ No model integration |
| **OData Support** | ✅ Query execution | ❌ Not applicable |
| **Service Integration** | ✅ Connects to services | ❌ Standalone |
| **Use Case** | AI model exploration, data querying | Testing, examples |

### Performance Considerations

**Model Caching:**
- The CDS model is compiled once and cached in `cds.model`
- Subsequent tool calls reuse the cached model
- Model updates are handled automatically by CAP

**Query Optimization:**
- Direct service connection when available
- Connection pooling managed by CAP
- Efficient fuzzy search with early termination

**Memory Usage:**
- Default tools: Minimal (uses existing `cds.model`)
- Example tools: ~5KB for demo product data

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Keywords

- CAP
- CDS
- MCP
- Model Context Protocol
- AI Assistant
- Tools
- Prompts
- Resources

## Acknowledgments

Thanks to the SAP CAP community and the MCP specification contributors for their support and contributions.