@drumcode/runner 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/README.md +139 -0
- package/dist/chunk-3CUTJWRW.mjs +358 -0
- package/dist/chunk-4ITFFQXW.mjs +716 -0
- package/dist/chunk-5NEEOHT4.mjs +632 -0
- package/dist/chunk-6BC7SCK5.mjs +720 -0
- package/dist/chunk-E3F3IKO5.mjs +359 -0
- package/dist/chunk-JN5YMFB7.mjs +1061 -0
- package/dist/chunk-T7I5AI3A.mjs +558 -0
- package/dist/chunk-VDJVZU3Q.mjs +908 -0
- package/dist/chunk-VYYR5EI4.mjs +1061 -0
- package/dist/chunk-ZOZS5KN7.mjs +713 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1432 -0
- package/dist/cli.mjs +360 -0
- package/dist/index.d.mts +192 -0
- package/dist/index.d.ts +192 -0
- package/dist/index.js +1085 -0
- package/dist/index.mjs +8 -0
- package/package.json +56 -0
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
DrumcodeRunner,
|
|
4
|
+
createServer
|
|
5
|
+
} from "./chunk-VYYR5EI4.mjs";
|
|
6
|
+
|
|
7
|
+
// src/cli.ts
|
|
8
|
+
import { Command } from "commander";
|
|
9
|
+
import { config } from "dotenv";
|
|
10
|
+
|
|
11
|
+
// src/sse-server.ts
|
|
12
|
+
import express from "express";
|
|
13
|
+
import cors from "cors";
|
|
14
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
15
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
16
|
+
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
17
|
+
import {
|
|
18
|
+
CallToolRequestSchema,
|
|
19
|
+
ListToolsRequestSchema
|
|
20
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
21
|
+
var demoTools = [
|
|
22
|
+
{
|
|
23
|
+
name: "drumcode_echo",
|
|
24
|
+
description: "Echo back the input arguments. Useful for testing.",
|
|
25
|
+
input_schema: {
|
|
26
|
+
type: "object",
|
|
27
|
+
properties: {
|
|
28
|
+
message: {
|
|
29
|
+
type: "string",
|
|
30
|
+
description: "The message to echo back"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
required: ["message"]
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "drumcode_http_get",
|
|
38
|
+
description: "Make an HTTP GET request to a URL and return the response.",
|
|
39
|
+
input_schema: {
|
|
40
|
+
type: "object",
|
|
41
|
+
properties: {
|
|
42
|
+
url: {
|
|
43
|
+
type: "string",
|
|
44
|
+
description: "The URL to fetch"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
required: ["url"]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
];
|
|
51
|
+
var arxivTools = [
|
|
52
|
+
{
|
|
53
|
+
name: "arxiv_search_papers",
|
|
54
|
+
description: "Search for academic papers on arXiv. Returns papers matching the query with optional filters.",
|
|
55
|
+
input_schema: {
|
|
56
|
+
type: "object",
|
|
57
|
+
properties: {
|
|
58
|
+
query: {
|
|
59
|
+
type: "string",
|
|
60
|
+
description: 'Search query keywords (e.g., "machine learning", "quantum computing")'
|
|
61
|
+
},
|
|
62
|
+
max_results: {
|
|
63
|
+
type: "number",
|
|
64
|
+
description: "Maximum number of results to return (1-20)"
|
|
65
|
+
},
|
|
66
|
+
categories: {
|
|
67
|
+
type: "string",
|
|
68
|
+
description: 'Comma-separated arXiv categories to filter by (e.g., "cs.AI,cs.LG")'
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
required: ["query"]
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "arxiv_get_paper",
|
|
76
|
+
description: "Get detailed metadata and abstract for a specific paper by its arXiv ID.",
|
|
77
|
+
input_schema: {
|
|
78
|
+
type: "object",
|
|
79
|
+
properties: {
|
|
80
|
+
paper_id: {
|
|
81
|
+
type: "string",
|
|
82
|
+
description: 'The arXiv paper ID (e.g., "2301.07041" or "1706.03762")'
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
required: ["paper_id"]
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "arxiv_search_by_author",
|
|
90
|
+
description: "Search for papers by a specific author on arXiv.",
|
|
91
|
+
input_schema: {
|
|
92
|
+
type: "object",
|
|
93
|
+
properties: {
|
|
94
|
+
author: {
|
|
95
|
+
type: "string",
|
|
96
|
+
description: "Author name to search for"
|
|
97
|
+
},
|
|
98
|
+
max_results: {
|
|
99
|
+
type: "number",
|
|
100
|
+
description: "Maximum number of results (1-20)"
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
required: ["author"]
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: "arxiv_search_by_category",
|
|
108
|
+
description: "Search for recent papers in a specific arXiv category.",
|
|
109
|
+
input_schema: {
|
|
110
|
+
type: "object",
|
|
111
|
+
properties: {
|
|
112
|
+
category: {
|
|
113
|
+
type: "string",
|
|
114
|
+
description: 'arXiv category (e.g., "cs.AI", "math.CO", "physics.hep-th")'
|
|
115
|
+
},
|
|
116
|
+
max_results: {
|
|
117
|
+
type: "number",
|
|
118
|
+
description: "Maximum number of results (1-20)"
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
required: ["category"]
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
];
|
|
125
|
+
async function createSSEServer(options) {
|
|
126
|
+
const runner = new DrumcodeRunner(options);
|
|
127
|
+
const authContext = await runner.initializeAuth();
|
|
128
|
+
if (authContext.isAuthenticated) {
|
|
129
|
+
console.error(`[drumcode] Authenticated as: ${authContext.tokenName || "unnamed token"}`);
|
|
130
|
+
console.error(`[drumcode] Project ID: ${authContext.projectId}`);
|
|
131
|
+
if (authContext.profileId) {
|
|
132
|
+
console.error(`[drumcode] Permission profile: ${authContext.profileId}`);
|
|
133
|
+
}
|
|
134
|
+
} else if (options.token) {
|
|
135
|
+
console.error("[drumcode] Warning: Token provided but authentication failed");
|
|
136
|
+
}
|
|
137
|
+
const app = express();
|
|
138
|
+
app.use(cors({
|
|
139
|
+
origin: "*",
|
|
140
|
+
methods: ["GET", "POST", "OPTIONS"],
|
|
141
|
+
allowedHeaders: ["Content-Type", "Authorization", "Mcp-Session-Id"],
|
|
142
|
+
exposedHeaders: ["Mcp-Session-Id"]
|
|
143
|
+
}));
|
|
144
|
+
app.use(express.json());
|
|
145
|
+
app.get("/health", (_req, res) => {
|
|
146
|
+
res.json({
|
|
147
|
+
status: "ok",
|
|
148
|
+
version: "0.1.0",
|
|
149
|
+
transport: "sse",
|
|
150
|
+
authenticated: authContext.isAuthenticated
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
const legacyTransports = /* @__PURE__ */ new Map();
|
|
154
|
+
const createMCPServer = () => {
|
|
155
|
+
const server2 = new Server(
|
|
156
|
+
{
|
|
157
|
+
name: "drumcode",
|
|
158
|
+
version: "0.1.0"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
capabilities: {
|
|
162
|
+
tools: {}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
);
|
|
166
|
+
server2.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
167
|
+
const capabilities = {
|
|
168
|
+
type: options.clientMode === "full" ? "anthropic" : "unknown",
|
|
169
|
+
supportsAdvancedToolUse: options.clientMode === "full",
|
|
170
|
+
supportsDeferredLoading: options.clientMode === "full"
|
|
171
|
+
};
|
|
172
|
+
const tools = await runner.getToolList(capabilities);
|
|
173
|
+
const toolMap = /* @__PURE__ */ new Map();
|
|
174
|
+
for (const t of [...demoTools, ...arxivTools]) {
|
|
175
|
+
toolMap.set(t.name, t);
|
|
176
|
+
}
|
|
177
|
+
for (const t of tools) {
|
|
178
|
+
toolMap.set(t.name, t);
|
|
179
|
+
}
|
|
180
|
+
const allTools = Array.from(toolMap.values()).map((t) => ({
|
|
181
|
+
name: t.name,
|
|
182
|
+
description: t.description,
|
|
183
|
+
inputSchema: {
|
|
184
|
+
type: "object",
|
|
185
|
+
properties: t.input_schema.properties,
|
|
186
|
+
required: t.input_schema.required
|
|
187
|
+
}
|
|
188
|
+
}));
|
|
189
|
+
return { tools: allTools };
|
|
190
|
+
});
|
|
191
|
+
server2.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
192
|
+
const { name, arguments: args } = request.params;
|
|
193
|
+
const result = await runner.executeTool({
|
|
194
|
+
name,
|
|
195
|
+
arguments: args ?? {}
|
|
196
|
+
});
|
|
197
|
+
return {
|
|
198
|
+
content: result.content,
|
|
199
|
+
isError: result.isError
|
|
200
|
+
};
|
|
201
|
+
});
|
|
202
|
+
return server2;
|
|
203
|
+
};
|
|
204
|
+
app.get("/sse", async (req, res) => {
|
|
205
|
+
console.error("[drumcode] Legacy SSE connection requested");
|
|
206
|
+
const transport = new SSEServerTransport("/messages", res);
|
|
207
|
+
const server2 = createMCPServer();
|
|
208
|
+
await server2.connect(transport);
|
|
209
|
+
const sessionId = transport.sessionId;
|
|
210
|
+
legacyTransports.set(sessionId, transport);
|
|
211
|
+
console.error(`[drumcode] Legacy SSE session started: ${sessionId}`);
|
|
212
|
+
res.on("close", () => {
|
|
213
|
+
legacyTransports.delete(sessionId);
|
|
214
|
+
console.error(`[drumcode] Legacy SSE session closed: ${sessionId}`);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
app.post("/messages", async (req, res) => {
|
|
218
|
+
const sessionId = req.query.sessionId;
|
|
219
|
+
if (!sessionId) {
|
|
220
|
+
res.status(400).json({ error: "Missing sessionId query parameter" });
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const transport = legacyTransports.get(sessionId);
|
|
224
|
+
if (!transport) {
|
|
225
|
+
res.status(404).json({ error: "Session not found. Connect to /sse first." });
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
await transport.handlePostMessage(req, res, req.body);
|
|
229
|
+
});
|
|
230
|
+
app.all("/mcp", async (req, res) => {
|
|
231
|
+
const authHeader = req.headers.authorization;
|
|
232
|
+
if (options.token && authHeader) {
|
|
233
|
+
const providedToken = authHeader.replace("Bearer ", "");
|
|
234
|
+
if (providedToken !== options.token) {
|
|
235
|
+
console.error("[drumcode] Invalid token in Authorization header");
|
|
236
|
+
res.status(401).json({ error: "Invalid token" });
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
const transport = new StreamableHTTPServerTransport({
|
|
241
|
+
sessionIdGenerator: void 0
|
|
242
|
+
// Stateless mode - no session tracking
|
|
243
|
+
});
|
|
244
|
+
const server2 = createMCPServer();
|
|
245
|
+
await server2.connect(transport);
|
|
246
|
+
await transport.handleRequest(req, res, req.body);
|
|
247
|
+
});
|
|
248
|
+
const server = app.listen(options.port, options.host, () => {
|
|
249
|
+
console.error(`[drumcode] SSE MCP Server started`);
|
|
250
|
+
console.error(`[drumcode] Listening on http://${options.host}:${options.port}`);
|
|
251
|
+
console.error(`[drumcode] MCP endpoint: http://${options.host}:${options.port}/mcp`);
|
|
252
|
+
console.error(`[drumcode] Health check: http://${options.host}:${options.port}/health`);
|
|
253
|
+
});
|
|
254
|
+
const shutdown = () => {
|
|
255
|
+
console.error("[drumcode] Shutting down...");
|
|
256
|
+
server.close(() => {
|
|
257
|
+
console.error("[drumcode] Server closed");
|
|
258
|
+
process.exit(0);
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
process.on("SIGTERM", shutdown);
|
|
262
|
+
process.on("SIGINT", shutdown);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// src/types.ts
|
|
266
|
+
import { z } from "zod";
|
|
267
|
+
var runnerOptionsSchema = z.object({
|
|
268
|
+
token: z.string().optional(),
|
|
269
|
+
project: z.string().optional(),
|
|
270
|
+
registryUrl: z.string().url().default("https://api.drumcode.ai"),
|
|
271
|
+
cacheEnabled: z.boolean().default(true),
|
|
272
|
+
logLevel: z.enum(["debug", "info", "warn", "error"]).default("info"),
|
|
273
|
+
transport: z.enum(["stdio", "sse"]).default("stdio"),
|
|
274
|
+
/**
|
|
275
|
+
* Client mode affects how tools are exposed:
|
|
276
|
+
* - 'polyfill': Only expose core meta-tools (search + get_schema) - default for generic clients
|
|
277
|
+
* - 'full': Expose full manifest from registry - for clients that support large tool lists
|
|
278
|
+
*/
|
|
279
|
+
clientMode: z.enum(["polyfill", "full"]).default("polyfill"),
|
|
280
|
+
/**
|
|
281
|
+
* Port for SSE server (only used when transport is 'sse')
|
|
282
|
+
*/
|
|
283
|
+
port: z.number().default(3001),
|
|
284
|
+
/**
|
|
285
|
+
* Host for SSE server (only used when transport is 'sse')
|
|
286
|
+
*/
|
|
287
|
+
host: z.string().default("0.0.0.0"),
|
|
288
|
+
/**
|
|
289
|
+
* Integration base URLs for registry tools (keyed by integration name)
|
|
290
|
+
*/
|
|
291
|
+
integrationBaseUrls: z.record(z.string()).optional(),
|
|
292
|
+
/**
|
|
293
|
+
* Integration headers for registry tools (keyed by integration name)
|
|
294
|
+
*/
|
|
295
|
+
integrationHeaders: z.record(z.record(z.string())).optional()
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// src/cli.ts
|
|
299
|
+
config();
|
|
300
|
+
function parseJsonEnv(value, name) {
|
|
301
|
+
if (!value) return void 0;
|
|
302
|
+
try {
|
|
303
|
+
return JSON.parse(value);
|
|
304
|
+
} catch {
|
|
305
|
+
throw new Error(`Invalid JSON in ${name}`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
var program = new Command();
|
|
309
|
+
program.name("drumcode").description("Drumcode MCP Runner - AI-Ready SaaS Infrastructure").version("0.1.0");
|
|
310
|
+
program.command("start").description("Start the Drumcode MCP server").option("-t, --token <token>", "Drumcode API token").option("-p, --project <project>", "Project name").option("-r, --registry <url>", "Registry URL", "https://drumcode-studio.vercel.app/api").option("--no-cache", "Disable caching").option("-l, --log-level <level>", "Log level (debug, info, warn, error)", "info").option("--transport <type>", "Transport type (stdio, sse)", "stdio").option("--port <port>", "Port for SSE server (default: 3001)", "3001").option("--host <host>", "Host for SSE server (default: 0.0.0.0)", "0.0.0.0").option("-m, --mode <mode>", "Client mode: polyfill (meta-tools only) or full (all tools from registry)", "polyfill").action(async (opts) => {
|
|
311
|
+
try {
|
|
312
|
+
const integrationBaseUrls = parseJsonEnv(
|
|
313
|
+
process.env.DRUMCODE_INTEGRATION_BASE_URLS,
|
|
314
|
+
"DRUMCODE_INTEGRATION_BASE_URLS"
|
|
315
|
+
);
|
|
316
|
+
const integrationHeaders = parseJsonEnv(
|
|
317
|
+
process.env.DRUMCODE_INTEGRATION_HEADERS,
|
|
318
|
+
"DRUMCODE_INTEGRATION_HEADERS"
|
|
319
|
+
);
|
|
320
|
+
const options = runnerOptionsSchema.parse({
|
|
321
|
+
token: opts.token || process.env.DRUMCODE_TOKEN,
|
|
322
|
+
project: opts.project || process.env.DRUMCODE_PROJECT,
|
|
323
|
+
registryUrl: opts.registry || process.env.DRUMCODE_REGISTRY_URL,
|
|
324
|
+
cacheEnabled: opts.cache !== false,
|
|
325
|
+
logLevel: opts.logLevel,
|
|
326
|
+
transport: opts.transport,
|
|
327
|
+
port: parseInt(opts.port, 10),
|
|
328
|
+
host: opts.host,
|
|
329
|
+
clientMode: opts.mode || process.env.DRUMCODE_CLIENT_MODE || "polyfill",
|
|
330
|
+
integrationBaseUrls,
|
|
331
|
+
integrationHeaders
|
|
332
|
+
});
|
|
333
|
+
console.error("[drumcode] Starting MCP server...");
|
|
334
|
+
console.error("[drumcode] Registry:", options.registryUrl);
|
|
335
|
+
console.error("[drumcode] Log level:", options.logLevel);
|
|
336
|
+
console.error("[drumcode] Transport:", options.transport);
|
|
337
|
+
console.error("[drumcode] Client mode:", options.clientMode);
|
|
338
|
+
if (!options.token) {
|
|
339
|
+
console.error("[drumcode] Warning: No token provided. Running in demo mode.");
|
|
340
|
+
console.error("[drumcode] Set DRUMCODE_TOKEN or use --token to connect to Registry.");
|
|
341
|
+
}
|
|
342
|
+
if (options.clientMode === "full") {
|
|
343
|
+
console.error("[drumcode] Full manifest mode: All tools from registry will be exposed");
|
|
344
|
+
} else {
|
|
345
|
+
console.error("[drumcode] Polyfill mode: Only meta-tools + hardcoded tools will be exposed");
|
|
346
|
+
}
|
|
347
|
+
if (options.transport === "sse") {
|
|
348
|
+
await createSSEServer(options);
|
|
349
|
+
} else {
|
|
350
|
+
await createServer(options);
|
|
351
|
+
}
|
|
352
|
+
} catch (error) {
|
|
353
|
+
console.error("[drumcode] Failed to start:", error);
|
|
354
|
+
process.exit(1);
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
program.command("version").description("Show version information").action(() => {
|
|
358
|
+
console.log("Drumcode Runner v0.1.0");
|
|
359
|
+
});
|
|
360
|
+
program.parse();
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { Tool } from '@drumcode/core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
declare const runnerOptionsSchema: z.ZodObject<{
|
|
5
|
+
token: z.ZodOptional<z.ZodString>;
|
|
6
|
+
project: z.ZodOptional<z.ZodString>;
|
|
7
|
+
registryUrl: z.ZodDefault<z.ZodString>;
|
|
8
|
+
cacheEnabled: z.ZodDefault<z.ZodBoolean>;
|
|
9
|
+
logLevel: z.ZodDefault<z.ZodEnum<["debug", "info", "warn", "error"]>>;
|
|
10
|
+
transport: z.ZodDefault<z.ZodEnum<["stdio", "sse"]>>;
|
|
11
|
+
/**
|
|
12
|
+
* Client mode affects how tools are exposed:
|
|
13
|
+
* - 'polyfill': Only expose core meta-tools (search + get_schema) - default for generic clients
|
|
14
|
+
* - 'full': Expose full manifest from registry - for clients that support large tool lists
|
|
15
|
+
*/
|
|
16
|
+
clientMode: z.ZodDefault<z.ZodEnum<["polyfill", "full"]>>;
|
|
17
|
+
/**
|
|
18
|
+
* Port for SSE server (only used when transport is 'sse')
|
|
19
|
+
*/
|
|
20
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
21
|
+
/**
|
|
22
|
+
* Host for SSE server (only used when transport is 'sse')
|
|
23
|
+
*/
|
|
24
|
+
host: z.ZodDefault<z.ZodString>;
|
|
25
|
+
/**
|
|
26
|
+
* Integration base URLs for registry tools (keyed by integration name)
|
|
27
|
+
*/
|
|
28
|
+
integrationBaseUrls: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
29
|
+
/**
|
|
30
|
+
* Integration headers for registry tools (keyed by integration name)
|
|
31
|
+
*/
|
|
32
|
+
integrationHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>>;
|
|
33
|
+
}, "strip", z.ZodTypeAny, {
|
|
34
|
+
registryUrl: string;
|
|
35
|
+
cacheEnabled: boolean;
|
|
36
|
+
logLevel: "info" | "debug" | "warn" | "error";
|
|
37
|
+
transport: "stdio" | "sse";
|
|
38
|
+
clientMode: "polyfill" | "full";
|
|
39
|
+
port: number;
|
|
40
|
+
host: string;
|
|
41
|
+
token?: string | undefined;
|
|
42
|
+
project?: string | undefined;
|
|
43
|
+
integrationBaseUrls?: Record<string, string> | undefined;
|
|
44
|
+
integrationHeaders?: Record<string, Record<string, string>> | undefined;
|
|
45
|
+
}, {
|
|
46
|
+
token?: string | undefined;
|
|
47
|
+
project?: string | undefined;
|
|
48
|
+
registryUrl?: string | undefined;
|
|
49
|
+
cacheEnabled?: boolean | undefined;
|
|
50
|
+
logLevel?: "info" | "debug" | "warn" | "error" | undefined;
|
|
51
|
+
transport?: "stdio" | "sse" | undefined;
|
|
52
|
+
clientMode?: "polyfill" | "full" | undefined;
|
|
53
|
+
port?: number | undefined;
|
|
54
|
+
host?: string | undefined;
|
|
55
|
+
integrationBaseUrls?: Record<string, string> | undefined;
|
|
56
|
+
integrationHeaders?: Record<string, Record<string, string>> | undefined;
|
|
57
|
+
}>;
|
|
58
|
+
type RunnerOptions = z.infer<typeof runnerOptionsSchema>;
|
|
59
|
+
interface ToolCallRequest {
|
|
60
|
+
name: string;
|
|
61
|
+
arguments: Record<string, unknown>;
|
|
62
|
+
}
|
|
63
|
+
interface ToolCallResult {
|
|
64
|
+
content: Array<{
|
|
65
|
+
type: 'text' | 'image' | 'resource';
|
|
66
|
+
text?: string;
|
|
67
|
+
data?: string;
|
|
68
|
+
mimeType?: string;
|
|
69
|
+
}>;
|
|
70
|
+
isError?: boolean;
|
|
71
|
+
}
|
|
72
|
+
interface TokenValidationResponse {
|
|
73
|
+
valid: boolean;
|
|
74
|
+
project?: {
|
|
75
|
+
id: string;
|
|
76
|
+
};
|
|
77
|
+
token?: {
|
|
78
|
+
id: string;
|
|
79
|
+
name: string | null;
|
|
80
|
+
profileId: string | null;
|
|
81
|
+
};
|
|
82
|
+
error?: {
|
|
83
|
+
code: string;
|
|
84
|
+
message: string;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
interface AuthenticatedContext {
|
|
88
|
+
isAuthenticated: boolean;
|
|
89
|
+
projectId: string | null;
|
|
90
|
+
tokenId: string | null;
|
|
91
|
+
tokenName: string | null;
|
|
92
|
+
profileId: string | null;
|
|
93
|
+
}
|
|
94
|
+
type ClientType = 'anthropic' | 'openai' | 'cursor' | 'langchain' | 'unknown';
|
|
95
|
+
interface ClientCapabilities {
|
|
96
|
+
type: ClientType;
|
|
97
|
+
supportsAdvancedToolUse: boolean;
|
|
98
|
+
supportsDeferredLoading: boolean;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
declare class DrumcodeRunner {
|
|
102
|
+
private options;
|
|
103
|
+
private toolCache;
|
|
104
|
+
private skillCache;
|
|
105
|
+
private manifestCache;
|
|
106
|
+
private authContext;
|
|
107
|
+
private authInitialized;
|
|
108
|
+
constructor(options: RunnerOptions);
|
|
109
|
+
/**
|
|
110
|
+
* Initialize authentication by validating the token with the registry
|
|
111
|
+
* This should be called before processing any requests
|
|
112
|
+
*/
|
|
113
|
+
initializeAuth(): Promise<AuthenticatedContext>;
|
|
114
|
+
/**
|
|
115
|
+
* Get the current authentication context
|
|
116
|
+
*/
|
|
117
|
+
getAuthContext(): AuthenticatedContext;
|
|
118
|
+
/**
|
|
119
|
+
* Check if the runner is authenticated
|
|
120
|
+
*/
|
|
121
|
+
isAuthenticated(): boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Get the list of tools to expose to the client
|
|
124
|
+
* Uses Polyfill strategy for non-Anthropic clients
|
|
125
|
+
*/
|
|
126
|
+
getToolList(capabilities: ClientCapabilities): Promise<Tool[]>;
|
|
127
|
+
/**
|
|
128
|
+
* Fetch the full tool manifest from the Registry
|
|
129
|
+
*/
|
|
130
|
+
private getFullManifest;
|
|
131
|
+
/**
|
|
132
|
+
* Execute a tool call
|
|
133
|
+
*/
|
|
134
|
+
executeTool(request: ToolCallRequest): Promise<ToolCallResult>;
|
|
135
|
+
/**
|
|
136
|
+
* Handle drumcode_search_tools meta-tool
|
|
137
|
+
*/
|
|
138
|
+
private handleSearchTools;
|
|
139
|
+
/**
|
|
140
|
+
* Handle drumcode_get_tool_schema meta-tool
|
|
141
|
+
*/
|
|
142
|
+
private handleGetToolSchema;
|
|
143
|
+
private fetchRegistryToolSchema;
|
|
144
|
+
/**
|
|
145
|
+
* Execute a regular (non-meta) tool
|
|
146
|
+
*/
|
|
147
|
+
private executeRegularTool;
|
|
148
|
+
private executeRegistryTool;
|
|
149
|
+
/**
|
|
150
|
+
* Fetch skill definition from registry
|
|
151
|
+
*/
|
|
152
|
+
private fetchSkill;
|
|
153
|
+
/**
|
|
154
|
+
* Execute a skill (validator or workflow)
|
|
155
|
+
*/
|
|
156
|
+
private executeSkill;
|
|
157
|
+
/**
|
|
158
|
+
* Evaluate a policy rule against context
|
|
159
|
+
* Simple expression evaluator for rules like "input.query && input.query.length >= 2"
|
|
160
|
+
*/
|
|
161
|
+
private evaluateRule;
|
|
162
|
+
/**
|
|
163
|
+
* Evaluate an argument mapping expression
|
|
164
|
+
* Supports expressions like "input.query", "input.max_results || 5", "steps.search_results.papers[0].id"
|
|
165
|
+
*/
|
|
166
|
+
private evaluateMapping;
|
|
167
|
+
/**
|
|
168
|
+
* Parse tool result content to extract structured data
|
|
169
|
+
*/
|
|
170
|
+
private parseToolResult;
|
|
171
|
+
/**
|
|
172
|
+
* Execute arXiv tools via the arXiv API
|
|
173
|
+
*/
|
|
174
|
+
private executeArxivTool;
|
|
175
|
+
/**
|
|
176
|
+
* Parse arXiv Atom XML response
|
|
177
|
+
*/
|
|
178
|
+
private parseArxivResponse;
|
|
179
|
+
private getIntegrationBaseUrl;
|
|
180
|
+
private getIntegrationHeaders;
|
|
181
|
+
private buildToolRequest;
|
|
182
|
+
private getAuthHeaders;
|
|
183
|
+
private formatToolSchema;
|
|
184
|
+
private log;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Create and configure the MCP server
|
|
189
|
+
*/
|
|
190
|
+
declare function createServer(options: RunnerOptions): Promise<void>;
|
|
191
|
+
|
|
192
|
+
export { type AuthenticatedContext, DrumcodeRunner, type RunnerOptions, type TokenValidationResponse, createServer };
|