@jrmc/adonis-mcp 1.0.0-beta.9 → 1.0.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 CHANGED
@@ -31,13 +31,12 @@ AdonisJS MCP - Server MCP for your AdonisJS applications.
31
31
  - [x] JSON Schema with VineJs
32
32
  - [x] Bounce integration
33
33
  - [x] Auth helpers
34
- - [ ] Events
35
- - [ ] Logger
34
+ - [x] Starter kit
35
+ - [x] Demo applications
36
+ - [x] Events
37
+ - [x] Logger
36
38
  - [ ] Alternative transports (SSE)
37
39
  - [ ] Output tool
38
- - [ ] Login flow
39
- - [ ] Starter kit
40
- - [ ] Demo applications
41
40
 
42
41
  ## Installation & Configuration
43
42
 
@@ -1 +1 @@
1
- {"commands":[{"commandName":"mcp:inspector","description":"Open the MCP Inspector tool to debug and test MCP Servers.","help":"","namespace":"mcp","aliases":[],"flags":[],"args":[{"name":"transport","argumentName":"transport","required":true,"description":"Transport type","default":"http","type":"string"}],"options":{"startApp":true},"filePath":"inspector.js"},{"commandName":"make:mcp-prompt","description":"Create a new MCP prompt","help":"","namespace":"make","aliases":[],"flags":[],"args":[{"name":"name","argumentName":"name","required":true,"description":"Name of the prompt","type":"string"}],"options":{"startApp":true},"filePath":"make/prompt.js"},{"commandName":"make:mcp-resource","description":"Create a new MCP resource","help":"","namespace":"make","aliases":[],"flags":[],"args":[{"name":"name","argumentName":"name","required":true,"description":"Name of the resource","type":"string"}],"options":{"startApp":true},"filePath":"make/resource.js"},{"commandName":"make:mcp-tool","description":"Create a new MCP tool","help":"","namespace":"make","aliases":[],"flags":[],"args":[{"name":"name","argumentName":"name","required":true,"description":"Name of the tool","type":"string"}],"options":{"startApp":true},"filePath":"make/tool.js"},{"commandName":"mcp:start","description":"Start the MCP server stdio transport","help":"","namespace":"mcp","aliases":[],"flags":[],"args":[],"options":{"startApp":true},"filePath":"start.js"}],"version":1}
1
+ {"commands":[{"commandName":"mcp:inspector","description":"Open the MCP Inspector tool to debug and test MCP Servers.","help":"","namespace":"mcp","aliases":["mcp:inspect"],"flags":[],"args":[{"name":"transport","argumentName":"transport","required":true,"description":"Transport type","default":"http","type":"string"}],"options":{"startApp":true},"filePath":"inspector.js"},{"commandName":"make:mcp-prompt","description":"Create a new MCP prompt","help":"","namespace":"make","aliases":[],"flags":[],"args":[{"name":"name","argumentName":"name","required":true,"description":"Name of the prompt","type":"string"}],"options":{"startApp":true},"filePath":"make/prompt.js"},{"commandName":"make:mcp-resource","description":"Create a new MCP resource","help":"","namespace":"make","aliases":[],"flags":[],"args":[{"name":"name","argumentName":"name","required":true,"description":"Name of the resource","type":"string"}],"options":{"startApp":true},"filePath":"make/resource.js"},{"commandName":"make:mcp-tool","description":"Create a new MCP tool","help":"","namespace":"make","aliases":[],"flags":[],"args":[{"name":"name","argumentName":"name","required":true,"description":"Name of the tool","type":"string"}],"options":{"startApp":true},"filePath":"make/tool.js"},{"commandName":"mcp:start","description":"Start the MCP server stdio transport","help":"","namespace":"mcp","aliases":[],"flags":[],"args":[],"options":{"startApp":true},"filePath":"start.js"}],"version":1}
@@ -9,6 +9,7 @@ import { BaseCommand } from '@adonisjs/core/ace';
9
9
  export default class Inspector extends BaseCommand {
10
10
  static commandName: string;
11
11
  static description: string;
12
+ static aliases: string[];
12
13
  static options: CommandOptions;
13
14
  transport: string;
14
15
  run(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"inspector.d.ts","sourceRoot":"","sources":["../../commands/inspector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAG9D,OAAO,EAAQ,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEtD,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,WAAW;IAChD,MAAM,CAAC,WAAW,SAAkB;IACpC,MAAM,CAAC,WAAW,SAA+D;IAEjF,MAAM,CAAC,OAAO,EAAE,cAAc,CAE7B;IAGO,SAAS,EAAE,MAAM,CAAA;IAEnB,GAAG;CAoCV"}
1
+ {"version":3,"file":"inspector.d.ts","sourceRoot":"","sources":["../../commands/inspector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAG9D,OAAO,EAAQ,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEtD,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,WAAW;IAChD,MAAM,CAAC,WAAW,SAAkB;IACpC,MAAM,CAAC,WAAW,SAA+D;IACjF,MAAM,CAAC,OAAO,WAAkB;IAEhC,MAAM,CAAC,OAAO,EAAE,cAAc,CAE7B;IAGO,SAAS,EAAE,MAAM,CAAA;IAEnB,GAAG;CAoCV"}
@@ -15,6 +15,7 @@ import { args, BaseCommand } from '@adonisjs/core/ace';
15
15
  export default class Inspector extends BaseCommand {
16
16
  static commandName = 'mcp:inspector';
17
17
  static description = 'Open the MCP Inspector tool to debug and test MCP Servers.';
18
+ static aliases = ['mcp:inspect'];
18
19
  static options = {
19
20
  startApp: true,
20
21
  };
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../commands/make/prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAE9D,OAAO,EAAQ,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAItD,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,WAAW;IACjD,MAAM,CAAC,WAAW,SAAoB;IACtC,MAAM,CAAC,WAAW,SAA4B;IAE9C,MAAM,CAAC,OAAO,EAAE,cAAc,CAE7B;IAGO,IAAI,EAAE,MAAM,CAAA;IAEd,GAAG;CAUV"}
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../commands/make/prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAE9D,OAAO,EAAQ,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAItD,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,WAAW;IACjD,MAAM,CAAC,WAAW,SAAoB;IACtC,MAAM,CAAC,WAAW,SAA4B;IAE9C,MAAM,CAAC,OAAO,EAAE,cAAc,CAE7B;IAGO,IAAI,EAAE,MAAM,CAAA;IAEd,GAAG;CAcV"}
@@ -21,7 +21,10 @@ export default class MakePrompt extends BaseCommand {
21
21
  };
22
22
  async run() {
23
23
  const codemods = await this.createCodemods();
24
- const stubPath = `make/mcp/prompts/main.ts.stub`;
24
+ let stubPath = `make/mcp/prompts/main.ts.stub`;
25
+ if (this.app.usingVineJS) {
26
+ stubPath = `make/mcp/prompts/with_vine.ts.stub`;
27
+ }
25
28
  await codemods.makeUsingStub(stubsRoot, stubPath, {
26
29
  name: string.pascalCase(this.name),
27
30
  });
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../../commands/make/tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAE9D,OAAO,EAAQ,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAItD,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,WAAW;IAC/C,MAAM,CAAC,WAAW,SAAkB;IACpC,MAAM,CAAC,WAAW,SAA0B;IAE5C,MAAM,CAAC,OAAO,EAAE,cAAc,CAE7B;IAGO,IAAI,EAAE,MAAM,CAAA;IAEd,GAAG;CAUV"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../../commands/make/tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAE9D,OAAO,EAAQ,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAItD,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,WAAW;IAC/C,MAAM,CAAC,WAAW,SAAkB;IACpC,MAAM,CAAC,WAAW,SAA0B;IAE5C,MAAM,CAAC,OAAO,EAAE,cAAc,CAE7B;IAGO,IAAI,EAAE,MAAM,CAAA;IAEd,GAAG;CAcV"}
@@ -21,7 +21,10 @@ export default class MakeTool extends BaseCommand {
21
21
  };
22
22
  async run() {
23
23
  const codemods = await this.createCodemods();
24
- const stubPath = `make/mcp/tools/main.ts.stub`;
24
+ let stubPath = `make/mcp/tools/main.ts.stub`;
25
+ if (this.app.usingVineJS) {
26
+ stubPath = `make/mcp/tools/with_vine.ts.stub`;
27
+ }
25
28
  await codemods.makeUsingStub(stubsRoot, stubPath, {
26
29
  name: string.pascalCase(this.name),
27
30
  });
@@ -1 +1 @@
1
- {"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../configure.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,SAAS,MAAM,mCAAmC,CAAA;AAG9D,wBAAsB,SAAS,CAAC,OAAO,EAAE,SAAS,iBA4BjD"}
1
+ {"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../configure.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,SAAS,MAAM,mCAAmC,CAAA;AAI9D,wBAAsB,SAAS,CAAC,OAAO,EAAE,SAAS,iBAsCjD"}
@@ -4,9 +4,19 @@
4
4
  * @license MIT
5
5
  * @copyright Jeremy Chaufourier <jeremy@chaufourier.fr>
6
6
  */
7
+ import { mkdir } from 'node:fs/promises';
7
8
  import { stubsRoot } from './stubs/main.js';
8
9
  export async function configure(command) {
9
10
  const codemods = await command.createCodemods();
11
+ /**
12
+ * Create mcp directory if it doesn't exist
13
+ */
14
+ const mcpDirectory = command.app.rcFile.directories['mcp'] || 'app/mcp/';
15
+ await Promise.all([
16
+ mkdir(command.app.makePath(mcpDirectory, 'tools'), { recursive: true }),
17
+ mkdir(command.app.makePath(mcpDirectory, 'resources'), { recursive: true }),
18
+ mkdir(command.app.makePath(mcpDirectory, 'prompts'), { recursive: true }),
19
+ ]);
10
20
  /**
11
21
  * Create default config file
12
22
  */
package/build/index.d.ts CHANGED
@@ -3,6 +3,5 @@ export { Tool } from './src/server/tool.js';
3
3
  export { Resource } from './src/server/resource.js';
4
4
  export { Prompt } from './src/server/prompt.js';
5
5
  export * as McpResponse from './src/response.js';
6
- export { default as McpBouncer } from './src/server/mcp_bouncer.js';
7
6
  export { defineConfig } from './src/define_config.js';
8
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAC/C,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAC/C,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA"}
package/build/index.js CHANGED
@@ -3,5 +3,4 @@ export { Tool } from './src/server/tool.js';
3
3
  export { Resource } from './src/server/resource.js';
4
4
  export { Prompt } from './src/server/prompt.js';
5
5
  export * as McpResponse from './src/response.js';
6
- export { default as McpBouncer } from './src/server/mcp_bouncer.js';
7
6
  export { defineConfig } from './src/define_config.js';
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import type { ApplicationService } from '@adonisjs/core/types';
8
8
  import type { RouteGroup } from '@adonisjs/core/http';
9
+ import type { JsonRpcRequest, JsonRpcResponse } from '../src/types/jsonrpc.js';
9
10
  import McpServer from '../src/server.js';
10
11
  export default class McpProvider {
11
12
  protected app: ApplicationService;
@@ -26,5 +27,9 @@ declare module '@adonisjs/core/types' {
26
27
  interface ContainerBindings {
27
28
  'jrmc.mcp': McpServer;
28
29
  }
30
+ interface EventsList {
31
+ 'mcp:request': JsonRpcRequest;
32
+ 'mcp:response': JsonRpcResponse;
33
+ }
29
34
  }
30
35
  //# sourceMappingURL=mcp_provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp_provider.d.ts","sourceRoot":"","sources":["../../providers/mcp_provider.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAMrD,OAAO,SAAS,MAAM,kBAAkB,CAAA;AAExC,MAAM,CAAC,OAAO,OAAO,WAAW;IAClB,SAAS,CAAC,GAAG,EAAE,kBAAkB;gBAAvB,GAAG,EAAE,kBAAkB;IAE7C,QAAQ;IAQF,KAAK;IAeL,aAAa;IAIb,iBAAiB;IAIjB,eAAe;IAIf,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,QAAQ;CA6C3D;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,MAAM;QACd,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,UAAU,CAAA;KACtC;CACF;AAED,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,iBAAiB;QACzB,UAAU,EAAE,SAAS,CAAA;KACtB;CACF"}
1
+ {"version":3,"file":"mcp_provider.d.ts","sourceRoot":"","sources":["../../providers/mcp_provider.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAErD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAK9E,OAAO,SAAS,MAAM,kBAAkB,CAAA;AAExC,MAAM,CAAC,OAAO,OAAO,WAAW;IAClB,SAAS,CAAC,GAAG,EAAE,kBAAkB;gBAAvB,GAAG,EAAE,kBAAkB;IAE7C,QAAQ;IAUF,KAAK;IAeL,aAAa;IAIb,iBAAiB;IAIjB,eAAe;IAIf,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,QAAQ;CA6C3D;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,MAAM;QACd,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,UAAU,CAAA;KACtC;CACF;AAED,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,iBAAiB;QACzB,UAAU,EAAE,SAAS,CAAA;KACtB;IAED,UAAU,UAAU;QAClB,aAAa,EAAE,cAAc,CAAA;QAC7B,cAAc,EAAE,eAAe,CAAA;KAChC;CACF"}
@@ -16,7 +16,9 @@ export default class McpProvider {
16
16
  register() {
17
17
  this.app.container.singleton('jrmc.mcp', async () => {
18
18
  const config = this.app.config.get('mcp', {});
19
- return new McpServer(config);
19
+ const logger = await this.app.container.make('logger');
20
+ const emitter = await this.app.container.make('emitter');
21
+ return new McpServer(config, { logger, emitter });
20
22
  });
21
23
  }
22
24
  async start() {
@@ -8,7 +8,12 @@ import type { McpConfig } from './types/config.js';
8
8
  import type { JsonRpcRequest } from './types/jsonrpc.js';
9
9
  import type { ToolList, ResourceList, PromptList } from './types/method.js';
10
10
  import type { Transport } from './server/contracts/transport.js';
11
+ import type { LoggerService, EmitterService } from '@adonisjs/core/types';
11
12
  import ServerContext from './server/context.js';
13
+ type Services = {
14
+ logger: LoggerService;
15
+ emitter: EmitterService;
16
+ };
12
17
  export default class Server {
13
18
  #private;
14
19
  config: McpConfig;
@@ -35,7 +40,7 @@ export default class Server {
35
40
  'completion/complete': () => Promise<typeof import("./server/methods/completion.js")>;
36
41
  ping: () => Promise<typeof import("./server/methods/ping.js")>;
37
42
  };
38
- constructor(config: McpConfig);
43
+ constructor(config: McpConfig, services?: Services);
39
44
  addCapability(key: string, value?: boolean): void;
40
45
  addTool(item: ToolList): void;
41
46
  addResource(item: ResourceList): void;
@@ -45,4 +50,5 @@ export default class Server {
45
50
  handle(jsonRequest: JsonRpcRequest): Promise<void | null>;
46
51
  createContext(jsonRpcRequest: JsonRpcRequest): ServerContext;
47
52
  }
53
+ export {};
48
54
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EACZ,UAAU,EAEX,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAA;AAIhE,OAAO,aAAa,MAAM,qBAAqB,CAAA;AAG/C,MAAM,CAAC,OAAO,OAAO,MAAM;;IAGzB,MAAM,EAAE,SAAS,CAAA;IACjB,IAAI,EAAE,MAAM,CAAwB;IACpC,OAAO,EAAE,MAAM,CAAU;IACzB,YAAY,EAAE,MAAM,CAA2E;IAE/F,wBAAwB,EAAE,MAAM,EAAE,CAA+B;IAEjE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAUhC;IAED,KAAK,EAAE,QAAQ,CAAK;IACpB,SAAS,EAAE,YAAY,CAAK;IAC5B,iBAAiB,EAAE,YAAY,CAAK;IACpC,OAAO,EAAE,UAAU,CAAK;IAExB,mBAAmB,EAAE,MAAM,CAAK;IAChC,uBAAuB,EAAE,MAAM,CAAK;IAEpC,OAAO;;;;;;;;;;;MAWN;gBAEW,MAAM,EAAE,SAAS;IA4B7B,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE,OAAc;IAchD,OAAO,CAAC,IAAI,EAAE,QAAQ;IAGtB,WAAW,CAAC,IAAI,EAAE,YAAY;IAG9B,mBAAmB,CAAC,IAAI,EAAE,YAAY;IAGtC,SAAS,CAAC,IAAI,EAAE,UAAU;IAIpB,OAAO,CAAC,SAAS,EAAE,SAAS;IAI5B,MAAM,CAAC,WAAW,EAAE,cAAc;IA6CxC,aAAa,CAAC,cAAc,EAAE,cAAc;CAgB7C"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EACZ,UAAU,EAEX,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAA;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAIzE,OAAO,aAAa,MAAM,qBAAqB,CAAA;AAG/C,KAAK,QAAQ,GAAG;IACd,MAAM,EAAE,aAAa,CAAA;IACrB,OAAO,EAAE,cAAc,CAAA;CACxB,CAAA;AAED,MAAM,CAAC,OAAO,OAAO,MAAM;;IAKzB,MAAM,EAAE,SAAS,CAAA;IACjB,IAAI,EAAE,MAAM,CAAwB;IACpC,OAAO,EAAE,MAAM,CAAU;IACzB,YAAY,EAAE,MAAM,CAA2E;IAE/F,wBAAwB,EAAE,MAAM,EAAE,CAA+B;IAEjE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAUhC;IAED,KAAK,EAAE,QAAQ,CAAK;IACpB,SAAS,EAAE,YAAY,CAAK;IAC5B,iBAAiB,EAAE,YAAY,CAAK;IACpC,OAAO,EAAE,UAAU,CAAK;IAExB,mBAAmB,EAAE,MAAM,CAAK;IAChC,uBAAuB,EAAE,MAAM,CAAK;IAEpC,OAAO;;;;;;;;;;;MAWN;gBAEW,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,QAAQ;IA+BlD,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE,OAAc;IAchD,OAAO,CAAC,IAAI,EAAE,QAAQ;IAGtB,WAAW,CAAC,IAAI,EAAE,YAAY;IAG9B,mBAAmB,CAAC,IAAI,EAAE,YAAY;IAGtC,SAAS,CAAC,IAAI,EAAE,UAAU;IAIpB,OAAO,CAAC,SAAS,EAAE,SAAS;IAI5B,MAAM,CAAC,WAAW,EAAE,cAAc;IAyDxC,aAAa,CAAC,cAAc,EAAE,cAAc;CAgB7C"}
@@ -9,6 +9,8 @@ import { ErrorCode } from './enums/error.js';
9
9
  import ServerContext from './server/context.js';
10
10
  import JsonRpcException from './server/exceptions/jsonrpc_exception.js';
11
11
  export default class Server {
12
+ #logger;
13
+ #emitter;
12
14
  #transport;
13
15
  config;
14
16
  name = 'AdonisJS MCP Server';
@@ -44,7 +46,7 @@ export default class Server {
44
46
  'completion/complete': () => import('./server/methods/completion.js'),
45
47
  'ping': () => import('./server/methods/ping.js'),
46
48
  };
47
- constructor(config) {
49
+ constructor(config, services) {
48
50
  this.config = config;
49
51
  if (config.name) {
50
52
  this.name = config.name;
@@ -64,6 +66,8 @@ export default class Server {
64
66
  if (config.completions) {
65
67
  this.addCapability('completions');
66
68
  }
69
+ this.#logger = services?.logger;
70
+ this.#emitter = services?.emitter;
67
71
  }
68
72
  addCapability(key, value = true) {
69
73
  if (key.includes('.')) {
@@ -91,6 +95,7 @@ export default class Server {
91
95
  this.#transport = transport;
92
96
  }
93
97
  async handle(jsonRequest) {
98
+ this.#emitter?.emit('mcp:request', jsonRequest);
94
99
  // INGORE NOTIFICATIONS FOR NOW
95
100
  if (jsonRequest.method.startsWith('notifications/')) {
96
101
  return null;
@@ -111,19 +116,31 @@ export default class Server {
111
116
  const instance = new MethodClass();
112
117
  // Ensure the instance is treated as MethodInterface when calling handle to satisfy TS
113
118
  const response = await instance.handle(mcpContext);
119
+ this.#emitter?.emit('mcp:response', response);
114
120
  this.#transport.send(response);
115
121
  }
116
122
  else {
117
- throw new JsonRpcException(`The method ${jsonRequest.method} was not found.`, ErrorCode.MethodNotFound, jsonRequest.id);
123
+ const jsonRpcException = new JsonRpcException(`The method ${jsonRequest.method} was not found.`, ErrorCode.MethodNotFound, jsonRequest.id);
124
+ throw jsonRpcException;
118
125
  }
119
126
  }
120
127
  catch (error) {
128
+ let response;
121
129
  if (error instanceof JsonRpcException) {
122
- return this.#transport.send(error.toJsonRpcResponse());
130
+ response = error.toJsonRpcResponse();
131
+ this.#logger?.error(response, error.message);
123
132
  }
124
- return this.#transport.send(new JsonRpcException('Internal error', ErrorCode.InternalError, jsonRequest.id, {
125
- error,
126
- }).toJsonRpcResponse());
133
+ else {
134
+ response = new JsonRpcException('Internal error', ErrorCode.InternalError, jsonRequest.id, {
135
+ error: {
136
+ name: error.name,
137
+ message: error.message,
138
+ },
139
+ }).toJsonRpcResponse();
140
+ this.#logger?.error(error);
141
+ }
142
+ this.#emitter?.emit('mcp:response', response);
143
+ return this.#transport.send(response);
127
144
  }
128
145
  }
129
146
  createContext(jsonRpcRequest) {
@@ -24,7 +24,7 @@ export default class {{ className }} extends Prompt<Schema> {
24
24
  async handle({ args, response }: PromptContext<Schema>) {
25
25
  return [
26
26
  response.text('Hello, world!'),
27
- response.text(args?.text)
27
+ response.text(args?.text!)
28
28
  ]
29
29
  }
30
30
 
@@ -0,0 +1,40 @@
1
+ {{#var className = `${name}Prompt`}}
2
+ {{#var promptName = string(name).snakeCase()}}
3
+ {{#var resourceFileName = string(className).snakeCase().ext('.ts').toString()}}
4
+ {{{
5
+ exports({
6
+ to: app.makePath(app.rcFile.directories['mcp'] || 'app/mcp/', `prompts/`, resourceFileName)
7
+ })
8
+ }}}
9
+ import type { PromptContext } from '@jrmc/adonis-mcp/types/context'
10
+ import type { BaseSchema } from '@jrmc/adonis-mcp/types/method'
11
+
12
+ import { Prompt } from '@jrmc/adonis-mcp'
13
+ import vine from '@vinejs/vine'
14
+
15
+ type Schema = BaseSchema<{
16
+ text: { type: "string" }
17
+ }>
18
+
19
+ const vineSchema = vine.object({
20
+ text: vine.string().meta({
21
+ description: 'Description text argument',
22
+ }),
23
+ })
24
+
25
+ export default class {{ className }} extends Prompt<Schema> {
26
+ name = '{{ promptName }}'
27
+ title = 'Prompt title'
28
+ description = 'Prompt description'
29
+
30
+ async handle({ args, response }: PromptContext<Schema>) {
31
+ return [
32
+ response.text('Hello, world!'),
33
+ response.text(args?.text!)
34
+ ]
35
+ }
36
+
37
+ schema() {
38
+ return vine.create(vineSchema).toJSONSchema() as Schema
39
+ }
40
+ }
@@ -0,0 +1,37 @@
1
+ {{#var className = `${name}Tool`}}
2
+ {{#var toolName = string(name).snakeCase()}}
3
+ {{#var resourceFileName = string(className).snakeCase().ext('.ts').toString()}}
4
+ {{{
5
+ exports({
6
+ to: app.makePath(app.rcFile.directories['mcp'] || 'app/mcp/', `tools/`, resourceFileName)
7
+ })
8
+ }}}
9
+ import type { ToolContext } from '@jrmc/adonis-mcp/types/context'
10
+ import type { BaseSchema } from '@jrmc/adonis-mcp/types/method'
11
+
12
+ import { Tool } from '@jrmc/adonis-mcp'
13
+ import vine from '@vinejs/vine'
14
+
15
+ type Schema = BaseSchema<{
16
+ name: { type: "string" }
17
+ }>
18
+
19
+ const vineSchema = vine.object({
20
+ name: vine.string().meta({
21
+ description: 'Description text argument',
22
+ }),
23
+ })
24
+
25
+ export default class {{ className }} extends Tool<Schema> {
26
+ name = '{{ toolName }}'
27
+ title = 'Tool title'
28
+ description = 'Tool description'
29
+
30
+ async handle({ args, response }: ToolContext<Schema>) {
31
+ return response.text({{ "`Hello, ${args?.name}`" }})
32
+ }
33
+
34
+ schema() {
35
+ return vine.create(vineSchema).toJSONSchema() as Schema
36
+ }
37
+ }
@@ -3,13 +3,12 @@
3
3
  }}}
4
4
  import type { HttpContext } from '@adonisjs/core/http'
5
5
  import type { NextFn } from '@adonisjs/core/types/http'
6
+ // import type * as abilities from '#abilities/main'
7
+ // import type { policies } from '#generated/policies'
8
+ // import type McpBouncer from '@jrmc/adonis-mcp/bouncer'
6
9
 
7
10
  import crypto from 'node:crypto'
8
11
 
9
- // import { policies } from '#policies/main'
10
- // import * as abilities from '#abilities/main'
11
- // import { McpBouncer } from '@jrmc/adonis-mcp'
12
-
13
12
  export default class McpMiddleware {
14
13
  async handle(ctx: HttpContext, next: NextFn) {
15
14
  const body = ctx.request.body()
@@ -39,7 +38,7 @@ export default class McpMiddleware {
39
38
  // declare module '@jrmc/adonis-mcp/types/context' {
40
39
  // export interface McpContext {
41
40
  // auth: {
42
- // user?: HttpContext['auth']['user']
41
+ // user: HttpContext['auth']['user']
43
42
  // }
44
43
  // bouncer: McpBouncer<
45
44
  // Exclude<HttpContext['auth']['user'], undefined>,