@spicyapi/mcp 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/LICENSE +21 -0
- package/README.md +16 -0
- package/SECURITY.md +4 -0
- package/dist/src/mcp/http.d.ts +15 -0
- package/dist/src/mcp/http.d.ts.map +1 -0
- package/dist/src/mcp/http.js +173 -0
- package/dist/src/mcp/http.js.map +1 -0
- package/dist/src/mcp/server.d.ts +14 -0
- package/dist/src/mcp/server.d.ts.map +1 -0
- package/dist/src/mcp/server.js +502 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/mcp/stdio.d.ts +5 -0
- package/dist/src/mcp/stdio.d.ts.map +1 -0
- package/dist/src/mcp/stdio.js +21 -0
- package/dist/src/mcp/stdio.js.map +1 -0
- package/dist/src/runtime/entrypoint.d.ts +2 -0
- package/dist/src/runtime/entrypoint.d.ts.map +1 -0
- package/dist/src/runtime/entrypoint.js +15 -0
- package/dist/src/runtime/entrypoint.js.map +1 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SpicyAPI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# @spicyapi/mcp
|
|
2
|
+
|
|
3
|
+
Official standalone local MCP server for SpicyAPI. It exposes `spicyapi-mcp` for stdio and
|
|
4
|
+
`spicyapi-mcp-http` for loopback-only Streamable HTTP. It does not include the CLI or Codex Skill.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
npx --yes --package=@spicyapi/mcp spicyapi-mcp
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Set `SPICY_API_KEY` in the MCP process environment. Billable tools use protocol elicitation and
|
|
11
|
+
signed request state before creating or retrying a task.
|
|
12
|
+
|
|
13
|
+
The HTTP entrypoint requires a separate `SPICY_MCP_HTTP_TOKEN` of at least 32 bytes and refuses
|
|
14
|
+
non-loopback binding.
|
|
15
|
+
|
|
16
|
+
Client configuration: <https://spicyapi.ai/en/docs/agents>
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { type Server } from "node:http";
|
|
3
|
+
import { type SpicyMcpFactoryOptions } from "./server.js";
|
|
4
|
+
export interface SpicyMcpHttpOptions extends Omit<SpicyMcpFactoryOptions, "client"> {
|
|
5
|
+
host?: string;
|
|
6
|
+
port?: number;
|
|
7
|
+
token?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface SpicyMcpHttpHandle {
|
|
10
|
+
server: Server;
|
|
11
|
+
url: string;
|
|
12
|
+
close: () => Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export declare function startHttpServer(options?: SpicyMcpHttpOptions): Promise<SpicyMcpHttpHandle>;
|
|
15
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/mcp/http.ts"],"names":[],"mappings":";AAGA,OAAO,EAAsC,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAW5E,OAAO,EAAyB,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAIjF,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,sBAAsB,EAAE,QAAQ,CAAC;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAyCD,wBAAsB,eAAe,CACnC,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CA0H7B"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { timingSafeEqual } from "node:crypto";
|
|
3
|
+
import { createServer } from "node:http";
|
|
4
|
+
import { Readable } from "node:stream";
|
|
5
|
+
import { localhostHostValidation, localhostOriginValidation, toNodeHandler, } from "@modelcontextprotocol/node";
|
|
6
|
+
import { createMcpHandler } from "@modelcontextprotocol/server";
|
|
7
|
+
import { isMainModule } from "../runtime/entrypoint.js";
|
|
8
|
+
import { createSpicyMcpFactory } from "./server.js";
|
|
9
|
+
const MAX_MCP_BODY_BYTES = 2 * 1_024 * 1_024;
|
|
10
|
+
function isLoopbackHost(host) {
|
|
11
|
+
return host === "127.0.0.1" || host === "localhost" || host === "::1";
|
|
12
|
+
}
|
|
13
|
+
function authorized(header, token) {
|
|
14
|
+
if (!header?.startsWith("Bearer "))
|
|
15
|
+
return false;
|
|
16
|
+
const provided = Buffer.from(header.slice("Bearer ".length), "utf8");
|
|
17
|
+
const expected = Buffer.from(token, "utf8");
|
|
18
|
+
if (provided.byteLength !== expected.byteLength) {
|
|
19
|
+
const padded = Buffer.alloc(expected.byteLength);
|
|
20
|
+
provided.copy(padded, 0, 0, expected.byteLength);
|
|
21
|
+
timingSafeEqual(expected, padded);
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
return timingSafeEqual(expected, provided);
|
|
25
|
+
}
|
|
26
|
+
function parsePort(value) {
|
|
27
|
+
const parsed = Number(value ?? "8765");
|
|
28
|
+
if (!Number.isInteger(parsed) || parsed < 0 || parsed > 65_535) {
|
|
29
|
+
throw new TypeError("SPICY_MCP_PORT must be an integer between 0 and 65535");
|
|
30
|
+
}
|
|
31
|
+
return parsed;
|
|
32
|
+
}
|
|
33
|
+
class RequestBodyTooLargeError extends Error {
|
|
34
|
+
}
|
|
35
|
+
async function readBoundedBody(request) {
|
|
36
|
+
let total = 0;
|
|
37
|
+
const chunks = [];
|
|
38
|
+
for await (const value of request) {
|
|
39
|
+
const chunk = Buffer.isBuffer(value) ? value : Buffer.from(value);
|
|
40
|
+
total += chunk.byteLength;
|
|
41
|
+
if (total > MAX_MCP_BODY_BYTES)
|
|
42
|
+
throw new RequestBodyTooLargeError();
|
|
43
|
+
chunks.push(chunk);
|
|
44
|
+
}
|
|
45
|
+
return Buffer.concat(chunks, total);
|
|
46
|
+
}
|
|
47
|
+
export async function startHttpServer(options = {}) {
|
|
48
|
+
const host = options.host ?? process.env.SPICY_MCP_HOST ?? "127.0.0.1";
|
|
49
|
+
if (!isLoopbackHost(host)) {
|
|
50
|
+
throw new Error("remote MCP HTTP is disabled: use a standards-compliant OAuth resource server with audience-bound tokens");
|
|
51
|
+
}
|
|
52
|
+
const port = options.port ?? parsePort(process.env.SPICY_MCP_PORT);
|
|
53
|
+
const token = options.token ?? process.env.SPICY_MCP_HTTP_TOKEN;
|
|
54
|
+
if (!token || Buffer.byteLength(token, "utf8") < 32) {
|
|
55
|
+
throw new Error("SPICY_MCP_HTTP_TOKEN must contain at least 32 bytes of random secret material");
|
|
56
|
+
}
|
|
57
|
+
const apiKey = options.clientOptions?.apiKey ?? process.env.SPICY_API_KEY;
|
|
58
|
+
if (apiKey && token === apiKey) {
|
|
59
|
+
throw new Error("SPICY_MCP_HTTP_TOKEN must be separate from SPICY_API_KEY");
|
|
60
|
+
}
|
|
61
|
+
const factory = createSpicyMcpFactory({
|
|
62
|
+
...options,
|
|
63
|
+
stateSecret: options.stateSecret ?? token,
|
|
64
|
+
principalBinding: options.principalBinding ?? "local-http-token",
|
|
65
|
+
});
|
|
66
|
+
const handler = createMcpHandler(factory, {
|
|
67
|
+
legacy: "stateless",
|
|
68
|
+
responseMode: "auto",
|
|
69
|
+
maxSubscriptions: 128,
|
|
70
|
+
onerror: options.onError ?? ((error) => console.error(error.message)),
|
|
71
|
+
});
|
|
72
|
+
const nodeHandler = toNodeHandler(handler);
|
|
73
|
+
const validateHost = localhostHostValidation();
|
|
74
|
+
const validateOrigin = localhostOriginValidation();
|
|
75
|
+
const server = createServer({
|
|
76
|
+
requestTimeout: 120_000,
|
|
77
|
+
headersTimeout: 15_000,
|
|
78
|
+
keepAliveTimeout: 5_000,
|
|
79
|
+
});
|
|
80
|
+
server.on("request", (request, response) => {
|
|
81
|
+
void (async () => {
|
|
82
|
+
const pathname = new URL(request.url ?? "/", "http://localhost").pathname;
|
|
83
|
+
if (pathname === "/healthz" && request.method === "GET") {
|
|
84
|
+
response.writeHead(200, {
|
|
85
|
+
"Content-Type": "application/json",
|
|
86
|
+
"Cache-Control": "no-store",
|
|
87
|
+
});
|
|
88
|
+
response.end('{"ok":true}');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (pathname !== "/mcp") {
|
|
92
|
+
response.writeHead(404, { "Content-Type": "application/json" });
|
|
93
|
+
response.end('{"error":"not found"}');
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (!validateHost(request, response) || !validateOrigin(request, response))
|
|
97
|
+
return;
|
|
98
|
+
if (!authorized(request.headers.authorization, token)) {
|
|
99
|
+
response.writeHead(401, {
|
|
100
|
+
"Content-Type": "application/json",
|
|
101
|
+
"Cache-Control": "no-store",
|
|
102
|
+
"WWW-Authenticate": 'Bearer realm="spicyapi-mcp"',
|
|
103
|
+
});
|
|
104
|
+
response.end('{"error":"unauthorized"}');
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const declaredLength = Number(request.headers["content-length"] ?? "0");
|
|
108
|
+
if (Number.isFinite(declaredLength) && declaredLength > MAX_MCP_BODY_BYTES) {
|
|
109
|
+
response.writeHead(413, { "Content-Type": "application/json", Connection: "close" });
|
|
110
|
+
response.end('{"error":"request body too large"}');
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const body = await readBoundedBody(request);
|
|
115
|
+
await nodeHandler({
|
|
116
|
+
headers: request.headers,
|
|
117
|
+
...(request.method === undefined ? {} : { method: request.method }),
|
|
118
|
+
...(request.url === undefined ? {} : { url: request.url }),
|
|
119
|
+
[Symbol.asyncIterator]: () => Readable.from(body.byteLength > 0 ? [body] : [])[Symbol.asyncIterator](),
|
|
120
|
+
}, response);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
if (!(error instanceof RequestBodyTooLargeError))
|
|
124
|
+
throw error;
|
|
125
|
+
request.resume();
|
|
126
|
+
if (!response.headersSent) {
|
|
127
|
+
response.writeHead(413, { "Content-Type": "application/json", Connection: "close" });
|
|
128
|
+
}
|
|
129
|
+
if (!response.writableEnded)
|
|
130
|
+
response.end('{"error":"request body too large"}');
|
|
131
|
+
}
|
|
132
|
+
})().catch((error) => {
|
|
133
|
+
(options.onError ?? console.error)(error instanceof Error ? error : new Error("MCP HTTP request failed"));
|
|
134
|
+
if (!response.headersSent)
|
|
135
|
+
response.writeHead(500, { "Content-Type": "application/json" });
|
|
136
|
+
if (!response.writableEnded)
|
|
137
|
+
response.end('{"error":"internal error"}');
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
await new Promise((resolve, reject) => {
|
|
141
|
+
server.once("error", reject);
|
|
142
|
+
server.listen(port, host, () => {
|
|
143
|
+
server.off("error", reject);
|
|
144
|
+
resolve();
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
const address = server.address();
|
|
148
|
+
if (address === null || typeof address === "string")
|
|
149
|
+
throw new Error("MCP HTTP server did not bind a TCP port");
|
|
150
|
+
const displayHost = host === "::1" ? "[::1]" : host;
|
|
151
|
+
return {
|
|
152
|
+
server,
|
|
153
|
+
url: `http://${displayHost}:${address.port}/mcp`,
|
|
154
|
+
close: async () => {
|
|
155
|
+
await handler.close();
|
|
156
|
+
await new Promise((resolve, reject) => {
|
|
157
|
+
server.close((error) => (error ? reject(error) : resolve()));
|
|
158
|
+
});
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
if (isMainModule(import.meta.url)) {
|
|
163
|
+
const handle = await startHttpServer();
|
|
164
|
+
console.error(`SpicyAPI MCP HTTP listening at ${handle.url}`);
|
|
165
|
+
const close = () => {
|
|
166
|
+
void handle.close().catch((error) => {
|
|
167
|
+
console.error(error instanceof Error ? error.message : "failed to close MCP HTTP server");
|
|
168
|
+
});
|
|
169
|
+
};
|
|
170
|
+
process.once("SIGINT", close);
|
|
171
|
+
process.once("SIGTERM", close);
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/mcp/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { McpServer, type McpServerFactory } from "@modelcontextprotocol/server";
|
|
2
|
+
import { SpicyClient, type SpicyClientOptions } from "@spicyapi/sdk";
|
|
3
|
+
export declare const SPICYAPI_MCP_TOOLS: readonly ["spicyapi_service_status", "spicyapi_docs_search", "spicyapi_models_list", "spicyapi_model_get", "spicyapi_balance_get", "spicyapi_task_get", "spicyapi_task_wait", "spicyapi_upload_prepare", "spicyapi_upload_commit", "spicyapi_download_url_create", "spicyapi_task_create", "spicyapi_task_retry"];
|
|
4
|
+
export interface SpicyMcpFactoryOptions {
|
|
5
|
+
client?: SpicyClient;
|
|
6
|
+
clientOptions?: SpicyClientOptions;
|
|
7
|
+
stateSecret?: string | Uint8Array;
|
|
8
|
+
stateTtlSeconds?: number;
|
|
9
|
+
principalBinding?: string;
|
|
10
|
+
onError?: (error: Error) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function createSpicyMcpFactory(options?: SpicyMcpFactoryOptions): McpServerFactory;
|
|
13
|
+
export declare function createSpicyMcpServer(options?: SpicyMcpFactoryOptions): McpServer;
|
|
14
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,SAAS,EAGT,KAAK,gBAAgB,EAEtB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EAKL,WAAW,EACX,KAAK,kBAAkB,EACxB,MAAM,eAAe,CAAC;AAmJvB,eAAO,MAAM,kBAAkB,mTAarB,CAAC;AAEX,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAiED,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,sBAA2B,GAAG,gBAAgB,CA+Z5F;AAED,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,sBAA2B,GAAG,SAAS,CAEpF"}
|
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
2
|
+
import { acceptedContent, createRequestStateCodec, inputRequired, inputResponse, McpServer, } from "@modelcontextprotocol/server";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { DOCUMENTATION, readOpenApiContract, searchDocumentation, SpicyApiError, SpicyClient, } from "@spicyapi/sdk";
|
|
5
|
+
const SERVER_NAME = "spicyapi";
|
|
6
|
+
const SERVER_VERSION = "0.1.0";
|
|
7
|
+
const CONFIRMATION_KEY = "confirm_billable_operation";
|
|
8
|
+
const emptySchema = z.object({});
|
|
9
|
+
const confirmationSchema = z.object({ confirm: z.boolean() });
|
|
10
|
+
const unknownObjectSchema = z.record(z.string(), z.unknown());
|
|
11
|
+
const usdStringSchema = z.string().regex(/^-?[0-9]+(?:\.[0-9]+)?$/);
|
|
12
|
+
const taskStateSchema = z.enum(["queued", "running", "succeeded", "failed", "canceled", "expired"]);
|
|
13
|
+
const uploadContentTypeSchema = z.enum(["image/jpeg", "image/png", "image/webp", "image/gif"]);
|
|
14
|
+
const documentationEntrySchema = z
|
|
15
|
+
.object({
|
|
16
|
+
slug: z.string(),
|
|
17
|
+
title: z.string(),
|
|
18
|
+
summary: z.string(),
|
|
19
|
+
url: z.string(),
|
|
20
|
+
keywords: z.array(z.string()),
|
|
21
|
+
})
|
|
22
|
+
.passthrough();
|
|
23
|
+
const probeSchema = z
|
|
24
|
+
.object({
|
|
25
|
+
path: z.enum(["/healthz", "/readyz"]),
|
|
26
|
+
ok: z.boolean(),
|
|
27
|
+
status: z.number().int(),
|
|
28
|
+
body: z.string(),
|
|
29
|
+
error: z.string().optional(),
|
|
30
|
+
})
|
|
31
|
+
.passthrough();
|
|
32
|
+
const serviceStatusSchema = z
|
|
33
|
+
.object({
|
|
34
|
+
operational: z.boolean(),
|
|
35
|
+
health: probeSchema,
|
|
36
|
+
readiness: probeSchema,
|
|
37
|
+
checkedAt: z.string(),
|
|
38
|
+
})
|
|
39
|
+
.passthrough();
|
|
40
|
+
const modelPriceSchema = z
|
|
41
|
+
.object({
|
|
42
|
+
variant: z.string(),
|
|
43
|
+
unit: z.enum(["per_image", "per_second", "per_request", "per_1k_tokens"]),
|
|
44
|
+
price: usdStringSchema,
|
|
45
|
+
currency: z.literal("USD"),
|
|
46
|
+
})
|
|
47
|
+
.passthrough();
|
|
48
|
+
const modelExampleSchema = z
|
|
49
|
+
.object({ id: z.string(), input: unknownObjectSchema, sortWeight: z.number().int() })
|
|
50
|
+
.passthrough();
|
|
51
|
+
const apiModelSchema = z
|
|
52
|
+
.object({
|
|
53
|
+
model: z.string(),
|
|
54
|
+
family: z.string(),
|
|
55
|
+
displayName: z.string(),
|
|
56
|
+
provider: z.string(),
|
|
57
|
+
modality: z.enum(["image", "video", "audio", "text"]),
|
|
58
|
+
tasks: z.array(z.string()),
|
|
59
|
+
async: z.boolean(),
|
|
60
|
+
mature: z
|
|
61
|
+
.boolean()
|
|
62
|
+
.describe("Informational model capability metadata; not a platform routing or access gate."),
|
|
63
|
+
policyTier: z
|
|
64
|
+
.enum(["unrestricted", "borderline", "unspecified"])
|
|
65
|
+
.describe("Informational model policy metadata; not a platform routing or access gate."),
|
|
66
|
+
taskTimeoutSeconds: z.number().int().positive(),
|
|
67
|
+
maxOutputDurationSeconds: z.number().int().positive().optional(),
|
|
68
|
+
enabled: z.boolean(),
|
|
69
|
+
available: z.boolean(),
|
|
70
|
+
quantityField: z.string(),
|
|
71
|
+
pricing: z.array(modelPriceSchema),
|
|
72
|
+
startingPrice: modelPriceSchema.optional(),
|
|
73
|
+
inputSchema: unknownObjectSchema.optional(),
|
|
74
|
+
version: z.string(),
|
|
75
|
+
availability: z.enum(["planned", "available", "preview", "maintenance"]),
|
|
76
|
+
badges: z.array(z.string()),
|
|
77
|
+
relatedModels: z.array(z.string()),
|
|
78
|
+
examples: z.array(modelExampleSchema).optional(),
|
|
79
|
+
updatedAt: z.string(),
|
|
80
|
+
})
|
|
81
|
+
.passthrough();
|
|
82
|
+
const modelListSchema = z
|
|
83
|
+
.object({ total: z.number().int().nonnegative(), items: z.array(apiModelSchema) })
|
|
84
|
+
.passthrough();
|
|
85
|
+
const balanceSchema = z
|
|
86
|
+
.object({ available: usdStringSchema, held: usdStringSchema, total: usdStringSchema })
|
|
87
|
+
.passthrough();
|
|
88
|
+
const taskRecordSchema = z
|
|
89
|
+
.object({
|
|
90
|
+
taskId: z.string(),
|
|
91
|
+
sourceTaskId: z.string().optional(),
|
|
92
|
+
model: z.string(),
|
|
93
|
+
state: taskStateSchema,
|
|
94
|
+
input: unknownObjectSchema.optional(),
|
|
95
|
+
output: unknownObjectSchema.optional(),
|
|
96
|
+
errorCode: z.string().optional(),
|
|
97
|
+
errorMessage: z.string().optional(),
|
|
98
|
+
cost: usdStringSchema,
|
|
99
|
+
settled: z.boolean(),
|
|
100
|
+
createdAt: z.string(),
|
|
101
|
+
completedAt: z.string().optional(),
|
|
102
|
+
})
|
|
103
|
+
.passthrough();
|
|
104
|
+
const uploadTicketSchema = z
|
|
105
|
+
.object({
|
|
106
|
+
fileId: z.string(),
|
|
107
|
+
key: z.string(),
|
|
108
|
+
uploadUrl: z.string(),
|
|
109
|
+
method: z.literal("PUT"),
|
|
110
|
+
headers: z.record(z.string(), z.string()),
|
|
111
|
+
expiresAt: z.string(),
|
|
112
|
+
maxBytes: z.number().int().positive(),
|
|
113
|
+
})
|
|
114
|
+
.passthrough();
|
|
115
|
+
const uploadedFileSchema = z
|
|
116
|
+
.object({
|
|
117
|
+
fileId: z.string(),
|
|
118
|
+
status: z.literal("ready"),
|
|
119
|
+
bytes: z.number().int().positive(),
|
|
120
|
+
contentType: uploadContentTypeSchema,
|
|
121
|
+
sha256: z.string().regex(/^[a-f0-9]{64}$/),
|
|
122
|
+
uri: z.string(),
|
|
123
|
+
expiresAt: z.string(),
|
|
124
|
+
})
|
|
125
|
+
.passthrough();
|
|
126
|
+
const downloadTicketSchema = z
|
|
127
|
+
.object({ key: z.string(), url: z.string(), expiresAt: z.string() })
|
|
128
|
+
.passthrough();
|
|
129
|
+
const createTaskResultSchema = z
|
|
130
|
+
.object({ taskId: z.string(), state: taskStateSchema, estimatedCost: usdStringSchema })
|
|
131
|
+
.passthrough();
|
|
132
|
+
const retryTaskResultSchema = createTaskResultSchema.extend({ sourceTaskId: z.string() });
|
|
133
|
+
const confirmedCreateTaskResultSchema = createTaskResultSchema.extend({
|
|
134
|
+
idempotencyKey: z.string(),
|
|
135
|
+
});
|
|
136
|
+
const confirmedRetryTaskResultSchema = retryTaskResultSchema.extend({ idempotencyKey: z.string() });
|
|
137
|
+
function resultOf(result) {
|
|
138
|
+
return z.object({ result });
|
|
139
|
+
}
|
|
140
|
+
const billableStateSchema = z.object({
|
|
141
|
+
action: z.enum(["create_task", "retry_task"]),
|
|
142
|
+
fingerprint: z.string(),
|
|
143
|
+
idempotencyKey: z.string(),
|
|
144
|
+
});
|
|
145
|
+
export const SPICYAPI_MCP_TOOLS = [
|
|
146
|
+
"spicyapi_service_status",
|
|
147
|
+
"spicyapi_docs_search",
|
|
148
|
+
"spicyapi_models_list",
|
|
149
|
+
"spicyapi_model_get",
|
|
150
|
+
"spicyapi_balance_get",
|
|
151
|
+
"spicyapi_task_get",
|
|
152
|
+
"spicyapi_task_wait",
|
|
153
|
+
"spicyapi_upload_prepare",
|
|
154
|
+
"spicyapi_upload_commit",
|
|
155
|
+
"spicyapi_download_url_create",
|
|
156
|
+
"spicyapi_task_create",
|
|
157
|
+
"spicyapi_task_retry",
|
|
158
|
+
];
|
|
159
|
+
function jsonResult(value) {
|
|
160
|
+
return {
|
|
161
|
+
content: [{ type: "text", text: JSON.stringify(value, null, 2) }],
|
|
162
|
+
structuredContent: { result: value },
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function toolError(error) {
|
|
166
|
+
if (error instanceof SpicyApiError) {
|
|
167
|
+
const details = {
|
|
168
|
+
error: error.message,
|
|
169
|
+
type: error.name,
|
|
170
|
+
status: error.status,
|
|
171
|
+
...(error.code === undefined ? {} : { code: error.code }),
|
|
172
|
+
...(error.requestId === undefined ? {} : { requestId: error.requestId }),
|
|
173
|
+
...(error.retryAfterSeconds === undefined
|
|
174
|
+
? {}
|
|
175
|
+
: { retryAfterSeconds: error.retryAfterSeconds }),
|
|
176
|
+
};
|
|
177
|
+
return { isError: true, content: [{ type: "text", text: JSON.stringify(details) }] };
|
|
178
|
+
}
|
|
179
|
+
const message = error instanceof Error ? error.message : "unknown error";
|
|
180
|
+
return { isError: true, content: [{ type: "text", text: message }] };
|
|
181
|
+
}
|
|
182
|
+
async function safely(operation) {
|
|
183
|
+
try {
|
|
184
|
+
return jsonResult(await operation());
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
return toolError(error);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function stableJson(value) {
|
|
191
|
+
if (value === null || typeof value !== "object")
|
|
192
|
+
return JSON.stringify(value);
|
|
193
|
+
if (Array.isArray(value))
|
|
194
|
+
return `[${value.map((item) => stableJson(item)).join(",")}]`;
|
|
195
|
+
return `{${Object.entries(value)
|
|
196
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
197
|
+
.map(([key, item]) => `${JSON.stringify(key)}:${stableJson(item)}`)
|
|
198
|
+
.join(",")}}`;
|
|
199
|
+
}
|
|
200
|
+
function fingerprint(action, args) {
|
|
201
|
+
return createHash("sha256")
|
|
202
|
+
.update(`${action}\0${stableJson(args)}`)
|
|
203
|
+
.digest("hex");
|
|
204
|
+
}
|
|
205
|
+
function stateKey(options) {
|
|
206
|
+
if (options.stateSecret !== undefined) {
|
|
207
|
+
const key = typeof options.stateSecret === "string"
|
|
208
|
+
? new TextEncoder().encode(options.stateSecret)
|
|
209
|
+
: options.stateSecret;
|
|
210
|
+
if (key.byteLength < 32)
|
|
211
|
+
throw new RangeError("MCP request-state secret must be at least 32 bytes");
|
|
212
|
+
return key;
|
|
213
|
+
}
|
|
214
|
+
const apiKey = options.clientOptions?.apiKey ?? process.env.SPICY_API_KEY;
|
|
215
|
+
if (apiKey)
|
|
216
|
+
return createHash("sha256").update(`spicyapi.mcp.state\0${apiKey}`).digest();
|
|
217
|
+
return randomBytes(32);
|
|
218
|
+
}
|
|
219
|
+
export function createSpicyMcpFactory(options = {}) {
|
|
220
|
+
const client = options.client ?? new SpicyClient(options.clientOptions);
|
|
221
|
+
const principalBinding = options.principalBinding ?? "local-spicyapi-user";
|
|
222
|
+
const codec = createRequestStateCodec({
|
|
223
|
+
key: stateKey(options),
|
|
224
|
+
ttlSeconds: options.stateTtlSeconds ?? 600,
|
|
225
|
+
bind: (ctx) => `${ctx.mcpReq.method}\0${principalBinding}`,
|
|
226
|
+
});
|
|
227
|
+
return () => {
|
|
228
|
+
const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION }, {
|
|
229
|
+
instructions: "Use the live model catalog as the only source of model IDs and input schemas. Task creation and retry can reserve funds and always require user confirmation. Never invent cancellation or task-list APIs; they are not part of the public contract.",
|
|
230
|
+
cacheHints: {
|
|
231
|
+
"tools/list": { ttlMs: 60_000, cacheScope: "private" },
|
|
232
|
+
"resources/list": { ttlMs: 300_000, cacheScope: "public" },
|
|
233
|
+
"prompts/list": { ttlMs: 300_000, cacheScope: "public" },
|
|
234
|
+
},
|
|
235
|
+
inputRequired: { maxRounds: 3, roundTimeoutMs: 600_000, legacyShim: true },
|
|
236
|
+
requestState: { verify: (state, ctx) => codec.verify(state, ctx) },
|
|
237
|
+
});
|
|
238
|
+
server.server.onerror = (error) => (options.onError ?? console.error)(error);
|
|
239
|
+
async function requireBillableConfirmation(action, args, ctx, message, execute) {
|
|
240
|
+
const expectedFingerprint = fingerprint(action, args);
|
|
241
|
+
const parsedState = billableStateSchema.safeParse(ctx.mcpReq.requestState());
|
|
242
|
+
const state = parsedState.success ? parsedState.data : undefined;
|
|
243
|
+
if (state && (state.action !== action || state.fingerprint !== expectedFingerprint)) {
|
|
244
|
+
return toolError(new Error("confirmed request state does not match the current tool arguments"));
|
|
245
|
+
}
|
|
246
|
+
const response = inputResponse(ctx.mcpReq.inputResponses, CONFIRMATION_KEY);
|
|
247
|
+
if (state && response.kind === "elicit" && response.action !== "accept") {
|
|
248
|
+
return toolError(new Error("operation declined; no SpicyAPI request was made"));
|
|
249
|
+
}
|
|
250
|
+
const confirmation = acceptedContent(ctx.mcpReq.inputResponses, CONFIRMATION_KEY, confirmationSchema);
|
|
251
|
+
if (state && confirmation?.confirm === true) {
|
|
252
|
+
return safely(() => execute(state.idempotencyKey));
|
|
253
|
+
}
|
|
254
|
+
const suppliedKey = typeof args.idempotencyKey === "string" ? args.idempotencyKey : undefined;
|
|
255
|
+
const idempotencyKey = state?.idempotencyKey ?? suppliedKey ?? randomUUID();
|
|
256
|
+
const requestState = await codec.mint({ action, fingerprint: expectedFingerprint, idempotencyKey }, ctx);
|
|
257
|
+
return inputRequired({
|
|
258
|
+
inputRequests: {
|
|
259
|
+
[CONFIRMATION_KEY]: inputRequired.elicit({
|
|
260
|
+
message: `${message} The current model schema, price, operational API-key scope, balance, and routing are evaluated when accepted. The caller-declared mature value is forwarded without a platform content gate. Idempotency-Key: ${idempotencyKey}`,
|
|
261
|
+
requestedSchema: confirmationSchema,
|
|
262
|
+
}),
|
|
263
|
+
},
|
|
264
|
+
requestState,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
server.registerTool("spicyapi_service_status", {
|
|
268
|
+
title: "Check SpicyAPI service status",
|
|
269
|
+
description: "Read public health and readiness endpoints. No API key is required.",
|
|
270
|
+
inputSchema: emptySchema,
|
|
271
|
+
outputSchema: resultOf(serviceStatusSchema),
|
|
272
|
+
annotations: {
|
|
273
|
+
readOnlyHint: true,
|
|
274
|
+
destructiveHint: false,
|
|
275
|
+
idempotentHint: true,
|
|
276
|
+
openWorldHint: true,
|
|
277
|
+
},
|
|
278
|
+
}, async (_args, ctx) => safely(() => client.getStatus({ signal: ctx.mcpReq.signal })));
|
|
279
|
+
server.registerTool("spicyapi_docs_search", {
|
|
280
|
+
title: "Search SpicyAPI documentation",
|
|
281
|
+
description: "Search the bundled index of verified first-party documentation URLs.",
|
|
282
|
+
inputSchema: z.object({
|
|
283
|
+
query: z.string().default(""),
|
|
284
|
+
limit: z.number().int().min(1).max(25).default(10),
|
|
285
|
+
}),
|
|
286
|
+
outputSchema: resultOf(z.array(documentationEntrySchema)),
|
|
287
|
+
annotations: {
|
|
288
|
+
readOnlyHint: true,
|
|
289
|
+
destructiveHint: false,
|
|
290
|
+
idempotentHint: true,
|
|
291
|
+
openWorldHint: false,
|
|
292
|
+
},
|
|
293
|
+
}, ({ query, limit }) => jsonResult(searchDocumentation(query, limit)));
|
|
294
|
+
server.registerTool("spicyapi_models_list", {
|
|
295
|
+
title: "List callable SpicyAPI models",
|
|
296
|
+
description: "Return enabled models and account-specific prices. Use includeSchema before creating a task.",
|
|
297
|
+
inputSchema: z.object({
|
|
298
|
+
modality: z.enum(["image", "video", "audio", "text"]).optional(),
|
|
299
|
+
provider: z.string().optional(),
|
|
300
|
+
task: z.string().optional(),
|
|
301
|
+
search: z.string().optional(),
|
|
302
|
+
includeSchema: z.boolean().default(false),
|
|
303
|
+
includeExamples: z.boolean().default(false),
|
|
304
|
+
}),
|
|
305
|
+
outputSchema: resultOf(modelListSchema),
|
|
306
|
+
annotations: {
|
|
307
|
+
readOnlyHint: true,
|
|
308
|
+
destructiveHint: false,
|
|
309
|
+
idempotentHint: true,
|
|
310
|
+
openWorldHint: true,
|
|
311
|
+
},
|
|
312
|
+
}, async (args, ctx) => safely(() => client.listModels({ ...args, signal: ctx.mcpReq.signal })));
|
|
313
|
+
server.registerTool("spicyapi_model_get", {
|
|
314
|
+
title: "Get one SpicyAPI model",
|
|
315
|
+
description: "Return one exact model, its live input schema, pricing, policy and availability.",
|
|
316
|
+
inputSchema: z.object({ model: z.string().min(1) }),
|
|
317
|
+
outputSchema: resultOf(apiModelSchema),
|
|
318
|
+
annotations: {
|
|
319
|
+
readOnlyHint: true,
|
|
320
|
+
destructiveHint: false,
|
|
321
|
+
idempotentHint: true,
|
|
322
|
+
openWorldHint: true,
|
|
323
|
+
},
|
|
324
|
+
}, async ({ model }, ctx) => safely(() => client.getModel(model, { signal: ctx.mcpReq.signal })));
|
|
325
|
+
server.registerTool("spicyapi_balance_get", {
|
|
326
|
+
title: "Get SpicyAPI credit balance",
|
|
327
|
+
description: "Return available, held, and total credit as exact decimal USD strings.",
|
|
328
|
+
inputSchema: emptySchema,
|
|
329
|
+
outputSchema: resultOf(balanceSchema),
|
|
330
|
+
annotations: {
|
|
331
|
+
readOnlyHint: true,
|
|
332
|
+
destructiveHint: false,
|
|
333
|
+
idempotentHint: true,
|
|
334
|
+
openWorldHint: true,
|
|
335
|
+
},
|
|
336
|
+
}, async (_args, ctx) => safely(() => client.getBalance({ signal: ctx.mcpReq.signal })));
|
|
337
|
+
server.registerTool("spicyapi_task_get", {
|
|
338
|
+
title: "Get a SpicyAPI task",
|
|
339
|
+
description: "Read a task created by the current API key. Unknown and inaccessible IDs are both 404.",
|
|
340
|
+
inputSchema: z.object({ taskId: z.string().min(1) }),
|
|
341
|
+
outputSchema: resultOf(taskRecordSchema),
|
|
342
|
+
annotations: {
|
|
343
|
+
readOnlyHint: true,
|
|
344
|
+
destructiveHint: false,
|
|
345
|
+
idempotentHint: true,
|
|
346
|
+
openWorldHint: true,
|
|
347
|
+
},
|
|
348
|
+
}, async ({ taskId }, ctx) => safely(() => client.getTask(taskId, { signal: ctx.mcpReq.signal })));
|
|
349
|
+
server.registerTool("spicyapi_task_wait", {
|
|
350
|
+
title: "Wait briefly for a SpicyAPI task",
|
|
351
|
+
description: "Poll a task to a terminal state for up to 300 seconds. Prefer signed webhooks for production.",
|
|
352
|
+
inputSchema: z.object({
|
|
353
|
+
taskId: z.string().min(1),
|
|
354
|
+
intervalSeconds: z.number().int().min(1).max(60).default(2),
|
|
355
|
+
timeoutSeconds: z.number().int().min(1).max(300).default(60),
|
|
356
|
+
}),
|
|
357
|
+
outputSchema: resultOf(taskRecordSchema),
|
|
358
|
+
annotations: {
|
|
359
|
+
readOnlyHint: true,
|
|
360
|
+
destructiveHint: false,
|
|
361
|
+
idempotentHint: true,
|
|
362
|
+
openWorldHint: true,
|
|
363
|
+
},
|
|
364
|
+
}, async ({ taskId, intervalSeconds, timeoutSeconds }, ctx) => safely(() => client.waitForTask(taskId, {
|
|
365
|
+
intervalMs: intervalSeconds * 1_000,
|
|
366
|
+
timeoutMs: timeoutSeconds * 1_000,
|
|
367
|
+
signal: ctx.mcpReq.signal,
|
|
368
|
+
})));
|
|
369
|
+
server.registerTool("spicyapi_upload_prepare", {
|
|
370
|
+
title: "Prepare a direct SpicyAPI upload",
|
|
371
|
+
description: "Create a short-lived presigned PUT ticket. Never attach the SpicyAPI key to the returned URL.",
|
|
372
|
+
inputSchema: z.object({
|
|
373
|
+
contentType: z.enum(["image/jpeg", "image/png", "image/webp", "image/gif"]),
|
|
374
|
+
bytes: z.number().int().positive(),
|
|
375
|
+
}),
|
|
376
|
+
outputSchema: resultOf(uploadTicketSchema),
|
|
377
|
+
annotations: {
|
|
378
|
+
readOnlyHint: false,
|
|
379
|
+
destructiveHint: false,
|
|
380
|
+
idempotentHint: false,
|
|
381
|
+
openWorldHint: true,
|
|
382
|
+
},
|
|
383
|
+
}, async ({ contentType, bytes }, ctx) => safely(() => client.createUploadUrl(contentType, bytes, { signal: ctx.mcpReq.signal })));
|
|
384
|
+
server.registerTool("spicyapi_upload_commit", {
|
|
385
|
+
title: "Commit a direct SpicyAPI upload",
|
|
386
|
+
description: "Verify a completed PUT and return its tenant-scoped spicy:// URI. Repeated success is idempotent.",
|
|
387
|
+
inputSchema: z.object({ fileId: z.string().min(1) }),
|
|
388
|
+
outputSchema: resultOf(uploadedFileSchema),
|
|
389
|
+
annotations: {
|
|
390
|
+
readOnlyHint: false,
|
|
391
|
+
destructiveHint: false,
|
|
392
|
+
idempotentHint: true,
|
|
393
|
+
openWorldHint: true,
|
|
394
|
+
},
|
|
395
|
+
}, async ({ fileId }, ctx) => safely(() => client.commitUploadedFile(fileId, { signal: ctx.mcpReq.signal })));
|
|
396
|
+
server.registerTool("spicyapi_download_url_create", {
|
|
397
|
+
title: "Create a SpicyAPI output download URL",
|
|
398
|
+
description: "Create a short-lived signed URL for an output owned by the current task and API key.",
|
|
399
|
+
inputSchema: z.object({ taskId: z.string().min(1), key: z.string().optional() }),
|
|
400
|
+
outputSchema: resultOf(downloadTicketSchema),
|
|
401
|
+
annotations: {
|
|
402
|
+
readOnlyHint: false,
|
|
403
|
+
destructiveHint: false,
|
|
404
|
+
idempotentHint: false,
|
|
405
|
+
openWorldHint: true,
|
|
406
|
+
},
|
|
407
|
+
}, async ({ taskId, key }, ctx) => safely(() => client.createDownloadUrl(taskId, key, { signal: ctx.mcpReq.signal })));
|
|
408
|
+
const createTaskSchema = z.object({
|
|
409
|
+
model: z.string().min(1),
|
|
410
|
+
input: z.record(z.string(), z.unknown()),
|
|
411
|
+
callBackUrl: z.string().optional(),
|
|
412
|
+
mature: z
|
|
413
|
+
.boolean()
|
|
414
|
+
.default(false)
|
|
415
|
+
.describe("Caller-declared execution metadata forwarded without account, API-key, model, channel, or platform content gating."),
|
|
416
|
+
idempotencyKey: z.string().min(1).optional(),
|
|
417
|
+
});
|
|
418
|
+
server.registerTool("spicyapi_task_create", {
|
|
419
|
+
title: "Create a billable SpicyAPI task",
|
|
420
|
+
description: "Reserve the estimate and create an asynchronous task. The mature field is transparent execution metadata, not a platform entitlement check. Requires a user confirmation round.",
|
|
421
|
+
inputSchema: createTaskSchema,
|
|
422
|
+
outputSchema: resultOf(confirmedCreateTaskResultSchema),
|
|
423
|
+
annotations: {
|
|
424
|
+
readOnlyHint: false,
|
|
425
|
+
destructiveHint: false,
|
|
426
|
+
idempotentHint: true,
|
|
427
|
+
openWorldHint: true,
|
|
428
|
+
},
|
|
429
|
+
}, async (args, ctx) => requireBillableConfirmation("create_task", args, ctx, `Create a billable task using ${args.model}?`, async (idempotencyKey) => ({
|
|
430
|
+
idempotencyKey,
|
|
431
|
+
...(await client.createTask({
|
|
432
|
+
model: args.model,
|
|
433
|
+
input: args.input,
|
|
434
|
+
...(args.callBackUrl === undefined ? {} : { callBackUrl: args.callBackUrl }),
|
|
435
|
+
mature: args.mature,
|
|
436
|
+
}, { idempotencyKey, signal: ctx.mcpReq.signal })),
|
|
437
|
+
})));
|
|
438
|
+
const retryTaskSchema = z.object({
|
|
439
|
+
taskId: z.string().min(1),
|
|
440
|
+
idempotencyKey: z.string().min(1).optional(),
|
|
441
|
+
});
|
|
442
|
+
server.registerTool("spicyapi_task_retry", {
|
|
443
|
+
title: "Retry a billable SpicyAPI task",
|
|
444
|
+
description: "Create a new task from a failed or expired source. Requires a user confirmation round.",
|
|
445
|
+
inputSchema: retryTaskSchema,
|
|
446
|
+
outputSchema: resultOf(confirmedRetryTaskResultSchema),
|
|
447
|
+
annotations: {
|
|
448
|
+
readOnlyHint: false,
|
|
449
|
+
destructiveHint: false,
|
|
450
|
+
idempotentHint: true,
|
|
451
|
+
openWorldHint: true,
|
|
452
|
+
},
|
|
453
|
+
}, async (args, ctx) => requireBillableConfirmation("retry_task", args, ctx, `Retry source task ${args.taskId} as a new billable task?`, async (idempotencyKey) => ({
|
|
454
|
+
idempotencyKey,
|
|
455
|
+
...(await client.retryTask(args.taskId, { idempotencyKey, signal: ctx.mcpReq.signal })),
|
|
456
|
+
})));
|
|
457
|
+
server.registerResource("spicyapi-documentation-index", "spicyapi://docs/index", {
|
|
458
|
+
title: "SpicyAPI documentation index",
|
|
459
|
+
description: "Verified first-party documentation topics and URLs.",
|
|
460
|
+
mimeType: "application/json",
|
|
461
|
+
cacheHint: { ttlMs: 300_000, cacheScope: "public" },
|
|
462
|
+
}, (uri) => ({
|
|
463
|
+
contents: [
|
|
464
|
+
{
|
|
465
|
+
uri: uri.href,
|
|
466
|
+
mimeType: "application/json",
|
|
467
|
+
text: JSON.stringify(DOCUMENTATION, null, 2),
|
|
468
|
+
},
|
|
469
|
+
],
|
|
470
|
+
}));
|
|
471
|
+
server.registerResource("spicyapi-openapi-contract", "spicyapi://contract/openapi", {
|
|
472
|
+
title: "SpicyAPI public OpenAPI contract",
|
|
473
|
+
description: "The package-pinned public API contract used to generate SDK types.",
|
|
474
|
+
mimeType: "application/yaml",
|
|
475
|
+
cacheHint: { ttlMs: 300_000, cacheScope: "public" },
|
|
476
|
+
}, async (uri) => ({
|
|
477
|
+
contents: [
|
|
478
|
+
{ uri: uri.href, mimeType: "application/yaml", text: await readOpenApiContract() },
|
|
479
|
+
],
|
|
480
|
+
}));
|
|
481
|
+
server.registerPrompt("spicyapi_generation_workflow", {
|
|
482
|
+
title: "Plan a safe SpicyAPI generation",
|
|
483
|
+
description: "Build a workflow that discovers the live schema before requesting a billable task.",
|
|
484
|
+
argsSchema: z.object({ goal: z.string().min(1), model: z.string().optional() }),
|
|
485
|
+
}, ({ goal, model }) => ({
|
|
486
|
+
messages: [
|
|
487
|
+
{
|
|
488
|
+
role: "user",
|
|
489
|
+
content: {
|
|
490
|
+
type: "text",
|
|
491
|
+
text: `Goal: ${goal}\n${model ? `Candidate model: ${model}\n` : ""}Use spicyapi_models_list or spicyapi_model_get to read the live input schema and account-specific price. Do not invent fields. Explain the expected hold and ask for confirmation before spicyapi_task_create. Prefer a verified webhook for long tasks; use polling only as a bounded fallback. Exchange output keys for short-lived download URLs and copy durable results to storage the user controls.`,
|
|
492
|
+
},
|
|
493
|
+
},
|
|
494
|
+
],
|
|
495
|
+
}));
|
|
496
|
+
return server;
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
export function createSpicyMcpServer(options = {}) {
|
|
500
|
+
return createSpicyMcpFactory(options)({ era: "modern" });
|
|
501
|
+
}
|
|
502
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { type StdioServerHandle } from "@modelcontextprotocol/server/stdio";
|
|
3
|
+
import { type SpicyMcpFactoryOptions } from "./server.js";
|
|
4
|
+
export declare function runStdioServer(options?: SpicyMcpFactoryOptions): StdioServerHandle;
|
|
5
|
+
//# sourceMappingURL=stdio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../../src/mcp/stdio.ts"],"names":[],"mappings":";AAEA,OAAO,EAAc,KAAK,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAGxF,OAAO,EAAyB,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAEjF,wBAAgB,cAAc,CAAC,OAAO,GAAE,sBAA2B,GAAG,iBAAiB,CAKtF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
3
|
+
import { isMainModule } from "../runtime/entrypoint.js";
|
|
4
|
+
import { createSpicyMcpFactory } from "./server.js";
|
|
5
|
+
export function runStdioServer(options = {}) {
|
|
6
|
+
return serveStdio(createSpicyMcpFactory(options), {
|
|
7
|
+
legacy: "serve",
|
|
8
|
+
maxSubscriptions: 128,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
if (isMainModule(import.meta.url)) {
|
|
12
|
+
const handle = runStdioServer({ onError: (error) => console.error(error.message) });
|
|
13
|
+
const close = () => {
|
|
14
|
+
void handle.close().catch((error) => {
|
|
15
|
+
console.error(error instanceof Error ? error.message : "failed to close MCP stdio server");
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
process.once("SIGINT", close);
|
|
19
|
+
process.once("SIGTERM", close);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=stdio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../../src/mcp/stdio.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAA0B,MAAM,oCAAoC,CAAC;AAExF,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAA+B,MAAM,aAAa,CAAC;AAEjF,MAAM,UAAU,cAAc,CAAC,UAAkC,EAAE;IACjE,OAAO,UAAU,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE;QAChD,MAAM,EAAE,OAAO;QACf,gBAAgB,EAAE,GAAG;KACtB,CAAC,CAAC;AACL,CAAC;AAED,IAAI,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACpF,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YAC3C,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC;QAC7F,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC9B,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entrypoint.d.ts","sourceRoot":"","sources":["../../../src/runtime/entrypoint.ts"],"names":[],"mappings":"AAIA,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAQrD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { realpathSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
export function isMainModule(metaUrl) {
|
|
5
|
+
const entry = process.argv[1];
|
|
6
|
+
if (!entry)
|
|
7
|
+
return false;
|
|
8
|
+
try {
|
|
9
|
+
return realpathSync(entry) === realpathSync(fileURLToPath(metaUrl));
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return path.resolve(entry) === path.resolve(fileURLToPath(metaUrl));
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=entrypoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entrypoint.js","sourceRoot":"","sources":["../../../src/runtime/entrypoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,CAAC,KAAK,YAAY,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;IACtE,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@spicyapi/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Official local MCP server for the SpicyAPI public API",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/SpicyAPI/spicy-devkit.git",
|
|
10
|
+
"directory": "packages/mcp"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://spicyapi.ai",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://spicyapi.ai/contact"
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=22.13.0"
|
|
21
|
+
},
|
|
22
|
+
"main": "./dist/src/mcp/server.js",
|
|
23
|
+
"types": "./dist/src/mcp/server.d.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/src/mcp/server.d.ts",
|
|
27
|
+
"import": "./dist/src/mcp/server.js"
|
|
28
|
+
},
|
|
29
|
+
"./stdio": {
|
|
30
|
+
"types": "./dist/src/mcp/stdio.d.ts",
|
|
31
|
+
"import": "./dist/src/mcp/stdio.js"
|
|
32
|
+
},
|
|
33
|
+
"./http": {
|
|
34
|
+
"types": "./dist/src/mcp/http.d.ts",
|
|
35
|
+
"import": "./dist/src/mcp/http.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"bin": {
|
|
39
|
+
"spicyapi-mcp": "dist/src/mcp/stdio.js",
|
|
40
|
+
"spicyapi-mcp-http": "dist/src/mcp/http.js"
|
|
41
|
+
},
|
|
42
|
+
"files": [
|
|
43
|
+
"dist/src",
|
|
44
|
+
"README.md",
|
|
45
|
+
"SECURITY.md",
|
|
46
|
+
"LICENSE"
|
|
47
|
+
],
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc -p tsconfig.json",
|
|
50
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@modelcontextprotocol/node": "2.0.0",
|
|
54
|
+
"@modelcontextprotocol/server": "2.0.0",
|
|
55
|
+
"@spicyapi/sdk": "^0.1.0",
|
|
56
|
+
"zod": "4.5.4"
|
|
57
|
+
}
|
|
58
|
+
}
|