Skip to content

Commit 92059a3

Browse files
committed
Adding automatic schema validation
1 parent c4d0fe3 commit 92059a3

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

provider/modelcontextprotocoltools/index.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ describe('Module exports', () => {
8080
const isValidInput = ajv.validate(inputSchema, validInput);
8181
console.log('Valid input:', isValidInput, validInput);
8282

83+
const items = await proxy.items!({ mention: { uri: 'test', title: 'echo', data: { message: 'hello' } } }, {})
84+
console.log(items)
85+
8386

8487
// While we can't test types directly, we can verify the module has exports
8588
// expect(mentions.length).toBeGreaterThan(0)

provider/modelcontextprotocoltools/index.ts

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88

99
} from '@modelcontextprotocol/sdk/types.js'
1010
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
11-
11+
import Ajv from 'ajv';
1212
import { createServer } from "./everything.js";
1313
import type {
1414
Item,
@@ -59,6 +59,7 @@ async function createClient(
5959

6060
class MCPToolsProxy implements Provider {
6161
private mcpClient?: Promise<Client>
62+
private toolSchemas: Map<string, any> = new Map() // Add this line to store schemas
6263

6364
async meta(settings: ProviderSettings): Promise<MetaResult> {
6465
const nodeCommand: string = (settings.nodeCommand as string) ?? 'node'
@@ -88,7 +89,6 @@ class MCPToolsProxy implements Provider {
8889
},
8990
}
9091
}
91-
9292
async mentions?(params: MentionsParams, _settings: ProviderSettings): Promise<MentionsResult> {
9393
if (!this.mcpClient) {
9494
return []
@@ -99,6 +99,9 @@ class MCPToolsProxy implements Provider {
9999
const { tools } = toolsResp
100100
const mentions: Mention[] = []
101101
for (const tool of tools) {
102+
// Store the schema in the Map using tool name as key
103+
this.toolSchemas.set(tool.name, JSON.stringify(tool.inputSchema))
104+
102105
const r = {
103106
uri: tool.uri,
104107
title: tool.name,
@@ -126,17 +129,45 @@ class MCPToolsProxy implements Provider {
126129

127130
return [...prefixMatches, ...substringMatches]
128131
}
132+
// Add a method to get the stored schema
133+
getToolSchema(toolName: string): any {
134+
return this.toolSchemas.get(toolName)
135+
}
129136

130137
async items?(params: ItemsParams, _settings: ProviderSettings): Promise<ItemsResult> {
131-
if ( !this.mcpClient) {
138+
if (!this.mcpClient) {
132139
return []
133140
}
134141
const mcpClient = await this.mcpClient
142+
143+
// Get the tool name and validate its input
144+
const toolName = params.mention?.title
145+
const toolInput = params.mention?.data
146+
147+
if (toolName && toolInput) {
148+
// Get the stored schema for this tool
149+
const schema = JSON.parse(this.toolSchemas.get(toolName) as string)
150+
console.log("we have the schema", schema)
151+
if (schema) {
152+
// Validate the input against the schema
153+
const Ajv = require("ajv");
154+
const ajv = new Ajv()
155+
const isValid = ajv.validate(schema, toolInput)
156+
157+
if (!isValid) {
158+
console.error('Invalid tool input:', ajv.errors)
159+
throw new Error(`Invalid input for tool ${toolName}: ${JSON.stringify(ajv.errors)}`)
160+
}
161+
}
162+
}
163+
135164
const response = await mcpClient.request(
136165
{
137166
method: 'tools/call' as const,
138-
params: { name: params.mention?.title,
139-
arguments: params.mention?.data },
167+
params: {
168+
name: toolName,
169+
arguments: toolInput
170+
},
140171
},
141172
CallToolResultSchema,
142173
)

0 commit comments

Comments
 (0)