@youdotcom-oss/mcp 1.3.8 → 1.3.9-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/stdio.js +879 -774
- package/dist/contents/contents.schemas.d.ts +39 -0
- package/dist/contents/contents.utils.d.ts +28 -0
- package/dist/contents/register-contents-tool.d.ts +10 -0
- package/dist/express/express.schemas.d.ts +56 -0
- package/dist/express/express.utils.d.ts +45 -0
- package/dist/express/register-express-tool.d.ts +6 -0
- package/dist/get-mcp-server.d.ts +2 -0
- package/dist/http.d.ts +3 -0
- package/{src/utils.ts → dist/main.d.ts} +1 -0
- package/dist/search/register-search-tool.d.ts +6 -0
- package/dist/search/search.schemas.d.ts +131 -0
- package/dist/search/search.utils.d.ts +96 -0
- package/dist/shared/api-constants.d.ts +9 -0
- package/dist/shared/check-response-for-errors.d.ts +6 -0
- package/dist/shared/format-search-results-text.d.ts +19 -0
- package/dist/shared/generate-error-report-link.d.ts +9 -0
- package/dist/shared/get-logger.d.ts +7 -0
- package/dist/shared/use-client-version.d.ts +6 -0
- package/dist/stdio.d.ts +2 -0
- package/package.json +14 -7
- package/src/contents/contents.utils.ts +1 -2
- package/src/contents/tests/contents.utils.spec.ts +69 -57
- package/src/express/express.utils.ts +2 -4
- package/src/express/tests/express.utils.spec.ts +74 -62
- package/src/main.ts +9 -0
- package/src/search/search.utils.ts +2 -1
- package/src/search/tests/search.utils.spec.ts +114 -92
- package/src/shared/api-constants.ts +10 -0
- package/src/tests/http.spec.ts +35 -31
- package/src/tests/tool.spec.ts +490 -402
|
@@ -7,63 +7,75 @@ const getUserAgent = () => 'MCP/test (You.com; test-client)';
|
|
|
7
7
|
// NOTE: The following tests require a You.com API key with access to the Contents API
|
|
8
8
|
// Using example.com/example.org as test URLs since You.com blocks self-scraping
|
|
9
9
|
describe('fetchContents', () => {
|
|
10
|
-
test(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
10
|
+
test(
|
|
11
|
+
'returns valid response structure for single URL',
|
|
12
|
+
async () => {
|
|
13
|
+
const result = await fetchContents({
|
|
14
|
+
contentsQuery: {
|
|
15
|
+
urls: ['https://documentation.you.com/developer-resources/mcp-server'],
|
|
16
|
+
format: 'markdown',
|
|
17
|
+
},
|
|
18
|
+
getUserAgent,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
expect(Array.isArray(result)).toBe(true);
|
|
22
|
+
expect(result.length).toBeGreaterThan(0);
|
|
23
|
+
|
|
24
|
+
const firstItem = result[0];
|
|
25
|
+
expect(firstItem).toBeDefined();
|
|
26
|
+
|
|
27
|
+
// Should have markdown content
|
|
28
|
+
expect(firstItem?.markdown).toBeDefined();
|
|
29
|
+
expect(typeof firstItem?.markdown).toBe('string');
|
|
30
|
+
},
|
|
31
|
+
{ retry: 2 },
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
test(
|
|
35
|
+
'handles multiple URLs',
|
|
36
|
+
async () => {
|
|
37
|
+
const result = await fetchContents({
|
|
38
|
+
contentsQuery: {
|
|
39
|
+
urls: [
|
|
40
|
+
'https://documentation.you.com/developer-resources/mcp-server',
|
|
41
|
+
'https://documentation.you.com/developer-resources/python-sdk',
|
|
42
|
+
],
|
|
43
|
+
format: 'markdown',
|
|
44
|
+
},
|
|
45
|
+
getUserAgent,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
expect(Array.isArray(result)).toBe(true);
|
|
49
|
+
expect(result.length).toBe(2);
|
|
50
|
+
|
|
51
|
+
for (const item of result) {
|
|
52
|
+
expect(item).toHaveProperty('url');
|
|
53
|
+
expect(item.markdown).toBeDefined();
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{ retry: 2 },
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
test(
|
|
60
|
+
'handles html format',
|
|
61
|
+
async () => {
|
|
62
|
+
const result = await fetchContents({
|
|
63
|
+
contentsQuery: {
|
|
64
|
+
urls: ['https://documentation.you.com/developer-resources/mcp-server'],
|
|
65
|
+
format: 'html',
|
|
66
|
+
},
|
|
67
|
+
getUserAgent,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
expect(Array.isArray(result)).toBe(true);
|
|
71
|
+
const firstItem = result[0];
|
|
72
|
+
expect(firstItem).toBeDefined();
|
|
73
|
+
|
|
74
|
+
expect(firstItem?.html).toBeDefined();
|
|
75
|
+
expect(typeof firstItem?.html).toBe('string');
|
|
76
|
+
},
|
|
77
|
+
{ retry: 2 },
|
|
78
|
+
);
|
|
67
79
|
});
|
|
68
80
|
|
|
69
81
|
describe('formatContentsResponse', () => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EXPRESS_API_URL } from '../shared/api-constants.ts';
|
|
1
2
|
import { checkResponseForErrors } from '../shared/check-response-for-errors.ts';
|
|
2
3
|
import { formatSearchResultsText } from '../shared/format-search-results-text.ts';
|
|
3
4
|
import {
|
|
@@ -7,9 +8,6 @@ import {
|
|
|
7
8
|
type ExpressAgentMcpResponse,
|
|
8
9
|
} from './express.schemas.ts';
|
|
9
10
|
|
|
10
|
-
// Express Agent Constants
|
|
11
|
-
const AGENTS_RUN_URL = 'https://api.you.com/v1/agents/runs';
|
|
12
|
-
|
|
13
11
|
/**
|
|
14
12
|
* Checks response status and throws appropriate errors for agent API calls
|
|
15
13
|
*/
|
|
@@ -70,7 +68,7 @@ export const callExpressAgent = async ({
|
|
|
70
68
|
body: JSON.stringify(requestBody),
|
|
71
69
|
};
|
|
72
70
|
|
|
73
|
-
const response = await fetch(
|
|
71
|
+
const response = await fetch(EXPRESS_API_URL, options);
|
|
74
72
|
|
|
75
73
|
if (!response.ok) {
|
|
76
74
|
await agentThrowOnFailedStatus(response);
|
|
@@ -7,68 +7,80 @@ const getUserAgent = () => 'MCP/test (You.com; test-client)';
|
|
|
7
7
|
setDefaultTimeout(20_000);
|
|
8
8
|
|
|
9
9
|
describe('callExpressAgent', () => {
|
|
10
|
-
test(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
10
|
+
test(
|
|
11
|
+
'returns answer only (WITHOUT web_search tools)',
|
|
12
|
+
async () => {
|
|
13
|
+
const result = await callExpressAgent({
|
|
14
|
+
agentInput: { input: 'What is machine learning?' },
|
|
15
|
+
getUserAgent,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// Verify MCP response structure
|
|
19
|
+
expect(result).toHaveProperty('answer');
|
|
20
|
+
expect(typeof result.answer).toBe('string');
|
|
21
|
+
expect(result.answer.length).toBeGreaterThan(0);
|
|
22
|
+
|
|
23
|
+
// Should NOT have results when web_search is not used
|
|
24
|
+
expect(result.results).toBeUndefined();
|
|
25
|
+
|
|
26
|
+
expect(result.agent).toBe('express');
|
|
27
|
+
},
|
|
28
|
+
{ retry: 2 },
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
test(
|
|
32
|
+
'returns answer and search results (WITH web_search tools)',
|
|
33
|
+
async () => {
|
|
34
|
+
const result = await callExpressAgent({
|
|
35
|
+
agentInput: {
|
|
36
|
+
input: 'Latest developments in quantum computing',
|
|
37
|
+
tools: [{ type: 'web_search' }],
|
|
38
|
+
},
|
|
39
|
+
getUserAgent,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Verify MCP response has both answer and results
|
|
43
|
+
expect(result).toHaveProperty('answer');
|
|
44
|
+
expect(typeof result.answer).toBe('string');
|
|
45
|
+
expect(result.answer.length).toBeGreaterThan(0);
|
|
46
|
+
|
|
47
|
+
expect(result).toHaveProperty('results');
|
|
48
|
+
expect(result.results).toHaveProperty('web');
|
|
49
|
+
expect(Array.isArray(result.results?.web)).toBe(true);
|
|
50
|
+
expect(result.results?.web.length).toBeGreaterThan(0);
|
|
51
|
+
|
|
52
|
+
// Verify each search result has required fields
|
|
53
|
+
const firstResult = result.results?.web[0];
|
|
54
|
+
expect(firstResult).toHaveProperty('url');
|
|
55
|
+
expect(firstResult).toHaveProperty('title');
|
|
56
|
+
expect(firstResult).toHaveProperty('snippet');
|
|
57
|
+
expect(typeof firstResult?.url).toBe('string');
|
|
58
|
+
expect(typeof firstResult?.title).toBe('string');
|
|
59
|
+
expect(typeof firstResult?.snippet).toBe('string');
|
|
60
|
+
expect(firstResult?.url.length).toBeGreaterThan(0);
|
|
61
|
+
expect(firstResult?.title.length).toBeGreaterThan(0);
|
|
62
|
+
|
|
63
|
+
expect(result.agent).toBe('express');
|
|
64
|
+
},
|
|
65
|
+
{ timeout: 30_000, retry: 2 },
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
test(
|
|
69
|
+
'works without optional parameters',
|
|
70
|
+
async () => {
|
|
71
|
+
const result = await callExpressAgent({
|
|
72
|
+
agentInput: { input: 'What is the capital of France?' },
|
|
73
|
+
getUserAgent,
|
|
74
|
+
// No progressToken or sendProgress provided
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Should work normally without progress tracking
|
|
78
|
+
expect(result).toHaveProperty('answer');
|
|
79
|
+
expect(result.answer.length).toBeGreaterThan(0);
|
|
80
|
+
expect(result.agent).toBe('express');
|
|
81
|
+
},
|
|
82
|
+
{ retry: 2 },
|
|
83
|
+
);
|
|
72
84
|
});
|
|
73
85
|
|
|
74
86
|
describe('formatExpressAgentResponse', () => {
|
package/src/main.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './contents/contents.schemas.ts';
|
|
2
|
+
export * from './contents/contents.utils.ts';
|
|
3
|
+
export * from './express/express.schemas.ts';
|
|
4
|
+
export * from './express/express.utils.ts';
|
|
5
|
+
export * from './search/search.schemas.ts';
|
|
6
|
+
export * from './search/search.utils.ts';
|
|
7
|
+
export * from './shared/api-constants.ts';
|
|
8
|
+
export * from './shared/check-response-for-errors.ts';
|
|
9
|
+
export * from './shared/format-search-results-text.ts';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SEARCH_API_URL } from '../shared/api-constants.ts';
|
|
1
2
|
import { checkResponseForErrors } from '../shared/check-response-for-errors.ts';
|
|
2
3
|
import { formatSearchResultsText } from '../shared/format-search-results-text.ts';
|
|
3
4
|
import { type NewsResult, type SearchQuery, type SearchResponse, SearchResponseSchema } from './search.schemas.ts';
|
|
@@ -11,7 +12,7 @@ export const fetchSearchResults = async ({
|
|
|
11
12
|
YDC_API_KEY?: string;
|
|
12
13
|
getUserAgent: () => string;
|
|
13
14
|
}) => {
|
|
14
|
-
const url = new URL(
|
|
15
|
+
const url = new URL(SEARCH_API_URL);
|
|
15
16
|
|
|
16
17
|
const searchParams = new URLSearchParams();
|
|
17
18
|
|
|
@@ -5,113 +5,135 @@ import { fetchSearchResults, formatSearchResults } from '../search.utils.ts';
|
|
|
5
5
|
const getUserAgent = () => 'MCP/test (You.com; test-client)';
|
|
6
6
|
|
|
7
7
|
describe('fetchSearchResults', () => {
|
|
8
|
-
test(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
test(
|
|
9
|
+
'returns valid response structure for basic query',
|
|
10
|
+
async () => {
|
|
11
|
+
const result = await fetchSearchResults({
|
|
12
|
+
searchQuery: { query: 'latest stock news' },
|
|
13
|
+
getUserAgent,
|
|
14
|
+
});
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
expect(result).toHaveProperty('results');
|
|
17
|
+
expect(result).toHaveProperty('metadata');
|
|
18
|
+
expect(result.results).toHaveProperty('web');
|
|
19
|
+
expect(result.results).toHaveProperty('news');
|
|
20
|
+
expect(Array.isArray(result.results.web)).toBe(true);
|
|
21
|
+
expect(Array.isArray(result.results.news)).toBe(true);
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
// Assert required metadata fields
|
|
24
|
+
expect(typeof result.metadata?.query).toBe('string');
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
expect(typeof result.metadata
|
|
27
|
-
}
|
|
28
|
-
|
|
26
|
+
// search_uuid is optional but should be string if present
|
|
27
|
+
expect(result.metadata?.search_uuid).toBeDefined();
|
|
28
|
+
expect(typeof result.metadata?.search_uuid).toBe('string');
|
|
29
|
+
},
|
|
30
|
+
{ retry: 2 },
|
|
31
|
+
);
|
|
29
32
|
|
|
30
|
-
test(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
test(
|
|
34
|
+
'handles search with filters',
|
|
35
|
+
async () => {
|
|
36
|
+
const result = await fetchSearchResults({
|
|
37
|
+
searchQuery: {
|
|
38
|
+
query: 'javascript tutorial',
|
|
39
|
+
count: 3,
|
|
40
|
+
freshness: 'week',
|
|
41
|
+
country: 'US',
|
|
42
|
+
},
|
|
43
|
+
getUserAgent,
|
|
44
|
+
});
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
expect(result.results.web?.length).toBeLessThanOrEqual(3);
|
|
47
|
+
expect(result.metadata?.query).toContain('javascript tutorial');
|
|
48
|
+
},
|
|
49
|
+
{ retry: 2 },
|
|
50
|
+
);
|
|
44
51
|
|
|
45
|
-
test(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
test(
|
|
53
|
+
'validates response schema',
|
|
54
|
+
async () => {
|
|
55
|
+
const result = await fetchSearchResults({
|
|
56
|
+
searchQuery: { query: 'latest technology news' },
|
|
57
|
+
getUserAgent,
|
|
58
|
+
});
|
|
50
59
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
60
|
+
// Test that web results have required properties
|
|
61
|
+
// biome-ignore lint/style/noNonNullAssertion: Test
|
|
62
|
+
const webResult = result.results.web![0];
|
|
54
63
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
64
|
+
expect(webResult).toHaveProperty('url');
|
|
65
|
+
expect(webResult).toHaveProperty('title');
|
|
66
|
+
expect(webResult).toHaveProperty('description');
|
|
67
|
+
expect(webResult).toHaveProperty('snippets');
|
|
68
|
+
expect(Array.isArray(webResult?.snippets)).toBe(true);
|
|
60
69
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
// Test that news results have required properties
|
|
71
|
+
// biome-ignore lint/style/noNonNullAssertion: Test
|
|
72
|
+
const newsResult = result.results.news![0];
|
|
73
|
+
expect(newsResult).toHaveProperty('url');
|
|
74
|
+
expect(newsResult).toHaveProperty('title');
|
|
75
|
+
expect(newsResult).toHaveProperty('description');
|
|
76
|
+
expect(newsResult).toHaveProperty('page_age');
|
|
77
|
+
},
|
|
78
|
+
{ retry: 2 },
|
|
79
|
+
);
|
|
69
80
|
|
|
70
|
-
test(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
test(
|
|
82
|
+
'handles livecrawl parameters',
|
|
83
|
+
async () => {
|
|
84
|
+
const result = await fetchSearchResults({
|
|
85
|
+
searchQuery: {
|
|
86
|
+
query: 'python tutorial',
|
|
87
|
+
count: 2,
|
|
88
|
+
livecrawl: 'web',
|
|
89
|
+
livecrawl_formats: 'markdown',
|
|
90
|
+
},
|
|
91
|
+
getUserAgent,
|
|
92
|
+
});
|
|
80
93
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
expect(result.results.web[0]
|
|
85
|
-
expect(typeof result.results.web[0]
|
|
86
|
-
}
|
|
87
|
-
|
|
94
|
+
expect(result.results.web?.length).toBeLessThanOrEqual(2);
|
|
95
|
+
// Livecrawl should return contents field (fails naturally if not present)
|
|
96
|
+
expect(result.results.web?.[0]).toHaveProperty('contents');
|
|
97
|
+
expect(result.results.web?.[0]?.contents).toHaveProperty('markdown');
|
|
98
|
+
expect(typeof result.results.web?.[0]?.contents?.markdown).toBe('string');
|
|
99
|
+
},
|
|
100
|
+
{ retry: 2 },
|
|
101
|
+
);
|
|
88
102
|
|
|
89
|
-
test(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
103
|
+
test(
|
|
104
|
+
'handles freshness date ranges',
|
|
105
|
+
async () => {
|
|
106
|
+
const result = await fetchSearchResults({
|
|
107
|
+
searchQuery: {
|
|
108
|
+
query: 'AI news',
|
|
109
|
+
freshness: '2024-01-01to2024-12-31',
|
|
110
|
+
count: 3,
|
|
111
|
+
},
|
|
112
|
+
getUserAgent,
|
|
113
|
+
});
|
|
98
114
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
115
|
+
expect(result).toHaveProperty('results');
|
|
116
|
+
expect(result.metadata?.query).toContain('AI news');
|
|
117
|
+
},
|
|
118
|
+
{ retry: 2 },
|
|
119
|
+
);
|
|
102
120
|
|
|
103
|
-
test(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
121
|
+
test(
|
|
122
|
+
'handles count greater than 20',
|
|
123
|
+
async () => {
|
|
124
|
+
const result = await fetchSearchResults({
|
|
125
|
+
searchQuery: {
|
|
126
|
+
query: 'machine learning',
|
|
127
|
+
count: 50,
|
|
128
|
+
},
|
|
129
|
+
getUserAgent,
|
|
130
|
+
});
|
|
111
131
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
132
|
+
expect(result.results.web?.length).toBeGreaterThan(0);
|
|
133
|
+
expect(result.results.web?.length).toBeLessThanOrEqual(50);
|
|
134
|
+
},
|
|
135
|
+
{ retry: 2 },
|
|
136
|
+
);
|
|
115
137
|
});
|
|
116
138
|
|
|
117
139
|
describe('formatSearchResults', () => {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* You.com API endpoints
|
|
3
|
+
*
|
|
4
|
+
* These constants define the base URLs for You.com's APIs.
|
|
5
|
+
* Exported for use in tests and external packages.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const SEARCH_API_URL = 'https://ydc-index.io/v1/search';
|
|
9
|
+
export const EXPRESS_API_URL = 'https://api.you.com/v1/agents/runs';
|
|
10
|
+
export const CONTENTS_API_URL = 'https://ydc-index.io/v1/contents';
|
package/src/tests/http.spec.ts
CHANGED
|
@@ -283,36 +283,40 @@ describe('HTTP MCP Endpoint Basic Functionality', () => {
|
|
|
283
283
|
expect(text).toContain('42');
|
|
284
284
|
});
|
|
285
285
|
|
|
286
|
-
test(
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
jsonrpc: '2.0',
|
|
296
|
-
method: 'tools/call',
|
|
297
|
-
id: 100,
|
|
298
|
-
params: {
|
|
299
|
-
name: 'you-search',
|
|
300
|
-
arguments: {
|
|
301
|
-
query: 'latest tech news',
|
|
302
|
-
count: 3,
|
|
303
|
-
},
|
|
286
|
+
test(
|
|
287
|
+
'mcp server handles search tool request for latest tech news',
|
|
288
|
+
async () => {
|
|
289
|
+
const response = await fetch(`${baseUrl}/mcp`, {
|
|
290
|
+
method: 'POST',
|
|
291
|
+
headers: {
|
|
292
|
+
'Content-Type': 'application/json',
|
|
293
|
+
Accept: 'application/json, text/event-stream',
|
|
294
|
+
Authorization: `Bearer ${testApiKey}`,
|
|
304
295
|
},
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
296
|
+
body: JSON.stringify({
|
|
297
|
+
jsonrpc: '2.0',
|
|
298
|
+
method: 'tools/call',
|
|
299
|
+
id: 100,
|
|
300
|
+
params: {
|
|
301
|
+
name: 'you-search',
|
|
302
|
+
arguments: {
|
|
303
|
+
query: 'latest tech news',
|
|
304
|
+
count: 3,
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
}),
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
expect(response.status).toBe(200);
|
|
311
|
+
expect(response.headers.get('content-type')).toContain('text/event-stream');
|
|
312
|
+
|
|
313
|
+
const text = await response.text();
|
|
314
|
+
expect(text).toContain('data:');
|
|
315
|
+
expect(text).toContain('jsonrpc');
|
|
316
|
+
expect(text).toContain('result');
|
|
317
|
+
expect(text).toContain('latest tech news');
|
|
318
|
+
expect(text).toContain('Search Results for');
|
|
319
|
+
},
|
|
320
|
+
{ retry: 2 },
|
|
321
|
+
);
|
|
318
322
|
});
|