Fix custom header schema freshness (#358)
Co-authored-by: Paul Carleton <paulcarletonjr@gmail.com>
This commit is contained in:
parent
8c1d4a6d83
commit
7022d78607
3 changed files with 86 additions and 4 deletions
|
|
@ -349,7 +349,11 @@ describe('http-custom-headers mock results (2026-07-28)', () => {
|
||||||
method: 'tools/list',
|
method: 'tools/list',
|
||||||
params: {}
|
params: {}
|
||||||
});
|
});
|
||||||
expect(list.body.result).toMatchObject(CACHEABLE_FIELDS);
|
expect(list.body.result).toMatchObject({
|
||||||
|
resultType: 'complete',
|
||||||
|
cacheScope: 'private'
|
||||||
|
});
|
||||||
|
expect(list.body.result.ttlMs).toBeGreaterThan(0);
|
||||||
|
|
||||||
const call = await post(serverUrl, {
|
const call = await post(serverUrl, {
|
||||||
jsonrpc: '2.0',
|
jsonrpc: '2.0',
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ async function post(
|
||||||
serverUrl: string,
|
serverUrl: string,
|
||||||
body: object,
|
body: object,
|
||||||
headers: Record<string, string> = {}
|
headers: Record<string, string> = {}
|
||||||
): Promise<void> {
|
): Promise<{ status: number; body: any }> {
|
||||||
await fetch(serverUrl, {
|
const response = await fetch(serverUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
|
@ -28,6 +28,7 @@ async function post(
|
||||||
},
|
},
|
||||||
body: JSON.stringify(body)
|
body: JSON.stringify(body)
|
||||||
});
|
});
|
||||||
|
return { status: response.status, body: await response.json() };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function postJson(serverUrl: string, body: object): Promise<any> {
|
async function postJson(serverUrl: string, body: object): Promise<any> {
|
||||||
|
|
@ -162,6 +163,83 @@ describe('HttpCustomHeadersScenario (SEP-2243) check IDs', () => {
|
||||||
await scenario.stop();
|
await scenario.stop();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('serves a fresh tools/list TTL before requiring schema-derived custom headers', async () => {
|
||||||
|
const scenario = new HttpCustomHeadersScenario();
|
||||||
|
const { serverUrl } = await scenario.start(testScenarioContext());
|
||||||
|
try {
|
||||||
|
const toolsList = await post(serverUrl, {
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 1,
|
||||||
|
method: 'tools/list'
|
||||||
|
});
|
||||||
|
const schemaIsFresh = toolsList.body.result.ttlMs > 0;
|
||||||
|
|
||||||
|
const nonAscii = 'Hello, 世界';
|
||||||
|
const nonAsciiB64 = Buffer.from(nonAscii, 'utf-8').toString('base64');
|
||||||
|
await post(
|
||||||
|
serverUrl,
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 2,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: {
|
||||||
|
name: 'test_custom_headers',
|
||||||
|
arguments: {
|
||||||
|
region: 'us-west1',
|
||||||
|
priority: 42,
|
||||||
|
non_ascii_val: nonAscii,
|
||||||
|
query: 'SELECT 1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
schemaIsFresh
|
||||||
|
? {
|
||||||
|
'Mcp-Method': 'tools/call',
|
||||||
|
'Mcp-Name': 'test_custom_headers',
|
||||||
|
'Mcp-Param-Region': 'us-west1',
|
||||||
|
'Mcp-Param-Priority': '42',
|
||||||
|
'Mcp-Param-NonAscii': `=?base64?${nonAsciiB64}?=`
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
);
|
||||||
|
await post(
|
||||||
|
serverUrl,
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 3,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: {
|
||||||
|
name: 'test_custom_headers_null',
|
||||||
|
arguments: {
|
||||||
|
region: 'us-east1',
|
||||||
|
priority: 1,
|
||||||
|
verbose: null,
|
||||||
|
query: 'SELECT 1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
schemaIsFresh
|
||||||
|
? {
|
||||||
|
'Mcp-Method': 'tools/call',
|
||||||
|
'Mcp-Name': 'test_custom_headers_null',
|
||||||
|
'Mcp-Param-Region': 'us-east1',
|
||||||
|
'Mcp-Param-Priority': '1'
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(toolsList.body.result.ttlMs).toBeGreaterThan(0);
|
||||||
|
const checks = scenario.getChecks();
|
||||||
|
for (const id of CUSTOM_HEADERS_DECLARED_CHECK_IDS) {
|
||||||
|
const statuses = statusesFor(checks, id);
|
||||||
|
expect(statuses.length, id).toBeGreaterThan(0);
|
||||||
|
expect(statuses, id).not.toContain('FAILURE');
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
await scenario.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('HttpInvalidToolHeadersScenario (SEP-2243) check IDs', () => {
|
describe('HttpInvalidToolHeadersScenario (SEP-2243) check IDs', () => {
|
||||||
|
|
|
||||||
|
|
@ -278,7 +278,7 @@ export class HttpCustomHeadersScenario extends BaseHttpScenario {
|
||||||
id: request.id,
|
id: request.id,
|
||||||
result: {
|
result: {
|
||||||
resultType: 'complete',
|
resultType: 'complete',
|
||||||
ttlMs: 0,
|
ttlMs: 300000,
|
||||||
cacheScope: 'private',
|
cacheScope: 'private',
|
||||||
tools: [
|
tools: [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue