@runapi.ai/mcp-core 0.1.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/config.d.ts +7 -0
- package/dist/config.js +32 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +5 -0
- package/dist/constants.js +6 -0
- package/dist/constants.js.map +1 -0
- package/dist/contract.d.ts +20 -0
- package/dist/contract.js +79 -0
- package/dist/contract.js.map +1 -0
- package/dist/errors.d.ts +10 -0
- package/dist/errors.js +88 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/input-rules.d.ts +3 -0
- package/dist/input-rules.js +35 -0
- package/dist/input-rules.js.map +1 -0
- package/dist/pricing.d.ts +6 -0
- package/dist/pricing.js +44 -0
- package/dist/pricing.js.map +1 -0
- package/dist/runapi-client.d.ts +17 -0
- package/dist/runapi-client.js +115 -0
- package/dist/runapi-client.js.map +1 -0
- package/dist/schema.d.ts +4 -0
- package/dist/schema.js +44 -0
- package/dist/schema.js.map +1 -0
- package/dist/server.d.ts +24 -0
- package/dist/server.js +127 -0
- package/dist/server.js.map +1 -0
- package/dist/text.d.ts +5 -0
- package/dist/text.js +27 -0
- package/dist/text.js.map +1 -0
- package/dist/tool-response.d.ts +6 -0
- package/dist/tool-response.js +11 -0
- package/dist/tool-response.js.map +1 -0
- package/dist/types.d.ts +115 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +49 -0
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type RunApiConfig = {
|
|
2
|
+
apiKey?: string;
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
};
|
|
5
|
+
export declare function configPath(): string;
|
|
6
|
+
export declare function loadConfig(env?: NodeJS.ProcessEnv): RunApiConfig;
|
|
7
|
+
export declare function requireApiKey(config?: RunApiConfig): string;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { DEFAULT_BASE_URL, RUNAPI_API_KEY_ENV } from "./constants.js";
|
|
5
|
+
export function configPath() {
|
|
6
|
+
return path.join(os.homedir(), ".config", "runapi", "config.json");
|
|
7
|
+
}
|
|
8
|
+
export function loadConfig(env = process.env) {
|
|
9
|
+
const file = readConfigFile();
|
|
10
|
+
const apiKey = env[RUNAPI_API_KEY_ENV]?.trim() || file.apiKey || file.api_key || undefined;
|
|
11
|
+
const baseUrl = env.RUNAPI_BASE_URL?.trim() || file.baseUrl || file.base_url || DEFAULT_BASE_URL;
|
|
12
|
+
return { apiKey, baseUrl };
|
|
13
|
+
}
|
|
14
|
+
export function requireApiKey(config = loadConfig()) {
|
|
15
|
+
if (!config.apiKey) {
|
|
16
|
+
throw new Error("RunAPI API key is required. Sign up at https://runapi.ai, go to Dashboard > API Keys, then: mkdir -p ~/.config/runapi && echo '{\"api_key\":\"YOUR_KEY\"}' > ~/.config/runapi/config.json");
|
|
17
|
+
}
|
|
18
|
+
return config.apiKey;
|
|
19
|
+
}
|
|
20
|
+
function readConfigFile() {
|
|
21
|
+
const file = configPath();
|
|
22
|
+
if (!fs.existsSync(file)) {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AActE,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,GAAG,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,IAAI,SAAS,CAAC;IAC3F,MAAM,OAAO,GAAG,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,IAAI,gBAAgB,CAAC;IAEjG,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAM,GAAG,UAAU,EAAE;IACjD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,2LAA2L,CAAC,CAAC;IAC/M,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC;AAED,SAAS,cAAc;IACrB,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAe,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const CORE_PACKAGE_NAME = "@runapi.ai/mcp-core";
|
|
2
|
+
export declare const CORE_PACKAGE_VERSION = "0.1.0";
|
|
3
|
+
export declare const DEFAULT_BASE_URL = "https://runapi.ai";
|
|
4
|
+
export declare const RUNAPI_API_KEY_ENV = "RUNAPI_API_KEY";
|
|
5
|
+
export declare const USER_AGENT = "@runapi.ai/mcp-core/0.1.0";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const CORE_PACKAGE_NAME = "@runapi.ai/mcp-core";
|
|
2
|
+
export const CORE_PACKAGE_VERSION = "0.1.0";
|
|
3
|
+
export const DEFAULT_BASE_URL = "https://runapi.ai";
|
|
4
|
+
export const RUNAPI_API_KEY_ENV = "RUNAPI_API_KEY";
|
|
5
|
+
export const USER_AGENT = `${CORE_PACKAGE_NAME}/${CORE_PACKAGE_VERSION}`;
|
|
6
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAAG,qBAAqB,CAAC;AACvD,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAC5C,MAAM,CAAC,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AACpD,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AACnD,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,iBAAiB,IAAI,oBAAoB,EAAE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Contract, ContractAction, ContractField, ModelInfo } from "./types.js";
|
|
2
|
+
export declare function listContractModels(source: Contract): ModelInfo[];
|
|
3
|
+
export declare function listActionGroups(source: Contract): {
|
|
4
|
+
modality: string;
|
|
5
|
+
actions: string[];
|
|
6
|
+
}[];
|
|
7
|
+
export declare function findAction(service: string, action: string, source: Contract): ContractAction | undefined;
|
|
8
|
+
export declare function findModel(model: string, source: Contract): ModelInfo | undefined;
|
|
9
|
+
export declare function findModels(model: string, source: Contract): ModelInfo[];
|
|
10
|
+
export declare function findModelForAction(service: string, action: string, model: string | undefined, source: Contract): ModelInfo | undefined;
|
|
11
|
+
export declare function fieldsForModel(action: ContractAction, model: string): Record<string, ContractField>;
|
|
12
|
+
export declare function fieldSummary(fields: Record<string, ContractField>): {
|
|
13
|
+
name: string;
|
|
14
|
+
required: boolean;
|
|
15
|
+
enum: unknown[] | undefined;
|
|
16
|
+
default: unknown;
|
|
17
|
+
min: number | undefined;
|
|
18
|
+
max: number | undefined;
|
|
19
|
+
type: string | undefined;
|
|
20
|
+
}[];
|
package/dist/contract.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { contractKey, modalityForAction, routeAction } from "./text.js";
|
|
2
|
+
export function listContractModels(source) {
|
|
3
|
+
return Object.entries(source.actions).flatMap(([key, action]) => {
|
|
4
|
+
const [service, actionSlug] = key.split("/");
|
|
5
|
+
return action.models.map((model) => ({
|
|
6
|
+
service,
|
|
7
|
+
action: action.endpoint,
|
|
8
|
+
route_action: routeAction(actionSlug),
|
|
9
|
+
provider: action.provider,
|
|
10
|
+
model_line: action.model,
|
|
11
|
+
model,
|
|
12
|
+
fields: fieldsForModel(action, model)
|
|
13
|
+
}));
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export function listActionGroups(source) {
|
|
17
|
+
const groups = new Map();
|
|
18
|
+
for (const action of Object.values(source.actions)) {
|
|
19
|
+
const modality = modalityForAction(action.endpoint);
|
|
20
|
+
if (!groups.has(modality)) {
|
|
21
|
+
groups.set(modality, new Set());
|
|
22
|
+
}
|
|
23
|
+
groups.get(modality)?.add(action.endpoint);
|
|
24
|
+
}
|
|
25
|
+
return [...groups.entries()].map(([modality, actions]) => ({
|
|
26
|
+
modality,
|
|
27
|
+
actions: [...actions].sort()
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
export function findAction(service, action, source) {
|
|
31
|
+
const direct = source.actions[contractKey(service, action)];
|
|
32
|
+
if (direct) {
|
|
33
|
+
return direct;
|
|
34
|
+
}
|
|
35
|
+
return Object.entries(source.actions).find(([key, value]) => {
|
|
36
|
+
const [candidateService] = key.split("/");
|
|
37
|
+
return candidateService === service && value.endpoint === action;
|
|
38
|
+
})?.[1];
|
|
39
|
+
}
|
|
40
|
+
export function findModel(model, source) {
|
|
41
|
+
return listContractModels(source).find((entry) => entry.model === model);
|
|
42
|
+
}
|
|
43
|
+
export function findModels(model, source) {
|
|
44
|
+
return listContractModels(source).filter((entry) => entry.model === model);
|
|
45
|
+
}
|
|
46
|
+
export function findModelForAction(service, action, model, source) {
|
|
47
|
+
const entry = findAction(service, action, source);
|
|
48
|
+
if (!entry) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
const selectedModel = model || entry.models[0];
|
|
52
|
+
if (!entry.models.includes(selectedModel)) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
service,
|
|
57
|
+
action: entry.endpoint,
|
|
58
|
+
route_action: entry.endpoint,
|
|
59
|
+
provider: entry.provider,
|
|
60
|
+
model_line: entry.model,
|
|
61
|
+
model: selectedModel,
|
|
62
|
+
fields: fieldsForModel(entry, selectedModel)
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export function fieldsForModel(action, model) {
|
|
66
|
+
return action.fields_by_model[model] || action.fields_by_model.__nil_model__ || {};
|
|
67
|
+
}
|
|
68
|
+
export function fieldSummary(fields) {
|
|
69
|
+
return Object.entries(fields).map(([name, field]) => ({
|
|
70
|
+
name,
|
|
71
|
+
required: Boolean(field.required),
|
|
72
|
+
enum: field.enum,
|
|
73
|
+
default: field.default,
|
|
74
|
+
min: field.min ?? field.minimum,
|
|
75
|
+
max: field.max ?? field.maximum,
|
|
76
|
+
type: field.type
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class RunApiClientError extends Error {
|
|
2
|
+
readonly status?: number | undefined;
|
|
3
|
+
readonly details?: unknown | undefined;
|
|
4
|
+
constructor(message: string, status?: number | undefined, details?: unknown | undefined);
|
|
5
|
+
}
|
|
6
|
+
export declare class PollTimeoutError extends Error {
|
|
7
|
+
constructor(message: string);
|
|
8
|
+
}
|
|
9
|
+
export declare function friendlyError(error: unknown): string;
|
|
10
|
+
export declare function errorFromResponse(response: Response): Promise<RunApiClientError>;
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export class RunApiClientError extends Error {
|
|
2
|
+
status;
|
|
3
|
+
details;
|
|
4
|
+
constructor(message, status, details) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.status = status;
|
|
7
|
+
this.details = details;
|
|
8
|
+
this.name = "RunApiClientError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export class PollTimeoutError extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "PollTimeoutError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function friendlyError(error) {
|
|
18
|
+
if (error instanceof RunApiClientError) {
|
|
19
|
+
switch (error.status) {
|
|
20
|
+
case 401:
|
|
21
|
+
return "RunAPI rejected the API key. Check RUNAPI_API_KEY or ~/.config/runapi/config.json.";
|
|
22
|
+
case 402:
|
|
23
|
+
return "The RunAPI account has insufficient credits. Add credits in the RunAPI dashboard, then retry.";
|
|
24
|
+
case 429:
|
|
25
|
+
return "RunAPI rate limited this request. Wait briefly, then retry.";
|
|
26
|
+
case 503:
|
|
27
|
+
return "This RunAPI service is temporarily unavailable. Retry later or choose another model.";
|
|
28
|
+
default:
|
|
29
|
+
return error.message;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (error instanceof Error) {
|
|
33
|
+
return error.message;
|
|
34
|
+
}
|
|
35
|
+
return "RunAPI request failed.";
|
|
36
|
+
}
|
|
37
|
+
export async function errorFromResponse(response) {
|
|
38
|
+
const text = await response.text();
|
|
39
|
+
let body = text;
|
|
40
|
+
try {
|
|
41
|
+
body = text ? JSON.parse(text) : undefined;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
body = text;
|
|
45
|
+
}
|
|
46
|
+
return new RunApiClientError(extractMessage(body) || defaultMessage(response.status), response.status, body);
|
|
47
|
+
}
|
|
48
|
+
function extractMessage(body) {
|
|
49
|
+
if (typeof body === "string") {
|
|
50
|
+
return body.trim() || undefined;
|
|
51
|
+
}
|
|
52
|
+
if (!body || typeof body !== "object") {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
const record = body;
|
|
56
|
+
for (const key of ["message", "detail", "error", "msg"]) {
|
|
57
|
+
const value = record[key];
|
|
58
|
+
if (typeof value === "string" && value.trim()) {
|
|
59
|
+
return value.trim();
|
|
60
|
+
}
|
|
61
|
+
const nested = extractMessage(value);
|
|
62
|
+
if (nested) {
|
|
63
|
+
return nested;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
function defaultMessage(status) {
|
|
69
|
+
switch (status) {
|
|
70
|
+
case 400:
|
|
71
|
+
return "RunAPI rejected the request parameters.";
|
|
72
|
+
case 401:
|
|
73
|
+
return "RunAPI API key is invalid or missing.";
|
|
74
|
+
case 402:
|
|
75
|
+
return "Insufficient RunAPI credits.";
|
|
76
|
+
case 404:
|
|
77
|
+
return "RunAPI resource was not found.";
|
|
78
|
+
case 422:
|
|
79
|
+
return "RunAPI could not validate the request.";
|
|
80
|
+
case 429:
|
|
81
|
+
return "RunAPI rate limit exceeded.";
|
|
82
|
+
case 503:
|
|
83
|
+
return "RunAPI service unavailable.";
|
|
84
|
+
default:
|
|
85
|
+
return `RunAPI request failed with HTTP ${status}.`;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./constants.js";
|
|
3
|
+
export * from "./config.js";
|
|
4
|
+
export * from "./errors.js";
|
|
5
|
+
export * from "./text.js";
|
|
6
|
+
export * from "./tool-response.js";
|
|
7
|
+
export * from "./schema.js";
|
|
8
|
+
export * from "./contract.js";
|
|
9
|
+
export * from "./pricing.js";
|
|
10
|
+
export { validateInputRules } from "./input-rules.js";
|
|
11
|
+
export * from "./runapi-client.js";
|
|
12
|
+
export * from "./server.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./constants.js";
|
|
3
|
+
export * from "./config.js";
|
|
4
|
+
export * from "./errors.js";
|
|
5
|
+
export * from "./text.js";
|
|
6
|
+
export * from "./tool-response.js";
|
|
7
|
+
export * from "./schema.js";
|
|
8
|
+
export * from "./contract.js";
|
|
9
|
+
export * from "./pricing.js";
|
|
10
|
+
export { validateInputRules } from "./input-rules.js";
|
|
11
|
+
export * from "./runapi-client.js";
|
|
12
|
+
export * from "./server.js";
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function validateInputRules(rules, params) {
|
|
2
|
+
if (rules.length === 0) {
|
|
3
|
+
return undefined;
|
|
4
|
+
}
|
|
5
|
+
const controllingFields = new Set(rules.flatMap((rule) => Object.keys(rule.when)));
|
|
6
|
+
for (const field of controllingFields) {
|
|
7
|
+
if (!hasValue(params[field])) {
|
|
8
|
+
return `${field} is required to choose a valid parameter shape.`;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const rule = rules.find((candidate) => Object.entries(candidate.when).every(([field, value]) => params[field] === value));
|
|
12
|
+
if (!rule) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
const missing = rule.required.filter((field) => !hasValue(params[field]));
|
|
16
|
+
const presentForbidden = rule.forbidden.filter((field) => hasValue(params[field]));
|
|
17
|
+
if (missing.length === 0 && presentForbidden.length === 0) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
const parts = [];
|
|
21
|
+
if (missing.length > 0) {
|
|
22
|
+
parts.push(`requires ${missing.join(", ")}`);
|
|
23
|
+
}
|
|
24
|
+
if (presentForbidden.length > 0) {
|
|
25
|
+
parts.push(`must not include ${presentForbidden.join(", ")}`);
|
|
26
|
+
}
|
|
27
|
+
return `${formatWhen(rule.when)} ${parts.join(" and ")}.`;
|
|
28
|
+
}
|
|
29
|
+
function hasValue(value) {
|
|
30
|
+
return value !== undefined && value !== null && !(typeof value === "string" && value.trim() === "");
|
|
31
|
+
}
|
|
32
|
+
function formatWhen(when) {
|
|
33
|
+
return Object.entries(when).map(([field, value]) => `${field}=${String(value)}`).join(", ");
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=input-rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-rules.js","sourceRoot":"","sources":["../src/input-rules.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,kBAAkB,CAAC,KAAkB,EAAE,MAA+B;IACpF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnF,KAAK,MAAM,KAAK,IAAI,iBAAiB,EAAE,CAAC;QACtC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAC7B,OAAO,GAAG,KAAK,iDAAiD,CAAC;QACnE,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC;IAC1H,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1D,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,KAAK,GAAG,EAAE,CAAC;IACjB,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,YAAY,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,oBAAoB,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;AAC5D,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACtG,CAAC;AAED,SAAS,UAAU,CAAC,IAA6B;IAC/C,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9F,CAAC"}
|
package/dist/pricing.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export function priceForModel(info, source) {
|
|
2
|
+
const key = pricingKey(info);
|
|
3
|
+
const endpoint = source.endpoints?.[key];
|
|
4
|
+
const hasPrice = endpoint ? hasPriceData(endpoint) : false;
|
|
5
|
+
const markup = effectiveMarkup(key, info.provider, source);
|
|
6
|
+
return {
|
|
7
|
+
pricing: endpoint && hasPrice ? presentPrice(endpoint, markup) : undefined,
|
|
8
|
+
pricing_source: hasPrice ? "build-time pricing snapshot" : "pricing page",
|
|
9
|
+
pricing_url: "https://runapi.ai/pricing"
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function pricingKey(info) {
|
|
13
|
+
return `${info.provider}/${info.model_line}/${info.model}/${info.action}`;
|
|
14
|
+
}
|
|
15
|
+
function effectiveMarkup(key, provider, source) {
|
|
16
|
+
return source.endpoint_markup?.[key] ?? source.provider_markup?.[provider] ?? source.markup_rate ?? 1;
|
|
17
|
+
}
|
|
18
|
+
function hasPriceData(endpoint) {
|
|
19
|
+
return Object.values(endpoint).some((value) => value !== undefined && value !== null);
|
|
20
|
+
}
|
|
21
|
+
function presentPrice(endpoint, markup) {
|
|
22
|
+
const result = {};
|
|
23
|
+
for (const [name, value] of Object.entries(endpoint)) {
|
|
24
|
+
if (name === "cost_billing_config") {
|
|
25
|
+
result.billing_config = presentBillingConfig(endpoint.cost_billing_config, markup);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (typeof value === "number") {
|
|
29
|
+
const publicName = name.replace(/^cost_/, "");
|
|
30
|
+
result[publicName] = Number.isInteger(value * markup) ? value * markup : Math.ceil(value * markup);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
function presentBillingConfig(config, markup) {
|
|
36
|
+
if (!config) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
key: config.key,
|
|
41
|
+
overrides: Object.fromEntries(Object.entries(config.overrides || {}).map(([key, value]) => [key, value * markup]))
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=pricing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,aAAa,CAAC,IAAe,EAAE,MAAqB;IAClE,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC3D,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAE3D,OAAO;QACL,OAAO,EAAE,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;QAC1E,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,cAAc;QACzE,WAAW,EAAE,2BAA2B;KACzC,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,IAAe;IACjC,OAAO,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;AAC5E,CAAC;AAED,SAAS,eAAe,CAAC,GAAW,EAAE,QAAgB,EAAE,MAAqB;IAC3E,OAAO,MAAM,CAAC,eAAe,EAAE,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC;AACxG,CAAC;AAED,SAAS,YAAY,CAAC,QAAyB;IAC7C,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC;AACxF,CAAC;AAED,SAAS,YAAY,CAAC,QAAyB,EAAE,MAAc;IAC7D,MAAM,MAAM,GAA4B,EAAE,CAAC;IAE3C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrD,IAAI,IAAI,KAAK,qBAAqB,EAAE,CAAC;YACnC,MAAM,CAAC,cAAc,GAAG,oBAAoB,CAAC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;YACnF,SAAS;QACX,CAAC;QAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC9C,MAAM,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC;QACrG,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,oBAAoB,CAAC,MAA8C,EAAE,MAAc;IAC1F,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC;KACnH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type RunApiConfig } from "./config.js";
|
|
2
|
+
import type { PollingOptions, RunApiPromptsResponse, RunApiTaskResponse, SearchPromptsParams } from "./types.js";
|
|
3
|
+
export declare class RunApiClient {
|
|
4
|
+
private readonly config;
|
|
5
|
+
private readonly fetchImpl;
|
|
6
|
+
private readonly userAgent;
|
|
7
|
+
constructor(config?: RunApiConfig, fetchImpl?: typeof fetch, userAgent?: string);
|
|
8
|
+
listModels(): Promise<unknown>;
|
|
9
|
+
searchPrompts(params?: SearchPromptsParams): Promise<RunApiPromptsResponse>;
|
|
10
|
+
balance(): Promise<unknown>;
|
|
11
|
+
createTask(service: string, action: string, params: Record<string, unknown>): Promise<RunApiTaskResponse>;
|
|
12
|
+
getTask(service: string, taskId: string, action?: string): Promise<RunApiTaskResponse>;
|
|
13
|
+
pollTask(service: string, taskId: string, action?: string, options?: PollingOptions): Promise<RunApiTaskResponse>;
|
|
14
|
+
private request;
|
|
15
|
+
}
|
|
16
|
+
export declare function taskStatus(task?: RunApiTaskResponse): string;
|
|
17
|
+
export declare function taskIdFromResponse(task: RunApiTaskResponse): string | undefined;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { USER_AGENT } from "./constants.js";
|
|
2
|
+
import { loadConfig, requireApiKey } from "./config.js";
|
|
3
|
+
import { errorFromResponse, PollTimeoutError } from "./errors.js";
|
|
4
|
+
const COMPLETED_STATUSES = new Set(["completed", "complete", "succeeded", "success", "finished"]);
|
|
5
|
+
const FAILED_STATUSES = new Set(["failed", "error", "canceled", "cancelled", "timeout"]);
|
|
6
|
+
export class RunApiClient {
|
|
7
|
+
config;
|
|
8
|
+
fetchImpl;
|
|
9
|
+
userAgent;
|
|
10
|
+
constructor(config = loadConfig(), fetchImpl = fetch, userAgent = USER_AGENT) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
this.fetchImpl = fetchImpl;
|
|
13
|
+
this.userAgent = userAgent;
|
|
14
|
+
}
|
|
15
|
+
async listModels() {
|
|
16
|
+
return this.request("GET", "/v1/models", { auth: false });
|
|
17
|
+
}
|
|
18
|
+
async searchPrompts(params = {}) {
|
|
19
|
+
const query = new URLSearchParams();
|
|
20
|
+
appendQuery(query, "modality", params.modality);
|
|
21
|
+
appendQuery(query, "category", params.category);
|
|
22
|
+
appendQuery(query, "tags", params.tags?.join(","));
|
|
23
|
+
appendQuery(query, "q", params.q);
|
|
24
|
+
appendQuery(query, "model", params.model);
|
|
25
|
+
appendQuery(query, "featured", params.featured);
|
|
26
|
+
appendQuery(query, "page", params.page);
|
|
27
|
+
appendQuery(query, "per_page", params.per_page);
|
|
28
|
+
const suffix = query.size > 0 ? `?${query.toString()}` : "";
|
|
29
|
+
return this.request("GET", `/api/v1/prompts${suffix}`, { auth: false });
|
|
30
|
+
}
|
|
31
|
+
async balance() {
|
|
32
|
+
return this.request("GET", "/api/v1/me/balance", { auth: true });
|
|
33
|
+
}
|
|
34
|
+
async createTask(service, action, params) {
|
|
35
|
+
return this.request("POST", `/api/v1/${routeServiceSlug(service)}/${action}`, {
|
|
36
|
+
auth: true,
|
|
37
|
+
body: params
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async getTask(service, taskId, action) {
|
|
41
|
+
const routeService = routeServiceSlug(service);
|
|
42
|
+
const path = action ? `/api/v1/${routeService}/${action}/${taskId}` : `/api/v1/${routeService}/${taskId}`;
|
|
43
|
+
return this.request("GET", path, {
|
|
44
|
+
auth: true
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
async pollTask(service, taskId, action, options = {}) {
|
|
48
|
+
const timeoutMs = options.timeoutMs ?? 120_000;
|
|
49
|
+
const intervalMs = options.intervalMs ?? 5_000;
|
|
50
|
+
const startedAt = Date.now();
|
|
51
|
+
let lastTask;
|
|
52
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
53
|
+
const task = await this.getTask(service, taskId, action);
|
|
54
|
+
lastTask = task;
|
|
55
|
+
await options.onProgress?.(task);
|
|
56
|
+
const status = taskStatus(task);
|
|
57
|
+
if (COMPLETED_STATUSES.has(status) || FAILED_STATUSES.has(status)) {
|
|
58
|
+
return task;
|
|
59
|
+
}
|
|
60
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
61
|
+
}
|
|
62
|
+
throw new PollTimeoutError(`Timed out waiting for RunAPI task ${taskId}. Last status: ${taskStatus(lastTask)}.`);
|
|
63
|
+
}
|
|
64
|
+
async request(method, requestPath, options = {}) {
|
|
65
|
+
const url = new URL(requestPath, this.config.baseUrl.replace(/\/+$/, ""));
|
|
66
|
+
const headers = {
|
|
67
|
+
accept: "application/json",
|
|
68
|
+
"user-agent": this.userAgent,
|
|
69
|
+
...options.headers
|
|
70
|
+
};
|
|
71
|
+
if (options.body !== undefined) {
|
|
72
|
+
headers["content-type"] = "application/json";
|
|
73
|
+
}
|
|
74
|
+
if (options.auth !== false) {
|
|
75
|
+
headers.authorization = `Bearer ${requireApiKey(this.config)}`;
|
|
76
|
+
}
|
|
77
|
+
const response = await this.fetchImpl(url, {
|
|
78
|
+
method,
|
|
79
|
+
headers,
|
|
80
|
+
body: options.body === undefined ? undefined : JSON.stringify(options.body)
|
|
81
|
+
});
|
|
82
|
+
if (!response.ok) {
|
|
83
|
+
throw await errorFromResponse(response);
|
|
84
|
+
}
|
|
85
|
+
if (response.status === 204) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
return await response.json();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export function taskStatus(task) {
|
|
92
|
+
const status = task?.status || task?.state || nestedString(task?.data, "status");
|
|
93
|
+
return typeof status === "string" ? status.toLowerCase() : "unknown";
|
|
94
|
+
}
|
|
95
|
+
export function taskIdFromResponse(task) {
|
|
96
|
+
const id = task.id || task.task_id || nestedString(task.data, "id") || nestedString(task.data, "task_id");
|
|
97
|
+
return typeof id === "string" && id.length > 0 ? id : undefined;
|
|
98
|
+
}
|
|
99
|
+
function nestedString(value, key) {
|
|
100
|
+
if (!value || typeof value !== "object") {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
const nested = value[key];
|
|
104
|
+
return typeof nested === "string" ? nested : undefined;
|
|
105
|
+
}
|
|
106
|
+
function routeServiceSlug(service) {
|
|
107
|
+
return service.replace(/-/g, "_");
|
|
108
|
+
}
|
|
109
|
+
function appendQuery(query, key, value) {
|
|
110
|
+
if (value === undefined || value === "") {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
query.set(key, String(value));
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=runapi-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runapi-client.js","sourceRoot":"","sources":["../src/runapi-client.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ContractField } from "./types.js";
|
|
3
|
+
export declare function validateParams(fields: Record<string, ContractField>, params: Record<string, unknown>): z.objectOutputType<Record<string, z.ZodTypeAny>, z.ZodTypeAny, "passthrough">;
|
|
4
|
+
export declare function zodShapeForFields(fields: Record<string, ContractField>): Record<string, z.ZodTypeAny>;
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function validateParams(fields, params) {
|
|
3
|
+
return z.object(zodShapeForFields(fields)).passthrough().parse(params);
|
|
4
|
+
}
|
|
5
|
+
// The contract stores constraints, not complete JSON Schema. This keeps strict
|
|
6
|
+
// checks for required/enums/ranges while allowing API-specific params to pass through.
|
|
7
|
+
export function zodShapeForFields(fields) {
|
|
8
|
+
return Object.fromEntries(Object.entries(fields).map(([name, field]) => [name, zodForField(field)]));
|
|
9
|
+
}
|
|
10
|
+
function zodForField(field) {
|
|
11
|
+
let schema;
|
|
12
|
+
if (field.enum?.length) {
|
|
13
|
+
schema = z.union(field.enum.map((value) => literalFor(value)));
|
|
14
|
+
}
|
|
15
|
+
else if (field.type === "number" || field.type === "integer" || field.min !== undefined || field.max !== undefined || field.minimum !== undefined || field.maximum !== undefined) {
|
|
16
|
+
let numberSchema = z.number();
|
|
17
|
+
const min = field.min ?? field.minimum;
|
|
18
|
+
const max = field.max ?? field.maximum;
|
|
19
|
+
if (min !== undefined) {
|
|
20
|
+
numberSchema = numberSchema.min(min);
|
|
21
|
+
}
|
|
22
|
+
if (max !== undefined) {
|
|
23
|
+
numberSchema = numberSchema.max(max);
|
|
24
|
+
}
|
|
25
|
+
schema = numberSchema;
|
|
26
|
+
}
|
|
27
|
+
else if (field.type === "boolean") {
|
|
28
|
+
schema = z.boolean();
|
|
29
|
+
}
|
|
30
|
+
else if (field.type === "array") {
|
|
31
|
+
schema = z.array(z.unknown());
|
|
32
|
+
}
|
|
33
|
+
else if (field.type === "object") {
|
|
34
|
+
schema = z.record(z.unknown());
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
schema = z.unknown();
|
|
38
|
+
}
|
|
39
|
+
return field.required ? schema : schema.optional();
|
|
40
|
+
}
|
|
41
|
+
function literalFor(value) {
|
|
42
|
+
return z.literal(value);
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,cAAc,CAAC,MAAqC,EAAE,MAA+B;IACnG,OAAO,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACzE,CAAC;AAED,+EAA+E;AAC/E,uFAAuF;AACvF,MAAM,UAAU,iBAAiB,CAAC,MAAqC;IACrE,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACvG,CAAC;AAED,SAAS,WAAW,CAAC,KAAoB;IACvC,IAAI,MAAoB,CAAC;IAEzB,IAAI,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QACvB,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAA+E,CAAC,CAAC;IAC/I,CAAC;SAAM,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACnL,IAAI,YAAY,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC;QACvC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC;QACvC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,YAAY,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC;QACD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,YAAY,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC;QACD,MAAM,GAAG,YAAY,CAAC;IACxB,CAAC;SAAM,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACpC,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IACvB,CAAC;SAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAClC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAChC,CAAC;SAAM,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IACjC,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IACvB,CAAC;IAED,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,CAAC,CAAC,OAAO,CAAC,KAAc,CAAC,CAAC;AACnC,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { Contract, ContractField, InputRule, PricingConfig } from "./types.js";
|
|
3
|
+
import { RunApiClient } from "./runapi-client.js";
|
|
4
|
+
export type ModelServerTool = {
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
service: string;
|
|
8
|
+
action: string;
|
|
9
|
+
models: string[];
|
|
10
|
+
inputSchema: Record<string, ContractField>;
|
|
11
|
+
};
|
|
12
|
+
export type CreateModelServerOptions = {
|
|
13
|
+
name: string;
|
|
14
|
+
version: string;
|
|
15
|
+
lineSlug: string;
|
|
16
|
+
contract: Contract;
|
|
17
|
+
pricing: PricingConfig;
|
|
18
|
+
inputRules: Record<string, InputRule[]>;
|
|
19
|
+
tools: ModelServerTool[];
|
|
20
|
+
client?: RunApiClient;
|
|
21
|
+
instructions?: string;
|
|
22
|
+
};
|
|
23
|
+
export declare function createModelServer(options: CreateModelServerOptions): McpServer;
|
|
24
|
+
export declare function defaultTimeout(action: string): number;
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { findModelForAction } from "./contract.js";
|
|
4
|
+
import { priceForModel } from "./pricing.js";
|
|
5
|
+
import { validateInputRules } from "./input-rules.js";
|
|
6
|
+
import { validateParams, zodShapeForFields } from "./schema.js";
|
|
7
|
+
import { RunApiClient, taskIdFromResponse, taskStatus } from "./runapi-client.js";
|
|
8
|
+
import { friendlyError } from "./errors.js";
|
|
9
|
+
import { jsonText } from "./tool-response.js";
|
|
10
|
+
// Builds a per-model RunAPI MCP server from injected catalog data — no disk
|
|
11
|
+
// access. Each tool creates and optionally polls a RunAPI task for its
|
|
12
|
+
// service/action, validating params against the tool's inputSchema and the
|
|
13
|
+
// endpoint's cross-field input rules.
|
|
14
|
+
export function createModelServer(options) {
|
|
15
|
+
const { name, version, lineSlug, contract, pricing, inputRules, tools, client = new RunApiClient() } = options;
|
|
16
|
+
const server = new McpServer({
|
|
17
|
+
name,
|
|
18
|
+
version
|
|
19
|
+
}, {
|
|
20
|
+
instructions: options.instructions ?? defaultInstructions(lineSlug),
|
|
21
|
+
capabilities: {
|
|
22
|
+
tools: {}
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
for (const tool of tools) {
|
|
26
|
+
server.tool(tool.name, tool.description, toolShape(tool), async (args, extra) => {
|
|
27
|
+
const { wait = true, timeout_ms, poll_interval_ms, model, ...params } = args;
|
|
28
|
+
try {
|
|
29
|
+
const info = findModelForAction(tool.service, tool.action, model, contract);
|
|
30
|
+
if (!info) {
|
|
31
|
+
return jsonText({
|
|
32
|
+
error: "Unsupported RunAPI service/action/model combination.",
|
|
33
|
+
hint: "This model server was generated for a specific model line; verify the requested model."
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
const body = validateParams(tool.inputSchema, {
|
|
37
|
+
...params,
|
|
38
|
+
...(model ? { model } : {})
|
|
39
|
+
});
|
|
40
|
+
const ruleError = validateInputRules(inputRules[tool.action] ?? [], body);
|
|
41
|
+
if (ruleError) {
|
|
42
|
+
return jsonText({
|
|
43
|
+
error: `Invalid RunAPI parameters: ${ruleError}`,
|
|
44
|
+
hint: "Adjust the parameters to satisfy the endpoint input rules before retrying."
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const price = priceForModel(info, pricing);
|
|
48
|
+
const created = await client.createTask(tool.service, tool.action, body);
|
|
49
|
+
const taskId = taskIdFromResponse(created);
|
|
50
|
+
if (!wait || !taskId) {
|
|
51
|
+
return jsonText({
|
|
52
|
+
created,
|
|
53
|
+
task_id: taskId,
|
|
54
|
+
status: taskStatus(created),
|
|
55
|
+
price
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const timeout = timeout_ms ?? defaultTimeout(tool.action);
|
|
59
|
+
const startedAt = Date.now();
|
|
60
|
+
const completed = await client.pollTask(tool.service, taskId, tool.action, {
|
|
61
|
+
timeoutMs: timeout,
|
|
62
|
+
intervalMs: poll_interval_ms ?? 5_000,
|
|
63
|
+
onProgress: async (task) => {
|
|
64
|
+
const elapsed = Date.now() - startedAt;
|
|
65
|
+
await extra.sendNotification?.({
|
|
66
|
+
method: "notifications/progress",
|
|
67
|
+
params: {
|
|
68
|
+
progressToken: extra._meta?.progressToken ?? taskId,
|
|
69
|
+
progress: Math.min(elapsed, timeout),
|
|
70
|
+
total: timeout,
|
|
71
|
+
message: `RunAPI task ${taskId}: ${taskStatus(task)}`
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return jsonText({
|
|
77
|
+
task_id: taskId,
|
|
78
|
+
status: taskStatus(completed),
|
|
79
|
+
result: completed,
|
|
80
|
+
price
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
return jsonText({ error: friendlyError(error) });
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return server;
|
|
89
|
+
}
|
|
90
|
+
function toolShape(tool) {
|
|
91
|
+
const shape = {
|
|
92
|
+
...zodShapeForFields(tool.inputSchema),
|
|
93
|
+
wait: z.boolean().default(true).describe("Poll until the task reaches a terminal status."),
|
|
94
|
+
timeout_ms: z.number().int().positive().optional(),
|
|
95
|
+
poll_interval_ms: z.number().int().positive().optional()
|
|
96
|
+
};
|
|
97
|
+
if (tool.models.length > 0) {
|
|
98
|
+
shape.model = z.enum(tool.models).optional().describe("RunAPI model slug for this model line.");
|
|
99
|
+
}
|
|
100
|
+
return shape;
|
|
101
|
+
}
|
|
102
|
+
export function defaultTimeout(action) {
|
|
103
|
+
if (action.includes("video")) {
|
|
104
|
+
return 300_000;
|
|
105
|
+
}
|
|
106
|
+
if (["music", "audio", "speech", "sound", "voice"].some((term) => action.includes(term))) {
|
|
107
|
+
return 300_000;
|
|
108
|
+
}
|
|
109
|
+
if (action.includes("image")) {
|
|
110
|
+
return 120_000;
|
|
111
|
+
}
|
|
112
|
+
return 30_000;
|
|
113
|
+
}
|
|
114
|
+
function defaultInstructions(lineSlug) {
|
|
115
|
+
return [
|
|
116
|
+
`RunAPI MCP server for the ${lineSlug} model line.`,
|
|
117
|
+
"",
|
|
118
|
+
"Each tool creates a RunAPI media task and optionally polls until completion.",
|
|
119
|
+
"Behavior:",
|
|
120
|
+
"1. Use the user's language and be concise.",
|
|
121
|
+
"2. Confirm before expensive, long-running, or batch requests.",
|
|
122
|
+
"3. Present results as task ID, status, output URLs, and cost fields when available.",
|
|
123
|
+
"4. Do not describe generated media as if you inspected it.",
|
|
124
|
+
"5. On an API key error, guide the user to configure RUNAPI_API_KEY or ~/.config/runapi/config.json."
|
|
125
|
+
].join("\n");
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/text.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function humanize(value: string): string;
|
|
2
|
+
export declare function modalityForAction(action: string): "image" | "video" | "audio" | "utility";
|
|
3
|
+
export declare function contractKey(service: string, action: string): string;
|
|
4
|
+
export declare function routeAction(action: string): string;
|
|
5
|
+
export declare function publicModelUrl(model: string): string;
|
package/dist/text.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function humanize(value) {
|
|
2
|
+
return value
|
|
3
|
+
.replace(/[_-]+/g, " ")
|
|
4
|
+
.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
5
|
+
}
|
|
6
|
+
export function modalityForAction(action) {
|
|
7
|
+
if (action.includes("video") || action === "ai_avatar" || action === "motion_control" || action === "animate") {
|
|
8
|
+
return "video";
|
|
9
|
+
}
|
|
10
|
+
if (action.includes("image") || action.includes("background") || action === "create_character") {
|
|
11
|
+
return "image";
|
|
12
|
+
}
|
|
13
|
+
if (action.includes("audio") || action.includes("music") || action.includes("speech") || action.includes("sound") || action.includes("voice") || action.includes("dialogue")) {
|
|
14
|
+
return "audio";
|
|
15
|
+
}
|
|
16
|
+
return "utility";
|
|
17
|
+
}
|
|
18
|
+
export function contractKey(service, action) {
|
|
19
|
+
return `${service}/${action.replaceAll("_", "-")}`;
|
|
20
|
+
}
|
|
21
|
+
export function routeAction(action) {
|
|
22
|
+
return action.replaceAll("-", "_");
|
|
23
|
+
}
|
|
24
|
+
export function publicModelUrl(model) {
|
|
25
|
+
return `https://runapi.ai/pricing?model=${encodeURIComponent(model)}`;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=text.js.map
|
package/dist/text.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../src/text.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,OAAO,KAAK;SACT,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,gBAAgB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9G,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,MAAM,KAAK,kBAAkB,EAAE,CAAC;QAC/F,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7K,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,MAAc;IACzD,OAAO,GAAG,OAAO,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,OAAO,mCAAmC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;AACxE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-response.js","sourceRoot":"","sources":["../src/tool-response.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;aACrC;SACF;KACF,CAAC;AACJ,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
export type ContractField = {
|
|
2
|
+
required?: boolean;
|
|
3
|
+
enum?: unknown[];
|
|
4
|
+
default?: unknown;
|
|
5
|
+
min?: number;
|
|
6
|
+
max?: number;
|
|
7
|
+
minimum?: number;
|
|
8
|
+
maximum?: number;
|
|
9
|
+
type?: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
};
|
|
12
|
+
export type ContractAction = {
|
|
13
|
+
provider: string;
|
|
14
|
+
model: string;
|
|
15
|
+
endpoint: string;
|
|
16
|
+
models: string[];
|
|
17
|
+
fields_by_model: Record<string, Record<string, ContractField>>;
|
|
18
|
+
};
|
|
19
|
+
export type Contract = {
|
|
20
|
+
generated_by: string;
|
|
21
|
+
catalog_models: string[];
|
|
22
|
+
actions: Record<string, ContractAction>;
|
|
23
|
+
unresolved_actions: string[];
|
|
24
|
+
};
|
|
25
|
+
export type PricingConfig = {
|
|
26
|
+
markup_rate?: number;
|
|
27
|
+
provider_markup?: Record<string, number>;
|
|
28
|
+
endpoint_markup?: Record<string, number>;
|
|
29
|
+
endpoints?: Record<string, PricingEndpoint>;
|
|
30
|
+
};
|
|
31
|
+
export type PricingEndpoint = {
|
|
32
|
+
cost_unit_price_cents?: number;
|
|
33
|
+
cost_input_price_per_1m_cents?: number;
|
|
34
|
+
cost_output_price_per_1m_cents?: number;
|
|
35
|
+
cost_cache_read_price_per_1m_cents?: number;
|
|
36
|
+
cost_cache_write_5m_price_per_1m_cents?: number;
|
|
37
|
+
cost_cache_write_1h_price_per_1m_cents?: number;
|
|
38
|
+
cost_billing_config?: {
|
|
39
|
+
key?: string;
|
|
40
|
+
overrides?: Record<string, number>;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
export type ModelInfo = {
|
|
44
|
+
service: string;
|
|
45
|
+
action: string;
|
|
46
|
+
route_action: string;
|
|
47
|
+
provider: string;
|
|
48
|
+
model_line: string;
|
|
49
|
+
model: string;
|
|
50
|
+
fields: Record<string, ContractField>;
|
|
51
|
+
};
|
|
52
|
+
export type RunApiTaskResponse = {
|
|
53
|
+
id?: string;
|
|
54
|
+
task_id?: string;
|
|
55
|
+
status?: string;
|
|
56
|
+
state?: string;
|
|
57
|
+
data?: unknown;
|
|
58
|
+
result?: unknown;
|
|
59
|
+
output?: unknown;
|
|
60
|
+
outputs?: unknown;
|
|
61
|
+
url?: string;
|
|
62
|
+
urls?: string[];
|
|
63
|
+
cost_cents?: number;
|
|
64
|
+
amount_cents?: number;
|
|
65
|
+
[key: string]: unknown;
|
|
66
|
+
};
|
|
67
|
+
export type SearchPromptsParams = {
|
|
68
|
+
modality?: string;
|
|
69
|
+
category?: string;
|
|
70
|
+
tags?: string[];
|
|
71
|
+
q?: string;
|
|
72
|
+
model?: string;
|
|
73
|
+
featured?: boolean;
|
|
74
|
+
page?: number;
|
|
75
|
+
per_page?: number;
|
|
76
|
+
};
|
|
77
|
+
export type RunApiPrompt = {
|
|
78
|
+
id: number;
|
|
79
|
+
title?: string | null;
|
|
80
|
+
prompt: string;
|
|
81
|
+
modality: string;
|
|
82
|
+
service?: string | null;
|
|
83
|
+
action?: string | null;
|
|
84
|
+
runapi_model?: string | null;
|
|
85
|
+
source_model?: string | null;
|
|
86
|
+
source?: string | null;
|
|
87
|
+
source_url?: string | null;
|
|
88
|
+
category?: string | null;
|
|
89
|
+
tags?: string[];
|
|
90
|
+
difficulty?: string | null;
|
|
91
|
+
engagement?: unknown;
|
|
92
|
+
params?: unknown;
|
|
93
|
+
preview_url?: string | null;
|
|
94
|
+
featured?: boolean;
|
|
95
|
+
};
|
|
96
|
+
export type RunApiPromptsResponse = {
|
|
97
|
+
prompts: RunApiPrompt[];
|
|
98
|
+
pagination: {
|
|
99
|
+
page: number;
|
|
100
|
+
per_page: number;
|
|
101
|
+
total: number;
|
|
102
|
+
pages: number;
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
export type PollingOptions = {
|
|
106
|
+
timeoutMs?: number;
|
|
107
|
+
intervalMs?: number;
|
|
108
|
+
onProgress?: (task: RunApiTaskResponse) => Promise<void> | void;
|
|
109
|
+
};
|
|
110
|
+
export type InputRule = {
|
|
111
|
+
when: Record<string, unknown>;
|
|
112
|
+
required: string[];
|
|
113
|
+
forbidden: string[];
|
|
114
|
+
description: string;
|
|
115
|
+
};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@runapi.ai/mcp-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Reusable core for building RunAPI MCP servers: client, contract/pricing/schema queries, input-rule engine, and a createModelServer factory.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc -p tsconfig.json",
|
|
13
|
+
"prepack": "npm run build",
|
|
14
|
+
"typecheck": "tsc --noEmit",
|
|
15
|
+
"test": "vitest run"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"runapi",
|
|
19
|
+
"mcp",
|
|
20
|
+
"model-context-protocol",
|
|
21
|
+
"ai"
|
|
22
|
+
],
|
|
23
|
+
"author": "RunAPI",
|
|
24
|
+
"license": "Apache-2.0",
|
|
25
|
+
"homepage": "https://runapi.ai",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/runapi-ai/mcp-core.git"
|
|
29
|
+
},
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/runapi-ai/mcp-core/issues"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=22.0.0"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
38
|
+
"zod": "^3.25.76"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^24.10.1",
|
|
42
|
+
"tsx": "^4.20.6",
|
|
43
|
+
"typescript": "^5.9.3",
|
|
44
|
+
"vitest": "^4.0.14"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
}
|
|
49
|
+
}
|