@youdotcom-oss/mcp 1.3.3 → 1.3.5-next.11
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/README.md +2 -2
- package/bin/stdio.js +12712 -6877
- package/package.json +18 -41
- package/src/contents/contents.schemas.ts +2 -2
- package/src/contents/register-contents-tool.ts +90 -0
- package/src/contents/tests/contents.utils.spec.ts +188 -0
- package/src/express/register-express-tool.ts +67 -0
- package/src/express/tests/express.utils.spec.ts +244 -0
- package/src/get-mcp-server.ts +17 -0
- package/src/http.ts +72 -0
- package/src/search/register-search-tool.ts +87 -0
- package/src/search/tests/search.utils.spec.ts +217 -0
- package/src/shared/generate-error-report-link.ts +37 -0
- package/src/shared/get-logger.ts +10 -0
- package/src/shared/tests/shared.utils.spec.ts +160 -0
- package/src/shared/use-client-version.ts +21 -0
- package/src/stdio.ts +24 -0
- package/src/tests/exports.spec.ts +24 -0
- package/src/tests/http.spec.ts +318 -0
- package/src/tests/tool.spec.ts +496 -0
- package/src/utils.ts +8 -0
- package/AGENTS.md +0 -702
- package/CONTRIBUTING.md +0 -246
- package/docs/API.md +0 -319
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@youdotcom-oss/mcp",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.5-next.11",
|
|
4
4
|
"description": "You.com API Model Context Protocol Server",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
},
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
12
|
-
"url": "git+https://github.com/youdotcom-oss/
|
|
12
|
+
"url": "git+https://github.com/youdotcom-oss/dx-toolkit.git",
|
|
13
|
+
"directory": "packages/mcp"
|
|
13
14
|
},
|
|
14
15
|
"bugs": {
|
|
15
|
-
"url": "https://github.com/youdotcom-oss/
|
|
16
|
+
"url": "https://github.com/youdotcom-oss/dx-toolkit/issues"
|
|
16
17
|
},
|
|
17
|
-
"homepage": "https://github.com/youdotcom-oss/
|
|
18
|
+
"homepage": "https://github.com/youdotcom-oss/dx-toolkit/tree/main/packages/mcp#readme",
|
|
18
19
|
"author": "You.com (https://you.com)",
|
|
19
20
|
"keywords": [
|
|
20
21
|
"mcp",
|
|
@@ -23,19 +24,17 @@
|
|
|
23
24
|
],
|
|
24
25
|
"bin": "bin/stdio.js",
|
|
25
26
|
"type": "module",
|
|
26
|
-
"main": "./src/
|
|
27
|
+
"main": "./src/utils.ts",
|
|
27
28
|
"exports": {
|
|
28
|
-
".": "./src/
|
|
29
|
+
".": "./src/utils.ts",
|
|
30
|
+
"./http": "./src/http.ts",
|
|
31
|
+
"./stdio": "./src/stdio.ts"
|
|
29
32
|
},
|
|
30
33
|
"files": [
|
|
31
34
|
"bin/stdio.js",
|
|
32
|
-
"src
|
|
33
|
-
"src
|
|
34
|
-
"src
|
|
35
|
-
"src/shared/format-search-results-text.ts",
|
|
36
|
-
"AGENTS.md",
|
|
37
|
-
"CONTRIBUTING.md",
|
|
38
|
-
"docs/API.md"
|
|
35
|
+
"./src/**",
|
|
36
|
+
"!./src/**/tests/*",
|
|
37
|
+
"!./src/**/*.spec.@(tsx|ts)"
|
|
39
38
|
],
|
|
40
39
|
"publishConfig": {
|
|
41
40
|
"access": "public"
|
|
@@ -54,41 +53,19 @@
|
|
|
54
53
|
"inspect": "bash -c 'source .env 2>/dev/null || true; bunx @modelcontextprotocol/inspector -e YDC_API_KEY=$YDC_API_KEY bun dev'",
|
|
55
54
|
"lint": "biome lint",
|
|
56
55
|
"lint:fix": "biome lint --write",
|
|
57
|
-
"prepare": "git config core.hooksPath .hooks",
|
|
58
56
|
"start": "bun run bin/http",
|
|
59
57
|
"test": "bun test",
|
|
60
58
|
"test:coverage": "bun test --coverage",
|
|
61
59
|
"test:coverage:watch": "bun test --coverage --watch",
|
|
62
60
|
"test:watch": "bun test --watch"
|
|
63
61
|
},
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"
|
|
69
|
-
"biome format --write --no-errors-on-unmatched"
|
|
70
|
-
],
|
|
71
|
-
"package.json": [
|
|
72
|
-
"format-package --write"
|
|
73
|
-
]
|
|
74
|
-
},
|
|
75
|
-
"peerDependencies": {
|
|
76
|
-
"zod": "^3.25.76"
|
|
62
|
+
"dependencies": {
|
|
63
|
+
"zod": "^4.1.13",
|
|
64
|
+
"@hono/mcp": "^0.2.0",
|
|
65
|
+
"@modelcontextprotocol/sdk": "^1.24.3",
|
|
66
|
+
"hono": "^4.10.7"
|
|
77
67
|
},
|
|
78
68
|
"devDependencies": {
|
|
79
|
-
"@
|
|
80
|
-
"@commitlint/cli": "^20.1.0",
|
|
81
|
-
"@commitlint/config-conventional": "^20.0.0",
|
|
82
|
-
"@eslint/js": "9.39.1",
|
|
83
|
-
"@modelcontextprotocol/inspector": "0.17.2",
|
|
84
|
-
"@types/bun": "latest",
|
|
85
|
-
"typescript": "5.9.3",
|
|
86
|
-
"lint-staged": "^16.2.7",
|
|
87
|
-
"format-package": "^7.0.0",
|
|
88
|
-
"@hono/bun-compress": "0.1.0",
|
|
89
|
-
"@hono/mcp": "0.2.0",
|
|
90
|
-
"@modelcontextprotocol/sdk": "1.22.0",
|
|
91
|
-
"hono": "^4.10.6",
|
|
92
|
-
"zod": "3.25.76"
|
|
69
|
+
"@modelcontextprotocol/inspector": "0.17.5"
|
|
93
70
|
}
|
|
94
71
|
}
|
|
@@ -20,7 +20,7 @@ export type ContentsQuery = z.infer<typeof ContentsQuerySchema>;
|
|
|
20
20
|
*/
|
|
21
21
|
const ContentsItemSchema = z.object({
|
|
22
22
|
url: z.string().describe('URL'),
|
|
23
|
-
title: z.string().describe('Title'),
|
|
23
|
+
title: z.string().optional().describe('Title'),
|
|
24
24
|
html: z.string().optional().describe('HTML content'),
|
|
25
25
|
markdown: z.string().optional().describe('Markdown content'),
|
|
26
26
|
});
|
|
@@ -44,7 +44,7 @@ export const ContentsStructuredContentSchema = z.object({
|
|
|
44
44
|
.array(
|
|
45
45
|
z.object({
|
|
46
46
|
url: z.string().describe('URL'),
|
|
47
|
-
title: z.string().describe('Title'),
|
|
47
|
+
title: z.string().optional().describe('Title'),
|
|
48
48
|
content: z.string().describe('Extracted content'),
|
|
49
49
|
contentLength: z.number().describe('Content length'),
|
|
50
50
|
}),
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { generateErrorReportLink } from '../shared/generate-error-report-link.ts';
|
|
3
|
+
import { getLogger } from '../shared/get-logger.ts';
|
|
4
|
+
import { ContentsQuerySchema, ContentsStructuredContentSchema } from './contents.schemas.ts';
|
|
5
|
+
import { fetchContents, formatContentsResponse } from './contents.utils.ts';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Register the you-contents tool with the MCP server
|
|
9
|
+
* Extracts and returns full content from multiple URLs in markdown or HTML format
|
|
10
|
+
*/
|
|
11
|
+
export const registerContentsTool = ({
|
|
12
|
+
mcp,
|
|
13
|
+
YDC_API_KEY,
|
|
14
|
+
getUserAgent,
|
|
15
|
+
}: {
|
|
16
|
+
mcp: McpServer;
|
|
17
|
+
YDC_API_KEY?: string;
|
|
18
|
+
getUserAgent: () => string;
|
|
19
|
+
}) => {
|
|
20
|
+
// Register the tool
|
|
21
|
+
mcp.registerTool(
|
|
22
|
+
'you-contents',
|
|
23
|
+
{
|
|
24
|
+
title: 'Extract Web Page Contents',
|
|
25
|
+
description: 'Extract page content in markdown or HTML',
|
|
26
|
+
inputSchema: ContentsQuerySchema.shape,
|
|
27
|
+
outputSchema: ContentsStructuredContentSchema.shape,
|
|
28
|
+
},
|
|
29
|
+
async (toolInput) => {
|
|
30
|
+
const logger = getLogger(mcp);
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
// Validate and parse input
|
|
34
|
+
const contentsQuery = ContentsQuerySchema.parse(toolInput);
|
|
35
|
+
const { urls, format = 'markdown' } = contentsQuery;
|
|
36
|
+
|
|
37
|
+
// Log the request
|
|
38
|
+
await logger({
|
|
39
|
+
level: 'info',
|
|
40
|
+
data: `Contents API call initiated for ${urls.length} URL(s) with format: ${format}`,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Fetch contents from API
|
|
44
|
+
const response = await fetchContents({
|
|
45
|
+
contentsQuery,
|
|
46
|
+
YDC_API_KEY,
|
|
47
|
+
getUserAgent,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Format response with full content
|
|
51
|
+
const { content, structuredContent } = formatContentsResponse(response, format);
|
|
52
|
+
|
|
53
|
+
// Log success
|
|
54
|
+
await logger({
|
|
55
|
+
level: 'info',
|
|
56
|
+
data: `Contents API call successful: extracted ${response.length} page(s)`,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
content,
|
|
61
|
+
structuredContent,
|
|
62
|
+
};
|
|
63
|
+
} catch (err: unknown) {
|
|
64
|
+
// Handle and log errors
|
|
65
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
66
|
+
const reportLink = generateErrorReportLink({
|
|
67
|
+
errorMessage,
|
|
68
|
+
tool: 'you-contents',
|
|
69
|
+
clientInfo: getUserAgent(),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
await logger({
|
|
73
|
+
level: 'error',
|
|
74
|
+
data: `Contents API call failed: ${errorMessage}\n\nReport this issue: ${reportLink}`,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
content: [
|
|
79
|
+
{
|
|
80
|
+
type: 'text' as const,
|
|
81
|
+
text: `Error extracting contents: ${errorMessage}`,
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
structuredContent: undefined,
|
|
85
|
+
isError: true,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
};
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import type { ContentsApiResponse } from '../contents.schemas.ts';
|
|
3
|
+
import { fetchContents, formatContentsResponse } from '../contents.utils.ts';
|
|
4
|
+
|
|
5
|
+
const getUserAgent = () => 'MCP/test (You.com; test-client)';
|
|
6
|
+
|
|
7
|
+
// NOTE: The following tests require a You.com API key with access to the Contents API
|
|
8
|
+
// Using example.com/example.org as test URLs since You.com blocks self-scraping
|
|
9
|
+
describe('fetchContents', () => {
|
|
10
|
+
test('returns valid response structure for single URL', async () => {
|
|
11
|
+
const result = await fetchContents({
|
|
12
|
+
contentsQuery: {
|
|
13
|
+
urls: ['https://documentation.you.com/developer-resources/mcp-server'],
|
|
14
|
+
format: 'markdown',
|
|
15
|
+
},
|
|
16
|
+
getUserAgent,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
expect(Array.isArray(result)).toBe(true);
|
|
20
|
+
expect(result.length).toBeGreaterThan(0);
|
|
21
|
+
|
|
22
|
+
const firstItem = result[0];
|
|
23
|
+
expect(firstItem).toBeDefined();
|
|
24
|
+
|
|
25
|
+
// Should have markdown content
|
|
26
|
+
expect(firstItem?.markdown).toBeDefined();
|
|
27
|
+
expect(typeof firstItem?.markdown).toBe('string');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('handles multiple URLs', async () => {
|
|
31
|
+
const result = await fetchContents({
|
|
32
|
+
contentsQuery: {
|
|
33
|
+
urls: [
|
|
34
|
+
'https://documentation.you.com/developer-resources/mcp-server',
|
|
35
|
+
'https://documentation.you.com/developer-resources/python-sdk',
|
|
36
|
+
],
|
|
37
|
+
format: 'markdown',
|
|
38
|
+
},
|
|
39
|
+
getUserAgent,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
expect(Array.isArray(result)).toBe(true);
|
|
43
|
+
expect(result.length).toBe(2);
|
|
44
|
+
|
|
45
|
+
for (const item of result) {
|
|
46
|
+
expect(item).toHaveProperty('url');
|
|
47
|
+
expect(item.markdown).toBeDefined();
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('handles html format', async () => {
|
|
52
|
+
const result = await fetchContents({
|
|
53
|
+
contentsQuery: {
|
|
54
|
+
urls: ['https://documentation.you.com/developer-resources/mcp-server'],
|
|
55
|
+
format: 'html',
|
|
56
|
+
},
|
|
57
|
+
getUserAgent,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
expect(Array.isArray(result)).toBe(true);
|
|
61
|
+
const firstItem = result[0];
|
|
62
|
+
expect(firstItem).toBeDefined();
|
|
63
|
+
|
|
64
|
+
expect(firstItem?.html).toBeDefined();
|
|
65
|
+
expect(typeof firstItem?.html).toBe('string');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('formatContentsResponse', () => {
|
|
70
|
+
test('formats single markdown content correctly', () => {
|
|
71
|
+
const mockResponse: ContentsApiResponse = [
|
|
72
|
+
{
|
|
73
|
+
url: 'https://example.com',
|
|
74
|
+
title: 'Example Page',
|
|
75
|
+
markdown: '# Hello\n\nThis is a test page with some content.',
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
const result = formatContentsResponse(mockResponse, 'markdown');
|
|
80
|
+
|
|
81
|
+
expect(result).toHaveProperty('content');
|
|
82
|
+
expect(result).toHaveProperty('structuredContent');
|
|
83
|
+
expect(Array.isArray(result.content)).toBe(true);
|
|
84
|
+
expect(result.content[0]).toHaveProperty('type', 'text');
|
|
85
|
+
expect(result.content[0]).toHaveProperty('text');
|
|
86
|
+
|
|
87
|
+
const text = result.content[0]?.text;
|
|
88
|
+
expect(text).toContain('Example Page');
|
|
89
|
+
expect(text).toContain('https://example.com');
|
|
90
|
+
expect(text).toContain('Format: markdown');
|
|
91
|
+
expect(text).toContain('# Hello');
|
|
92
|
+
expect(text).toContain('This is a test page with some content.');
|
|
93
|
+
|
|
94
|
+
expect(result.structuredContent).toHaveProperty('count', 1);
|
|
95
|
+
expect(result.structuredContent).toHaveProperty('format', 'markdown');
|
|
96
|
+
expect(result.structuredContent.items).toHaveLength(1);
|
|
97
|
+
|
|
98
|
+
const item = result.structuredContent.items[0];
|
|
99
|
+
expect(item).toBeDefined();
|
|
100
|
+
|
|
101
|
+
expect(item).toHaveProperty('url', 'https://example.com');
|
|
102
|
+
expect(item).toHaveProperty('title', 'Example Page');
|
|
103
|
+
expect(item).toHaveProperty('content', '# Hello\n\nThis is a test page with some content.');
|
|
104
|
+
expect(item?.contentLength).toBe('# Hello\n\nThis is a test page with some content.'.length);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('formats multiple items correctly', () => {
|
|
108
|
+
const mockResponse: ContentsApiResponse = [
|
|
109
|
+
{
|
|
110
|
+
url: 'https://example1.com',
|
|
111
|
+
title: 'Page 1',
|
|
112
|
+
markdown: 'Content 1',
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
url: 'https://example2.com',
|
|
116
|
+
title: 'Page 2',
|
|
117
|
+
markdown: 'Content 2',
|
|
118
|
+
},
|
|
119
|
+
];
|
|
120
|
+
|
|
121
|
+
const result = formatContentsResponse(mockResponse, 'markdown');
|
|
122
|
+
|
|
123
|
+
expect(result.structuredContent.count).toBe(2);
|
|
124
|
+
expect(result.structuredContent.items).toHaveLength(2);
|
|
125
|
+
|
|
126
|
+
const text = result.content[0]?.text;
|
|
127
|
+
expect(text).toContain('Page 1');
|
|
128
|
+
expect(text).toContain('Page 2');
|
|
129
|
+
expect(text).toContain('https://example1.com');
|
|
130
|
+
expect(text).toContain('https://example2.com');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test('handles html format', () => {
|
|
134
|
+
const mockResponse: ContentsApiResponse = [
|
|
135
|
+
{
|
|
136
|
+
url: 'https://example.com',
|
|
137
|
+
title: 'HTML Page',
|
|
138
|
+
html: '<html><body><h1>Hello</h1></body></html>',
|
|
139
|
+
},
|
|
140
|
+
];
|
|
141
|
+
|
|
142
|
+
const result = formatContentsResponse(mockResponse, 'html');
|
|
143
|
+
|
|
144
|
+
expect(result.structuredContent.format).toBe('html');
|
|
145
|
+
const text = result.content[0]?.text;
|
|
146
|
+
expect(text).toContain('Format: html');
|
|
147
|
+
expect(text).toContain('<html>');
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test('includes full content for long text', () => {
|
|
151
|
+
const longContent = 'a'.repeat(1000);
|
|
152
|
+
const mockResponse: ContentsApiResponse = [
|
|
153
|
+
{
|
|
154
|
+
url: 'https://example.com',
|
|
155
|
+
title: 'Long Page',
|
|
156
|
+
markdown: longContent,
|
|
157
|
+
},
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
const result = formatContentsResponse(mockResponse, 'markdown');
|
|
161
|
+
|
|
162
|
+
const text = result.content[0]?.text;
|
|
163
|
+
// Full content should be included (not truncated)
|
|
164
|
+
expect(text).toContain(longContent);
|
|
165
|
+
|
|
166
|
+
// Structured content should have full content and correct length
|
|
167
|
+
const item = result.structuredContent.items[0];
|
|
168
|
+
expect(item?.content).toBe(longContent);
|
|
169
|
+
expect(item?.contentLength).toBe(1000);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test('handles empty content gracefully', () => {
|
|
173
|
+
const mockResponse: ContentsApiResponse = [
|
|
174
|
+
{
|
|
175
|
+
url: 'https://example.com',
|
|
176
|
+
title: 'Empty Page',
|
|
177
|
+
markdown: '',
|
|
178
|
+
},
|
|
179
|
+
];
|
|
180
|
+
|
|
181
|
+
const result = formatContentsResponse(mockResponse, 'markdown');
|
|
182
|
+
|
|
183
|
+
expect(result.structuredContent.items[0]?.contentLength).toBe(0);
|
|
184
|
+
const text = result.content[0]?.text;
|
|
185
|
+
expect(text).toContain('Empty Page');
|
|
186
|
+
expect(text).toContain('Content Length: 0 characters');
|
|
187
|
+
});
|
|
188
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { generateErrorReportLink } from '../shared/generate-error-report-link.ts';
|
|
3
|
+
import { getLogger } from '../shared/get-logger.ts';
|
|
4
|
+
import { ExpressAgentInputSchema, ExpressStructuredContentSchema } from './express.schemas.ts';
|
|
5
|
+
import { callExpressAgent, formatExpressAgentResponse } from './express.utils.ts';
|
|
6
|
+
|
|
7
|
+
export const registerExpressTool = ({
|
|
8
|
+
mcp,
|
|
9
|
+
YDC_API_KEY,
|
|
10
|
+
getUserAgent,
|
|
11
|
+
}: {
|
|
12
|
+
mcp: McpServer;
|
|
13
|
+
YDC_API_KEY?: string;
|
|
14
|
+
getUserAgent: () => string;
|
|
15
|
+
}) => {
|
|
16
|
+
mcp.registerTool(
|
|
17
|
+
'you-express',
|
|
18
|
+
{
|
|
19
|
+
title: 'Express Agent',
|
|
20
|
+
description: 'Fast AI answers with web search',
|
|
21
|
+
inputSchema: ExpressAgentInputSchema.shape,
|
|
22
|
+
outputSchema: ExpressStructuredContentSchema.shape,
|
|
23
|
+
},
|
|
24
|
+
async (agentInput) => {
|
|
25
|
+
const logger = getLogger(mcp);
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const response = await callExpressAgent({
|
|
29
|
+
agentInput,
|
|
30
|
+
YDC_API_KEY,
|
|
31
|
+
getUserAgent,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
await logger({
|
|
35
|
+
level: 'info',
|
|
36
|
+
data: `Express agent call successful for input: "${agentInput.input}"`,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const { content, structuredContent } = formatExpressAgentResponse(response);
|
|
40
|
+
return { content, structuredContent };
|
|
41
|
+
} catch (err: unknown) {
|
|
42
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
43
|
+
const reportLink = generateErrorReportLink({
|
|
44
|
+
errorMessage,
|
|
45
|
+
tool: 'you-express',
|
|
46
|
+
clientInfo: getUserAgent(),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
await logger({
|
|
50
|
+
level: 'error',
|
|
51
|
+
data: `Express agent call failed: ${errorMessage}\n\nReport this issue: ${reportLink}`,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
content: [
|
|
56
|
+
{
|
|
57
|
+
type: 'text' as const,
|
|
58
|
+
text: `Error: ${errorMessage}`,
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
structuredContent: undefined,
|
|
62
|
+
isError: true,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
);
|
|
67
|
+
};
|