@qverisai/sdk 0.1.1 → 0.2.0

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/dist/client.js ADDED
@@ -0,0 +1,293 @@
1
+ /**
2
+ * QVeris API client.
3
+ *
4
+ * A lightweight, dependency-free typed client for the QVeris REST API using
5
+ * native fetch (Node.js 18+). Handles authentication, region resolution,
6
+ * success-envelope unwrapping, timeouts, and error normalization.
7
+ *
8
+ * The wire semantics mirror the Python SDK (`qveris` on PyPI) and the MCP
9
+ * server (`@qverisai/mcp`).
10
+ *
11
+ * @module client
12
+ */
13
+ import { QverisApiError } from './errors.js';
14
+ /** Region-specific API base URLs */
15
+ const REGION_URLS = {
16
+ global: 'https://qveris.ai/api/v1',
17
+ cn: 'https://qveris.cn/api/v1',
18
+ };
19
+ /**
20
+ * Detect region from API key prefix.
21
+ * sk-cn-xxx -> cn, sk-xxx -> global
22
+ */
23
+ function detectRegionFromKey(apiKey) {
24
+ return apiKey.startsWith('sk-cn-') ? 'cn' : 'global';
25
+ }
26
+ /**
27
+ * Resolve the base URL for the QVeris API.
28
+ * Priority: explicit baseUrl > QVERIS_BASE_URL env > QVERIS_REGION env > key prefix auto-detect > default
29
+ */
30
+ function resolveBaseUrl(apiKey, explicitBaseUrl) {
31
+ if (explicitBaseUrl)
32
+ return explicitBaseUrl.replace(/\/+$/, '');
33
+ if (typeof process !== 'undefined') {
34
+ if (process.env.QVERIS_BASE_URL)
35
+ return process.env.QVERIS_BASE_URL.replace(/\/+$/, '');
36
+ if (process.env.QVERIS_REGION) {
37
+ const region = process.env.QVERIS_REGION.toLowerCase();
38
+ return REGION_URLS[region] ?? REGION_URLS.global;
39
+ }
40
+ }
41
+ return REGION_URLS[detectRegionFromKey(apiKey)];
42
+ }
43
+ /** Default timeout: 30s for discover/inspect/audit, 120s for call */
44
+ const DEFAULT_TIMEOUT_MS = 30_000;
45
+ const EXECUTE_TIMEOUT_MS = 120_000;
46
+ /**
47
+ * QVeris API client.
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * import { Qveris } from '@qverisai/sdk';
52
+ *
53
+ * const qveris = new Qveris({ apiKey: process.env.QVERIS_API_KEY! });
54
+ *
55
+ * const found = await qveris.discover('stock price market data API', { limit: 5 });
56
+ * const tool = found.results[0];
57
+ *
58
+ * const outcome = await qveris.call(tool.tool_id, {
59
+ * searchId: found.search_id,
60
+ * parameters: { symbol: 'AAPL' },
61
+ * });
62
+ * ```
63
+ */
64
+ export class Qveris {
65
+ apiKey;
66
+ baseUrl;
67
+ defaultTimeoutMs;
68
+ constructor(config) {
69
+ if (!config.apiKey) {
70
+ throw new Error('QVeris API key is required.\n' +
71
+ 'Global: https://qveris.ai/account?page=api-keys\n' +
72
+ 'China: https://qveris.cn/account?page=api-keys');
73
+ }
74
+ this.apiKey = config.apiKey;
75
+ this.baseUrl = resolveBaseUrl(config.apiKey, config.baseUrl);
76
+ this.defaultTimeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
77
+ }
78
+ /**
79
+ * Create a client from the QVERIS_API_KEY environment variable.
80
+ * Region is auto-detected from the key prefix (sk-cn-xxx -> cn), or
81
+ * overridden via QVERIS_REGION / QVERIS_BASE_URL.
82
+ */
83
+ static fromEnv(overrides) {
84
+ const apiKey = process.env.QVERIS_API_KEY;
85
+ if (!apiKey) {
86
+ throw new Error('QVERIS_API_KEY environment variable is required.\n' +
87
+ 'Global: https://qveris.ai/account?page=api-keys\n' +
88
+ 'China: https://qveris.cn/account?page=api-keys');
89
+ }
90
+ return new Qveris({ apiKey, ...overrides });
91
+ }
92
+ /**
93
+ * Discover capabilities from a natural-language query. Free.
94
+ */
95
+ async discover(query, options = {}) {
96
+ return this.request('discover', 'POST', '/search', {
97
+ query,
98
+ ...(options.limit !== undefined && { limit: options.limit }),
99
+ ...(options.sessionId !== undefined && { session_id: options.sessionId }),
100
+ }, options.timeoutMs);
101
+ }
102
+ /**
103
+ * Inspect capabilities by id to get current parameter schemas. Free.
104
+ * An empty id list resolves locally without a network request.
105
+ */
106
+ async inspect(toolIds, options = {}) {
107
+ const ids = typeof toolIds === 'string' ? [toolIds] : toolIds;
108
+ if (ids.length === 0) {
109
+ return { search_id: options.searchId ?? '', total: 0, results: [] };
110
+ }
111
+ return this.request('inspect', 'POST', '/tools/by-ids', {
112
+ tool_ids: ids,
113
+ ...(options.searchId !== undefined && { search_id: options.searchId }),
114
+ ...(options.sessionId !== undefined && { session_id: options.sessionId }),
115
+ }, options.timeoutMs);
116
+ }
117
+ /**
118
+ * Call a capability. The response may include pre-settlement billing;
119
+ * final charges are reflected in usage() and ledger().
120
+ */
121
+ async call(toolId, options) {
122
+ return this.request('call', 'POST', `/tools/execute?tool_id=${encodeURIComponent(toolId)}`, {
123
+ parameters: options.parameters,
124
+ search_id: options.searchId ?? null,
125
+ ...(options.sessionId !== undefined && { session_id: options.sessionId }),
126
+ ...(options.maxResponseSize !== undefined && {
127
+ max_response_size: options.maxResponseSize,
128
+ }),
129
+ }, options.timeoutMs ?? EXECUTE_TIMEOUT_MS);
130
+ }
131
+ /** Get current credit balance and bucket details. */
132
+ async credits() {
133
+ return this.request('credits', 'GET', '/auth/credits');
134
+ }
135
+ /** Query request-level usage audit history. */
136
+ async usage(filters = {}) {
137
+ return this.request('usage_history', 'GET', '/auth/usage/history/v2', undefined, undefined, filters);
138
+ }
139
+ /** Query final credits ledger entries. */
140
+ async ledger(filters = {}) {
141
+ return this.request('credits_ledger', 'GET', '/auth/credits/ledger', undefined, undefined, filters);
142
+ }
143
+ /**
144
+ * Makes an authenticated HTTP request and unwraps success envelopes.
145
+ */
146
+ async request(operation, method, endpoint, body, timeoutMs, query) {
147
+ const url = new URL(`${this.baseUrl}${endpoint}`);
148
+ if (query) {
149
+ for (const [key, value] of Object.entries(query)) {
150
+ if (value !== undefined && value !== null && value !== '') {
151
+ url.searchParams.set(key, String(value));
152
+ }
153
+ }
154
+ }
155
+ const controller = new AbortController();
156
+ const resolvedTimeoutMs = timeoutMs ?? this.defaultTimeoutMs;
157
+ const queryParams = Object.fromEntries(url.searchParams.entries());
158
+ const requestContext = {
159
+ source: 'qveris_api',
160
+ operation,
161
+ method,
162
+ endpoint,
163
+ url: url.toString(),
164
+ ...(Object.keys(queryParams).length > 0 && { query_params: queryParams }),
165
+ timeout_ms: resolvedTimeoutMs,
166
+ };
167
+ const timeout = setTimeout(() => controller.abort(), resolvedTimeoutMs);
168
+ try {
169
+ const response = await fetch(url.toString(), {
170
+ method,
171
+ headers: {
172
+ 'Authorization': `Bearer ${this.apiKey}`,
173
+ 'Content-Type': 'application/json',
174
+ },
175
+ body: body ? JSON.stringify(body) : undefined,
176
+ signal: controller.signal,
177
+ });
178
+ if (!response.ok) {
179
+ const status = response.status;
180
+ let errorMessage;
181
+ let errorDetails;
182
+ try {
183
+ const errorBody = (await response.json());
184
+ errorMessage =
185
+ errorBody.error_message ||
186
+ errorBody.message ||
187
+ errorBody.error ||
188
+ response.statusText;
189
+ errorDetails = errorBody;
190
+ }
191
+ catch {
192
+ errorMessage = response.statusText || `HTTP ${status}`;
193
+ }
194
+ if (status === 402) {
195
+ const pricingHost = this.baseUrl.includes('qveris.cn')
196
+ ? 'https://qveris.cn'
197
+ : 'https://qveris.ai';
198
+ errorMessage = `Insufficient credits. ${errorMessage}. Purchase credits at ${pricingHost}/pricing`;
199
+ }
200
+ throw new QverisApiError({
201
+ status,
202
+ message: errorMessage,
203
+ ...(errorDetails !== undefined && { details: errorDetails }),
204
+ observability: withErrorContext(requestContext, 'http_error', status, extractRequestId(response)),
205
+ });
206
+ }
207
+ let payload;
208
+ try {
209
+ payload = await response.json();
210
+ }
211
+ catch {
212
+ throw new QverisApiError({
213
+ status: response.status,
214
+ message: 'Invalid or empty JSON response from API',
215
+ observability: withErrorContext(requestContext, 'invalid_json', response.status, extractRequestId(response)),
216
+ });
217
+ }
218
+ return this.unwrapEnvelope(payload, requestContext);
219
+ }
220
+ catch (err) {
221
+ if (err instanceof QverisApiError) {
222
+ throw err;
223
+ }
224
+ if (err instanceof Error && err.name === 'AbortError') {
225
+ throw new QverisApiError({
226
+ status: 408,
227
+ message: 'Request timed out. Check connectivity or increase timeout.',
228
+ observability: withErrorContext(requestContext, 'timeout', 0),
229
+ ...(errorCause(err) && { cause: errorCause(err) }),
230
+ });
231
+ }
232
+ throw new QverisApiError({
233
+ status: 0,
234
+ message: err instanceof Error && err.message ? err.message : 'Network request failed',
235
+ observability: withErrorContext(requestContext, 'network_error', 0),
236
+ ...(errorCause(err) && { cause: errorCause(err) }),
237
+ });
238
+ }
239
+ finally {
240
+ clearTimeout(timeout);
241
+ }
242
+ }
243
+ /**
244
+ * Unwrap `{status: "success", data: ...}` envelopes; raw payloads pass
245
+ * through. A failure envelope throws before any result parsing, matching
246
+ * the Python SDK behavior.
247
+ */
248
+ unwrapEnvelope(payload, context) {
249
+ if (payload !== null &&
250
+ typeof payload === 'object' &&
251
+ 'status' in payload &&
252
+ 'data' in payload &&
253
+ typeof payload.status === 'string') {
254
+ const envelope = payload;
255
+ if (envelope.status !== 'success') {
256
+ throw new QverisApiError({
257
+ status: envelope.status_code ?? 400,
258
+ message: envelope.message ?? `API returned status "${envelope.status}"`,
259
+ details: payload,
260
+ observability: withErrorContext(context, 'http_error', envelope.status_code ?? 400),
261
+ });
262
+ }
263
+ return envelope.data;
264
+ }
265
+ return payload;
266
+ }
267
+ }
268
+ function withErrorContext(context, errorType, httpStatus, requestId) {
269
+ return {
270
+ ...context,
271
+ error_type: errorType,
272
+ ...(httpStatus !== undefined && { http_status: httpStatus }),
273
+ ...(requestId && { request_id: requestId }),
274
+ };
275
+ }
276
+ function extractRequestId(response) {
277
+ const headers = response.headers;
278
+ return (headers?.get('x-request-id') ??
279
+ headers?.get('x-qveris-request-id') ??
280
+ headers?.get('x-correlation-id') ??
281
+ undefined);
282
+ }
283
+ function errorCause(error) {
284
+ if (!(error instanceof Error))
285
+ return undefined;
286
+ const cause = error.cause;
287
+ if (cause instanceof Error)
288
+ return cause.message;
289
+ if (typeof cause === 'string' && cause)
290
+ return cause;
291
+ return undefined;
292
+ }
293
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * QVeris SDK error types.
3
+ *
4
+ * @module errors
5
+ */
6
+ import type { ApiError, ApiObservability } from './types.js';
7
+ /**
8
+ * Error thrown for any failed QVeris API interaction: HTTP errors,
9
+ * failure envelopes, timeouts, and network failures.
10
+ *
11
+ * Carries the same shape as the wire-level {@link ApiError} so callers can
12
+ * branch on `status` and inspect `observability` for diagnostics.
13
+ */
14
+ export declare class QverisApiError extends Error implements ApiError {
15
+ /** HTTP status code (0 for network errors, 408 for timeouts) */
16
+ readonly status: number;
17
+ /** Original error details if available */
18
+ readonly details?: unknown;
19
+ /** Request metadata for diagnosing API failures */
20
+ readonly observability?: ApiObservability;
21
+ /** Lower-level transport or runtime cause when available */
22
+ readonly cause?: string;
23
+ constructor(error: ApiError);
24
+ }
25
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE7D;;;;;;GAMG;AACH,qBAAa,cAAe,SAAQ,KAAM,YAAW,QAAQ;IAC3D,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,0CAA0C;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAE3B,mDAAmD;IACnD,QAAQ,CAAC,aAAa,CAAC,EAAE,gBAAgB,CAAC;IAE1C,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;gBAEZ,KAAK,EAAE,QAAQ;CAQ5B"}
package/dist/errors.js ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * QVeris SDK error types.
3
+ *
4
+ * @module errors
5
+ */
6
+ /**
7
+ * Error thrown for any failed QVeris API interaction: HTTP errors,
8
+ * failure envelopes, timeouts, and network failures.
9
+ *
10
+ * Carries the same shape as the wire-level {@link ApiError} so callers can
11
+ * branch on `status` and inspect `observability` for diagnostics.
12
+ */
13
+ export class QverisApiError extends Error {
14
+ /** HTTP status code (0 for network errors, 408 for timeouts) */
15
+ status;
16
+ /** Original error details if available */
17
+ details;
18
+ /** Request metadata for diagnosing API failures */
19
+ observability;
20
+ /** Lower-level transport or runtime cause when available */
21
+ cause;
22
+ constructor(error) {
23
+ super(error.message);
24
+ this.name = 'QverisApiError';
25
+ this.status = error.status;
26
+ if (error.details !== undefined)
27
+ this.details = error.details;
28
+ if (error.observability !== undefined)
29
+ this.observability = error.observability;
30
+ if (error.cause !== undefined)
31
+ this.cause = error.cause;
32
+ }
33
+ }
34
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;;;GAMG;AACH,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,gEAAgE;IACvD,MAAM,CAAS;IAExB,0CAA0C;IACjC,OAAO,CAAW;IAE3B,mDAAmD;IAC1C,aAAa,CAAoB;IAE1C,4DAA4D;IACnD,KAAK,CAAU;IAExB,YAAY,KAAe;QACzB,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC3B,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAC9D,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS;YAAE,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;QAChF,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC1D,CAAC;CACF"}
package/dist/index.d.ts CHANGED
@@ -1,27 +1,21 @@
1
- #!/usr/bin/env node
2
1
  /**
3
- * Qveris MCP Server
2
+ * QVeris TypeScript SDK.
4
3
  *
5
- * A Model Context Protocol (MCP) server that provides access to the Qveris
6
- * tool discovery and execution API. Enables LLMs to dynamically search for
7
- * and execute third-party tools via natural language.
8
- *
9
- * @module @qverisai/sdk
10
- * @version 0.1.0
4
+ * Typed client for the QVeris Agent External Data & Tool Harness:
5
+ * discover, inspect, call, plus usage and credits-ledger audit.
11
6
  *
12
7
  * @example
13
- * Configure in Claude Desktop or Cursor:
14
- * ```json
15
- * {
16
- * "mcpServers": {
17
- * "qveris": {
18
- * "command": "npx",
19
- * "args": ["@qverisai/sdk"],
20
- * "env": { "QVERIS_API_KEY": "your-api-key" }
21
- * }
22
- * }
23
- * }
8
+ * ```typescript
9
+ * import { Qveris } from '@qverisai/sdk';
10
+ *
11
+ * const qveris = Qveris.fromEnv();
12
+ * const found = await qveris.discover('weather forecast API');
24
13
  * ```
14
+ *
15
+ * @module @qverisai/sdk
25
16
  */
26
- export {};
17
+ export { Qveris } from './client.js';
18
+ export type { DiscoverOptions, InspectOptions, CallOptions } from './client.js';
19
+ export { QverisApiError } from './errors.js';
20
+ export * from './types.js';
27
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;GAuBG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,cAAc,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,233 +1,20 @@
1
- #!/usr/bin/env node
2
1
  /**
3
- * Qveris MCP Server
2
+ * QVeris TypeScript SDK.
4
3
  *
5
- * A Model Context Protocol (MCP) server that provides access to the Qveris
6
- * tool discovery and execution API. Enables LLMs to dynamically search for
7
- * and execute third-party tools via natural language.
8
- *
9
- * @module @qverisai/sdk
10
- * @version 0.1.0
4
+ * Typed client for the QVeris Agent External Data & Tool Harness:
5
+ * discover, inspect, call, plus usage and credits-ledger audit.
11
6
  *
12
7
  * @example
13
- * Configure in Claude Desktop or Cursor:
14
- * ```json
15
- * {
16
- * "mcpServers": {
17
- * "qveris": {
18
- * "command": "npx",
19
- * "args": ["@qverisai/sdk"],
20
- * "env": { "QVERIS_API_KEY": "your-api-key" }
21
- * }
22
- * }
23
- * }
8
+ * ```typescript
9
+ * import { Qveris } from '@qverisai/sdk';
10
+ *
11
+ * const qveris = Qveris.fromEnv();
12
+ * const found = await qveris.discover('weather forecast API');
24
13
  * ```
25
- */
26
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
27
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
28
- import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
29
- import { v4 as uuidv4 } from 'uuid';
30
- import { createClientFromEnv } from './api/client.js';
31
- import { searchToolsSchema, executeSearchTools, } from './tools/search.js';
32
- import { executeToolSchema, executeExecuteTool, } from './tools/execute.js';
33
- // ============================================================================
34
- // Server Configuration
35
- // ============================================================================
36
- const SERVER_NAME = 'qveris';
37
- const SERVER_VERSION = '0.1.0';
38
- /**
39
- * Main entry point for the Qveris MCP Server.
40
14
  *
41
- * Sets up the MCP server with stdio transport, registers the search_tools
42
- * and execute_tool handlers, and starts listening for requests.
43
- */
44
- async function main() {
45
- // Initialize API client (validates QVERIS_API_KEY)
46
- let client;
47
- try {
48
- client = createClientFromEnv();
49
- }
50
- catch (error) {
51
- console.error(error instanceof Error ? error.message : 'Failed to initialize Qveris client');
52
- process.exit(1);
53
- }
54
- // Generate a default session ID for this server instance
55
- const defaultSessionId = uuidv4();
56
- // Create MCP server
57
- const server = new Server({
58
- name: SERVER_NAME,
59
- version: SERVER_VERSION,
60
- }, {
61
- capabilities: {
62
- tools: {},
63
- },
64
- });
65
- // =========================================================================
66
- // Tool Handlers
67
- // =========================================================================
68
- /**
69
- * Lists available tools.
70
- * Returns the search_tools and execute_tool definitions.
71
- */
72
- server.setRequestHandler(ListToolsRequestSchema, async () => {
73
- return {
74
- tools: [
75
- {
76
- name: 'search_tools',
77
- description: 'Search for available tools based on natural language queries. ' +
78
- 'Returns relevant tools that can help accomplish tasks. ' +
79
- 'Use this to discover tools before executing them.',
80
- inputSchema: searchToolsSchema,
81
- },
82
- {
83
- name: 'execute_tool',
84
- description: 'Execute a specific remote tool with provided parameters. ' +
85
- 'The tool_id and search_id must come from a previous search_tools call. ' +
86
- 'Pass parameters to the tool through params_to_tool as a JSON string.',
87
- inputSchema: executeToolSchema,
88
- },
89
- ],
90
- };
91
- });
92
- /**
93
- * Handles tool execution requests.
94
- * Routes to the appropriate handler based on tool name.
95
- */
96
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
97
- const { name, arguments: args } = request.params;
98
- try {
99
- if (name === 'search_tools') {
100
- const input = args;
101
- // Validate required fields
102
- if (!input.query || typeof input.query !== 'string') {
103
- return {
104
- content: [
105
- {
106
- type: 'text',
107
- text: JSON.stringify({
108
- error: 'Missing required parameter: query',
109
- hint: 'Provide a natural language query describing the tool capability you need',
110
- }),
111
- },
112
- ],
113
- isError: true,
114
- };
115
- }
116
- const result = await executeSearchTools(client, input, defaultSessionId);
117
- return {
118
- content: [
119
- {
120
- type: 'text',
121
- text: JSON.stringify(result, null, 2),
122
- },
123
- ],
124
- };
125
- }
126
- if (name === 'execute_tool') {
127
- const input = args;
128
- // Validate required fields
129
- const missingFields = [];
130
- if (!input.tool_id)
131
- missingFields.push('tool_id');
132
- if (!input.search_id)
133
- missingFields.push('search_id');
134
- if (!input.params_to_tool)
135
- missingFields.push('params_to_tool');
136
- if (missingFields.length > 0) {
137
- return {
138
- content: [
139
- {
140
- type: 'text',
141
- text: JSON.stringify({
142
- error: `Missing required parameters: ${missingFields.join(', ')}`,
143
- hint: 'tool_id and search_id must come from a previous search_tools call',
144
- }),
145
- },
146
- ],
147
- isError: true,
148
- };
149
- }
150
- const result = await executeExecuteTool(client, input, defaultSessionId);
151
- return {
152
- content: [
153
- {
154
- type: 'text',
155
- text: JSON.stringify(result, null, 2),
156
- },
157
- ],
158
- };
159
- }
160
- // Unknown tool
161
- return {
162
- content: [
163
- {
164
- type: 'text',
165
- text: JSON.stringify({
166
- error: `Unknown tool: ${name}`,
167
- available_tools: ['search_tools', 'execute_tool'],
168
- }),
169
- },
170
- ],
171
- isError: true,
172
- };
173
- }
174
- catch (error) {
175
- // Handle API errors
176
- if (isApiError(error)) {
177
- return {
178
- content: [
179
- {
180
- type: 'text',
181
- text: JSON.stringify({
182
- error: error.message,
183
- status: error.status,
184
- details: error.details,
185
- }),
186
- },
187
- ],
188
- isError: true,
189
- };
190
- }
191
- // Handle other errors (including fetch network errors)
192
- const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
193
- const errorCause = error instanceof Error && error.cause instanceof Error
194
- ? error.cause.message
195
- : undefined;
196
- return {
197
- content: [
198
- {
199
- type: 'text',
200
- text: JSON.stringify({
201
- error: errorMessage,
202
- ...(errorCause && { cause: errorCause }),
203
- }),
204
- },
205
- ],
206
- isError: true,
207
- };
208
- }
209
- });
210
- // =========================================================================
211
- // Start Server
212
- // =========================================================================
213
- const transport = new StdioServerTransport();
214
- await server.connect(transport);
215
- // Log startup to stderr (stdout is reserved for MCP protocol)
216
- console.error(`Qveris MCP Server v${SERVER_VERSION} started`);
217
- console.error(`Session ID: ${defaultSessionId}`);
218
- }
219
- /**
220
- * Type guard for API errors.
15
+ * @module @qverisai/sdk
221
16
  */
222
- function isApiError(error) {
223
- return (typeof error === 'object' &&
224
- error !== null &&
225
- 'status' in error &&
226
- 'message' in error);
227
- }
228
- // Run the server
229
- main().catch((error) => {
230
- console.error('Fatal error:', error);
231
- process.exit(1);
232
- });
17
+ export { Qveris } from './client.js';
18
+ export { QverisApiError } from './errors.js';
19
+ export * from './types.js';
233
20
  //# sourceMappingURL=index.js.map