@inkeep/agents-run-api 0.39.5 → 0.41.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/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase1/system-prompt.js +5 -0
- package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase1/thinking-preparation.js +5 -0
- package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase1/tool.js +5 -0
- package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase2/data-component.js +5 -0
- package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase2/data-components.js +5 -0
- package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/phase2/system-prompt.js +5 -0
- package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/shared/artifact-retrieval-guidance.js +5 -0
- package/dist/_virtual/_raw_/home/runner/work/agents/agents/agents-run-api/templates/v1/shared/artifact.js +5 -0
- package/dist/a2a/client.d.ts +184 -0
- package/dist/a2a/client.js +510 -0
- package/dist/a2a/handlers.d.ts +7 -0
- package/dist/a2a/handlers.js +576 -0
- package/dist/a2a/transfer.d.ts +22 -0
- package/dist/a2a/transfer.js +46 -0
- package/dist/a2a/types.d.ts +79 -0
- package/dist/a2a/types.js +22 -0
- package/dist/agents/Agent.d.ts +268 -0
- package/dist/agents/Agent.js +1932 -0
- package/dist/agents/ModelFactory.d.ts +63 -0
- package/dist/agents/ModelFactory.js +194 -0
- package/dist/agents/SystemPromptBuilder.d.ts +21 -0
- package/dist/agents/SystemPromptBuilder.js +48 -0
- package/dist/agents/ToolSessionManager.d.ts +63 -0
- package/dist/agents/ToolSessionManager.js +146 -0
- package/dist/agents/generateTaskHandler.d.ts +49 -0
- package/dist/agents/generateTaskHandler.js +523 -0
- package/dist/agents/relationTools.d.ts +57 -0
- package/dist/agents/relationTools.js +262 -0
- package/dist/agents/types.d.ts +28 -0
- package/dist/agents/types.js +1 -0
- package/dist/agents/versions/v1/Phase1Config.d.ts +27 -0
- package/dist/agents/versions/v1/Phase1Config.js +424 -0
- package/dist/agents/versions/v1/Phase2Config.d.ts +31 -0
- package/dist/agents/versions/v1/Phase2Config.js +330 -0
- package/dist/constants/execution-limits/defaults.d.ts +51 -0
- package/dist/constants/execution-limits/defaults.js +52 -0
- package/dist/constants/execution-limits/index.d.ts +6 -0
- package/dist/constants/execution-limits/index.js +21 -0
- package/dist/create-app.d.ts +9 -0
- package/dist/create-app.js +195 -0
- package/dist/data/agent.d.ts +7 -0
- package/dist/data/agent.js +72 -0
- package/dist/data/agents.d.ts +34 -0
- package/dist/data/agents.js +139 -0
- package/dist/data/conversations.d.ts +128 -0
- package/dist/data/conversations.js +522 -0
- package/dist/data/db/dbClient.d.ts +6 -0
- package/dist/data/db/dbClient.js +17 -0
- package/dist/env.d.ts +57 -0
- package/dist/env.js +1 -2
- package/dist/handlers/executionHandler.d.ts +41 -0
- package/dist/handlers/executionHandler.js +457 -0
- package/dist/index.d.ts +8 -29
- package/dist/index.js +5 -11386
- package/dist/instrumentation.d.ts +1 -2
- package/dist/instrumentation.js +66 -3
- package/dist/{logger2.js → logger.d.ts} +1 -2
- package/dist/logger.js +1 -1
- package/dist/middleware/api-key-auth.d.ts +26 -0
- package/dist/middleware/api-key-auth.js +240 -0
- package/dist/middleware/index.d.ts +2 -0
- package/dist/middleware/index.js +3 -0
- package/dist/openapi.d.ts +4 -0
- package/dist/openapi.js +54 -0
- package/dist/routes/agents.d.ts +12 -0
- package/dist/routes/agents.js +147 -0
- package/dist/routes/chat.d.ts +13 -0
- package/dist/routes/chat.js +305 -0
- package/dist/routes/chatDataStream.d.ts +13 -0
- package/dist/routes/chatDataStream.js +365 -0
- package/dist/routes/mcp.d.ts +13 -0
- package/dist/routes/mcp.js +495 -0
- package/dist/services/AgentSession.d.ts +356 -0
- package/dist/services/AgentSession.js +1208 -0
- package/dist/services/ArtifactParser.d.ts +105 -0
- package/dist/services/ArtifactParser.js +338 -0
- package/dist/services/ArtifactService.d.ts +123 -0
- package/dist/services/ArtifactService.js +612 -0
- package/dist/services/BaseCompressor.d.ts +183 -0
- package/dist/services/BaseCompressor.js +500 -0
- package/dist/services/ConversationCompressor.d.ts +32 -0
- package/dist/services/ConversationCompressor.js +91 -0
- package/dist/services/IncrementalStreamParser.d.ts +98 -0
- package/dist/services/IncrementalStreamParser.js +327 -0
- package/dist/services/MidGenerationCompressor.d.ts +63 -0
- package/dist/services/MidGenerationCompressor.js +104 -0
- package/dist/services/PendingToolApprovalManager.d.ts +62 -0
- package/dist/services/PendingToolApprovalManager.js +133 -0
- package/dist/services/ResponseFormatter.d.ts +39 -0
- package/dist/services/ResponseFormatter.js +152 -0
- package/dist/tools/NativeSandboxExecutor.d.ts +38 -0
- package/dist/tools/NativeSandboxExecutor.js +432 -0
- package/dist/tools/SandboxExecutorFactory.d.ts +36 -0
- package/dist/tools/SandboxExecutorFactory.js +80 -0
- package/dist/tools/VercelSandboxExecutor.d.ts +71 -0
- package/dist/tools/VercelSandboxExecutor.js +340 -0
- package/dist/tools/distill-conversation-history-tool.d.ts +62 -0
- package/dist/tools/distill-conversation-history-tool.js +206 -0
- package/dist/tools/distill-conversation-tool.d.ts +41 -0
- package/dist/tools/distill-conversation-tool.js +141 -0
- package/dist/tools/sandbox-utils.d.ts +18 -0
- package/dist/tools/sandbox-utils.js +53 -0
- package/dist/types/chat.d.ts +27 -0
- package/dist/types/chat.js +1 -0
- package/dist/types/execution-context.d.ts +46 -0
- package/dist/types/execution-context.js +27 -0
- package/dist/types/xml.d.ts +5 -0
- package/dist/utils/SchemaProcessor.d.ts +52 -0
- package/dist/utils/SchemaProcessor.js +182 -0
- package/dist/utils/agent-operations.d.ts +62 -0
- package/dist/utils/agent-operations.js +53 -0
- package/dist/utils/artifact-component-schema.d.ts +42 -0
- package/dist/utils/artifact-component-schema.js +186 -0
- package/dist/utils/cleanup.d.ts +21 -0
- package/dist/utils/cleanup.js +59 -0
- package/dist/utils/data-component-schema.d.ts +2 -0
- package/dist/utils/data-component-schema.js +3 -0
- package/dist/utils/default-status-schemas.d.ts +20 -0
- package/dist/utils/default-status-schemas.js +24 -0
- package/dist/utils/json-postprocessor.d.ts +13 -0
- package/dist/{json-postprocessor.cjs → utils/json-postprocessor.js} +2 -3
- package/dist/utils/model-context-utils.d.ts +39 -0
- package/dist/utils/model-context-utils.js +181 -0
- package/dist/utils/model-resolver.d.ts +6 -0
- package/dist/utils/model-resolver.js +34 -0
- package/dist/utils/schema-validation.d.ts +44 -0
- package/dist/utils/schema-validation.js +97 -0
- package/dist/utils/stream-helpers.d.ts +197 -0
- package/dist/utils/stream-helpers.js +518 -0
- package/dist/utils/stream-registry.d.ts +22 -0
- package/dist/utils/stream-registry.js +34 -0
- package/dist/utils/token-estimator.d.ts +69 -0
- package/dist/utils/token-estimator.js +53 -0
- package/dist/utils/tracer.d.ts +7 -0
- package/dist/utils/tracer.js +7 -0
- package/package.json +10 -26
- package/dist/SandboxExecutorFactory.cjs +0 -895
- package/dist/SandboxExecutorFactory.js +0 -893
- package/dist/SandboxExecutorFactory.js.map +0 -1
- package/dist/chunk-VBDAOXYI.cjs +0 -927
- package/dist/chunk-VBDAOXYI.js +0 -832
- package/dist/chunk-VBDAOXYI.js.map +0 -1
- package/dist/chunk.cjs +0 -34
- package/dist/conversations.cjs +0 -7
- package/dist/conversations.js +0 -7
- package/dist/conversations2.cjs +0 -209
- package/dist/conversations2.js +0 -180
- package/dist/conversations2.js.map +0 -1
- package/dist/dbClient.cjs +0 -9676
- package/dist/dbClient.js +0 -9670
- package/dist/dbClient.js.map +0 -1
- package/dist/dbClient2.cjs +0 -5
- package/dist/dbClient2.js +0 -5
- package/dist/env.cjs +0 -59
- package/dist/env.js.map +0 -1
- package/dist/execution-limits.cjs +0 -260
- package/dist/execution-limits.js +0 -63
- package/dist/execution-limits.js.map +0 -1
- package/dist/index.cjs +0 -11411
- package/dist/index.d.cts +0 -36
- package/dist/index.d.cts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/instrumentation.cjs +0 -12
- package/dist/instrumentation.d.cts +0 -18
- package/dist/instrumentation.d.cts.map +0 -1
- package/dist/instrumentation.d.ts.map +0 -1
- package/dist/instrumentation2.cjs +0 -116
- package/dist/instrumentation2.js +0 -69
- package/dist/instrumentation2.js.map +0 -1
- package/dist/json-postprocessor.js +0 -20
- package/dist/json-postprocessor.js.map +0 -1
- package/dist/logger.cjs +0 -5
- package/dist/logger2.cjs +0 -1
- package/dist/nodefs.cjs +0 -29
- package/dist/nodefs.js +0 -27
- package/dist/nodefs.js.map +0 -1
- package/dist/opfs-ahp.cjs +0 -367
- package/dist/opfs-ahp.js +0 -368
- package/dist/opfs-ahp.js.map +0 -1
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
import { getLogger } from "../logger.js";
|
|
2
|
+
import dbClient_default from "../data/db/dbClient.js";
|
|
3
|
+
import { createMCPStreamHelper } from "../utils/stream-helpers.js";
|
|
4
|
+
import { ExecutionHandler } from "../handlers/executionHandler.js";
|
|
5
|
+
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
|
|
6
|
+
import { HeadersScopeSchema, contextValidationMiddleware, createMessage, createOrGetConversation, generateId, getAgentWithDefaultSubAgent, getConversation, getConversationId, getRequestExecutionContext, getSubAgentById, handleContextResolution, updateConversation } from "@inkeep/agents-core";
|
|
7
|
+
import { context, propagation, trace } from "@opentelemetry/api";
|
|
8
|
+
import { McpServer } from "@alcyone-labs/modelcontextprotocol-sdk/server/mcp.js";
|
|
9
|
+
import { StreamableHTTPServerTransport } from "@alcyone-labs/modelcontextprotocol-sdk/server/streamableHttp.js";
|
|
10
|
+
import { toFetchResponse, toReqRes } from "fetch-to-node";
|
|
11
|
+
|
|
12
|
+
//#region src/routes/mcp.ts
|
|
13
|
+
const logger = getLogger("mcp");
|
|
14
|
+
/**
|
|
15
|
+
* Singleton mock response object for spoof initialization
|
|
16
|
+
*/
|
|
17
|
+
var MockResponseSingleton = class MockResponseSingleton {
|
|
18
|
+
static instance;
|
|
19
|
+
mockRes;
|
|
20
|
+
constructor() {
|
|
21
|
+
this.mockRes = {
|
|
22
|
+
statusCode: 200,
|
|
23
|
+
headers: {},
|
|
24
|
+
setHeader: function(name, value) {
|
|
25
|
+
this.headers[name] = value;
|
|
26
|
+
},
|
|
27
|
+
getHeaders: function() {
|
|
28
|
+
return this.headers;
|
|
29
|
+
},
|
|
30
|
+
end: () => {},
|
|
31
|
+
write: () => {},
|
|
32
|
+
writeHead: () => {}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
static getInstance() {
|
|
36
|
+
if (!MockResponseSingleton.instance) MockResponseSingleton.instance = new MockResponseSingleton();
|
|
37
|
+
return MockResponseSingleton.instance;
|
|
38
|
+
}
|
|
39
|
+
getMockResponse() {
|
|
40
|
+
this.mockRes.headers = {};
|
|
41
|
+
this.mockRes.statusCode = 200;
|
|
42
|
+
return this.mockRes;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Creates a spoof initialization message with the given protocol version
|
|
47
|
+
* Extracted as a pure function for better testability and reuse
|
|
48
|
+
*/
|
|
49
|
+
const createSpoofInitMessage = (mcpProtocolVersion) => ({
|
|
50
|
+
method: "initialize",
|
|
51
|
+
params: {
|
|
52
|
+
protocolVersion: mcpProtocolVersion || "2025-06-18",
|
|
53
|
+
capabilities: {
|
|
54
|
+
tools: true,
|
|
55
|
+
prompts: true,
|
|
56
|
+
resources: false,
|
|
57
|
+
logging: false,
|
|
58
|
+
roots: { listChanged: false }
|
|
59
|
+
},
|
|
60
|
+
clientInfo: {
|
|
61
|
+
name: "inkeep-mcp-server",
|
|
62
|
+
version: "1.0.0"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
jsonrpc: "2.0",
|
|
66
|
+
id: 0
|
|
67
|
+
});
|
|
68
|
+
/**
|
|
69
|
+
* Spoofs an initialization message to set the transport's initialized flag
|
|
70
|
+
* This is necessary when recreating transports for existing sessions because the transport expects to have received an initialization message from the client.
|
|
71
|
+
*/
|
|
72
|
+
const spoofTransportInitialization = async (transport, req, sessionId, mcpProtocolVersion) => {
|
|
73
|
+
logger.info({ sessionId }, "Spoofing initialization message to set transport state");
|
|
74
|
+
const spoofInitMessage = createSpoofInitMessage(mcpProtocolVersion);
|
|
75
|
+
const mockRes = MockResponseSingleton.getInstance().getMockResponse();
|
|
76
|
+
try {
|
|
77
|
+
await transport.handleRequest(req, mockRes, spoofInitMessage);
|
|
78
|
+
logger.info({ sessionId }, "Successfully spoofed initialization");
|
|
79
|
+
} catch (spoofError) {
|
|
80
|
+
logger.warn({
|
|
81
|
+
sessionId,
|
|
82
|
+
error: spoofError
|
|
83
|
+
}, "Spoof initialization failed, continuing anyway");
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const validateSession = async (req, res, body, tenantId, projectId, agentId) => {
|
|
87
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
88
|
+
logger.info({ sessionId }, "Received MCP session ID");
|
|
89
|
+
if (!sessionId) {
|
|
90
|
+
logger.info({ body }, "Missing session ID");
|
|
91
|
+
res.writeHead(400).end(JSON.stringify({
|
|
92
|
+
jsonrpc: "2.0",
|
|
93
|
+
error: {
|
|
94
|
+
code: -32602,
|
|
95
|
+
message: "Bad Request: Mcp-Session-Id header is required"
|
|
96
|
+
},
|
|
97
|
+
id: null
|
|
98
|
+
}));
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
if (Array.isArray(sessionId)) {
|
|
102
|
+
res.writeHead(400).end(JSON.stringify({
|
|
103
|
+
jsonrpc: "2.0",
|
|
104
|
+
error: {
|
|
105
|
+
code: -32e3,
|
|
106
|
+
message: "Bad Request: Mcp-Session-Id header must be a single value"
|
|
107
|
+
},
|
|
108
|
+
id: null
|
|
109
|
+
}));
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
const conversation = await getConversation(dbClient_default)({
|
|
113
|
+
scopes: {
|
|
114
|
+
tenantId,
|
|
115
|
+
projectId
|
|
116
|
+
},
|
|
117
|
+
conversationId: sessionId
|
|
118
|
+
});
|
|
119
|
+
logger.info({
|
|
120
|
+
sessionId,
|
|
121
|
+
conversationFound: !!conversation,
|
|
122
|
+
sessionType: conversation?.metadata?.sessionData?.sessionType,
|
|
123
|
+
storedAgentId: conversation?.metadata?.sessionData?.agentId,
|
|
124
|
+
requestAgentId: agentId
|
|
125
|
+
}, "Conversation lookup result");
|
|
126
|
+
if (!conversation || conversation.metadata?.sessionData?.sessionType !== "mcp" || conversation.metadata?.sessionData?.agentId !== agentId) {
|
|
127
|
+
logger.info({
|
|
128
|
+
sessionId,
|
|
129
|
+
conversationId: conversation?.id
|
|
130
|
+
}, "MCP session not found or invalid");
|
|
131
|
+
res.writeHead(404).end(JSON.stringify({
|
|
132
|
+
jsonrpc: "2.0",
|
|
133
|
+
error: {
|
|
134
|
+
code: -32001,
|
|
135
|
+
message: "Session not found"
|
|
136
|
+
},
|
|
137
|
+
id: null
|
|
138
|
+
}));
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
return conversation;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Sets up tracing attributes for the active span
|
|
145
|
+
*/
|
|
146
|
+
const setupTracing = (conversationId, tenantId, agentId) => {
|
|
147
|
+
const activeSpan = trace.getActiveSpan();
|
|
148
|
+
if (activeSpan) activeSpan.setAttributes({
|
|
149
|
+
"conversation.id": conversationId,
|
|
150
|
+
"tenant.id": tenantId,
|
|
151
|
+
"agent.id": agentId
|
|
152
|
+
});
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* Processes and stores the user message
|
|
156
|
+
*/
|
|
157
|
+
const processUserMessage = async (tenantId, projectId, conversationId, query) => {
|
|
158
|
+
const messageSpan = trace.getActiveSpan();
|
|
159
|
+
if (messageSpan) messageSpan.setAttributes({
|
|
160
|
+
"message.content": query,
|
|
161
|
+
"message.timestamp": Date.now()
|
|
162
|
+
});
|
|
163
|
+
await createMessage(dbClient_default)({
|
|
164
|
+
id: generateId(),
|
|
165
|
+
tenantId,
|
|
166
|
+
projectId,
|
|
167
|
+
conversationId,
|
|
168
|
+
role: "user",
|
|
169
|
+
content: { text: query },
|
|
170
|
+
visibility: "user-facing",
|
|
171
|
+
messageType: "chat"
|
|
172
|
+
});
|
|
173
|
+
};
|
|
174
|
+
/**
|
|
175
|
+
* Executes the agent query and returns the result
|
|
176
|
+
*/
|
|
177
|
+
const executeAgentQuery = async (executionContext, conversationId, query, defaultSubAgentId) => {
|
|
178
|
+
const requestId = `mcp-${Date.now()}`;
|
|
179
|
+
const mcpStreamHelper = createMCPStreamHelper();
|
|
180
|
+
const result = await new ExecutionHandler().execute({
|
|
181
|
+
executionContext,
|
|
182
|
+
conversationId,
|
|
183
|
+
userMessage: query,
|
|
184
|
+
initialAgentId: defaultSubAgentId,
|
|
185
|
+
requestId,
|
|
186
|
+
sseHelper: mcpStreamHelper
|
|
187
|
+
});
|
|
188
|
+
logger.info({ result }, `Execution completed: ${result.success ? "success" : "failed"} after ${result.iterations} iterations`);
|
|
189
|
+
if (!result.success) return {
|
|
190
|
+
content: [{
|
|
191
|
+
type: "text",
|
|
192
|
+
text: result.error || `Sorry, I was unable to process your request at this time. Please try again.`
|
|
193
|
+
}],
|
|
194
|
+
isError: true
|
|
195
|
+
};
|
|
196
|
+
return { content: [{
|
|
197
|
+
type: "text",
|
|
198
|
+
text: result.response || "No response generated"
|
|
199
|
+
}] };
|
|
200
|
+
};
|
|
201
|
+
/**
|
|
202
|
+
* Creates and configures an MCP server for the given context
|
|
203
|
+
*/
|
|
204
|
+
const getServer = async (headers$1, executionContext, conversationId, credentialStores) => {
|
|
205
|
+
const { tenantId, projectId, agentId } = executionContext;
|
|
206
|
+
setupTracing(conversationId, tenantId, agentId);
|
|
207
|
+
const agent = await getAgentWithDefaultSubAgent(dbClient_default)({ scopes: {
|
|
208
|
+
tenantId,
|
|
209
|
+
projectId,
|
|
210
|
+
agentId
|
|
211
|
+
} });
|
|
212
|
+
if (!agent) throw new Error("Agent not found");
|
|
213
|
+
const server = new McpServer({
|
|
214
|
+
name: "inkeep-chat-api-server",
|
|
215
|
+
version: "1.0.0"
|
|
216
|
+
}, { capabilities: { logging: {} } });
|
|
217
|
+
server.tool("send-query-to-agent", `Send a query to the ${agent.name} agent. The agent has the following description: ${agent.description}`, { query: z.string().describe("The query to send to the agent") }, async ({ query }) => {
|
|
218
|
+
try {
|
|
219
|
+
if (!agent.defaultSubAgentId) return {
|
|
220
|
+
content: [{
|
|
221
|
+
type: "text",
|
|
222
|
+
text: `Agent does not have a default agent configured`
|
|
223
|
+
}],
|
|
224
|
+
isError: true
|
|
225
|
+
};
|
|
226
|
+
const defaultSubAgentId = agent.defaultSubAgentId;
|
|
227
|
+
if (!await getSubAgentById(dbClient_default)({
|
|
228
|
+
scopes: {
|
|
229
|
+
tenantId,
|
|
230
|
+
projectId,
|
|
231
|
+
agentId
|
|
232
|
+
},
|
|
233
|
+
subAgentId: defaultSubAgentId
|
|
234
|
+
})) return {
|
|
235
|
+
content: [{
|
|
236
|
+
type: "text",
|
|
237
|
+
text: `Agent not found`
|
|
238
|
+
}],
|
|
239
|
+
isError: true
|
|
240
|
+
};
|
|
241
|
+
const resolvedContext = await handleContextResolution({
|
|
242
|
+
tenantId,
|
|
243
|
+
projectId,
|
|
244
|
+
agentId,
|
|
245
|
+
conversationId,
|
|
246
|
+
headers: headers$1,
|
|
247
|
+
dbClient: dbClient_default,
|
|
248
|
+
credentialStores
|
|
249
|
+
});
|
|
250
|
+
logger.info({
|
|
251
|
+
tenantId,
|
|
252
|
+
projectId,
|
|
253
|
+
agentId,
|
|
254
|
+
conversationId,
|
|
255
|
+
hasContextConfig: !!agent.contextConfigId,
|
|
256
|
+
hasHeaders: !!headers$1,
|
|
257
|
+
hasValidatedContext: !!resolvedContext
|
|
258
|
+
}, "parameters");
|
|
259
|
+
await processUserMessage(tenantId, projectId, conversationId, query);
|
|
260
|
+
return executeAgentQuery(executionContext, conversationId, query, defaultSubAgentId);
|
|
261
|
+
} catch (error) {
|
|
262
|
+
return {
|
|
263
|
+
content: [{
|
|
264
|
+
type: "text",
|
|
265
|
+
text: `Error sending query: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
266
|
+
}],
|
|
267
|
+
isError: true
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
return server;
|
|
272
|
+
};
|
|
273
|
+
const app = new OpenAPIHono();
|
|
274
|
+
app.use("/", async (c, next) => {
|
|
275
|
+
if (c.req.method === "POST") return contextValidationMiddleware(dbClient_default)(c, next);
|
|
276
|
+
return next();
|
|
277
|
+
});
|
|
278
|
+
/**
|
|
279
|
+
* Validates request parameters and returns execution context if valid
|
|
280
|
+
*/
|
|
281
|
+
const validateRequestParameters = (c) => {
|
|
282
|
+
try {
|
|
283
|
+
const executionContext = getRequestExecutionContext(c);
|
|
284
|
+
const { tenantId, projectId, agentId } = executionContext;
|
|
285
|
+
getLogger("mcp").debug({
|
|
286
|
+
tenantId,
|
|
287
|
+
projectId,
|
|
288
|
+
agentId
|
|
289
|
+
}, "Extracted MCP entity parameters");
|
|
290
|
+
return {
|
|
291
|
+
valid: true,
|
|
292
|
+
executionContext
|
|
293
|
+
};
|
|
294
|
+
} catch (error) {
|
|
295
|
+
getLogger("chat").warn({ error: error instanceof Error ? error.message : "Unknown error" }, "Failed to get execution context");
|
|
296
|
+
return {
|
|
297
|
+
valid: false,
|
|
298
|
+
response: c.json({
|
|
299
|
+
jsonrpc: "2.0",
|
|
300
|
+
error: {
|
|
301
|
+
code: -32602,
|
|
302
|
+
message: "API key authentication required"
|
|
303
|
+
},
|
|
304
|
+
id: null
|
|
305
|
+
}, { status: 401 })
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
/**
|
|
310
|
+
* Creates a new MCP session and handles initialization
|
|
311
|
+
*/
|
|
312
|
+
const handleInitializationRequest = async (body, executionContext, validatedContext, req, res, c, credentialStores) => {
|
|
313
|
+
const { tenantId, projectId, agentId } = executionContext;
|
|
314
|
+
logger.info({ body }, "Received initialization request");
|
|
315
|
+
const sessionId = getConversationId();
|
|
316
|
+
const activeSpan = trace.getActiveSpan();
|
|
317
|
+
if (activeSpan) activeSpan.setAttributes({
|
|
318
|
+
"conversation.id": sessionId,
|
|
319
|
+
"tenant.id": tenantId,
|
|
320
|
+
"agent.id": agentId,
|
|
321
|
+
"project.id": projectId
|
|
322
|
+
});
|
|
323
|
+
let currentBag = propagation.getBaggage(context.active());
|
|
324
|
+
if (!currentBag) currentBag = propagation.createBaggage();
|
|
325
|
+
currentBag = currentBag.setEntry("conversation.id", { value: sessionId });
|
|
326
|
+
const ctxWithBaggage = propagation.setBaggage(context.active(), currentBag);
|
|
327
|
+
return await context.with(ctxWithBaggage, async () => {
|
|
328
|
+
const agent = await getAgentWithDefaultSubAgent(dbClient_default)({ scopes: {
|
|
329
|
+
tenantId,
|
|
330
|
+
projectId,
|
|
331
|
+
agentId
|
|
332
|
+
} });
|
|
333
|
+
if (!agent) return c.json({
|
|
334
|
+
jsonrpc: "2.0",
|
|
335
|
+
error: {
|
|
336
|
+
code: -32001,
|
|
337
|
+
message: "Agent not found"
|
|
338
|
+
},
|
|
339
|
+
id: body.id || null
|
|
340
|
+
}, { status: 404 });
|
|
341
|
+
if (!agent.defaultSubAgentId) return c.json({
|
|
342
|
+
jsonrpc: "2.0",
|
|
343
|
+
error: {
|
|
344
|
+
code: -32001,
|
|
345
|
+
message: "Agent does not have a default agent configured"
|
|
346
|
+
},
|
|
347
|
+
id: body.id || null
|
|
348
|
+
}, { status: 400 });
|
|
349
|
+
const conversation = await createOrGetConversation(dbClient_default)({
|
|
350
|
+
id: sessionId,
|
|
351
|
+
tenantId,
|
|
352
|
+
projectId,
|
|
353
|
+
activeSubAgentId: agent.defaultSubAgentId,
|
|
354
|
+
metadata: { sessionData: {
|
|
355
|
+
agentId,
|
|
356
|
+
sessionType: "mcp",
|
|
357
|
+
mcpProtocolVersion: c.req.header("mcp-protocol-version"),
|
|
358
|
+
initialized: false
|
|
359
|
+
} }
|
|
360
|
+
});
|
|
361
|
+
logger.info({
|
|
362
|
+
sessionId,
|
|
363
|
+
conversationId: conversation.id
|
|
364
|
+
}, "Created MCP session as conversation");
|
|
365
|
+
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => sessionId });
|
|
366
|
+
await (await getServer(validatedContext, executionContext, sessionId, credentialStores)).connect(transport);
|
|
367
|
+
logger.info({ sessionId }, "Server connected for initialization");
|
|
368
|
+
res.setHeader("Mcp-Session-Id", sessionId);
|
|
369
|
+
logger.info({
|
|
370
|
+
sessionId,
|
|
371
|
+
bodyMethod: body?.method,
|
|
372
|
+
bodyId: body?.id
|
|
373
|
+
}, "About to handle initialization request");
|
|
374
|
+
await transport.handleRequest(req, res, body);
|
|
375
|
+
logger.info({ sessionId }, "Successfully handled initialization request");
|
|
376
|
+
return toFetchResponse(res);
|
|
377
|
+
});
|
|
378
|
+
};
|
|
379
|
+
/**
|
|
380
|
+
* Handles requests for existing MCP sessions
|
|
381
|
+
*/
|
|
382
|
+
const handleExistingSessionRequest = async (body, executionContext, validatedContext, req, res, credentialStores) => {
|
|
383
|
+
const { tenantId, projectId, agentId } = executionContext;
|
|
384
|
+
const conversation = await validateSession(req, res, body, tenantId, projectId, agentId);
|
|
385
|
+
if (!conversation) return toFetchResponse(res);
|
|
386
|
+
const sessionId = conversation.id;
|
|
387
|
+
await updateConversation(dbClient_default)({
|
|
388
|
+
scopes: {
|
|
389
|
+
tenantId,
|
|
390
|
+
projectId
|
|
391
|
+
},
|
|
392
|
+
conversationId: sessionId,
|
|
393
|
+
data: {}
|
|
394
|
+
});
|
|
395
|
+
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => sessionId });
|
|
396
|
+
await (await getServer(validatedContext, executionContext, sessionId, credentialStores)).connect(transport);
|
|
397
|
+
await spoofTransportInitialization(transport, req, sessionId, conversation.metadata?.session_data?.mcpProtocolVersion);
|
|
398
|
+
logger.info({ sessionId }, "Server connected and transport initialized");
|
|
399
|
+
logger.info({
|
|
400
|
+
sessionId,
|
|
401
|
+
bodyKeys: Object.keys(body || {}),
|
|
402
|
+
bodyMethod: body?.method,
|
|
403
|
+
bodyId: body?.id,
|
|
404
|
+
requestHeaders: Object.fromEntries(Object.entries(req.headers || {}).filter(([k]) => k.startsWith("mcp-")))
|
|
405
|
+
}, "About to handle MCP request with existing session");
|
|
406
|
+
try {
|
|
407
|
+
await transport.handleRequest(req, res, body);
|
|
408
|
+
logger.info({ sessionId }, "Successfully handled MCP request");
|
|
409
|
+
} catch (transportError) {
|
|
410
|
+
logger.error({
|
|
411
|
+
sessionId,
|
|
412
|
+
error: transportError,
|
|
413
|
+
errorMessage: transportError instanceof Error ? transportError.message : "Unknown error"
|
|
414
|
+
}, "Transport handleRequest failed");
|
|
415
|
+
throw transportError;
|
|
416
|
+
}
|
|
417
|
+
return toFetchResponse(res);
|
|
418
|
+
};
|
|
419
|
+
/**
|
|
420
|
+
* Creates a JSON-RPC error response
|
|
421
|
+
*/
|
|
422
|
+
const createErrorResponse = (code, message, id = null) => ({
|
|
423
|
+
jsonrpc: "2.0",
|
|
424
|
+
error: {
|
|
425
|
+
code,
|
|
426
|
+
message
|
|
427
|
+
},
|
|
428
|
+
id
|
|
429
|
+
});
|
|
430
|
+
app.openapi(createRoute({
|
|
431
|
+
method: "post",
|
|
432
|
+
path: "/",
|
|
433
|
+
tags: ["MCP"],
|
|
434
|
+
summary: "MCP Protocol",
|
|
435
|
+
description: "Handles Model Context Protocol (MCP) JSON-RPC requests",
|
|
436
|
+
security: [{ bearerAuth: [] }],
|
|
437
|
+
request: { headers: HeadersScopeSchema },
|
|
438
|
+
responses: {
|
|
439
|
+
200: { description: "MCP response" },
|
|
440
|
+
401: { description: "Unauthorized - API key authentication required" },
|
|
441
|
+
404: { description: "Not Found - Agent not found" },
|
|
442
|
+
500: { description: "Internal Server Error" }
|
|
443
|
+
}
|
|
444
|
+
}), async (c) => {
|
|
445
|
+
try {
|
|
446
|
+
const paramValidation = validateRequestParameters(c);
|
|
447
|
+
if (!paramValidation.valid) return paramValidation.response;
|
|
448
|
+
const { executionContext } = paramValidation;
|
|
449
|
+
const body = c.get("requestBody") || {};
|
|
450
|
+
logger.info({
|
|
451
|
+
body,
|
|
452
|
+
bodyKeys: Object.keys(body || {})
|
|
453
|
+
}, "Parsed request body");
|
|
454
|
+
const isInitRequest = body.method === "initialize";
|
|
455
|
+
const { req, res } = toReqRes(c.req.raw);
|
|
456
|
+
const validatedContext = c.get("validatedContext") || {};
|
|
457
|
+
const credentialStores = c.get("credentialStores");
|
|
458
|
+
logger.info({ validatedContext }, "Validated context");
|
|
459
|
+
logger.info({ req }, "request");
|
|
460
|
+
if (isInitRequest) return await handleInitializationRequest(body, executionContext, validatedContext, req, res, c, credentialStores);
|
|
461
|
+
return await handleExistingSessionRequest(body, executionContext, validatedContext, req, res, credentialStores);
|
|
462
|
+
} catch (e) {
|
|
463
|
+
logger.error({
|
|
464
|
+
error: e instanceof Error ? e.message : e,
|
|
465
|
+
stack: e instanceof Error ? e.stack : void 0
|
|
466
|
+
}, "MCP request error");
|
|
467
|
+
return c.json(createErrorResponse(-32603, "Internal server error"), { status: 500 });
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
app.get("/", async (c) => {
|
|
471
|
+
logger.info({}, "Received GET MCP request");
|
|
472
|
+
return c.json({
|
|
473
|
+
jsonrpc: "2.0",
|
|
474
|
+
error: {
|
|
475
|
+
code: -32e3,
|
|
476
|
+
message: "Method not allowed."
|
|
477
|
+
},
|
|
478
|
+
id: null
|
|
479
|
+
}, { status: 405 });
|
|
480
|
+
});
|
|
481
|
+
app.delete("/", async (c) => {
|
|
482
|
+
logger.info({}, "Received DELETE MCP request");
|
|
483
|
+
return c.json({
|
|
484
|
+
jsonrpc: "2.0",
|
|
485
|
+
error: {
|
|
486
|
+
code: -32001,
|
|
487
|
+
message: "Method Not Allowed"
|
|
488
|
+
},
|
|
489
|
+
id: null
|
|
490
|
+
}, { status: 405 });
|
|
491
|
+
});
|
|
492
|
+
var mcp_default = app;
|
|
493
|
+
|
|
494
|
+
//#endregion
|
|
495
|
+
export { mcp_default as default };
|