@kraki/tentacle 0.15.4 → 0.16.1

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.
@@ -25,6 +25,8 @@ process.on('unhandledRejection', () => {
25
25
  import { RelayClient } from './relay-client.js';
26
26
  import { SessionManager } from './session-manager.js';
27
27
  import { KeyManager } from './key-manager.js';
28
+ import { AttachmentStore } from './attachment-store.js';
29
+ import { KrakiMcpServer } from './mcp/index.js';
28
30
  import { createLogger } from './logger.js';
29
31
  import { initStatusFile, updateRelayState, updateRegion, clearStatusFile } from './status-file.js';
30
32
  const logger = createLogger('daemon');
@@ -73,8 +75,32 @@ export async function startWorker() {
73
75
  }
74
76
  }
75
77
  // 3. Initialize components
76
- const adapter = new CopilotAdapter();
77
78
  const sessionManager = new SessionManager();
79
+ const attachmentStore = new AttachmentStore(sessionManager.getSessionsRoot());
80
+ // 3b. Start Kraki MCP server (in-process HTTP, loopback only). If bind
81
+ // fails, log and continue without it — daemon stays up.
82
+ let mcpInfo;
83
+ let mcpServer = null;
84
+ try {
85
+ mcpServer = new KrakiMcpServer({
86
+ version: getVersion(),
87
+ isSessionActive: (id) => sessionManager.isSessionActive(id),
88
+ });
89
+ const started = await mcpServer.start();
90
+ mcpInfo = {
91
+ urlForSession: started.urlForSession,
92
+ bearerToken: started.bearerToken,
93
+ };
94
+ logger.info({ port: started.port }, 'Kraki MCP server started');
95
+ }
96
+ catch (err) {
97
+ logger.warn({ err: err.message }, 'Kraki MCP server failed to start — kraki-show_image will be unavailable');
98
+ mcpServer = null;
99
+ }
100
+ const adapter = new CopilotAdapter({
101
+ attachmentStore,
102
+ ...(mcpInfo && { krakiMcp: mcpInfo }),
103
+ });
78
104
  const keyManager = new KeyManager();
79
105
  const deviceId = getOrCreateDeviceId();
80
106
  // 4. Start Copilot adapter
@@ -134,7 +160,7 @@ export async function startWorker() {
134
160
  token,
135
161
  reconnectDelay: 3000,
136
162
  version: getVersion(),
137
- }, keyManager);
163
+ }, keyManager, attachmentStore);
138
164
  relay.onStateChange = (state) => {
139
165
  logger.debug({ state }, 'Relay connection state changed');
140
166
  updateRelayState(state);
@@ -163,6 +189,12 @@ export async function startWorker() {
163
189
  clearStatusFile();
164
190
  relay.disconnect();
165
191
  await adapter.stop();
192
+ if (mcpServer) {
193
+ try {
194
+ await mcpServer.stop();
195
+ }
196
+ catch { /* already stopped */ }
197
+ }
166
198
  };
167
199
  process.on('SIGTERM', () => { shutdown().catch(() => { }).finally(() => process.exit(0)); });
168
200
  process.on('SIGINT', () => { shutdown().catch(() => { }).finally(() => process.exit(0)); });
@@ -1 +1 @@
1
- {"version":3,"file":"daemon-worker.js","sourceRoot":"","sources":["../src/daemon-worker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"daemon-worker.js","sourceRoot":"","sources":["../src/daemon-worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export { KrakiMcpServer } from './server.js';
2
+ export type { KrakiMcpServerOptions, KrakiMcpServerStartResult } from './server.js';
3
+ export { showImageTool, showImageHandler, SHOW_IMAGE_TOOL_NAME, SHOW_IMAGE_MAX_BYTES, SHOW_IMAGE_MIME_BY_EXT, } from './tools/show-image.js';
4
+ export { ToolRegistry } from './tools/index.js';
5
+ export type { RegisteredTool, ToolContext, ToolHandler } from './tools/index.js';
6
+ export { MCP_PROTOCOL_VERSION, JSON_RPC_INVALID_PARAMS, JSON_RPC_METHOD_NOT_FOUND, JSON_RPC_PARSE_ERROR, JSON_RPC_INVALID_REQUEST, } from './protocol.js';
7
+ export type { JsonRpcRequest, JsonRpcResponse, JsonRpcSuccess, JsonRpcError, McpInitializeResult, McpToolDefinition, McpToolsListResult, McpToolsCallParams, McpToolResult, McpContentBlock, } from './protocol.js';
@@ -0,0 +1,5 @@
1
+ export { KrakiMcpServer } from './server.js';
2
+ export { showImageTool, showImageHandler, SHOW_IMAGE_TOOL_NAME, SHOW_IMAGE_MAX_BYTES, SHOW_IMAGE_MIME_BY_EXT, } from './tools/show-image.js';
3
+ export { ToolRegistry } from './tools/index.js';
4
+ export { MCP_PROTOCOL_VERSION, JSON_RPC_INVALID_PARAMS, JSON_RPC_METHOD_NOT_FOUND, JSON_RPC_PARSE_ERROR, JSON_RPC_INVALID_REQUEST, } from './protocol.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,yBAAyB,EACzB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Minimal Model Context Protocol (MCP) types used by the Kraki MCP server.
3
+ *
4
+ * We implement only the surface we need:
5
+ * - JSON-RPC 2.0 envelope
6
+ * - `initialize` handshake
7
+ * - `tools/list` + `tools/call`
8
+ *
9
+ * Prompts, resources, sampling, completions, etc. are out of scope for v1.
10
+ */
11
+ export interface JsonRpcRequest {
12
+ jsonrpc: '2.0';
13
+ id: number | string | null;
14
+ method: string;
15
+ params?: unknown;
16
+ }
17
+ export interface JsonRpcSuccess {
18
+ jsonrpc: '2.0';
19
+ id: number | string | null;
20
+ result: unknown;
21
+ }
22
+ export interface JsonRpcError {
23
+ jsonrpc: '2.0';
24
+ id: number | string | null;
25
+ error: {
26
+ code: number;
27
+ message: string;
28
+ data?: unknown;
29
+ };
30
+ }
31
+ export type JsonRpcResponse = JsonRpcSuccess | JsonRpcError;
32
+ export declare const JSON_RPC_PARSE_ERROR = -32700;
33
+ export declare const JSON_RPC_INVALID_REQUEST = -32600;
34
+ export declare const JSON_RPC_METHOD_NOT_FOUND = -32601;
35
+ export declare const JSON_RPC_INVALID_PARAMS = -32602;
36
+ export declare const JSON_RPC_INTERNAL_ERROR = -32603;
37
+ /** MCP protocol version we declare during initialize. */
38
+ export declare const MCP_PROTOCOL_VERSION = "2024-11-05";
39
+ export interface McpInitializeParams {
40
+ protocolVersion: string;
41
+ capabilities?: Record<string, unknown>;
42
+ clientInfo?: {
43
+ name: string;
44
+ version: string;
45
+ };
46
+ }
47
+ export interface McpInitializeResult {
48
+ protocolVersion: string;
49
+ serverInfo: {
50
+ name: string;
51
+ version: string;
52
+ };
53
+ capabilities: {
54
+ tools?: {
55
+ listChanged?: boolean;
56
+ };
57
+ };
58
+ }
59
+ export interface McpToolDefinition {
60
+ name: string;
61
+ description?: string;
62
+ inputSchema: Record<string, unknown>;
63
+ }
64
+ export interface McpToolsListResult {
65
+ tools: McpToolDefinition[];
66
+ }
67
+ export interface McpToolsCallParams {
68
+ name: string;
69
+ arguments?: Record<string, unknown>;
70
+ }
71
+ export type McpContentBlock = {
72
+ type: 'text';
73
+ text: string;
74
+ } | {
75
+ type: 'image';
76
+ data: string;
77
+ mimeType: string;
78
+ };
79
+ export interface McpToolResult {
80
+ content: McpContentBlock[];
81
+ isError?: boolean;
82
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Minimal Model Context Protocol (MCP) types used by the Kraki MCP server.
3
+ *
4
+ * We implement only the surface we need:
5
+ * - JSON-RPC 2.0 envelope
6
+ * - `initialize` handshake
7
+ * - `tools/list` + `tools/call`
8
+ *
9
+ * Prompts, resources, sampling, completions, etc. are out of scope for v1.
10
+ */
11
+ export const JSON_RPC_PARSE_ERROR = -32700;
12
+ export const JSON_RPC_INVALID_REQUEST = -32600;
13
+ export const JSON_RPC_METHOD_NOT_FOUND = -32601;
14
+ export const JSON_RPC_INVALID_PARAMS = -32602;
15
+ export const JSON_RPC_INTERNAL_ERROR = -32603;
16
+ // ── MCP-specific ────────────────────────────────────────────────────────
17
+ /** MCP protocol version we declare during initialize. */
18
+ export const MCP_PROTOCOL_VERSION = '2024-11-05';
19
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/mcp/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAyBH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAK,CAAC;AAC3C,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,KAAK,CAAC;AAC/C,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,KAAK,CAAC;AAChD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,KAAK,CAAC;AAC9C,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,KAAK,CAAC;AAE9C,2EAA2E;AAE3E,yDAAyD;AACzD,MAAM,CAAC,MAAM,oBAAoB,GAAG,YAAY,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { ToolRegistry, type RegisteredTool } from './tools/index.js';
2
+ export interface KrakiMcpServerOptions {
3
+ /** Server semver — surfaced in `initialize` response. */
4
+ version: string;
5
+ /**
6
+ * Predicate used to validate the sessionId encoded in the URL path of
7
+ * `tools/call` requests. Other methods (`initialize`, `tools/list`) do not
8
+ * require it.
9
+ */
10
+ isSessionActive: (sessionId: string) => boolean;
11
+ }
12
+ export interface KrakiMcpServerStartResult {
13
+ /** Base URL up to (but excluding) the per-session segment. */
14
+ baseUrl: string;
15
+ /** Bearer token clients must send in `Authorization`. */
16
+ bearerToken: string;
17
+ /** Helper: build the per-session URL the SDK should connect to. */
18
+ urlForSession(sessionId: string): string;
19
+ /** Bound port (resolved after listen). */
20
+ port: number;
21
+ }
22
+ /**
23
+ * Tentacle-hosted MCP server.
24
+ *
25
+ * - Binds to 127.0.0.1 on a kernel-assigned port (no LAN exposure)
26
+ * - Requires `Authorization: Bearer <token>` on every request
27
+ * - Routes requests under `/mcp/<sessionId>`; the sessionId is injected into
28
+ * tool-call context. `initialize` and `tools/list` accept a `/mcp` URL too.
29
+ */
30
+ export declare class KrakiMcpServer {
31
+ private readonly registry;
32
+ private readonly token;
33
+ private readonly version;
34
+ private readonly isSessionActive;
35
+ private server;
36
+ private port;
37
+ constructor(options: KrakiMcpServerOptions, tools?: readonly RegisteredTool[]);
38
+ /** Expose registered tools (test helper). */
39
+ get tools(): ToolRegistry;
40
+ /** Bearer token (test helper). */
41
+ get bearerToken(): string;
42
+ start(): Promise<KrakiMcpServerStartResult>;
43
+ stop(): Promise<void>;
44
+ private handleRequest;
45
+ private checkAuth;
46
+ /**
47
+ * Extract the per-session segment from `/mcp` or `/mcp/<sessionId>`.
48
+ * Returns:
49
+ * - the sessionId string for `/mcp/<sessionId>`
50
+ * - '' for `/mcp` (allowed for initialize/tools/list)
51
+ * - null for any other URL shape (caller responds 404)
52
+ */
53
+ private extractSessionId;
54
+ private dispatch;
55
+ private handleInitialize;
56
+ private handleToolsList;
57
+ private handleToolsCall;
58
+ }
@@ -0,0 +1,253 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { createServer, } from 'node:http';
3
+ import { createLogger } from '../logger.js';
4
+ import { JSON_RPC_INTERNAL_ERROR, JSON_RPC_INVALID_PARAMS, JSON_RPC_INVALID_REQUEST, JSON_RPC_METHOD_NOT_FOUND, JSON_RPC_PARSE_ERROR, MCP_PROTOCOL_VERSION, } from './protocol.js';
5
+ import { ToolRegistry } from './tools/index.js';
6
+ import { showImageTool } from './tools/show-image.js';
7
+ const logger = createLogger('mcp-server');
8
+ const MAX_BODY_BYTES = 16 * 1024 * 1024; // generous, since show_image can return ~8 MB
9
+ const SERVER_NAME = 'kraki';
10
+ /**
11
+ * Tentacle-hosted MCP server.
12
+ *
13
+ * - Binds to 127.0.0.1 on a kernel-assigned port (no LAN exposure)
14
+ * - Requires `Authorization: Bearer <token>` on every request
15
+ * - Routes requests under `/mcp/<sessionId>`; the sessionId is injected into
16
+ * tool-call context. `initialize` and `tools/list` accept a `/mcp` URL too.
17
+ */
18
+ export class KrakiMcpServer {
19
+ registry = new ToolRegistry();
20
+ token = randomBytes(32).toString('hex');
21
+ version;
22
+ isSessionActive;
23
+ server = null;
24
+ port = 0;
25
+ constructor(options, tools = [showImageTool]) {
26
+ this.version = options.version;
27
+ this.isSessionActive = options.isSessionActive;
28
+ for (const tool of tools)
29
+ this.registry.register(tool);
30
+ }
31
+ /** Expose registered tools (test helper). */
32
+ get tools() {
33
+ return this.registry;
34
+ }
35
+ /** Bearer token (test helper). */
36
+ get bearerToken() {
37
+ return this.token;
38
+ }
39
+ async start() {
40
+ if (this.server)
41
+ throw new Error('KrakiMcpServer already started');
42
+ const server = createServer((req, res) => {
43
+ void this.handleRequest(req, res).catch((err) => {
44
+ logger.error({ err }, 'unhandled error in MCP request');
45
+ if (!res.headersSent) {
46
+ res.writeHead(500, { 'content-type': 'application/json' });
47
+ res.end(JSON.stringify({ error: 'internal_error' }));
48
+ }
49
+ });
50
+ });
51
+ await new Promise((resolve, reject) => {
52
+ server.once('error', reject);
53
+ server.listen(0, '127.0.0.1', () => {
54
+ server.off('error', reject);
55
+ resolve();
56
+ });
57
+ });
58
+ this.server = server;
59
+ this.port = server.address().port;
60
+ logger.info({ port: this.port, tools: this.registry.size() }, 'MCP server listening');
61
+ const baseUrl = `http://127.0.0.1:${this.port}/mcp`;
62
+ return {
63
+ baseUrl,
64
+ bearerToken: this.token,
65
+ port: this.port,
66
+ urlForSession: (sessionId) => `${baseUrl}/${encodeURIComponent(sessionId)}`,
67
+ };
68
+ }
69
+ async stop() {
70
+ if (!this.server)
71
+ return;
72
+ await new Promise((resolve) => {
73
+ this.server?.close(() => resolve());
74
+ });
75
+ this.server = null;
76
+ }
77
+ // ── Request handling ──────────────────────────────────────────────────
78
+ async handleRequest(req, res) {
79
+ if (req.method !== 'POST') {
80
+ res.writeHead(405, { 'content-type': 'application/json', 'allow': 'POST' });
81
+ res.end(JSON.stringify({ error: 'method_not_allowed' }));
82
+ return;
83
+ }
84
+ if (!this.checkAuth(req)) {
85
+ res.writeHead(401, { 'content-type': 'application/json' });
86
+ res.end(JSON.stringify({ error: 'unauthorized' }));
87
+ return;
88
+ }
89
+ const sessionId = this.extractSessionId(req.url ?? '');
90
+ // sessionId === null means malformed path; sessionId === '' means `/mcp` with no segment
91
+ if (sessionId === null) {
92
+ res.writeHead(404, { 'content-type': 'application/json' });
93
+ res.end(JSON.stringify({ error: 'not_found' }));
94
+ return;
95
+ }
96
+ let body;
97
+ try {
98
+ body = await readBody(req, MAX_BODY_BYTES);
99
+ }
100
+ catch (err) {
101
+ logger.warn({ err }, 'failed to read request body');
102
+ res.writeHead(413, { 'content-type': 'application/json' });
103
+ res.end(JSON.stringify({ error: 'payload_too_large' }));
104
+ return;
105
+ }
106
+ let rpc;
107
+ try {
108
+ rpc = JSON.parse(body);
109
+ }
110
+ catch {
111
+ res.writeHead(200, { 'content-type': 'application/json' });
112
+ res.end(JSON.stringify(rpcError(null, JSON_RPC_PARSE_ERROR, 'Parse error')));
113
+ return;
114
+ }
115
+ if (rpc.jsonrpc !== '2.0' || typeof rpc.method !== 'string') {
116
+ res.writeHead(200, { 'content-type': 'application/json' });
117
+ res.end(JSON.stringify(rpcError(rpc?.id ?? null, JSON_RPC_INVALID_REQUEST, 'Invalid request')));
118
+ return;
119
+ }
120
+ const response = await this.dispatch(rpc, sessionId);
121
+ res.writeHead(200, { 'content-type': 'application/json' });
122
+ res.end(JSON.stringify(response));
123
+ }
124
+ checkAuth(req) {
125
+ const header = req.headers['authorization'];
126
+ if (typeof header !== 'string')
127
+ return false;
128
+ if (!header.startsWith('Bearer '))
129
+ return false;
130
+ const presented = header.slice('Bearer '.length).trim();
131
+ // constant-time-ish compare (length differs → reject; otherwise compare)
132
+ if (presented.length !== this.token.length)
133
+ return false;
134
+ let diff = 0;
135
+ for (let i = 0; i < presented.length; i++) {
136
+ diff |= presented.charCodeAt(i) ^ this.token.charCodeAt(i);
137
+ }
138
+ return diff === 0;
139
+ }
140
+ /**
141
+ * Extract the per-session segment from `/mcp` or `/mcp/<sessionId>`.
142
+ * Returns:
143
+ * - the sessionId string for `/mcp/<sessionId>`
144
+ * - '' for `/mcp` (allowed for initialize/tools/list)
145
+ * - null for any other URL shape (caller responds 404)
146
+ */
147
+ extractSessionId(rawUrl) {
148
+ const qIdx = rawUrl.indexOf('?');
149
+ const pathname = qIdx === -1 ? rawUrl : rawUrl.slice(0, qIdx);
150
+ if (pathname === '/mcp' || pathname === '/mcp/')
151
+ return '';
152
+ if (!pathname.startsWith('/mcp/'))
153
+ return null;
154
+ const rest = pathname.slice('/mcp/'.length);
155
+ if (rest.length === 0 || rest.includes('/'))
156
+ return null;
157
+ try {
158
+ return decodeURIComponent(rest);
159
+ }
160
+ catch {
161
+ return null;
162
+ }
163
+ }
164
+ async dispatch(rpc, sessionId) {
165
+ try {
166
+ switch (rpc.method) {
167
+ case 'initialize':
168
+ return rpcOk(rpc.id, this.handleInitialize());
169
+ case 'notifications/initialized':
170
+ // No-op notification; per JSON-RPC, notifications have no `id`. The
171
+ // MCP spec sends this after initialize; we accept and respond with
172
+ // an empty success for any request form, but it usually arrives as a
173
+ // notification (no id). For notifications we still must not send a
174
+ // response per JSON-RPC; but Copilot SDK is happy with an empty 200.
175
+ return rpcOk(rpc.id, {});
176
+ case 'tools/list':
177
+ return rpcOk(rpc.id, this.handleToolsList());
178
+ case 'tools/call':
179
+ return await this.handleToolsCall(rpc, sessionId);
180
+ default:
181
+ return rpcError(rpc.id, JSON_RPC_METHOD_NOT_FOUND, `Method not found: ${rpc.method}`);
182
+ }
183
+ }
184
+ catch (err) {
185
+ logger.error({ err, method: rpc.method }, 'dispatch error');
186
+ return rpcError(rpc.id, JSON_RPC_INTERNAL_ERROR, `Internal error: ${err.message}`);
187
+ }
188
+ }
189
+ handleInitialize() {
190
+ return {
191
+ protocolVersion: MCP_PROTOCOL_VERSION,
192
+ serverInfo: { name: SERVER_NAME, version: this.version },
193
+ capabilities: { tools: { listChanged: false } },
194
+ };
195
+ }
196
+ handleToolsList() {
197
+ return { tools: this.registry.list() };
198
+ }
199
+ async handleToolsCall(rpc, sessionId) {
200
+ if (sessionId === '') {
201
+ return rpcError(rpc.id, JSON_RPC_INVALID_PARAMS, 'tools/call requires a session-scoped URL (/mcp/<sessionId>)');
202
+ }
203
+ if (!this.isSessionActive(sessionId)) {
204
+ return rpcError(rpc.id, JSON_RPC_INVALID_PARAMS, `Unknown or inactive session: ${sessionId}`);
205
+ }
206
+ const params = rpc.params;
207
+ if (!params || typeof params.name !== 'string') {
208
+ return rpcError(rpc.id, JSON_RPC_INVALID_PARAMS, 'tools/call requires { name, arguments? }');
209
+ }
210
+ const tool = this.registry.get(params.name);
211
+ if (!tool) {
212
+ return rpcError(rpc.id, JSON_RPC_METHOD_NOT_FOUND, `Unknown tool: ${params.name}`);
213
+ }
214
+ const args = (params.arguments ?? {});
215
+ let result;
216
+ try {
217
+ result = await tool.handler(args, { sessionId });
218
+ }
219
+ catch (err) {
220
+ logger.error({ err, tool: params.name }, 'tool handler threw');
221
+ result = {
222
+ content: [{ type: 'text', text: `Tool execution failed: ${err.message}` }],
223
+ isError: true,
224
+ };
225
+ }
226
+ return rpcOk(rpc.id, result);
227
+ }
228
+ }
229
+ // ── Helpers ─────────────────────────────────────────────────────────────
230
+ function rpcOk(id, result) {
231
+ return { jsonrpc: '2.0', id, result };
232
+ }
233
+ function rpcError(id, code, message, data) {
234
+ return { jsonrpc: '2.0', id, error: data === undefined ? { code, message } : { code, message, data } };
235
+ }
236
+ async function readBody(req, maxBytes) {
237
+ return new Promise((resolve, reject) => {
238
+ const chunks = [];
239
+ let size = 0;
240
+ req.on('data', (chunk) => {
241
+ size += chunk.length;
242
+ if (size > maxBytes) {
243
+ req.destroy();
244
+ reject(new Error(`body exceeds ${maxBytes} bytes`));
245
+ return;
246
+ }
247
+ chunks.push(chunk);
248
+ });
249
+ req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
250
+ req.on('error', reject);
251
+ });
252
+ }
253
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { McpToolDefinition, McpToolResult } from '../protocol.js';
2
+ /**
3
+ * Context passed to every tool handler.
4
+ *
5
+ * Includes the Kraki session ID this MCP call is bound to (resolved by the
6
+ * server from the URL path before dispatch). The agent never sees this — the
7
+ * sessionId is injected by tentacle, not supplied by the model.
8
+ */
9
+ export interface ToolContext {
10
+ /** Kraki session ID this tool call belongs to. */
11
+ sessionId: string;
12
+ }
13
+ export type ToolHandler = (args: Record<string, unknown>, ctx: ToolContext) => Promise<McpToolResult>;
14
+ export interface RegisteredTool {
15
+ definition: McpToolDefinition;
16
+ handler: ToolHandler;
17
+ }
18
+ export declare class ToolRegistry {
19
+ private tools;
20
+ register(tool: RegisteredTool): void;
21
+ get(name: string): RegisteredTool | undefined;
22
+ list(): McpToolDefinition[];
23
+ size(): number;
24
+ }
@@ -0,0 +1,19 @@
1
+ export class ToolRegistry {
2
+ tools = new Map();
3
+ register(tool) {
4
+ if (this.tools.has(tool.definition.name)) {
5
+ throw new Error(`Tool already registered: ${tool.definition.name}`);
6
+ }
7
+ this.tools.set(tool.definition.name, tool);
8
+ }
9
+ get(name) {
10
+ return this.tools.get(name);
11
+ }
12
+ list() {
13
+ return Array.from(this.tools.values(), (t) => t.definition);
14
+ }
15
+ size() {
16
+ return this.tools.size;
17
+ }
18
+ }
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/mcp/tools/index.ts"],"names":[],"mappings":"AAwBA,MAAM,OAAO,YAAY;IACf,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;IAElD,QAAQ,CAAC,IAAoB;QAC3B,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,4BAA4B,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;QACtE,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ import type { RegisteredTool, ToolHandler } from './index.js';
2
+ /** Hard cap on a single image's raw bytes. Stays well under the relay 10 MB
3
+ * frame cap once base64 + JSON wrapping + RSA-OAEP per-recipient keys are
4
+ * added by the broadcast path. */
5
+ export declare const SHOW_IMAGE_MAX_BYTES: number;
6
+ /** Allowed image MIME types, keyed by lowercase file extension. */
7
+ export declare const SHOW_IMAGE_MIME_BY_EXT: Readonly<Record<string, string>>;
8
+ export declare const SHOW_IMAGE_TOOL_NAME = "show_image";
9
+ export declare const showImageHandler: ToolHandler;
10
+ export declare const showImageTool: RegisteredTool;