@jrmc/adonis-mcp 1.0.0-alpha.13 → 1.0.0-alpha.15

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.
Files changed (102) hide show
  1. package/README.md +223 -21
  2. package/build/commands/commands.json +1 -1
  3. package/build/commands/inspector.d.ts +16 -0
  4. package/build/commands/inspector.d.ts.map +1 -0
  5. package/build/commands/inspector.js +54 -0
  6. package/build/src/response.d.ts +2 -2
  7. package/build/src/response.d.ts.map +1 -1
  8. package/build/src/response.js +4 -4
  9. package/build/src/server/contents/audio.d.ts +3 -2
  10. package/build/src/server/contents/audio.d.ts.map +1 -1
  11. package/build/src/server/contents/audio.js +16 -9
  12. package/build/src/server/contents/blob.d.ts +2 -1
  13. package/build/src/server/contents/blob.d.ts.map +1 -1
  14. package/build/src/server/contents/blob.js +13 -2
  15. package/build/src/server/contents/embedded_resource.d.ts +2 -1
  16. package/build/src/server/contents/embedded_resource.d.ts.map +1 -1
  17. package/build/src/server/contents/embedded_resource.js +21 -10
  18. package/build/src/server/contents/error.d.ts +1 -1
  19. package/build/src/server/contents/error.d.ts.map +1 -1
  20. package/build/src/server/contents/image.d.ts +3 -2
  21. package/build/src/server/contents/image.d.ts.map +1 -1
  22. package/build/src/server/contents/image.js +16 -9
  23. package/build/src/server/contents/resource_link.d.ts +4 -2
  24. package/build/src/server/contents/resource_link.d.ts.map +1 -1
  25. package/build/src/server/contents/resource_link.js +20 -9
  26. package/build/src/server/contents/structured.d.ts +1 -1
  27. package/build/src/server/contents/structured.d.ts.map +1 -1
  28. package/build/src/server/contents/text.d.ts +2 -1
  29. package/build/src/server/contents/text.d.ts.map +1 -1
  30. package/build/src/server/contents/text.js +18 -7
  31. package/build/src/server/context.d.ts +5 -1
  32. package/build/src/server/context.d.ts.map +1 -1
  33. package/build/src/server/context.js +26 -0
  34. package/build/src/server/{content.d.ts → contracts/content.d.ts} +4 -4
  35. package/build/src/server/contracts/content.d.ts.map +1 -0
  36. package/build/src/server/contracts/context.d.ts +29 -0
  37. package/build/src/server/contracts/context.d.ts.map +1 -0
  38. package/build/src/{types → server/contracts}/transport.d.ts +1 -1
  39. package/build/src/server/contracts/transport.d.ts.map +1 -0
  40. package/build/src/server/contracts/transport.js +7 -0
  41. package/build/src/server/methods/call_tool.d.ts +1 -1
  42. package/build/src/server/methods/call_tool.d.ts.map +1 -1
  43. package/build/src/server/methods/get_prompt.d.ts +1 -1
  44. package/build/src/server/methods/get_prompt.d.ts.map +1 -1
  45. package/build/src/server/methods/initialize.d.ts +1 -1
  46. package/build/src/server/methods/initialize.d.ts.map +1 -1
  47. package/build/src/server/methods/list_prompts.d.ts +1 -1
  48. package/build/src/server/methods/list_prompts.d.ts.map +1 -1
  49. package/build/src/server/methods/list_prompts.js +1 -16
  50. package/build/src/server/methods/list_resource_templates.d.ts +12 -0
  51. package/build/src/server/methods/list_resource_templates.d.ts.map +1 -0
  52. package/build/src/server/methods/list_resource_templates.js +31 -0
  53. package/build/src/server/methods/list_resources.d.ts +1 -1
  54. package/build/src/server/methods/list_resources.d.ts.map +1 -1
  55. package/build/src/server/methods/list_resources.js +2 -9
  56. package/build/src/server/methods/list_tools.d.ts +1 -1
  57. package/build/src/server/methods/list_tools.d.ts.map +1 -1
  58. package/build/src/server/methods/list_tools.js +1 -16
  59. package/build/src/server/methods/ping.d.ts +1 -1
  60. package/build/src/server/methods/ping.d.ts.map +1 -1
  61. package/build/src/server/methods/read_resource.d.ts +1 -1
  62. package/build/src/server/methods/read_resource.d.ts.map +1 -1
  63. package/build/src/server/methods/read_resource.js +7 -7
  64. package/build/src/server/prompt.d.ts +13 -9
  65. package/build/src/server/prompt.d.ts.map +1 -1
  66. package/build/src/server/prompt.js +17 -0
  67. package/build/src/server/resource.d.ts +9 -8
  68. package/build/src/server/resource.d.ts.map +1 -1
  69. package/build/src/server/resource.js +23 -0
  70. package/build/src/server/tool.d.ts +13 -9
  71. package/build/src/server/tool.d.ts.map +1 -1
  72. package/build/src/server/tool.js +17 -0
  73. package/build/src/server/transports/fake_transport.d.ts +2 -2
  74. package/build/src/server/transports/fake_transport.d.ts.map +1 -1
  75. package/build/src/server/transports/http_transport.d.ts +2 -2
  76. package/build/src/server/transports/http_transport.d.ts.map +1 -1
  77. package/build/src/server/transports/stdio_transport.d.ts +1 -1
  78. package/build/src/server/transports/stdio_transport.d.ts.map +1 -1
  79. package/build/src/server.d.ts +2 -1
  80. package/build/src/server.d.ts.map +1 -1
  81. package/build/src/server.js +1 -0
  82. package/build/src/types/content.d.ts +14 -10
  83. package/build/src/types/content.d.ts.map +1 -1
  84. package/build/src/types/context.d.ts +9 -22
  85. package/build/src/types/context.d.ts.map +1 -1
  86. package/build/src/types/method.d.ts +1 -1
  87. package/build/src/types/method.d.ts.map +1 -1
  88. package/build/src/utils/find_resource_pattern.d.ts +13 -0
  89. package/build/src/utils/find_resource_pattern.d.ts.map +1 -0
  90. package/build/src/utils/find_resource_pattern.js +29 -0
  91. package/build/src/utils/uri_template.d.ts +25 -0
  92. package/build/src/utils/uri_template.d.ts.map +1 -0
  93. package/build/src/utils/uri_template.js +240 -0
  94. package/build/stubs/make/mcp/prompts/main.ts.stub +3 -4
  95. package/build/stubs/make/mcp/resources/main.ts.stub +1 -1
  96. package/build/stubs/make/mcp/tools/main.ts.stub +3 -5
  97. package/build/tsconfig.tsbuildinfo +1 -1
  98. package/package.json +2 -1
  99. package/build/src/server/content.d.ts.map +0 -1
  100. package/build/src/types/transport.d.ts.map +0 -1
  101. /package/build/src/server/{content.js → contracts/content.js} +0 -0
  102. /package/build/src/{types/transport.js → server/contracts/context.js} +0 -0
@@ -0,0 +1,29 @@
1
+ import { UriTemplate } from './uri_template.js';
2
+ import { ErrorCode } from '../enums/error.js';
3
+ import JsonRpcException from '../server/exceptions/jsonrpc_exception.js';
4
+ export function findResourcePattern({ uri, resourceList, ctx }) {
5
+ return Object.keys(resourceList).find((key) => {
6
+ if (key === uri) {
7
+ return true;
8
+ }
9
+ const uriTemplate = new UriTemplate(key);
10
+ const variables = uriTemplate.match(uri);
11
+ if (variables) {
12
+ if (ctx) {
13
+ ;
14
+ ctx.args = variables ?? {};
15
+ }
16
+ return true;
17
+ }
18
+ });
19
+ }
20
+ export async function findResource({ uri, resourceList, ctx }) {
21
+ const key = findResourcePattern({ uri, resourceList, ctx });
22
+ if (!key) {
23
+ throw new JsonRpcException(`The resource ${uri} was not found.`, ErrorCode.MethodNotFound, ctx.request.id);
24
+ }
25
+ const { default: Resource } = await import(resourceList[key]);
26
+ const resource = new Resource(ctx);
27
+ resource.uri = uri;
28
+ return resource;
29
+ }
@@ -0,0 +1,25 @@
1
+ export type Variables = Record<string, string | string[]>;
2
+ export declare class UriTemplate {
3
+ /**
4
+ * Returns true if the given string contains any URI template expressions.
5
+ * A template expression is a sequence of characters enclosed in curly braces,
6
+ * like {foo} or {?bar}.
7
+ */
8
+ static isTemplate(str: string): boolean;
9
+ private static validateLength;
10
+ private readonly template;
11
+ private readonly parts;
12
+ get variableNames(): string[];
13
+ constructor(template: string);
14
+ toString(): string;
15
+ private parse;
16
+ private getOperator;
17
+ private getNames;
18
+ private encodeValue;
19
+ private expandPart;
20
+ expand(variables: Variables): string;
21
+ private escapeRegExp;
22
+ private partToRegExp;
23
+ match(uri: string): Variables | null;
24
+ }
25
+ //# sourceMappingURL=uri_template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uri_template.d.ts","sourceRoot":"","sources":["../../../src/utils/uri_template.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;AAOzD,qBAAa,WAAW;IACtB;;;;OAIG;IACH,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAMvC,OAAO,CAAC,MAAM,CAAC,cAAc;IAK7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAErB;IAED,IAAI,aAAa,IAAI,MAAM,EAAE,CAE5B;gBAEW,QAAQ,EAAE,MAAM;IAM5B,QAAQ,IAAI,MAAM;IAIlB,OAAO,CAAC,KAAK;IAoDb,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,UAAU;IAsDlB,MAAM,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM;IA4BpC,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,YAAY;IAkDpB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;CAuCrC"}
@@ -0,0 +1,240 @@
1
+ // Claude-authored implementation of RFC 6570 URI Templates
2
+ const MAX_TEMPLATE_LENGTH = 1000000; // 1MB
3
+ const MAX_VARIABLE_LENGTH = 1000000; // 1MB
4
+ const MAX_TEMPLATE_EXPRESSIONS = 10000;
5
+ const MAX_REGEX_LENGTH = 1000000; // 1MB
6
+ export class UriTemplate {
7
+ /**
8
+ * Returns true if the given string contains any URI template expressions.
9
+ * A template expression is a sequence of characters enclosed in curly braces,
10
+ * like {foo} or {?bar}.
11
+ */
12
+ static isTemplate(str) {
13
+ // Look for any sequence of characters between curly braces
14
+ // that isn't just whitespace
15
+ return /\{[^}\s]+\}/.test(str);
16
+ }
17
+ static validateLength(str, max, context) {
18
+ if (str.length > max) {
19
+ throw new Error(`${context} exceeds maximum length of ${max} characters (got ${str.length})`);
20
+ }
21
+ }
22
+ template;
23
+ parts;
24
+ get variableNames() {
25
+ return this.parts.flatMap((part) => (typeof part === 'string' ? [] : part.names));
26
+ }
27
+ constructor(template) {
28
+ UriTemplate.validateLength(template, MAX_TEMPLATE_LENGTH, 'Template');
29
+ this.template = template;
30
+ this.parts = this.parse(template);
31
+ }
32
+ toString() {
33
+ return this.template;
34
+ }
35
+ parse(template) {
36
+ const parts = [];
37
+ let currentText = '';
38
+ let i = 0;
39
+ let expressionCount = 0;
40
+ while (i < template.length) {
41
+ if (template[i] === '{') {
42
+ if (currentText) {
43
+ parts.push(currentText);
44
+ currentText = '';
45
+ }
46
+ const end = template.indexOf('}', i);
47
+ if (end === -1)
48
+ throw new Error('Unclosed template expression');
49
+ expressionCount++;
50
+ if (expressionCount > MAX_TEMPLATE_EXPRESSIONS) {
51
+ throw new Error(`Template contains too many expressions (max ${MAX_TEMPLATE_EXPRESSIONS})`);
52
+ }
53
+ const expr = template.slice(i + 1, end);
54
+ const operator = this.getOperator(expr);
55
+ const exploded = expr.includes('*');
56
+ const names = this.getNames(expr);
57
+ const name = names[0];
58
+ // Validate variable name length
59
+ for (const name of names) {
60
+ UriTemplate.validateLength(name, MAX_VARIABLE_LENGTH, 'Variable name');
61
+ }
62
+ parts.push({ name, operator, names, exploded });
63
+ i = end + 1;
64
+ }
65
+ else {
66
+ currentText += template[i];
67
+ i++;
68
+ }
69
+ }
70
+ if (currentText) {
71
+ parts.push(currentText);
72
+ }
73
+ return parts;
74
+ }
75
+ getOperator(expr) {
76
+ const operators = ['+', '#', '.', '/', '?', '&'];
77
+ return operators.find((op) => expr.startsWith(op)) || '';
78
+ }
79
+ getNames(expr) {
80
+ const operator = this.getOperator(expr);
81
+ return expr
82
+ .slice(operator.length)
83
+ .split(',')
84
+ .map((name) => name.replace('*', '').trim())
85
+ .filter((name) => name.length > 0);
86
+ }
87
+ encodeValue(value, operator) {
88
+ UriTemplate.validateLength(value, MAX_VARIABLE_LENGTH, 'Variable value');
89
+ if (operator === '+' || operator === '#') {
90
+ return encodeURI(value);
91
+ }
92
+ return encodeURIComponent(value);
93
+ }
94
+ expandPart(part, variables) {
95
+ if (part.operator === '?' || part.operator === '&') {
96
+ const pairs = part.names
97
+ .map((name) => {
98
+ const value = variables[name];
99
+ if (value === undefined)
100
+ return '';
101
+ const encoded = Array.isArray(value)
102
+ ? value.map((v) => this.encodeValue(v, part.operator)).join(',')
103
+ : this.encodeValue(value.toString(), part.operator);
104
+ return `${name}=${encoded}`;
105
+ })
106
+ .filter((pair) => pair.length > 0);
107
+ if (pairs.length === 0)
108
+ return '';
109
+ const separator = part.operator === '?' ? '?' : '&';
110
+ return separator + pairs.join('&');
111
+ }
112
+ if (part.names.length > 1) {
113
+ const values = part.names.map((name) => variables[name]).filter((v) => v !== undefined);
114
+ if (values.length === 0)
115
+ return '';
116
+ return values.map((v) => (Array.isArray(v) ? v[0] : v)).join(',');
117
+ }
118
+ const value = variables[part.name];
119
+ if (value === undefined)
120
+ return '';
121
+ const values = Array.isArray(value) ? value : [value];
122
+ const encoded = values.map((v) => this.encodeValue(v, part.operator));
123
+ switch (part.operator) {
124
+ case '':
125
+ return encoded.join(',');
126
+ case '+':
127
+ return encoded.join(',');
128
+ case '#':
129
+ return '#' + encoded.join(',');
130
+ case '.':
131
+ return '.' + encoded.join('.');
132
+ case '/':
133
+ return '/' + encoded.join('/');
134
+ default:
135
+ return encoded.join(',');
136
+ }
137
+ }
138
+ expand(variables) {
139
+ let result = '';
140
+ let hasQueryParam = false;
141
+ for (const part of this.parts) {
142
+ if (typeof part === 'string') {
143
+ result += part;
144
+ continue;
145
+ }
146
+ const expanded = this.expandPart(part, variables);
147
+ if (!expanded)
148
+ continue;
149
+ // Convert ? to & if we already have a query parameter
150
+ if ((part.operator === '?' || part.operator === '&') && hasQueryParam) {
151
+ result += expanded.replace('?', '&');
152
+ }
153
+ else {
154
+ result += expanded;
155
+ }
156
+ if (part.operator === '?' || part.operator === '&') {
157
+ hasQueryParam = true;
158
+ }
159
+ }
160
+ return result;
161
+ }
162
+ escapeRegExp(str) {
163
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
164
+ }
165
+ partToRegExp(part) {
166
+ const patterns = [];
167
+ // Validate variable name length for matching
168
+ for (const name of part.names) {
169
+ UriTemplate.validateLength(name, MAX_VARIABLE_LENGTH, 'Variable name');
170
+ }
171
+ if (part.operator === '?' || part.operator === '&') {
172
+ for (let i = 0; i < part.names.length; i++) {
173
+ const name = part.names[i];
174
+ const prefix = i === 0 ? '\\' + part.operator : '&';
175
+ patterns.push({
176
+ pattern: prefix + this.escapeRegExp(name) + '=([^&]+)',
177
+ name,
178
+ });
179
+ }
180
+ return patterns;
181
+ }
182
+ let pattern;
183
+ const name = part.name;
184
+ switch (part.operator) {
185
+ case '':
186
+ pattern = part.exploded ? '([^/]+(?:,[^/]+)*)' : '([^/,]+)';
187
+ break;
188
+ case '+':
189
+ case '#':
190
+ pattern = '(.+)';
191
+ break;
192
+ case '.':
193
+ pattern = '\\.([^/,]+)';
194
+ break;
195
+ case '/':
196
+ pattern = '/' + (part.exploded ? '([^/]+(?:,[^/]+)*)' : '([^/,]+)');
197
+ break;
198
+ default:
199
+ pattern = '([^/]+)';
200
+ }
201
+ patterns.push({ pattern, name });
202
+ return patterns;
203
+ }
204
+ match(uri) {
205
+ UriTemplate.validateLength(uri, MAX_TEMPLATE_LENGTH, 'URI');
206
+ let pattern = '^';
207
+ const names = [];
208
+ for (const part of this.parts) {
209
+ if (typeof part === 'string') {
210
+ pattern += this.escapeRegExp(part);
211
+ }
212
+ else {
213
+ const patterns = this.partToRegExp(part);
214
+ for (const { pattern: partPattern, name } of patterns) {
215
+ pattern += partPattern;
216
+ names.push({ name, exploded: part.exploded });
217
+ }
218
+ }
219
+ }
220
+ pattern += '$';
221
+ UriTemplate.validateLength(pattern, MAX_REGEX_LENGTH, 'Generated regex pattern');
222
+ const regex = new RegExp(pattern);
223
+ const match = uri.match(regex);
224
+ if (!match)
225
+ return null;
226
+ const result = {};
227
+ for (let i = 0; i < names.length; i++) {
228
+ const { name, exploded } = names[i];
229
+ const value = match[i + 1];
230
+ const cleanName = name.replace('*', '');
231
+ if (exploded && value.includes(',')) {
232
+ result[cleanName] = value.split(',');
233
+ }
234
+ else {
235
+ result[cleanName] = value;
236
+ }
237
+ }
238
+ return result;
239
+ }
240
+ }
@@ -6,7 +6,7 @@
6
6
  })
7
7
  }}}
8
8
  import type { PromptContext } from '@jrmc/adonis-mcp/types/context'
9
- import type { BaseSchema, InferJSONSchema } from '@jrmc/adonis-mcp/types/method'
9
+ import type { BaseSchema } from '@jrmc/adonis-mcp/types/method'
10
10
 
11
11
  import { Prompt } from '@jrmc/adonis-mcp'
12
12
 
@@ -14,14 +14,13 @@ type Schema = BaseSchema<{
14
14
  text: { type: "string" }
15
15
  }>
16
16
 
17
- type Context = PromptContext & { args: InferJSONSchema<Schema> }
18
17
 
19
- export default class {{ className }} implements Prompt<Schema> {
18
+ export default class {{ className }} extends Prompt<Schema> {
20
19
  name = '{{ name }}'
21
20
  title = 'Prompt title'
22
21
  description = 'Prompt description'
23
22
 
24
- async handle({ args, response }: Context) {
23
+ async handle({ args, response }: PromptContext<Schema>) {
25
24
  console.log(args.text)
26
25
  return [
27
26
  response.text('Hello, world!')
@@ -9,7 +9,7 @@ import type { ResourceContext } from '@jrmc/adonis-mcp/types/context'
9
9
 
10
10
  import { Resource } from '@jrmc/adonis-mcp'
11
11
 
12
- export default class {{ className }} implements Resource {
12
+ export default class {{ className }} extends Resource {
13
13
  name = 'example.txt'
14
14
  uri = 'file:///example.txt'
15
15
  mimeType = 'text/plain"'
@@ -6,7 +6,7 @@
6
6
  })
7
7
  }}}
8
8
  import type { ToolContext } from '@jrmc/adonis-mcp/types/context'
9
- import type { BaseSchema, InferJSONSchema } from '@jrmc/adonis-mcp/types/method'
9
+ import type { BaseSchema } from '@jrmc/adonis-mcp/types/method'
10
10
 
11
11
  import { Tool } from '@jrmc/adonis-mcp'
12
12
 
@@ -14,14 +14,12 @@ type Schema = BaseSchema<{
14
14
  text: { type: "string" }
15
15
  }>
16
16
 
17
- type Context = ToolContext & { args: InferJSONSchema<Schema> }
18
-
19
- export default class {{ className }} implements Tool<Schema> {
17
+ export default class {{ className }} extends Tool<Schema> {
20
18
  name = '{{ name }}'
21
19
  title = 'Tool title'
22
20
  description = 'Tool description'
23
21
 
24
- async handle({ args, response }: Context) {
22
+ async handle({ args, response }: ToolContext<Schema>) {
25
23
  console.log(args.text)
26
24
  return response.text('Hello, world!')
27
25
  }