Skip to content

Commit db35622

Browse files
authored
Merge pull request #35 from supabase-community/fix/tool-default-values
fix: tool param not set to default value when omitted
2 parents cdabea4 + 3f13b01 commit db35622

File tree

4 files changed

+126
-19
lines changed

4 files changed

+126
-19
lines changed

packages/mcp-server-supabase/src/server.test.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -843,9 +843,7 @@ describe('tools', () => {
843843
service: invalidService,
844844
},
845845
});
846-
await expect(getLogsPromise).rejects.toThrow(
847-
`unsupported log service type: invalid-service`
848-
);
846+
await expect(getLogsPromise).rejects.toThrow('Invalid enum value');
849847
});
850848

851849
test('create branch', async () => {

packages/mcp-server-supabase/src/server.ts

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -178,16 +178,13 @@ export function createSupabaseMcpServer(options: SupabaseMcpServerOptions) {
178178
),
179179
organization_id: z.string(),
180180
confirm_cost_id: z
181-
.string()
181+
.string({
182+
required_error:
183+
'User must confirm understanding of costs before creating a project.',
184+
})
182185
.describe('The cost confirmation ID. Call `confirm_cost` first.'),
183186
}),
184187
execute: async ({ name, region, organization_id, confirm_cost_id }) => {
185-
if (!confirm_cost_id) {
186-
throw new Error(
187-
'User must confirm understanding of costs before creating a project.'
188-
);
189-
}
190-
191188
const cost = await getNextProjectCost(
192189
managementApiClient,
193190
organization_id
@@ -513,16 +510,13 @@ export function createSupabaseMcpServer(options: SupabaseMcpServerOptions) {
513510
.default('develop')
514511
.describe('Name of the branch to create'),
515512
confirm_cost_id: z
516-
.string()
513+
.string({
514+
required_error:
515+
'User must confirm understanding of costs before creating a branch.',
516+
})
517517
.describe('The cost confirmation ID. Call `confirm_cost` first.'),
518518
}),
519519
execute: async ({ project_id, name, confirm_cost_id }) => {
520-
if (!confirm_cost_id) {
521-
throw new Error(
522-
'User must confirm understanding of costs before creating a branch.'
523-
);
524-
}
525-
526520
const cost = getBranchCost();
527521
const costHash = await hashObject(cost);
528522
if (costHash !== confirm_cost_id) {

packages/mcp-utils/src/server.test.ts

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,120 @@
1+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2+
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
3+
import {
4+
CallToolResultSchema,
5+
type CallToolRequest,
6+
} from '@modelcontextprotocol/sdk/types.js';
17
import { describe, expect, test } from 'vitest';
2-
import { resource, resources, resourceTemplate } from './server.js';
8+
import { z } from 'zod';
9+
import {
10+
createMcpServer,
11+
resource,
12+
resources,
13+
resourceTemplate,
14+
tool,
15+
} from './server.js';
16+
import { StreamTransport } from './stream-transport.js';
17+
18+
export const MCP_CLIENT_NAME = 'test-client';
19+
export const MCP_CLIENT_VERSION = '0.1.0';
20+
21+
type SetupOptions = {
22+
server: Server;
23+
};
24+
25+
/**
26+
* Sets up an MCP client and server for testing.
27+
*/
28+
async function setup(options: SetupOptions) {
29+
const { server } = options;
30+
const clientTransport = new StreamTransport();
31+
const serverTransport = new StreamTransport();
32+
33+
clientTransport.readable.pipeTo(serverTransport.writable);
34+
serverTransport.readable.pipeTo(clientTransport.writable);
35+
36+
const client = new Client(
37+
{
38+
name: MCP_CLIENT_NAME,
39+
version: MCP_CLIENT_VERSION,
40+
},
41+
{
42+
capabilities: {},
43+
}
44+
);
45+
46+
await server.connect(serverTransport);
47+
await client.connect(clientTransport);
48+
49+
/**
50+
* Calls a tool with the given parameters.
51+
*
52+
* Wrapper around the `client.callTool` method to handle the response and errors.
53+
*/
54+
async function callTool(params: CallToolRequest['params']) {
55+
const output = await client.callTool(params);
56+
const { content } = CallToolResultSchema.parse(output);
57+
const [textContent] = content;
58+
59+
if (!textContent) {
60+
return undefined;
61+
}
62+
63+
if (textContent.type !== 'text') {
64+
throw new Error('tool result content is not text');
65+
}
66+
67+
if (textContent.text === '') {
68+
throw new Error('tool result content is empty');
69+
}
70+
71+
const result = JSON.parse(textContent.text);
72+
73+
if (output.isError) {
74+
throw new Error(result.error.message);
75+
}
76+
77+
return result;
78+
}
79+
80+
return { client, clientTransport, callTool, server, serverTransport };
81+
}
82+
83+
describe('tools', () => {
84+
test('parameter set to default value when omitted by caller', async () => {
85+
const server = createMcpServer({
86+
name: 'test-server',
87+
version: '0.0.0',
88+
tools: {
89+
search: tool({
90+
description: 'Search text',
91+
parameters: z.object({
92+
query: z.string(),
93+
caseSensitive: z.boolean().default(false),
94+
}),
95+
execute: async (args) => {
96+
return args;
97+
},
98+
}),
99+
},
100+
});
101+
102+
const { callTool } = await setup({ server });
103+
104+
// Call the tool without the optional parameter
105+
const result = await callTool({
106+
name: 'search',
107+
arguments: {
108+
query: 'hello',
109+
},
110+
});
111+
112+
expect(result).toEqual({
113+
query: 'hello',
114+
caseSensitive: false,
115+
});
116+
});
117+
});
3118

4119
describe('resources helper', () => {
5120
test('should add scheme to resource URIs', () => {

packages/mcp-utils/src/server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ export function createMcpServer(options: McpServerOptions) {
340340
throw new Error('tool not found');
341341
}
342342

343-
const args = request.params.arguments as z.infer<Tool['parameters']>;
343+
const args = tool.parameters.parse(request.params.arguments);
344344

345345
if (!args) {
346346
throw new Error('missing arguments');

0 commit comments

Comments
 (0)