@y2-intel/mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/LICENSE +190 -0
- package/README.md +136 -0
- package/SECURITY.md +12 -0
- package/dist/config.d.ts +14 -0
- package/dist/config.js +47 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.js +25 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/docs.d.ts +3 -0
- package/dist/resources/docs.js +50 -0
- package/dist/resources/docs.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +26 -0
- package/dist/server.js.map +1 -0
- package/dist/stream.d.ts +1 -0
- package/dist/stream.js +74 -0
- package/dist/stream.js.map +1 -0
- package/dist/text.d.ts +16 -0
- package/dist/text.js +21 -0
- package/dist/text.js.map +1 -0
- package/dist/tools/ask-agent.d.ts +4 -0
- package/dist/tools/ask-agent.js +26 -0
- package/dist/tools/ask-agent.js.map +1 -0
- package/dist/tools/news.d.ts +4 -0
- package/dist/tools/news.js +33 -0
- package/dist/tools/news.js.map +1 -0
- package/dist/tools/openapi.d.ts +5 -0
- package/dist/tools/openapi.js +67 -0
- package/dist/tools/openapi.js.map +1 -0
- package/dist/tools/prompts.d.ts +2 -0
- package/dist/tools/prompts.js +52 -0
- package/dist/tools/prompts.js.map +1 -0
- package/dist/tools/reports.d.ts +4 -0
- package/dist/tools/reports.js +35 -0
- package/dist/tools/reports.js.map +1 -0
- package/dist/y2-client.d.ts +32 -0
- package/dist/y2-client.js +144 -0
- package/dist/y2-client.js.map +1 -0
- package/examples/claude-code.md +22 -0
- package/examples/claude-desktop.json +12 -0
- package/examples/codex.md +28 -0
- package/examples/mcp-inspector.md +53 -0
- package/package.json +71 -0
- package/server.json +17 -0
package/dist/stream.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
function parseJsonPayload(payload) {
|
|
2
|
+
try {
|
|
3
|
+
return JSON.parse(payload);
|
|
4
|
+
}
|
|
5
|
+
catch {
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
function textFromObject(value) {
|
|
10
|
+
if (typeof value === "string")
|
|
11
|
+
return value;
|
|
12
|
+
if (!value || typeof value !== "object")
|
|
13
|
+
return undefined;
|
|
14
|
+
const record = value;
|
|
15
|
+
if (typeof record.text === "string")
|
|
16
|
+
return record.text;
|
|
17
|
+
if (typeof record.textDelta === "string")
|
|
18
|
+
return record.textDelta;
|
|
19
|
+
if (typeof record.delta === "string")
|
|
20
|
+
return record.delta;
|
|
21
|
+
if (Array.isArray(record.choices)) {
|
|
22
|
+
return record.choices
|
|
23
|
+
.map((choice) => {
|
|
24
|
+
if (!choice || typeof choice !== "object")
|
|
25
|
+
return "";
|
|
26
|
+
const choiceRecord = choice;
|
|
27
|
+
if (typeof choiceRecord.text === "string")
|
|
28
|
+
return choiceRecord.text;
|
|
29
|
+
if (choiceRecord.delta && typeof choiceRecord.delta === "object") {
|
|
30
|
+
const delta = choiceRecord.delta;
|
|
31
|
+
return typeof delta.content === "string" ? delta.content : "";
|
|
32
|
+
}
|
|
33
|
+
return "";
|
|
34
|
+
})
|
|
35
|
+
.join("");
|
|
36
|
+
}
|
|
37
|
+
if (Array.isArray(record.content)) {
|
|
38
|
+
return record.content
|
|
39
|
+
.map((part) => {
|
|
40
|
+
if (!part || typeof part !== "object")
|
|
41
|
+
return "";
|
|
42
|
+
const partRecord = part;
|
|
43
|
+
return typeof partRecord.text === "string" ? partRecord.text : "";
|
|
44
|
+
})
|
|
45
|
+
.join("");
|
|
46
|
+
}
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
function textFromPayload(payload) {
|
|
50
|
+
if (!payload || payload === "[DONE]")
|
|
51
|
+
return undefined;
|
|
52
|
+
const aiSdkDataStream = payload.match(/^(\d+):(.*)$/s);
|
|
53
|
+
if (aiSdkDataStream) {
|
|
54
|
+
const [, code, encoded] = aiSdkDataStream;
|
|
55
|
+
if (code !== "0")
|
|
56
|
+
return undefined;
|
|
57
|
+
return textFromObject(parseJsonPayload(encoded));
|
|
58
|
+
}
|
|
59
|
+
return textFromObject(parseJsonPayload(payload));
|
|
60
|
+
}
|
|
61
|
+
export function extractAssistantTextFromStream(raw) {
|
|
62
|
+
const chunks = [];
|
|
63
|
+
for (const originalLine of raw.split(/\r?\n/)) {
|
|
64
|
+
const line = originalLine.trim();
|
|
65
|
+
if (!line || line.startsWith("event:"))
|
|
66
|
+
continue;
|
|
67
|
+
const payload = line.startsWith("data:") ? line.slice("data:".length).trim() : line;
|
|
68
|
+
const text = textFromPayload(payload);
|
|
69
|
+
if (text)
|
|
70
|
+
chunks.push(text);
|
|
71
|
+
}
|
|
72
|
+
return chunks.join("").trim();
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"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"}
|
package/dist/text.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Y2McpConfig } from "./config.js";
|
|
2
|
+
export declare function limitText(text: string, maxChars: number): string;
|
|
3
|
+
export declare function formatJson(value: unknown, config: Y2McpConfig): string;
|
|
4
|
+
export declare function textResult(text: string): {
|
|
5
|
+
content: {
|
|
6
|
+
type: "text";
|
|
7
|
+
text: string;
|
|
8
|
+
}[];
|
|
9
|
+
};
|
|
10
|
+
export declare function errorResult(error: unknown, config: Y2McpConfig): {
|
|
11
|
+
isError: boolean;
|
|
12
|
+
content: {
|
|
13
|
+
type: "text";
|
|
14
|
+
text: string;
|
|
15
|
+
}[];
|
|
16
|
+
};
|
package/dist/text.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { formatToolError } from "./errors.js";
|
|
2
|
+
export function limitText(text, maxChars) {
|
|
3
|
+
if (text.length <= maxChars)
|
|
4
|
+
return text;
|
|
5
|
+
return `${text.slice(0, maxChars)}\n\n[truncated ${text.length - maxChars} characters]`;
|
|
6
|
+
}
|
|
7
|
+
export function formatJson(value, config) {
|
|
8
|
+
return limitText(JSON.stringify(value, null, 2), config.maxResponseChars);
|
|
9
|
+
}
|
|
10
|
+
export function textResult(text) {
|
|
11
|
+
return {
|
|
12
|
+
content: [{ type: "text", text }],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function errorResult(error, config) {
|
|
16
|
+
return {
|
|
17
|
+
isError: true,
|
|
18
|
+
content: [{ type: "text", text: formatToolError(error, config) }],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=text.js.map
|
package/dist/text.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../src/text.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,QAAgB;IACvD,IAAI,IAAI,CAAC,MAAM,IAAI,QAAQ;QAAE,OAAO,IAAI,CAAC;IACzC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,kBAAkB,IAAI,CAAC,MAAM,GAAG,QAAQ,cAAc,CAAC;AACzF,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAc,EAAE,MAAmB;IAC7D,OAAO,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACtC,OAAO;QACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;KAC1C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc,EAAE,MAAmB;IAC9D,OAAO;QACN,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;KAC1E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { Y2McpConfig } from "../config.js";
|
|
3
|
+
import type { Y2Client } from "../y2-client.js";
|
|
4
|
+
export declare function registerAgentTools(server: McpServer, client: Y2Client, config: Y2McpConfig): void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { errorResult, textResult } from "../text.js";
|
|
3
|
+
const askAgentInput = {
|
|
4
|
+
message: z.string().min(1).max(20_000).describe("Message to send to Agent Y2."),
|
|
5
|
+
threadId: z.string().min(1).max(256).optional().describe("Existing Y2 chat thread ID."),
|
|
6
|
+
source: z.string().min(1).max(128).optional().describe("Optional integration source label."),
|
|
7
|
+
externalUserId: z.string().min(1).max(256).optional(),
|
|
8
|
+
externalThreadId: z.string().min(1).max(256).optional(),
|
|
9
|
+
};
|
|
10
|
+
export function registerAgentTools(server, client, config) {
|
|
11
|
+
server.tool("y2_ask_agent", "Ask Agent Y2. Requires agent:y2. Agent Y2 may use Y2 account tools and mutate resources within the API key's plan and scopes.", askAgentInput, async (input) => {
|
|
12
|
+
try {
|
|
13
|
+
const response = await client.askAgent(input);
|
|
14
|
+
return textResult([
|
|
15
|
+
response.text || "Agent Y2 returned an empty response.",
|
|
16
|
+
"",
|
|
17
|
+
`Thread ID: ${response.threadId ?? "not returned"}`,
|
|
18
|
+
`Status: ${response.status}`,
|
|
19
|
+
].join("\n"));
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
return errorResult(error, config);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=ask-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask-agent.js","sourceRoot":"","sources":["../../src/tools/ask-agent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGrD,MAAM,aAAa,GAAG;IACrB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,8BAA8B,CAAC;IAC/E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;IACvF,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;IAC5F,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IACrD,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;CACvD,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,MAAgB,EAAE,MAAmB;IAC1F,MAAM,CAAC,IAAI,CACV,cAAc,EACd,+HAA+H,EAC/H,aAAa,EACb,KAAK,EAAE,KAAK,EAAE,EAAE;QACf,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC9C,OAAO,UAAU,CAChB;gBACC,QAAQ,CAAC,IAAI,IAAI,sCAAsC;gBACvD,EAAE;gBACF,cAAc,QAAQ,CAAC,QAAQ,IAAI,cAAc,EAAE;gBACnD,WAAW,QAAQ,CAAC,MAAM,EAAE;aAC5B,CAAC,IAAI,CAAC,IAAI,CAAC,CACZ,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACnC,CAAC;IACF,CAAC,CACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { Y2McpConfig } from "../config.js";
|
|
3
|
+
import type { Y2Client } from "../y2-client.js";
|
|
4
|
+
export declare function registerNewsTools(server: McpServer, client: Y2Client, config: Y2McpConfig): void;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { errorResult, formatJson, textResult } from "../text.js";
|
|
3
|
+
const newsInput = {
|
|
4
|
+
topics: z
|
|
5
|
+
.array(z.string().min(1).max(64))
|
|
6
|
+
.max(12)
|
|
7
|
+
.optional()
|
|
8
|
+
.describe("Optional list of Y2 news topics."),
|
|
9
|
+
limit: z
|
|
10
|
+
.number()
|
|
11
|
+
.int()
|
|
12
|
+
.min(1)
|
|
13
|
+
.max(200)
|
|
14
|
+
.default(50)
|
|
15
|
+
.describe("Maximum news items to return. Y2 API caps this at 200."),
|
|
16
|
+
};
|
|
17
|
+
export function registerNewsTools(server, client, config) {
|
|
18
|
+
server.tool("y2_list_news", "List bounded Y2 News Terminal items. Requires news:read.", newsInput, async ({ topics, limit }) => {
|
|
19
|
+
try {
|
|
20
|
+
const data = await client.requestJson("/api/v1/news", {
|
|
21
|
+
query: {
|
|
22
|
+
limit: String(limit),
|
|
23
|
+
...(topics?.length ? { topics: topics.join(",") } : {}),
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
return textResult(formatJson(data, config));
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
return errorResult(error, config);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=news.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"news.js","sourceRoot":"","sources":["../../src/tools/news.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGjE,MAAM,SAAS,GAAG;IACjB,MAAM,EAAE,CAAC;SACP,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;SAChC,GAAG,CAAC,EAAE,CAAC;SACP,QAAQ,EAAE;SACV,QAAQ,CAAC,kCAAkC,CAAC;IAC9C,KAAK,EAAE,CAAC;SACN,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,GAAG,CAAC;SACR,OAAO,CAAC,EAAE,CAAC;SACX,QAAQ,CAAC,wDAAwD,CAAC;CACpE,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,MAAiB,EAAE,MAAgB,EAAE,MAAmB;IACzF,MAAM,CAAC,IAAI,CACV,cAAc,EACd,0DAA0D,EAC1D,SAAS,EACT,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;QAC3B,IAAI,CAAC;YACJ,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,cAAc,EAAE;gBACrD,KAAK,EAAE;oBACN,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;oBACpB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACvD;aACD,CAAC,CAAC;YACH,OAAO,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACnC,CAAC;IACF,CAAC,CACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { Y2McpConfig } from "../config.js";
|
|
3
|
+
import type { Y2Client } from "../y2-client.js";
|
|
4
|
+
export declare function candidateOpenApiPaths(input: string): string[];
|
|
5
|
+
export declare function registerOpenApiTools(server: McpServer, client: Y2Client, config: Y2McpConfig): void;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { parse } from "yaml";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { errorResult, formatJson, textResult } from "../text.js";
|
|
4
|
+
const operationInput = {
|
|
5
|
+
operationId: z.string().min(1).max(128).optional(),
|
|
6
|
+
path: z.string().min(1).max(512).optional(),
|
|
7
|
+
method: z.enum(["get", "post", "put", "patch", "delete"]).optional(),
|
|
8
|
+
};
|
|
9
|
+
function asRecord(value) {
|
|
10
|
+
return value && typeof value === "object" ? value : {};
|
|
11
|
+
}
|
|
12
|
+
function findByOperationId(openApi, operationId) {
|
|
13
|
+
const paths = asRecord(asRecord(openApi).paths);
|
|
14
|
+
for (const [path, pathItem] of Object.entries(paths)) {
|
|
15
|
+
for (const [method, operation] of Object.entries(asRecord(pathItem))) {
|
|
16
|
+
if (asRecord(operation).operationId === operationId) {
|
|
17
|
+
return { path, method, operation };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
export function candidateOpenApiPaths(input) {
|
|
24
|
+
const pathname = (() => {
|
|
25
|
+
try {
|
|
26
|
+
return new URL(input).pathname;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return input.startsWith("/") ? input : `/${input}`;
|
|
30
|
+
}
|
|
31
|
+
})();
|
|
32
|
+
const candidates = [pathname];
|
|
33
|
+
if (pathname.startsWith("/api/v1/")) {
|
|
34
|
+
candidates.push(pathname.slice("/api/v1".length));
|
|
35
|
+
}
|
|
36
|
+
return [...new Set(candidates)];
|
|
37
|
+
}
|
|
38
|
+
function findByPath(openApi, path, method) {
|
|
39
|
+
const paths = asRecord(asRecord(openApi).paths);
|
|
40
|
+
for (const candidatePath of candidateOpenApiPaths(path)) {
|
|
41
|
+
const operation = asRecord(paths[candidatePath])[method];
|
|
42
|
+
if (operation)
|
|
43
|
+
return { path: candidatePath, method, operation };
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
export function registerOpenApiTools(server, client, config) {
|
|
48
|
+
server.tool("y2_get_openapi_operation", "Return one Y2 OpenAPI operation by operationId or path plus method. Does not require Y2_API_KEY.", operationInput, async ({ operationId, path, method }) => {
|
|
49
|
+
try {
|
|
50
|
+
if (!operationId && (!path || !method)) {
|
|
51
|
+
throw new Error("Provide operationId or both path and method.");
|
|
52
|
+
}
|
|
53
|
+
const spec = parse(await client.fetchDocsText("/api/openapi.yaml"));
|
|
54
|
+
const operation = operationId
|
|
55
|
+
? findByOperationId(spec, operationId)
|
|
56
|
+
: findByPath(spec, path ?? "", method ?? "");
|
|
57
|
+
if (!operation) {
|
|
58
|
+
throw new Error("OpenAPI operation not found.");
|
|
59
|
+
}
|
|
60
|
+
return textResult(formatJson(operation, config));
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
return errorResult(error, config);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=openapi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi.js","sourceRoot":"","sources":["../../src/tools/openapi.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerPrompts(server) {
|
|
3
|
+
server.prompt("integrate-y2-api", { task: z.string().optional() }, ({ task }) => ({
|
|
4
|
+
messages: [
|
|
5
|
+
{
|
|
6
|
+
role: "user",
|
|
7
|
+
content: {
|
|
8
|
+
type: "text",
|
|
9
|
+
text: [
|
|
10
|
+
"Integrate the Y2 API into this codebase.",
|
|
11
|
+
"Read y2://docs/index, y2://quickstart, and y2://openapi first.",
|
|
12
|
+
"Keep Y2_API_KEY server-side or in local MCP environment only.",
|
|
13
|
+
"Choose the narrowest scopes needed and handle 401, 402, 403, 429, and 5xx.",
|
|
14
|
+
task ? `Task: ${task}` : "",
|
|
15
|
+
]
|
|
16
|
+
.filter(Boolean)
|
|
17
|
+
.join("\n"),
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
}));
|
|
22
|
+
server.prompt("ask-y2-brief", { topic: z.string().min(1).max(256) }, ({ topic }) => ({
|
|
23
|
+
messages: [
|
|
24
|
+
{
|
|
25
|
+
role: "user",
|
|
26
|
+
content: {
|
|
27
|
+
type: "text",
|
|
28
|
+
text: `Ask Agent Y2 for a concise intelligence brief about: ${topic}`,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
}));
|
|
33
|
+
server.prompt("debug-y2-api-call", { statusCode: z.string().optional(), endpoint: z.string().optional() }, ({ statusCode, endpoint }) => ({
|
|
34
|
+
messages: [
|
|
35
|
+
{
|
|
36
|
+
role: "user",
|
|
37
|
+
content: {
|
|
38
|
+
type: "text",
|
|
39
|
+
text: [
|
|
40
|
+
"Debug this Y2 API integration before guessing.",
|
|
41
|
+
"Check endpoint, method, scopes, API key placement, status code, rate-limit headers, and response body.",
|
|
42
|
+
endpoint ? `Endpoint: ${endpoint}` : "",
|
|
43
|
+
statusCode ? `Status code: ${statusCode}` : "",
|
|
44
|
+
]
|
|
45
|
+
.filter(Boolean)
|
|
46
|
+
.join("\n"),
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/tools/prompts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,UAAU,eAAe,CAAC,MAAiB;IAChD,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACjF,QAAQ,EAAE;YACT;gBACC,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE;wBACL,0CAA0C;wBAC1C,gEAAgE;wBAChE,+DAA+D;wBAC/D,4EAA4E;wBAC5E,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE;qBAC3B;yBACC,MAAM,CAAC,OAAO,CAAC;yBACf,IAAI,CAAC,IAAI,CAAC;iBACZ;aACD;SACD;KACD,CAAC,CAAC,CAAC;IAEJ,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QACpF,QAAQ,EAAE;YACT;gBACC,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,wDAAwD,KAAK,EAAE;iBACrE;aACD;SACD;KACD,CAAC,CAAC,CAAC;IAEJ,MAAM,CAAC,MAAM,CACZ,mBAAmB,EACnB,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,EACtE,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QAC9B,QAAQ,EAAE;YACT;gBACC,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE;wBACL,gDAAgD;wBAChD,wGAAwG;wBACxG,QAAQ,CAAC,CAAC,CAAC,aAAa,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE;wBACvC,UAAU,CAAC,CAAC,CAAC,gBAAgB,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE;qBAC9C;yBACC,MAAM,CAAC,OAAO,CAAC;yBACf,IAAI,CAAC,IAAI,CAAC;iBACZ;aACD;SACD;KACD,CAAC,CACF,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { Y2McpConfig } from "../config.js";
|
|
3
|
+
import type { Y2Client } from "../y2-client.js";
|
|
4
|
+
export declare function registerReportTools(server: McpServer, client: Y2Client, config: Y2McpConfig): void;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { errorResult, formatJson, textResult } from "../text.js";
|
|
3
|
+
const listReportsInput = {
|
|
4
|
+
profileId: z.string().min(1).max(256).optional(),
|
|
5
|
+
limit: z.number().int().min(1).max(5).default(5),
|
|
6
|
+
};
|
|
7
|
+
const getReportInput = {
|
|
8
|
+
reportId: z.string().min(1).max(256),
|
|
9
|
+
};
|
|
10
|
+
export function registerReportTools(server, client, config) {
|
|
11
|
+
server.tool("y2_list_reports", "List recent Y2 reports. Requires reports:read.", listReportsInput, async ({ profileId, limit }) => {
|
|
12
|
+
try {
|
|
13
|
+
const data = await client.requestJson("/api/v1/reports", {
|
|
14
|
+
query: {
|
|
15
|
+
limit: String(limit),
|
|
16
|
+
...(profileId ? { profileId } : {}),
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
return textResult(formatJson(data, config));
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
return errorResult(error, config);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
server.tool("y2_get_report", "Get one Y2 report by ID. Requires reports:read.", getReportInput, async ({ reportId }) => {
|
|
26
|
+
try {
|
|
27
|
+
const data = await client.requestJson(`/api/v1/reports/${encodeURIComponent(reportId)}`);
|
|
28
|
+
return textResult(formatJson(data, config));
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
return errorResult(error, config);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=reports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reports.js","sourceRoot":"","sources":["../../src/tools/reports.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGjE,MAAM,gBAAgB,GAAG;IACxB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IAChD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;CAChD,CAAC;AAEF,MAAM,cAAc,GAAG;IACtB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;CACpC,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,MAAiB,EAAE,MAAgB,EAAE,MAAmB;IAC3F,MAAM,CAAC,IAAI,CACV,iBAAiB,EACjB,gDAAgD,EAChD,gBAAgB,EAChB,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE;QAC9B,IAAI,CAAC;YACJ,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,iBAAiB,EAAE;gBACxD,KAAK,EAAE;oBACN,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;oBACpB,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACnC;aACD,CAAC,CAAC;YACH,OAAO,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACnC,CAAC;IACF,CAAC,CACD,CAAC;IAEF,MAAM,CAAC,IAAI,CACV,eAAe,EACf,iDAAiD,EACjD,cAAc,EACd,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QACtB,IAAI,CAAC;YACJ,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,mBAAmB,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACzF,OAAO,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACnC,CAAC;IACF,CAAC,CACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Y2McpConfig } from "./config.js";
|
|
2
|
+
type Query = Record<string, string | undefined>;
|
|
3
|
+
type RequestOptions = {
|
|
4
|
+
method?: string;
|
|
5
|
+
query?: Query;
|
|
6
|
+
body?: unknown;
|
|
7
|
+
auth?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type AskAgentInput = {
|
|
10
|
+
message: string;
|
|
11
|
+
threadId?: string;
|
|
12
|
+
source?: string;
|
|
13
|
+
externalUserId?: string;
|
|
14
|
+
externalThreadId?: string;
|
|
15
|
+
};
|
|
16
|
+
export type AskAgentResponse = {
|
|
17
|
+
text: string;
|
|
18
|
+
threadId: string | null;
|
|
19
|
+
status: number;
|
|
20
|
+
};
|
|
21
|
+
export declare class Y2Client {
|
|
22
|
+
#private;
|
|
23
|
+
constructor(config: Y2McpConfig);
|
|
24
|
+
fetchDocsText(path: string): Promise<string>;
|
|
25
|
+
requestJson(path: string, options?: RequestOptions): Promise<unknown>;
|
|
26
|
+
askAgent(input: AskAgentInput): Promise<AskAgentResponse>;
|
|
27
|
+
request(path: string, options?: RequestOptions): Promise<Response>;
|
|
28
|
+
fetch(url: URL, init: RequestInit): Promise<Response>;
|
|
29
|
+
readOkText(response: Response): Promise<string>;
|
|
30
|
+
throwIfNotOk(response: Response): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { requireApiKey } from "./config.js";
|
|
2
|
+
import { Y2ApiError } from "./errors.js";
|
|
3
|
+
import { extractAssistantTextFromStream } from "./stream.js";
|
|
4
|
+
function appendQuery(url, query) {
|
|
5
|
+
if (!query)
|
|
6
|
+
return;
|
|
7
|
+
for (const [key, value] of Object.entries(query)) {
|
|
8
|
+
if (value !== undefined)
|
|
9
|
+
url.searchParams.set(key, value);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function buildUrl(baseUrl, path, query) {
|
|
13
|
+
const url = new URL(path, `${baseUrl}/`);
|
|
14
|
+
appendQuery(url, query);
|
|
15
|
+
return url;
|
|
16
|
+
}
|
|
17
|
+
async function responseText(response) {
|
|
18
|
+
try {
|
|
19
|
+
return await response.text();
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return "";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function errorMessageFromBody(body) {
|
|
26
|
+
if (!body)
|
|
27
|
+
return { message: "Request failed." };
|
|
28
|
+
try {
|
|
29
|
+
const json = JSON.parse(body);
|
|
30
|
+
const message = typeof json.message === "string"
|
|
31
|
+
? json.message
|
|
32
|
+
: typeof json.error === "string"
|
|
33
|
+
? json.error
|
|
34
|
+
: typeof json.error?.message === "string"
|
|
35
|
+
? json.error.message
|
|
36
|
+
: body;
|
|
37
|
+
const code = typeof json.code === "string"
|
|
38
|
+
? json.code
|
|
39
|
+
: typeof json.error?.code === "string"
|
|
40
|
+
? json.error.code
|
|
41
|
+
: undefined;
|
|
42
|
+
return { message, code };
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return { message: body };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export class Y2Client {
|
|
49
|
+
#config;
|
|
50
|
+
constructor(config) {
|
|
51
|
+
this.#config = config;
|
|
52
|
+
}
|
|
53
|
+
async fetchDocsText(path) {
|
|
54
|
+
const response = await this.fetch(buildUrl(this.#config.docsBaseUrl, path), {
|
|
55
|
+
method: "GET",
|
|
56
|
+
});
|
|
57
|
+
return await this.readOkText(response);
|
|
58
|
+
}
|
|
59
|
+
async requestJson(path, options = {}) {
|
|
60
|
+
const response = await this.request(path, options);
|
|
61
|
+
const text = await responseText(response);
|
|
62
|
+
if (!text)
|
|
63
|
+
return null;
|
|
64
|
+
return JSON.parse(text);
|
|
65
|
+
}
|
|
66
|
+
async askAgent(input) {
|
|
67
|
+
const body = {
|
|
68
|
+
messages: [
|
|
69
|
+
{
|
|
70
|
+
role: "user",
|
|
71
|
+
parts: [{ type: "text", text: input.message }],
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
...(input.threadId ? { threadId: input.threadId } : {}),
|
|
75
|
+
...(input.source || input.externalUserId || input.externalThreadId
|
|
76
|
+
? {
|
|
77
|
+
metadata: {
|
|
78
|
+
...(input.source ? { source: input.source } : {}),
|
|
79
|
+
...(input.externalUserId ? { externalUserId: input.externalUserId } : {}),
|
|
80
|
+
...(input.externalThreadId ? { externalThreadId: input.externalThreadId } : {}),
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
: {}),
|
|
84
|
+
};
|
|
85
|
+
const response = await this.request("/api/v1/agent-y2/chat/stream", {
|
|
86
|
+
method: "POST",
|
|
87
|
+
body,
|
|
88
|
+
});
|
|
89
|
+
const raw = await responseText(response);
|
|
90
|
+
return {
|
|
91
|
+
text: extractAssistantTextFromStream(raw),
|
|
92
|
+
threadId: response.headers.get("x-thread-id"),
|
|
93
|
+
status: response.status,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async request(path, options = {}) {
|
|
97
|
+
const headers = new Headers();
|
|
98
|
+
headers.set("Accept", "application/json, text/event-stream, text/plain");
|
|
99
|
+
if (options.auth !== false) {
|
|
100
|
+
headers.set("Authorization", `Bearer ${requireApiKey(this.#config)}`);
|
|
101
|
+
}
|
|
102
|
+
if (options.body !== undefined)
|
|
103
|
+
headers.set("Content-Type", "application/json");
|
|
104
|
+
const response = await this.fetch(buildUrl(this.#config.apiBaseUrl, path, options.query), {
|
|
105
|
+
method: options.method ?? (options.body === undefined ? "GET" : "POST"),
|
|
106
|
+
headers,
|
|
107
|
+
body: options.body === undefined ? undefined : JSON.stringify(options.body),
|
|
108
|
+
});
|
|
109
|
+
await this.throwIfNotOk(response);
|
|
110
|
+
return response;
|
|
111
|
+
}
|
|
112
|
+
async fetch(url, init) {
|
|
113
|
+
const controller = new AbortController();
|
|
114
|
+
const timeout = setTimeout(() => controller.abort(), this.#config.timeoutMs);
|
|
115
|
+
try {
|
|
116
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
120
|
+
throw new Error(`Y2 request timed out after ${this.#config.timeoutMs}ms.`);
|
|
121
|
+
}
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
clearTimeout(timeout);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async readOkText(response) {
|
|
129
|
+
await this.throwIfNotOk(response);
|
|
130
|
+
return await responseText(response);
|
|
131
|
+
}
|
|
132
|
+
async throwIfNotOk(response) {
|
|
133
|
+
if (response.ok)
|
|
134
|
+
return;
|
|
135
|
+
const body = await responseText(response);
|
|
136
|
+
const { message, code } = errorMessageFromBody(body);
|
|
137
|
+
throw new Y2ApiError(message, {
|
|
138
|
+
status: response.status,
|
|
139
|
+
code,
|
|
140
|
+
retryAfter: response.headers.get("retry-after") ?? undefined,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=y2-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"y2-client.js","sourceRoot":"","sources":["../src/y2-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Claude Code
|
|
2
|
+
|
|
3
|
+
Install the Y2 MCP server as a local stdio server:
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
export Y2_API_KEY=y2_...
|
|
7
|
+
|
|
8
|
+
claude mcp add --env Y2_API_KEY=$Y2_API_KEY --transport stdio y2 \
|
|
9
|
+
-- npx -y @y2-intel/mcp
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Use a dedicated Y2 API key for Claude Code. Add only the scopes needed by the
|
|
13
|
+
tools you expect to use:
|
|
14
|
+
|
|
15
|
+
- `reports:read` for report tools
|
|
16
|
+
- `news:read` for News Terminal tools
|
|
17
|
+
|
|
18
|
+
Agent Y2 is disabled by default. To expose `y2_ask_agent`, use a key with
|
|
19
|
+
`agent:y2` and add `--env Y2_MCP_ENABLE_AGENT=1` to the `claude mcp add`
|
|
20
|
+
command.
|
|
21
|
+
|
|
22
|
+
Do not paste `Y2_API_KEY` into prompts.
|