roboport 0.3.0 → 0.4.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/mcp/clients/github.d.ts +12 -0
- package/mcp/clients/slack.d.ts +23 -0
- package/mcp/core.d.ts +2 -1
- package/mcp/index.d.ts +3 -1
- package/mcp/index.js +419 -182
- package/package.json +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Mcp as McpBase } from '../core';
|
|
2
|
+
type Options = {
|
|
3
|
+
token: string;
|
|
4
|
+
name?: string;
|
|
5
|
+
toolsets?: string[];
|
|
6
|
+
readOnly?: boolean;
|
|
7
|
+
deferred?: boolean;
|
|
8
|
+
};
|
|
9
|
+
declare class Mcp extends McpBase {
|
|
10
|
+
constructor(opts: Options);
|
|
11
|
+
}
|
|
12
|
+
export default Mcp;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Tool, type McpClient } from '../../core';
|
|
2
|
+
type Options = {
|
|
3
|
+
/**
|
|
4
|
+
* Slack bot token (`xoxb-…`). Requires these OAuth scopes:
|
|
5
|
+
* `chat:write` (post_message, reply_in_thread),
|
|
6
|
+
* `channels:read` (list_channels),
|
|
7
|
+
* `channels:history` (get_channel_history),
|
|
8
|
+
* `users:read` (list_users, get_user),
|
|
9
|
+
* `reactions:write` (add_reaction).
|
|
10
|
+
*/
|
|
11
|
+
botToken: string;
|
|
12
|
+
name?: string;
|
|
13
|
+
deferred?: boolean;
|
|
14
|
+
};
|
|
15
|
+
declare class Mcp implements McpClient {
|
|
16
|
+
private auth;
|
|
17
|
+
private nameSpace;
|
|
18
|
+
private deferred;
|
|
19
|
+
constructor(opts: Options);
|
|
20
|
+
connect(): Promise<Tool[]>;
|
|
21
|
+
disconnect(): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export default Mcp;
|
package/mcp/core.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ type HttpTransportConfig = {
|
|
|
13
13
|
auth?: AuthProvider;
|
|
14
14
|
};
|
|
15
15
|
type McpTransportConfig = StdioTransportConfig | HttpTransportConfig;
|
|
16
|
+
declare function validateMcpName(name: string): void;
|
|
16
17
|
declare class Mcp implements McpClient {
|
|
17
18
|
name: string;
|
|
18
19
|
transport: McpTransportConfig;
|
|
@@ -27,4 +28,4 @@ declare class Mcp implements McpClient {
|
|
|
27
28
|
disconnect(): Promise<void>;
|
|
28
29
|
private wrap;
|
|
29
30
|
}
|
|
30
|
-
export { Mcp, type McpTransportConfig, type StdioTransportConfig, type HttpTransportConfig, };
|
|
31
|
+
export { Mcp, validateMcpName, type McpTransportConfig, type StdioTransportConfig, type HttpTransportConfig, };
|
package/mcp/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { BearerAuth, OAuthAuth, type AuthProvider, type OAuthAuthOptions } from './auth';
|
|
2
|
+
import Github from './clients/github';
|
|
2
3
|
import Grafana from './clients/grafana';
|
|
3
4
|
import Linear from './clients/linear';
|
|
5
|
+
import Slack from './clients/slack';
|
|
4
6
|
import Tenderly from './clients/tenderly';
|
|
5
7
|
import { Mcp, type HttpTransportConfig, type McpTransportConfig, type StdioTransportConfig } from './core';
|
|
6
8
|
import { FileStorage, MemoryStorage, type OAuthStorage, type TokenSet } from './storage';
|
|
7
|
-
export { BearerAuth, FileStorage, Grafana, Linear, Mcp, MemoryStorage, OAuthAuth, Tenderly, type AuthProvider, type HttpTransportConfig, type McpTransportConfig, type OAuthAuthOptions, type OAuthStorage, type StdioTransportConfig, type TokenSet, };
|
|
9
|
+
export { BearerAuth, FileStorage, Github, Grafana, Linear, Mcp, MemoryStorage, OAuthAuth, Slack, Tenderly, type AuthProvider, type HttpTransportConfig, type McpTransportConfig, type OAuthAuthOptions, type OAuthStorage, type StdioTransportConfig, type TokenSet, };
|
package/mcp/index.js
CHANGED
|
@@ -884,179 +884,6 @@ class Skill {
|
|
|
884
884
|
}
|
|
885
885
|
}
|
|
886
886
|
|
|
887
|
-
// src/mcp/clients/grafana.ts
|
|
888
|
-
var EMPTY_OBJECT = {
|
|
889
|
-
type: "object",
|
|
890
|
-
properties: {},
|
|
891
|
-
additionalProperties: false
|
|
892
|
-
};
|
|
893
|
-
var TOOLS = [
|
|
894
|
-
{
|
|
895
|
-
name: "list_datasources",
|
|
896
|
-
description: "List all configured Grafana datasources.",
|
|
897
|
-
inputSchema: EMPTY_OBJECT,
|
|
898
|
-
call: (_, ctx) => request(ctx, "GET", "/api/datasources")
|
|
899
|
-
},
|
|
900
|
-
{
|
|
901
|
-
name: "get_datasource",
|
|
902
|
-
description: "Fetch a single datasource by UID.",
|
|
903
|
-
inputSchema: {
|
|
904
|
-
type: "object",
|
|
905
|
-
properties: {
|
|
906
|
-
uid: { type: "string", description: "Datasource UID." }
|
|
907
|
-
},
|
|
908
|
-
required: ["uid"],
|
|
909
|
-
additionalProperties: false
|
|
910
|
-
},
|
|
911
|
-
call: (args, ctx) => request(ctx, "GET", `/api/datasources/uid/${encodeURIComponent(String(args.uid))}`)
|
|
912
|
-
},
|
|
913
|
-
{
|
|
914
|
-
name: "query",
|
|
915
|
-
description: "Run one or more queries against Grafana datasources via /api/ds/query. Pass the query array as Grafana expects (each item needs refId and datasource.uid).",
|
|
916
|
-
inputSchema: {
|
|
917
|
-
type: "object",
|
|
918
|
-
properties: {
|
|
919
|
-
queries: {
|
|
920
|
-
type: "array",
|
|
921
|
-
description: "Array of query objects (refId, datasource, expr/range/etc.).",
|
|
922
|
-
items: { type: "object" }
|
|
923
|
-
},
|
|
924
|
-
from: {
|
|
925
|
-
type: "string",
|
|
926
|
-
description: 'Range start, e.g. "now-1h" or epoch ms as string.'
|
|
927
|
-
},
|
|
928
|
-
to: {
|
|
929
|
-
type: "string",
|
|
930
|
-
description: 'Range end, e.g. "now" or epoch ms as string.'
|
|
931
|
-
}
|
|
932
|
-
},
|
|
933
|
-
required: ["queries"],
|
|
934
|
-
additionalProperties: false
|
|
935
|
-
},
|
|
936
|
-
call: (args, ctx) => request(ctx, "POST", "/api/ds/query", {
|
|
937
|
-
queries: args.queries,
|
|
938
|
-
from: args.from ?? "now-1h",
|
|
939
|
-
to: args.to ?? "now"
|
|
940
|
-
})
|
|
941
|
-
},
|
|
942
|
-
{
|
|
943
|
-
name: "search_dashboards",
|
|
944
|
-
description: "Search dashboards by name, tag, or folder.",
|
|
945
|
-
inputSchema: {
|
|
946
|
-
type: "object",
|
|
947
|
-
properties: {
|
|
948
|
-
query: {
|
|
949
|
-
type: "string",
|
|
950
|
-
description: "Substring match on dashboard title."
|
|
951
|
-
},
|
|
952
|
-
tag: {
|
|
953
|
-
type: "array",
|
|
954
|
-
items: { type: "string" },
|
|
955
|
-
description: "Filter by tags."
|
|
956
|
-
},
|
|
957
|
-
folderUIDs: {
|
|
958
|
-
type: "array",
|
|
959
|
-
items: { type: "string" },
|
|
960
|
-
description: "Limit to specific folder UIDs."
|
|
961
|
-
},
|
|
962
|
-
limit: { type: "number", description: "Max results (default 100)." }
|
|
963
|
-
},
|
|
964
|
-
additionalProperties: false
|
|
965
|
-
},
|
|
966
|
-
call: (args, ctx) => {
|
|
967
|
-
const params = new URLSearchParams;
|
|
968
|
-
params.set("type", "dash-db");
|
|
969
|
-
if (typeof args.query === "string")
|
|
970
|
-
params.set("query", args.query);
|
|
971
|
-
if (typeof args.limit === "number")
|
|
972
|
-
params.set("limit", String(args.limit));
|
|
973
|
-
for (const tag of args.tag ?? [])
|
|
974
|
-
params.append("tag", tag);
|
|
975
|
-
for (const uid of args.folderUIDs ?? [])
|
|
976
|
-
params.append("folderUIDs", uid);
|
|
977
|
-
return request(ctx, "GET", `/api/search?${params.toString()}`);
|
|
978
|
-
}
|
|
979
|
-
},
|
|
980
|
-
{
|
|
981
|
-
name: "get_dashboard",
|
|
982
|
-
description: "Fetch a dashboard JSON by UID.",
|
|
983
|
-
inputSchema: {
|
|
984
|
-
type: "object",
|
|
985
|
-
properties: {
|
|
986
|
-
uid: { type: "string", description: "Dashboard UID." }
|
|
987
|
-
},
|
|
988
|
-
required: ["uid"],
|
|
989
|
-
additionalProperties: false
|
|
990
|
-
},
|
|
991
|
-
call: (args, ctx) => request(ctx, "GET", `/api/dashboards/uid/${encodeURIComponent(String(args.uid))}`)
|
|
992
|
-
},
|
|
993
|
-
{
|
|
994
|
-
name: "list_folders",
|
|
995
|
-
description: "List dashboard folders.",
|
|
996
|
-
inputSchema: EMPTY_OBJECT,
|
|
997
|
-
call: (_, ctx) => request(ctx, "GET", "/api/folders")
|
|
998
|
-
},
|
|
999
|
-
{
|
|
1000
|
-
name: "list_alert_rules",
|
|
1001
|
-
description: "List provisioned alert rules.",
|
|
1002
|
-
inputSchema: EMPTY_OBJECT,
|
|
1003
|
-
call: (_, ctx) => request(ctx, "GET", "/api/v1/provisioning/alert-rules")
|
|
1004
|
-
}
|
|
1005
|
-
];
|
|
1006
|
-
async function request(ctx, method, path, body) {
|
|
1007
|
-
const headers = {
|
|
1008
|
-
accept: "application/json",
|
|
1009
|
-
authorization: await ctx.auth.getHeader()
|
|
1010
|
-
};
|
|
1011
|
-
if (body !== undefined)
|
|
1012
|
-
headers["content-type"] = "application/json";
|
|
1013
|
-
const res = await fetch(`${ctx.baseUrl}${path}`, {
|
|
1014
|
-
method,
|
|
1015
|
-
headers,
|
|
1016
|
-
body: body !== undefined ? JSON.stringify(body) : undefined
|
|
1017
|
-
});
|
|
1018
|
-
const text = await res.text();
|
|
1019
|
-
if (!res.ok) {
|
|
1020
|
-
throw new Error(`Grafana ${method} ${path} failed: ${res.status} ${text}`);
|
|
1021
|
-
}
|
|
1022
|
-
if (!text)
|
|
1023
|
-
return null;
|
|
1024
|
-
try {
|
|
1025
|
-
return JSON.parse(text);
|
|
1026
|
-
} catch {
|
|
1027
|
-
return text;
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
class Mcp {
|
|
1032
|
-
baseUrl;
|
|
1033
|
-
auth;
|
|
1034
|
-
nameSpace;
|
|
1035
|
-
deferred;
|
|
1036
|
-
constructor(opts) {
|
|
1037
|
-
this.baseUrl = opts.url.replace(/\/$/, "");
|
|
1038
|
-
this.auth = new BearerAuth(opts.serviceAccountToken);
|
|
1039
|
-
this.nameSpace = opts.name ?? "grafana";
|
|
1040
|
-
this.deferred = opts.deferred ?? true;
|
|
1041
|
-
}
|
|
1042
|
-
async connect() {
|
|
1043
|
-
const ctx = { baseUrl: this.baseUrl, auth: this.auth };
|
|
1044
|
-
return TOOLS.map((def) => new Tool({
|
|
1045
|
-
name: `mcp__${this.nameSpace}__${def.name}`,
|
|
1046
|
-
description: def.description,
|
|
1047
|
-
jsonSchema: def.inputSchema,
|
|
1048
|
-
deferred: this.deferred,
|
|
1049
|
-
execute: async (input) => {
|
|
1050
|
-
const args = input ?? {};
|
|
1051
|
-
const result = await def.call(args, ctx);
|
|
1052
|
-
return typeof result === "string" ? result : JSON.stringify(result);
|
|
1053
|
-
}
|
|
1054
|
-
}));
|
|
1055
|
-
}
|
|
1056
|
-
async disconnect() {}
|
|
1057
|
-
}
|
|
1058
|
-
var grafana_default = Mcp;
|
|
1059
|
-
|
|
1060
887
|
// src/mcp/core.ts
|
|
1061
888
|
var PROTOCOL_VERSION = "2024-11-05";
|
|
1062
889
|
|
|
@@ -1256,6 +1083,11 @@ class HttpTransport {
|
|
|
1256
1083
|
await this.send(req, undefined);
|
|
1257
1084
|
}
|
|
1258
1085
|
}
|
|
1086
|
+
function validateMcpName(name) {
|
|
1087
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
|
|
1088
|
+
throw new Error(`Invalid MCP name "${name}": use only letters, digits, underscores, and hyphens.`);
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1259
1091
|
function formatContent(content) {
|
|
1260
1092
|
if (content.length === 1 && content[0]?.type === "text") {
|
|
1261
1093
|
return content[0].text ?? "";
|
|
@@ -1264,7 +1096,7 @@ function formatContent(content) {
|
|
|
1264
1096
|
`);
|
|
1265
1097
|
}
|
|
1266
1098
|
|
|
1267
|
-
class
|
|
1099
|
+
class Mcp {
|
|
1268
1100
|
name;
|
|
1269
1101
|
transport;
|
|
1270
1102
|
deferred;
|
|
@@ -1274,9 +1106,7 @@ class Mcp2 {
|
|
|
1274
1106
|
transport,
|
|
1275
1107
|
deferred
|
|
1276
1108
|
}) {
|
|
1277
|
-
|
|
1278
|
-
throw new Error(`Invalid MCP name "${name}": use only letters, digits, underscores, and hyphens.`);
|
|
1279
|
-
}
|
|
1109
|
+
validateMcpName(name);
|
|
1280
1110
|
this.name = name;
|
|
1281
1111
|
this.transport = transport;
|
|
1282
1112
|
this.deferred = deferred ?? true;
|
|
@@ -1324,10 +1154,210 @@ class Mcp2 {
|
|
|
1324
1154
|
}
|
|
1325
1155
|
}
|
|
1326
1156
|
|
|
1157
|
+
// src/mcp/clients/github.ts
|
|
1158
|
+
var GITHUB_MCP_URL = "https://api.githubcopilot.com/mcp/";
|
|
1159
|
+
|
|
1160
|
+
class Mcp2 extends Mcp {
|
|
1161
|
+
constructor(opts) {
|
|
1162
|
+
const headers = {};
|
|
1163
|
+
if (opts.toolsets?.length) {
|
|
1164
|
+
headers["X-MCP-Toolsets"] = opts.toolsets.join(",");
|
|
1165
|
+
}
|
|
1166
|
+
if (opts.readOnly) {
|
|
1167
|
+
headers["X-MCP-Readonly"] = "true";
|
|
1168
|
+
}
|
|
1169
|
+
super({
|
|
1170
|
+
name: opts.name ?? "github",
|
|
1171
|
+
deferred: opts.deferred,
|
|
1172
|
+
transport: {
|
|
1173
|
+
type: "http",
|
|
1174
|
+
url: GITHUB_MCP_URL,
|
|
1175
|
+
headers,
|
|
1176
|
+
auth: new BearerAuth(opts.token)
|
|
1177
|
+
}
|
|
1178
|
+
});
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
var github_default = Mcp2;
|
|
1182
|
+
|
|
1183
|
+
// src/mcp/clients/grafana.ts
|
|
1184
|
+
var EMPTY_OBJECT = {
|
|
1185
|
+
type: "object",
|
|
1186
|
+
properties: {},
|
|
1187
|
+
additionalProperties: false
|
|
1188
|
+
};
|
|
1189
|
+
var TOOLS = [
|
|
1190
|
+
{
|
|
1191
|
+
name: "list_datasources",
|
|
1192
|
+
description: "List all configured Grafana datasources.",
|
|
1193
|
+
inputSchema: EMPTY_OBJECT,
|
|
1194
|
+
call: (_, ctx) => request(ctx, "GET", "/api/datasources")
|
|
1195
|
+
},
|
|
1196
|
+
{
|
|
1197
|
+
name: "get_datasource",
|
|
1198
|
+
description: "Fetch a single datasource by UID.",
|
|
1199
|
+
inputSchema: {
|
|
1200
|
+
type: "object",
|
|
1201
|
+
properties: {
|
|
1202
|
+
uid: { type: "string", description: "Datasource UID." }
|
|
1203
|
+
},
|
|
1204
|
+
required: ["uid"],
|
|
1205
|
+
additionalProperties: false
|
|
1206
|
+
},
|
|
1207
|
+
call: (args, ctx) => request(ctx, "GET", `/api/datasources/uid/${encodeURIComponent(String(args.uid))}`)
|
|
1208
|
+
},
|
|
1209
|
+
{
|
|
1210
|
+
name: "query",
|
|
1211
|
+
description: "Run one or more queries against Grafana datasources via /api/ds/query. Pass the query array as Grafana expects (each item needs refId and datasource.uid).",
|
|
1212
|
+
inputSchema: {
|
|
1213
|
+
type: "object",
|
|
1214
|
+
properties: {
|
|
1215
|
+
queries: {
|
|
1216
|
+
type: "array",
|
|
1217
|
+
description: "Array of query objects (refId, datasource, expr/range/etc.).",
|
|
1218
|
+
items: { type: "object" }
|
|
1219
|
+
},
|
|
1220
|
+
from: {
|
|
1221
|
+
type: "string",
|
|
1222
|
+
description: 'Range start, e.g. "now-1h" or epoch ms as string.'
|
|
1223
|
+
},
|
|
1224
|
+
to: {
|
|
1225
|
+
type: "string",
|
|
1226
|
+
description: 'Range end, e.g. "now" or epoch ms as string.'
|
|
1227
|
+
}
|
|
1228
|
+
},
|
|
1229
|
+
required: ["queries"],
|
|
1230
|
+
additionalProperties: false
|
|
1231
|
+
},
|
|
1232
|
+
call: (args, ctx) => request(ctx, "POST", "/api/ds/query", {
|
|
1233
|
+
queries: args.queries,
|
|
1234
|
+
from: args.from ?? "now-1h",
|
|
1235
|
+
to: args.to ?? "now"
|
|
1236
|
+
})
|
|
1237
|
+
},
|
|
1238
|
+
{
|
|
1239
|
+
name: "search_dashboards",
|
|
1240
|
+
description: "Search dashboards by name, tag, or folder.",
|
|
1241
|
+
inputSchema: {
|
|
1242
|
+
type: "object",
|
|
1243
|
+
properties: {
|
|
1244
|
+
query: {
|
|
1245
|
+
type: "string",
|
|
1246
|
+
description: "Substring match on dashboard title."
|
|
1247
|
+
},
|
|
1248
|
+
tag: {
|
|
1249
|
+
type: "array",
|
|
1250
|
+
items: { type: "string" },
|
|
1251
|
+
description: "Filter by tags."
|
|
1252
|
+
},
|
|
1253
|
+
folderUIDs: {
|
|
1254
|
+
type: "array",
|
|
1255
|
+
items: { type: "string" },
|
|
1256
|
+
description: "Limit to specific folder UIDs."
|
|
1257
|
+
},
|
|
1258
|
+
limit: { type: "number", description: "Max results (default 100)." }
|
|
1259
|
+
},
|
|
1260
|
+
additionalProperties: false
|
|
1261
|
+
},
|
|
1262
|
+
call: (args, ctx) => {
|
|
1263
|
+
const params = new URLSearchParams;
|
|
1264
|
+
params.set("type", "dash-db");
|
|
1265
|
+
if (typeof args.query === "string")
|
|
1266
|
+
params.set("query", args.query);
|
|
1267
|
+
if (typeof args.limit === "number")
|
|
1268
|
+
params.set("limit", String(args.limit));
|
|
1269
|
+
for (const tag of args.tag ?? [])
|
|
1270
|
+
params.append("tag", tag);
|
|
1271
|
+
for (const uid of args.folderUIDs ?? [])
|
|
1272
|
+
params.append("folderUIDs", uid);
|
|
1273
|
+
return request(ctx, "GET", `/api/search?${params.toString()}`);
|
|
1274
|
+
}
|
|
1275
|
+
},
|
|
1276
|
+
{
|
|
1277
|
+
name: "get_dashboard",
|
|
1278
|
+
description: "Fetch a dashboard JSON by UID.",
|
|
1279
|
+
inputSchema: {
|
|
1280
|
+
type: "object",
|
|
1281
|
+
properties: {
|
|
1282
|
+
uid: { type: "string", description: "Dashboard UID." }
|
|
1283
|
+
},
|
|
1284
|
+
required: ["uid"],
|
|
1285
|
+
additionalProperties: false
|
|
1286
|
+
},
|
|
1287
|
+
call: (args, ctx) => request(ctx, "GET", `/api/dashboards/uid/${encodeURIComponent(String(args.uid))}`)
|
|
1288
|
+
},
|
|
1289
|
+
{
|
|
1290
|
+
name: "list_folders",
|
|
1291
|
+
description: "List dashboard folders.",
|
|
1292
|
+
inputSchema: EMPTY_OBJECT,
|
|
1293
|
+
call: (_, ctx) => request(ctx, "GET", "/api/folders")
|
|
1294
|
+
},
|
|
1295
|
+
{
|
|
1296
|
+
name: "list_alert_rules",
|
|
1297
|
+
description: "List provisioned alert rules.",
|
|
1298
|
+
inputSchema: EMPTY_OBJECT,
|
|
1299
|
+
call: (_, ctx) => request(ctx, "GET", "/api/v1/provisioning/alert-rules")
|
|
1300
|
+
}
|
|
1301
|
+
];
|
|
1302
|
+
async function request(ctx, method, path, body) {
|
|
1303
|
+
const headers = {
|
|
1304
|
+
accept: "application/json",
|
|
1305
|
+
authorization: await ctx.auth.getHeader()
|
|
1306
|
+
};
|
|
1307
|
+
if (body !== undefined)
|
|
1308
|
+
headers["content-type"] = "application/json";
|
|
1309
|
+
const res = await fetch(`${ctx.baseUrl}${path}`, {
|
|
1310
|
+
method,
|
|
1311
|
+
headers,
|
|
1312
|
+
body: body !== undefined ? JSON.stringify(body) : undefined
|
|
1313
|
+
});
|
|
1314
|
+
const text = await res.text();
|
|
1315
|
+
if (!res.ok) {
|
|
1316
|
+
throw new Error(`Grafana ${method} ${path} failed: ${res.status} ${text}`);
|
|
1317
|
+
}
|
|
1318
|
+
if (!text)
|
|
1319
|
+
return null;
|
|
1320
|
+
try {
|
|
1321
|
+
return JSON.parse(text);
|
|
1322
|
+
} catch {
|
|
1323
|
+
return text;
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
class Mcp3 {
|
|
1328
|
+
baseUrl;
|
|
1329
|
+
auth;
|
|
1330
|
+
nameSpace;
|
|
1331
|
+
deferred;
|
|
1332
|
+
constructor(opts) {
|
|
1333
|
+
this.baseUrl = opts.url.replace(/\/$/, "");
|
|
1334
|
+
this.auth = new BearerAuth(opts.serviceAccountToken);
|
|
1335
|
+
this.nameSpace = opts.name ?? "grafana";
|
|
1336
|
+
validateMcpName(this.nameSpace);
|
|
1337
|
+
this.deferred = opts.deferred ?? true;
|
|
1338
|
+
}
|
|
1339
|
+
async connect() {
|
|
1340
|
+
const ctx = { baseUrl: this.baseUrl, auth: this.auth };
|
|
1341
|
+
return TOOLS.map((def) => new Tool({
|
|
1342
|
+
name: `mcp__${this.nameSpace}__${def.name}`,
|
|
1343
|
+
description: def.description,
|
|
1344
|
+
jsonSchema: def.inputSchema,
|
|
1345
|
+
deferred: this.deferred,
|
|
1346
|
+
execute: async (input) => {
|
|
1347
|
+
const args = input ?? {};
|
|
1348
|
+
const result = await def.call(args, ctx);
|
|
1349
|
+
return typeof result === "string" ? result : JSON.stringify(result);
|
|
1350
|
+
}
|
|
1351
|
+
}));
|
|
1352
|
+
}
|
|
1353
|
+
async disconnect() {}
|
|
1354
|
+
}
|
|
1355
|
+
var grafana_default = Mcp3;
|
|
1356
|
+
|
|
1327
1357
|
// src/mcp/clients/linear.ts
|
|
1328
1358
|
var LINEAR_MCP_URL = "https://mcp.linear.app/mcp";
|
|
1329
1359
|
|
|
1330
|
-
class
|
|
1360
|
+
class Mcp4 extends Mcp {
|
|
1331
1361
|
constructor(opts) {
|
|
1332
1362
|
super({
|
|
1333
1363
|
name: opts.name ?? "linear",
|
|
@@ -1339,12 +1369,217 @@ class Mcp3 extends Mcp2 {
|
|
|
1339
1369
|
});
|
|
1340
1370
|
}
|
|
1341
1371
|
}
|
|
1342
|
-
var linear_default =
|
|
1372
|
+
var linear_default = Mcp4;
|
|
1373
|
+
|
|
1374
|
+
// src/mcp/clients/slack.ts
|
|
1375
|
+
var SLACK_API_URL = "https://slack.com/api";
|
|
1376
|
+
var TOOLS2 = [
|
|
1377
|
+
{
|
|
1378
|
+
name: "post_message",
|
|
1379
|
+
description: "Post a message to a Slack channel.",
|
|
1380
|
+
inputSchema: {
|
|
1381
|
+
type: "object",
|
|
1382
|
+
properties: {
|
|
1383
|
+
channel: {
|
|
1384
|
+
type: "string",
|
|
1385
|
+
description: "Channel ID (e.g. C012AB3CD) or name (e.g. #general)."
|
|
1386
|
+
},
|
|
1387
|
+
text: { type: "string", description: "Message text." }
|
|
1388
|
+
},
|
|
1389
|
+
required: ["channel", "text"],
|
|
1390
|
+
additionalProperties: false
|
|
1391
|
+
},
|
|
1392
|
+
call: (args, ctx) => request2(ctx, "chat.postMessage", {
|
|
1393
|
+
channel: args.channel,
|
|
1394
|
+
text: args.text
|
|
1395
|
+
})
|
|
1396
|
+
},
|
|
1397
|
+
{
|
|
1398
|
+
name: "reply_in_thread",
|
|
1399
|
+
description: "Reply to an existing message thread in a Slack channel.",
|
|
1400
|
+
inputSchema: {
|
|
1401
|
+
type: "object",
|
|
1402
|
+
properties: {
|
|
1403
|
+
channel: { type: "string", description: "Channel ID or name." },
|
|
1404
|
+
thread_ts: {
|
|
1405
|
+
type: "string",
|
|
1406
|
+
description: "Timestamp (ts) of the parent message to reply to."
|
|
1407
|
+
},
|
|
1408
|
+
text: { type: "string", description: "Reply text." }
|
|
1409
|
+
},
|
|
1410
|
+
required: ["channel", "thread_ts", "text"],
|
|
1411
|
+
additionalProperties: false
|
|
1412
|
+
},
|
|
1413
|
+
call: (args, ctx) => request2(ctx, "chat.postMessage", {
|
|
1414
|
+
channel: args.channel,
|
|
1415
|
+
thread_ts: args.thread_ts,
|
|
1416
|
+
text: args.text
|
|
1417
|
+
})
|
|
1418
|
+
},
|
|
1419
|
+
{
|
|
1420
|
+
name: "list_channels",
|
|
1421
|
+
description: "List channels in the workspace.",
|
|
1422
|
+
inputSchema: {
|
|
1423
|
+
type: "object",
|
|
1424
|
+
properties: {
|
|
1425
|
+
types: {
|
|
1426
|
+
type: "string",
|
|
1427
|
+
description: 'Comma-separated channel types (default "public_channel").'
|
|
1428
|
+
},
|
|
1429
|
+
limit: { type: "number", description: "Max results (default 100)." },
|
|
1430
|
+
cursor: { type: "string", description: "Pagination cursor." },
|
|
1431
|
+
exclude_archived: {
|
|
1432
|
+
type: "boolean",
|
|
1433
|
+
description: "Omit archived channels (default true)."
|
|
1434
|
+
}
|
|
1435
|
+
},
|
|
1436
|
+
additionalProperties: false
|
|
1437
|
+
},
|
|
1438
|
+
call: (args, ctx) => request2(ctx, "conversations.list", {
|
|
1439
|
+
types: args.types ?? "public_channel",
|
|
1440
|
+
limit: args.limit ?? 100,
|
|
1441
|
+
cursor: args.cursor,
|
|
1442
|
+
exclude_archived: args.exclude_archived ?? true
|
|
1443
|
+
})
|
|
1444
|
+
},
|
|
1445
|
+
{
|
|
1446
|
+
name: "get_channel_history",
|
|
1447
|
+
description: "Fetch recent messages from a channel.",
|
|
1448
|
+
inputSchema: {
|
|
1449
|
+
type: "object",
|
|
1450
|
+
properties: {
|
|
1451
|
+
channel: { type: "string", description: "Channel ID." },
|
|
1452
|
+
limit: { type: "number", description: "Max messages (default 100)." },
|
|
1453
|
+
cursor: { type: "string", description: "Pagination cursor." },
|
|
1454
|
+
oldest: {
|
|
1455
|
+
type: "string",
|
|
1456
|
+
description: "Only messages after this ts."
|
|
1457
|
+
},
|
|
1458
|
+
latest: {
|
|
1459
|
+
type: "string",
|
|
1460
|
+
description: "Only messages before this ts."
|
|
1461
|
+
}
|
|
1462
|
+
},
|
|
1463
|
+
required: ["channel"],
|
|
1464
|
+
additionalProperties: false
|
|
1465
|
+
},
|
|
1466
|
+
call: (args, ctx) => request2(ctx, "conversations.history", {
|
|
1467
|
+
channel: args.channel,
|
|
1468
|
+
limit: args.limit ?? 100,
|
|
1469
|
+
cursor: args.cursor,
|
|
1470
|
+
oldest: args.oldest,
|
|
1471
|
+
latest: args.latest
|
|
1472
|
+
})
|
|
1473
|
+
},
|
|
1474
|
+
{
|
|
1475
|
+
name: "list_users",
|
|
1476
|
+
description: "List users in the workspace.",
|
|
1477
|
+
inputSchema: {
|
|
1478
|
+
type: "object",
|
|
1479
|
+
properties: {
|
|
1480
|
+
limit: { type: "number", description: "Max results (default 100)." },
|
|
1481
|
+
cursor: { type: "string", description: "Pagination cursor." }
|
|
1482
|
+
},
|
|
1483
|
+
additionalProperties: false
|
|
1484
|
+
},
|
|
1485
|
+
call: (args, ctx) => request2(ctx, "users.list", {
|
|
1486
|
+
limit: args.limit ?? 100,
|
|
1487
|
+
cursor: args.cursor
|
|
1488
|
+
})
|
|
1489
|
+
},
|
|
1490
|
+
{
|
|
1491
|
+
name: "get_user",
|
|
1492
|
+
description: "Fetch a single user by ID.",
|
|
1493
|
+
inputSchema: {
|
|
1494
|
+
type: "object",
|
|
1495
|
+
properties: {
|
|
1496
|
+
user: { type: "string", description: "User ID (e.g. U012AB3CD)." }
|
|
1497
|
+
},
|
|
1498
|
+
required: ["user"],
|
|
1499
|
+
additionalProperties: false
|
|
1500
|
+
},
|
|
1501
|
+
call: (args, ctx) => request2(ctx, "users.info", { user: args.user })
|
|
1502
|
+
},
|
|
1503
|
+
{
|
|
1504
|
+
name: "add_reaction",
|
|
1505
|
+
description: "Add an emoji reaction to a message.",
|
|
1506
|
+
inputSchema: {
|
|
1507
|
+
type: "object",
|
|
1508
|
+
properties: {
|
|
1509
|
+
channel: { type: "string", description: "Channel ID." },
|
|
1510
|
+
timestamp: {
|
|
1511
|
+
type: "string",
|
|
1512
|
+
description: "Timestamp (ts) of the target message."
|
|
1513
|
+
},
|
|
1514
|
+
name: {
|
|
1515
|
+
type: "string",
|
|
1516
|
+
description: 'Emoji name without colons (e.g. "thumbsup").'
|
|
1517
|
+
}
|
|
1518
|
+
},
|
|
1519
|
+
required: ["channel", "timestamp", "name"],
|
|
1520
|
+
additionalProperties: false
|
|
1521
|
+
},
|
|
1522
|
+
call: (args, ctx) => request2(ctx, "reactions.add", {
|
|
1523
|
+
channel: args.channel,
|
|
1524
|
+
timestamp: args.timestamp,
|
|
1525
|
+
name: args.name
|
|
1526
|
+
})
|
|
1527
|
+
}
|
|
1528
|
+
];
|
|
1529
|
+
async function request2(ctx, method, params) {
|
|
1530
|
+
const body = new URLSearchParams;
|
|
1531
|
+
for (const [key, value] of Object.entries(params)) {
|
|
1532
|
+
if (value === undefined || value === null)
|
|
1533
|
+
continue;
|
|
1534
|
+
body.set(key, String(value));
|
|
1535
|
+
}
|
|
1536
|
+
const res = await fetch(`${SLACK_API_URL}/${method}`, {
|
|
1537
|
+
method: "POST",
|
|
1538
|
+
headers: {
|
|
1539
|
+
authorization: await ctx.auth.getHeader(),
|
|
1540
|
+
"content-type": "application/x-www-form-urlencoded"
|
|
1541
|
+
},
|
|
1542
|
+
body
|
|
1543
|
+
});
|
|
1544
|
+
const json = await res.json();
|
|
1545
|
+
if (!json.ok) {
|
|
1546
|
+
throw new Error(`Slack ${method} failed: ${json.error ?? res.status}`);
|
|
1547
|
+
}
|
|
1548
|
+
return json;
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
class Mcp5 {
|
|
1552
|
+
auth;
|
|
1553
|
+
nameSpace;
|
|
1554
|
+
deferred;
|
|
1555
|
+
constructor(opts) {
|
|
1556
|
+
this.auth = new BearerAuth(opts.botToken);
|
|
1557
|
+
this.nameSpace = opts.name ?? "slack";
|
|
1558
|
+
validateMcpName(this.nameSpace);
|
|
1559
|
+
this.deferred = opts.deferred ?? true;
|
|
1560
|
+
}
|
|
1561
|
+
async connect() {
|
|
1562
|
+
const ctx = { auth: this.auth };
|
|
1563
|
+
return TOOLS2.map((def) => new Tool({
|
|
1564
|
+
name: `mcp__${this.nameSpace}__${def.name}`,
|
|
1565
|
+
description: def.description,
|
|
1566
|
+
jsonSchema: def.inputSchema,
|
|
1567
|
+
deferred: this.deferred,
|
|
1568
|
+
execute: async (input) => {
|
|
1569
|
+
const args = input ?? {};
|
|
1570
|
+
const result = await def.call(args, ctx);
|
|
1571
|
+
return typeof result === "string" ? result : JSON.stringify(result);
|
|
1572
|
+
}
|
|
1573
|
+
}));
|
|
1574
|
+
}
|
|
1575
|
+
async disconnect() {}
|
|
1576
|
+
}
|
|
1577
|
+
var slack_default = Mcp5;
|
|
1343
1578
|
|
|
1344
1579
|
// src/mcp/clients/tenderly.ts
|
|
1345
1580
|
var TENDERLY_MCP_URL = "https://mcp.tenderly.co/mcp";
|
|
1346
1581
|
|
|
1347
|
-
class
|
|
1582
|
+
class Mcp6 extends Mcp {
|
|
1348
1583
|
constructor(opts) {
|
|
1349
1584
|
const auth = new OAuthAuth({
|
|
1350
1585
|
serverUrl: TENDERLY_MCP_URL,
|
|
@@ -1362,14 +1597,16 @@ class Mcp4 extends Mcp2 {
|
|
|
1362
1597
|
});
|
|
1363
1598
|
}
|
|
1364
1599
|
}
|
|
1365
|
-
var tenderly_default =
|
|
1600
|
+
var tenderly_default = Mcp6;
|
|
1366
1601
|
export {
|
|
1367
1602
|
tenderly_default as Tenderly,
|
|
1603
|
+
slack_default as Slack,
|
|
1368
1604
|
OAuthAuth,
|
|
1369
1605
|
MemoryStorage,
|
|
1370
|
-
|
|
1606
|
+
Mcp,
|
|
1371
1607
|
linear_default as Linear,
|
|
1372
1608
|
grafana_default as Grafana,
|
|
1609
|
+
github_default as Github,
|
|
1373
1610
|
FileStorage,
|
|
1374
1611
|
BearerAuth
|
|
1375
1612
|
};
|