@elsium-ai/mcp 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +154 -3
- package/dist/client.d.ts +5 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +232 -11
- package/dist/server.d.ts +21 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -186,6 +186,8 @@ interface MCPServerConfig {
|
|
|
186
186
|
name: string
|
|
187
187
|
version?: string
|
|
188
188
|
tools: Tool[]
|
|
189
|
+
resources?: MCPResourceHandler[]
|
|
190
|
+
prompts?: MCPPromptHandler[]
|
|
189
191
|
}
|
|
190
192
|
```
|
|
191
193
|
|
|
@@ -194,6 +196,8 @@ interface MCPServerConfig {
|
|
|
194
196
|
| `name` | `string` | yes | -- | Server name reported in the `initialize` handshake |
|
|
195
197
|
| `version` | `string` | no | `'0.1.0'` | Server version reported in the `initialize` handshake |
|
|
196
198
|
| `tools` | `Tool[]` | yes | -- | Array of ElsiumAI `Tool` objects to expose over MCP |
|
|
199
|
+
| `resources` | `MCPResourceHandler[]` | no | `[]` | Resource handlers to expose over MCP |
|
|
200
|
+
| `prompts` | `MCPPromptHandler[]` | no | `[]` | Prompt handlers to expose over MCP |
|
|
197
201
|
|
|
198
202
|
### `MCPServer`
|
|
199
203
|
|
|
@@ -210,7 +214,7 @@ interface MCPServer {
|
|
|
210
214
|
| Member | Description |
|
|
211
215
|
| ------ | ----------- |
|
|
212
216
|
| `running` | Read-only boolean indicating whether the server is currently listening for requests |
|
|
213
|
-
| `start()` | Begin listening on `stdin` for incoming JSON-RPC messages. Handles `initialize`, `notifications/initialized`, `tools/list`,
|
|
217
|
+
| `start()` | Begin listening on `stdin` for incoming JSON-RPC messages. Handles `initialize`, `notifications/initialized`, `tools/list`, `tools/call`, `resources/list`, `resources/read`, `prompts/list`, and `prompts/get` |
|
|
214
218
|
| `stop()` | Stop the server by setting the running flag to false |
|
|
215
219
|
|
|
216
220
|
### `createMCPServer(config)`
|
|
@@ -250,8 +254,155 @@ const server = createMCPServer({
|
|
|
250
254
|
})
|
|
251
255
|
|
|
252
256
|
await server.start()
|
|
253
|
-
|
|
254
|
-
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**Example -- server with resources and prompts**
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
import { createMCPServer } from '@elsium-ai/mcp'
|
|
263
|
+
import { createTool } from '@elsium-ai/tools'
|
|
264
|
+
import { z } from 'zod'
|
|
265
|
+
|
|
266
|
+
const greet = createTool({
|
|
267
|
+
name: 'greet',
|
|
268
|
+
description: 'Return a greeting for the given name',
|
|
269
|
+
input: z.object({ name: z.string() }),
|
|
270
|
+
execute: async ({ input }) => `Hello, ${input.name}!`,
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
const server = createMCPServer({
|
|
274
|
+
name: 'my-server',
|
|
275
|
+
version: '1.0.0',
|
|
276
|
+
tools: [greet],
|
|
277
|
+
resources: [
|
|
278
|
+
{
|
|
279
|
+
uri: 'config://app',
|
|
280
|
+
name: 'App Configuration',
|
|
281
|
+
description: 'Current application configuration',
|
|
282
|
+
mimeType: 'application/json',
|
|
283
|
+
read: async () => JSON.stringify({ env: 'production', version: '1.0.0' }),
|
|
284
|
+
},
|
|
285
|
+
],
|
|
286
|
+
prompts: [
|
|
287
|
+
{
|
|
288
|
+
name: 'summarize',
|
|
289
|
+
description: 'Summarize the given text',
|
|
290
|
+
arguments: [
|
|
291
|
+
{ name: 'text', description: 'Text to summarize', required: true },
|
|
292
|
+
{ name: 'style', description: 'Summary style (brief or detailed)', required: false },
|
|
293
|
+
],
|
|
294
|
+
get: async (args) => ({
|
|
295
|
+
messages: [
|
|
296
|
+
{
|
|
297
|
+
role: 'user',
|
|
298
|
+
content: `Summarize the following text in a ${args?.style ?? 'brief'} style:\n\n${args?.text}`,
|
|
299
|
+
},
|
|
300
|
+
],
|
|
301
|
+
}),
|
|
302
|
+
},
|
|
303
|
+
],
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
await server.start()
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## Resources
|
|
312
|
+
|
|
313
|
+
### `MCPResourceHandler`
|
|
314
|
+
|
|
315
|
+
Defines a resource that the MCP server can expose. Resources provide read-only data to clients (configuration, files, database records, etc.).
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
interface MCPResourceHandler {
|
|
319
|
+
uri: string
|
|
320
|
+
name: string
|
|
321
|
+
description?: string
|
|
322
|
+
mimeType?: string
|
|
323
|
+
read(): Promise<string>
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
| Property | Type | Required | Description |
|
|
328
|
+
| -------- | ---- | -------- | ----------- |
|
|
329
|
+
| `uri` | `string` | yes | Unique URI identifying the resource (e.g. `'config://app'`, `'file:///data.json'`) |
|
|
330
|
+
| `name` | `string` | yes | Human-readable name for the resource |
|
|
331
|
+
| `description` | `string` | no | Description of what the resource provides |
|
|
332
|
+
| `mimeType` | `string` | no | MIME type of the returned content |
|
|
333
|
+
| `read` | `() => Promise<string>` | yes | Async function that returns the resource content as a string |
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## Prompts
|
|
338
|
+
|
|
339
|
+
### `MCPPromptHandler`
|
|
340
|
+
|
|
341
|
+
Defines a prompt template that the MCP server can expose. Prompts allow clients to request pre-built message sequences with optional arguments.
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
interface MCPPromptHandler {
|
|
345
|
+
name: string
|
|
346
|
+
description?: string
|
|
347
|
+
arguments?: MCPPromptArgument[]
|
|
348
|
+
get(args?: Record<string, string>): Promise<{ messages: Array<{ role: string; content: string }> }>
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
interface MCPPromptArgument {
|
|
352
|
+
name: string
|
|
353
|
+
description?: string
|
|
354
|
+
required?: boolean
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
| Property | Type | Required | Description |
|
|
359
|
+
| -------- | ---- | -------- | ----------- |
|
|
360
|
+
| `name` | `string` | yes | Unique name for the prompt |
|
|
361
|
+
| `description` | `string` | no | Description of what the prompt does |
|
|
362
|
+
| `arguments` | `MCPPromptArgument[]` | no | Arguments the prompt accepts |
|
|
363
|
+
| `get` | `(args?) => Promise<{ messages }>` | yes | Async function that returns the prompt's message sequence |
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Client Resource and Prompt Methods
|
|
368
|
+
|
|
369
|
+
The `MCPClient` also supports listing and reading resources and prompts from a connected server:
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
interface MCPClient {
|
|
373
|
+
listResources(): Promise<MCPResourceInfo[]>
|
|
374
|
+
readResource(uri: string): Promise<string>
|
|
375
|
+
listPrompts(): Promise<MCPPromptInfo[]>
|
|
376
|
+
getPrompt(name: string, args?: Record<string, string>): Promise<{ messages: Array<{ role: string; content: string }> }>
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
| Method | Description |
|
|
381
|
+
| ------ | ----------- |
|
|
382
|
+
| `listResources()` | List all resources exposed by the connected MCP server |
|
|
383
|
+
| `readResource(uri)` | Read the content of a specific resource by URI |
|
|
384
|
+
| `listPrompts()` | List all prompts exposed by the connected MCP server |
|
|
385
|
+
| `getPrompt(name, args?)` | Get a prompt's message sequence, optionally passing arguments |
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
import { createMCPClient } from '@elsium-ai/mcp'
|
|
389
|
+
|
|
390
|
+
const client = createMCPClient({
|
|
391
|
+
name: 'my-client',
|
|
392
|
+
transport: 'stdio',
|
|
393
|
+
command: 'node',
|
|
394
|
+
args: ['./my-mcp-server.js'],
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
await client.connect()
|
|
398
|
+
|
|
399
|
+
const resources = await client.listResources()
|
|
400
|
+
const config = await client.readResource('config://app')
|
|
401
|
+
|
|
402
|
+
const prompts = await client.listPrompts()
|
|
403
|
+
const prompt = await client.getPrompt('summarize', { text: 'Long article...', style: 'brief' })
|
|
404
|
+
|
|
405
|
+
await client.disconnect()
|
|
255
406
|
```
|
|
256
407
|
|
|
257
408
|
---
|
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Tool } from '@elsium-ai/tools';
|
|
2
|
+
import type { MCPPrompt, MCPPromptMessage, MCPResource, MCPResourceContent } from './types';
|
|
2
3
|
export interface MCPClientStdioConfig {
|
|
3
4
|
name: string;
|
|
4
5
|
transport: 'stdio';
|
|
@@ -26,6 +27,10 @@ export interface MCPClient {
|
|
|
26
27
|
listTools(): Promise<MCPToolInfo[]>;
|
|
27
28
|
callTool(name: string, args: Record<string, unknown>): Promise<unknown>;
|
|
28
29
|
toElsiumTools(): Promise<Tool[]>;
|
|
30
|
+
listResources(): Promise<MCPResource[]>;
|
|
31
|
+
readResource(uri: string): Promise<MCPResourceContent[]>;
|
|
32
|
+
listPrompts(): Promise<MCPPrompt[]>;
|
|
33
|
+
getPrompt(name: string, args?: Record<string, string>): Promise<MCPPromptMessage[]>;
|
|
29
34
|
readonly connected: boolean;
|
|
30
35
|
}
|
|
31
36
|
export declare function createMCPClient(config: MCPClientConfig): MCPClient;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAoC,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAoC,MAAM,kBAAkB,CAAA;AAC9E,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAE3F,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,MAAM,eAAe,GAAG,oBAAoB,GAAG,mBAAmB,CAAA;AAExE,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACpC;AAgBD,MAAM,WAAW,SAAS;IACzB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3B,SAAS,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAAA;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACvE,aAAa,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IAChC,aAAa,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAAA;IACvC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAA;IACxD,WAAW,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAAA;IACnC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAA;IACnF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC3B;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CAKlE"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { createMCPClient } from './client';
|
|
2
2
|
export type { MCPClient, MCPClientConfig, MCPClientStdioConfig, MCPClientHttpConfig, MCPToolInfo, } from './client';
|
|
3
3
|
export { createMCPServer, createMCPHttpHandler } from './server';
|
|
4
|
-
export type { MCPServer, MCPServerConfig, MCPHttpHandlerConfig, MCPHttpHandler } from './server';
|
|
5
|
-
export type { JsonRpcRequest, JsonRpcResponse, MCPTransport } from './types';
|
|
4
|
+
export type { MCPServer, MCPServerConfig, MCPHttpHandlerConfig, MCPHttpHandler, MCPResourceHandler, MCPPromptHandler, } from './server';
|
|
5
|
+
export type { JsonRpcRequest, JsonRpcResponse, MCPTransport, MCPResource, MCPResourceContent, MCPPrompt, MCPPromptArgument, MCPPromptMessage, } from './types';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,YAAY,EACX,SAAS,EACT,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,WAAW,GACX,MAAM,UAAU,CAAA;AAGjB,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAChE,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,YAAY,EACX,SAAS,EACT,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,WAAW,GACX,MAAM,UAAU,CAAA;AAGjB,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAChE,YAAY,EACX,SAAS,EACT,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,GAChB,MAAM,UAAU,CAAA;AAGjB,YAAY,EACX,cAAc,EACd,eAAe,EACf,YAAY,EACZ,WAAW,EACX,kBAAkB,EAClB,SAAS,EACT,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,SAAS,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -259,6 +259,25 @@ function createHttpMCPClient(config) {
|
|
|
259
259
|
`);
|
|
260
260
|
return textContent ?? result;
|
|
261
261
|
},
|
|
262
|
+
async listResources() {
|
|
263
|
+
const result = await sendRequest("resources/list");
|
|
264
|
+
return result.resources ?? [];
|
|
265
|
+
},
|
|
266
|
+
async readResource(uri) {
|
|
267
|
+
const result = await sendRequest("resources/read", { uri });
|
|
268
|
+
return result.contents ?? [];
|
|
269
|
+
},
|
|
270
|
+
async listPrompts() {
|
|
271
|
+
const result = await sendRequest("prompts/list");
|
|
272
|
+
return result.prompts ?? [];
|
|
273
|
+
},
|
|
274
|
+
async getPrompt(name, args) {
|
|
275
|
+
const params = { name };
|
|
276
|
+
if (args)
|
|
277
|
+
params.arguments = args;
|
|
278
|
+
const result = await sendRequest("prompts/get", params);
|
|
279
|
+
return result.messages ?? [];
|
|
280
|
+
},
|
|
262
281
|
async toElsiumTools() {
|
|
263
282
|
const mcpTools = await this.listTools();
|
|
264
283
|
const client = this;
|
|
@@ -467,6 +486,25 @@ function createStdioMCPClient(config) {
|
|
|
467
486
|
`);
|
|
468
487
|
return textContent ?? result;
|
|
469
488
|
},
|
|
489
|
+
async listResources() {
|
|
490
|
+
const result = await sendRequest("resources/list");
|
|
491
|
+
return result.resources ?? [];
|
|
492
|
+
},
|
|
493
|
+
async readResource(uri) {
|
|
494
|
+
const result = await sendRequest("resources/read", { uri });
|
|
495
|
+
return result.contents ?? [];
|
|
496
|
+
},
|
|
497
|
+
async listPrompts() {
|
|
498
|
+
const result = await sendRequest("prompts/list");
|
|
499
|
+
return result.prompts ?? [];
|
|
500
|
+
},
|
|
501
|
+
async getPrompt(name, args) {
|
|
502
|
+
const params = { name };
|
|
503
|
+
if (args)
|
|
504
|
+
params.arguments = args;
|
|
505
|
+
const result = await sendRequest("prompts/get", params);
|
|
506
|
+
return result.messages ?? [];
|
|
507
|
+
},
|
|
470
508
|
async toElsiumTools() {
|
|
471
509
|
const mcpTools = await this.listTools();
|
|
472
510
|
const client = this;
|
|
@@ -515,6 +553,18 @@ var log3 = createLogger();
|
|
|
515
553
|
function createMCPServer(config) {
|
|
516
554
|
let running = false;
|
|
517
555
|
const toolMap = new Map(config.tools.map((t) => [t.name, t]));
|
|
556
|
+
const resourceMap = new Map((config.resources ?? []).map((r) => [r.uri, r]));
|
|
557
|
+
const promptMap = new Map((config.prompts ?? []).map((p) => [p.name, p]));
|
|
558
|
+
function buildCapabilities() {
|
|
559
|
+
const capabilities = {};
|
|
560
|
+
if (config.tools.length > 0)
|
|
561
|
+
capabilities.tools = {};
|
|
562
|
+
if (config.resources?.length)
|
|
563
|
+
capabilities.resources = {};
|
|
564
|
+
if (config.prompts?.length)
|
|
565
|
+
capabilities.prompts = {};
|
|
566
|
+
return capabilities;
|
|
567
|
+
}
|
|
518
568
|
function handleRequest(request) {
|
|
519
569
|
const id = request.id ?? 0;
|
|
520
570
|
switch (request.method) {
|
|
@@ -524,7 +574,7 @@ function createMCPServer(config) {
|
|
|
524
574
|
id,
|
|
525
575
|
result: {
|
|
526
576
|
protocolVersion: "2024-11-05",
|
|
527
|
-
capabilities:
|
|
577
|
+
capabilities: buildCapabilities(),
|
|
528
578
|
serverInfo: {
|
|
529
579
|
name: config.name,
|
|
530
580
|
version: config.version ?? "0.1.0"
|
|
@@ -553,6 +603,37 @@ function createMCPServer(config) {
|
|
|
553
603
|
case "tools/call": {
|
|
554
604
|
return null;
|
|
555
605
|
}
|
|
606
|
+
case "resources/list": {
|
|
607
|
+
const resources = (config.resources ?? []).map((r) => ({
|
|
608
|
+
uri: r.uri,
|
|
609
|
+
name: r.name,
|
|
610
|
+
description: r.description,
|
|
611
|
+
mimeType: r.mimeType
|
|
612
|
+
}));
|
|
613
|
+
return {
|
|
614
|
+
jsonrpc: "2.0",
|
|
615
|
+
id,
|
|
616
|
+
result: { resources }
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
case "resources/read": {
|
|
620
|
+
return null;
|
|
621
|
+
}
|
|
622
|
+
case "prompts/list": {
|
|
623
|
+
const prompts = (config.prompts ?? []).map((p) => ({
|
|
624
|
+
name: p.name,
|
|
625
|
+
description: p.description,
|
|
626
|
+
arguments: p.arguments
|
|
627
|
+
}));
|
|
628
|
+
return {
|
|
629
|
+
jsonrpc: "2.0",
|
|
630
|
+
id,
|
|
631
|
+
result: { prompts }
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
case "prompts/get": {
|
|
635
|
+
return null;
|
|
636
|
+
}
|
|
556
637
|
default: {
|
|
557
638
|
return {
|
|
558
639
|
jsonrpc: "2.0",
|
|
@@ -604,10 +685,60 @@ function createMCPServer(config) {
|
|
|
604
685
|
}
|
|
605
686
|
};
|
|
606
687
|
}
|
|
688
|
+
async function handleResourceRead(request) {
|
|
689
|
+
const id = request.id ?? 0;
|
|
690
|
+
const uri = request.params?.uri;
|
|
691
|
+
const resource = resourceMap.get(uri);
|
|
692
|
+
if (!resource) {
|
|
693
|
+
return {
|
|
694
|
+
jsonrpc: "2.0",
|
|
695
|
+
id,
|
|
696
|
+
error: { code: -32602, message: `Unknown resource: ${uri}` }
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
const data = await resource.read();
|
|
700
|
+
const content = typeof data === "string" ? { uri, mimeType: resource.mimeType, text: data } : { uri, mimeType: resource.mimeType, ...data };
|
|
701
|
+
return {
|
|
702
|
+
jsonrpc: "2.0",
|
|
703
|
+
id,
|
|
704
|
+
result: { contents: [content] }
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
async function handlePromptGet(request) {
|
|
708
|
+
const id = request.id ?? 0;
|
|
709
|
+
const name = request.params?.name;
|
|
710
|
+
const args = request.params?.arguments;
|
|
711
|
+
const prompt = promptMap.get(name);
|
|
712
|
+
if (!prompt) {
|
|
713
|
+
return {
|
|
714
|
+
jsonrpc: "2.0",
|
|
715
|
+
id,
|
|
716
|
+
error: { code: -32602, message: `Unknown prompt: ${name}` }
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
const messages = await prompt.get(args);
|
|
720
|
+
return {
|
|
721
|
+
jsonrpc: "2.0",
|
|
722
|
+
id,
|
|
723
|
+
result: { messages }
|
|
724
|
+
};
|
|
725
|
+
}
|
|
607
726
|
function writeLine(data) {
|
|
608
727
|
process.stdout.write(`${JSON.stringify(data)}
|
|
609
728
|
`);
|
|
610
729
|
}
|
|
730
|
+
async function handleAsyncRequest(request) {
|
|
731
|
+
switch (request.method) {
|
|
732
|
+
case "tools/call":
|
|
733
|
+
return handleToolCall(request);
|
|
734
|
+
case "resources/read":
|
|
735
|
+
return handleResourceRead(request);
|
|
736
|
+
case "prompts/get":
|
|
737
|
+
return handlePromptGet(request);
|
|
738
|
+
default:
|
|
739
|
+
return null;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
611
742
|
async function processRequestLine(line) {
|
|
612
743
|
if (!line.trim())
|
|
613
744
|
return;
|
|
@@ -617,9 +748,9 @@ function createMCPServer(config) {
|
|
|
617
748
|
} catch {
|
|
618
749
|
return;
|
|
619
750
|
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
writeLine(
|
|
751
|
+
const asyncResponse = await handleAsyncRequest(request);
|
|
752
|
+
if (asyncResponse) {
|
|
753
|
+
writeLine(asyncResponse);
|
|
623
754
|
return;
|
|
624
755
|
}
|
|
625
756
|
const response = handleRequest(request);
|
|
@@ -683,6 +814,15 @@ function createMCPServer(config) {
|
|
|
683
814
|
}
|
|
684
815
|
function createMCPHttpHandler(config) {
|
|
685
816
|
const toolMap = new Map(config.tools.map((t) => [t.name, t]));
|
|
817
|
+
const resourceMap = new Map((config.resources ?? []).map((r) => [r.uri, r]));
|
|
818
|
+
const promptMap = new Map((config.prompts ?? []).map((p) => [p.name, p]));
|
|
819
|
+
const httpCapabilities = {};
|
|
820
|
+
if (config.tools.length > 0)
|
|
821
|
+
httpCapabilities.tools = {};
|
|
822
|
+
if (config.resources?.length)
|
|
823
|
+
httpCapabilities.resources = {};
|
|
824
|
+
if (config.prompts?.length)
|
|
825
|
+
httpCapabilities.prompts = {};
|
|
686
826
|
function handleSyncRequest(request) {
|
|
687
827
|
const id = request.id ?? 0;
|
|
688
828
|
switch (request.method) {
|
|
@@ -692,7 +832,7 @@ function createMCPHttpHandler(config) {
|
|
|
692
832
|
id,
|
|
693
833
|
result: {
|
|
694
834
|
protocolVersion: "2024-11-05",
|
|
695
|
-
capabilities:
|
|
835
|
+
capabilities: httpCapabilities,
|
|
696
836
|
serverInfo: {
|
|
697
837
|
name: config.name,
|
|
698
838
|
version: config.version ?? "0.1.0"
|
|
@@ -716,6 +856,31 @@ function createMCPHttpHandler(config) {
|
|
|
716
856
|
})
|
|
717
857
|
}
|
|
718
858
|
};
|
|
859
|
+
case "resources/list":
|
|
860
|
+
return {
|
|
861
|
+
jsonrpc: "2.0",
|
|
862
|
+
id,
|
|
863
|
+
result: {
|
|
864
|
+
resources: (config.resources ?? []).map((r) => ({
|
|
865
|
+
uri: r.uri,
|
|
866
|
+
name: r.name,
|
|
867
|
+
description: r.description,
|
|
868
|
+
mimeType: r.mimeType
|
|
869
|
+
}))
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
case "prompts/list":
|
|
873
|
+
return {
|
|
874
|
+
jsonrpc: "2.0",
|
|
875
|
+
id,
|
|
876
|
+
result: {
|
|
877
|
+
prompts: (config.prompts ?? []).map((p) => ({
|
|
878
|
+
name: p.name,
|
|
879
|
+
description: p.description,
|
|
880
|
+
arguments: p.arguments
|
|
881
|
+
}))
|
|
882
|
+
}
|
|
883
|
+
};
|
|
719
884
|
default:
|
|
720
885
|
return {
|
|
721
886
|
jsonrpc: "2.0",
|
|
@@ -763,6 +928,56 @@ function createMCPHttpHandler(config) {
|
|
|
763
928
|
}
|
|
764
929
|
};
|
|
765
930
|
}
|
|
931
|
+
async function handleResourceRead(request) {
|
|
932
|
+
const id = request.id ?? 0;
|
|
933
|
+
const uri = request.params?.uri;
|
|
934
|
+
const resource = resourceMap.get(uri);
|
|
935
|
+
if (!resource) {
|
|
936
|
+
return {
|
|
937
|
+
jsonrpc: "2.0",
|
|
938
|
+
id,
|
|
939
|
+
error: { code: -32602, message: `Unknown resource: ${uri}` }
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
const data = await resource.read();
|
|
943
|
+
const content = typeof data === "string" ? { uri, mimeType: resource.mimeType, text: data } : { uri, mimeType: resource.mimeType, ...data };
|
|
944
|
+
return {
|
|
945
|
+
jsonrpc: "2.0",
|
|
946
|
+
id,
|
|
947
|
+
result: { contents: [content] }
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
async function handlePromptGet(request) {
|
|
951
|
+
const id = request.id ?? 0;
|
|
952
|
+
const name = request.params?.name;
|
|
953
|
+
const args = request.params?.arguments;
|
|
954
|
+
const prompt = promptMap.get(name);
|
|
955
|
+
if (!prompt) {
|
|
956
|
+
return {
|
|
957
|
+
jsonrpc: "2.0",
|
|
958
|
+
id,
|
|
959
|
+
error: { code: -32602, message: `Unknown prompt: ${name}` }
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
const messages = await prompt.get(args);
|
|
963
|
+
return {
|
|
964
|
+
jsonrpc: "2.0",
|
|
965
|
+
id,
|
|
966
|
+
result: { messages }
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
async function handleAsyncMethod(body) {
|
|
970
|
+
switch (body.method) {
|
|
971
|
+
case "tools/call":
|
|
972
|
+
return handleToolCall(body);
|
|
973
|
+
case "resources/read":
|
|
974
|
+
return handleResourceRead(body);
|
|
975
|
+
case "prompts/get":
|
|
976
|
+
return handlePromptGet(body);
|
|
977
|
+
default:
|
|
978
|
+
return null;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
766
981
|
return async (request) => {
|
|
767
982
|
if (request.method !== "POST") {
|
|
768
983
|
return new Response(JSON.stringify({ error: "Method not allowed" }), {
|
|
@@ -774,14 +989,20 @@ function createMCPHttpHandler(config) {
|
|
|
774
989
|
try {
|
|
775
990
|
body = await request.json();
|
|
776
991
|
} catch {
|
|
777
|
-
return new Response(JSON.stringify({
|
|
992
|
+
return new Response(JSON.stringify({
|
|
993
|
+
jsonrpc: "2.0",
|
|
994
|
+
id: 0,
|
|
995
|
+
error: { code: -32700, message: "Parse error" }
|
|
996
|
+
}), { status: 400, headers: { "Content-Type": "application/json" } });
|
|
778
997
|
}
|
|
779
|
-
|
|
780
|
-
if (
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
998
|
+
const asyncResponse = await handleAsyncMethod(body);
|
|
999
|
+
if (asyncResponse) {
|
|
1000
|
+
return new Response(JSON.stringify(asyncResponse), {
|
|
1001
|
+
status: 200,
|
|
1002
|
+
headers: { "Content-Type": "application/json" }
|
|
1003
|
+
});
|
|
784
1004
|
}
|
|
1005
|
+
const response = handleSyncRequest(body);
|
|
785
1006
|
if (!response) {
|
|
786
1007
|
return new Response(null, { status: 204 });
|
|
787
1008
|
}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
import type { Tool } from '@elsium-ai/tools';
|
|
2
|
+
import type { MCPPromptArgument, MCPPromptMessage } from './types';
|
|
3
|
+
export interface MCPResourceHandler {
|
|
4
|
+
uri: string;
|
|
5
|
+
name: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
mimeType?: string;
|
|
8
|
+
read: () => Promise<string | {
|
|
9
|
+
text?: string;
|
|
10
|
+
blob?: string;
|
|
11
|
+
}>;
|
|
12
|
+
}
|
|
13
|
+
export interface MCPPromptHandler {
|
|
14
|
+
name: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
arguments?: MCPPromptArgument[];
|
|
17
|
+
get: (args?: Record<string, string>) => Promise<MCPPromptMessage[]>;
|
|
18
|
+
}
|
|
2
19
|
export interface MCPServerConfig {
|
|
3
20
|
name: string;
|
|
4
21
|
version?: string;
|
|
5
22
|
tools: Tool[];
|
|
23
|
+
resources?: MCPResourceHandler[];
|
|
24
|
+
prompts?: MCPPromptHandler[];
|
|
6
25
|
}
|
|
7
26
|
export interface MCPServer {
|
|
8
27
|
start(): Promise<void>;
|
|
@@ -14,6 +33,8 @@ export interface MCPHttpHandlerConfig {
|
|
|
14
33
|
name: string;
|
|
15
34
|
version?: string;
|
|
16
35
|
tools: Tool[];
|
|
36
|
+
resources?: MCPResourceHandler[];
|
|
37
|
+
prompts?: MCPPromptHandler[];
|
|
17
38
|
}
|
|
18
39
|
export type MCPHttpHandler = (request: Request) => Promise<Response>;
|
|
19
40
|
export declare function createMCPHttpHandler(config: MCPHttpHandlerConfig): MCPHttpHandler;
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AAC5C,OAAO,KAAK,EAAmC,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAInG,MAAM,WAAW,kBAAkB;IAClC,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAC9D;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAC/B,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAA;CACnE;AAED,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,IAAI,EAAE,CAAA;IACb,SAAS,CAAC,EAAE,kBAAkB,EAAE,CAAA;IAChC,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAA;CAC5B;AAgBD,MAAM,WAAW,SAAS;IACzB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACtB,IAAI,IAAI,IAAI,CAAA;IACZ,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CACzB;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CA4SlE;AAID,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,IAAI,EAAE,CAAA;IACb,SAAS,CAAC,EAAE,kBAAkB,EAAE,CAAA;IAChC,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAA;CAC5B;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAEpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,cAAc,CAwOjF"}
|
package/dist/types.d.ts
CHANGED
|
@@ -15,4 +15,33 @@ export interface JsonRpcResponse {
|
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
export type MCPTransport = 'stdio' | 'http';
|
|
18
|
+
export interface MCPResource {
|
|
19
|
+
uri: string;
|
|
20
|
+
name: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
mimeType?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface MCPResourceContent {
|
|
25
|
+
uri: string;
|
|
26
|
+
mimeType?: string;
|
|
27
|
+
text?: string;
|
|
28
|
+
blob?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface MCPPrompt {
|
|
31
|
+
name: string;
|
|
32
|
+
description?: string;
|
|
33
|
+
arguments?: MCPPromptArgument[];
|
|
34
|
+
}
|
|
35
|
+
export interface MCPPromptArgument {
|
|
36
|
+
name: string;
|
|
37
|
+
description?: string;
|
|
38
|
+
required?: boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface MCPPromptMessage {
|
|
41
|
+
role: 'user' | 'assistant';
|
|
42
|
+
content: {
|
|
43
|
+
type: 'text';
|
|
44
|
+
text: string;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
18
47
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC9B,OAAO,EAAE,KAAK,CAAA;IACd,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,KAAK,CAAA;IACd,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CACzD;AAED,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,CAAA"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC9B,OAAO,EAAE,KAAK,CAAA;IACd,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,KAAK,CAAA;IACd,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CACzD;AAED,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,CAAA;AAE3C,MAAM,WAAW,WAAW;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,kBAAkB;IAClC,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAA;CAC/B;AAED,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAA;IAC1B,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CACvC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elsium-ai/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Model Context Protocol (MCP) support for ElsiumAI — bidirectional bridge",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Eric Utrera <ebutrera9103@gmail.com>",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"dev": "bun --watch src/index.ts"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@elsium-ai/core": "^0.
|
|
30
|
-
"@elsium-ai/tools": "^0.
|
|
29
|
+
"@elsium-ai/core": "^0.9.0",
|
|
30
|
+
"@elsium-ai/tools": "^0.9.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"typescript": "^5.7.0"
|