@cencori/mcp 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +180 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +955 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +954 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +64 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,955 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// src/index.ts
|
|
5
|
+
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
6
|
+
|
|
7
|
+
// src/config.ts
|
|
8
|
+
var DEFAULT_BASE_URL = "https://cencori.com";
|
|
9
|
+
var KNOWN_FEATURES = [
|
|
10
|
+
"docs",
|
|
11
|
+
"gateway",
|
|
12
|
+
"agents",
|
|
13
|
+
"memory",
|
|
14
|
+
"sessions",
|
|
15
|
+
"multimodal",
|
|
16
|
+
"governance",
|
|
17
|
+
"guidance"
|
|
18
|
+
];
|
|
19
|
+
function normalizeBaseUrl(value) {
|
|
20
|
+
return value.replace(/\/$/, "");
|
|
21
|
+
}
|
|
22
|
+
function parseBooleanEnv(value, defaultValue) {
|
|
23
|
+
if (value === void 0) {
|
|
24
|
+
return defaultValue;
|
|
25
|
+
}
|
|
26
|
+
return !["0", "false", "no", "off"].includes(value.trim().toLowerCase());
|
|
27
|
+
}
|
|
28
|
+
function isMcpFeature(value) {
|
|
29
|
+
return KNOWN_FEATURES.includes(value);
|
|
30
|
+
}
|
|
31
|
+
function allFeaturesEnabled() {
|
|
32
|
+
return {
|
|
33
|
+
docs: true,
|
|
34
|
+
gateway: true,
|
|
35
|
+
agents: true,
|
|
36
|
+
memory: true,
|
|
37
|
+
sessions: true,
|
|
38
|
+
multimodal: true,
|
|
39
|
+
governance: true,
|
|
40
|
+
guidance: true
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function parseFeatures(value) {
|
|
44
|
+
if (!value || value.trim() === "") {
|
|
45
|
+
return allFeaturesEnabled();
|
|
46
|
+
}
|
|
47
|
+
const tokens = value.split(",").map((feature) => feature.trim().toLowerCase()).filter(Boolean);
|
|
48
|
+
const unrecognized = tokens.filter((token) => !isMcpFeature(token));
|
|
49
|
+
if (unrecognized.length > 0) {
|
|
50
|
+
console.error(
|
|
51
|
+
`[cencori-mcp] Ignoring unrecognized CENCORI_MCP_FEATURES value(s): ${unrecognized.join(", ")}. Known features: ${KNOWN_FEATURES.join(", ")}.`
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
const enabled = new Set(tokens.filter(isMcpFeature));
|
|
55
|
+
return {
|
|
56
|
+
docs: enabled.has("docs"),
|
|
57
|
+
gateway: enabled.has("gateway"),
|
|
58
|
+
agents: enabled.has("agents"),
|
|
59
|
+
memory: enabled.has("memory"),
|
|
60
|
+
sessions: enabled.has("sessions"),
|
|
61
|
+
multimodal: enabled.has("multimodal"),
|
|
62
|
+
governance: enabled.has("governance"),
|
|
63
|
+
guidance: enabled.has("guidance")
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function loadConfig() {
|
|
67
|
+
const docsBaseUrl = normalizeBaseUrl(process.env.CENCORI_DOCS_BASE_URL ?? DEFAULT_BASE_URL);
|
|
68
|
+
const baseUrl = normalizeBaseUrl(process.env.CENCORI_BASE_URL ?? DEFAULT_BASE_URL);
|
|
69
|
+
const apiKey = process.env.CENCORI_API_KEY?.trim() || void 0;
|
|
70
|
+
const features = parseFeatures(process.env.CENCORI_MCP_FEATURES);
|
|
71
|
+
const destructive = parseBooleanEnv(process.env.CENCORI_MCP_DESTRUCTIVE, false);
|
|
72
|
+
const write = destructive || parseBooleanEnv(process.env.CENCORI_MCP_WRITE, false);
|
|
73
|
+
return {
|
|
74
|
+
docsBaseUrl,
|
|
75
|
+
baseUrl,
|
|
76
|
+
apiKey,
|
|
77
|
+
capabilities: { write, destructive },
|
|
78
|
+
features
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/server.ts
|
|
83
|
+
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
84
|
+
|
|
85
|
+
// src/http.ts
|
|
86
|
+
var FETCH_TIMEOUT_MS = 15e3;
|
|
87
|
+
function fetchSignal() {
|
|
88
|
+
return AbortSignal.timeout(FETCH_TIMEOUT_MS);
|
|
89
|
+
}
|
|
90
|
+
async function readHttpErrorMessage(response) {
|
|
91
|
+
const errorData = await response.json().catch(() => null);
|
|
92
|
+
if (typeof errorData?.error === "string") {
|
|
93
|
+
return errorData.error;
|
|
94
|
+
}
|
|
95
|
+
if (errorData?.error && typeof errorData.error === "object" && errorData.error.message) {
|
|
96
|
+
return errorData.error.message;
|
|
97
|
+
}
|
|
98
|
+
return response.statusText || `HTTP ${response.status}`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/client.ts
|
|
102
|
+
var PlatformClient = class {
|
|
103
|
+
constructor(baseUrl, apiKey) {
|
|
104
|
+
this.baseUrl = baseUrl;
|
|
105
|
+
this.apiKey = apiKey;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Low-level request against the Cencori API. Sends `Authorization: Bearer`,
|
|
109
|
+
* which the gateway accepts for both `/v1/*` and `/api/ai/*` routes.
|
|
110
|
+
*/
|
|
111
|
+
async request(method, path, options = {}) {
|
|
112
|
+
const url = new URL(`/api${path}`, this.baseUrl);
|
|
113
|
+
if (options.searchParams) {
|
|
114
|
+
for (const [key, value] of Object.entries(options.searchParams)) {
|
|
115
|
+
if (value !== void 0) {
|
|
116
|
+
url.searchParams.set(key, value);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const headers = {
|
|
121
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
122
|
+
};
|
|
123
|
+
const init = { method, headers, signal: fetchSignal() };
|
|
124
|
+
if (options.body !== void 0) {
|
|
125
|
+
headers["Content-Type"] = "application/json";
|
|
126
|
+
init.body = JSON.stringify(options.body);
|
|
127
|
+
}
|
|
128
|
+
const response = await fetch(url, init);
|
|
129
|
+
if (!response.ok) {
|
|
130
|
+
const message = await readHttpErrorMessage(response);
|
|
131
|
+
throw new Error(`Cencori API error: ${message}`);
|
|
132
|
+
}
|
|
133
|
+
const text = await response.text();
|
|
134
|
+
if (!text) {
|
|
135
|
+
return void 0;
|
|
136
|
+
}
|
|
137
|
+
return JSON.parse(text);
|
|
138
|
+
}
|
|
139
|
+
get(path, searchParams) {
|
|
140
|
+
return this.request("GET", path, { searchParams });
|
|
141
|
+
}
|
|
142
|
+
post(path, body, searchParams) {
|
|
143
|
+
return this.request("POST", path, { body, searchParams });
|
|
144
|
+
}
|
|
145
|
+
patch(path, body) {
|
|
146
|
+
return this.request("PATCH", path, { body });
|
|
147
|
+
}
|
|
148
|
+
del(path) {
|
|
149
|
+
return this.request("DELETE", path);
|
|
150
|
+
}
|
|
151
|
+
listModels() {
|
|
152
|
+
return this.get("/v1/models");
|
|
153
|
+
}
|
|
154
|
+
getMetrics(period = "7d") {
|
|
155
|
+
return this.get("/v1/metrics", { period });
|
|
156
|
+
}
|
|
157
|
+
listAgents() {
|
|
158
|
+
return this.get("/v1/agents");
|
|
159
|
+
}
|
|
160
|
+
getAgent(agentId) {
|
|
161
|
+
return this.get(`/v1/agents/${agentId}`);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// src/docs/client.ts
|
|
166
|
+
var DocsClient = class {
|
|
167
|
+
constructor(baseUrl) {
|
|
168
|
+
this.baseUrl = baseUrl;
|
|
169
|
+
}
|
|
170
|
+
async search(query) {
|
|
171
|
+
const url = new URL("/api/docs/search", this.baseUrl);
|
|
172
|
+
url.searchParams.set("q", query);
|
|
173
|
+
const response = await fetch(url, { signal: fetchSignal() });
|
|
174
|
+
if (!response.ok) {
|
|
175
|
+
const message = await readHttpErrorMessage(response);
|
|
176
|
+
throw new Error(`Docs search failed (${response.status}): ${message}`);
|
|
177
|
+
}
|
|
178
|
+
return response.json();
|
|
179
|
+
}
|
|
180
|
+
async getDoc(slug) {
|
|
181
|
+
const normalizedSlug = slug.replace(/^\/docs\//, "").replace(/^\//, "");
|
|
182
|
+
const url = new URL("/api/docs/raw", this.baseUrl);
|
|
183
|
+
url.searchParams.set("slug", normalizedSlug);
|
|
184
|
+
const response = await fetch(url, { signal: fetchSignal() });
|
|
185
|
+
if (response.status === 404) {
|
|
186
|
+
return { content: "", error: `Document not found: ${normalizedSlug}` };
|
|
187
|
+
}
|
|
188
|
+
if (!response.ok) {
|
|
189
|
+
const message = await readHttpErrorMessage(response);
|
|
190
|
+
throw new Error(`Docs fetch failed (${response.status}): ${message}`);
|
|
191
|
+
}
|
|
192
|
+
return response.json();
|
|
193
|
+
}
|
|
194
|
+
async listNavigation() {
|
|
195
|
+
const url = new URL("/api/docs/navigation", this.baseUrl);
|
|
196
|
+
const response = await fetch(url, { signal: fetchSignal() });
|
|
197
|
+
if (!response.ok) {
|
|
198
|
+
const message = await readHttpErrorMessage(response);
|
|
199
|
+
throw new Error(`Docs navigation failed (${response.status}): ${message}`);
|
|
200
|
+
}
|
|
201
|
+
return response.json();
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
// src/tools/docs.ts
|
|
206
|
+
var import_zod = require("zod");
|
|
207
|
+
|
|
208
|
+
// src/tools/shared.ts
|
|
209
|
+
var READ_ONLY_ANNOTATIONS = {
|
|
210
|
+
title: "Read-only",
|
|
211
|
+
readOnlyHint: true,
|
|
212
|
+
destructiveHint: false,
|
|
213
|
+
openWorldHint: false
|
|
214
|
+
};
|
|
215
|
+
var WRITE_ANNOTATIONS = {
|
|
216
|
+
title: "Write",
|
|
217
|
+
readOnlyHint: false,
|
|
218
|
+
destructiveHint: false,
|
|
219
|
+
openWorldHint: false
|
|
220
|
+
};
|
|
221
|
+
function jsonResult(data) {
|
|
222
|
+
return {
|
|
223
|
+
content: [
|
|
224
|
+
{
|
|
225
|
+
type: "text",
|
|
226
|
+
text: JSON.stringify(data, null, 2)
|
|
227
|
+
}
|
|
228
|
+
]
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// src/tools/docs.ts
|
|
233
|
+
function registerDocsTools(server, docs, docsBaseUrl) {
|
|
234
|
+
server.registerTool(
|
|
235
|
+
"search_docs",
|
|
236
|
+
{
|
|
237
|
+
title: "Search Cencori docs",
|
|
238
|
+
description: "Search Cencori documentation by keyword. Returns matching pages with title, section, URL, and snippet.",
|
|
239
|
+
inputSchema: {
|
|
240
|
+
query: import_zod.z.string().min(2).describe('Search query (minimum 2 characters). Example: "rate limiting", "api keys", "failover".')
|
|
241
|
+
},
|
|
242
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
243
|
+
},
|
|
244
|
+
async ({ query }) => {
|
|
245
|
+
const { results } = await docs.search(query);
|
|
246
|
+
return jsonResult({ query, count: results.length, results });
|
|
247
|
+
}
|
|
248
|
+
);
|
|
249
|
+
server.registerTool(
|
|
250
|
+
"get_doc",
|
|
251
|
+
{
|
|
252
|
+
title: "Get Cencori doc page",
|
|
253
|
+
description: 'Fetch the raw markdown content of a Cencori documentation page by slug. Example slugs: "quick-start", "ai/sdk", "api/chat".',
|
|
254
|
+
inputSchema: {
|
|
255
|
+
slug: import_zod.z.string().min(1).describe('Doc slug without /docs/ prefix. Example: "ai/gateway" or "security/scan".')
|
|
256
|
+
},
|
|
257
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
258
|
+
},
|
|
259
|
+
async ({ slug }) => {
|
|
260
|
+
const doc = await docs.getDoc(slug);
|
|
261
|
+
const normalizedSlug = slug.replace(/^\/docs\//, "").replace(/^\//, "");
|
|
262
|
+
if (doc.error) {
|
|
263
|
+
return jsonResult({ slug: normalizedSlug, error: doc.error });
|
|
264
|
+
}
|
|
265
|
+
return jsonResult({
|
|
266
|
+
slug: normalizedSlug,
|
|
267
|
+
url: `${docsBaseUrl}/docs/${normalizedSlug}`,
|
|
268
|
+
content: doc.content
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
);
|
|
272
|
+
server.registerTool(
|
|
273
|
+
"list_docs",
|
|
274
|
+
{
|
|
275
|
+
title: "List Cencori docs",
|
|
276
|
+
description: "List the Cencori documentation table of contents grouped by section (Getting Started, Platform, AI, API Reference, etc.).",
|
|
277
|
+
inputSchema: {},
|
|
278
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
279
|
+
},
|
|
280
|
+
async () => {
|
|
281
|
+
const navigation = await docs.listNavigation();
|
|
282
|
+
return jsonResult(navigation);
|
|
283
|
+
}
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// src/tools/gateway.ts
|
|
288
|
+
var import_zod2 = require("zod");
|
|
289
|
+
function registerGatewayTools(server, client) {
|
|
290
|
+
server.registerTool(
|
|
291
|
+
"list_models",
|
|
292
|
+
{
|
|
293
|
+
title: "List Cencori gateway models",
|
|
294
|
+
description: "List models available through the Cencori gateway for the authenticated project.",
|
|
295
|
+
inputSchema: {},
|
|
296
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
297
|
+
},
|
|
298
|
+
async () => {
|
|
299
|
+
const models = await client.listModels();
|
|
300
|
+
return jsonResult(models);
|
|
301
|
+
}
|
|
302
|
+
);
|
|
303
|
+
server.registerTool(
|
|
304
|
+
"get_metrics",
|
|
305
|
+
{
|
|
306
|
+
title: "Get Cencori gateway metrics",
|
|
307
|
+
description: "Get gateway usage metrics for the authenticated project, including requests, cost, tokens, latency, and model/provider breakdowns.",
|
|
308
|
+
inputSchema: {
|
|
309
|
+
period: import_zod2.z.enum(["1h", "24h", "7d", "30d", "mtd"]).optional().describe("Metrics time window. Allowed values: 1h, 24h, 7d, 30d, mtd.")
|
|
310
|
+
},
|
|
311
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
312
|
+
},
|
|
313
|
+
async ({ period }) => {
|
|
314
|
+
const metrics = await client.getMetrics(period);
|
|
315
|
+
return jsonResult(metrics);
|
|
316
|
+
}
|
|
317
|
+
);
|
|
318
|
+
server.registerTool(
|
|
319
|
+
"get_health",
|
|
320
|
+
{
|
|
321
|
+
title: "Get Cencori gateway health",
|
|
322
|
+
description: "Check gateway/platform health for the authenticated project.",
|
|
323
|
+
inputSchema: {},
|
|
324
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
325
|
+
},
|
|
326
|
+
async () => jsonResult(await client.get("/v1/health"))
|
|
327
|
+
);
|
|
328
|
+
server.registerTool(
|
|
329
|
+
"check_quota",
|
|
330
|
+
{
|
|
331
|
+
title: "Check billing quota",
|
|
332
|
+
description: "Check remaining quota/credits and usage limits for the authenticated project.",
|
|
333
|
+
inputSchema: {},
|
|
334
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
335
|
+
},
|
|
336
|
+
async () => jsonResult(await client.get("/v1/billing/check-quota"))
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// src/tools/agents.ts
|
|
341
|
+
var import_zod3 = require("zod");
|
|
342
|
+
function registerAgentsTools(server, client) {
|
|
343
|
+
server.registerTool(
|
|
344
|
+
"list_agents",
|
|
345
|
+
{
|
|
346
|
+
title: "List Cencori agents",
|
|
347
|
+
description: "List agents available to the authenticated project.",
|
|
348
|
+
inputSchema: {},
|
|
349
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
350
|
+
},
|
|
351
|
+
async () => {
|
|
352
|
+
const agents = await client.listAgents();
|
|
353
|
+
return jsonResult(agents);
|
|
354
|
+
}
|
|
355
|
+
);
|
|
356
|
+
server.registerTool(
|
|
357
|
+
"get_agent",
|
|
358
|
+
{
|
|
359
|
+
title: "Get Cencori agent",
|
|
360
|
+
description: "Fetch the full configuration for one Cencori agent by ID.",
|
|
361
|
+
inputSchema: {
|
|
362
|
+
agent_id: import_zod3.z.string().min(1).describe("The agent ID to fetch.")
|
|
363
|
+
},
|
|
364
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
365
|
+
},
|
|
366
|
+
async ({ agent_id }) => {
|
|
367
|
+
const agent = await client.getAgent(agent_id);
|
|
368
|
+
return jsonResult(agent);
|
|
369
|
+
}
|
|
370
|
+
);
|
|
371
|
+
server.registerTool(
|
|
372
|
+
"poll_agent_actions",
|
|
373
|
+
{
|
|
374
|
+
title: "Poll pending agent actions",
|
|
375
|
+
description: "Poll for pending actions queued for agents in the authenticated project.",
|
|
376
|
+
inputSchema: {},
|
|
377
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
378
|
+
},
|
|
379
|
+
async () => jsonResult(await client.get("/v1/agent/actions/poll"))
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// src/tools/memory.ts
|
|
384
|
+
var import_zod4 = require("zod");
|
|
385
|
+
var scopeShape = {
|
|
386
|
+
namespace: import_zod4.z.string().optional().describe("Memory namespace to scope to."),
|
|
387
|
+
scope: import_zod4.z.string().optional().describe("Memory scope (e.g. project, user, session)."),
|
|
388
|
+
user_id: import_zod4.z.string().optional().describe("Scope to a specific end-user id."),
|
|
389
|
+
session_id: import_zod4.z.string().optional().describe("Scope to a specific session id.")
|
|
390
|
+
};
|
|
391
|
+
function registerMemoryTools(server, client) {
|
|
392
|
+
server.registerTool(
|
|
393
|
+
"list_memories",
|
|
394
|
+
{
|
|
395
|
+
title: "List memories",
|
|
396
|
+
description: "List stored memories for the project, optionally scoped by namespace/user/session.",
|
|
397
|
+
inputSchema: {
|
|
398
|
+
...scopeShape,
|
|
399
|
+
limit: import_zod4.z.number().int().positive().max(200).optional(),
|
|
400
|
+
cursor: import_zod4.z.string().optional().describe("Pagination cursor from a previous response.")
|
|
401
|
+
},
|
|
402
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
403
|
+
},
|
|
404
|
+
async ({ namespace, scope, user_id, session_id, limit, cursor }) => jsonResult(
|
|
405
|
+
await client.get("/v1/memory/list", {
|
|
406
|
+
namespace,
|
|
407
|
+
scope,
|
|
408
|
+
userId: user_id,
|
|
409
|
+
sessionId: session_id,
|
|
410
|
+
limit: limit?.toString(),
|
|
411
|
+
cursor
|
|
412
|
+
})
|
|
413
|
+
)
|
|
414
|
+
);
|
|
415
|
+
server.registerTool(
|
|
416
|
+
"search_memory",
|
|
417
|
+
{
|
|
418
|
+
title: "Search memory (semantic)",
|
|
419
|
+
description: "Semantically search stored memories by query.",
|
|
420
|
+
inputSchema: {
|
|
421
|
+
query: import_zod4.z.string().min(1).describe("Natural-language search query."),
|
|
422
|
+
...scopeShape,
|
|
423
|
+
top_k: import_zod4.z.number().int().positive().max(100).optional().describe("Max results."),
|
|
424
|
+
threshold: import_zod4.z.number().min(0).max(1).optional().describe("Similarity threshold.")
|
|
425
|
+
},
|
|
426
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
427
|
+
},
|
|
428
|
+
async ({ query, namespace, scope, user_id, session_id, top_k, threshold }) => jsonResult(
|
|
429
|
+
await client.post("/v1/memory/search", {
|
|
430
|
+
query,
|
|
431
|
+
namespace,
|
|
432
|
+
scope,
|
|
433
|
+
userId: user_id,
|
|
434
|
+
sessionId: session_id,
|
|
435
|
+
topK: top_k,
|
|
436
|
+
threshold
|
|
437
|
+
})
|
|
438
|
+
)
|
|
439
|
+
);
|
|
440
|
+
server.registerTool(
|
|
441
|
+
"get_memory",
|
|
442
|
+
{
|
|
443
|
+
title: "Get a memory",
|
|
444
|
+
description: "Fetch a single memory by id.",
|
|
445
|
+
inputSchema: { memory_id: import_zod4.z.string().min(1).describe("The memory id.") },
|
|
446
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
447
|
+
},
|
|
448
|
+
async ({ memory_id }) => jsonResult(await client.get(`/v1/memory/${memory_id}`))
|
|
449
|
+
);
|
|
450
|
+
server.registerTool(
|
|
451
|
+
"list_memory_entities",
|
|
452
|
+
{
|
|
453
|
+
title: "List memory entities",
|
|
454
|
+
description: "List entities resolved from the memory graph.",
|
|
455
|
+
inputSchema: scopeShape,
|
|
456
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
457
|
+
},
|
|
458
|
+
async ({ namespace, scope, user_id, session_id }) => jsonResult(
|
|
459
|
+
await client.get("/v1/memory/entities", {
|
|
460
|
+
namespace,
|
|
461
|
+
scope,
|
|
462
|
+
userId: user_id,
|
|
463
|
+
sessionId: session_id
|
|
464
|
+
})
|
|
465
|
+
)
|
|
466
|
+
);
|
|
467
|
+
server.registerTool(
|
|
468
|
+
"get_memory_graph",
|
|
469
|
+
{
|
|
470
|
+
title: "Get memory entity graph",
|
|
471
|
+
description: "Traverse the memory entity graph from an optional starting entity.",
|
|
472
|
+
inputSchema: {
|
|
473
|
+
...scopeShape,
|
|
474
|
+
entity: import_zod4.z.string().optional().describe("Entity to start traversal from."),
|
|
475
|
+
hops: import_zod4.z.number().int().positive().max(5).optional().describe("Traversal depth.")
|
|
476
|
+
},
|
|
477
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
478
|
+
},
|
|
479
|
+
async ({ namespace, scope, user_id, session_id, entity, hops }) => jsonResult(
|
|
480
|
+
await client.get("/v1/memory/graph", {
|
|
481
|
+
namespace,
|
|
482
|
+
scope,
|
|
483
|
+
userId: user_id,
|
|
484
|
+
sessionId: session_id,
|
|
485
|
+
entity,
|
|
486
|
+
hops: hops?.toString()
|
|
487
|
+
})
|
|
488
|
+
)
|
|
489
|
+
);
|
|
490
|
+
server.registerTool(
|
|
491
|
+
"get_forget_suggestions",
|
|
492
|
+
{
|
|
493
|
+
title: "Get forget suggestions",
|
|
494
|
+
description: "List memories the system suggests forgetting (stale/superseded).",
|
|
495
|
+
inputSchema: scopeShape,
|
|
496
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
497
|
+
},
|
|
498
|
+
async ({ namespace, scope, user_id, session_id }) => jsonResult(
|
|
499
|
+
await client.get("/v1/memory/forget-suggestions", {
|
|
500
|
+
namespace,
|
|
501
|
+
scope,
|
|
502
|
+
userId: user_id,
|
|
503
|
+
sessionId: session_id
|
|
504
|
+
})
|
|
505
|
+
)
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// src/tools/sessions.ts
|
|
510
|
+
var import_zod5 = require("zod");
|
|
511
|
+
function registerSessionsTools(server, client) {
|
|
512
|
+
server.registerTool(
|
|
513
|
+
"list_sessions",
|
|
514
|
+
{
|
|
515
|
+
title: "List agent sessions",
|
|
516
|
+
description: "List agent sessions for the project, optionally filtered by status or agent.",
|
|
517
|
+
inputSchema: {
|
|
518
|
+
status: import_zod5.z.string().optional().describe("Filter by session status."),
|
|
519
|
+
agent_id: import_zod5.z.string().optional().describe("Filter by agent id."),
|
|
520
|
+
page: import_zod5.z.number().int().positive().optional(),
|
|
521
|
+
limit: import_zod5.z.number().int().positive().max(100).optional()
|
|
522
|
+
},
|
|
523
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
524
|
+
},
|
|
525
|
+
async ({ status, agent_id, page, limit }) => jsonResult(
|
|
526
|
+
await client.get("/v1/sessions", {
|
|
527
|
+
status,
|
|
528
|
+
agent_id,
|
|
529
|
+
page: page?.toString(),
|
|
530
|
+
limit: limit?.toString()
|
|
531
|
+
})
|
|
532
|
+
)
|
|
533
|
+
);
|
|
534
|
+
server.registerTool(
|
|
535
|
+
"get_session",
|
|
536
|
+
{
|
|
537
|
+
title: "Get an agent session",
|
|
538
|
+
description: "Fetch one agent session by id.",
|
|
539
|
+
inputSchema: { session_id: import_zod5.z.string().min(1).describe("The session id.") },
|
|
540
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
541
|
+
},
|
|
542
|
+
async ({ session_id }) => jsonResult(await client.get(`/v1/sessions/${session_id}`))
|
|
543
|
+
);
|
|
544
|
+
server.registerTool(
|
|
545
|
+
"get_session_events",
|
|
546
|
+
{
|
|
547
|
+
title: "Get agent session events",
|
|
548
|
+
description: "List the event timeline for one agent session.",
|
|
549
|
+
inputSchema: { session_id: import_zod5.z.string().min(1).describe("The session id.") },
|
|
550
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
551
|
+
},
|
|
552
|
+
async ({ session_id }) => jsonResult(await client.get(`/v1/sessions/${session_id}/events`))
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// src/tools/governance.ts
|
|
557
|
+
var import_zod6 = require("zod");
|
|
558
|
+
function registerGovernanceTools(server, client) {
|
|
559
|
+
server.registerTool(
|
|
560
|
+
"list_policies",
|
|
561
|
+
{
|
|
562
|
+
title: "List governance policies",
|
|
563
|
+
description: "List governance policies for the org, optionally filtered by status.",
|
|
564
|
+
inputSchema: {
|
|
565
|
+
status: import_zod6.z.enum(["draft", "pending_review", "active", "retired"]).optional()
|
|
566
|
+
},
|
|
567
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
568
|
+
},
|
|
569
|
+
async ({ status }) => jsonResult(await client.get("/v1/governance/policies", { status }))
|
|
570
|
+
);
|
|
571
|
+
server.registerTool(
|
|
572
|
+
"list_roles",
|
|
573
|
+
{
|
|
574
|
+
title: "List governance roles",
|
|
575
|
+
description: "List governance roles defined for the org.",
|
|
576
|
+
inputSchema: {},
|
|
577
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
578
|
+
},
|
|
579
|
+
async () => jsonResult(await client.get("/v1/governance/roles"))
|
|
580
|
+
);
|
|
581
|
+
server.registerTool(
|
|
582
|
+
"list_change_requests",
|
|
583
|
+
{
|
|
584
|
+
title: "List governance change requests",
|
|
585
|
+
description: "List maker-checker change requests for governance policies.",
|
|
586
|
+
inputSchema: {},
|
|
587
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
588
|
+
},
|
|
589
|
+
async () => jsonResult(await client.get("/v1/governance/change-requests"))
|
|
590
|
+
);
|
|
591
|
+
server.registerTool(
|
|
592
|
+
"get_governance_ledger",
|
|
593
|
+
{
|
|
594
|
+
title: "Get governance audit ledger",
|
|
595
|
+
description: "Read the immutable governance audit ledger.",
|
|
596
|
+
inputSchema: {},
|
|
597
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
598
|
+
},
|
|
599
|
+
async () => jsonResult(await client.get("/v1/governance/ledger"))
|
|
600
|
+
);
|
|
601
|
+
server.registerTool(
|
|
602
|
+
"get_governance_evidence",
|
|
603
|
+
{
|
|
604
|
+
title: "Get governance evidence",
|
|
605
|
+
description: "Read governance evidence records (enforcement decisions).",
|
|
606
|
+
inputSchema: {},
|
|
607
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
608
|
+
},
|
|
609
|
+
async () => jsonResult(await client.get("/v1/governance/evidence"))
|
|
610
|
+
);
|
|
611
|
+
server.registerTool(
|
|
612
|
+
"list_governance_templates",
|
|
613
|
+
{
|
|
614
|
+
title: "List governance policy templates",
|
|
615
|
+
description: "List installable governance policy templates.",
|
|
616
|
+
inputSchema: {},
|
|
617
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
618
|
+
},
|
|
619
|
+
async () => jsonResult(await client.get("/v1/governance/templates"))
|
|
620
|
+
);
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// src/tools/multimodal.ts
|
|
624
|
+
var import_zod7 = require("zod");
|
|
625
|
+
var messageSchema = import_zod7.z.array(
|
|
626
|
+
import_zod7.z.object({
|
|
627
|
+
role: import_zod7.z.enum(["system", "user", "assistant"]),
|
|
628
|
+
content: import_zod7.z.string()
|
|
629
|
+
})
|
|
630
|
+
).min(1).describe("Chat messages in OpenAI format.");
|
|
631
|
+
var imageSourceShape = {
|
|
632
|
+
image_url: import_zod7.z.string().url().optional().describe("Public URL of the image."),
|
|
633
|
+
image_base64: import_zod7.z.string().optional().describe("Base64-encoded image bytes (use with mime_type)."),
|
|
634
|
+
mime_type: import_zod7.z.string().optional().describe("MIME type for image_base64, e.g. image/png."),
|
|
635
|
+
prompt: import_zod7.z.string().optional().describe("Optional instruction to steer the analysis."),
|
|
636
|
+
model: import_zod7.z.string().optional().describe("Override the model.")
|
|
637
|
+
};
|
|
638
|
+
var documentSourceShape = {
|
|
639
|
+
document_url: import_zod7.z.string().url().optional().describe("Public URL of the PDF/image."),
|
|
640
|
+
document_base64: import_zod7.z.string().optional().describe("Base64-encoded document bytes (use with mime_type)."),
|
|
641
|
+
mime_type: import_zod7.z.string().optional().describe("MIME type for document_base64, e.g. application/pdf."),
|
|
642
|
+
model: import_zod7.z.string().optional().describe("Override the model.")
|
|
643
|
+
};
|
|
644
|
+
function registerMultimodalTools(server, client) {
|
|
645
|
+
server.registerTool(
|
|
646
|
+
"generate_text",
|
|
647
|
+
{
|
|
648
|
+
title: "Generate text (chat completion)",
|
|
649
|
+
description: "Run a chat completion through the Cencori gateway. Incurs usage/cost.",
|
|
650
|
+
inputSchema: {
|
|
651
|
+
model: import_zod7.z.string().describe("Model id, e.g. llama-3.1-8b-instant or claude-opus-5."),
|
|
652
|
+
messages: messageSchema,
|
|
653
|
+
temperature: import_zod7.z.number().min(0).max(2).optional(),
|
|
654
|
+
max_tokens: import_zod7.z.number().int().positive().optional()
|
|
655
|
+
},
|
|
656
|
+
annotations: WRITE_ANNOTATIONS
|
|
657
|
+
},
|
|
658
|
+
async ({ model, messages, temperature, max_tokens }) => jsonResult(await client.post("/v1/chat/completions", { model, messages, temperature, max_tokens }))
|
|
659
|
+
);
|
|
660
|
+
server.registerTool(
|
|
661
|
+
"generate_rag",
|
|
662
|
+
{
|
|
663
|
+
title: "RAG chat over a memory namespace",
|
|
664
|
+
description: "Answer a question grounded in stored memories for a namespace. Incurs usage/cost.",
|
|
665
|
+
inputSchema: {
|
|
666
|
+
model: import_zod7.z.string().describe("Model id for the answer."),
|
|
667
|
+
messages: messageSchema,
|
|
668
|
+
namespace: import_zod7.z.string().min(1).describe("Memory namespace to retrieve context from."),
|
|
669
|
+
limit: import_zod7.z.number().int().positive().optional().describe("Max memories to retrieve.")
|
|
670
|
+
},
|
|
671
|
+
annotations: WRITE_ANNOTATIONS
|
|
672
|
+
},
|
|
673
|
+
async ({ model, messages, namespace, limit }) => jsonResult(await client.post("/ai/rag", { model, messages, namespace, limit }))
|
|
674
|
+
);
|
|
675
|
+
server.registerTool(
|
|
676
|
+
"create_embeddings",
|
|
677
|
+
{
|
|
678
|
+
title: "Create embeddings",
|
|
679
|
+
description: "Generate vector embeddings for text. Incurs usage/cost.",
|
|
680
|
+
inputSchema: {
|
|
681
|
+
input: import_zod7.z.union([import_zod7.z.string(), import_zod7.z.array(import_zod7.z.string())]).describe("Text or array of texts to embed."),
|
|
682
|
+
model: import_zod7.z.string().optional().describe("Embedding model. Defaults to text-embedding-3-small."),
|
|
683
|
+
dimensions: import_zod7.z.number().int().positive().optional()
|
|
684
|
+
},
|
|
685
|
+
annotations: WRITE_ANNOTATIONS
|
|
686
|
+
},
|
|
687
|
+
async ({ input, model, dimensions }) => jsonResult(await client.post("/ai/embeddings", { input, model, dimensions }))
|
|
688
|
+
);
|
|
689
|
+
server.registerTool(
|
|
690
|
+
"moderate_content",
|
|
691
|
+
{
|
|
692
|
+
title: "Moderate content",
|
|
693
|
+
description: "Classify text for policy violations via the moderation endpoint.",
|
|
694
|
+
inputSchema: {
|
|
695
|
+
input: import_zod7.z.union([import_zod7.z.string(), import_zod7.z.array(import_zod7.z.string())]).describe("Text or array of texts to moderate."),
|
|
696
|
+
model: import_zod7.z.string().optional()
|
|
697
|
+
},
|
|
698
|
+
annotations: WRITE_ANNOTATIONS
|
|
699
|
+
},
|
|
700
|
+
async ({ input, model }) => jsonResult(await client.post("/ai/moderation", { input, model }))
|
|
701
|
+
);
|
|
702
|
+
server.registerTool(
|
|
703
|
+
"generate_image",
|
|
704
|
+
{
|
|
705
|
+
title: "Generate an image",
|
|
706
|
+
description: "Generate image(s) from a text prompt. Incurs usage/cost.",
|
|
707
|
+
inputSchema: {
|
|
708
|
+
prompt: import_zod7.z.string().min(1).describe("Text prompt describing the image."),
|
|
709
|
+
model: import_zod7.z.string().optional(),
|
|
710
|
+
n: import_zod7.z.number().int().positive().optional().describe("Number of images."),
|
|
711
|
+
size: import_zod7.z.string().optional().describe("Image size, e.g. 1024x1024.")
|
|
712
|
+
},
|
|
713
|
+
annotations: WRITE_ANNOTATIONS
|
|
714
|
+
},
|
|
715
|
+
async ({ prompt, model, n, size }) => jsonResult(await client.post("/ai/images/generate", { prompt, model, n, size }))
|
|
716
|
+
);
|
|
717
|
+
for (const [name, path, title] of [
|
|
718
|
+
["describe_image", "/ai/vision/describe", "Describe an image"],
|
|
719
|
+
["ocr_image", "/ai/vision/ocr", "Extract text from an image (OCR)"],
|
|
720
|
+
["classify_image", "/ai/vision/classify", "Classify an image (JSON tags)"]
|
|
721
|
+
]) {
|
|
722
|
+
server.registerTool(
|
|
723
|
+
name,
|
|
724
|
+
{
|
|
725
|
+
title,
|
|
726
|
+
description: `${title} via the Cencori vision endpoint. Incurs usage/cost.`,
|
|
727
|
+
inputSchema: imageSourceShape,
|
|
728
|
+
annotations: WRITE_ANNOTATIONS
|
|
729
|
+
},
|
|
730
|
+
async (args) => jsonResult(await client.post(path, args))
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
server.registerTool(
|
|
734
|
+
"extract_document",
|
|
735
|
+
{
|
|
736
|
+
title: "Extract text from a document",
|
|
737
|
+
description: "Extract clean text from a PDF or image (native extraction for text PDFs). Incurs usage/cost for OCR.",
|
|
738
|
+
inputSchema: documentSourceShape,
|
|
739
|
+
annotations: WRITE_ANNOTATIONS
|
|
740
|
+
},
|
|
741
|
+
async (args) => jsonResult(await client.post("/ai/documents/extract", args))
|
|
742
|
+
);
|
|
743
|
+
server.registerTool(
|
|
744
|
+
"summarize_document",
|
|
745
|
+
{
|
|
746
|
+
title: "Summarize a document",
|
|
747
|
+
description: "Extract and summarize a PDF or image. Incurs usage/cost.",
|
|
748
|
+
inputSchema: { ...documentSourceShape, prompt: import_zod7.z.string().optional().describe("Optional summary instruction.") },
|
|
749
|
+
annotations: WRITE_ANNOTATIONS
|
|
750
|
+
},
|
|
751
|
+
async (args) => jsonResult(await client.post("/ai/documents/summarize", args))
|
|
752
|
+
);
|
|
753
|
+
server.registerTool(
|
|
754
|
+
"query_document",
|
|
755
|
+
{
|
|
756
|
+
title: "Ask a question about a document",
|
|
757
|
+
description: "Extract a document and answer a question about it. Incurs usage/cost.",
|
|
758
|
+
inputSchema: {
|
|
759
|
+
...documentSourceShape,
|
|
760
|
+
question: import_zod7.z.string().min(1).describe("The question to answer about the document.")
|
|
761
|
+
},
|
|
762
|
+
annotations: WRITE_ANNOTATIONS
|
|
763
|
+
},
|
|
764
|
+
async (args) => jsonResult(await client.post("/ai/documents/query", args))
|
|
765
|
+
);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// src/tools/guidance.ts
|
|
769
|
+
var import_zod8 = require("zod");
|
|
770
|
+
var orgProjectShape = {
|
|
771
|
+
org_slug: import_zod8.z.string().min(1).optional().describe("Your organization slug, to build an exact dashboard link."),
|
|
772
|
+
project_slug: import_zod8.z.string().min(1).optional().describe("Your project slug, to build an exact dashboard link.")
|
|
773
|
+
};
|
|
774
|
+
function registerGuide(server, name, title, description, buildPath, steps, baseUrl) {
|
|
775
|
+
server.registerTool(
|
|
776
|
+
name,
|
|
777
|
+
{
|
|
778
|
+
title,
|
|
779
|
+
description,
|
|
780
|
+
inputSchema: orgProjectShape,
|
|
781
|
+
annotations: READ_ONLY_ANNOTATIONS
|
|
782
|
+
},
|
|
783
|
+
async (args) => {
|
|
784
|
+
return jsonResult({
|
|
785
|
+
manual_action: true,
|
|
786
|
+
note: "This action is intentionally not automated. Tell the user to complete it themselves in the Cencori dashboard.",
|
|
787
|
+
steps,
|
|
788
|
+
dashboard_url: `${baseUrl}${buildPath(args)}`
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
);
|
|
792
|
+
}
|
|
793
|
+
var ORG = (s) => s.org_slug ?? "<your-org>";
|
|
794
|
+
var PROJ = (s) => s.project_slug ?? "<your-project>";
|
|
795
|
+
function registerGuidanceTools(server, baseUrl) {
|
|
796
|
+
registerGuide(
|
|
797
|
+
server,
|
|
798
|
+
"how_to_create_api_key",
|
|
799
|
+
"How to create a Cencori API key",
|
|
800
|
+
"Steps for the USER to create a Cencori project API key. The MCP never creates keys.",
|
|
801
|
+
(s) => `/${ORG(s)}/${PROJ(s)}/api-keys`,
|
|
802
|
+
[
|
|
803
|
+
"Open the Cencori dashboard and select your organization, then your project.",
|
|
804
|
+
"Go to the project\u2019s API Keys page.",
|
|
805
|
+
"Click \u201CCreate key\u201D, name it, choose the environment, and copy the `csk_...` secret.",
|
|
806
|
+
"Store it server-side as CENCORI_API_KEY \u2014 it is shown only once."
|
|
807
|
+
],
|
|
808
|
+
baseUrl
|
|
809
|
+
);
|
|
810
|
+
registerGuide(
|
|
811
|
+
server,
|
|
812
|
+
"how_to_edit_api_key",
|
|
813
|
+
"How to edit a Cencori API key",
|
|
814
|
+
"Steps for the USER to rename or change scopes/limits on an API key. The MCP never edits keys.",
|
|
815
|
+
(s) => `/${ORG(s)}/${PROJ(s)}/api-keys`,
|
|
816
|
+
[
|
|
817
|
+
"Open the project\u2019s API Keys page in the dashboard.",
|
|
818
|
+
"Find the key and open its actions menu.",
|
|
819
|
+
"Update its name, environment, or limits and save."
|
|
820
|
+
],
|
|
821
|
+
baseUrl
|
|
822
|
+
);
|
|
823
|
+
registerGuide(
|
|
824
|
+
server,
|
|
825
|
+
"how_to_revoke_api_key",
|
|
826
|
+
"How to revoke a Cencori API key",
|
|
827
|
+
"Steps for the USER to revoke/rotate an API key. The MCP never revokes keys.",
|
|
828
|
+
(s) => `/${ORG(s)}/${PROJ(s)}/api-keys`,
|
|
829
|
+
[
|
|
830
|
+
"Open the project\u2019s API Keys page in the dashboard.",
|
|
831
|
+
"Find the key to revoke and choose \u201CRevoke\u201D. This immediately invalidates it.",
|
|
832
|
+
"If rotating, create a new key first and update CENCORI_API_KEY before revoking the old one."
|
|
833
|
+
],
|
|
834
|
+
baseUrl
|
|
835
|
+
);
|
|
836
|
+
registerGuide(
|
|
837
|
+
server,
|
|
838
|
+
"how_to_activate_policy",
|
|
839
|
+
"How to activate a governance policy",
|
|
840
|
+
"Steps for the USER to activate/retire a governance policy. Activation is a maker-checker human step \u2014 the MCP can draft a policy but never activates one.",
|
|
841
|
+
(s) => `/${ORG(s)}/~/governance`,
|
|
842
|
+
[
|
|
843
|
+
"Open the Governance page for your organization in the dashboard.",
|
|
844
|
+
"Find the draft (or pending-review) policy version.",
|
|
845
|
+
"Review it and, as an authorized checker, activate it. Exactly one version per policy can be active."
|
|
846
|
+
],
|
|
847
|
+
baseUrl
|
|
848
|
+
);
|
|
849
|
+
registerGuide(
|
|
850
|
+
server,
|
|
851
|
+
"how_to_respond_to_change_request",
|
|
852
|
+
"How to respond to a governance change request",
|
|
853
|
+
"Steps for the USER (as checker) to approve or reject a governance change request. The MCP never approves/rejects on the user\u2019s behalf.",
|
|
854
|
+
(s) => `/${ORG(s)}/~/governance`,
|
|
855
|
+
[
|
|
856
|
+
"Open the Governance page and go to Change Requests.",
|
|
857
|
+
"Open the pending request and review the proposed change.",
|
|
858
|
+
"As an authorized checker, approve or reject it."
|
|
859
|
+
],
|
|
860
|
+
baseUrl
|
|
861
|
+
);
|
|
862
|
+
registerGuide(
|
|
863
|
+
server,
|
|
864
|
+
"how_to_change_plan",
|
|
865
|
+
"How to change your Cencori plan",
|
|
866
|
+
"Steps for the USER to change plan/tier. The MCP never changes plans or charges.",
|
|
867
|
+
(s) => `/${ORG(s)}/~/billing`,
|
|
868
|
+
[
|
|
869
|
+
"Open the Billing page for your organization in the dashboard.",
|
|
870
|
+
"Choose the plan you want and confirm the change."
|
|
871
|
+
],
|
|
872
|
+
baseUrl
|
|
873
|
+
);
|
|
874
|
+
registerGuide(
|
|
875
|
+
server,
|
|
876
|
+
"how_to_manage_billing",
|
|
877
|
+
"How to manage billing, payment methods, and credits",
|
|
878
|
+
"Steps for the USER to update payment methods or buy credits. The MCP never manages payment or credits.",
|
|
879
|
+
(s) => `/${ORG(s)}/~/billing`,
|
|
880
|
+
[
|
|
881
|
+
"Open the Billing page for your organization in the dashboard.",
|
|
882
|
+
"Update a payment method, or purchase credits, from the billing controls."
|
|
883
|
+
],
|
|
884
|
+
baseUrl
|
|
885
|
+
);
|
|
886
|
+
registerGuide(
|
|
887
|
+
server,
|
|
888
|
+
"how_to_manage_members",
|
|
889
|
+
"How to manage members, roles, and SSO",
|
|
890
|
+
"Steps for the USER to invite/remove members, change roles, or configure SSO. The MCP never alters access.",
|
|
891
|
+
(s) => `/${ORG(s)}/~/teams`,
|
|
892
|
+
[
|
|
893
|
+
"Open the Teams page for your organization in the dashboard.",
|
|
894
|
+
"Invite or remove members, or change a member\u2019s role.",
|
|
895
|
+
"Configure SSO from the organization settings if applicable."
|
|
896
|
+
],
|
|
897
|
+
baseUrl
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
// src/server.ts
|
|
902
|
+
var SERVER_NAME = "cencori";
|
|
903
|
+
var SERVER_VERSION = "0.2.0";
|
|
904
|
+
function createServer(config) {
|
|
905
|
+
const server = new import_mcp.McpServer(
|
|
906
|
+
{
|
|
907
|
+
name: SERVER_NAME,
|
|
908
|
+
version: SERVER_VERSION,
|
|
909
|
+
websiteUrl: "https://cencori.com/docs"
|
|
910
|
+
},
|
|
911
|
+
{
|
|
912
|
+
capabilities: {
|
|
913
|
+
tools: {}
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
);
|
|
917
|
+
const { features, capabilities } = config;
|
|
918
|
+
if (features.docs) {
|
|
919
|
+
const docs = new DocsClient(config.docsBaseUrl);
|
|
920
|
+
registerDocsTools(server, docs, config.docsBaseUrl);
|
|
921
|
+
}
|
|
922
|
+
if (features.guidance) {
|
|
923
|
+
registerGuidanceTools(server, config.baseUrl);
|
|
924
|
+
}
|
|
925
|
+
if (config.apiKey) {
|
|
926
|
+
const client = new PlatformClient(config.baseUrl, config.apiKey);
|
|
927
|
+
if (features.gateway) registerGatewayTools(server, client);
|
|
928
|
+
if (features.agents) registerAgentsTools(server, client);
|
|
929
|
+
if (features.memory) registerMemoryTools(server, client);
|
|
930
|
+
if (features.sessions) registerSessionsTools(server, client);
|
|
931
|
+
if (features.governance) registerGovernanceTools(server, client);
|
|
932
|
+
if (features.multimodal && capabilities.write) {
|
|
933
|
+
registerMultimodalTools(server, client);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
return server;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
// src/index.ts
|
|
940
|
+
async function main() {
|
|
941
|
+
const config = loadConfig();
|
|
942
|
+
const server = createServer(config);
|
|
943
|
+
const transport = new import_stdio.StdioServerTransport();
|
|
944
|
+
await server.connect(transport);
|
|
945
|
+
const enabledFeatures = Object.entries(config.features).filter(([, enabled]) => enabled).map(([feature]) => feature).join(", ");
|
|
946
|
+
const tier = config.capabilities.destructive ? "read+write+destructive" : config.capabilities.write ? "read+write" : "read-only";
|
|
947
|
+
console.error(
|
|
948
|
+
`Cencori MCP server running (tier=${tier}, base=${config.baseUrl}, features=${enabledFeatures}, apiKey=${config.apiKey ? "configured" : "not set"})`
|
|
949
|
+
);
|
|
950
|
+
}
|
|
951
|
+
main().catch((error) => {
|
|
952
|
+
console.error("Fatal error:", error);
|
|
953
|
+
process.exit(1);
|
|
954
|
+
});
|
|
955
|
+
//# sourceMappingURL=index.js.map
|