@ananay-nag/mcp-decorators 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.
Files changed (214) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +561 -0
  3. package/banner.svg +111 -0
  4. package/dist/cjs/index.d.ts +3 -0
  5. package/dist/cjs/index.d.ts.map +1 -0
  6. package/dist/cjs/index.js +36 -0
  7. package/dist/cjs/index.js.map +1 -0
  8. package/dist/cjs/package.json +1 -0
  9. package/dist/cjs/src/client/decorators/client.decorator.d.ts +66 -0
  10. package/dist/cjs/src/client/decorators/client.decorator.d.ts.map +1 -0
  11. package/dist/cjs/src/client/decorators/client.decorator.js +206 -0
  12. package/dist/cjs/src/client/decorators/client.decorator.js.map +1 -0
  13. package/dist/cjs/src/client/decorators/index.d.ts +4 -0
  14. package/dist/cjs/src/client/decorators/index.d.ts.map +1 -0
  15. package/dist/cjs/src/client/decorators/index.js +23 -0
  16. package/dist/cjs/src/client/decorators/index.js.map +1 -0
  17. package/dist/cjs/src/client/decorators/notification.decorator.d.ts +8 -0
  18. package/dist/cjs/src/client/decorators/notification.decorator.d.ts.map +1 -0
  19. package/dist/cjs/src/client/decorators/notification.decorator.js +19 -0
  20. package/dist/cjs/src/client/decorators/notification.decorator.js.map +1 -0
  21. package/dist/cjs/src/client/decorators/requestHandler.decorator.d.ts +7 -0
  22. package/dist/cjs/src/client/decorators/requestHandler.decorator.d.ts.map +1 -0
  23. package/dist/cjs/src/client/decorators/requestHandler.decorator.js +18 -0
  24. package/dist/cjs/src/client/decorators/requestHandler.decorator.js.map +1 -0
  25. package/dist/cjs/src/client/index.d.ts +4 -0
  26. package/dist/cjs/src/client/index.d.ts.map +1 -0
  27. package/dist/cjs/src/client/index.js +20 -0
  28. package/dist/cjs/src/client/index.js.map +1 -0
  29. package/dist/cjs/src/client/types/client/client.d.ts +14 -0
  30. package/dist/cjs/src/client/types/client/client.d.ts.map +1 -0
  31. package/dist/cjs/src/client/types/client/client.js +3 -0
  32. package/dist/cjs/src/client/types/client/client.js.map +1 -0
  33. package/dist/cjs/src/client/types/index.d.ts +3 -0
  34. package/dist/cjs/src/client/types/index.d.ts.map +1 -0
  35. package/dist/cjs/src/client/types/index.js +19 -0
  36. package/dist/cjs/src/client/types/index.js.map +1 -0
  37. package/dist/cjs/src/client/utils/clientRegistry.d.ts +10 -0
  38. package/dist/cjs/src/client/utils/clientRegistry.d.ts.map +1 -0
  39. package/dist/cjs/src/client/utils/clientRegistry.js +38 -0
  40. package/dist/cjs/src/client/utils/clientRegistry.js.map +1 -0
  41. package/dist/cjs/src/client/utils/index.d.ts +2 -0
  42. package/dist/cjs/src/client/utils/index.d.ts.map +1 -0
  43. package/dist/cjs/src/client/utils/index.js +18 -0
  44. package/dist/cjs/src/client/utils/index.js.map +1 -0
  45. package/dist/cjs/src/server/decorators/action.decorator.d.ts +11 -0
  46. package/dist/cjs/src/server/decorators/action.decorator.d.ts.map +1 -0
  47. package/dist/cjs/src/server/decorators/action.decorator.js +23 -0
  48. package/dist/cjs/src/server/decorators/action.decorator.js.map +1 -0
  49. package/dist/cjs/src/server/decorators/completion.decorator.d.ts +12 -0
  50. package/dist/cjs/src/server/decorators/completion.decorator.d.ts.map +1 -0
  51. package/dist/cjs/src/server/decorators/completion.decorator.js +22 -0
  52. package/dist/cjs/src/server/decorators/completion.decorator.js.map +1 -0
  53. package/dist/cjs/src/server/decorators/index.d.ts +10 -0
  54. package/dist/cjs/src/server/decorators/index.d.ts.map +1 -0
  55. package/dist/cjs/src/server/decorators/index.js +25 -0
  56. package/dist/cjs/src/server/decorators/index.js.map +1 -0
  57. package/dist/cjs/src/server/decorators/notification.decorator.d.ts +11 -0
  58. package/dist/cjs/src/server/decorators/notification.decorator.d.ts.map +1 -0
  59. package/dist/cjs/src/server/decorators/notification.decorator.js +23 -0
  60. package/dist/cjs/src/server/decorators/notification.decorator.js.map +1 -0
  61. package/dist/cjs/src/server/decorators/prompt.decorator.d.ts +19 -0
  62. package/dist/cjs/src/server/decorators/prompt.decorator.d.ts.map +1 -0
  63. package/dist/cjs/src/server/decorators/prompt.decorator.js +23 -0
  64. package/dist/cjs/src/server/decorators/prompt.decorator.js.map +1 -0
  65. package/dist/cjs/src/server/decorators/requestHandler.decorator.d.ts +10 -0
  66. package/dist/cjs/src/server/decorators/requestHandler.decorator.d.ts.map +1 -0
  67. package/dist/cjs/src/server/decorators/requestHandler.decorator.js +33 -0
  68. package/dist/cjs/src/server/decorators/requestHandler.decorator.js.map +1 -0
  69. package/dist/cjs/src/server/decorators/resource.decorator.d.ts +27 -0
  70. package/dist/cjs/src/server/decorators/resource.decorator.d.ts.map +1 -0
  71. package/dist/cjs/src/server/decorators/resource.decorator.js +40 -0
  72. package/dist/cjs/src/server/decorators/resource.decorator.js.map +1 -0
  73. package/dist/cjs/src/server/decorators/server.decorator.d.ts +18 -0
  74. package/dist/cjs/src/server/decorators/server.decorator.d.ts.map +1 -0
  75. package/dist/cjs/src/server/decorators/server.decorator.js +385 -0
  76. package/dist/cjs/src/server/decorators/server.decorator.js.map +1 -0
  77. package/dist/cjs/src/server/decorators/subscribe.decorator.d.ts +13 -0
  78. package/dist/cjs/src/server/decorators/subscribe.decorator.d.ts.map +1 -0
  79. package/dist/cjs/src/server/decorators/subscribe.decorator.js +26 -0
  80. package/dist/cjs/src/server/decorators/subscribe.decorator.js.map +1 -0
  81. package/dist/cjs/src/server/decorators/tool.decorator.d.ts +15 -0
  82. package/dist/cjs/src/server/decorators/tool.decorator.d.ts.map +1 -0
  83. package/dist/cjs/src/server/decorators/tool.decorator.js +23 -0
  84. package/dist/cjs/src/server/decorators/tool.decorator.js.map +1 -0
  85. package/dist/cjs/src/server/index.d.ts +4 -0
  86. package/dist/cjs/src/server/index.d.ts.map +1 -0
  87. package/dist/cjs/src/server/index.js +33 -0
  88. package/dist/cjs/src/server/index.js.map +1 -0
  89. package/dist/cjs/src/server/types/index.d.ts +3 -0
  90. package/dist/cjs/src/server/types/index.d.ts.map +1 -0
  91. package/dist/cjs/src/server/types/index.js +19 -0
  92. package/dist/cjs/src/server/types/index.js.map +1 -0
  93. package/dist/cjs/src/server/types/server/index.d.ts +2 -0
  94. package/dist/cjs/src/server/types/server/index.d.ts.map +1 -0
  95. package/dist/cjs/src/server/types/server/index.js +18 -0
  96. package/dist/cjs/src/server/types/server/index.js.map +1 -0
  97. package/dist/cjs/src/server/types/server/server.d.ts +35 -0
  98. package/dist/cjs/src/server/types/server/server.d.ts.map +1 -0
  99. package/dist/cjs/src/server/types/server/server.js +3 -0
  100. package/dist/cjs/src/server/types/server/server.js.map +1 -0
  101. package/dist/cjs/src/server/utils/index.d.ts +2 -0
  102. package/dist/cjs/src/server/utils/index.d.ts.map +1 -0
  103. package/dist/cjs/src/server/utils/index.js +18 -0
  104. package/dist/cjs/src/server/utils/index.js.map +1 -0
  105. package/dist/cjs/src/server/utils/serverRegistry.d.ts +81 -0
  106. package/dist/cjs/src/server/utils/serverRegistry.d.ts.map +1 -0
  107. package/dist/cjs/src/server/utils/serverRegistry.js +151 -0
  108. package/dist/cjs/src/server/utils/serverRegistry.js.map +1 -0
  109. package/dist/esm/index.d.ts +3 -0
  110. package/dist/esm/index.d.ts.map +1 -0
  111. package/dist/esm/index.js +3 -0
  112. package/dist/esm/index.js.map +1 -0
  113. package/dist/esm/package.json +1 -0
  114. package/dist/esm/src/client/decorators/client.decorator.d.ts +66 -0
  115. package/dist/esm/src/client/decorators/client.decorator.d.ts.map +1 -0
  116. package/dist/esm/src/client/decorators/client.decorator.js +198 -0
  117. package/dist/esm/src/client/decorators/client.decorator.js.map +1 -0
  118. package/dist/esm/src/client/decorators/index.d.ts +4 -0
  119. package/dist/esm/src/client/decorators/index.d.ts.map +1 -0
  120. package/dist/esm/src/client/decorators/index.js +4 -0
  121. package/dist/esm/src/client/decorators/index.js.map +1 -0
  122. package/dist/esm/src/client/decorators/notification.decorator.d.ts +8 -0
  123. package/dist/esm/src/client/decorators/notification.decorator.d.ts.map +1 -0
  124. package/dist/esm/src/client/decorators/notification.decorator.js +15 -0
  125. package/dist/esm/src/client/decorators/notification.decorator.js.map +1 -0
  126. package/dist/esm/src/client/decorators/requestHandler.decorator.d.ts +7 -0
  127. package/dist/esm/src/client/decorators/requestHandler.decorator.d.ts.map +1 -0
  128. package/dist/esm/src/client/decorators/requestHandler.decorator.js +14 -0
  129. package/dist/esm/src/client/decorators/requestHandler.decorator.js.map +1 -0
  130. package/dist/esm/src/client/index.d.ts +4 -0
  131. package/dist/esm/src/client/index.d.ts.map +1 -0
  132. package/dist/esm/src/client/index.js +4 -0
  133. package/dist/esm/src/client/index.js.map +1 -0
  134. package/dist/esm/src/client/types/client/client.d.ts +14 -0
  135. package/dist/esm/src/client/types/client/client.d.ts.map +1 -0
  136. package/dist/esm/src/client/types/client/client.js +2 -0
  137. package/dist/esm/src/client/types/client/client.js.map +1 -0
  138. package/dist/esm/src/client/types/index.d.ts +3 -0
  139. package/dist/esm/src/client/types/index.d.ts.map +1 -0
  140. package/dist/esm/src/client/types/index.js +3 -0
  141. package/dist/esm/src/client/types/index.js.map +1 -0
  142. package/dist/esm/src/client/utils/clientRegistry.d.ts +10 -0
  143. package/dist/esm/src/client/utils/clientRegistry.d.ts.map +1 -0
  144. package/dist/esm/src/client/utils/clientRegistry.js +33 -0
  145. package/dist/esm/src/client/utils/clientRegistry.js.map +1 -0
  146. package/dist/esm/src/client/utils/index.d.ts +2 -0
  147. package/dist/esm/src/client/utils/index.d.ts.map +1 -0
  148. package/dist/esm/src/client/utils/index.js +2 -0
  149. package/dist/esm/src/client/utils/index.js.map +1 -0
  150. package/dist/esm/src/server/decorators/action.decorator.d.ts +11 -0
  151. package/dist/esm/src/server/decorators/action.decorator.d.ts.map +1 -0
  152. package/dist/esm/src/server/decorators/action.decorator.js +19 -0
  153. package/dist/esm/src/server/decorators/action.decorator.js.map +1 -0
  154. package/dist/esm/src/server/decorators/completion.decorator.d.ts +12 -0
  155. package/dist/esm/src/server/decorators/completion.decorator.d.ts.map +1 -0
  156. package/dist/esm/src/server/decorators/completion.decorator.js +18 -0
  157. package/dist/esm/src/server/decorators/completion.decorator.js.map +1 -0
  158. package/dist/esm/src/server/decorators/index.d.ts +10 -0
  159. package/dist/esm/src/server/decorators/index.d.ts.map +1 -0
  160. package/dist/esm/src/server/decorators/index.js +10 -0
  161. package/dist/esm/src/server/decorators/index.js.map +1 -0
  162. package/dist/esm/src/server/decorators/notification.decorator.d.ts +11 -0
  163. package/dist/esm/src/server/decorators/notification.decorator.d.ts.map +1 -0
  164. package/dist/esm/src/server/decorators/notification.decorator.js +19 -0
  165. package/dist/esm/src/server/decorators/notification.decorator.js.map +1 -0
  166. package/dist/esm/src/server/decorators/prompt.decorator.d.ts +19 -0
  167. package/dist/esm/src/server/decorators/prompt.decorator.d.ts.map +1 -0
  168. package/dist/esm/src/server/decorators/prompt.decorator.js +19 -0
  169. package/dist/esm/src/server/decorators/prompt.decorator.js.map +1 -0
  170. package/dist/esm/src/server/decorators/requestHandler.decorator.d.ts +10 -0
  171. package/dist/esm/src/server/decorators/requestHandler.decorator.d.ts.map +1 -0
  172. package/dist/esm/src/server/decorators/requestHandler.decorator.js +29 -0
  173. package/dist/esm/src/server/decorators/requestHandler.decorator.js.map +1 -0
  174. package/dist/esm/src/server/decorators/resource.decorator.d.ts +27 -0
  175. package/dist/esm/src/server/decorators/resource.decorator.d.ts.map +1 -0
  176. package/dist/esm/src/server/decorators/resource.decorator.js +35 -0
  177. package/dist/esm/src/server/decorators/resource.decorator.js.map +1 -0
  178. package/dist/esm/src/server/decorators/server.decorator.d.ts +18 -0
  179. package/dist/esm/src/server/decorators/server.decorator.d.ts.map +1 -0
  180. package/dist/esm/src/server/decorators/server.decorator.js +378 -0
  181. package/dist/esm/src/server/decorators/server.decorator.js.map +1 -0
  182. package/dist/esm/src/server/decorators/subscribe.decorator.d.ts +13 -0
  183. package/dist/esm/src/server/decorators/subscribe.decorator.d.ts.map +1 -0
  184. package/dist/esm/src/server/decorators/subscribe.decorator.js +21 -0
  185. package/dist/esm/src/server/decorators/subscribe.decorator.js.map +1 -0
  186. package/dist/esm/src/server/decorators/tool.decorator.d.ts +15 -0
  187. package/dist/esm/src/server/decorators/tool.decorator.d.ts.map +1 -0
  188. package/dist/esm/src/server/decorators/tool.decorator.js +19 -0
  189. package/dist/esm/src/server/decorators/tool.decorator.js.map +1 -0
  190. package/dist/esm/src/server/index.d.ts +4 -0
  191. package/dist/esm/src/server/index.d.ts.map +1 -0
  192. package/dist/esm/src/server/index.js +4 -0
  193. package/dist/esm/src/server/index.js.map +1 -0
  194. package/dist/esm/src/server/types/index.d.ts +3 -0
  195. package/dist/esm/src/server/types/index.d.ts.map +1 -0
  196. package/dist/esm/src/server/types/index.js +3 -0
  197. package/dist/esm/src/server/types/index.js.map +1 -0
  198. package/dist/esm/src/server/types/server/index.d.ts +2 -0
  199. package/dist/esm/src/server/types/server/index.d.ts.map +1 -0
  200. package/dist/esm/src/server/types/server/index.js +2 -0
  201. package/dist/esm/src/server/types/server/index.js.map +1 -0
  202. package/dist/esm/src/server/types/server/server.d.ts +35 -0
  203. package/dist/esm/src/server/types/server/server.d.ts.map +1 -0
  204. package/dist/esm/src/server/types/server/server.js +2 -0
  205. package/dist/esm/src/server/types/server/server.js.map +1 -0
  206. package/dist/esm/src/server/utils/index.d.ts +2 -0
  207. package/dist/esm/src/server/utils/index.d.ts.map +1 -0
  208. package/dist/esm/src/server/utils/index.js +2 -0
  209. package/dist/esm/src/server/utils/index.js.map +1 -0
  210. package/dist/esm/src/server/utils/serverRegistry.d.ts +81 -0
  211. package/dist/esm/src/server/utils/serverRegistry.d.ts.map +1 -0
  212. package/dist/esm/src/server/utils/serverRegistry.js +140 -0
  213. package/dist/esm/src/server/utils/serverRegistry.js.map +1 -0
  214. package/package.json +50 -0
package/README.md ADDED
@@ -0,0 +1,561 @@
1
+ # 🚀 MCP (Model Context Protocol) Decorators
2
+
3
+ ![MCP Decorators Banner](banner.svg)
4
+
5
+ A powerful, TypeScript-native decorator library to simplify and supercharge your Model Context Protocol (MCP) server and client development.
6
+
7
+ `@ananay-nag/mcp-decorators` enables clean, declarative class-based structures, completely removing repetitive boilerplate for request handling, client calls, resource serving, notifications, autocompletions, and capabilities registration.
8
+
9
+ ### [MCP Decorators - Documentation](https://mcp-decorators-doc.vercel.app/)
10
+
11
+ ---
12
+
13
+ ## Table of Contents
14
+ 1. [Installation & Configuration](#installation--configuration)
15
+ 2. [Server-Side Decorators](#server-side-decorators)
16
+ - [Core Class Decorators](#core-class-decorators)
17
+ - [MCP Capabilities Decorators](#mcp-capabilities-decorators)
18
+ - [Advanced Server Routing](#advanced-server-routing)
19
+ 3. [Full Server Example](#full-server-example)
20
+ 4. [Client-Side Decorators](#client-side-decorators)
21
+ - [Core Client Decorators](#core-client-decorators)
22
+ - [Client Call Wrapper Decorators](#client-call-wrapper-decorators)
23
+ - [Client Request/Notification Handlers](#client-requestnotification-handlers)
24
+ 5. [Full Client Example](#full-client-example)
25
+ 6. [Utilities](#utilities)
26
+ 7. [Under the Hood & Advantages](#under-the-hood--advantages)
27
+
28
+ ---
29
+
30
+ ## Installation & Configuration
31
+
32
+ Install the package via npm:
33
+
34
+ ```bash
35
+ npm install @ananay-nag/mcp-decorators
36
+ ```
37
+
38
+ Ensure that you have enabled decorator support in your `tsconfig.json`:
39
+
40
+ ```json
41
+ {
42
+ "compilerOptions": {
43
+ "experimentalDecorators": true,
44
+ "emitDecoratorMetadata": true
45
+ }
46
+ }
47
+ ```
48
+
49
+ ---
50
+
51
+ ## Server-Side Decorators
52
+
53
+ Server-side decorators automate capability aggregation, map request dispatchers, manage client subscriptions, and route incoming requests and notifications.
54
+
55
+ ### Core Class Decorators
56
+
57
+ #### 1. `@RegisterServer()`
58
+ * **Target**: Class extending `Server` (from `@modelcontextprotocol/sdk/server/index.js`)
59
+ * **Description**: Automatically registers the instantiated server in the global registry using the name and version passed to the class constructor.
60
+ ```typescript
61
+ import { Server, ServerOptions } from "@modelcontextprotocol/sdk/server/index.js";
62
+ import { RegisterServer } from "@ananay-nag/mcp-decorators";
63
+ import { Implementation } from "@modelcontextprotocol/sdk/types.js";
64
+
65
+ @RegisterServer()
66
+ export class MyMCPServer extends Server {
67
+ constructor(serverInfo: Implementation, options?: ServerOptions) {
68
+ super(serverInfo, options);
69
+ }
70
+ }
71
+ ```
72
+
73
+ #### 2. `@UseServer(options)`
74
+ * **Target**: Any handler/service class
75
+ * **Parameters**: `options: { name: string; version?: string }`
76
+ * **Description**: Injects the registered server instance into the class prototype as `this.server` and automatically binds all decorated handlers on class instantiation.
77
+ ```typescript
78
+ import { UseServer } from "@ananay-nag/mcp-decorators";
79
+
80
+ @UseServer({ name: "my-mcp-server", version: "1.0.0" })
81
+ export class DbHandlers {
82
+ server: any; // Injected server instance
83
+ }
84
+ ```
85
+
86
+ ---
87
+
88
+ ### MCP Capabilities Decorators
89
+
90
+ #### 3. `@Tool(options)`
91
+ * **Target**: Method
92
+ * **Parameters**: `options: { name: string; description: string; inputSchema?: any }`
93
+ * **Description**: Registers a method as an MCP Tool. Validates inputs automatically using the `inputSchema` (supports standard schemas or **Zod** schemas).
94
+ ```typescript
95
+ import { Tool } from "@ananay-nag/mcp-decorators";
96
+ import { z } from "zod";
97
+
98
+ @Tool({
99
+ name: "query_database",
100
+ description: "Run a read-only SQL query against the database",
101
+ inputSchema: z.object({
102
+ sql: z.string(),
103
+ })
104
+ })
105
+ async query(args: { sql: string }) {
106
+ // Method body receives the arguments object directly
107
+ return {
108
+ content: [{ type: "text", text: `Results for: ${args.sql}` }]
109
+ };
110
+ }
111
+ ```
112
+
113
+ #### 4. `@Prompt(options)`
114
+ * **Target**: Method
115
+ * **Parameters**: `options: { name: string; description?: string; arguments?: Array<{ name: string; description?: string; required?: boolean }> }`
116
+ * **Description**: Exposes a prompt template to clients.
117
+ ```typescript
118
+ import { Prompt } from "@ananay-nag/mcp-decorators";
119
+
120
+ @Prompt({
121
+ name: "explain_code",
122
+ description: "Explain the provided code snippet",
123
+ arguments: [{ name: "code", description: "Source code to explain", required: true }]
124
+ })
125
+ async explainCode(args: { code: string }) {
126
+ return {
127
+ messages: [
128
+ { role: "user", content: { type: "text", text: `Please explain this code:\n\n${args.code}` } }
129
+ ]
130
+ };
131
+ }
132
+ ```
133
+
134
+ #### 5. `@Resource(options)` & `@ResourceTemplate(options)`
135
+ * **Target**: Method
136
+ * **Parameters**:
137
+ - `@Resource`: `options: { uri: string; name: string; description?: string; mimeType?: string }`
138
+ - `@ResourceTemplate`: `options: { uriTemplate: string; name: string; description?: string; mimeType?: string }`
139
+ * **Description**: Expose static text/binary files or dynamic URI templates.
140
+ ```typescript
141
+ import { Resource, ResourceTemplate } from "@ananay-nag/mcp-decorators";
142
+
143
+ // Exposes a static resource
144
+ @Resource({
145
+ uri: "mysql://schema/tables",
146
+ name: "Tables list schema"
147
+ })
148
+ async getTables() {
149
+ return { contents: [{ uri: "mysql://schema/tables", text: "['users', 'orders']" }] };
150
+ }
151
+
152
+ // Exposes dynamic URIs matching a template (e.g. mysql://users/schema)
153
+ @ResourceTemplate({
154
+ uriTemplate: "mysql://{tableName}/schema",
155
+ name: "Dynamic Table Schema"
156
+ })
157
+ async getTableSchema(params: { tableName: string }) {
158
+ // 'tableName' is automatically parsed from the requested URI and injected
159
+ return {
160
+ contents: [{ uri: `mysql://${params.tableName}/schema`, text: `Schema for ${params.tableName}` }]
161
+ };
162
+ }
163
+ ```
164
+
165
+ #### 6. `@Subscribe()` & `@Unsubscribe()`
166
+ * **Target**: Methods
167
+ * **Description**: Triggered when a client subscribes/unsubscribes to resource URI updates.
168
+ ```typescript
169
+ import { Subscribe, Unsubscribe } from "@ananay-nag/mcp-decorators";
170
+
171
+ @Subscribe()
172
+ async onSubscribe(uri: string) {
173
+ console.log(`Client subscribed to resource updates on: ${uri}`);
174
+ }
175
+
176
+ @Unsubscribe()
177
+ async onUnsubscribe(uri: string) {
178
+ console.log(`Client unsubscribed from: ${uri}`);
179
+ }
180
+ ```
181
+
182
+ #### 7. `@Completion(ref)`
183
+ * **Target**: Method
184
+ * **Parameters**: `ref: { type: "prompt" | "resource"; name: string }`
185
+ * **Description**: Registers auto-completion handler for a prompt argument or a resource template parameter.
186
+ ```typescript
187
+ import { Completion } from "@ananay-nag/mcp-decorators";
188
+
189
+ @Completion({ type: "prompt", name: "explain_code" })
190
+ async autocompleteCodePrompt(args: { argument: string; value: string }) {
191
+ return {
192
+ completion: {
193
+ values: ["typescript", "javascript", "python"]
194
+ }
195
+ };
196
+ }
197
+ ```
198
+
199
+ ---
200
+
201
+ ### Advanced Server Routing
202
+
203
+ #### 8. `@RequestHandler(schema)` & `@NotificationHandler(schema)`
204
+ * **Target**: Method
205
+ * **Parameters**: `schema: string | ZodSchema`
206
+ * **Description**: Low-level request and notification catch-alls. If a string is provided, it matches the JSON-RPC method name exactly.
207
+ ```typescript
208
+ import { RequestHandler, NotificationHandler } from "@ananay-nag/mcp-decorators";
209
+
210
+ @NotificationHandler("notifications/initialized")
211
+ async onClientInit(params: any) {
212
+ console.log("Client initialization completed!");
213
+ }
214
+ ```
215
+
216
+ #### 9. `@ActionHandler(actionName)`
217
+ * **Target**: Method
218
+ * **Parameters**: `actionName: string`
219
+ * **Description**: Used **in conjunction** with `@RequestHandler`. It maps specific sub-actions (like different tool calls or custom action names where `request.params.name === actionName`) under a single request schema to different handler methods.
220
+ ```typescript
221
+ import { RequestHandler, ActionHandler } from "@ananay-nag/mcp-decorators";
222
+ import { CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
223
+
224
+ export class RawHandlers {
225
+ // Routes tool calls for "ping" tool
226
+ @RequestHandler(CallToolRequestSchema)
227
+ @ActionHandler("ping")
228
+ async handlePing(request: any) {
229
+ return { content: [{ type: "text", text: "pong" }] };
230
+ }
231
+
232
+ // Routes tool calls for "query" tool
233
+ @RequestHandler(CallToolRequestSchema)
234
+ @ActionHandler("query")
235
+ async handleQuery(request: any) {
236
+ return { content: [{ type: "text", text: "executing query..." }] };
237
+ }
238
+ }
239
+ ```
240
+
241
+ ---
242
+
243
+ ## Full Server Example
244
+
245
+ ### `server.ts`
246
+ ```typescript
247
+ import { Server, ServerOptions } from "@modelcontextprotocol/sdk/server/index.js";
248
+ import { RegisterServer } from "@ananay-nag/mcp-decorators";
249
+ import { Implementation } from "@modelcontextprotocol/sdk/types.js";
250
+
251
+ @RegisterServer()
252
+ export class MyMCPServer extends Server {
253
+ constructor(serverInfo: Implementation, options?: ServerOptions) {
254
+ super(serverInfo, options);
255
+ }
256
+ }
257
+ ```
258
+
259
+ ### `dbHandlers.ts`
260
+ ```typescript
261
+ import { UseServer, Tool, Resource, ResourceTemplate } from "@ananay-nag/mcp-decorators";
262
+ import { z } from "zod";
263
+
264
+ @UseServer({ name: "my-database-mcp", version: "1.0.0" })
265
+ export class DbHandlers {
266
+ server: any; // Injected instance
267
+
268
+ @Tool({
269
+ name: "fetch_users",
270
+ description: "Fetch list of active users",
271
+ inputSchema: z.object({
272
+ limit: z.number().default(10)
273
+ })
274
+ })
275
+ async fetchUsers(args: { limit: number }) {
276
+ return {
277
+ content: [{ type: "text", text: `Fetched ${args.limit} users.` }]
278
+ };
279
+ }
280
+
281
+ @Resource({
282
+ uri: "mysql://tables/list",
283
+ name: "MySQL Tables",
284
+ description: "List of tables in MySQL database"
285
+ })
286
+ async listTables() {
287
+ return {
288
+ contents: [{ uri: "mysql://tables/list", text: JSON.stringify(["users", "orders", "payments"]) }]
289
+ };
290
+ }
291
+
292
+ @ResourceTemplate({
293
+ uriTemplate: "mysql://{tableName}/schema",
294
+ name: "Table Schema Details"
295
+ })
296
+ async getTableSchema(params: { tableName: string }) {
297
+ return {
298
+ contents: [{ uri: `mysql://${params.tableName}/schema`, text: `Fields details for ${params.tableName}` }]
299
+ };
300
+ }
301
+ }
302
+ ```
303
+
304
+ ### `index.ts`
305
+ ```typescript
306
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
307
+ import { MyMCPServer } from "./server.js";
308
+ import { DbHandlers } from "./dbHandlers.js";
309
+
310
+ async function main() {
311
+ // 1. Create registered server instance
312
+ const server = new MyMCPServer(
313
+ { name: "my-database-mcp", version: "1.0.0" },
314
+ { capabilities: {} }
315
+ );
316
+
317
+ // 2. Instantiate handlers (binds decorators dynamically BEFORE connecting)
318
+ new DbHandlers();
319
+
320
+ // 3. Setup stdio transport and connect
321
+ const transport = new StdioServerTransport();
322
+ await server.connect(transport);
323
+
324
+ console.error("🚀 MCP Server running on Stdio!");
325
+ }
326
+
327
+ main().catch(console.error);
328
+ ```
329
+
330
+ ---
331
+
332
+ ## Client-Side Decorators
333
+
334
+ Client decorators allow you to inject an active client instance, auto-wrap local methods into server-side JSON-RPC requests, and register local message/notification handlers.
335
+
336
+ ### Core Client Decorators
337
+
338
+ #### 1. `@RegisterClient()`
339
+ * **Target**: Class extending `Client` (from `@modelcontextprotocol/sdk/client/index.js`)
340
+ * **Description**: Registers the client instance in the global client registry upon construction.
341
+ ```typescript
342
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
343
+ import { RegisterClient } from "@ananay-nag/mcp-decorators";
344
+
345
+ @RegisterClient()
346
+ export class MyMCPClient extends Client {}
347
+ ```
348
+
349
+ #### 2. `@UseClient(options)`
350
+ * **Target**: Client service/controller class
351
+ * **Parameters**: `options: { name: string; version?: string }`
352
+ * **Description**: Injects the registered client instance as `this.client` and binds all method capability wrappers.
353
+ ```typescript
354
+ import { UseClient } from "@ananay-nag/mcp-decorators";
355
+
356
+ @UseClient({ name: "my-mcp-client" })
357
+ export class MyService {
358
+ client: any; // Injected
359
+ }
360
+ ```
361
+
362
+ ---
363
+
364
+ ### Client Call Wrapper Decorators
365
+
366
+ By decorating a method in a `@UseClient` class, calling that method locally automatically triggers a request to the server.
367
+
368
+ * **Pre-processing arguments**: If you write code in the body of the decorated method, it runs **before** the request is dispatched. Whatever you return will be sent to the server. If you return nothing (`undefined`), the original arguments passed to the method are forwarded.
369
+ * **Empty Methods**: You can declare them with empty bodies (e.g. `async myMethod(args): Promise<any> {}`), and they will forward the arguments directly to the server.
370
+
371
+ | Decorator | JSON-RPC Method | Description |
372
+ | :--- | :--- | :--- |
373
+ | **`@CallTool(name?)`** | `tools/call` | Calls a server tool. Uses method name if name is omitted. |
374
+ | **`@ListTools()`** | `tools/list` | Lists all available tools on the server. |
375
+ | **`@GetPrompt(name?)`** | `prompts/get` | Retrieves a specific prompt template. |
376
+ | **`@ListPrompts()`** | `prompts/list` | Lists prompts available on the server. |
377
+ | **`@ReadResource(uri?)`** | `resources/read` | Reads a resource. Direct URI parameter is supported. |
378
+ | **`@ListResources()`** | `resources/list` | Lists resources available on the server. |
379
+ | **`@ListResourceTemplates()`**| `resources/templates/list` | Lists dynamic resource templates. |
380
+ | **`@SubscribeResource(uri?)`**| `resources/subscribe` | Subscribes to resource updates. |
381
+ | **`@UnsubscribeResource(uri?)`**| `resources/unsubscribe` | Unsubscribes from resource updates. |
382
+ | **`@CompletePromptOrResource()`**| `completion/complete` | Retrieves auto-completion values. |
383
+ | **`@SetLoggingLevel(level?)`**| `logging/setLevel` | Sets server logging level. |
384
+ | **`@PingServer()`** | `ping` | Pings the server. |
385
+
386
+ ---
387
+
388
+ ### Client Request/Notification Handlers
389
+
390
+ Client classes decorated with `@UseClient` can also listen to requests and notifications sent from the server using:
391
+ * `@RequestHandler(schema)`
392
+ * `@NotificationHandler(schema)`
393
+
394
+ For instance, you can handle resource update notifications pushed by the server.
395
+
396
+ ```typescript
397
+ import { UseClient, NotificationHandler } from "@ananay-nag/mcp-decorators";
398
+
399
+ @UseClient({ name: "my-mcp-client" })
400
+ export class LogController {
401
+ client: any;
402
+
403
+ // Handle resource updates pushed by the server
404
+ @NotificationHandler("notifications/resources/updated")
405
+ async onResourceUpdate(params: { uri: string }) {
406
+ console.log(`⚠️ Server notified update for: ${params.uri}`);
407
+ }
408
+ }
409
+ ```
410
+
411
+ ---
412
+
413
+ ## Full Client Example
414
+
415
+ ### `client.ts`
416
+ ```typescript
417
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
418
+ import { RegisterClient } from "@ananay-nag/mcp-decorators";
419
+
420
+ @RegisterClient()
421
+ export class MyMCPClient extends Client {}
422
+ ```
423
+
424
+ ### `service.ts`
425
+ ```typescript
426
+ import { UseClient, CallTool, ListTools, ReadResource, NotificationHandler } from "@ananay-nag/mcp-decorators";
427
+
428
+ @UseClient({ name: "my-mcp-client", version: "1.0.0" })
429
+ export class ClientController {
430
+ client: any; // Injected instance
431
+
432
+ // 1. Calling a tool named "fetch_users"
433
+ @CallTool("fetch_users")
434
+ async fetchUsers(args: { limit: number }): Promise<any> {}
435
+
436
+ // 2. List tools on the server
437
+ @ListTools()
438
+ async getToolsList(): Promise<any> {}
439
+
440
+ // 3. Read a resource (Preprocesses parameter into URI schema)
441
+ @ReadResource()
442
+ async loadTableSchema(tableName: string) {
443
+ return `mysql://${tableName}/schema`; // Returns final argument sent to server
444
+ }
445
+
446
+ // 4. Handle notifications pushed from server
447
+ @NotificationHandler("notifications/resources/updated")
448
+ onResourceUpdated(params: { uri: string }) {
449
+ console.log(`Resource changed on server: ${params.uri}`);
450
+ }
451
+ }
452
+ ```
453
+
454
+ ### `index.ts`
455
+ ```typescript
456
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
457
+ import { MyMCPClient } from "./client.js";
458
+ import { ClientController } from "./service.js";
459
+
460
+ async function runClient() {
461
+ const client = new MyMCPClient(
462
+ { name: "my-mcp-client", version: "1.0.0" },
463
+ { capabilities: {} }
464
+ );
465
+
466
+ const transport = new StdioClientTransport({
467
+ command: "node",
468
+ args: ["path/to/server/index.js"]
469
+ });
470
+
471
+ await client.connect(transport);
472
+
473
+ // Initialize service to bind decorators
474
+ const controller = new ClientController();
475
+
476
+ // Test tool call
477
+ const users = await controller.fetchUsers({ limit: 5 });
478
+ console.log("Users output:", users);
479
+
480
+ // Test resource read
481
+ const schema = await controller.loadTableSchema("users");
482
+ console.log("Schema output:", schema);
483
+ }
484
+
485
+ runClient().catch(console.error);
486
+ ```
487
+
488
+ ---
489
+
490
+ ## Utilities
491
+
492
+ #### 1. `notifyResourceUpdated(server, uri)`
493
+ Triggers a push notification to all clients subscribed to the specified resource URI.
494
+ ```typescript
495
+ import { notifyResourceUpdated } from "@ananay-nag/mcp-decorators";
496
+
497
+ // Pushes notification to clients subscribed to 'mysql://users/schema'
498
+ await notifyResourceUpdated(this.server, "mysql://users/schema");
499
+ ```
500
+
501
+ #### 2. `sendProgress(server, progressToken, progress, total?, message?)`
502
+ Send real-time progress updates back to the client during long-running tasks.
503
+ ```typescript
504
+ import { sendProgress } from "@ananay-nag/mcp-decorators";
505
+
506
+ // Inside a Tool handler method:
507
+ const token = request._meta?.progressToken;
508
+ if (token) {
509
+ await sendProgress(this.server, token, 1, 5, "Processing part 1...");
510
+ }
511
+ ```
512
+
513
+ #### 3. `sendLoggingMessage(server, level, data, logger?)`
514
+ Transmits standard log notifications to the client over MCP.
515
+ ```typescript
516
+ import { sendLoggingMessage } from "@ananay-nag/mcp-decorators";
517
+
518
+ await sendLoggingMessage(this.server, "info", { query: "SELECT * FROM users" }, "DatabaseLogger");
519
+ ```
520
+
521
+ #### 4. `elicitInput(server, params, options?)`
522
+ Prompts the client/user for dynamic input or form submission mid-request.
523
+ ```typescript
524
+ import { elicitInput } from "@ananay-nag/mcp-decorators";
525
+
526
+ const response = await elicitInput(this.server, {
527
+ mode: "form",
528
+ message: "Confirm table drop?",
529
+ requestedSchema: {
530
+ type: "object",
531
+ properties: { confirm: { type: "boolean" } },
532
+ required: ["confirm"]
533
+ }
534
+ });
535
+ ```
536
+
537
+ #### 5. `getServer(options)`
538
+ Fetch a registered server instance programmatically.
539
+ ```typescript
540
+ import { getServer } from "@ananay-nag/mcp-decorators";
541
+
542
+ const server = getServer({ name: "my-database-mcp", version: "1.0.0" });
543
+ ```
544
+
545
+ #### 6. `getClient(options)`
546
+ Fetch a registered client instance programmatically.
547
+ ```typescript
548
+ import { getClient } from "@ananay-nag/mcp-decorators";
549
+
550
+ const client = getClient({ name: "my-mcp-client", version: "1.0.0" });
551
+ ```
552
+
553
+ ---
554
+
555
+ ## Under the Hood & Advantages
556
+
557
+ * **No Overhead Handler Overwrites**: In the standard MCP SDK, setting a request handler replaces the previous registration. `mcp-decorators` aggregates all class-level decorators (e.g. tools, prompts, resources, completions) and maps them internally inside single dispatchers. This allows you to split logic across multiple handler classes safely without breaking capabilities.
558
+ * **Zod Validation Integration**: Automatically processes typescript parameter typing or schema validations using Zod validator patterns on Tool inputSchemas.
559
+ * **Auto-Capability Detection**: Evaluates registered decorators at instantiation and registers corresponding server capabilities (`tools`, `prompts`, `resources`) dynamically so you don't have to manually configure them in options.
560
+ * **Smart URI Parameter Extraction**: Parses template URIs (e.g., `mysql://{tableName}/schema`) and extracts named path parameters (e.g. `tableName: "users"`) to inject directly as parameters to your resource templates method.
561
+ * **Dual CJS & ESM Compatibility**: Fully compiled for both exports setups to prevent TypeScript resolution errors in legacy standard node projects.
package/banner.svg ADDED
@@ -0,0 +1,111 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 280" width="800" height="280">
2
+ <defs>
3
+ <!-- Background Gradient -->
4
+ <linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
5
+ <stop offset="0%" stop-color="#050b14" />
6
+ <stop offset="100%" stop-color="#0c192c" />
7
+ </linearGradient>
8
+
9
+ <!-- Glowing Accent Gradient -->
10
+ <radialGradient id="glowGrad" cx="50%" cy="50%" r="50%">
11
+ <stop offset="0%" stop-color="#db2777" stop-opacity="0.15" />
12
+ <stop offset="100%" stop-color="#db2777" stop-opacity="0" />
13
+ </radialGradient>
14
+
15
+ <!-- Dark Blue Gradient for Hexagon Frame -->
16
+ <linearGradient id="darkBlueGrad" x1="0%" y1="0%" x2="100%" y2="100%">
17
+ <stop offset="0%" stop-color="#0f2942" />
18
+ <stop offset="100%" stop-color="#1e3a8a" />
19
+ </linearGradient>
20
+
21
+ <!-- Pink Gradient for Logo loops -->
22
+ <linearGradient id="pinkGrad" x1="0%" y1="0%" x2="100%" y2="100%">
23
+ <stop offset="0%" stop-color="#f472b6" /> <!-- Pink-400 -->
24
+ <stop offset="50%" stop-color="#db2777" /> <!-- Pink-600 -->
25
+ <stop offset="100%" stop-color="#9d174d" /> <!-- Pink-800 -->
26
+ </linearGradient>
27
+
28
+ <!-- Text Purple-to-Pink Gradient -->
29
+ <linearGradient id="textGrad" x1="0%" y1="0%" x2="100%" y2="0%">
30
+ <stop offset="0%" stop-color="#a78bfa" /> <!-- Violet-400 -->
31
+ <stop offset="100%" stop-color="#f472b6" /> <!-- Pink-400 -->
32
+ </linearGradient>
33
+ </defs>
34
+
35
+ <!-- Background Layer -->
36
+ <rect width="800" height="280" fill="url(#bgGrad)" />
37
+
38
+ <!-- Subtle Grid Lines -->
39
+ <g stroke="#1e293b" stroke-width="0.5" opacity="0.3">
40
+ <path d="M 0,40 H 800 M 0,80 H 800 M 0,120 H 800 M 0,160 H 800 M 0,200 H 800 M 0,240 H 800" />
41
+ <path d="M 80,0 V 280 M 160,0 V 280 M 240,0 V 280 M 320,0 V 280 M 400,0 V 280 M 480,0 V 280 M 560,0 V 280 M 640,0 V 280 M 720,0 V 280" />
42
+ </g>
43
+
44
+ <!-- Background Glow behind the Logo -->
45
+ <circle cx="160" cy="140" r="120" fill="url(#glowGrad)" />
46
+
47
+ <!-- Logo Group (mcp-hex-pink.svg) scaled and centered on the left -->
48
+ <g transform="translate(60, 40) scale(2)">
49
+ <!-- Hexagon Frame -->
50
+ <path d="M 50,12
51
+ L 83,31
52
+ L 83,69
53
+ L 50,88
54
+ L 17,69
55
+ L 17,31 Z"
56
+ fill="none"
57
+ stroke="url(#darkBlueGrad)"
58
+ stroke-width="4.5"
59
+ stroke-linecap="round"
60
+ stroke-linejoin="round" />
61
+
62
+ <!-- Nested Official Loop Shape -->
63
+ <g transform="translate(50, 50) scale(0.72) translate(-50, -50)">
64
+ <g transform="rotate(-45, 50, 50)">
65
+ <path d="M 28 25
66
+ H 64
67
+ A 8 8 0 0 1 64 41
68
+ H 36
69
+ A 8 8 0 0 0 36 57
70
+ H 72
71
+ A 8 8 0 0 1 72 73
72
+ H 44"
73
+ fill="none"
74
+ stroke="url(#pinkGrad)"
75
+ stroke-width="7.5"
76
+ stroke-linecap="round"
77
+ stroke-linejoin="round" />
78
+ </g>
79
+ </g>
80
+ </g>
81
+
82
+ <!-- Title & Branding Text (Left-aligned next to logo) -->
83
+ <text x="280" y="115" font-family="Inter, system-ui, sans-serif" font-weight="900" font-size="38" letter-spacing="-1.5" fill="url(#textGrad)">MCP Decorators</text>
84
+
85
+ <text x="280" y="150" font-family="Inter, system-ui, sans-serif" font-weight="500" font-size="16" letter-spacing="-0.5" fill="#94a3b8">
86
+ Declarative Model Context Protocol for TypeScript
87
+ </text>
88
+
89
+ <text x="280" y="175" font-family="Inter, system-ui, sans-serif" font-weight="400" font-size="14" fill="#64748b">
90
+ Write cleaner, modular, and metadata-driven MCP servers and clients.
91
+ </text>
92
+
93
+ <!-- Bullet Feature Pill Badges -->
94
+ <g transform="translate(280, 205)">
95
+ <!-- Badge 1: @mcp -->
96
+ <rect x="0" y="0" width="60" height="24" rx="12" fill="#1e1b4b" stroke="#312e81" stroke-width="1" />
97
+ <text x="30" y="16" font-family="JetBrains Mono, Courier New, monospace" font-weight="700" font-size="11" fill="#c084fc" text-anchor="middle">@mcp</text>
98
+
99
+ <!-- Badge 2: @tool -->
100
+ <rect x="70" y="0" width="65" height="24" rx="12" fill="#1e1b4b" stroke="#312e81" stroke-width="1" />
101
+ <text x="102.5" y="16" font-family="JetBrains Mono, Courier New, monospace" font-weight="700" font-size="11" fill="#c084fc" text-anchor="middle">@tool</text>
102
+
103
+ <!-- Badge 3: @prompt -->
104
+ <rect x="145" y="0" width="75" height="24" rx="12" fill="#1e1b4b" stroke="#312e81" stroke-width="1" />
105
+ <text x="182.5" y="16" font-family="JetBrains Mono, Courier New, monospace" font-weight="700" font-size="11" fill="#c084fc" text-anchor="middle">@prompt</text>
106
+
107
+ <!-- Badge 4: @resource -->
108
+ <rect x="230" y="0" width="95" height="24" rx="12" fill="#1e1b4b" stroke="#312e81" stroke-width="1" />
109
+ <text x="277.5" y="16" font-family="JetBrains Mono, Courier New, monospace" font-weight="700" font-size="11" fill="#c084fc" text-anchor="middle">@resource</text>
110
+ </g>
111
+ </svg>
@@ -0,0 +1,3 @@
1
+ export * from "./src/server/index.js";
2
+ export { RegisterClient, UseClient, CallTool, ListTools, GetPrompt, ListPrompts, ReadResource, ListResources, ListResourceTemplates, SubscribeResource, UnsubscribeResource, CompletePromptOrResource, SetLoggingLevel, PingServer, getClient, registerClient } from "./src/client/index.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,OAAO,EACL,cAAc,EACd,SAAS,EACT,QAAQ,EACR,SAAS,EACT,SAAS,EACT,WAAW,EACX,YAAY,EACZ,aAAa,EACb,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,wBAAwB,EACxB,eAAe,EACf,UAAU,EACV,SAAS,EACT,cAAc,EACf,MAAM,uBAAuB,CAAC"}